mirror of
				https://github.com/retspen/webvirtcloud
				synced 2025-07-31 12:41:08 +00:00 
			
		
		
		
	Rest framework (#24)
* Add rest framework for API: First Commit * modify some shell scripts to make variable references safer; modify some python scripts to reduce the code complexity and cyclomatic complexity of functions. * Add REST API for some webvirtcloud functions. Instance list/delete/create, compute list/delete/create, storages-network list/retrieve. Add swagger and redoc for API interface * update requirements Co-authored-by: herengui <herengui@uniontech.com>
This commit is contained in:
		
							parent
							
								
									92254401dc
								
							
						
					
					
						commit
						cfce71ec2b
					
				
					 42 changed files with 1170 additions and 348 deletions
				
			
		|  | @ -181,10 +181,7 @@ class IPint(object): | |||
|         if isinstance(data, INT_TYPES): | ||||
|             self.ip = int(data) | ||||
|             if ipversion == 0: | ||||
|                 if self.ip <= MAX_IPV4_ADDRESS: | ||||
|                     ipversion = 4 | ||||
|                 else: | ||||
|                     ipversion = 6 | ||||
|                 ipversion = 4 if self.ip <= MAX_IPV4_ADDRESS else 6 | ||||
|             if ipversion == 4: | ||||
|                 if self.ip > MAX_IPV4_ADDRESS: | ||||
|                     raise ValueError("IPv4 Address can't be larger than %x: %x" % (MAX_IPV4_ADDRESS, self.ip)) | ||||
|  |  | |||
|  | @ -1,4 +1,5 @@ | |||
| import string | ||||
| import contextlib | ||||
| 
 | ||||
| from vrtManager import util | ||||
| from vrtManager.connection import wvmConnect | ||||
|  | @ -30,19 +31,13 @@ class wvmCreate(wvmConnect): | |||
|         """ | ||||
|         Function return all images on all storages | ||||
|         """ | ||||
|         images = list() | ||||
|         images = [] | ||||
|         storages = self.get_storages(only_actives=True) | ||||
|         for storage in storages: | ||||
|             stg = self.get_storage(storage) | ||||
|             try: | ||||
|             with contextlib.suppress(Exception): | ||||
|                 stg.refresh(0) | ||||
|             except Exception: | ||||
|                 pass | ||||
|             for img in stg.listVolumes(): | ||||
|                 if img.lower().endswith(".iso"): | ||||
|                     pass | ||||
|                 else: | ||||
|                     images.append(img) | ||||
|             images.extend(img for img in stg.listVolumes() if not img.lower().endswith(".iso")) | ||||
|         return images | ||||
| 
 | ||||
|     def get_os_type(self): | ||||
|  | @ -50,7 +45,7 @@ class wvmCreate(wvmConnect): | |||
|         return util.get_xml_path(self.get_cap_xml(), "/capabilities/guest/os_type") | ||||
| 
 | ||||
|     def get_host_arch(self): | ||||
|         """Get guest capabilities""" | ||||
|         """Get host architecture""" | ||||
|         return util.get_xml_path(self.get_cap_xml(), "/capabilities/host/cpu/arch") | ||||
| 
 | ||||
|     def create_volume(self, storage, name, size, image_format, metadata=False, disk_owner_uid=0, disk_owner_gid=0): | ||||
|  | @ -58,10 +53,7 @@ class wvmCreate(wvmConnect): | |||
|         stg = self.get_storage(storage) | ||||
|         storage_type = util.get_xml_path(stg.XMLDesc(0), "/pool/@type") | ||||
|         if storage_type == "dir": | ||||
|             if image_format in ("qcow", "qcow2"): | ||||
|                 name += "." + image_format | ||||
|             else: | ||||
|                 name += ".img" | ||||
|             name += f".{image_format}" if image_format in ("qcow", "qcow2") else ".img" | ||||
|             alloc = 0 | ||||
|         else: | ||||
|             image_format = 'raw' | ||||
|  | @ -87,28 +79,19 @@ class wvmCreate(wvmConnect): | |||
|                 </target> | ||||
|             </volume>""" | ||||
|         stg.createXML(xml, metadata) | ||||
|         try: | ||||
| 
 | ||||
|         with contextlib.suppress(Exception): | ||||
|             stg.refresh(0) | ||||
|         except: | ||||
|             pass | ||||
|         vol = stg.storageVolLookupByName(name) | ||||
|         return vol.path() | ||||
| 
 | ||||
|     def get_volume_format_type(self, path): | ||||
|         vol = self.get_volume_by_path(path) | ||||
|         vol_type = util.get_xml_path(vol.XMLDesc(0), "/volume/target/format/@type") | ||||
|         if vol_type == "unknown" or vol_type == "iso": | ||||
|             return "raw" | ||||
|         if vol_type: | ||||
|             return vol_type | ||||
|         else: | ||||
|             return "raw" | ||||
|         return "raw" if vol_type in ["unknown", "iso"] else vol_type or "raw" | ||||
| 
 | ||||
|     def get_volume_path(self, volume, pool=None): | ||||
|         if not pool: | ||||
|             storages = self.get_storages(only_actives=True) | ||||
|         else: | ||||
|             storages = [pool] | ||||
|         storages = [pool] if pool else self.get_storages(only_actives=True) | ||||
|         for storage in storages: | ||||
|             stg = self.get_storage(storage) | ||||
|             if stg.info()[0] != 0: | ||||
|  | @ -124,10 +107,7 @@ class wvmCreate(wvmConnect): | |||
| 
 | ||||
|     def clone_from_template(self, clone, template, storage=None, metadata=False, disk_owner_uid=0, disk_owner_gid=0): | ||||
|         vol = self.get_volume_by_path(template) | ||||
|         if not storage: | ||||
|             stg = vol.storagePoolLookupByVolume() | ||||
|         else: | ||||
|             stg = self.get_storage(storage) | ||||
|         stg = self.get_storage(storage) if storage else vol.storagePoolLookupByVolume() | ||||
| 
 | ||||
|         storage_type = util.get_xml_path(stg.XMLDesc(0), "/pool/@type") | ||||
|         format = util.get_xml_path(vol.XMLDesc(0), "/volume/target/format/@type") | ||||
|  | @ -180,7 +160,7 @@ class wvmCreate(wvmConnect): | |||
|         nwfilter, | ||||
|         graphics, | ||||
|         virtio, | ||||
|         listen_addr, | ||||
|         listener_addr, | ||||
|         video="vga", | ||||
|         console_pass="random", | ||||
|         mac=None, | ||||
|  | @ -226,12 +206,8 @@ class wvmCreate(wvmConnect): | |||
| 
 | ||||
|         if caps["features"]: | ||||
|             xml += """<features>""" | ||||
|             if "acpi" in caps["features"]: | ||||
|                 xml += """<acpi/>""" | ||||
|             if "apic" in caps["features"]: | ||||
|                 xml += """<apic/>""" | ||||
|             if "pae" in caps["features"]: | ||||
|                 xml += """<pae/>""" | ||||
|             for feat in [x for x in ("acpi", "apic", "pae",) if x in caps["features"]]: | ||||
|                 xml += f"""<{feat}/>""" | ||||
|             if firmware.get("secure", "no") == "yes": | ||||
|                 xml += """<smm state="on"/>""" | ||||
|             xml += """</features>""" | ||||
|  | @ -240,9 +216,7 @@ class wvmCreate(wvmConnect): | |||
|             xml += """<cpu mode='host-model'/>""" | ||||
|         elif vcpu_mode == "host-passthrough": | ||||
|             xml += """<cpu mode='host-passthrough'/>""" | ||||
|         elif vcpu_mode == "": | ||||
|             pass | ||||
|         else: | ||||
|         elif vcpu_mode != "": | ||||
|             xml += f"""<cpu mode='custom' match='exact' check='none'> | ||||
|                         <model fallback='allow'>{vcpu_mode}</model>""" | ||||
|             xml += """</cpu>""" | ||||
|  | @ -306,7 +280,7 @@ class wvmCreate(wvmConnect): | |||
|                 xml += """<target dev='hd%s' bus='%s'/>""" % (hd_disk_letters.pop(0), volume.get("bus")) | ||||
|             elif volume.get("bus") == "fdc": | ||||
|                 xml += """<target dev='fd%s' bus='%s'/>""" % (fd_disk_letters.pop(0), volume.get("bus")) | ||||
|             elif volume.get("bus") == "sata" or volume.get("bus") == "scsi": | ||||
|             elif volume.get("bus") in ["sata", "scsi"]: | ||||
|                 xml += """<target dev='sd%s' bus='%s'/>""" % (sd_disk_letters.pop(0), volume.get("bus")) | ||||
|             else: | ||||
|                 xml += """<target dev='sd%s'/>""" % sd_disk_letters.pop(0) | ||||
|  | @ -345,21 +319,20 @@ class wvmCreate(wvmConnect): | |||
| 
 | ||||
|         if console_pass == "random": | ||||
|             console_pass = "passwd='" + util.randomPasswd() + "'" | ||||
|         else: | ||||
|             if not console_pass == "": | ||||
|                 console_pass = "passwd='" + console_pass + "'" | ||||
|         elif console_pass != "": | ||||
|             console_pass = "passwd='" + console_pass + "'" | ||||
| 
 | ||||
|         if "usb" in dom_caps["disk_bus"]: | ||||
|             xml += """<input type='mouse' bus='{}'/>""".format("virtio" if virtio else "usb") | ||||
|             xml += """<input type='keyboard' bus='{}'/>""".format("virtio" if virtio else "usb") | ||||
|             xml += """<input type='tablet' bus='{}'/>""".format("virtio" if virtio else "usb") | ||||
|             xml += f"""<input type='mouse' bus='{"virtio" if virtio else "usb"}'/>""" | ||||
|             xml += f"""<input type='keyboard' bus='{"virtio" if virtio else "usb"}'/>""" | ||||
|             xml += f"""<input type='tablet' bus='{"virtio" if virtio else "usb"}'/>""" | ||||
|         else: | ||||
|             xml += """<input type='mouse'/>""" | ||||
|             xml += """<input type='keyboard'/>""" | ||||
|             xml += """<input type='tablet'/>""" | ||||
| 
 | ||||
|         xml += f""" | ||||
|                 <graphics type='{graphics}' port='-1' autoport='yes' {console_pass} listen='{listen_addr}'/> | ||||
|                 <graphics type='{graphics}' port='-1' autoport='yes' {console_pass} listen='{listener_addr}'/> | ||||
|                 <console type='pty'/> """ | ||||
| 
 | ||||
|         if qemu_ga and virtio: | ||||
|  | @ -372,4 +345,4 @@ class wvmCreate(wvmConnect): | |||
|                    </video> | ||||
|               </devices> | ||||
|             </domain>""" | ||||
|         self._defineXML(xml) | ||||
|         return self._defineXML(xml) | ||||
|  |  | |||
|  | @ -21,12 +21,11 @@ class wvmHostDetails(wvmConnect): | |||
|         freemem = self.wvm.getMemoryStats(-1, 0) | ||||
|         if isinstance(freemem, dict): | ||||
|             free = (freemem["buffers"] + freemem["free"] + freemem["cached"]) * 1024 | ||||
|             percent = abs(100 - ((free * 100) // all_mem)) | ||||
|             percent = abs(100 - free * 100 // all_mem) | ||||
|             usage = all_mem - free | ||||
|             mem_usage = {"total": all_mem, "usage": usage, "percent": percent} | ||||
|             return {"total": all_mem, "usage": usage, "percent": percent} | ||||
|         else: | ||||
|             mem_usage = {"total": None, "usage": None, "percent": None} | ||||
|         return mem_usage | ||||
|             return {"total": None, "usage": None, "percent": None} | ||||
| 
 | ||||
|     def get_cpu_usage(self): | ||||
|         """ | ||||
|  | @ -35,30 +34,30 @@ class wvmHostDetails(wvmConnect): | |||
|         prev_idle = 0 | ||||
|         prev_total = 0 | ||||
|         cpu = self.wvm.getCPUStats(-1, 0) | ||||
|         if isinstance(cpu, dict): | ||||
|             for num in range(2): | ||||
|                 idle = self.wvm.getCPUStats(-1, 0)["idle"] | ||||
|                 total = sum(self.wvm.getCPUStats(-1, 0).values()) | ||||
|                 diff_idle = idle - prev_idle | ||||
|                 diff_total = total - prev_total | ||||
|                 diff_usage = (1000 * (diff_total - diff_idle) / diff_total + 5) / 10 | ||||
|                 prev_total = total | ||||
|                 prev_idle = idle | ||||
|                 if num == 0: | ||||
|                     time.sleep(1) | ||||
|                 else: | ||||
|                     if diff_usage < 0: | ||||
|                         diff_usage = 0 | ||||
|         else: | ||||
|         if not isinstance(cpu, dict): | ||||
|             return {"usage": None} | ||||
| 
 | ||||
|         for num in range(2): | ||||
|             idle = self.wvm.getCPUStats(-1, 0)["idle"] | ||||
|             total = sum(self.wvm.getCPUStats(-1, 0).values()) | ||||
|             diff_idle = idle - prev_idle | ||||
|             diff_total = total - prev_total | ||||
|             diff_usage = (1000 * (diff_total - diff_idle) / | ||||
|                           diff_total + 5) / 10 | ||||
|             prev_total = total | ||||
|             prev_idle = idle | ||||
|             if num == 0: | ||||
|                 time.sleep(1) | ||||
|             else: | ||||
|                 diff_usage = max(diff_usage, 0) | ||||
| 
 | ||||
|         return {"usage": diff_usage} | ||||
| 
 | ||||
|     def get_node_info(self): | ||||
|         """ | ||||
|         Function return host server information: hostname, cpu, memory, ... | ||||
|         """ | ||||
|         info = list() | ||||
|         info.append(self.wvm.getHostname())  # hostname | ||||
|         info = [self.wvm.getHostname()]  # hostname | ||||
|         info.append(self.wvm.getInfo()[0])  # architecture | ||||
|         info.append(self.wvm.getInfo()[1] * 1048576)  # memory | ||||
|         info.append(self.wvm.getInfo()[2])  # cpu core count | ||||
|  |  | |||
|  | @ -130,12 +130,12 @@ class wvmInstances(wvmConnect): | |||
| 
 | ||||
|     def graphics_listen(self, name): | ||||
|         inst = self.get_instance(name) | ||||
|         listen_addr = util.get_xml_path(inst.XMLDesc(0), "/domain/devices/graphics/@listen") | ||||
|         if listen_addr is None: | ||||
|             listen_addr = util.get_xml_path(inst.XMLDesc(0), "/domain/devices/graphics/listen/@address") | ||||
|             if listen_addr is None: | ||||
|         listener_addr = util.get_xml_path(inst.XMLDesc(0), "/domain/devices/graphics/@listen") | ||||
|         if listener_addr is None: | ||||
|             listener_addr = util.get_xml_path(inst.XMLDesc(0), "/domain/devices/graphics/listen/@address") | ||||
|             if listener_addr is None: | ||||
|                 return "None" | ||||
|         return listen_addr | ||||
|         return listener_addr | ||||
| 
 | ||||
|     def graphics_port(self, name): | ||||
|         inst = self.get_instance(name) | ||||
|  | @ -253,6 +253,9 @@ class wvmInstance(wvmConnect): | |||
|         else: | ||||
|             return self.get_vcpu() | ||||
| 
 | ||||
|     def get_vcpu_mode(self): | ||||
|         return util.get_xml_path(self._XMLDesc(0), "/domain/cpu/@current") | ||||
| 
 | ||||
|     def get_arch(self): | ||||
|         return util.get_xml_path(self._XMLDesc(0), "/domain/os/type/@arch") | ||||
| 
 | ||||
|  | @ -979,15 +982,15 @@ class wvmInstance(wvmConnect): | |||
|                                 telnet_port = service_port | ||||
|         return telnet_port | ||||
| 
 | ||||
|     def get_console_listen_addr(self): | ||||
|         listen_addr = util.get_xml_path(self._XMLDesc(0), "/domain/devices/graphics/@listen") | ||||
|         if listen_addr is None: | ||||
|             listen_addr = util.get_xml_path(self._XMLDesc(0), "/domain/devices/graphics/listen/@address") | ||||
|             if listen_addr is None: | ||||
|     def get_console_listener_addr(self): | ||||
|         listener_addr = util.get_xml_path(self._XMLDesc(0), "/domain/devices/graphics/@listen") | ||||
|         if listener_addr is None: | ||||
|             listener_addr = util.get_xml_path(self._XMLDesc(0), "/domain/devices/graphics/listen/@address") | ||||
|             if listener_addr is None: | ||||
|                 return "127.0.0.1" | ||||
|         return listen_addr | ||||
|         return listener_addr | ||||
| 
 | ||||
|     def set_console_listen_addr(self, listen_addr): | ||||
|     def set_console_listener_addr(self, listener_addr): | ||||
|         xml = self._XMLDesc(VIR_DOMAIN_XML_SECURE) | ||||
|         root = ElementTree.fromstring(xml) | ||||
|         console_type = self.get_console_type() | ||||
|  | @ -1001,9 +1004,9 @@ class wvmInstance(wvmConnect): | |||
|         listen = graphic.find("listen[@type='address']") | ||||
|         if listen is None: | ||||
|             return False | ||||
|         if listen_addr: | ||||
|             graphic.set("listen", listen_addr) | ||||
|             listen.set("address", listen_addr) | ||||
|         if listener_addr: | ||||
|             graphic.set("listen", listener_addr) | ||||
|             listen.set("address", listener_addr) | ||||
|         else: | ||||
|             try: | ||||
|                 graphic.attrib.pop("listen") | ||||
|  |  | |||
|  | @ -57,7 +57,7 @@ class wvmInterface(wvmConnect): | |||
|         try: | ||||
|             xml = self._XMLDesc(VIR_INTERFACE_XML_INACTIVE) | ||||
|             return util.get_xml_path(xml, "/interface/start/@mode") | ||||
|         except: | ||||
|         except Exception: | ||||
|             return None | ||||
| 
 | ||||
|     def is_active(self): | ||||
|  | @ -65,10 +65,7 @@ class wvmInterface(wvmConnect): | |||
| 
 | ||||
|     def get_mac(self): | ||||
|         mac = self.iface.MACString() | ||||
|         if mac: | ||||
|             return mac | ||||
|         else: | ||||
|             return None | ||||
|         return mac or None | ||||
| 
 | ||||
|     def get_type(self): | ||||
|         xml = self._XMLDesc() | ||||
|  | @ -78,11 +75,8 @@ class wvmInterface(wvmConnect): | |||
|         try: | ||||
|             xml = self._XMLDesc(VIR_INTERFACE_XML_INACTIVE) | ||||
|             ipaddr = util.get_xml_path(xml, "/interface/protocol[@family='ipv4']/ip/@address") | ||||
|             if ipaddr: | ||||
|                 return "static" | ||||
|             else: | ||||
|                 return "dhcp" | ||||
|         except: | ||||
|             return "static" if ipaddr else "dhcp" | ||||
|         except Exception: | ||||
|             return None | ||||
| 
 | ||||
|     def get_ipv4(self): | ||||
|  | @ -92,17 +86,14 @@ class wvmInterface(wvmConnect): | |||
|         if not int_ipv4_ip or not int_ipv4_mask: | ||||
|             return None | ||||
|         else: | ||||
|             return int_ipv4_ip + "/" + int_ipv4_mask | ||||
|             return f"{int_ipv4_ip}/{int_ipv4_mask}" | ||||
| 
 | ||||
|     def get_ipv6_type(self): | ||||
|         try: | ||||
|             xml = self._XMLDesc(VIR_INTERFACE_XML_INACTIVE) | ||||
|             ipaddr = util.get_xml_path(xml, "/interface/protocol[@family='ipv6']/ip/@address") | ||||
|             if ipaddr: | ||||
|                 return "static" | ||||
|             else: | ||||
|                 return "dhcp" | ||||
|         except: | ||||
|             return "static" if ipaddr else "dhcp" | ||||
|         except Exception: | ||||
|             return None | ||||
| 
 | ||||
|     def get_ipv6(self): | ||||
|  | @ -112,40 +103,39 @@ class wvmInterface(wvmConnect): | |||
|         if not int_ipv6_ip or not int_ipv6_mask: | ||||
|             return None | ||||
|         else: | ||||
|             return int_ipv6_ip + "/" + int_ipv6_mask | ||||
|             return f"{int_ipv6_ip}/{int_ipv6_mask}" | ||||
| 
 | ||||
|     def get_bridge(self): | ||||
|         bridge = None | ||||
|         if self.get_type() == "bridge": | ||||
|             bridge = util.get_xml_path(self._XMLDesc(), "/interface/bridge/interface/@name") | ||||
|             for iface in self.get_bridge_slave_ifaces(): | ||||
|                 if iface.get("state") == "up" and iface.get("speed") != "unknown": | ||||
|                     bridge = iface.get("name") | ||||
|                     return bridge | ||||
|             return bridge | ||||
|         else: | ||||
|         if self.get_type() != "bridge": | ||||
|             return None | ||||
|         bridge = util.get_xml_path(self._XMLDesc(), "/interface/bridge/interface/@name") | ||||
|         for iface in self.get_bridge_slave_ifaces(): | ||||
|             if iface.get("state") == "up" and iface.get("speed") != "unknown": | ||||
|                 bridge = iface.get("name") | ||||
|                 return bridge | ||||
|         return bridge | ||||
| 
 | ||||
|     def get_bridge_slave_ifaces(self): | ||||
|         ifaces = list() | ||||
|         if self.get_type() == "bridge": | ||||
|             tree = ElementTree.fromstring(self._XMLDesc()) | ||||
|             for iface in tree.findall("./bridge/"): | ||||
|                 address = state = speed = None | ||||
|                 name = iface.get("name") | ||||
|                 if_type = iface.get("type") | ||||
|                 link = iface.find("link") | ||||
|                 if link is not None: | ||||
|                     state = link.get("state") | ||||
|                     speed = link.get("speed") | ||||
|                 mac = iface.find("mac") | ||||
|                 if mac is not None: | ||||
|                     address = mac.get("address") | ||||
|                 ifaces.append({"name": name, "type": if_type, "state": state, "speed": speed, "mac": address}) | ||||
|             return ifaces | ||||
|         else: | ||||
|         if self.get_type() != "bridge": | ||||
|             return None | ||||
| 
 | ||||
|         ifaces = [] | ||||
|         tree = ElementTree.fromstring(self._XMLDesc()) | ||||
|         for iface in tree.findall("./bridge/"): | ||||
|             address = state = speed = None | ||||
|             name = iface.get("name") | ||||
|             if_type = iface.get("type") | ||||
|             link = iface.find("link") | ||||
|             if link is not None: | ||||
|                 state = link.get("state") | ||||
|                 speed = link.get("speed") | ||||
|             mac = iface.find("mac") | ||||
|             if mac is not None: | ||||
|                 address = mac.get("address") | ||||
|             ifaces.append({"name": name, "type": if_type, "state": state, "speed": speed, "mac": address}) | ||||
|         return ifaces | ||||
| 
 | ||||
|     def get_details(self): | ||||
|         mac = self.get_mac() | ||||
|         itype = self.get_type() | ||||
|  |  | |||
|  | @ -23,10 +23,8 @@ def network_size(subnet, dhcp=None): | |||
|     if addr.version() == 6: | ||||
|         mask = mask.lstrip("/") if "/" in mask else mask | ||||
|         dhcp_pool = [IP(addr[0].strCompressed() + hex(256)), IP(addr[0].strCompressed() + hex(512 - 1))] | ||||
|     if dhcp: | ||||
|         return gateway, mask, dhcp_pool | ||||
|     else: | ||||
|         return gateway, mask, None | ||||
| 
 | ||||
|     return (gateway, mask, dhcp_pool) if dhcp else (gateway, mask, None) | ||||
| 
 | ||||
| 
 | ||||
| class wvmNetworks(wvmConnect): | ||||
|  | @ -42,7 +40,12 @@ class wvmNetworks(wvmConnect): | |||
|                 net_bridge = util.get_xml_path(net.XMLDesc(0), "/network/forward/interface/@dev") | ||||
| 
 | ||||
|             net_forward = util.get_xml_path(net.XMLDesc(0), "/network/forward/@mode") | ||||
|             networks.append({"name": network, "status": net_status, "device": net_bridge, "forward": net_forward}) | ||||
|             networks.append({ | ||||
|                 "name": network,  | ||||
|                 "status": net_status,  | ||||
|                 "device": net_bridge,  | ||||
|                 "forward": net_forward | ||||
|                 }) | ||||
|         return networks | ||||
| 
 | ||||
|     def define_network(self, xml): | ||||
|  | @ -137,7 +140,7 @@ class wvmNetwork(wvmConnect): | |||
|     def get_bridge_device(self): | ||||
|         try: | ||||
|             return self.net.bridgeName() | ||||
|         except: | ||||
|         except Exception: | ||||
|             return util.get_xml_path(self._XMLDesc(0), "/network/forward/interface/@dev") | ||||
| 
 | ||||
|     def start(self): | ||||
|  | @ -153,7 +156,7 @@ class wvmNetwork(wvmConnect): | |||
|         return self.net.update(command, section, parentIndex, xml, flags) | ||||
| 
 | ||||
|     def get_ip_networks(self): | ||||
|         ip_networks = dict() | ||||
|         ip_networks = {} | ||||
|         xml = self._XMLDesc(0) | ||||
|         if util.get_xml_path(xml, "/network/ip") is None: | ||||
|             return ip_networks | ||||
|  | @ -164,10 +167,10 @@ class wvmNetwork(wvmConnect): | |||
|             netmask_str = ip.get("netmask") | ||||
|             prefix = ip.get("prefix") | ||||
|             family = ip.get("family", "ipv4") | ||||
|             base = 32 if family == "ipv4" else 128 | ||||
|             if prefix: | ||||
|                 prefix = int(prefix) | ||||
|                 binstr = (prefix * "1") + ((base - prefix) * "0") | ||||
|                 base = 32 if family == "ipv4" else 128 | ||||
|                 binstr = prefix * "1" + (base - prefix) * "0" | ||||
|                 netmask_str = str(IP(int(binstr, base=2))) | ||||
| 
 | ||||
|             if netmask_str: | ||||
|  | @ -183,8 +186,7 @@ class wvmNetwork(wvmConnect): | |||
| 
 | ||||
|     def get_network_mac(self): | ||||
|         xml = self._XMLDesc(0) | ||||
|         mac = util.get_xml_path(xml, "/network/mac/@address") | ||||
|         return mac | ||||
|         return util.get_xml_path(xml, "/network/mac/@address") | ||||
| 
 | ||||
|     def get_network_forward(self): | ||||
|         xml = self._XMLDesc(0) | ||||
|  | @ -201,22 +203,15 @@ class wvmNetwork(wvmConnect): | |||
|             dhcpstart = util.get_xml_path(xml, "/network/ip[@family='ipv6']/dhcp/range[1]/@start") | ||||
|             dhcpend = util.get_xml_path(xml, "/network/ip[@family='ipv6']/dhcp/range[1]/@end") | ||||
| 
 | ||||
|         if not dhcpstart or not dhcpend: | ||||
|             return None | ||||
| 
 | ||||
|         return [IP(dhcpstart), IP(dhcpend)] | ||||
|         return None if not dhcpstart or not dhcpend else [IP(dhcpstart), IP(dhcpend)] | ||||
| 
 | ||||
|     def get_dhcp_range_start(self, family="ipv4"): | ||||
|         dhcp = self.get_dhcp_range(family) | ||||
|         if not dhcp: | ||||
|             return None | ||||
|         return dhcp[0] | ||||
|         return dhcp[0] if dhcp else None | ||||
| 
 | ||||
|     def get_dhcp_range_end(self, family="ipv4"): | ||||
|         dhcp = self.get_dhcp_range(family) | ||||
|         if not dhcp: | ||||
|             return None | ||||
|         return dhcp[1] | ||||
|         return dhcp[1] if dhcp else None | ||||
| 
 | ||||
|     def can_pxe(self): | ||||
|         xml = self._XMLDesc(0) | ||||
|  | @ -226,21 +221,19 @@ class wvmNetwork(wvmConnect): | |||
|         return bool(util.get_xml_path(xml, "/network/ip/dhcp/bootp/@file")) | ||||
| 
 | ||||
|     def get_dhcp_host_addr(self, family="ipv4"): | ||||
|         result = list() | ||||
|         result = [] | ||||
|         tree = etree.fromstring(self._XMLDesc(0)) | ||||
| 
 | ||||
|         for ipdhcp in tree.findall("./ip"): | ||||
|             if family == "ipv4": | ||||
|                 if ipdhcp.get("family") is None: | ||||
|                     hosts = ipdhcp.findall("./dhcp/host") | ||||
|                     for host in hosts: | ||||
|                         host_ip = host.get("ip") | ||||
|                         mac = host.get("mac") | ||||
|                         name = host.get("name", "") | ||||
|                         result.append({"ip": host_ip, "mac": mac, "name": name}) | ||||
|                     return result | ||||
|                 else: | ||||
|                 if ipdhcp.get("family") is not None: | ||||
|                     continue | ||||
|                 hosts = ipdhcp.findall("./dhcp/host") | ||||
|                 for host in hosts: | ||||
|                     host_ip = host.get("ip") | ||||
|                     mac = host.get("mac") | ||||
|                     name = host.get("name", "") | ||||
|                     result.append({"ip": host_ip, "mac": mac, "name": name}) | ||||
|                 return result | ||||
|             if family == "ipv6": | ||||
|                 hosts = tree.xpath("./ip[@family='ipv6']/dhcp/host") | ||||
|                 for host in hosts: | ||||
|  | @ -272,9 +265,9 @@ class wvmNetwork(wvmConnect): | |||
|         for h in hosts: | ||||
|             if h.get("ip") == ip: | ||||
|                 if family == "ipv4": | ||||
|                     new_xml = '<host mac="{}" name="{}" ip="{}"/>'.format(h.get("mac"), h.get("name"), ip) | ||||
|                     new_xml = f'<host mac="{h.get("mac")}" name="{h.get("name")}" ip="{ip}"/>' | ||||
|                 if family == "ipv6": | ||||
|                     new_xml = '<host id="{}" name="{}" ip="{}"/>'.format(h.get("id"), h.get("name"), ip) | ||||
|                     new_xml = f'<host id="{h.get("id")}" name="{h.get("name")}" ip="{ip}"/>' | ||||
| 
 | ||||
|                 self.update( | ||||
|                     VIR_NETWORK_UPDATE_COMMAND_DELETE, | ||||
|  | @ -298,12 +291,7 @@ class wvmNetwork(wvmConnect): | |||
|             compare_var = "id" | ||||
|             parent_index = self.parent_count - 1 | ||||
|         new_host_xml = etree.fromstring(new_xml) | ||||
| 
 | ||||
|         host = None | ||||
|         for h in hosts: | ||||
|             if h.get(compare_var) == mac_duid: | ||||
|                 host = h | ||||
|                 break | ||||
|         host = next((h for h in hosts if h.get(compare_var) == mac_duid), None) | ||||
|         if host is None: | ||||
|             self.update( | ||||
|                 VIR_NETWORK_UPDATE_COMMAND_ADD_LAST, | ||||
|  | @ -326,7 +314,7 @@ class wvmNetwork(wvmConnect): | |||
|                 ) | ||||
| 
 | ||||
|     def get_qos(self): | ||||
|         qos_values = dict() | ||||
|         qos_values = {} | ||||
|         tree = etree.fromstring(self._XMLDesc(0)) | ||||
|         qos = tree.xpath("/network/bandwidth") | ||||
|         if qos: | ||||
|  | @ -348,13 +336,10 @@ class wvmNetwork(wvmConnect): | |||
|         return qos_values | ||||
| 
 | ||||
|     def set_qos(self, direction, average, peak, burst): | ||||
|         if direction == "inbound": | ||||
|             xml = f"<inbound average='{average}' peak='{peak}' burst='{burst}'/>" | ||||
|         elif direction == "outbound": | ||||
|             xml = f"<outbound average='{average}' peak='{peak}' burst='{burst}'/>" | ||||
|         else: | ||||
|         if direction not in ("inbound","outbound"): | ||||
|             raise Exception("Direction must be inbound or outbound") | ||||
| 
 | ||||
|         xml = f"<{direction} average='{average}' peak='{peak}' burst='{burst}'/>" | ||||
|         tree = etree.fromstring(self._XMLDesc(0)) | ||||
| 
 | ||||
|         band = tree.xpath("/network/bandwidth") | ||||
|  | @ -388,7 +373,7 @@ class wvmNetwork(wvmConnect): | |||
|             self.leases = self.net.DHCPLeases() | ||||
|         except Exception as e: | ||||
|             self.leases = [] | ||||
|             raise "Error getting {} DHCP leases: {}".format(self, e) | ||||
|             raise f"Error getting {self} DHCP leases: {e}" from e | ||||
| 
 | ||||
|     def get_dhcp_leases(self): | ||||
|         if self.leases is None: | ||||
|  |  | |||
|  | @ -47,11 +47,8 @@ class wvmNWFilter(wvmConnect): | |||
|         return ElementTree.tostring(tree).decode() | ||||
| 
 | ||||
|     def get_filter_refs(self): | ||||
|         refs = [] | ||||
|         tree = ElementTree.fromstring(self._XMLDesc(0)) | ||||
|         for ref in tree.findall("./filterref"): | ||||
|             refs.append(ref.get("filter")) | ||||
|         return refs | ||||
|         return [ref.get("filter") for ref in tree.findall("./filterref")] | ||||
| 
 | ||||
|     def get_rules(self): | ||||
|         rules = [] | ||||
|  |  | |||
|  | @ -1,3 +1,5 @@ | |||
| import contextlib | ||||
| 
 | ||||
| from vrtManager import util | ||||
| from vrtManager.connection import wvmConnect | ||||
| 
 | ||||
|  | @ -10,10 +12,7 @@ class wvmStorages(wvmConnect): | |||
|             stg = self.get_storage(pool) | ||||
|             stg_status = stg.isActive() | ||||
|             stg_type = util.get_xml_path(stg.XMLDesc(0), "/pool/@type") | ||||
|             if stg_status: | ||||
|                 stg_vol = len(stg.listVolumes()) | ||||
|             else: | ||||
|                 stg_vol = None | ||||
|             stg_vol = len(stg.listVolumes()) if stg_status else None | ||||
|             stg_size = stg.info()[1] | ||||
|             storages.append( | ||||
|                 {"name": pool, "status": stg_status, "type": stg_type, "volumes": stg_vol, "size": stg_size} | ||||
|  | @ -33,7 +32,7 @@ class wvmStorages(wvmConnect): | |||
|                             <format type='lvm2'/> | ||||
|                         </source>""" | ||||
|         if stg_type == "logical": | ||||
|             target = "/dev/" + name | ||||
|             target = f"/dev/{name}" | ||||
|         xml += f""" | ||||
|                   <target> | ||||
|                        <path>{target}</path> | ||||
|  | @ -125,10 +124,10 @@ class wvmStorage(wvmConnect): | |||
|         return self.pool.UUIDString() | ||||
| 
 | ||||
|     def start(self): | ||||
|         self.pool.create(0) | ||||
|         return self.pool.create(0) | ||||
| 
 | ||||
|     def stop(self): | ||||
|         self.pool.destroy() | ||||
|         return self.pool.destroy() | ||||
| 
 | ||||
|     def delete(self): | ||||
|         self.pool.undefine() | ||||
|  | @ -225,26 +224,30 @@ class wvmStorage(wvmConnect): | |||
|         return util.get_xml_path(vol_xml, "/volume/@type") | ||||
| 
 | ||||
|     def refresh(self): | ||||
|         self.pool.refresh(0) | ||||
|         return self.pool.refresh(0) | ||||
| 
 | ||||
|     def update_volumes(self): | ||||
|     def get_volume_details(self, volname): | ||||
|         try: | ||||
|             self.refresh() | ||||
|         except Exception: | ||||
|             pass | ||||
|         vols = self.get_volumes() | ||||
|         vol_list = [] | ||||
| 
 | ||||
|         for volname in vols: | ||||
|             vol_list.append( | ||||
|                 { | ||||
|                     "name": volname, | ||||
|                     "size": self.get_volume_size(volname), | ||||
|                     "allocation": self.get_volume_allocation(volname), | ||||
|                     "type": self.get_volume_format_type(volname), | ||||
|                 } | ||||
|             ) | ||||
|         return vol_list | ||||
|         return { | ||||
|                 "name": volname, | ||||
|                 "size": self.get_volume_size(volname), | ||||
|                 "allocation": self.get_volume_allocation(volname), | ||||
|                 "type": self.get_volume_format_type(volname), | ||||
|         } | ||||
| 
 | ||||
| 
 | ||||
|     def update_volumes(self): | ||||
|         with contextlib.suppress(Exception): | ||||
|             self.refresh() | ||||
|         vols = self.get_volumes() | ||||
|         return [{"name": volname, "size": self.get_volume_size(volname), | ||||
|                  "allocation": self.get_volume_allocation(volname), | ||||
|                  "type": self.get_volume_format_type(volname)} for volname in vols] | ||||
| 
 | ||||
| 
 | ||||
|     def create_volume(self, name, size, vol_fmt="qcow2", metadata=False, disk_owner_uid=0, disk_owner_gid=0): | ||||
|         size = int(size) * 1073741824 | ||||
|  | @ -253,10 +256,7 @@ class wvmStorage(wvmConnect): | |||
|         if vol_fmt == "unknown": | ||||
|             vol_fmt = "raw" | ||||
|         if storage_type == "dir": | ||||
|             if vol_fmt in ("qcow", "qcow2"): | ||||
|                 name += "." + vol_fmt | ||||
|             else: | ||||
|                 name += ".img" | ||||
|             name += f".{vol_fmt}" if vol_fmt in ("qcow", "qcow2") else ".img" | ||||
|             alloc = 0 | ||||
|         xml = f""" | ||||
|             <volume> | ||||
|  | @ -300,9 +300,9 @@ class wvmStorage(wvmConnect): | |||
|         storage_type = self.get_type() | ||||
|         if storage_type == "dir": | ||||
|             if vol_fmt in ["qcow", "qcow2"]: | ||||
|                 target_file += "." + vol_fmt | ||||
|                 target_file += f".{vol_fmt}" | ||||
|             else: | ||||
|                 suffix = "." + file_suffix | ||||
|                 suffix = f".{file_suffix}" | ||||
|                 target_file += suffix if len(suffix) > 1 else "" | ||||
| 
 | ||||
|         xml = f""" | ||||
|  |  | |||
|  | @ -9,10 +9,7 @@ import lxml.etree as etree | |||
| 
 | ||||
| def is_kvm_available(xml): | ||||
|     kvm_domains = get_xml_path(xml, "//domain/@type='kvm'") | ||||
|     if kvm_domains > 0: | ||||
|         return True | ||||
|     else: | ||||
|         return False | ||||
|     return kvm_domains > 0 | ||||
| 
 | ||||
| 
 | ||||
| def randomMAC(): | ||||
|  | @ -26,40 +23,40 @@ def randomMAC(): | |||
| 
 | ||||
| def randomUUID(): | ||||
|     """Generate a random UUID.""" | ||||
|     u = [secrets.randbelow(256) for ignore in range(0, 16)] | ||||
|     u[6] = (u[6] & 0x0F) | (4 << 4) | ||||
|     u[8] = (u[8] & 0x3F) | (2 << 6) | ||||
|     u = [secrets.randbelow(256) for _ in range(16)] | ||||
|     u[6] = u[6] & 15 | 4 << 4 | ||||
|     u[8] = u[8] & 63 | 2 << 6 | ||||
|     return "-".join(["%02x" * 4, "%02x" * 2, "%02x" * 2, "%02x" * 2, "%02x" * 6]) % tuple(u) | ||||
| 
 | ||||
| 
 | ||||
| def randomPasswd(length=12, alphabet=string.ascii_letters + string.digits): | ||||
|     """Generate a random password""" | ||||
|     return "".join([secrets.choice(alphabet) for i in range(length)]) | ||||
|     return "".join([secrets.choice(alphabet) for _ in range(length)]) | ||||
| 
 | ||||
| 
 | ||||
| def get_max_vcpus(conn, type=None): | ||||
| def get_max_vcpus(conn, guest_type=None): | ||||
|     """@param conn: libvirt connection to poll for max possible vcpus | ||||
|     @type type: optional guest type (kvm, etc.)""" | ||||
|     @param guest_type: optional guest type (kvm, etc.)""" | ||||
|     if type is None: | ||||
|         type = conn.getType() | ||||
|         guest_type = conn.getType() | ||||
|     try: | ||||
|         m = conn.getMaxVcpus(type.lower()) | ||||
|         m = conn.getMaxVcpus(guest_type.lower()) | ||||
|     except libvirt.libvirtError: | ||||
|         m = 32 | ||||
|     return m | ||||
| 
 | ||||
| 
 | ||||
| def xml_escape(str): | ||||
| def xml_escape(xml_str): | ||||
|     """Replaces chars ' " < > & with xml safe counterparts""" | ||||
|     if str is None: | ||||
|     if xml_str is None: | ||||
|         return None | ||||
| 
 | ||||
|     str = str.replace("&", "&") | ||||
|     str = str.replace("'", "'") | ||||
|     str = str.replace('"', """) | ||||
|     str = str.replace("<", "<") | ||||
|     str = str.replace(">", ">") | ||||
|     return str | ||||
|     xml_str = xml_str.replace("&", "&") | ||||
|     xml_str = xml_str.replace("'", "'") | ||||
|     xml_str = xml_str.replace('"', """) | ||||
|     xml_str = xml_str.replace("<", "<") | ||||
|     xml_str = xml_str.replace(">", ">") | ||||
|     return xml_str | ||||
| 
 | ||||
| 
 | ||||
| def compareMAC(p, q): | ||||
|  | @ -108,10 +105,7 @@ def get_xpath(doc, path): | |||
|     if ret is not None: | ||||
|         if isinstance(ret, list): | ||||
|             if len(ret) >= 1: | ||||
|                 if hasattr(ret[0], "text"): | ||||
|                     result = ret[0].text | ||||
|                 else: | ||||
|                     result = ret[0] | ||||
|                 result = ret[0].text if hasattr(ret[0], "text") else ret[0] | ||||
|         else: | ||||
|             result = ret | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue