pass to help flesh out documentation for core.misc

This commit is contained in:
Blake J. Harnden 2017-05-04 10:36:13 -07:00
parent 8ade6f4f02
commit 3f82c980de
8 changed files with 662 additions and 116 deletions

View file

@ -14,10 +14,25 @@ logger = log.get_logger(__name__)
class MacAddress(object):
"""
Provides mac address utilities for use within core.
"""
def __init__(self, address):
"""
Creates a MacAddress instance.
:param str address: mac address
"""
self.addr = address
def __str__(self):
"""
Create a string representation of a MacAddress.
:return: string representation
:rtype: str
"""
return ":".join(map(lambda x: "%02x" % ord(x), self.addr))
def to_link_local(self):
@ -41,42 +56,100 @@ class MacAddress(object):
@classmethod
def from_string(cls, s):
"""
Create a mac address object from a string.
:param s: string representation of a mac address
:return: mac address class
:rtype: MacAddress
"""
addr = "".join(map(lambda x: chr(int(x, 16)), s.split(":")))
return cls(addr)
@classmethod
def random(cls):
"""
Create a random mac address.
:return: random mac address
:rtype: MacAddress
"""
tmp = random.randint(0, 0xFFFFFF)
tmp |= 0x00163E << 24 # use the Xen OID 00:16:3E
# use the Xen OID 00:16:3E
tmp |= 0x00163E << 24
tmpbytes = struct.pack("!Q", tmp)
return cls(tmpbytes[2:])
class IpAddress(object):
"""
Provides ip utilities and functionality for use within core.
"""
def __init__(self, af, address):
"""
Create a IpAddress instance.
:param int af: address family
:param str address: ip address
:return:
"""
# check if (af, addr) is valid
if not socket.inet_ntop(af, address):
raise ValueError, "invalid af/addr"
raise ValueError("invalid af/addr")
self.af = af
self.addr = address
def is_ipv4(self):
"""
Checks if this is an ipv4 address.
:return: True if ipv4 address, False otherwise
:rtype: bool
"""
return self.af == AF_INET
def is_ipv6(self):
"""
Checks if this is an ipv6 address.
:return: True if ipv6 address, False otherwise
:rtype: bool
"""
return self.af == AF_INET6
def __str__(self):
"""
Create a string representation of this address.
:return: string representation of address
:rtype: str
"""
return socket.inet_ntop(self.af, self.addr)
def __eq__(self, other):
try:
return other.af == self.af and other.addr == self.addr
except AttributeError:
logger.exception("error during equals compare")
"""
Checks for equality with another ip address.
:param IpAddress other: other ip address to check equality with
:return: True is the other IpAddress is equal, False otherwise
:rtype: bool
"""
if not isinstance(other, IpAddress):
return False
elif self is other:
return True
else:
return other.af == self.af and other.addr == self.addr
def __add__(self, other):
"""
Add value to ip addresses.
:param int other: value to add to ip address
:return: added together ip address instance
:rtype: IpAddress
"""
try:
carry = int(other)
except ValueError:
@ -94,40 +167,68 @@ class IpAddress(object):
return self.__class__(self.af, addr)
def __sub__(self, other):
"""
Subtract value from ip address.
:param int other: value to subtract from ip address
:return:
"""
try:
tmp = -int(other)
except ValueError:
logger.exception("error during subtraction")
return NotImplemented
return self.__add__(tmp)
@classmethod
def from_string(cls, s):
"""
Create a ip address from a string representation.
:param s: string representation to create ip address from
:return: ip address instance
:rtype: IpAddress
"""
for af in AF_INET, AF_INET6:
return cls(af, socket.inet_pton(af, s))
@staticmethod
def to_int(s):
"""
convert IPv4 string to 32-bit integer
Convert IPv4 string to integer
:param s: string to convert to 32-bit integer
:return: integer value
:rtype: int
"""
bin = socket.inet_pton(AF_INET, s)
return struct.unpack('!I', bin)[0]
class IpPrefix(object):
"""
Provides ip address generation and prefix utilities.
"""
def __init__(self, af, prefixstr):
"prefixstr format: address/prefixlen"
"""
Create a IpPrefix instance.
:param int af: address family for ip prefix
:param prefixstr: ip prefix string
"""
# prefixstr format: address/prefixlen
tmp = prefixstr.split("/")
if len(tmp) > 2:
raise ValueError, "invalid prefix: '%s'" % prefixstr
raise ValueError("invalid prefix: '%s'" % prefixstr)
self.af = af
if self.af == AF_INET:
self.addrlen = 32
elif self.af == AF_INET6:
self.addrlen = 128
else:
raise ValueError, "invalid address family: '%s'" % self.af
raise ValueError("invalid address family: '%s'" % self.af)
if len(tmp) == 2:
self.prefixlen = int(tmp[1])
else:
@ -143,12 +244,37 @@ class IpPrefix(object):
self.prefix = self.prefix[:i] + prefix
def __str__(self):
"""
String representation of an ip prefix.
:return: string representation
:rtype: str
"""
return "%s/%s" % (socket.inet_ntop(self.af, self.prefix), self.prefixlen)
def __eq__(self, other):
return other.af == self.af and other.prefixlen == self.prefixlen and other.prefix == self.prefix
"""
Compare equality with another ip prefix.
:param IpPrefix other: other ip prefix to compare with
:return: True is equal, False otherwise
:rtype: bool
"""
if not isinstance(other, IpPrefix):
return False
elif self is other:
return True
else:
return other.af == self.af and other.prefixlen == self.prefixlen and other.prefix == self.prefix
def __add__(self, other):
"""
Add a value to this ip prefix.
:param int other: value to add
:return: added ip prefix instance
:rtype: IpPrefix
"""
try:
tmp = int(other)
except ValueError:
@ -163,6 +289,13 @@ class IpPrefix(object):
return self.__class__(prefixstr)
def __sub__(self, other):
"""
Subtract value from this ip prefix.
:param int other: value to subtract
:return: subtracted ip prefix instance
:rtype: IpPrefix
"""
try:
tmp = -int(other)
except ValueError:
@ -172,11 +305,19 @@ class IpPrefix(object):
return self.__add__(tmp)
def addr(self, hostid):
"""
Create an ip address for a given host id.
:param hostid: host id for an ip address
:return: ip address
:rtype: IpAddress
"""
tmp = int(hostid)
if tmp in [-1, 0, 1] and self.addrlen == self.prefixlen:
return IpAddress(self.af, self.prefix)
if tmp == 0 or tmp > (1 << (self.addrlen - self.prefixlen)) - 1 or \
(self.af == AF_INET and tmp == (1 << (self.addrlen - self.prefixlen)) - 1):
if tmp == 0 or tmp > (1 << (self.addrlen - self.prefixlen)) - 1 or (
self.af == AF_INET and tmp == (1 << (self.addrlen - self.prefixlen)) - 1):
raise ValueError("invalid hostid for prefix %s: %s" % (self, hostid))
addr = ""
@ -191,21 +332,51 @@ class IpPrefix(object):
return IpAddress(self.af, addr)
def min_addr(self):
"""
Return the minimum ip address for this prefix.
:return: minimum ip address
:rtype: IpAddress
"""
return self.addr(1)
def max_addr(self):
"""
Return the maximum ip address for this prefix.
:return: maximum ip address
:rtype: IpAddress
"""
if self.af == AF_INET:
return self.addr((1 << (self.addrlen - self.prefixlen)) - 2)
else:
return self.addr((1 << (self.addrlen - self.prefixlen)) - 1)
def num_addr(self):
"""
Retrieve the number of ip addresses for this prefix.
:return: maximum number of ip addresses
:rtype: int
"""
return max(0, (1 << (self.addrlen - self.prefixlen)) - 2)
def prefix_str(self):
"""
Retrieve the prefix string for this ip address.
:return: prefix string
:rtype: str
"""
return "%s" % socket.inet_ntop(self.af, self.prefix)
def netmask_str(self):
"""
Retrieve the netmask string for this ip address.
:return: netmask string
:rtype: str
"""
addrbits = self.addrlen - self.prefixlen
netmask = ((1L << self.prefixlen) - 1) << addrbits
netmaskbytes = struct.pack("!L", netmask)
@ -213,26 +384,66 @@ class IpPrefix(object):
class Ipv4Prefix(IpPrefix):
"""
Provides an ipv4 specific class for ip prefixes.
"""
def __init__(self, prefixstr):
"""
Create a Ipv4Prefix instance.
:param str prefixstr: ip prefix
"""
IpPrefix.__init__(self, AF_INET, prefixstr)
class Ipv6Prefix(IpPrefix):
"""
Provides an ipv6 specific class for ip prefixes.
"""
def __init__(self, prefixstr):
"""
Create a Ipv6Prefix instance.
:param str prefixstr: ip prefix
"""
IpPrefix.__init__(self, AF_INET6, prefixstr)
def is_ip_address(af, addrstr):
"""
Check if ip address string is a valid ip address.
:param int af: address family
:param str addrstr: ip address string
:return: True if a valid ip address, False otherwise
:rtype: bool
"""
try:
tmp = socket.inet_pton(af, addrstr)
socket.inet_pton(af, addrstr)
return True
except:
except IOError:
return False
def is_ipv4_address(addrstr):
"""
Check if ipv4 address string is a valid ipv4 address.
:param str addrstr: ipv4 address string
:return: True if a valid ipv4 address, False otherwise
:rtype: bool
"""
return is_ip_address(AF_INET, addrstr)
def is_ipv6_address(addrstr):
"""
Check if ipv6 address string is a valid ipv6 address.
:param str addrstr: ipv6 address string
:return: True if a valid ipv6 address, False otherwise
:rtype: bool
"""
return is_ip_address(AF_INET6, addrstr)