1
0
Fork 0
mirror of https://github.com/retspen/webvirtcloud synced 2024-12-25 15:45:23 +00:00

Merge pull request #484 from catborise/master

updates & fixes 1
This commit is contained in:
catborise 2022-01-12 13:41:10 +03:00 committed by GitHub
commit 9977c650db
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 15412 additions and 15050 deletions

View file

@ -1,4 +1,4 @@
FROM phusion/baseimage:focal-1.0.0 FROM phusion/baseimage:focal-1.1.0
EXPOSE 80 EXPOSE 80
EXPOSE 6080 EXPOSE 6080

View file

@ -32,7 +32,7 @@ WebVirtCloud is a virtualization web interface for admins and users. It can dele
## Quick Install with Installer (Beta) ## Quick Install with Installer (Beta)
Install an OS and run specified commands. Installer supported OSes: Ubuntu 18.04, Debian 10, Centos/OEL/RHEL 8. Install an OS and run specified commands. Installer supported OSes: Ubuntu 18.04/20.04, Debian 10/11, Centos/OEL/RHEL 8.
It can be installed on a virtual machine, physical host or on a KVM host. It can be installed on a virtual machine, physical host or on a KVM host.
```bash ```bash

View file

@ -1,4 +1,4 @@
Django==3.2.10 Django==3.2.11
django_bootstrap5==21.2 django_bootstrap5==21.2
django-icons==21.1 django-icons==21.1
django-login-required-middleware==0.7 django-login-required-middleware==0.7

View file

@ -4,4 +4,4 @@ django-debug-toolbar==3.2.4
pycodestyle==2.8.0 pycodestyle==2.8.0
pyflakes==2.4.0 pyflakes==2.4.0
pylint==2.12.2 pylint==2.12.2
yapf==0.31.0 yapf==0.32.0

View file

@ -342,15 +342,17 @@ def migrate(request, pk):
compress = request.POST.get("compress", False) compress = request.POST.get("compress", False)
postcopy = request.POST.get("postcopy", False) postcopy = request.POST.get("postcopy", False)
new_compute = Compute.objects.get(id=compute_id) current_host = instance.compute.hostname
target_host = Compute.objects.get(id=compute_id)
try: try:
utils.migrate_instance(new_compute, instance, request.user, live, unsafe, xml_del, offline) utils.migrate_instance(target_host, instance, request.user, live, unsafe, xml_del, offline)
except libvirtError as err: except libvirtError as err:
messages.error(request, err) messages.error(request, err)
msg = _("Instance is migrated to %(hostname)s") % {"hostname": new_compute.hostname} migration_method = "live" if live is True else "offline"
addlogmsg(request.user.username, instance.compute.hostname, instance.name, msg) msg = _("Instance is migrated(%(method)s) to %(hostname)s") % {"hostname": target_host.hostname, "method": migration_method}
addlogmsg(request.user.username, current_host, instance.name, msg)
return redirect(request.META.get("HTTP_REFERER")) return redirect(request.META.get("HTTP_REFERER"))

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

Binary file not shown.

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

Binary file not shown.

File diff suppressed because it is too large Load diff

View file

@ -6,128 +6,131 @@ Further Information might be available at:
https://github.com/haypo/python-ipy https://github.com/haypo/python-ipy
""" """
__version__ = "1.00" __version__ = '1.01'
import bisect import bisect
import collections
import sys
import types import types
try:
import collections.abc as collections_abc
except ImportError:
import collections as collections_abc
# Definition of the Ranges for IPv4 IPs # Definition of the Ranges for IPv4 IPs
# this should include www.iana.org/assignments/ipv4-address-space # this should include www.iana.org/assignments/ipv4-address-space
# and www.iana.org/assignments/multicast-addresses # and www.iana.org/assignments/multicast-addresses
IPv4ranges = { IPv4ranges = {
"0": "PUBLIC", # fall back '0': 'PUBLIC', # fall back
"00000000": "PRIVATE", # 0/8 '00000000': 'PRIVATE', # 0/8
"00001010": "PRIVATE", # 10/8 '00001010': 'PRIVATE', # 10/8
"0110010001": "CARRIER_GRADE_NAT", # 100.64/10 '0110010001': 'CARRIER_GRADE_NAT', #100.64/10
"01111111": "LOOPBACK", # 127.0/8 '01111111': 'LOOPBACK', # 127.0/8
"1": "PUBLIC", # fall back '1': 'PUBLIC', # fall back
"1010100111111110": "PRIVATE", # 169.254/16 '1010100111111110': 'PRIVATE', # 169.254/16
"101011000001": "PRIVATE", # 172.16/12 '101011000001': 'PRIVATE', # 172.16/12
"1100000010101000": "PRIVATE", # 192.168/16 '1100000010101000': 'PRIVATE', # 192.168/16
"111": "RESERVED", # 224/3 '111': 'RESERVED', # 224/3
} }
# Definition of the Ranges for IPv6 IPs # Definition of the Ranges for IPv6 IPs
# http://www.iana.org/assignments/ipv6-address-space/ # http://www.iana.org/assignments/ipv6-address-space/
# http://www.iana.org/assignments/ipv6-unicast-address-assignments/ # http://www.iana.org/assignments/ipv6-unicast-address-assignments/
# http://www.iana.org/assignments/ipv6-multicast-addresses/ # http://www.iana.org/assignments/ipv6-multicast-addresses/
IPv6ranges = { IPv6ranges = {
"00000000": "RESERVED", # ::/8 '00000000' : 'RESERVED', # ::/8
"0" * 96: "RESERVED", # ::/96 Formerly IPV4COMP [RFC4291] '0' * 96 : 'RESERVED', # ::/96 Formerly IPV4COMP [RFC4291]
"0" * 128: "UNSPECIFIED", # ::/128 '0' * 128 : 'UNSPECIFIED', # ::/128
"0" * 127 + "1": "LOOPBACK", # ::1/128 '0' * 127 + '1' : 'LOOPBACK', # ::1/128
"0" * 80 + "1" * 16: "IPV4MAP", # ::ffff:0:0/96 '0' * 80 + '1' * 16 : 'IPV4MAP', # ::ffff:0:0/96
"00000000011001001111111110011011" + "0" * 64: "WKP46TRANS", # 0064:ff9b::/96 Well-Known-Prefix [RFC6052] '00000000011001001111111110011011' + '0' * 64 : 'WKP46TRANS', # 0064:ff9b::/96 Well-Known-Prefix [RFC6052]
"00000001": "UNASSIGNED", # 0100::/8 '00000001' : 'UNASSIGNED', # 0100::/8
"0000001": "RESERVED", # 0200::/7 Formerly NSAP [RFC4048] '0000001' : 'RESERVED', # 0200::/7 Formerly NSAP [RFC4048]
"0000010": "RESERVED", # 0400::/7 Formerly IPX [RFC3513] '0000010' : 'RESERVED', # 0400::/7 Formerly IPX [RFC3513]
"0000011": "RESERVED", # 0600::/7 '0000011' : 'RESERVED', # 0600::/7
"00001": "RESERVED", # 0800::/5 '00001' : 'RESERVED', # 0800::/5
"0001": "RESERVED", # 1000::/4 '0001' : 'RESERVED', # 1000::/4
"001": "GLOBAL-UNICAST", # 2000::/3 [RFC4291] '001' : 'GLOBAL-UNICAST', # 2000::/3 [RFC4291]
"00100000000000010000000": "SPECIALPURPOSE", # 2001::/23 [RFC4773] '00100000000000010000000' : 'SPECIALPURPOSE', # 2001::/23 [RFC4773]
"00100000000000010000000000000000": "TEREDO", # 2001::/32 [RFC4380] '00100000000000010000000000000000' : 'TEREDO', # 2001::/32 [RFC4380]
"00100000000000010000000000000010" + "0" * 16: "BMWG", # 2001:0002::/48 Benchmarking [RFC5180] '00100000000000010000000000000010' + '0' * 16 : 'BMWG', # 2001:0002::/48 Benchmarking [RFC5180]
"0010000000000001000000000001": "ORCHID", # 2001:0010::/28 (Temp until 2014-03-21) [RFC4843] '0010000000000001000000000001' : 'ORCHID', # 2001:0010::/28 (Temp until 2014-03-21) [RFC4843]
"00100000000000010000001": "ALLOCATED APNIC", # 2001:0200::/23 '00100000000000010000001' : 'ALLOCATED APNIC', # 2001:0200::/23
"00100000000000010000010": "ALLOCATED ARIN", # 2001:0400::/23 '00100000000000010000010' : 'ALLOCATED ARIN', # 2001:0400::/23
"00100000000000010000011": "ALLOCATED RIPE NCC", # 2001:0600::/23 '00100000000000010000011' : 'ALLOCATED RIPE NCC', # 2001:0600::/23
"00100000000000010000100": "ALLOCATED RIPE NCC", # 2001:0800::/23 '00100000000000010000100' : 'ALLOCATED RIPE NCC', # 2001:0800::/23
"00100000000000010000101": "ALLOCATED RIPE NCC", # 2001:0a00::/23 '00100000000000010000101' : 'ALLOCATED RIPE NCC', # 2001:0a00::/23
"00100000000000010000110": "ALLOCATED APNIC", # 2001:0c00::/23 '00100000000000010000110' : 'ALLOCATED APNIC', # 2001:0c00::/23
"00100000000000010000110110111000": "DOCUMENTATION", # 2001:0db8::/32 [RFC3849] '00100000000000010000110110111000' : 'DOCUMENTATION', # 2001:0db8::/32 [RFC3849]
"00100000000000010000111": "ALLOCATED APNIC", # 2001:0e00::/23 '00100000000000010000111' : 'ALLOCATED APNIC', # 2001:0e00::/23
"00100000000000010001001": "ALLOCATED LACNIC", # 2001:1200::/23 '00100000000000010001001' : 'ALLOCATED LACNIC', # 2001:1200::/23
"00100000000000010001010": "ALLOCATED RIPE NCC", # 2001:1400::/23 '00100000000000010001010' : 'ALLOCATED RIPE NCC', # 2001:1400::/23
"00100000000000010001011": "ALLOCATED RIPE NCC", # 2001:1600::/23 '00100000000000010001011' : 'ALLOCATED RIPE NCC', # 2001:1600::/23
"00100000000000010001100": "ALLOCATED ARIN", # 2001:1800::/23 '00100000000000010001100' : 'ALLOCATED ARIN', # 2001:1800::/23
"00100000000000010001101": "ALLOCATED RIPE NCC", # 2001:1a00::/23 '00100000000000010001101' : 'ALLOCATED RIPE NCC', # 2001:1a00::/23
"0010000000000001000111": "ALLOCATED RIPE NCC", # 2001:1c00::/22 '0010000000000001000111' : 'ALLOCATED RIPE NCC', # 2001:1c00::/22
"00100000000000010010": "ALLOCATED RIPE NCC", # 2001:2000::/20 '00100000000000010010' : 'ALLOCATED RIPE NCC', # 2001:2000::/20
"001000000000000100110": "ALLOCATED RIPE NCC", # 2001:3000::/21 '001000000000000100110' : 'ALLOCATED RIPE NCC', # 2001:3000::/21
"0010000000000001001110": "ALLOCATED RIPE NCC", # 2001:3800::/22 '0010000000000001001110' : 'ALLOCATED RIPE NCC', # 2001:3800::/22
"0010000000000001001111": "RESERVED", # 2001:3c00::/22 Possible future allocation to RIPE NCC '0010000000000001001111' : 'RESERVED', # 2001:3c00::/22 Possible future allocation to RIPE NCC
"00100000000000010100000": "ALLOCATED RIPE NCC", # 2001:4000::/23 '00100000000000010100000' : 'ALLOCATED RIPE NCC', # 2001:4000::/23
"00100000000000010100001": "ALLOCATED AFRINIC", # 2001:4200::/23 '00100000000000010100001' : 'ALLOCATED AFRINIC', # 2001:4200::/23
"00100000000000010100010": "ALLOCATED APNIC", # 2001:4400::/23 '00100000000000010100010' : 'ALLOCATED APNIC', # 2001:4400::/23
"00100000000000010100011": "ALLOCATED RIPE NCC", # 2001:4600::/23 '00100000000000010100011' : 'ALLOCATED RIPE NCC', # 2001:4600::/23
"00100000000000010100100": "ALLOCATED ARIN", # 2001:4800::/23 '00100000000000010100100' : 'ALLOCATED ARIN', # 2001:4800::/23
"00100000000000010100101": "ALLOCATED RIPE NCC", # 2001:4a00::/23 '00100000000000010100101' : 'ALLOCATED RIPE NCC', # 2001:4a00::/23
"00100000000000010100110": "ALLOCATED RIPE NCC", # 2001:4c00::/23 '00100000000000010100110' : 'ALLOCATED RIPE NCC', # 2001:4c00::/23
"00100000000000010101": "ALLOCATED RIPE NCC", # 2001:5000::/20 '00100000000000010101' : 'ALLOCATED RIPE NCC', # 2001:5000::/20
"0010000000000001100": "ALLOCATED APNIC", # 2001:8000::/19 '0010000000000001100' : 'ALLOCATED APNIC', # 2001:8000::/19
"00100000000000011010": "ALLOCATED APNIC", # 2001:a000::/20 '00100000000000011010' : 'ALLOCATED APNIC', # 2001:a000::/20
"00100000000000011011": "ALLOCATED APNIC", # 2001:b000::/20 '00100000000000011011' : 'ALLOCATED APNIC', # 2001:b000::/20
"0010000000000010": "6TO4", # 2002::/16 "6to4" [RFC3056] '0010000000000010' : '6TO4', # 2002::/16 "6to4" [RFC3056]
"001000000000001100": "ALLOCATED RIPE NCC", # 2003::/18 '001000000000001100' : 'ALLOCATED RIPE NCC', # 2003::/18
"001001000000": "ALLOCATED APNIC", # 2400::/12 '001001000000' : 'ALLOCATED APNIC', # 2400::/12
"001001100000": "ALLOCATED ARIN", # 2600::/12 '001001100000' : 'ALLOCATED ARIN', # 2600::/12
"00100110000100000000000": "ALLOCATED ARIN", # 2610::/23 '00100110000100000000000' : 'ALLOCATED ARIN', # 2610::/23
"00100110001000000000000": "ALLOCATED ARIN", # 2620::/23 '00100110001000000000000' : 'ALLOCATED ARIN', # 2620::/23
"001010000000": "ALLOCATED LACNIC", # 2800::/12 '001010000000' : 'ALLOCATED LACNIC', # 2800::/12
"001010100000": "ALLOCATED RIPE NCC", # 2a00::/12 '001010100000' : 'ALLOCATED RIPE NCC', # 2a00::/12
"001011000000": "ALLOCATED AFRINIC", # 2c00::/12 '001011000000' : 'ALLOCATED AFRINIC', # 2c00::/12
"00101101": "RESERVED", # 2d00::/8 '00101101' : 'RESERVED', # 2d00::/8
"0010111": "RESERVED", # 2e00::/7 '0010111' : 'RESERVED', # 2e00::/7
"0011": "RESERVED", # 3000::/4 '0011' : 'RESERVED', # 3000::/4
"010": "RESERVED", # 4000::/3 '010' : 'RESERVED', # 4000::/3
"011": "RESERVED", # 6000::/3 '011' : 'RESERVED', # 6000::/3
"100": "RESERVED", # 8000::/3 '100' : 'RESERVED', # 8000::/3
"101": "RESERVED", # a000::/3 '101' : 'RESERVED', # a000::/3
"110": "RESERVED", # c000::/3 '110' : 'RESERVED', # c000::/3
"1110": "RESERVED", # e000::/4 '1110' : 'RESERVED', # e000::/4
"11110": "RESERVED", # f000::/5 '11110' : 'RESERVED', # f000::/5
"111110": "RESERVED", # f800::/6 '111110' : 'RESERVED', # f800::/6
"1111110": "ULA", # fc00::/7 [RFC4193] '1111110' : 'ULA', # fc00::/7 [RFC4193]
"111111100": "RESERVED", # fe00::/9 '111111100' : 'RESERVED', # fe00::/9
"1111111010": "LINKLOCAL", # fe80::/10 '1111111010' : 'LINKLOCAL', # fe80::/10
"1111111011": "RESERVED", # fec0::/10 Formerly SITELOCAL [RFC4291] '1111111011' : 'RESERVED', # fec0::/10 Formerly SITELOCAL [RFC4291]
"11111111": "MULTICAST", # ff00::/8 '11111111' : 'MULTICAST', # ff00::/8
"1111111100000001": "NODE-LOCAL MULTICAST", # ff01::/16 '1111111100000001' : 'NODE-LOCAL MULTICAST', # ff01::/16
"1111111100000010": "LINK-LOCAL MULTICAST", # ff02::/16 '1111111100000010' : 'LINK-LOCAL MULTICAST', # ff02::/16
"1111111100000100": "ADMIN-LOCAL MULTICAST", # ff04::/16 '1111111100000100' : 'ADMIN-LOCAL MULTICAST', # ff04::/16
"1111111100000101": "SITE-LOCAL MULTICAST", # ff05::/16 '1111111100000101' : 'SITE-LOCAL MULTICAST', # ff05::/16
"1111111100001000": "ORG-LOCAL MULTICAST", # ff08::/16 '1111111100001000' : 'ORG-LOCAL MULTICAST', # ff08::/16
"1111111100001110": "GLOBAL MULTICAST", # ff0e::/16 '1111111100001110' : 'GLOBAL MULTICAST', # ff0e::/16
"1111111100001111": "RESERVED MULTICAST", # ff0f::/16 '1111111100001111' : 'RESERVED MULTICAST', # ff0f::/16
"111111110011": "PREFIX-BASED MULTICAST", # ff30::/12 [RFC3306] '111111110011' : 'PREFIX-BASED MULTICAST', # ff30::/12 [RFC3306]
"111111110111": "RP-EMBEDDED MULTICAST", # ff70::/12 [RFC3956] '111111110111' : 'RP-EMBEDDED MULTICAST', # ff70::/12 [RFC3956]
} }
MAX_IPV4_ADDRESS = 0xFFFFFFFF MAX_IPV4_ADDRESS = 0xffffffff
MAX_IPV6_ADDRESS = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF MAX_IPV6_ADDRESS = 0xffffffffffffffffffffffffffffffff
IPV6_TEST_MAP = 0xFFFFFFFFFFFFFFFFFFFFFFFF00000000 IPV6_TEST_MAP = 0xffffffffffffffffffffffff00000000
IPV6_MAP_MASK = 0x00000000000000000000FFFF00000000 IPV6_MAP_MASK = 0x00000000000000000000ffff00000000
if sys.version_info >= (3,): try:
INT_TYPES = (int, long)
STR_TYPES = (str, unicode)
xrange
except NameError:
INT_TYPES = (int,) INT_TYPES = (int,)
STR_TYPES = (str,) STR_TYPES = (str,)
xrange = range xrange = range
else:
INT_TYPES = (int, long)
STR_TYPES = (str, unicode)
class IPint(object): class IPint(object):
@ -202,7 +205,7 @@ class IPint(object):
elif isinstance(data, STR_TYPES): elif isinstance(data, STR_TYPES):
# TODO: refactor me! # TODO: refactor me!
# splitting of a string into IP and prefixlen et. al. # splitting of a string into IP and prefixlen et. al.
x = data.split("-") x = data.split('-')
if len(x) == 2: if len(x) == 2:
# a.b.c.0-a.b.c.255 specification ? # a.b.c.0-a.b.c.255 specification ?
(ip, last) = x (ip, last) = x
@ -219,10 +222,10 @@ class IPint(object):
# make sure the broadcast is the same as the last ip # make sure the broadcast is the same as the last ip
# otherwise it will return /16 for something like: # otherwise it will return /16 for something like:
# 192.168.0.0-192.168.191.255 # 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) raise ValueError("the range %s is not on a network boundary." % data)
elif len(x) == 1: elif len(x) == 1:
x = data.split("/") x = data.split('/')
# if no prefix is given use defaults # if no prefix is given use defaults
if len(x) == 1: if len(x) == 1:
ip = x[0] ip = x[0]
@ -231,7 +234,7 @@ class IPint(object):
raise ValueError("only one '/' allowed in IP Address") raise ValueError("only one '/' allowed in IP Address")
else: else:
(ip, prefixlen) = x (ip, prefixlen) = x
if prefixlen.find(".") != -1: if prefixlen.find('.') != -1:
# check if the user might have used a netmask like # check if the user might have used a netmask like
# a.b.c.d/255.255.255.0 # a.b.c.d/255.255.255.0
(netmask, vers) = parseAddress(prefixlen) (netmask, vers) = parseAddress(prefixlen)
@ -255,7 +258,8 @@ class IPint(object):
if make_net: if make_net:
self.ip = self.ip & _prefixlenToNetmask(self._prefixlen, self._ipversion) 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)) raise ValueError("%s has invalid prefix length (%s)" % (repr(self), self._prefixlen))
else: else:
raise TypeError("Unsupported data type: %s" % type(data)) raise TypeError("Unsupported data type: %s" % type(data))
@ -313,12 +317,13 @@ class IPint(object):
want == 3 -lastip 1.2.3.0-1.2.3.255 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: if self.NoPrefixForSingleIp:
want = 0 want = 0
if want is None: if want == None:
want = self.WantPrefixLen want = self.WantPrefixLen
if want is None: if want == None:
want = 1 want = 1
if want: if want:
if want == 2: if want == 2:
@ -333,7 +338,7 @@ class IPint(object):
# default # default
return "/%d" % (self._prefixlen) return "/%d" % (self._prefixlen)
else: else:
return "" return ''
# We have different flavours to convert to: # We have different flavours to convert to:
# strFullsize 127.0.0.1 2001:0658:022a:cafe:0200:c0ff:fe8d:08fa # strFullsize 127.0.0.1 2001:0658:022a:cafe:0200:c0ff:fe8d:08fa
@ -342,7 +347,7 @@ class IPint(object):
# strHex 0x7F000001 0x20010658022ACAFE0200C0FFFE8D08FA # strHex 0x7F000001 0x20010658022ACAFE0200C0FFFE8D08FA
# strDec 2130706433 42540616829182469433547974687817795834 # strDec 2130706433 42540616829182469433547974687817795834
def strBin(self, wantprefixlen=None): def strBin(self, wantprefixlen = None):
"""Return a string representation as a binary value. """Return a string representation as a binary value.
>>> print(IP('127.0.0.1').strBin()) >>> print(IP('127.0.0.1').strBin())
@ -352,12 +357,12 @@ class IPint(object):
""" """
bits = _ipVersionToLen(self._ipversion) bits = _ipVersionToLen(self._ipversion)
if self.WantPrefixLen is None and wantprefixlen is None: if self.WantPrefixLen == None and wantprefixlen == None:
wantprefixlen = 0 wantprefixlen = 0
ret = _intToBin(self.ip) 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): def strCompressed(self, wantprefixlen = None):
"""Return a string representation in compressed format using '::' Notation. """Return a string representation in compressed format using '::' Notation.
>>> IP('127.0.0.1').strCompressed() >>> IP('127.0.0.1').strCompressed()
@ -368,18 +373,18 @@ class IPint(object):
'ffff:ffff:ffff:ffff:ffff:f:f:fffc/127' 'ffff:ffff:ffff:ffff:ffff:f:f:fffc/127'
""" """
if self.WantPrefixLen is None and wantprefixlen is None: if self.WantPrefixLen == None and wantprefixlen == None:
wantprefixlen = 1 wantprefixlen = 1
if self._ipversion == 4: if self._ipversion == 4:
return self.strFullsize(wantprefixlen) return self.strFullsize(wantprefixlen)
else: else:
if self.ip >> 32 == 0xFFFF: if self.ip >> 32 == 0xffff:
ipv4 = intToIp(self.ip & MAX_IPV4_ADDRESS, 4) ipv4 = intToIp(self.ip & MAX_IPV4_ADDRESS, 4)
text = "::ffff:" + ipv4 + self._printPrefix(wantprefixlen) text = "::ffff:" + ipv4 + self._printPrefix(wantprefixlen)
return text return text
# find the longest sequence of '0' # 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 # every element of followingzeros will contain the number of zeros
# following the corresponding element of hextets # following the corresponding element of hextets
followingzeros = [0] * 8 followingzeros = [0] * 8
@ -390,19 +395,19 @@ class IPint(object):
if max(followingzeros) > 1: if max(followingzeros) > 1:
# genererate string with the longest number of zeros cut out # genererate string with the longest number of zeros cut out
# now we need hextets as strings # now we need hextets as strings
hextets = [x for x in self.strNormal(0).split(":")] hextets = [x for x in self.strNormal(0).split(':')]
while compressionpos < len(hextets) and hextets[compressionpos] == "0": while compressionpos < len(hextets) and hextets[compressionpos] == '0':
del hextets[compressionpos] del(hextets[compressionpos])
hextets.insert(compressionpos, "") hextets.insert(compressionpos, '')
if compressionpos + 1 >= len(hextets): if compressionpos + 1 >= len(hextets):
hextets.append("") hextets.append('')
if compressionpos == 0: if compressionpos == 0:
hextets = [""] + hextets hextets = [''] + hextets
return ":".join(hextets) + self._printPrefix(wantprefixlen) return ':'.join(hextets) + self._printPrefix(wantprefixlen)
else: else:
return self.strNormal(0) + self._printPrefix(wantprefixlen) return self.strNormal(0) + self._printPrefix(wantprefixlen)
def strNormal(self, wantprefixlen=None): def strNormal(self, wantprefixlen = None):
"""Return a string representation in the usual format. """Return a string representation in the usual format.
>>> print(IP('127.0.0.1').strNormal()) >>> print(IP('127.0.0.1').strNormal())
@ -411,19 +416,21 @@ class IPint(object):
2001:658:22a:cafe:200:0:0:1 2001:658:22a:cafe:200:0:0:1
""" """
if self.WantPrefixLen is None and wantprefixlen is None: if self.WantPrefixLen == None and wantprefixlen == None:
wantprefixlen = 1 wantprefixlen = 1
if self._ipversion == 4: if self._ipversion == 4:
ret = self.strFullsize(0) ret = self.strFullsize(0)
elif self._ipversion == 6: 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: else:
raise ValueError("only IPv4 and IPv6 supported") raise ValueError("only IPv4 and IPv6 supported")
return ret + self._printPrefix(wantprefixlen) return ret + self._printPrefix(wantprefixlen)
def strFullsize(self, wantprefixlen=None): def strFullsize(self, wantprefixlen = None):
"""Return a string representation in the non-mangled format. """Return a string representation in the non-mangled format.
>>> print(IP('127.0.0.1').strFullsize()) >>> print(IP('127.0.0.1').strFullsize())
@ -432,12 +439,12 @@ class IPint(object):
2001:0658:022a:cafe:0200:0000:0000:0001 2001:0658:022a:cafe:0200:0000:0000:0001
""" """
if self.WantPrefixLen is None and wantprefixlen is None: if self.WantPrefixLen == None and wantprefixlen == None:
wantprefixlen = 1 wantprefixlen = 1
return intToIp(self.ip, self._ipversion) + self._printPrefix(wantprefixlen) return intToIp(self.ip, self._ipversion) + self._printPrefix(wantprefixlen)
def strHex(self, wantprefixlen=None): def strHex(self, wantprefixlen = None):
"""Return a string representation in hex format in lower case. """Return a string representation in hex format in lower case.
>>> print(IP('127.0.0.1').strHex()) >>> print(IP('127.0.0.1').strHex())
@ -446,13 +453,13 @@ class IPint(object):
0x20010658022acafe0200000000000001 0x20010658022acafe0200000000000001
""" """
if self.WantPrefixLen is None and wantprefixlen is None: if self.WantPrefixLen == None and wantprefixlen == None:
wantprefixlen = 0 wantprefixlen = 0
x = "0x%x" % self.ip x = '0x%x' % self.ip
return x + self._printPrefix(wantprefixlen) return x + self._printPrefix(wantprefixlen)
def strDec(self, wantprefixlen=None): def strDec(self, wantprefixlen = None):
"""Return a string representation in decimal format. """Return a string representation in decimal format.
>>> print(IP('127.0.0.1').strDec()) >>> print(IP('127.0.0.1').strDec())
@ -461,10 +468,10 @@ class IPint(object):
42540616829182469433547762482097946625 42540616829182469433547762482097946625
""" """
if self.WantPrefixLen is None and wantprefixlen is None: if self.WantPrefixLen == None and wantprefixlen == None:
wantprefixlen = 0 wantprefixlen = 0
x = "%d" % self.ip x = '%d' % self.ip
return x + self._printPrefix(wantprefixlen) return x + self._printPrefix(wantprefixlen)
def iptype(self): def iptype(self):
@ -499,6 +506,7 @@ class IPint(object):
return iprange[bits[:i]] return iprange[bits[:i]]
return "unknown" return "unknown"
def netmask(self): def netmask(self):
"""Return netmask as an integer. """Return netmask as an integer.
@ -512,6 +520,7 @@ class IPint(object):
return ((2 ** self._prefixlen) - 1) << locallen return ((2 ** self._prefixlen) - 1) << locallen
def strNetmask(self): def strNetmask(self):
"""Return netmask as an string. Mostly useful for IPv6. """Return netmask as an string. Mostly useful for IPv6.
@ -543,6 +552,7 @@ class IPint(object):
locallen = bits - self._prefixlen locallen = bits - self._prefixlen
return 2 ** locallen return 2 ** locallen
def __nonzero__(self): def __nonzero__(self):
"""All IPy objects should evaluate to true in boolean context. """All IPy objects should evaluate to true in boolean context.
Ordinarily they do, but if handling a default route expressed as Ordinarily they do, but if handling a default route expressed as
@ -579,8 +589,10 @@ class IPint(object):
raise ValueError("Only adjacent networks can be added together.") raise ValueError("Only adjacent networks can be added together.")
ret = IP(self.int(), ipversion=self._ipversion) ret = IP(self.int(), ipversion=self._ipversion)
ret._prefixlen = self.prefixlen() - 1 ret._prefixlen = self.prefixlen() - 1
if not _checkNetaddrWorksWithPrefixlen(ret.ip, ret._prefixlen, ret._ipversion): if not _checkNetaddrWorksWithPrefixlen(ret.ip, ret._prefixlen,
raise ValueError("The resulting %s has invalid prefix length (%s)" % (repr(ret), ret._prefixlen)) ret._ipversion):
raise ValueError("The resulting %s has invalid prefix length (%s)"
% (repr(ret), ret._prefixlen))
return ret return ret
def __sub__(self, other): def __sub__(self, other):
@ -619,6 +631,8 @@ class IPint(object):
return self.ip + int(key) return self.ip + int(key)
def __contains__(self, item): def __contains__(self, item):
"""Called to implement membership test operators. """Called to implement membership test operators.
@ -645,6 +659,7 @@ class IPint(object):
else: else:
return False return False
def overlaps(self, item): def overlaps(self, item):
"""Check if two IP address ranges overlap. """Check if two IP address ranges overlap.
@ -670,6 +685,7 @@ class IPint(object):
else: else:
return 0 return 0
def __str__(self): def __str__(self):
"""Dispatch to the prefered String Representation. """Dispatch to the prefered String Representation.
@ -677,6 +693,7 @@ class IPint(object):
return self.strCompressed() return self.strCompressed()
def __repr__(self): def __repr__(self):
"""Print a representation of the Object. """Print a representation of the Object.
@ -688,7 +705,8 @@ class IPint(object):
IP('10.0.0.0/24') IP('10.0.0.0/24')
""" """
return "IPint('%s')" % (self.strCompressed(1)) return("IPint('%s')" % (self.strCompressed(1)))
def __cmp__(self, other): def __cmp__(self, other):
"""Called by comparison operations. """Called by comparison operations.
@ -773,7 +791,7 @@ class IPint(object):
thehash = int(-1) thehash = int(-1)
ip = self.ip ip = self.ip
while ip > 0: while ip > 0:
thehash = thehash ^ (ip & 0x7FFFFFFF) thehash = thehash ^ (ip & 0x7fffffff)
ip = ip >> 32 ip = ip >> 32
thehash = thehash ^ self._prefixlen thehash = thehash ^ self._prefixlen
return int(thehash) return int(thehash)
@ -813,11 +831,11 @@ class IP(IPint):
def _getIPv4Map(self): def _getIPv4Map(self):
if self._ipversion != 6: if self._ipversion != 6:
return None return None
if (self.ip >> 32) != 0xFFFF: if (self.ip >> 32) != 0xffff:
return None return None
ipv4 = self.ip & MAX_IPV4_ADDRESS ipv4 = self.ip & MAX_IPV4_ADDRESS
if self._prefixlen != 128: 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) return IP(ipv4, ipversion=4)
def reverseNames(self): def reverseNames(self):
@ -846,17 +864,17 @@ class IP(IPint):
if self._ipversion == 4: if self._ipversion == 4:
ret = [] ret = []
# TODO: Refactor. Add support for IPint objects # TODO: Refactor. Add support for IPint objects
if self.len() < 2 ** 8: if self.len() < 2**8:
for x in self: for x in self:
ret.append(x.reverseName()) ret.append(x.reverseName())
elif self.len() < 2 ** 16: elif self.len() < 2**16:
for i in xrange(0, self.len(), 2 ** 8): for i in xrange(0, self.len(), 2**8):
ret.append(self[i].reverseName()[2:]) ret.append(self[i].reverseName()[2:])
elif self.len() < 2 ** 24: elif self.len() < 2**24:
for i in xrange(0, self.len(), 2 ** 16): for i in xrange(0, self.len(), 2**16):
ret.append(self[i].reverseName()[4:]) ret.append(self[i].reverseName()[4:])
else: else:
for i in xrange(0, self.len(), 2 ** 24): for i in xrange(0, self.len(), 2**24):
ret.append(self[i].reverseName()[6:]) ret.append(self[i].reverseName()[6:])
return ret return ret
elif self._ipversion == 6: elif self._ipversion == 6:
@ -868,7 +886,7 @@ class IP(IPint):
raise NotImplementedError("can't create IPv6 reverse names at sub nibble level") raise NotImplementedError("can't create IPv6 reverse names at sub nibble level")
s = list(s) s = list(s)
s.reverse() s.reverse()
s = ".".join(s) s = '.'.join(s)
first_nibble_index = int(32 - (self._prefixlen // 4)) * 2 first_nibble_index = int(32 - (self._prefixlen // 4)) * 2
return ["%s.ip6.arpa." % s[first_nibble_index:]] return ["%s.ip6.arpa." % s[first_nibble_index:]]
else: else:
@ -893,34 +911,31 @@ class IP(IPint):
if self._ipversion == 4: if self._ipversion == 4:
s = self.strFullsize(0) s = self.strFullsize(0)
s = s.split(".") s = s.split('.')
s.reverse() s.reverse()
first_byte_index = int(4 - (self._prefixlen // 8)) first_byte_index = int(4 - (self._prefixlen // 8))
if self._prefixlen % 8 != 0: if self._prefixlen % 8 != 0:
nibblepart = "%s-%s" % ( nibblepart = "%s-%s" % (s[3-(self._prefixlen // 8)], intToIp(self.ip + self.len() - 1, 4).split('.')[-1])
s[3 - (self._prefixlen // 8)], nibblepart += '.'
intToIp(self.ip + self.len() - 1, 4).split(".")[-1],
)
nibblepart += "."
else: else:
nibblepart = "" nibblepart = ""
s = ".".join(s[first_byte_index:]) s = '.'.join(s[first_byte_index:])
return "%s%s.in-addr.arpa." % (nibblepart, s) return "%s%s.in-addr.arpa." % (nibblepart, s)
elif self._ipversion == 6: elif self._ipversion == 6:
ipv4 = self._getIPv4Map() ipv4 = self._getIPv4Map()
if ipv4 is not None: if ipv4 is not None:
return ipv4.reverseName() return ipv4.reverseName()
s = "%032x" % self.ip s = '%032x' % self.ip
if self._prefixlen % 4 != 0: if self._prefixlen % 4 != 0:
nibblepart = "%s-%x" % (s[self._prefixlen :], self.ip + self.len() - 1) nibblepart = "%s-%x" % (s[self._prefixlen:], self.ip + self.len() - 1)
nibblepart += "." nibblepart += '.'
else: else:
nibblepart = "" nibblepart = ""
s = list(s) s = list(s)
s.reverse() s.reverse()
s = ".".join(s) s = '.'.join(s)
first_nibble_index = int(32 - (self._prefixlen // 4)) * 2 first_nibble_index = int(32 - (self._prefixlen // 4)) * 2
return "%s%s.ip6.arpa." % (nibblepart, s[first_nibble_index:]) return "%s%s.ip6.arpa." % (nibblepart, s[first_nibble_index:])
else: else:
@ -935,9 +950,9 @@ class IP(IPint):
>>> print(IP('127.0.0.1').make_net('255.0.0.0')) >>> print(IP('127.0.0.1').make_net('255.0.0.0'))
127.0.0.0/8 127.0.0.0/8
""" """
if "/" in str(netmask): if '/' in str(netmask):
raise ValueError("invalid netmask (%s)" % 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): def __getitem__(self, key):
"""Called to implement evaluation of self[key]. """Called to implement evaluation of self[key].
@ -966,7 +981,7 @@ class IP(IPint):
IP('10.0.0.0/8') IP('10.0.0.0/8')
""" """
return "IP('%s')" % (self.strCompressed(1)) return("IP('%s')" % (self.strCompressed(1)))
def get_mac(self): def get_mac(self):
""" """
@ -978,15 +993,15 @@ class IP(IPint):
""" """
if self._ipversion != 6: if self._ipversion != 6:
return None return None
if (self.ip & 0x20000FFFF000000) != 0x20000FFFE000000: if (self.ip & 0x20000ffff000000) != 0x20000fffe000000:
return None return None
return "%02x:%02x:%02x:%02x:%02x:%02x" % ( return '%02x:%02x:%02x:%02x:%02x:%02x' % (
(((self.ip >> 56) & 0xFF) & 0xFD), (((self.ip >> 56) & 0xff) & 0xfd),
(self.ip >> 48) & 0xFF, (self.ip >> 48) & 0xff,
(self.ip >> 40) & 0xFF, (self.ip >> 40) & 0xff,
(self.ip >> 16) & 0xFF, (self.ip >> 16) & 0xff,
(self.ip >> 8) & 0xFF, (self.ip >> 8) & 0xff,
self.ip & 0xFF, self.ip & 0xff,
) )
def v46map(self): def v46map(self):
@ -1001,23 +1016,25 @@ class IP(IPint):
IP('192.168.1.1') IP('192.168.1.1')
""" """
if self._ipversion == 4: 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: else:
if self.ip & IPV6_TEST_MAP == IPV6_MAP_MASK: if self.ip & IPV6_TEST_MAP == IPV6_MAP_MASK:
return IP(str(self.ip - IPV6_MAP_MASK) + "/%s" % (self._prefixlen - 96)) return IP(str(self.ip - IPV6_MAP_MASK) +
raise ValueError("%s cannot be converted to an IPv4 address." % repr(self)) "/%s" % (self._prefixlen - 96))
raise ValueError("%s cannot be converted to an IPv4 address."
% repr(self))
class IPSet(collections_abc.MutableSet):
class IPSet(collections.MutableSet):
def __init__(self, iterable=[]): def __init__(self, iterable=[]):
# Make sure it's iterable, otherwise wrap # Make sure it's iterable, otherwise wrap
if not isinstance(iterable, collections.Iterable): if not isinstance(iterable, collections_abc.Iterable):
raise TypeError("'%s' object is not iterable" % type(iterable).__name__) raise TypeError("'%s' object is not iterable" % type(iterable).__name__)
# Make sure we only accept IP objects # Make sure we only accept IP objects
for prefix in iterable: for prefix in iterable:
if not isinstance(prefix, IP): 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 # Store and optimize
self.prefixes = iterable[:] self.prefixes = iterable[:]
@ -1026,7 +1043,7 @@ class IPSet(collections.MutableSet):
def __contains__(self, ip): def __contains__(self, ip):
valid_masks = self.prefixtable.keys() valid_masks = self.prefixtable.keys()
if isinstance(ip, IP): if isinstance(ip, IP):
# Don't dig through more-specific ranges #Don't dig through more-specific ranges
ip_mask = ip._prefixlen ip_mask = ip._prefixlen
valid_masks = [x for x in valid_masks if x <= ip_mask] valid_masks = [x for x in valid_masks if x <= ip_mask]
for mask in sorted(valid_masks): for mask in sorted(valid_masks):
@ -1078,20 +1095,20 @@ class IPSet(collections.MutableSet):
return IPSet(result) return IPSet(result)
def __repr__(self): 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): def len(self):
return sum(prefix.len() for prefix in self.prefixes) return sum(prefix.len() for prefix in self.prefixes)
def add(self, value): def add(self, value):
# Make sure it's iterable, otherwise wrap # Make sure it's iterable, otherwise wrap
if not isinstance(value, collections.Iterable): if not isinstance(value, collections_abc.Iterable):
value = [value] value = [value]
# Check type # Check type
for prefix in value: for prefix in value:
if not isinstance(prefix, IP): 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 # Append and optimize
self.prefixes.extend(value) self.prefixes.extend(value)
@ -1099,7 +1116,7 @@ class IPSet(collections.MutableSet):
def discard(self, value): def discard(self, value):
# Make sure it's iterable, otherwise wrap # Make sure it's iterable, otherwise wrap
if not isinstance(value, collections.Iterable): if not isinstance(value, collections_abc.Iterable):
value = [value] value = [value]
# This is much faster than iterating over the addresses # This is much faster than iterating over the addresses
@ -1109,7 +1126,7 @@ class IPSet(collections.MutableSet):
# Remove # Remove
for del_prefix in value: for del_prefix in value:
if not isinstance(del_prefix, IP): 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 # First check if this prefix contains anything in our list
found = False found = False
@ -1129,7 +1146,7 @@ class IPSet(collections.MutableSet):
found = False found = False
for i in range(len(self.prefixes)): for i in range(len(self.prefixes)):
if del_prefix in self.prefixes[i]: 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 break
self.optimize() self.optimize()
@ -1160,7 +1177,7 @@ class IPSet(collections.MutableSet):
while i < addrlen: while i < addrlen:
# Everything that might be inside this prefix follows # Everything that might be inside this prefix follows
# directly behind it # directly behind it
j = i + 1 j = i+1
while j < addrlen and self.prefixes[j] in self.prefixes[i]: while j < addrlen and self.prefixes[j] in self.prefixes[i]:
# Mark for deletion by overwriting with None # Mark for deletion by overwriting with None
self.prefixes[j] = None self.prefixes[j] = None
@ -1184,7 +1201,7 @@ class IPSet(collections.MutableSet):
# prefix length and differ only on the last bit of the prefix # prefix length and differ only on the last bit of the prefix
addrlen = len(self.prefixes) addrlen = len(self.prefixes)
i = 0 i = 0
while i < addrlen - 1: while i < addrlen-1:
j = i + 1 j = i + 1
try: try:
@ -1207,7 +1224,6 @@ class IPSet(collections.MutableSet):
except KeyError: except KeyError:
self.prefixtable[address._prefixlen] = [address] self.prefixtable[address._prefixlen] = [address]
def _parseAddressIPv6(ipstr): def _parseAddressIPv6(ipstr):
""" """
Internal function used by parseAddress() to parse IPv6 address with ':'. Internal function used by parseAddress() to parse IPv6 address with ':'.
@ -1274,16 +1290,16 @@ def _parseAddressIPv6(ipstr):
fill_pos = len(items) fill_pos = len(items)
index += 2 index += 2
continue continue
pos = text.find(":") pos = text.find(':')
if pos == 0: if pos == 0:
# Invalid IPv6, eg. '1::2:' # Invalid IPv6, eg. '1::2:'
raise ValueError("%r: Invalid IPv6 address" % ipstr) raise ValueError("%r: Invalid IPv6 address" % ipstr)
if pos != -1: if pos != -1:
items.append(text[:pos]) items.append(text[:pos])
if text[pos : pos + 2] == "::": if text[pos:pos+2] == "::":
index += pos index += pos
else: else:
index += pos + 1 index += pos+1
if index == len(ipstr): if index == len(ipstr):
# Invalid IPv6, eg. '1::2:' # Invalid IPv6, eg. '1::2:'
@ -1292,13 +1308,13 @@ def _parseAddressIPv6(ipstr):
items.append(text) items.append(text)
break break
if items and "." in items[-1]: if items and '.' in items[-1]:
# IPv6 ending with IPv4 like '::ffff:192.168.0.1' # IPv6 ending with IPv4 like '::ffff:192.168.0.1'
if (fill_pos is not None) and not (fill_pos <= len(items) - 1): if (fill_pos is not None) and not (fill_pos <= len(items)-1):
# Invalid IPv6: 'ffff:192.168.0.1::' # Invalid IPv6: 'ffff:192.168.0.1::'
raise ValueError("%r: Invalid IPv6 address: '::' after IPv4" % ipstr) raise ValueError("%r: Invalid IPv6 address: '::' after IPv4" % ipstr)
value = parseAddress(items[-1])[0] 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' # Expand fill_pos to fill with '0'
# ['1','2'] with fill_pos=1 => ['1', '0', '0', '0', '0', '0', '0', '2'] # ['1','2'] with fill_pos=1 => ['1', '0', '0', '0', '0', '0', '0', '2']
@ -1306,7 +1322,7 @@ def _parseAddressIPv6(ipstr):
diff = 8 - len(items) diff = 8 - len(items)
if diff <= 0: if diff <= 0:
raise ValueError("%r: Invalid IPv6 address: '::' is not needed" % ipstr) 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 # Here we have a list of 8 strings
if len(items) != 8: if len(items) != 8:
@ -1319,7 +1335,7 @@ def _parseAddressIPv6(ipstr):
for item in items: for item in items:
try: try:
item = int(item, 16) item = int(item, 16)
error = not (0 <= item <= 0xFFFF) error = not(0 <= item <= 0xffff)
except ValueError: except ValueError:
error = True error = True
if error: if error:
@ -1328,7 +1344,6 @@ def _parseAddressIPv6(ipstr):
index += 1 index += 1
return value return value
def parseAddress(ipstr, ipversion=0): def parseAddress(ipstr, ipversion=0):
""" """
Parse a string and return the corresponding IP address (as integer) Parse a string and return the corresponding IP address (as integer)
@ -1383,7 +1398,7 @@ def parseAddress(ipstr, ipversion=0):
except ValueError: except ValueError:
intval = None 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: if hexval > MAX_IPV6_ADDRESS:
raise ValueError("IP Address can't be larger than %x: %x" % (MAX_IPV6_ADDRESS, hexval)) raise ValueError("IP Address can't be larger than %x: %x" % (MAX_IPV6_ADDRESS, hexval))
if hexval <= MAX_IPV4_ADDRESS: if hexval <= MAX_IPV4_ADDRESS:
@ -1391,19 +1406,19 @@ def parseAddress(ipstr, ipversion=0):
else: else:
return (hexval, 6) return (hexval, 6)
if ipstr.find(":") != -1: if ipstr.find(':') != -1:
return (_parseAddressIPv6(ipstr), 6) return (_parseAddressIPv6(ipstr), 6)
elif len(ipstr) == 32 and hexval is not None: elif len(ipstr) == 32 and hexval is not None:
# assume IPv6 in pure hexadecimal notation # assume IPv6 in pure hexadecimal notation
return (hexval, 6) 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') # assume IPv4 ('127' gets interpreted as '127.0.0.0')
bytes = ipstr.split(".") bytes = ipstr.split('.')
if len(bytes) > 4: if len(bytes) > 4:
raise ValueError("IPv4 Address with more than 4 bytes") 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] bytes = [int(x) for x in bytes]
for x in bytes: for x in bytes:
if x > 255 or x < 0: if x > 255 or x < 0:
@ -1433,12 +1448,12 @@ def intToIp(ip, version):
if ip < 0: if ip < 0:
raise ValueError("IPs can't be negative: %d" % (ip)) raise ValueError("IPs can't be negative: %d" % (ip))
ret = "" ret = ''
if version == 4: if version == 4:
if ip > MAX_IPV4_ADDRESS: if ip > MAX_IPV4_ADDRESS:
raise ValueError("IPv4 Address can't be larger than %x: %x" % (MAX_IPV4_ADDRESS, ip)) raise ValueError("IPv4 Address can't be larger than %x: %x" % (MAX_IPV4_ADDRESS, ip))
for l in xrange(4): for l in xrange(4):
ret = str(ip & 0xFF) + "." + ret ret = str(ip & 0xff) + '.' + ret
ip = ip >> 8 ip = ip >> 8
ret = ret[:-1] ret = ret[:-1]
elif version == 6: elif version == 6:
@ -1448,14 +1463,13 @@ def intToIp(ip, version):
for x in xrange(1, 33): for x in xrange(1, 33):
ret = l[-x] + ret ret = l[-x] + ret
if x % 4 == 0: if x % 4 == 0:
ret = ":" + ret ret = ':' + ret
ret = ret[1:] ret = ret[1:]
else: else:
raise ValueError("only IPv4 and IPv6 supported") raise ValueError("only IPv4 and IPv6 supported")
return ret return ret
def _ipVersionToLen(version): def _ipVersionToLen(version):
"""Return number of bits in address for a certain IP version. """Return number of bits in address for a certain IP version.
@ -1489,25 +1503,10 @@ def _countFollowingZeros(l):
return 1 + _countFollowingZeros(l[1:]) return 1 + _countFollowingZeros(l[1:])
_BitTable = { _BitTable = {'0': '0000', '1': '0001', '2': '0010', '3': '0011',
"0": "0000", '4': '0100', '5': '0101', '6': '0110', '7': '0111',
"1": "0001", '8': '1000', '9': '1001', 'a': '1010', 'b': '1011',
"2": "0010", 'c': '1100', 'd': '1101', 'e': '1110', 'f': '1111'}
"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): def _intToBin(val):
"""Return the binary representation of an integer as string.""" """Return the binary representation of an integer as string."""
@ -1515,15 +1514,14 @@ def _intToBin(val):
if val < 0: if val < 0:
raise ValueError("Only positive values allowed") raise ValueError("Only positive values allowed")
s = "%x" % val s = "%x" % val
ret = "" ret = ''
for x in s: for x in s:
ret += _BitTable[x] ret += _BitTable[x]
# remove leading zeros # remove leading zeros
while ret[0] == "0" and len(ret) > 1: while ret[0] == '0' and len(ret) > 1:
ret = ret[1:] ret = ret[1:]
return ret return ret
def _count1Bits(num): def _count1Bits(num):
"""Find the highest bit set to 1 in an integer.""" """Find the highest bit set to 1 in an integer."""
ret = 0 ret = 0
@ -1532,7 +1530,6 @@ def _count1Bits(num):
ret += 1 ret += 1
return ret return ret
def _count0Bits(num): def _count0Bits(num):
"""Find the highest bit set to 0 in an integer.""" """Find the highest bit set to 0 in an integer."""
@ -1604,7 +1601,7 @@ def _checkNetmask(netmask, masklen):
def _checkNetaddrWorksWithPrefixlen(net, prefixlen, version): def _checkNetaddrWorksWithPrefixlen(net, prefixlen, version):
"""Check if a base addess of a network is compatible with a prefixlen""" """Check if a base addess of a network is compatible with a prefixlen"""
try: try:
return net & _prefixlenToNetmask(prefixlen, version) == net return (net & _prefixlenToNetmask(prefixlen, version) == net)
except ValueError: except ValueError:
return False return False
@ -1632,7 +1629,7 @@ def _prefixlenToNetmask(prefixlen, version):
return 0 return 0
elif prefixlen < 0: elif prefixlen < 0:
raise ValueError("Prefixlen must be > 0") raise ValueError("Prefixlen must be > 0")
return ((2 << prefixlen - 1) - 1) << (_ipVersionToLen(version) - prefixlen) return ((2<<prefixlen-1)-1) << (_ipVersionToLen(version) - prefixlen)
def _remove_subprefix(prefix, subprefix): def _remove_subprefix(prefix, subprefix):
@ -1646,8 +1643,8 @@ def _remove_subprefix(prefix, subprefix):
# Start cutting in half, recursively # Start cutting in half, recursively
prefixes = [ prefixes = [
IP("%s/%d" % (prefix[0], prefix._prefixlen + 1)), IP('%s/%d' % (prefix[0], prefix._prefixlen + 1)),
IP("%s/%d" % (prefix[int(prefix.len() / 2)], prefix._prefixlen + 1)), IP('%s/%d' % (prefix[int(prefix.len() / 2)], prefix._prefixlen + 1)),
] ]
if subprefix in prefixes[0]: if subprefix in prefixes[0]:
return _remove_subprefix(prefixes[0], subprefix) + IPSet([prefixes[1]]) return _remove_subprefix(prefixes[0], subprefix) + IPSet([prefixes[1]])
@ -1657,9 +1654,7 @@ def _remove_subprefix(prefix, subprefix):
if __name__ == "__main__": if __name__ == "__main__":
import doctest import doctest
failure, nbtest = doctest.testmod() failure, nbtest = doctest.testmod()
if failure: if failure:
import sys import sys
sys.exit(1) sys.exit(1)

View file

@ -12,14 +12,13 @@ try:
class LdapAuthenticationBackend(ModelBackend): class LdapAuthenticationBackend(ModelBackend):
def get_LDAP_user(self, username, password, filterString): def get_LDAP_user(self, username, password, filterString):
print('get_LDAP_user') print('get_LDAP_user {}'.format(username))
try: try:
server = Server(settings.LDAP_URL, port=settings.LDAP_PORT, server = Server(settings.LDAP_URL, port=settings.LDAP_PORT,
use_ssl=settings.USE_SSL,get_info=ALL) use_ssl=settings.USE_SSL,get_info=ALL)
connection = Connection(server, connection = Connection(server,
settings.LDAP_MASTER_DN, settings.LDAP_MASTER_DN,
settings.LDAP_MASTER_PW, auto_bind=True) settings.LDAP_MASTER_PW, auto_bind=True)
connection.search(settings.LDAP_ROOT_DN, connection.search(settings.LDAP_ROOT_DN,
'(&({attr}={login})({filter}))'.format( '(&({attr}={login})({filter}))'.format(
attr=settings.LDAP_USER_UID_PREFIX, attr=settings.LDAP_USER_UID_PREFIX,
@ -31,11 +30,10 @@ try:
return None return None
specificUser = connection.response[0] specificUser = connection.response[0]
userDn = str(specificUser.get('raw_dn'),'utf-8') userDn = str(specificUser.get('raw_dn'),'utf-8')
with Connection(server, with Connection(server, userDn, password) as con:
userDn,
password) as con:
return username return username
except: except Exception as e:
print("LDAP Exception: {}".format(e))
return None return None
return None return None
@ -50,6 +48,7 @@ try:
if self.get_LDAP_user(username, password, settings.LDAP_SEARCH_GROUP_FILTER_ADMINS) is None: if self.get_LDAP_user(username, password, settings.LDAP_SEARCH_GROUP_FILTER_ADMINS) is None:
if self.get_LDAP_user(username, password, settings.LDAP_SEARCH_GROUP_FILTER_STAFF) is None: if self.get_LDAP_user(username, password, settings.LDAP_SEARCH_GROUP_FILTER_STAFF) is None:
if self.get_LDAP_user(username, password, settings.LDAP_SEARCH_GROUP_FILTER_USERS) is None: if self.get_LDAP_user(username, password, settings.LDAP_SEARCH_GROUP_FILTER_USERS) is None:
print("User does not belong to any search group. Check LDAP_SEARCH_GROUP_FILTER in settings.")
return None return None
else: else:
isStaff = True isStaff = True
@ -62,7 +61,7 @@ try:
attributes = UserAttributes.objects.get(user=user) attributes = UserAttributes.objects.get(user=user)
# TODO VERIFY # TODO VERIFY
except User.DoesNotExist: except User.DoesNotExist:
print("authenticate-create new user") print("authenticate-create new user: {}".format(username))
user = User(username=username) user = User(username=username)
user.is_active = True user.is_active = True
user.is_staff = isStaff user.is_staff = isStaff

View file

@ -268,6 +268,7 @@ LDAP_MASTER_PW = ''
LDAP_ROOT_DN = '' LDAP_ROOT_DN = ''
## Queries to identify the users, i use groupOfUniqueNames on openldap ## Queries to identify the users, i use groupOfUniqueNames on openldap
### PLEASE BE SURE memberOf overlay is activated on slapd
## e.g. memberOf=cn=admins,cn=staff,cn=webvirtcloud,ou=groups,dc=kendar,dc=org ## e.g. memberOf=cn=admins,cn=staff,cn=webvirtcloud,ou=groups,dc=kendar,dc=org
LDAP_SEARCH_GROUP_FILTER_ADMINS = '' LDAP_SEARCH_GROUP_FILTER_ADMINS = ''
## e.g. memberOf=cn=staff,cn=webvirtcloud,ou=groups,dc=kendar,dc=org ## e.g. memberOf=cn=staff,cn=webvirtcloud,ou=groups,dc=kendar,dc=org