@param family: AF_INET | AF_INET6 | None
@rtype: L{Hostname}
@return: Hostname object
- @raise: errors.OpPrereqError
+ @raise errors.OpPrereqError: in case of errors in resolving
"""
try:
"""Class implementing resolver and hostname functionality.
"""
+ _VALID_NAME_RE = re.compile("^[a-z0-9._-]{1,255}$")
+
def __init__(self, name=None, family=None):
"""Initialize the host name object.
@param name: hostname or None
"""
- if name is None:
- name = self.GetSysName()
-
- self.name = self.GetNormalizedName(name)
+ self.name = self.GetNormalizedName(self.GetFqdn(name))
self.ip = self.GetIP(self.name, family=family)
+ @classmethod
+ def GetSysName(cls):
+ """Legacy method the get the current system's name.
+
+ """
+ return cls.GetFqdn()
+
@staticmethod
- def GetSysName():
- """Return the current system's name.
+ def GetFqdn(hostname=None):
+ """Return fqdn.
- This is simply a wrapper over C{socket.gethostname()}.
+ If hostname is None the system's fqdn is returned.
+
+ @type hostname: str
+ @param hostname: name to be fqdn'ed
+ @rtype: str
+ @return: fqdn of given name, if it exists, unmodified name otherwise
"""
- return socket.gethostname()
+ if hostname is None:
+ return socket.getfqdn()
+ else:
+ return socket.getfqdn(hostname)
@staticmethod
def GetIP(hostname, family=None):
if family in (socket.AF_INET, socket.AF_INET6):
result = socket.getaddrinfo(hostname, None, family)
else:
- result = socket.getaddrinfo(hostname, None, socket.AF_INET)
+ result = socket.getaddrinfo(hostname, None)
except (socket.gaierror, socket.herror, socket.error), err:
# hostname not found in DNS, or other socket exception in the
# (code, description format)
# getaddrinfo() returns a list of 5-tupes (family, socktype, proto,
# canonname, sockaddr). We return the first tuple's first address in
# sockaddr
- return result[0][4][0]
+ try:
+ return result[0][4][0]
+ except IndexError, err:
+ raise errors.ResolverError("Unknown error in getaddrinfo(): %s" % err)
- @staticmethod
- def GetNormalizedName(hostname):
+ @classmethod
+ def GetNormalizedName(cls, hostname):
"""Validate and normalize the given hostname.
@attention: the validation is a bit more relaxed than the standards
@raise errors.OpPrereqError: when the name is not valid
"""
- valid_name_re = re.compile("^[a-z0-9._-]{1,255}$")
hostname = hostname.lower()
- if (not valid_name_re.match(hostname) or
+ if (not cls._VALID_NAME_RE.match(hostname) or
# double-dots, meaning empty label
".." in hostname or
# empty initial label
to it.
@type target: str
- @param target: the IP or hostname to ping
+ @param target: the IP to ping
@type port: int
@param port: the port to connect to
@type timeout: int
"""Get integer value of IPv4 address.
@type address: str
- @param: IPv6 address
+ @param address: IPv6 address
@rtype: int
@return: integer value of given IP address
"""Get integer value of IPv6 address.
@type address: str
- @param: IPv6 address
+ @param address: IPv6 address
@rtype: int
@return: integer value of given IP address
address_int = (address_int << 16) + int(part or '0', 16)
return address_int
+
+
+def FormatAddress(address, family=None):
+ """Format a socket address
+
+ @type address: family specific (usually tuple)
+ @param address: address, as reported by this class
+ @type family: integer
+ @param family: socket family (one of socket.AF_*) or None
+
+ """
+ if family is None:
+ try:
+ family = IPAddress.GetAddressFamily(address[0])
+ except errors.IPAddressError:
+ raise errors.ParameterError(address)
+
+ if family == socket.AF_UNIX and len(address) == 3:
+ return "pid=%s, uid=%s, gid=%s" % address
+
+ if family in (socket.AF_INET, socket.AF_INET6) and len(address) == 2:
+ host, port = address
+ if family == socket.AF_INET6:
+ res = "[%s]" % host
+ else:
+ res = host
+
+ if port is not None:
+ res += ":%s" % port
+
+ return res
+
+ raise errors.ParameterError(family, address)