1
0
Fork 0
mirror of https://github.com/retspen/webvirtcloud synced 2025-07-31 12:41:08 +00:00

lint with black python. convert f style strings to old one. some small fixes

This commit is contained in:
catborise 2020-11-05 12:34:31 +03:00
parent c20c353a40
commit 508e3609be
54 changed files with 2123 additions and 1824 deletions

View file

@ -6,7 +6,7 @@ Further Information might be available at:
https://github.com/haypo/python-ipy
"""
__version__ = '1.00'
__version__ = "1.00"
import bisect
import collections
@ -17,16 +17,16 @@ import types
# this should include www.iana.org/assignments/ipv4-address-space
# and www.iana.org/assignments/multicast-addresses
IPv4ranges = {
'0': 'PUBLIC', # fall back
'00000000': 'PRIVATE', # 0/8
'00001010': 'PRIVATE', # 10/8
'0110010001': 'CARRIER_GRADE_NAT', # 100.64/10
'01111111': 'LOOPBACK', # 127.0/8
'1': 'PUBLIC', # fall back
'1010100111111110': 'PRIVATE', # 169.254/16
'101011000001': 'PRIVATE', # 172.16/12
'1100000010101000': 'PRIVATE', # 192.168/16
'111': 'RESERVED', # 224/3
"0": "PUBLIC", # fall back
"00000000": "PRIVATE", # 0/8
"00001010": "PRIVATE", # 10/8
"0110010001": "CARRIER_GRADE_NAT", # 100.64/10
"01111111": "LOOPBACK", # 127.0/8
"1": "PUBLIC", # fall back
"1010100111111110": "PRIVATE", # 169.254/16
"101011000001": "PRIVATE", # 172.16/12
"1100000010101000": "PRIVATE", # 192.168/16
"111": "RESERVED", # 224/3
}
# Definition of the Ranges for IPv6 IPs
@ -34,92 +34,92 @@ IPv4ranges = {
# http://www.iana.org/assignments/ipv6-unicast-address-assignments/
# http://www.iana.org/assignments/ipv6-multicast-addresses/
IPv6ranges = {
'00000000': 'RESERVED', # ::/8
'0' * 96: 'RESERVED', # ::/96 Formerly IPV4COMP [RFC4291]
'0' * 128: 'UNSPECIFIED', # ::/128
'0' * 127 + '1': 'LOOPBACK', # ::1/128
'0' * 80 + '1' * 16: 'IPV4MAP', # ::ffff:0:0/96
'00000000011001001111111110011011' + '0' * 64: 'WKP46TRANS', # 0064:ff9b::/96 Well-Known-Prefix [RFC6052]
'00000001': 'UNASSIGNED', # 0100::/8
'0000001': 'RESERVED', # 0200::/7 Formerly NSAP [RFC4048]
'0000010': 'RESERVED', # 0400::/7 Formerly IPX [RFC3513]
'0000011': 'RESERVED', # 0600::/7
'00001': 'RESERVED', # 0800::/5
'0001': 'RESERVED', # 1000::/4
'001': 'GLOBAL-UNICAST', # 2000::/3 [RFC4291]
'00100000000000010000000': 'SPECIALPURPOSE', # 2001::/23 [RFC4773]
'00100000000000010000000000000000': 'TEREDO', # 2001::/32 [RFC4380]
'00100000000000010000000000000010' + '0' * 16: 'BMWG', # 2001:0002::/48 Benchmarking [RFC5180]
'0010000000000001000000000001': 'ORCHID', # 2001:0010::/28 (Temp until 2014-03-21) [RFC4843]
'00100000000000010000001': 'ALLOCATED APNIC', # 2001:0200::/23
'00100000000000010000010': 'ALLOCATED ARIN', # 2001:0400::/23
'00100000000000010000011': 'ALLOCATED RIPE NCC', # 2001:0600::/23
'00100000000000010000100': 'ALLOCATED RIPE NCC', # 2001:0800::/23
'00100000000000010000101': 'ALLOCATED RIPE NCC', # 2001:0a00::/23
'00100000000000010000110': 'ALLOCATED APNIC', # 2001:0c00::/23
'00100000000000010000110110111000': 'DOCUMENTATION', # 2001:0db8::/32 [RFC3849]
'00100000000000010000111': 'ALLOCATED APNIC', # 2001:0e00::/23
'00100000000000010001001': 'ALLOCATED LACNIC', # 2001:1200::/23
'00100000000000010001010': 'ALLOCATED RIPE NCC', # 2001:1400::/23
'00100000000000010001011': 'ALLOCATED RIPE NCC', # 2001:1600::/23
'00100000000000010001100': 'ALLOCATED ARIN', # 2001:1800::/23
'00100000000000010001101': 'ALLOCATED RIPE NCC', # 2001:1a00::/23
'0010000000000001000111': 'ALLOCATED RIPE NCC', # 2001:1c00::/22
'00100000000000010010': 'ALLOCATED RIPE NCC', # 2001:2000::/20
'001000000000000100110': 'ALLOCATED RIPE NCC', # 2001:3000::/21
'0010000000000001001110': 'ALLOCATED RIPE NCC', # 2001:3800::/22
'0010000000000001001111': 'RESERVED', # 2001:3c00::/22 Possible future allocation to RIPE NCC
'00100000000000010100000': 'ALLOCATED RIPE NCC', # 2001:4000::/23
'00100000000000010100001': 'ALLOCATED AFRINIC', # 2001:4200::/23
'00100000000000010100010': 'ALLOCATED APNIC', # 2001:4400::/23
'00100000000000010100011': 'ALLOCATED RIPE NCC', # 2001:4600::/23
'00100000000000010100100': 'ALLOCATED ARIN', # 2001:4800::/23
'00100000000000010100101': 'ALLOCATED RIPE NCC', # 2001:4a00::/23
'00100000000000010100110': 'ALLOCATED RIPE NCC', # 2001:4c00::/23
'00100000000000010101': 'ALLOCATED RIPE NCC', # 2001:5000::/20
'0010000000000001100': 'ALLOCATED APNIC', # 2001:8000::/19
'00100000000000011010': 'ALLOCATED APNIC', # 2001:a000::/20
'00100000000000011011': 'ALLOCATED APNIC', # 2001:b000::/20
'0010000000000010': '6TO4', # 2002::/16 "6to4" [RFC3056]
'001000000000001100': 'ALLOCATED RIPE NCC', # 2003::/18
'001001000000': 'ALLOCATED APNIC', # 2400::/12
'001001100000': 'ALLOCATED ARIN', # 2600::/12
'00100110000100000000000': 'ALLOCATED ARIN', # 2610::/23
'00100110001000000000000': 'ALLOCATED ARIN', # 2620::/23
'001010000000': 'ALLOCATED LACNIC', # 2800::/12
'001010100000': 'ALLOCATED RIPE NCC', # 2a00::/12
'001011000000': 'ALLOCATED AFRINIC', # 2c00::/12
'00101101': 'RESERVED', # 2d00::/8
'0010111': 'RESERVED', # 2e00::/7
'0011': 'RESERVED', # 3000::/4
'010': 'RESERVED', # 4000::/3
'011': 'RESERVED', # 6000::/3
'100': 'RESERVED', # 8000::/3
'101': 'RESERVED', # a000::/3
'110': 'RESERVED', # c000::/3
'1110': 'RESERVED', # e000::/4
'11110': 'RESERVED', # f000::/5
'111110': 'RESERVED', # f800::/6
'1111110': 'ULA', # fc00::/7 [RFC4193]
'111111100': 'RESERVED', # fe00::/9
'1111111010': 'LINKLOCAL', # fe80::/10
'1111111011': 'RESERVED', # fec0::/10 Formerly SITELOCAL [RFC4291]
'11111111': 'MULTICAST', # ff00::/8
'1111111100000001': 'NODE-LOCAL MULTICAST', # ff01::/16
'1111111100000010': 'LINK-LOCAL MULTICAST', # ff02::/16
'1111111100000100': 'ADMIN-LOCAL MULTICAST', # ff04::/16
'1111111100000101': 'SITE-LOCAL MULTICAST', # ff05::/16
'1111111100001000': 'ORG-LOCAL MULTICAST', # ff08::/16
'1111111100001110': 'GLOBAL MULTICAST', # ff0e::/16
'1111111100001111': 'RESERVED MULTICAST', # ff0f::/16
'111111110011': 'PREFIX-BASED MULTICAST', # ff30::/12 [RFC3306]
'111111110111': 'RP-EMBEDDED MULTICAST', # ff70::/12 [RFC3956]
"00000000": "RESERVED", # ::/8
"0" * 96: "RESERVED", # ::/96 Formerly IPV4COMP [RFC4291]
"0" * 128: "UNSPECIFIED", # ::/128
"0" * 127 + "1": "LOOPBACK", # ::1/128
"0" * 80 + "1" * 16: "IPV4MAP", # ::ffff:0:0/96
"00000000011001001111111110011011" + "0" * 64: "WKP46TRANS", # 0064:ff9b::/96 Well-Known-Prefix [RFC6052]
"00000001": "UNASSIGNED", # 0100::/8
"0000001": "RESERVED", # 0200::/7 Formerly NSAP [RFC4048]
"0000010": "RESERVED", # 0400::/7 Formerly IPX [RFC3513]
"0000011": "RESERVED", # 0600::/7
"00001": "RESERVED", # 0800::/5
"0001": "RESERVED", # 1000::/4
"001": "GLOBAL-UNICAST", # 2000::/3 [RFC4291]
"00100000000000010000000": "SPECIALPURPOSE", # 2001::/23 [RFC4773]
"00100000000000010000000000000000": "TEREDO", # 2001::/32 [RFC4380]
"00100000000000010000000000000010" + "0" * 16: "BMWG", # 2001:0002::/48 Benchmarking [RFC5180]
"0010000000000001000000000001": "ORCHID", # 2001:0010::/28 (Temp until 2014-03-21) [RFC4843]
"00100000000000010000001": "ALLOCATED APNIC", # 2001:0200::/23
"00100000000000010000010": "ALLOCATED ARIN", # 2001:0400::/23
"00100000000000010000011": "ALLOCATED RIPE NCC", # 2001:0600::/23
"00100000000000010000100": "ALLOCATED RIPE NCC", # 2001:0800::/23
"00100000000000010000101": "ALLOCATED RIPE NCC", # 2001:0a00::/23
"00100000000000010000110": "ALLOCATED APNIC", # 2001:0c00::/23
"00100000000000010000110110111000": "DOCUMENTATION", # 2001:0db8::/32 [RFC3849]
"00100000000000010000111": "ALLOCATED APNIC", # 2001:0e00::/23
"00100000000000010001001": "ALLOCATED LACNIC", # 2001:1200::/23
"00100000000000010001010": "ALLOCATED RIPE NCC", # 2001:1400::/23
"00100000000000010001011": "ALLOCATED RIPE NCC", # 2001:1600::/23
"00100000000000010001100": "ALLOCATED ARIN", # 2001:1800::/23
"00100000000000010001101": "ALLOCATED RIPE NCC", # 2001:1a00::/23
"0010000000000001000111": "ALLOCATED RIPE NCC", # 2001:1c00::/22
"00100000000000010010": "ALLOCATED RIPE NCC", # 2001:2000::/20
"001000000000000100110": "ALLOCATED RIPE NCC", # 2001:3000::/21
"0010000000000001001110": "ALLOCATED RIPE NCC", # 2001:3800::/22
"0010000000000001001111": "RESERVED", # 2001:3c00::/22 Possible future allocation to RIPE NCC
"00100000000000010100000": "ALLOCATED RIPE NCC", # 2001:4000::/23
"00100000000000010100001": "ALLOCATED AFRINIC", # 2001:4200::/23
"00100000000000010100010": "ALLOCATED APNIC", # 2001:4400::/23
"00100000000000010100011": "ALLOCATED RIPE NCC", # 2001:4600::/23
"00100000000000010100100": "ALLOCATED ARIN", # 2001:4800::/23
"00100000000000010100101": "ALLOCATED RIPE NCC", # 2001:4a00::/23
"00100000000000010100110": "ALLOCATED RIPE NCC", # 2001:4c00::/23
"00100000000000010101": "ALLOCATED RIPE NCC", # 2001:5000::/20
"0010000000000001100": "ALLOCATED APNIC", # 2001:8000::/19
"00100000000000011010": "ALLOCATED APNIC", # 2001:a000::/20
"00100000000000011011": "ALLOCATED APNIC", # 2001:b000::/20
"0010000000000010": "6TO4", # 2002::/16 "6to4" [RFC3056]
"001000000000001100": "ALLOCATED RIPE NCC", # 2003::/18
"001001000000": "ALLOCATED APNIC", # 2400::/12
"001001100000": "ALLOCATED ARIN", # 2600::/12
"00100110000100000000000": "ALLOCATED ARIN", # 2610::/23
"00100110001000000000000": "ALLOCATED ARIN", # 2620::/23
"001010000000": "ALLOCATED LACNIC", # 2800::/12
"001010100000": "ALLOCATED RIPE NCC", # 2a00::/12
"001011000000": "ALLOCATED AFRINIC", # 2c00::/12
"00101101": "RESERVED", # 2d00::/8
"0010111": "RESERVED", # 2e00::/7
"0011": "RESERVED", # 3000::/4
"010": "RESERVED", # 4000::/3
"011": "RESERVED", # 6000::/3
"100": "RESERVED", # 8000::/3
"101": "RESERVED", # a000::/3
"110": "RESERVED", # c000::/3
"1110": "RESERVED", # e000::/4
"11110": "RESERVED", # f000::/5
"111110": "RESERVED", # f800::/6
"1111110": "ULA", # fc00::/7 [RFC4193]
"111111100": "RESERVED", # fe00::/9
"1111111010": "LINKLOCAL", # fe80::/10
"1111111011": "RESERVED", # fec0::/10 Formerly SITELOCAL [RFC4291]
"11111111": "MULTICAST", # ff00::/8
"1111111100000001": "NODE-LOCAL MULTICAST", # ff01::/16
"1111111100000010": "LINK-LOCAL MULTICAST", # ff02::/16
"1111111100000100": "ADMIN-LOCAL MULTICAST", # ff04::/16
"1111111100000101": "SITE-LOCAL MULTICAST", # ff05::/16
"1111111100001000": "ORG-LOCAL MULTICAST", # ff08::/16
"1111111100001110": "GLOBAL MULTICAST", # ff0e::/16
"1111111100001111": "RESERVED MULTICAST", # ff0f::/16
"111111110011": "PREFIX-BASED MULTICAST", # ff30::/12 [RFC3306]
"111111110111": "RP-EMBEDDED MULTICAST", # ff70::/12 [RFC3956]
}
MAX_IPV4_ADDRESS = 0xffffffff
MAX_IPV6_ADDRESS = 0xffffffffffffffffffffffffffffffff
IPV6_TEST_MAP = 0xffffffffffffffffffffffff00000000
IPV6_MAP_MASK = 0x00000000000000000000ffff00000000
MAX_IPV4_ADDRESS = 0xFFFFFFFF
MAX_IPV6_ADDRESS = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
IPV6_TEST_MAP = 0xFFFFFFFFFFFFFFFFFFFFFFFF00000000
IPV6_MAP_MASK = 0x00000000000000000000FFFF00000000
if sys.version_info >= (3,):
INT_TYPES = (int,)
@ -202,7 +202,7 @@ class IPint(object):
elif isinstance(data, STR_TYPES):
# TODO: refactor me!
# splitting of a string into IP and prefixlen et. al.
x = data.split('-')
x = data.split("-")
if len(x) == 2:
# a.b.c.0-a.b.c.255 specification ?
(ip, last) = x
@ -219,10 +219,10 @@ class IPint(object):
# make sure the broadcast is the same as the last ip
# otherwise it will return /16 for something like:
# 192.168.0.0-192.168.191.255
if IP('%s/%s' % (ip, 32 - netbits)).broadcast().int() != last:
if IP("%s/%s" % (ip, 32 - netbits)).broadcast().int() != last:
raise ValueError("the range %s is not on a network boundary." % data)
elif len(x) == 1:
x = data.split('/')
x = data.split("/")
# if no prefix is given use defaults
if len(x) == 1:
ip = x[0]
@ -231,7 +231,7 @@ class IPint(object):
raise ValueError("only one '/' allowed in IP Address")
else:
(ip, prefixlen) = x
if prefixlen.find('.') != -1:
if prefixlen.find(".") != -1:
# check if the user might have used a netmask like
# a.b.c.d/255.255.255.0
(netmask, vers) = parseAddress(prefixlen)
@ -255,8 +255,7 @@ class IPint(object):
if make_net:
self.ip = self.ip & _prefixlenToNetmask(self._prefixlen, self._ipversion)
if not _checkNetaddrWorksWithPrefixlen(self.ip,
self._prefixlen, self._ipversion):
if not _checkNetaddrWorksWithPrefixlen(self.ip, self._prefixlen, self._ipversion):
raise ValueError("%s has invalid prefix length (%s)" % (repr(self), self._prefixlen))
else:
raise TypeError("Unsupported data type: %s" % type(data))
@ -314,8 +313,7 @@ class IPint(object):
want == 3 -lastip 1.2.3.0-1.2.3.255
"""
if (self._ipversion == 4 and self._prefixlen == 32) or \
(self._ipversion == 6 and self._prefixlen == 128):
if (self._ipversion == 4 and self._prefixlen == 32) or (self._ipversion == 6 and self._prefixlen == 128):
if self.NoPrefixForSingleIp:
want = 0
if want is None:
@ -335,7 +333,7 @@ class IPint(object):
# default
return "/%d" % (self._prefixlen)
else:
return ''
return ""
# We have different flavours to convert to:
# strFullsize 127.0.0.1 2001:0658:022a:cafe:0200:c0ff:fe8d:08fa
@ -357,7 +355,7 @@ class IPint(object):
if self.WantPrefixLen is None and wantprefixlen is None:
wantprefixlen = 0
ret = _intToBin(self.ip)
return '0' * (bits - len(ret)) + ret + self._printPrefix(wantprefixlen)
return "0" * (bits - len(ret)) + ret + self._printPrefix(wantprefixlen)
def strCompressed(self, wantprefixlen=None):
"""Return a string representation in compressed format using '::' Notation.
@ -376,12 +374,12 @@ class IPint(object):
if self._ipversion == 4:
return self.strFullsize(wantprefixlen)
else:
if self.ip >> 32 == 0xffff:
if self.ip >> 32 == 0xFFFF:
ipv4 = intToIp(self.ip & MAX_IPV4_ADDRESS, 4)
text = "::ffff:" + ipv4 + self._printPrefix(wantprefixlen)
return text
# find the longest sequence of '0'
hextets = [int(x, 16) for x in self.strFullsize(0).split(':')]
hextets = [int(x, 16) for x in self.strFullsize(0).split(":")]
# every element of followingzeros will contain the number of zeros
# following the corresponding element of hextets
followingzeros = [0] * 8
@ -392,15 +390,15 @@ class IPint(object):
if max(followingzeros) > 1:
# genererate string with the longest number of zeros cut out
# now we need hextets as strings
hextets = [x for x in self.strNormal(0).split(':')]
while compressionpos < len(hextets) and hextets[compressionpos] == '0':
del (hextets[compressionpos])
hextets.insert(compressionpos, '')
hextets = [x for x in self.strNormal(0).split(":")]
while compressionpos < len(hextets) and hextets[compressionpos] == "0":
del hextets[compressionpos]
hextets.insert(compressionpos, "")
if compressionpos + 1 >= len(hextets):
hextets.append('')
hextets.append("")
if compressionpos == 0:
hextets = [''] + hextets
return ':'.join(hextets) + self._printPrefix(wantprefixlen)
hextets = [""] + hextets
return ":".join(hextets) + self._printPrefix(wantprefixlen)
else:
return self.strNormal(0) + self._printPrefix(wantprefixlen)
@ -419,7 +417,7 @@ class IPint(object):
if self._ipversion == 4:
ret = self.strFullsize(0)
elif self._ipversion == 6:
ret = ':'.join(["%x" % x for x in [int(x, 16) for x in self.strFullsize(0).split(':')]])
ret = ":".join(["%x" % x for x in [int(x, 16) for x in self.strFullsize(0).split(":")]])
else:
raise ValueError("only IPv4 and IPv6 supported")
@ -451,7 +449,7 @@ class IPint(object):
if self.WantPrefixLen is None and wantprefixlen is None:
wantprefixlen = 0
x = '0x%x' % self.ip
x = "0x%x" % self.ip
return x + self._printPrefix(wantprefixlen)
def strDec(self, wantprefixlen=None):
@ -466,7 +464,7 @@ class IPint(object):
if self.WantPrefixLen is None and wantprefixlen is None:
wantprefixlen = 0
x = '%d' % self.ip
x = "%d" % self.ip
return x + self._printPrefix(wantprefixlen)
def iptype(self):
@ -581,10 +579,8 @@ class IPint(object):
raise ValueError("Only adjacent networks can be added together.")
ret = IP(self.int(), ipversion=self._ipversion)
ret._prefixlen = self.prefixlen() - 1
if not _checkNetaddrWorksWithPrefixlen(ret.ip, ret._prefixlen,
ret._ipversion):
raise ValueError("The resulting %s has invalid prefix length (%s)"
% (repr(ret), ret._prefixlen))
if not _checkNetaddrWorksWithPrefixlen(ret.ip, ret._prefixlen, ret._ipversion):
raise ValueError("The resulting %s has invalid prefix length (%s)" % (repr(ret), ret._prefixlen))
return ret
def __sub__(self, other):
@ -692,7 +688,7 @@ class IPint(object):
IP('10.0.0.0/24')
"""
return ("IPint('%s')" % (self.strCompressed(1)))
return "IPint('%s')" % (self.strCompressed(1))
def __cmp__(self, other):
"""Called by comparison operations.
@ -777,7 +773,7 @@ class IPint(object):
thehash = int(-1)
ip = self.ip
while ip > 0:
thehash = thehash ^ (ip & 0x7fffffff)
thehash = thehash ^ (ip & 0x7FFFFFFF)
ip = ip >> 32
thehash = thehash ^ self._prefixlen
return int(thehash)
@ -811,17 +807,17 @@ class IP(IPint):
>>> IP('10.0.0.0/8').netmask()
IP('255.0.0.0')
"""
"""
return IP(IPint.netmask(self), ipversion=self._ipversion)
def _getIPv4Map(self):
if self._ipversion != 6:
return None
if (self.ip >> 32) != 0xffff:
if (self.ip >> 32) != 0xFFFF:
return None
ipv4 = self.ip & MAX_IPV4_ADDRESS
if self._prefixlen != 128:
ipv4 = '%s/%s' % (ipv4, 32 - (128 - self._prefixlen))
ipv4 = "%s/%s" % (ipv4, 32 - (128 - self._prefixlen))
return IP(ipv4, ipversion=4)
def reverseNames(self):
@ -872,7 +868,7 @@ class IP(IPint):
raise NotImplementedError("can't create IPv6 reverse names at sub nibble level")
s = list(s)
s.reverse()
s = '.'.join(s)
s = ".".join(s)
first_nibble_index = int(32 - (self._prefixlen // 4)) * 2
return ["%s.ip6.arpa." % s[first_nibble_index:]]
else:
@ -897,32 +893,34 @@ class IP(IPint):
if self._ipversion == 4:
s = self.strFullsize(0)
s = s.split('.')
s = s.split(".")
s.reverse()
first_byte_index = int(4 - (self._prefixlen // 8))
if self._prefixlen % 8 != 0:
nibblepart = "%s-%s" % (
s[3 - (self._prefixlen // 8)], intToIp(self.ip + self.len() - 1, 4).split('.')[-1])
nibblepart += '.'
s[3 - (self._prefixlen // 8)],
intToIp(self.ip + self.len() - 1, 4).split(".")[-1],
)
nibblepart += "."
else:
nibblepart = ""
s = '.'.join(s[first_byte_index:])
s = ".".join(s[first_byte_index:])
return "%s%s.in-addr.arpa." % (nibblepart, s)
elif self._ipversion == 6:
ipv4 = self._getIPv4Map()
if ipv4 is not None:
return ipv4.reverseName()
s = '%032x' % self.ip
s = "%032x" % self.ip
if self._prefixlen % 4 != 0:
nibblepart = "%s-%x" % (s[self._prefixlen:], self.ip + self.len() - 1)
nibblepart += '.'
nibblepart = "%s-%x" % (s[self._prefixlen :], self.ip + self.len() - 1)
nibblepart += "."
else:
nibblepart = ""
s = list(s)
s.reverse()
s = '.'.join(s)
s = ".".join(s)
first_nibble_index = int(32 - (self._prefixlen // 4)) * 2
return "%s%s.ip6.arpa." % (nibblepart, s[first_nibble_index:])
else:
@ -937,9 +935,9 @@ class IP(IPint):
>>> print(IP('127.0.0.1').make_net('255.0.0.0'))
127.0.0.0/8
"""
if '/' in str(netmask):
if "/" in str(netmask):
raise ValueError("invalid netmask (%s)" % netmask)
return IP('%s/%s' % (self, netmask), make_net=True)
return IP("%s/%s" % (self, netmask), make_net=True)
def __getitem__(self, key):
"""Called to implement evaluation of self[key].
@ -968,7 +966,7 @@ class IP(IPint):
IP('10.0.0.0/8')
"""
return ("IP('%s')" % (self.strCompressed(1)))
return "IP('%s')" % (self.strCompressed(1))
def get_mac(self):
"""
@ -980,15 +978,15 @@ class IP(IPint):
"""
if self._ipversion != 6:
return None
if (self.ip & 0x20000ffff000000) != 0x20000fffe000000:
if (self.ip & 0x20000FFFF000000) != 0x20000FFFE000000:
return None
return '%02x:%02x:%02x:%02x:%02x:%02x' % (
(((self.ip >> 56) & 0xff) & 0xfd),
(self.ip >> 48) & 0xff,
(self.ip >> 40) & 0xff,
(self.ip >> 16) & 0xff,
(self.ip >> 8) & 0xff,
self.ip & 0xff,
return "%02x:%02x:%02x:%02x:%02x:%02x" % (
(((self.ip >> 56) & 0xFF) & 0xFD),
(self.ip >> 48) & 0xFF,
(self.ip >> 40) & 0xFF,
(self.ip >> 16) & 0xFF,
(self.ip >> 8) & 0xFF,
self.ip & 0xFF,
)
def v46map(self):
@ -1003,14 +1001,11 @@ class IP(IPint):
IP('192.168.1.1')
"""
if self._ipversion == 4:
return IP(str(IPV6_MAP_MASK + self.ip) +
"/%s" % (self._prefixlen + 96))
return IP(str(IPV6_MAP_MASK + self.ip) + "/%s" % (self._prefixlen + 96))
else:
if self.ip & IPV6_TEST_MAP == IPV6_MAP_MASK:
return IP(str(self.ip - IPV6_MAP_MASK) +
"/%s" % (self._prefixlen - 96))
raise ValueError("%s cannot be converted to an IPv4 address."
% repr(self))
return IP(str(self.ip - IPV6_MAP_MASK) + "/%s" % (self._prefixlen - 96))
raise ValueError("%s cannot be converted to an IPv4 address." % repr(self))
class IPSet(collections.MutableSet):
@ -1022,7 +1017,7 @@ class IPSet(collections.MutableSet):
# Make sure we only accept IP objects
for prefix in iterable:
if not isinstance(prefix, IP):
raise ValueError('Only IP objects can be added to an IPSet')
raise ValueError("Only IP objects can be added to an IPSet")
# Store and optimize
self.prefixes = iterable[:]
@ -1083,7 +1078,7 @@ class IPSet(collections.MutableSet):
return IPSet(result)
def __repr__(self):
return '%s([' % self.__class__.__name__ + ', '.join(map(repr, self.prefixes)) + '])'
return "%s([" % self.__class__.__name__ + ", ".join(map(repr, self.prefixes)) + "])"
def len(self):
return sum(prefix.len() for prefix in self.prefixes)
@ -1096,7 +1091,7 @@ class IPSet(collections.MutableSet):
# Check type
for prefix in value:
if not isinstance(prefix, IP):
raise ValueError('Only IP objects can be added to an IPSet')
raise ValueError("Only IP objects can be added to an IPSet")
# Append and optimize
self.prefixes.extend(value)
@ -1114,7 +1109,7 @@ class IPSet(collections.MutableSet):
# Remove
for del_prefix in value:
if not isinstance(del_prefix, IP):
raise ValueError('Only IP objects can be removed from an IPSet')
raise ValueError("Only IP objects can be removed from an IPSet")
# First check if this prefix contains anything in our list
found = False
@ -1134,7 +1129,7 @@ class IPSet(collections.MutableSet):
found = False
for i in range(len(self.prefixes)):
if del_prefix in self.prefixes[i]:
self.prefixes[i:i + 1] = self.prefixes[i] - del_prefix
self.prefixes[i : i + 1] = self.prefixes[i] - del_prefix
break
self.optimize()
@ -1279,13 +1274,13 @@ def _parseAddressIPv6(ipstr):
fill_pos = len(items)
index += 2
continue
pos = text.find(':')
pos = text.find(":")
if pos == 0:
# Invalid IPv6, eg. '1::2:'
raise ValueError("%r: Invalid IPv6 address" % ipstr)
if pos != -1:
items.append(text[:pos])
if text[pos:pos + 2] == "::":
if text[pos : pos + 2] == "::":
index += pos
else:
index += pos + 1
@ -1297,13 +1292,13 @@ def _parseAddressIPv6(ipstr):
items.append(text)
break
if items and '.' in items[-1]:
if items and "." in items[-1]:
# IPv6 ending with IPv4 like '::ffff:192.168.0.1'
if (fill_pos is not None) and not (fill_pos <= len(items) - 1):
# Invalid IPv6: 'ffff:192.168.0.1::'
raise ValueError("%r: Invalid IPv6 address: '::' after IPv4" % ipstr)
value = parseAddress(items[-1])[0]
items = items[:-1] + ["%04x" % (value >> 16), "%04x" % (value & 0xffff)]
items = items[:-1] + ["%04x" % (value >> 16), "%04x" % (value & 0xFFFF)]
# Expand fill_pos to fill with '0'
# ['1','2'] with fill_pos=1 => ['1', '0', '0', '0', '0', '0', '0', '2']
@ -1311,7 +1306,7 @@ def _parseAddressIPv6(ipstr):
diff = 8 - len(items)
if diff <= 0:
raise ValueError("%r: Invalid IPv6 address: '::' is not needed" % ipstr)
items = items[:fill_pos] + ['0'] * diff + items[fill_pos:]
items = items[:fill_pos] + ["0"] * diff + items[fill_pos:]
# Here we have a list of 8 strings
if len(items) != 8:
@ -1324,7 +1319,7 @@ def _parseAddressIPv6(ipstr):
for item in items:
try:
item = int(item, 16)
error = not (0 <= item <= 0xffff)
error = not (0 <= item <= 0xFFFF)
except ValueError:
error = True
if error:
@ -1388,7 +1383,7 @@ def parseAddress(ipstr, ipversion=0):
except ValueError:
intval = None
if ipstr.startswith('0x') and hexval is not None:
if ipstr.startswith("0x") and hexval is not None:
if hexval > MAX_IPV6_ADDRESS:
raise ValueError("IP Address can't be larger than %x: %x" % (MAX_IPV6_ADDRESS, hexval))
if hexval <= MAX_IPV4_ADDRESS:
@ -1396,19 +1391,19 @@ def parseAddress(ipstr, ipversion=0):
else:
return (hexval, 6)
if ipstr.find(':') != -1:
if ipstr.find(":") != -1:
return (_parseAddressIPv6(ipstr), 6)
elif len(ipstr) == 32 and hexval is not None:
# assume IPv6 in pure hexadecimal notation
return (hexval, 6)
elif ipstr.find('.') != -1 or (intval is not None and intval < 256 and ipversion != 6):
elif ipstr.find(".") != -1 or (intval is not None and intval < 256 and ipversion != 6):
# assume IPv4 ('127' gets interpreted as '127.0.0.0')
bytes = ipstr.split('.')
bytes = ipstr.split(".")
if len(bytes) > 4:
raise ValueError("IPv4 Address with more than 4 bytes")
bytes += ['0'] * (4 - len(bytes))
bytes += ["0"] * (4 - len(bytes))
bytes = [int(x) for x in bytes]
for x in bytes:
if x > 255 or x < 0:
@ -1438,12 +1433,12 @@ def intToIp(ip, version):
if ip < 0:
raise ValueError("IPs can't be negative: %d" % (ip))
ret = ''
ret = ""
if version == 4:
if ip > MAX_IPV4_ADDRESS:
raise ValueError("IPv4 Address can't be larger than %x: %x" % (MAX_IPV4_ADDRESS, ip))
for l in xrange(4):
ret = str(ip & 0xff) + '.' + ret
ret = str(ip & 0xFF) + "." + ret
ip = ip >> 8
ret = ret[:-1]
elif version == 6:
@ -1453,7 +1448,7 @@ def intToIp(ip, version):
for x in xrange(1, 33):
ret = l[-x] + ret
if x % 4 == 0:
ret = ':' + ret
ret = ":" + ret
ret = ret[1:]
else:
raise ValueError("only IPv4 and IPv6 supported")
@ -1494,10 +1489,24 @@ def _countFollowingZeros(l):
return 1 + _countFollowingZeros(l[1:])
_BitTable = {'0': '0000', '1': '0001', '2': '0010', '3': '0011',
'4': '0100', '5': '0101', '6': '0110', '7': '0111',
'8': '1000', '9': '1001', 'a': '1010', 'b': '1011',
'c': '1100', 'd': '1101', 'e': '1110', 'f': '1111'}
_BitTable = {
"0": "0000",
"1": "0001",
"2": "0010",
"3": "0011",
"4": "0100",
"5": "0101",
"6": "0110",
"7": "0111",
"8": "1000",
"9": "1001",
"a": "1010",
"b": "1011",
"c": "1100",
"d": "1101",
"e": "1110",
"f": "1111",
}
def _intToBin(val):
@ -1506,11 +1515,11 @@ def _intToBin(val):
if val < 0:
raise ValueError("Only positive values allowed")
s = "%x" % val
ret = ''
ret = ""
for x in s:
ret += _BitTable[x]
# remove leading zeros
while ret[0] == '0' and len(ret) > 1:
while ret[0] == "0" and len(ret) > 1:
ret = ret[1:]
return ret
@ -1595,7 +1604,7 @@ def _checkNetmask(netmask, masklen):
def _checkNetaddrWorksWithPrefixlen(net, prefixlen, version):
"""Check if a base addess of a network is compatible with a prefixlen"""
try:
return (net & _prefixlenToNetmask(prefixlen, version) == net)
return net & _prefixlenToNetmask(prefixlen, version) == net
except ValueError:
return False
@ -1637,8 +1646,8 @@ def _remove_subprefix(prefix, subprefix):
# Start cutting in half, recursively
prefixes = [
IP('%s/%d' % (prefix[0], prefix._prefixlen + 1)),
IP('%s/%d' % (prefix[int(prefix.len() / 2)], prefix._prefixlen + 1)),
IP("%s/%d" % (prefix[0], prefix._prefixlen + 1)),
IP("%s/%d" % (prefix[int(prefix.len() / 2)], prefix._prefixlen + 1)),
]
if subprefix in prefixes[0]:
return _remove_subprefix(prefixes[0], subprefix) + IPSet([prefixes[1]])

View file

@ -1,11 +1,12 @@
import libvirt
import threading
import socket
import re
from vrtManager import util
from vrtManager.rwlock import ReadWriteLock
import socket
import threading
import libvirt
from django.conf import settings
from libvirt import libvirtError
from vrtManager import util
from vrtManager.rwlock import ReadWriteLock
CONN_SOCKET = 4
CONN_TLS = 3
@ -18,6 +19,7 @@ TCP_PORT = 16509
class wvmEventLoop(threading.Thread):
""" Event Loop Class"""
def __init__(self, group=None, target=None, name=None, args=(), kwargs={}):
# register the default event implementation
# of libvirt, as we do not have an existing
@ -25,7 +27,7 @@ class wvmEventLoop(threading.Thread):
libvirt.virEventRegisterDefaultImpl()
if name is None:
name = 'libvirt event loop'
name = "libvirt event loop"
super(wvmEventLoop, self).__init__(group, target, name, args, kwargs)
@ -46,6 +48,7 @@ class wvmConnection(object):
class representing a single connection stored in the Connection Manager
# to-do: may also need some locking to ensure to not connect simultaniously in 2 threads
"""
def __init__(self, host, login, passwd, conn):
"""
Sets all class attributes and tries to open the connection
@ -86,10 +89,12 @@ class wvmConnection(object):
# * set keep alive interval
# * set connection close/fail handler
try:
self.connection.setKeepAlive(connection_manager.keepalive_interval, connection_manager.keepalive_count)
self.connection.setKeepAlive(
connection_manager.keepalive_interval, connection_manager.keepalive_count
)
try:
self.connection.registerCloseCallback(self.__connection_close_callback, None)
except:
except Exception:
# Temporary fix for libvirt > libvirt-0.10.2-41
pass
except libvirtError as e:
@ -134,49 +139,49 @@ class wvmConnection(object):
def __connect_tcp(self):
flags = [libvirt.VIR_CRED_AUTHNAME, libvirt.VIR_CRED_PASSPHRASE]
auth = [flags, self.__libvirt_auth_credentials_callback, None]
uri = f'qemu+tcp://{self.host}/system'
uri = f"qemu+tcp://{self.host}/system"
try:
self.connection = libvirt.openAuth(uri, auth, 0)
self.last_error = None
except libvirtError as e:
self.last_error = f'Connection Failed: {str(e)}'
self.last_error = f"Connection Failed: {str(e)}"
self.connection = None
def __connect_ssh(self):
uri = 'qemu+ssh://%s@%s/system' % (self.login, self.host)
uri = "qemu+ssh://%s@%s/system" % (self.login, self.host)
try:
self.connection = libvirt.open(uri)
self.last_error = None
except libvirtError as e:
self.last_error = f'Connection Failed: {str(e)} --- ' + repr(libvirt.virGetLastError())
self.last_error = f"Connection Failed: {str(e)} --- " + repr(libvirt.virGetLastError())
self.connection = None
def __connect_tls(self):
flags = [libvirt.VIR_CRED_AUTHNAME, libvirt.VIR_CRED_PASSPHRASE]
auth = [flags, self.__libvirt_auth_credentials_callback, None]
uri = 'qemu+tls://%s@%s/system' % (self.login, self.host)
uri = "qemu+tls://%s@%s/system" % (self.login, self.host)
try:
self.connection = libvirt.openAuth(uri, auth, 0)
self.last_error = None
except libvirtError as e:
self.last_error = f'Connection Failed: {str(e)}'
self.last_error = f"Connection Failed: {str(e)}"
self.connection = None
def __connect_socket(self):
uri = 'qemu:///system'
uri = "qemu:///system"
try:
self.connection = libvirt.open(uri)
self.last_error = None
except libvirtError as e:
self.last_error = f'Connection Failed: {str(e)}'
self.last_error = f"Connection Failed: {str(e)}"
self.connection = None
def close(self):
@ -202,23 +207,23 @@ class wvmConnection(object):
# unregister callback (as it is no longer valid if this instance gets deleted)
try:
self.connection.unregisterCloseCallback()
except:
except Exception:
pass
def __str__(self):
if self.type == CONN_TCP:
type_str = 'tcp'
type_str = "tcp"
elif self.type == CONN_SSH:
type_str = 'ssh'
type_str = "ssh"
elif self.type == CONN_TLS:
type_str = 'tls'
type_str = "tls"
else:
type_str = 'invalid_type'
type_str = "invalid_type"
return f'qemu+{type_str}://{self.login}@{self.host}/system'
return f"qemu+{type_str}://{self.login}@{self.host}/system"
def __repr__(self):
return f'<wvmConnection {str(self)}>'
return f"<wvmConnection {str(self)}>"
class wvmConnectionManager(object):
@ -307,7 +312,7 @@ class wvmConnectionManager(object):
socket_host = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket_host.settimeout(1)
if conn_type == CONN_SSH:
if ':' in hostname:
if ":" in hostname:
libvirt_host, PORT = hostname.split(":")
PORT = int(PORT)
else:
@ -320,7 +325,7 @@ class wvmConnectionManager(object):
socket_host.connect((hostname, TLS_PORT))
if conn_type == CONN_SOCKET:
socket_host = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
socket_host.connect('/var/run/libvirt/libvirt-sock')
socket_host.connect("/var/run/libvirt/libvirt-sock")
socket_host.close()
return True
except Exception as err:
@ -328,8 +333,8 @@ class wvmConnectionManager(object):
connection_manager = wvmConnectionManager(
settings.LIBVIRT_KEEPALIVE_INTERVAL if hasattr(settings, 'LIBVIRT_KEEPALIVE_INTERVAL') else 5,
settings.LIBVIRT_KEEPALIVE_COUNT if hasattr(settings, 'LIBVIRT_KEEPALIVE_COUNT') else 5,
settings.LIBVIRT_KEEPALIVE_INTERVAL if hasattr(settings, "LIBVIRT_KEEPALIVE_INTERVAL") else 5,
settings.LIBVIRT_KEEPALIVE_COUNT if hasattr(settings, "LIBVIRT_KEEPALIVE_COUNT") else 5,
)
@ -353,15 +358,16 @@ class wvmConnect(object):
def get_dom_cap_xml(self, arch, machine):
""" Return domain capabilities xml"""
emulatorbin = self.get_emulator(arch)
virttype = 'kvm' if 'kvm' in self.get_hypervisors_domain_types()[arch] else 'qemu'
virttype = "kvm" if "kvm" in self.get_hypervisors_domain_types()[arch] else "qemu"
machine_types = self.get_machine_types(arch)
if not machine or machine not in machine_types:
machine = 'pc' if 'pc' in machine_types else machine_types[0]
machine = "pc" if "pc" in machine_types else machine_types[0]
return self.wvm.getDomainCapabilities(emulatorbin, arch, machine, virttype)
def get_capabilities(self, arch):
""" Host Capabilities for specified architecture """
def guests(ctx):
result = dict()
for arch_el in ctx.xpath("/capabilities/guest/arch[@name='{}']".format(arch)):
@ -371,11 +377,9 @@ class wvmConnect(object):
result["machines"] = []
for m in arch_el.xpath("machine"):
result["machines"].append({
"machine": m.text,
"max_cpu": m.get("maxCpus"),
"canonical": m.get("canonical")
})
result["machines"].append(
{"machine": m.text, "max_cpu": m.get("maxCpus"), "canonical": m.get("canonical")}
)
guest_el = arch_el.getparent()
for f in guest_el.xpath("features"):
@ -400,7 +404,7 @@ class wvmConnect(object):
result["os_support"] = util.get_xml_path(xml, "/domainCapabilities/os/@supported")
result["loader_support"] = util.get_xml_path(xml, "/domainCapabilities/os/loader/@supported")
if result["loader_support"] == 'yes':
if result["loader_support"] == "yes":
result["loaders"] = self.get_os_loaders(arch, machine)
result["loader_enums"] = self.get_os_loader_enums(arch, machine)
@ -410,27 +414,29 @@ class wvmConnect(object):
result["cpu_custom_models"] = self.get_cpu_custom_types(arch, machine)
result["disk_support"] = util.get_xml_path(xml, "/domainCapabilities/devices/disk/@supported")
if result["disk_support"] == 'yes':
if result["disk_support"] == "yes":
result["disk_devices"] = self.get_disk_device_types(arch, machine)
result["disk_bus"] = self.get_disk_bus_types(arch, machine)
result["graphics_support"] = util.get_xml_path(xml, "/domainCapabilities/devices/graphics/@supported")
if result["graphics_support"] == 'yes':
if result["graphics_support"] == "yes":
result["graphics_types"] = self.get_graphics_types(arch, machine)
result["video_support"] = util.get_xml_path(xml, "/domainCapabilities/devices/video/@supported")
if result["video_support"] == 'yes':
if result["video_support"] == "yes":
result["video_types"] = self.get_video_models(arch, machine)
result["hostdev_support"] = util.get_xml_path(xml, "/domainCapabilities/devices/hostdev/@supported")
if result["hostdev_support"] == 'yes':
if result["hostdev_support"] == "yes":
result["hostdev_types"] = self.get_hostdev_modes(arch, machine)
result["hostdev_startup_policies"] = self.get_hostdev_startup_policies(arch, machine)
result["hostdev_subsys_types"] = self.get_hostdev_subsys_types(arch, machine)
result["features_gic_support"] = util.get_xml_path(xml, "/domainCapabilities/features/gic/@supported")
result["features_genid_support"] = util.get_xml_path(xml, "/domainCapabilities/features/genid/@supported")
result["features_vmcoreinfo_support"] = util.get_xml_path(xml, "/domainCapabilities/features/vmcoreinfo/@supported")
result["features_vmcoreinfo_support"] = util.get_xml_path(
xml, "/domainCapabilities/features/vmcoreinfo/@supported"
)
result["features_sev_support"] = util.get_xml_path(xml, "/domainCapabilities/features/sev/@supported")
return result
@ -510,12 +516,12 @@ class wvmConnect(object):
:return: Get cache available modes
"""
return {
'default': 'Default',
'none': 'Disabled',
'writethrough': 'Write through',
'writeback': 'Write back',
'directsync': 'Direct sync', # since libvirt 0.9.5
'unsafe': 'Unsafe', # since libvirt 0.9.7
"default": "Default",
"none": "Disabled",
"writethrough": "Write through",
"writeback": "Write back",
"directsync": "Direct sync", # since libvirt 0.9.5
"unsafe": "Unsafe", # since libvirt 0.9.7
}
def get_io_modes(self):
@ -523,9 +529,9 @@ class wvmConnect(object):
:return: available io modes
"""
return {
'default': 'Default',
'native': 'Native',
'threads': 'Threads',
"default": "Default",
"native": "Native",
"threads": "Threads",
}
def get_discard_modes(self):
@ -533,9 +539,9 @@ class wvmConnect(object):
:return: available discard modes
"""
return {
'default': 'Default',
'ignore': 'Ignore',
'unmap': 'Unmap',
"default": "Default",
"ignore": "Ignore",
"unmap": "Unmap",
}
def get_detect_zeroes_modes(self):
@ -543,21 +549,22 @@ class wvmConnect(object):
:return: available detect zeroes modes
"""
return {
'default': 'Default',
'on': 'On',
'off': 'Off',
'unmap': 'Unmap',
"default": "Default",
"on": "On",
"off": "Off",
"unmap": "Unmap",
}
def get_hypervisors_domain_types(self):
"""
:return: hypervisor domain types
"""
def hypervisors(ctx):
result = {}
for arch in ctx.xpath('/capabilities/guest/arch'):
domain_types = arch.xpath('domain/@type')
arch_name = arch.xpath('@name')[0]
for arch in ctx.xpath("/capabilities/guest/arch"):
domain_types = arch.xpath("domain/@type")
arch_name = arch.xpath("@name")[0]
result[arch_name] = domain_types
return result
@ -567,9 +574,10 @@ class wvmConnect(object):
"""
:return: hypervisor and its machine types
"""
def machines(ctx):
result = dict()
for arche in ctx.xpath('/capabilities/guest/arch'):
for arche in ctx.xpath("/capabilities/guest/arch"):
arch = arche.get("name")
result[arch] = self.get_machine_types(arch)
@ -587,6 +595,7 @@ class wvmConnect(object):
"""
:return: canonical(if exist) name of machine types
"""
def machines(ctx):
result = list()
canonical_name = ctx.xpath("/capabilities/guest/arch[@name='{}']/machine[@canonical]".format(arch))
@ -602,22 +611,24 @@ class wvmConnect(object):
"""
:return: host emulators list
"""
def emulators(ctx):
result = {}
for arch in ctx.xpath('/capabilities/guest/arch'):
emulator = arch.xpath('emulator')
arch_name = arch.xpath('@name')[0]
for arch in ctx.xpath("/capabilities/guest/arch"):
emulator = arch.xpath("emulator")
arch_name = arch.xpath("@name")[0]
result[arch_name] = emulator
return result
return util.get_xml_path(self.get_cap_xml(), func=emulators)
def get_os_loaders(self, arch='x86_64', machine='pc'):
def get_os_loaders(self, arch="x86_64", machine="pc"):
"""
:param arch: architecture
:param machine:
:return: available os loaders list
"""
def get_os_loaders(ctx):
return [v.text for v in ctx.xpath("/domainCapabilities/os/loader[@supported='yes']/value")]
@ -629,6 +640,7 @@ class wvmConnect(object):
:param machine:
:return: available os loaders list
"""
def get_os_loader_enums(ctx):
result = dict()
enums = [v for v in ctx.xpath("/domainCapabilities/os/loader[@supported='yes']/enum/@name")]
@ -645,6 +657,7 @@ class wvmConnect(object):
:param arch:
:return: available disk bus types list
"""
def get_bus_list(ctx):
return [v.text for v in ctx.xpath("/domainCapabilities/devices/disk/enum[@name='bus']/value")]
@ -657,6 +670,7 @@ class wvmConnect(object):
:param machine:
:return: available disk device type list
"""
def get_device_list(ctx):
return [v.text for v in ctx.xpath("/domainCapabilities/devices/disk/enum[@name='diskDevice']/value")]
@ -669,6 +683,7 @@ class wvmConnect(object):
:param machine:
:return: available graphics types
"""
def get_graphics_list(ctx):
return [v.text for v in ctx.xpath("/domainCapabilities/devices/graphics/enum[@name='type']/value")]
@ -680,6 +695,7 @@ class wvmConnect(object):
:param machine:
:return: available cpu modes
"""
def get_cpu_modes(ctx):
return [v for v in ctx.xpath("/domainCapabilities/cpu/mode[@supported='yes']/@name")]
@ -691,6 +707,7 @@ class wvmConnect(object):
:param machine:
:return: available graphics types
"""
def get_custom_list(ctx):
usable_yes = "/domainCapabilities/cpu/mode[@name='custom'][@supported='yes']/model[@usable='yes']"
usable_unknown = "/domainCapabilities/cpu/mode[@name='custom'][@supported='yes']/model[@usable='unknown']"
@ -706,6 +723,7 @@ class wvmConnect(object):
:param machine:
:return. available nodedev modes
"""
def get_hostdev_list(ctx):
return [v.text for v in ctx.xpath("/domainCapabilities/devices/hostdev/enum[@name='mode']/value")]
@ -717,6 +735,7 @@ class wvmConnect(object):
:param machine:
:return: available hostdev modes
"""
def get_hostdev_list(ctx):
return [v.text for v in ctx.xpath("/domainCapabilities/devices/hostdev/enum[@name='startupPolicy']/value")]
@ -728,6 +747,7 @@ class wvmConnect(object):
:param machine:
:return: available nodedev sub system types
"""
def get_hostdev_list(ctx):
return [v.text for v in ctx.xpath("/domainCapabilities/devices/hostdev/enum[@name='subsysType']/value")]
@ -737,19 +757,19 @@ class wvmConnect(object):
"""
:return: network card models
"""
return ['default', 'e1000', 'virtio']
return ["default", "e1000", "virtio"]
def get_image_formats(self):
"""
:return: available image formats
"""
return ['raw', 'qcow', 'qcow2']
return ["raw", "qcow", "qcow2"]
def get_file_extensions(self):
"""
:return: available image filename extensions
"""
return ['img', 'qcow', 'qcow2']
return ["img", "qcow", "qcow2"]
def get_video_models(self, arch, machine):
"""
@ -757,9 +777,10 @@ class wvmConnect(object):
:param machine:
:return: available graphics video types
"""
def get_video_list(ctx):
result = []
for video_enum in ctx.xpath('/domainCapabilities/devices/video/enum'):
for video_enum in ctx.xpath("/domainCapabilities/devices/video/enum"):
if video_enum.xpath("@name")[0] == "modelType":
for values in video_enum:
result.append(values.text)
@ -787,8 +808,8 @@ class wvmConnect(object):
def get_network_forward(self, net_name):
def get_forward(doc):
forward_mode = util.get_xpath(doc, '/network/forward/@mode')
return forward_mode or 'isolated'
forward_mode = util.get_xpath(doc, "/network/forward/@mode")
return forward_mode or "isolated"
net = self.get_network(net_name)
xml = net.XMLDesc(0)
@ -825,14 +846,14 @@ class wvmConnect(object):
netdevice = []
def get_info(doc):
dev_type = util.get_xpath(doc, '/device/capability/@type')
interface = util.get_xpath(doc, '/device/capability/interface')
dev_type = util.get_xpath(doc, "/device/capability/@type")
interface = util.get_xpath(doc, "/device/capability/interface")
return dev_type, interface
for dev in self.wvm.listAllDevices(0):
xml = dev.XMLDesc(0)
(dev_type, interface) = util.get_xml_path(xml, func=get_info)
if dev_type == 'net':
if dev_type == "net":
netdevice.append(interface)
return netdevice
@ -850,9 +871,9 @@ class wvmConnect(object):
else:
vcpu = util.get_xpath(doc, "/domain/vcpu")
title = util.get_xpath(doc, "/domain/title")
title = title if title else ''
title = title if title else ""
description = util.get_xpath(doc, "/domain/description")
description = description if description else ''
description = description if description else ""
return mem, vcpu, title, description
for name in self.get_instances():
@ -860,12 +881,12 @@ class wvmConnect(object):
xml = dom.XMLDesc(0)
(mem, vcpu, title, description) = util.get_xml_path(xml, func=get_info)
vname[dom.name()] = {
'status': dom.info()[0],
'uuid': dom.UUIDString(),
'vcpu': vcpu,
'memory': mem,
'title': title,
'description': description,
"status": dom.info()[0],
"uuid": dom.UUIDString(),
"vcpu": vcpu,
"memory": mem,
"title": title,
"description": description,
}
return vname
@ -882,20 +903,20 @@ class wvmConnect(object):
else:
vcpu = util.get_xpath(ctx, "/domain/vcpu")
title = util.get_xpath(ctx, "/domain/title")
title = title if title else ''
title = title if title else ""
description = util.get_xpath(ctx, "/domain/description")
description = description if description else ''
description = description if description else ""
return mem, vcpu, title, description
(mem, vcpu, title, description) = util.get_xml_path(xml, func=get_info)
return {
'name': dom.name(),
'status': dom.info()[0],
'uuid': dom.UUIDString(),
'vcpu': vcpu,
'memory': mem,
'title': title,
'description': description,
"name": dom.name(),
"status": dom.info()[0],
"uuid": dom.UUIDString(),
"vcpu": vcpu,
"memory": mem,
"title": title,
"description": description,
}
def close(self):
@ -931,7 +952,7 @@ class wvmConnect(object):
for arch, patterns in util.UEFI_ARCH_PATTERNS.items():
for pattern in patterns:
if re.match(pattern, path):
return ("UEFI %(arch)s: %(path)s" % {"arch": arch, "path": path})
return "UEFI %(arch)s: %(path)s" % {"arch": arch, "path": path}
return "Custom: %(path)s" % {"path": path}
@ -945,15 +966,17 @@ class wvmConnect(object):
"""
Return True if libvirt advertises support for proper UEFI setup
"""
return ("readonly" in loader_enums and "yes" in loader_enums.get("readonly"))
return "readonly" in loader_enums and "yes" in loader_enums.get("readonly")
def is_supports_virtio(self, arch, machine):
if not self.is_qemu():
return False
# These _only_ support virtio so don't check the OS
if arch in ["aarch64", "armv7l", "ppc64", "ppc64le", "s390x", "riscv64", "riscv32"] and \
machine in ["virt", "pseries"]:
if arch in ["aarch64", "armv7l", "ppc64", "ppc64le", "s390x", "riscv64", "riscv32"] and machine in [
"virt",
"pseries",
]:
return True
if arch in ["x86_64", "i686"]:

View file

@ -1,4 +1,5 @@
import string
from vrtManager import util
from vrtManager.connection import wvmConnect
@ -12,15 +13,15 @@ def get_rbd_storage_data(stg):
for host in doc.xpath("/pool/source/host"):
name = host.prop("name")
if name:
hosts.append({'name': name, 'port': host.prop("port")})
hosts.append({"name": name, "port": host.prop("port")})
return hosts
ceph_hosts = util.get_xml_path(xml, func=get_ceph_hosts)
secret_uuid = util.get_xml_path(xml, "/pool/source/auth/secret/@uuid")
return ceph_user, secret_uuid, ceph_hosts
class wvmCreate(wvmConnect):
def get_storages_images(self):
"""
Function return all images on all storages
@ -31,10 +32,10 @@ class wvmCreate(wvmConnect):
stg = self.get_storage(storage)
try:
stg.refresh(0)
except:
except Exception:
pass
for img in stg.listVolumes():
if img.lower().endswith('.iso'):
if img.lower().endswith(".iso"):
pass
else:
images.append(img)
@ -52,11 +53,11 @@ class wvmCreate(wvmConnect):
size = int(size) * 1073741824
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
if storage_type == "dir":
if image_format in ("qcow", "qcow2"):
name += "." + image_format
else:
name += '.img'
name += ".img"
alloc = 0
else:
alloc = size
@ -91,12 +92,12 @@ class wvmCreate(wvmConnect):
def get_volume_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 == "unknown" or vol_type == "iso":
return "raw"
if vol_type:
return vol_type
else:
return 'raw'
return "raw"
def get_volume_path(self, volume, pool=None):
if not pool:
@ -125,8 +126,8 @@ class wvmCreate(wvmConnect):
storage_type = util.get_xml_path(stg.XMLDesc(0), "/pool/@type")
format = util.get_xml_path(vol.XMLDesc(0), "/volume/target/format/@type")
if storage_type == 'dir':
clone += '.img'
if storage_type == "dir":
clone += ".img"
else:
metadata = False
xml = f"""
@ -159,9 +160,27 @@ class wvmCreate(wvmConnect):
vol = self.get_volume_by_path(path)
vol.delete()
def create_instance(self, name, memory, vcpu, vcpu_mode, uuid, arch, machine, firmware, volumes,
networks, nwfilter, graphics, virtio, listen_addr,
video="vga", console_pass="random", mac=None, qemu_ga=True):
def create_instance(
self,
name,
memory,
vcpu,
vcpu_mode,
uuid,
arch,
machine,
firmware,
volumes,
networks,
nwfilter,
graphics,
virtio,
listen_addr,
video="vga",
console_pass="random",
mac=None,
qemu_ga=True,
):
"""
Create VM function
"""
@ -178,33 +197,37 @@ class wvmCreate(wvmConnect):
<memory unit='KiB'>{memory}</memory>
<vcpu>{vcpu}</vcpu>"""
if dom_caps["os_support"] == 'yes':
if dom_caps["os_support"] == "yes":
xml += f"""<os>
<type arch='{arch}' machine='{machine}'>{caps["os_type"]}</type>"""
xml += """ <boot dev='hd'/>
<boot dev='cdrom'/>
<bootmenu enable='yes'/>"""
if firmware:
if firmware["secure"] == 'yes':
xml += """<loader readonly='%s' type='%s' secure='%s'>%s</loader>""" % (firmware["readonly"],
firmware["type"],
firmware["secure"],
firmware["loader"])
if firmware["secure"] == 'no':
xml += """<loader readonly='%s' type='%s'>%s</loader>""" % (firmware["readonly"],
firmware["type"],
firmware["loader"])
if firmware["secure"] == "yes":
xml += """<loader readonly='%s' type='%s' secure='%s'>%s</loader>""" % (
firmware["readonly"],
firmware["type"],
firmware["secure"],
firmware["loader"],
)
if firmware["secure"] == "no":
xml += """<loader readonly='%s' type='%s'>%s</loader>""" % (
firmware["readonly"],
firmware["type"],
firmware["loader"],
)
xml += """</os>"""
if caps["features"]:
xml += """<features>"""
if 'acpi' in caps["features"]:
if "acpi" in caps["features"]:
xml += """<acpi/>"""
if 'apic' in caps["features"]:
if "apic" in caps["features"]:
xml += """<apic/>"""
if 'pae' in caps["features"]:
if "pae" in caps["features"]:
xml += """<pae/>"""
if firmware.get("secure", 'no') == 'yes':
if firmware.get("secure", "no") == "yes":
xml += """<smm state="on"/>"""
xml += """</features>"""
@ -235,56 +258,69 @@ class wvmCreate(wvmConnect):
for volume in volumes:
disk_opts = ''
if volume['cache_mode'] is not None and volume['cache_mode'] != 'default':
disk_opts = ""
if volume["cache_mode"] is not None and volume["cache_mode"] != "default":
disk_opts += f"cache='{volume['cache_mode']}' "
if volume['io_mode'] is not None and volume['io_mode'] != 'default':
if volume["io_mode"] is not None and volume["io_mode"] != "default":
disk_opts += f"io='{volume['io_mode']}' "
if volume['discard_mode'] is not None and volume['discard_mode'] != 'default':
if volume["discard_mode"] is not None and volume["discard_mode"] != "default":
disk_opts += f"discard='{volume['discard_mode']}' "
if volume['detect_zeroes_mode'] is not None and volume['detect_zeroes_mode'] != 'default':
if volume["detect_zeroes_mode"] is not None and volume["detect_zeroes_mode"] != "default":
disk_opts += f"detect_zeroes='{volume['detect_zeroes_mode']}' "
stg = self.get_storage_by_vol_path(volume['path'])
stg = self.get_storage_by_vol_path(volume["path"])
stg_type = util.get_xml_path(stg.XMLDesc(0), "/pool/@type")
if volume['device'] == 'cdrom': add_cd = False
if volume["device"] == "cdrom":
add_cd = False
if stg_type == 'rbd':
if stg_type == "rbd":
ceph_user, secret_uuid, ceph_hosts = get_rbd_storage_data(stg)
xml += """<disk type='network' device='disk'>
<driver name='qemu' type='%s' %s />""" % (volume['type'], disk_opts)
<driver name='qemu' type='%s' %s />""" % (
volume["type"],
disk_opts,
)
xml += """ <auth username='%s'>
<secret type='ceph' uuid='%s'/>
</auth>
<source protocol='rbd' name='%s'>""" % (ceph_user, secret_uuid, volume['path'])
<source protocol='rbd' name='%s'>""" % (
ceph_user,
secret_uuid,
volume["path"],
)
if isinstance(ceph_hosts, list):
for host in ceph_hosts:
if host.get('port'):
if host.get("port"):
xml += """
<host name='%s' port='%s'/>""" % (host.get('name'), host.get('port'))
<host name='%s' port='%s'/>""" % (
host.get("name"),
host.get("port"),
)
else:
xml += """
<host name='%s'/>""" % host.get('name')
<host name='%s'/>""" % host.get(
"name"
)
xml += """</source>"""
else:
xml += """<disk type='file' device='%s'>""" % volume['device']
xml += """ <driver name='qemu' type='%s' %s/>""" % (volume['type'], disk_opts)
xml += f""" <source file='%s'/>""" % volume['path']
xml += """<disk type='file' device='%s'>""" % volume["device"]
xml += """ <driver name='qemu' type='%s' %s/>""" % (volume["type"], disk_opts)
xml += """ <source file='%s'/>""" % volume["path"]
if volume.get('bus') == 'virtio':
xml += """<target dev='vd%s' bus='%s'/>""" % (vd_disk_letters.pop(0), volume.get('bus'))
elif volume.get('bus') == 'ide':
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':
xml += """<target dev='sd%s' bus='%s'/>""" % (sd_disk_letters.pop(0), volume.get('bus'))
if volume.get("bus") == "virtio":
xml += """<target dev='vd%s' bus='%s'/>""" % (vd_disk_letters.pop(0), volume.get("bus"))
elif volume.get("bus") == "ide":
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":
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)
xml += """</disk>"""
if volume.get('bus') == 'scsi':
if volume.get("bus") == "scsi":
xml += f"""<controller type='scsi' model='{volume.get('scsi_model')}'/>"""
if add_cd:
@ -292,17 +328,17 @@ class wvmCreate(wvmConnect):
<driver name='qemu' type='raw'/>
<source file = '' />
<readonly/>"""
if 'ide' in dom_caps['disk_bus']:
xml += """<target dev='hd%s' bus='%s'/>""" % (hd_disk_letters.pop(0), 'ide')
elif 'sata' in dom_caps['disk_bus']:
xml += """<target dev='sd%s' bus='%s'/>""" % (sd_disk_letters.pop(0), 'sata')
elif 'scsi' in dom_caps['disk_bus']:
xml += """<target dev='sd%s' bus='%s'/>""" % (sd_disk_letters.pop(0), 'scsi')
if "ide" in dom_caps["disk_bus"]:
xml += """<target dev='hd%s' bus='%s'/>""" % (hd_disk_letters.pop(0), "ide")
elif "sata" in dom_caps["disk_bus"]:
xml += """<target dev='sd%s' bus='%s'/>""" % (sd_disk_letters.pop(0), "sata")
elif "scsi" in dom_caps["disk_bus"]:
xml += """<target dev='sd%s' bus='%s'/>""" % (sd_disk_letters.pop(0), "scsi")
else:
xml += """<target dev='vd%s' bus='%s'/>""" % (vd_disk_letters.pop(0), 'virtio')
xml += """<target dev='vd%s' bus='%s'/>""" % (vd_disk_letters.pop(0), "virtio")
xml += """</disk>"""
for net in networks.split(','):
for net in networks.split(","):
xml += """<interface type='network'>"""
if mac:
xml += f"""<mac address='{mac}'/>"""
@ -319,10 +355,10 @@ class wvmCreate(wvmConnect):
if not 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')
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")
else:
xml += """<input type='mouse'/>"""
xml += """<input type='keyboard'/>"""

View file

@ -1,14 +1,15 @@
import time
from vrtManager.connection import wvmConnect
from vrtManager.util import get_xml_path
def cpu_version(doc):
for info in doc.xpath('/sysinfo/processor/entry'):
elem = info.xpath('@name')[0]
if elem == 'version':
for info in doc.xpath("/sysinfo/processor/entry"):
elem = info.xpath("@name")[0]
if elem == "version":
return info.text
return 'Unknown'
return "Unknown"
class wvmHostDetails(wvmConnect):
@ -19,14 +20,12 @@ class wvmHostDetails(wvmConnect):
all_mem = self.wvm.getInfo()[1] * 1048576
freemem = self.wvm.getMemoryStats(-1, 0)
if isinstance(freemem, dict):
free = (freemem['buffers'] +
freemem['free'] +
freemem['cached']) * 1024
free = (freemem["buffers"] + freemem["free"] + freemem["cached"]) * 1024
percent = abs(100 - ((free * 100) // all_mem))
usage = (all_mem - free)
mem_usage = {'total': all_mem, 'usage': usage, 'percent': percent}
usage = all_mem - free
mem_usage = {"total": all_mem, "usage": usage, "percent": percent}
else:
mem_usage = {'total': None, 'usage': None, 'percent': None}
mem_usage = {"total": None, "usage": None, "percent": None}
return mem_usage
def get_cpu_usage(self):
@ -38,7 +37,7 @@ class wvmHostDetails(wvmConnect):
cpu = self.wvm.getCPUStats(-1, 0)
if isinstance(cpu, dict):
for num in range(2):
idle = self.wvm.getCPUStats(-1, 0)['idle']
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
@ -51,8 +50,8 @@ class wvmHostDetails(wvmConnect):
if diff_usage < 0:
diff_usage = 0
else:
return {'usage': None}
return {'usage': diff_usage}
return {"usage": None}
return {"usage": diff_usage}
def get_node_info(self):
"""

File diff suppressed because it is too large Load diff

View file

@ -1,8 +1,8 @@
from xml.etree import ElementTree
from libvirt import VIR_INTERFACE_XML_INACTIVE
from vrtManager.connection import wvmConnect
from vrtManager import util
from libvirt import VIR_INTERFACE_XML_INACTIVE
from vrtManager import util
from vrtManager.connection import wvmConnect
class wvmInterfaces(wvmConnect):
@ -12,36 +12,37 @@ class wvmInterfaces(wvmConnect):
mac = iface.MACString()
itype = util.get_xml_path(xml, "/interface/@type")
state = iface.isActive()
return {'name': name, 'type': itype, 'state': state, 'mac': mac}
return {"name": name, "type": itype, "state": state, "mac": mac}
def define_iface(self, xml, flag=0):
self.wvm.interfaceDefineXML(xml, flag)
def create_iface(self, name, itype, mode, netdev, ipv4_type, ipv4_addr, ipv4_gw,
ipv6_type, ipv6_addr, ipv6_gw, stp, delay):
def create_iface(
self, name, itype, mode, netdev, ipv4_type, ipv4_addr, ipv4_gw, ipv6_type, ipv6_addr, ipv6_gw, stp, delay
):
xml = f"""<interface type='{itype}' name='{name}'>
<start mode='{mode}'/>"""
if ipv4_type == 'dhcp':
if ipv4_type == "dhcp":
xml += """<protocol family='ipv4'>
<dhcp/>
</protocol>"""
if ipv4_type == 'static':
address, prefix = ipv4_addr.split('/')
if ipv4_type == "static":
address, prefix = ipv4_addr.split("/")
xml += f"""<protocol family='ipv4'>
<ip address='{address}' prefix='{prefix}'/>
<route gateway='{ipv4_gw}'/>
</protocol>"""
if ipv6_type == 'dhcp':
if ipv6_type == "dhcp":
xml += """<protocol family='ipv6'>
<dhcp/>
</protocol>"""
if ipv6_type == 'static':
address, prefix = ipv6_addr.split('/')
if ipv6_type == "static":
address, prefix = ipv6_addr.split("/")
xml += f"""<protocol family='ipv6'>
<ip address='{address}' prefix='{prefix}'/>
<route gateway='{ipv6_gw}'/>
</protocol>"""
if itype == 'bridge':
if itype == "bridge":
xml += f"""<bridge stp='{stp}' delay='{delay}'>
<interface name='{netdev}' type='ethernet'/>
</bridge>"""
@ -85,9 +86,9 @@ class wvmInterface(wvmConnect):
xml = self._XMLDesc(VIR_INTERFACE_XML_INACTIVE)
ipaddr = util.get_xml_path(xml, "/interface/protocol[@family='ipv4']/ip/@address")
if ipaddr:
return 'static'
return "static"
else:
return 'dhcp'
return "dhcp"
except:
return None
@ -98,16 +99,16 @@ class wvmInterface(wvmConnect):
if not int_ipv4_ip or not int_ipv4_mask:
return None
else:
return int_ipv4_ip + '/' + int_ipv4_mask
return 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'
return "static"
else:
return 'dhcp'
return "dhcp"
except:
return None
@ -118,15 +119,15 @@ class wvmInterface(wvmConnect):
if not int_ipv6_ip or not int_ipv6_mask:
return None
else:
return int_ipv6_ip + '/' + int_ipv6_mask
return int_ipv6_ip + "/" + int_ipv6_mask
def get_bridge(self):
bridge = None
if self.get_type() == 'bridge':
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') is not 'unknown':
bridge = iface.get('name')
if iface.get("state") == "up" and iface.get("speed") != "unknown":
bridge = iface.get("name")
return bridge
return bridge
else:
@ -134,20 +135,20 @@ class wvmInterface(wvmConnect):
def get_bridge_slave_ifaces(self):
ifaces = list()
if self.get_type() == 'bridge':
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')
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')
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})
address = mac.get("address")
ifaces.append({"name": name, "type": if_type, "state": state, "speed": speed, "mac": address})
return ifaces
else:
return None

View file

@ -1,11 +1,15 @@
from libvirt import (
VIR_NETWORK_SECTION_IP_DHCP_HOST,
VIR_NETWORK_UPDATE_AFFECT_CONFIG,
VIR_NETWORK_UPDATE_AFFECT_LIVE,
VIR_NETWORK_UPDATE_COMMAND_ADD_LAST,
VIR_NETWORK_UPDATE_COMMAND_DELETE,
VIR_NETWORK_UPDATE_COMMAND_MODIFY, libvirtError)
from lxml import etree
from libvirt import libvirtError
from libvirt import VIR_NETWORK_SECTION_IP_DHCP_HOST
from libvirt import VIR_NETWORK_UPDATE_COMMAND_ADD_LAST, VIR_NETWORK_UPDATE_COMMAND_DELETE, VIR_NETWORK_UPDATE_COMMAND_MODIFY
from libvirt import VIR_NETWORK_UPDATE_AFFECT_LIVE, VIR_NETWORK_UPDATE_AFFECT_CONFIG
from vrtManager import util
from vrtManager.IPy import IP
from vrtManager.connection import wvmConnect
from vrtManager.IPy import IP
def network_size(subnet, dhcp=None):
"""
@ -17,7 +21,7 @@ def network_size(subnet, dhcp=None):
if addr.version() == 4:
dhcp_pool = [addr[2].strCompressed(), addr[addr.len() - 2].strCompressed()]
if addr.version() == 6:
mask = mask.lstrip('/') if '/' in mask else mask
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
@ -26,7 +30,6 @@ def network_size(subnet, dhcp=None):
class wvmNetworks(wvmConnect):
def get_networks_info(self):
get_networks = self.get_networks()
networks = []
@ -39,44 +42,55 @@ 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):
self.wvm.networkDefineXML(xml)
def create_network(self, name, forward,
ipv4, gateway, mask, dhcp4,
ipv6, gateway6, prefix6, dhcp6,
bridge, openvswitch, fixed=False):
def create_network(
self,
name,
forward,
ipv4,
gateway,
mask,
dhcp4,
ipv6,
gateway6,
prefix6,
dhcp6,
bridge,
openvswitch,
fixed=False,
):
xml = f"""
<network>
<name>{name}</name>"""
if forward in ['nat', 'route', 'bridge']:
if forward in ["nat", "route", "bridge"]:
xml += f"""<forward mode='{forward}'/>"""
if forward == 'macvtap':
if forward == "macvtap":
xml += f"""<forward mode='bridge'>
<interface dev='{bridge}'/>
</forward>"""
else:
xml += """<bridge """
if forward in ['nat', 'route', 'none']:
if forward in ["nat", "route", "none"]:
xml += """stp='on' delay='0'"""
if forward == 'bridge':
if forward == "bridge":
xml += f"""name='{bridge}'"""
xml += """/>"""
if openvswitch is True:
xml += """<virtualport type='openvswitch'/>"""
if forward not in ['bridge', 'macvtap']:
if forward not in ["bridge", "macvtap"]:
if ipv4:
xml += f"""<ip address='{gateway}' netmask='{mask}'>"""
if dhcp4:
xml += f"""<dhcp>
<range start='{dhcp4[0]}' end='{dhcp4[1]}' />"""
if fixed:
fist_oct = int(dhcp4[0].strip().split('.')[3])
last_oct = int(dhcp4[1].strip().split('.')[3])
fist_oct = int(dhcp4[0].strip().split(".")[3])
last_oct = int(dhcp4[1].strip().split(".")[3])
for ip in range(fist_oct, last_oct + 1):
xml += f"""<host mac='{util.randomMAC()}' ip='{gateway[:-2]}.{ip}' />"""
xml += """</dhcp>"""
@ -144,23 +158,23 @@ class wvmNetwork(wvmConnect):
if util.get_xml_path(xml, "/network/ip") is None:
return ip_networks
tree = etree.fromstring(xml)
ips = tree.findall('.ip')
ips = tree.findall(".ip")
for ip in ips:
address_str = ip.get('address')
netmask_str = ip.get('netmask')
prefix = ip.get('prefix')
family = ip.get('family', 'ipv4')
base = 32 if family == 'ipv4' else 128
address_str = ip.get("address")
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"))
binstr = (prefix * "1") + ((base - prefix) * "0")
netmask_str = str(IP(int(binstr, base=2)))
if netmask_str:
netmask = IP(netmask_str)
gateway = IP(address_str)
network = IP(gateway.int() & netmask.int())
netmask_str = netmask_str if family == 'ipv4' else str(prefix)
netmask_str = netmask_str if family == "ipv4" else str(prefix)
ret = IP(str(network) + "/" + netmask_str)
else:
ret = IP(str(address_str))
@ -178,12 +192,12 @@ class wvmNetwork(wvmConnect):
forward_dev = util.get_xml_path(xml, "/network/forward/@dev")
return [fw, forward_dev]
def get_dhcp_range(self, family='ipv4'):
def get_dhcp_range(self, family="ipv4"):
xml = self._XMLDesc(0)
if family == 'ipv4':
if family == "ipv4":
dhcpstart = util.get_xml_path(xml, "/network/ip[not(@family='ipv6')]/dhcp/range[1]/@start")
dhcpend = util.get_xml_path(xml, "/network/ip[not(@family='ipv6')]/dhcp/range[1]/@end")
if family == 'ipv6':
if family == "ipv6":
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")
@ -192,13 +206,13 @@ class wvmNetwork(wvmConnect):
return [IP(dhcpstart), IP(dhcpend)]
def get_dhcp_range_start(self, family='ipv4'):
def get_dhcp_range_start(self, family="ipv4"):
dhcp = self.get_dhcp_range(family)
if not dhcp:
return None
return dhcp[0]
def get_dhcp_range_end(self, family='ipv4'):
def get_dhcp_range_end(self, family="ipv4"):
dhcp = self.get_dhcp_range(family)
if not dhcp:
return None
@ -211,74 +225,77 @@ class wvmNetwork(wvmConnect):
return True
return bool(util.get_xml_path(xml, "/network/ip/dhcp/bootp/@file"))
def get_dhcp_host_addr(self, family='ipv4'):
def get_dhcp_host_addr(self, family="ipv4"):
result = list()
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')
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})
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:
continue
if family == 'ipv6':
if family == "ipv6":
hosts = tree.xpath("./ip[@family='ipv6']/dhcp/host")
for host in hosts:
host_ip = host.get('ip')
host_id = host.get('id')
name = host.get('name', '')
result.append({'ip': host_ip, 'id': host_id, 'name': name})
host_ip = host.get("ip")
host_id = host.get("id")
name = host.get("name", "")
result.append({"ip": host_ip, "id": host_id, "name": name})
return result
def modify_dhcp_range(self, range_start, range_end, family='ipv4'):
def modify_dhcp_range(self, range_start, range_end, family="ipv4"):
if not self.is_active():
tree = etree.fromstring(self._XMLDesc(0))
if family == 'ipv4':
if family == "ipv4":
dhcp_range = tree.xpath("./ip[not(@family='ipv6')]/dhcp/range")
if family == 'ipv6':
if family == "ipv6":
dhcp_range = tree.xpath("./ip[@family='ipv6']/dhcp/range")
dhcp_range[0].set('start', range_start)
dhcp_range[0].set('end', range_end)
dhcp_range[0].set("start", range_start)
dhcp_range[0].set("end", range_end)
self.wvm.networkDefineXML(etree.tostring(tree).decode())
def delete_fixed_address(self, ip, family='ipv4'):
def delete_fixed_address(self, ip, family="ipv4"):
tree = etree.fromstring(self._XMLDesc(0))
if family == 'ipv4':
if family == "ipv4":
hosts = tree.xpath("/network/ip[not(@family='ipv6')]/dhcp/host")
parent_index = self.parent_count - 2
if family == 'ipv6':
if family == "ipv6":
hosts = tree.xpath("/network/ip[@family='ipv6']/dhcp/host")
parent_index = self.parent_count - 1
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)
if family == 'ipv6':
new_xml = '<host id="{}" name="{}" ip="{}"/>'.format(h.get('id'), h.get('name'), ip)
if h.get("ip") == ip:
if family == "ipv4":
new_xml = '<host mac="{}" name="{}" ip="{}"/>'.format(h.get("mac"), h.get("name"), ip)
if family == "ipv6":
new_xml = '<host id="{}" name="{}" ip="{}"/>'.format(h.get("id"), h.get("name"), ip)
self.update(VIR_NETWORK_UPDATE_COMMAND_DELETE, VIR_NETWORK_SECTION_IP_DHCP_HOST,
new_xml,
parent_index,
VIR_NETWORK_UPDATE_AFFECT_LIVE | VIR_NETWORK_UPDATE_AFFECT_CONFIG)
self.update(
VIR_NETWORK_UPDATE_COMMAND_DELETE,
VIR_NETWORK_SECTION_IP_DHCP_HOST,
new_xml,
parent_index,
VIR_NETWORK_UPDATE_AFFECT_LIVE | VIR_NETWORK_UPDATE_AFFECT_CONFIG,
)
break
def modify_fixed_address(self, name, address, mac_duid, family='ipv4'):
def modify_fixed_address(self, name, address, mac_duid, family="ipv4"):
tree = etree.fromstring(self._XMLDesc(0))
if family == 'ipv4':
new_xml = '<host mac="{}" {} ip="{}"/>'.format(mac_duid, 'name="' + name + '"' if name else '', IP(address))
if family == "ipv4":
new_xml = '<host mac="{}" {} ip="{}"/>'.format(mac_duid, 'name="' + name + '"' if name else "", IP(address))
hosts = tree.xpath("./ip[not(@family='ipv6')]/dhcp/host")
compare_var = 'mac'
compare_var = "mac"
parent_index = self.parent_count - 2
if family == 'ipv6':
new_xml = '<host id="{}" {} ip="{}"/>'.format(mac_duid, 'name="' + name + '"' if name else '', IP(address))
if family == "ipv6":
new_xml = '<host id="{}" {} ip="{}"/>'.format(mac_duid, 'name="' + name + '"' if name else "", IP(address))
hosts = tree.xpath("./ip[@family='ipv6']/dhcp/host")
compare_var = 'id'
compare_var = "id"
parent_index = self.parent_count - 1
new_host_xml = etree.fromstring(new_xml)
@ -288,17 +305,25 @@ class wvmNetwork(wvmConnect):
host = h
break
if host is None:
self.update(VIR_NETWORK_UPDATE_COMMAND_ADD_LAST, VIR_NETWORK_SECTION_IP_DHCP_HOST, new_xml,
parent_index,
VIR_NETWORK_UPDATE_AFFECT_LIVE | VIR_NETWORK_UPDATE_AFFECT_CONFIG)
self.update(
VIR_NETWORK_UPDATE_COMMAND_ADD_LAST,
VIR_NETWORK_SECTION_IP_DHCP_HOST,
new_xml,
parent_index,
VIR_NETWORK_UPDATE_AFFECT_LIVE | VIR_NETWORK_UPDATE_AFFECT_CONFIG,
)
else:
# change the host
if host.get('name') == new_host_xml.get('name') and host.get('ip') == new_host_xml.get('ip'):
if host.get("name") == new_host_xml.get("name") and host.get("ip") == new_host_xml.get("ip"):
return False
else:
self.update(VIR_NETWORK_UPDATE_COMMAND_MODIFY, VIR_NETWORK_SECTION_IP_DHCP_HOST, new_xml,
parent_index,
VIR_NETWORK_UPDATE_AFFECT_LIVE | VIR_NETWORK_UPDATE_AFFECT_CONFIG)
self.update(
VIR_NETWORK_UPDATE_COMMAND_MODIFY,
VIR_NETWORK_SECTION_IP_DHCP_HOST,
new_xml,
parent_index,
VIR_NETWORK_UPDATE_AFFECT_LIVE | VIR_NETWORK_UPDATE_AFFECT_CONFIG,
)
def get_qos(self):
qos_values = dict()
@ -307,19 +332,19 @@ class wvmNetwork(wvmConnect):
if qos:
qos = qos[0]
in_qos = qos.find('inbound')
in_qos = qos.find("inbound")
if in_qos is not None:
in_av = in_qos.get('average')
in_peak = in_qos.get('peak')
in_burst = in_qos.get('burst')
qos_values['inbound'] = {'average': in_av, 'peak': in_peak, 'burst': in_burst}
in_av = in_qos.get("average")
in_peak = in_qos.get("peak")
in_burst = in_qos.get("burst")
qos_values["inbound"] = {"average": in_av, "peak": in_peak, "burst": in_burst}
out_qos = qos.find('outbound')
out_qos = qos.find("outbound")
if out_qos is not None:
out_av = out_qos.get('average')
out_peak = out_qos.get('peak')
out_burst = out_qos.get('burst')
qos_values['outbound'] = {'average': out_av, 'peak': out_peak, 'burst': out_burst}
out_av = out_qos.get("average")
out_peak = out_qos.get("peak")
out_burst = out_qos.get("burst")
qos_values["outbound"] = {"average": out_av, "peak": out_peak, "burst": out_burst}
return qos_values
def set_qos(self, direction, average, peak, burst):
@ -328,7 +353,7 @@ class wvmNetwork(wvmConnect):
elif direction == "outbound":
xml = f"<outbound average='{average}' peak='{peak}' burst='{burst}'/>"
else:
raise Exception('Direction must be inbound or outbound')
raise Exception("Direction must be inbound or outbound")
tree = etree.fromstring(self._XMLDesc(0))
@ -363,7 +388,7 @@ class wvmNetwork(wvmConnect):
self.leases = self.net.DHCPLeases()
except Exception as e:
self.leases = []
raise f"Error getting {self} DHCP leases: {e}"
raise "Error getting {} DHCP leases: {}".format(self, e)
def get_dhcp_leases(self):
if self.leases is None:

View file

@ -1,4 +1,5 @@
from xml.etree import ElementTree
from vrtManager.connection import wvmConnect
@ -7,7 +8,7 @@ class wvmNWFilters(wvmConnect):
nwfilter = self.get_nwfilter(name)
xml = nwfilter.XMLDesc(0)
uuid = nwfilter.UUIDString()
return {'name': name, 'uuid': uuid, 'xml': xml}
return {"name": name, "uuid": uuid, "xml": xml}
def create_nwfilter(self, xml):
self.wvm.nwfilterDefineXML(xml)
@ -16,8 +17,8 @@ class wvmNWFilters(wvmConnect):
nwfilter = self.get_nwfilter(name)
if nwfilter:
tree = ElementTree.fromstring(nwfilter.XMLDesc(0))
tree.set('name', cln_name)
uuid = tree.find('uuid')
tree.set("name", cln_name)
uuid = tree.find("uuid")
tree.remove(uuid)
self.create_nwfilter(ElementTree.tostring(tree).decode())
@ -41,7 +42,7 @@ class wvmNWFilter(wvmConnect):
def get_xml(self):
tree = ElementTree.fromstring(self._XMLDesc(0))
uuid = tree.find('uuid')
uuid = tree.find("uuid")
tree.remove(uuid)
return ElementTree.tostring(tree).decode()
@ -49,7 +50,7 @@ class wvmNWFilter(wvmConnect):
refs = []
tree = ElementTree.fromstring(self._XMLDesc(0))
for ref in tree.findall("./filterref"):
refs.append(ref.get('filter'))
refs.append(ref.get("filter"))
return refs
def get_rules(self):
@ -57,10 +58,10 @@ class wvmNWFilter(wvmConnect):
tree = ElementTree.fromstring(self._XMLDesc(0))
for r in tree.findall("./rule"):
rule_action = r.get('action')
rule_direction = r.get('direction')
rule_priority = r.get('priority')
rule_statematch = r.get('statematch')
rule_action = r.get("action")
rule_direction = r.get("direction")
rule_priority = r.get("priority")
rule_statematch = r.get("statematch")
rule_directives = r.find("./")
if rule_directives is not None:
@ -71,7 +72,7 @@ class wvmNWFilter(wvmConnect):
"direction": rule_direction,
"priority": rule_priority,
"statematch": rule_statematch,
"directives": rule_directives
"directives": rule_directives,
}
rules.append(rule_info)
@ -81,7 +82,7 @@ class wvmNWFilter(wvmConnect):
def delete_ref(self, name):
tree = ElementTree.fromstring(self._XMLDesc(0))
for ref in tree.findall("./filterref"):
if name == ref.get('filter'):
if name == ref.get("filter"):
tree.remove(ref)
break
return ElementTree.tostring(tree).decode()
@ -89,7 +90,9 @@ class wvmNWFilter(wvmConnect):
def delete_rule(self, action, direction, priority):
tree = ElementTree.fromstring(self._XMLDesc(0))
rule_tree = tree.findall("./rule[@action='%s'][@direction='%s'][@priority='%s']" % (action, direction, priority))
rule_tree = tree.findall(
"./rule[@action='%s'][@direction='%s'][@priority='%s']" % (action, direction, priority)
)
if rule_tree:
tree.remove(rule_tree[0])
@ -98,7 +101,7 @@ class wvmNWFilter(wvmConnect):
def add_ref(self, name):
tree = ElementTree.fromstring(self._XMLDesc(0))
element = ElementTree.Element("filterref")
element.attrib['filter'] = name
element.attrib["filter"] = name
tree.append(element)
return ElementTree.tostring(tree).decode()
@ -106,19 +109,21 @@ class wvmNWFilter(wvmConnect):
tree = ElementTree.fromstring(self._XMLDesc(0))
rule = ElementTree.fromstring(xml)
rule_action = rule.get('action')
rule_direction = rule.get('direction')
rule_priority = rule.get('priority')
rule_action = rule.get("action")
rule_direction = rule.get("direction")
rule_priority = rule.get("priority")
rule_directives = rule.find("./")
rule_tree = tree.findall("./rule[@action='%s'][@direction='%s'][@priority='%s']" % (rule_action, rule_direction, rule_priority))
rule_tree = tree.findall(
"./rule[@action='%s'][@direction='%s'][@priority='%s']" % (rule_action, rule_direction, rule_priority)
)
if rule_tree:
rule_tree[0].append(rule_directives)
else:
element = ElementTree.Element("rule")
element.attrib['action'] = rule_action
element.attrib['direction'] = rule_direction
element.attrib['priority'] = rule_priority
element.attrib["action"] = rule_action
element.attrib["direction"] = rule_direction
element.attrib["priority"] = rule_priority
element.append(rule_directives)
tree.append(element)

View file

@ -11,11 +11,9 @@ found at: http://code.activestate.com/recipes/502283-read-write-lock-class-rlock
# Imports
# -------
from threading import Condition, Lock, currentThread
from time import time
# Read write lock
# ---------------
@ -138,9 +136,7 @@ class ReadWriteLock(object):
# else also wants to upgrade, there is no way we can do
# this except if one of us releases all his read locks.
# Signal this to user.
raise ValueError(
"Inevitable dead lock, denying write lock"
)
raise ValueError("Inevitable dead lock, denying write lock")
upgradewriter = True
self.__upgradewritercount = self.__readers.pop(me)
else:

View file

@ -1,4 +1,5 @@
import base64
from vrtManager.connection import wvmConnect
@ -6,12 +7,12 @@ class wvmSecrets(wvmConnect):
def create_secret(self, ephemeral, private, secret_type, data):
xml = f"""<secret ephemeral='{ephemeral}' private='{private}'>
<usage type='{secret_type}'>"""
if secret_type == 'ceph':
if secret_type == "ceph":
xml += f"""<name>{data}</name>"""
if secret_type == 'volume':
if secret_type == "volume":
xml += f"""<volume>{data}</volume>"""
if secret_type == 'iscsi':
xml += f"""<target>{data}</target>"""
if secret_type == "iscsi":
xml += f"""<target>{data}</target>"""
xml += """</usage>
</secret>"""
self.wvm.secretDefineXML(xml)

View file

@ -16,13 +16,7 @@ class wvmStorages(wvmConnect):
stg_vol = None
stg_size = stg.info()[1]
storages.append(
{
"name": pool,
"status": stg_status,
"type": stg_type,
"volumes": stg_vol,
"size": stg_size
}
{"name": pool, "status": stg_status, "type": stg_type, "volumes": stg_vol, "size": stg_size}
)
return storages
@ -103,12 +97,7 @@ class wvmStorage(wvmConnect):
return self.pool.name()
def get_status(self):
status = [
"Not running",
"Initializing pool, not available",
"Running normally",
"Running degraded"
]
status = ["Not running", "Initializing pool, not available", "Running normally", "Running degraded"]
try:
return status[self.pool.info()[0]]
except ValueError:
@ -217,12 +206,12 @@ class wvmStorage(wvmConnect):
"name": volname,
"size": self.get_volume_size(volname),
"allocation": self.get_volume_allocation(volname),
"type": self.get_volume_type(volname)
"type": self.get_volume_type(volname),
}
)
return vol_list
def create_volume(self, name, size, vol_fmt='qcow2', metadata=False, disk_owner_uid=0, disk_owner_gid=0):
def create_volume(self, name, size, vol_fmt="qcow2", metadata=False, disk_owner_uid=0, disk_owner_gid=0):
size = int(size) * 1073741824
storage_type = self.get_type()
alloc = size
@ -258,7 +247,17 @@ class wvmStorage(wvmConnect):
self._createXML(xml, metadata)
return name
def clone_volume(self, name, target_file, vol_fmt=None, metadata=False, mode='0644', file_suffix='img', disk_owner_uid=0, disk_owner_gid=0):
def clone_volume(
self,
name,
target_file,
vol_fmt=None,
metadata=False,
mode="0644",
file_suffix="img",
disk_owner_uid=0,
disk_owner_gid=0,
):
vol = self.get_volume(name)
if not vol_fmt:
vol_fmt = self.get_volume_type(name)
@ -266,10 +265,10 @@ class wvmStorage(wvmConnect):
storage_type = self.get_type()
if storage_type == "dir":
if vol_fmt in ["qcow", "qcow2"]:
target_file += '.' + vol_fmt
target_file += "." + vol_fmt
else:
suffix = '.' + file_suffix
target_file += suffix if len(suffix) > 1 else ''
suffix = "." + file_suffix
target_file += suffix if len(suffix) > 1 else ""
xml = f"""
<volume>

View file

@ -1,8 +1,9 @@
import random
import string
import re
import lxml.etree as etree
import string
import libvirt
import lxml.etree as etree
def is_kvm_available(xml):
@ -18,10 +19,8 @@ def randomMAC():
# qemu MAC
oui = [0x52, 0x54, 0x00]
mac = oui + [random.randint(0x00, 0xff),
random.randint(0x00, 0xff),
random.randint(0x00, 0xff)]
return ':'.join(map(lambda x: "%02x" % x, mac))
mac = oui + [random.randint(0x00, 0xFF), random.randint(0x00, 0xFF), random.randint(0x00, 0xFF)]
return ":".join(map(lambda x: "%02x" % x, mac))
def randomUUID():
@ -29,18 +28,17 @@ def randomUUID():
u = [random.randint(0, 255) for ignore in range(0, 16)]
u[6] = (u[6] & 0x0F) | (4 << 4)
u[8] = (u[8] & 0x3F) | (2 << 6)
return "-".join(["%02x" * 4, "%02x" * 2, "%02x" * 2, "%02x" * 2,
"%02x" * 6]) % tuple(u)
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([random.choice(alphabet) for i in range(length)])
return "".join([random.choice(alphabet) for i in range(length)])
def get_max_vcpus(conn, type=None):
"""@param conn: libvirt connection to poll for max possible vcpus
@type type: optional guest type (kvm, etc.)"""
@type type: optional guest type (kvm, etc.)"""
if type is None:
type = conn.getType()
try:
@ -57,7 +55,7 @@ def xml_escape(str):
str = str.replace("&", "&amp;")
str = str.replace("'", "&apos;")
str = str.replace("\"", "&quot;")
str = str.replace('"', "&quot;")
str = str.replace("<", "&lt;")
str = str.replace(">", "&gt;")
return str
@ -109,7 +107,7 @@ def get_xpath(doc, path):
if ret is not None:
if isinstance(ret, list):
if len(ret) >= 1:
if hasattr(ret[0], 'text'):
if hasattr(ret[0], "text"):
result = ret[0].text
else:
result = ret[0]
@ -146,11 +144,11 @@ def validate_uuid(val):
raise ValueError(
"UUID must be a 32-digit hexadecimal number. It may take "
"the form xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx or may "
"omit hyphens altogether.")
"omit hyphens altogether."
)
else: # UUID had no dashes, so add them in
val = (val[0:8] + "-" + val[8:12] + "-" + val[12:16] +
"-" + val[16:20] + "-" + val[20:32])
else: # UUID had no dashes, so add them in
val = val[0:8] + "-" + val[8:12] + "-" + val[12:16] + "-" + val[16:20] + "-" + val[20:32]
return val
@ -163,7 +161,7 @@ def validate_macaddr(val):
form = re.match("^([0-9a-fA-F]{1,2}:){5}[0-9a-fA-F]{1,2}$", val)
if form is None:
raise ValueError(f"MAC address must be of the format AA:BB:CC:DD:EE:FF, was {val}")
raise ValueError("MAC address must be of the format AA:BB:CC:DD:EE:FF, was {}".format(val))
# Mapping of UEFI binary names to their associated architectures. We
@ -177,7 +175,8 @@ UEFI_ARCH_PATTERNS = {
r".*OVMF_CODE\.fd", # RHEL
r".*ovmf-x64/OVMF.*\.fd", # gerd's firmware repo
r".*ovmf-x86_64-.*", # SUSE
r".*ovmf.*", ".*OVMF.*", # generic attempt at a catchall
r".*ovmf.*",
".*OVMF.*", # generic attempt at a catchall
],
"aarch64": [
r".*AAVMF_CODE\.fd", # RHEL