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