This patch enables IPv6 name resolution by using socket.getaddrinfo
instead of socket.gethostbyname_ex.

It renames the HostInfo class to Hostname and unifies its use throughout
the code. This is achieved by using static calls where no object is
needed and removes some obsolete code.

For now, we just resolve to IPv4 addresses, but this will change once it
is needed.

Signed-off-by: Manuel Franceschini <livew...@google.com>
---
Resending with recent modifications due to finalizing IPv6 support. The
Hostname object can now be initiatlized with
family={None|AF_INET|AF_INET6}. If None then GetIP will return the first
address of getaddrinfo() independent of the address family, otherwise
only addresses of the given family will be considered.
 
 daemons/ganeti-masterd           |    4 +-
 daemons/ganeti-watcher           |    6 +-
 daemons/import-export            |    2 +-
 lib/backend.py                   |    6 +-
 lib/bootstrap.py                 |    7 +--
 lib/cli.py                       |    2 +-
 lib/cmdlib.py                    |   29 ++++++--------
 lib/config.py                    |    2 +-
 lib/jqueue.py                    |    2 +-
 lib/masterd/instance.py          |    2 +-
 lib/netutils.py                  |   77 ++++++++++++++++++++++----------------
 lib/rpc.py                       |   24 ++++--------
 lib/ssconf.py                    |    4 +-
 lib/utils.py                     |    9 ++--
 scripts/gnt-node                 |    3 +-
 test/ganeti.backend_unittest.py  |    3 +-
 test/ganeti.config_unittest.py   |    4 +-
 test/ganeti.netutils_unittest.py |   18 ++++----
 test/ganeti.rpc_unittest.py      |    4 +-
 test/mocks.py                    |    4 +-
 20 files changed, 106 insertions(+), 106 deletions(-)

diff --git a/daemons/ganeti-masterd b/daemons/ganeti-masterd
index 784a871..5328862 100755
--- a/daemons/ganeti-masterd
+++ b/daemons/ganeti-masterd
@@ -1,7 +1,7 @@
 #!/usr/bin/python
 #
 
-# Copyright (C) 2006, 2007, 2010 Google Inc.
+# Copyright (C) 2006, 2007, 2010 Google Inc.
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -423,7 +423,7 @@ def CheckAgreement():
   other node to be up too to confirm our status.
 
   """
-  myself = netutils.HostInfo().name
+  myself = netutils.Hostname.GetSysName()
   #temp instantiation of a config writer, used only to get the node list
   cfg = config.ConfigWriter()
   node_list = cfg.GetNodeList()
diff --git a/daemons/ganeti-watcher b/daemons/ganeti-watcher
index 1a57d3b..60ed04a 100755
--- a/daemons/ganeti-watcher
+++ b/daemons/ganeti-watcher
@@ -1,7 +1,7 @@
 #!/usr/bin/python
 #
 
-# Copyright (C) 2006, 2007, 2008, 2010 Google Inc.
+# Copyright (C) 2006, 2007, 2008, 2010 Google Inc.
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -215,7 +215,7 @@ class NodeMaintenance(object):
     """Check node status versus cluster desired state.
 
     """
-    my_name = netutils.HostInfo().name
+    my_name = netutils.Hostname.GetSysName()
     req = confd_client.ConfdClientRequest(type=
                                           constants.CONFD_REQ_NODE_ROLE_BYNAME,
                                           query=my_name)
@@ -466,7 +466,7 @@ class Watcher(object):
   def __init__(self, opts, notepad):
     self.notepad = notepad
     master = client.QueryConfigValues(["master_node"])[0]
-    if master != netutils.HostInfo().name:
+    if master != netutils.Hostname.GetSysName():
       raise NotMasterError("This is not the master node")
     # first archive old jobs
     self.ArchiveJobs(opts.job_age)
diff --git a/daemons/import-export b/daemons/import-export
index 02a5ad1..ce9c3bd 100755
--- a/daemons/import-export
+++ b/daemons/import-export
@@ -408,7 +408,7 @@ def ParseOptions():
   # Normalize and check parameters
   if options.host is not None:
     try:
-      options.host = netutils.HostInfo.NormalizeName(options.host)
+      options.host = netutils.Hostname.GetNormalizedName(options.host)
     except errors.OpPrereqError, err:
       parser.error("Invalid hostname '%s': %s" % (options.host, err))
 
diff --git a/lib/backend.py b/lib/backend.py
index 1ec723d..b872591 100644
--- a/lib/backend.py
+++ b/lib/backend.py
@@ -490,7 +490,7 @@ def VerifyNode(what, cluster_name):
 
   """
   result = {}
-  my_name = netutils.HostInfo().name
+  my_name = netutils.Hostname.GetSysName()
   port = netutils.GetDaemonPort(constants.NODED)
 
   if constants.NV_HYPERVISOR in what:
@@ -2595,7 +2595,7 @@ def CreateX509Certificate(validity, 
cryptodir=constants.CRYPTO_KEYS_DIR):
 
   """
   (key_pem, cert_pem) = \
-    utils.GenerateSelfSignedX509Cert(netutils.HostInfo.SysName(),
+    utils.GenerateSelfSignedX509Cert(netutils.Hostname.GetSysName(),
                                      min(validity, _MAX_SSL_CERT_VALIDITY))
 
   cert_dir = tempfile.mkdtemp(dir=cryptodir,
@@ -2938,7 +2938,7 @@ def _FindDisks(nodes_ip, disks):
 
   """
   # set the correct physical ID
-  my_name = netutils.HostInfo().name
+  my_name = netutils.Hostname.GetSysName()
   for cf in disks:
     cf.SetPhysicalID(my_name, nodes_ip)
 
diff --git a/lib/bootstrap.py b/lib/bootstrap.py
index f3319df..392d409 100644
--- a/lib/bootstrap.py
+++ b/lib/bootstrap.py
@@ -243,7 +243,7 @@ def InitCluster(cluster_name, mac_prefix,
                                " entries: %s" % invalid_hvs,
                                errors.ECODE_INVAL)
 
-  hostname = netutils.GetHostInfo()
+  hostname = netutils.GetHostname()
 
   if netutils.IP4Address.IsLoopback(hostname.ip):
     raise errors.OpPrereqError("This host's IP (%s) resolves to a loopback"
@@ -257,8 +257,7 @@ def InitCluster(cluster_name, mac_prefix,
                                " belong to this host. Aborting." %
                                hostname.ip, errors.ECODE_ENVIRON)
 
-  clustername = \
-    netutils.GetHostInfo(netutils.HostInfo.NormalizeName(cluster_name))
+  clustername = netutils.GetHostname(name=cluster_name)
 
   if netutils.TcpPing(clustername.ip, constants.DEFAULT_NODED_PORT,
                    timeout=5):
@@ -646,7 +645,7 @@ def GatherMasterVotes(node_list):
   @return: list of (node, votes)
 
   """
-  myself = netutils.HostInfo().name
+  myself = netutils.Hostname.GetSysName()
   try:
     node_list.remove(myself)
   except ValueError:
diff --git a/lib/cli.py b/lib/cli.py
index 4e6da39..fb1f15f 100644
--- a/lib/cli.py
+++ b/lib/cli.py
@@ -1648,7 +1648,7 @@ def FormatError(err):
   elif isinstance(err, errors.HooksFailure):
     obuf.write("Failure: hooks general failure: %s" % msg)
   elif isinstance(err, errors.ResolverError):
-    this_host = netutils.HostInfo.SysName()
+    this_host = netutils.Hostname.GetSysName()
     if err.args[0] == this_host:
       msg = "Failure: can't resolve my own hostname ('%s')"
     else:
diff --git a/lib/cmdlib.py b/lib/cmdlib.py
index 7861104..c15e890 100644
--- a/lib/cmdlib.py
+++ b/lib/cmdlib.py
@@ -2524,7 +2524,7 @@ class LURenameCluster(LogicalUnit):
     """Verify that the passed name is a valid one.
 
     """
-    hostname = netutils.GetHostInfo(self.op.name)
+    hostname = netutils.GetHostname(name=self.op.name)
 
     new_name = hostname.name
     self.ip = new_ip = hostname.ip
@@ -3671,7 +3671,7 @@ class LUAddNode(LogicalUnit):
 
   def CheckArguments(self):
     # validate/normalize the node name
-    self.op.node_name = netutils.HostInfo.NormalizeName(self.op.node_name)
+    self.op.node_name = netutils.Hostname.GetNormalizedName(self.op.node_name)
 
   def BuildHooksEnv(self):
     """Build hooks env.
@@ -3700,13 +3700,11 @@ class LUAddNode(LogicalUnit):
     Any errors are signaled by raising errors.OpPrereqError.
 
     """
-    node_name = self.op.node_name
+    hostname = netutils.GetHostname(name=self.op.node_name)
+    node = hostname.name
     cfg = self.cfg
 
-    dns_data = netutils.GetHostInfo(node_name)
-
-    node = dns_data.name
-    primary_ip = self.op.primary_ip = dns_data.ip
+    primary_ip = self.op.primary_ip = hostname.ip
     if self.op.secondary_ip is None:
       self.op.secondary_ip = primary_ip
     if not netutils.IP4Address.IsValid(self.op.secondary_ip):
@@ -4912,12 +4910,12 @@ class LURenameInstance(LogicalUnit):
 
     new_name = self.op.new_name
     if self.op.name_check:
-      hostinfo = netutils.HostInfo(netutils.HostInfo.NormalizeName(new_name))
-      new_name = hostinfo.name
+      hostname = netutils.GetHostname(name=new_name)
+      new_name = hostname.name
       if (self.op.ip_check and
-          netutils.TcpPing(hostinfo.ip, constants.DEFAULT_NODED_PORT)):
+          netutils.TcpPing(hostname.ip, constants.DEFAULT_NODED_PORT)):
         raise errors.OpPrereqError("IP %s of instance %s already in use" %
-                                   (hostinfo.ip, new_name),
+                                   (hostname.ip, new_name),
                                    errors.ECODE_NOTUNIQUE)
 
     instance_list = self.cfg.GetInstanceList()
@@ -4925,7 +4923,6 @@ class LURenameInstance(LogicalUnit):
       raise errors.OpPrereqError("Instance '%s' is already in the cluster" %
                                  new_name, errors.ECODE_EXISTS)
 
-
   def Exec(self, feedback_fn):
     """Reinstall the instance.
 
@@ -6534,7 +6531,7 @@ class LUCreateInstance(LogicalUnit):
       self.op.start = False
     # validate/normalize the instance name
     self.op.instance_name = \
-      netutils.HostInfo.NormalizeName(self.op.instance_name)
+      netutils.Hostname.GetNormalizedName(self.op.instance_name)
 
     if self.op.ip_check and not self.op.name_check:
       # TODO: make the ip check more flexible and not depend on the name check
@@ -6573,7 +6570,7 @@ class LUCreateInstance(LogicalUnit):
 
     # instance name verification
     if self.op.name_check:
-      self.hostname1 = netutils.GetHostInfo(self.op.instance_name)
+      self.hostname1 = netutils.GetHostname(name=self.op.instance_name)
       self.op.instance_name = self.hostname1.name
       # used in CheckPrereq for ip ping check
       self.check_ip = self.hostname1.ip
@@ -6653,8 +6650,8 @@ class LUCreateInstance(LogicalUnit):
         raise errors.OpPrereqError("Missing source instance name",
                                    errors.ECODE_INVAL)
 
-      norm_name = netutils.HostInfo.NormalizeName(src_instance_name)
-      self.source_instance_name = netutils.GetHostInfo(norm_name).name
+      self.source_instance_name = \
+          netutils.GetHostname(name=src_instance_name).name
 
     else:
       raise errors.OpPrereqError("Invalid instance creation mode %r" %
diff --git a/lib/config.py b/lib/config.py
index 16acc10..c1cdb78 100644
--- a/lib/config.py
+++ b/lib/config.py
@@ -151,7 +151,7 @@ class ConfigWriter:
     # _DistributeConfig, we compute it here once and reuse it; it's
     # better to raise an error before starting to modify the config
     # file than after it was modified
-    self._my_hostname = netutils.HostInfo().name
+    self._my_hostname = netutils.Hostname.GetSysName()
     self._last_cluster_serial = -1
     self._OpenConfig()
 
diff --git a/lib/jqueue.py b/lib/jqueue.py
index ebb6bf7..13171dc 100644
--- a/lib/jqueue.py
+++ b/lib/jqueue.py
@@ -849,7 +849,7 @@ class JobQueue(object):
     """
     self.context = context
     self._memcache = weakref.WeakValueDictionary()
-    self._my_hostname = netutils.HostInfo().name
+    self._my_hostname = netutils.Hostname.GetSysName()
 
     # The Big JobQueue lock. If a code block or method acquires it in shared
     # mode safe it must guarantee concurrency with all the code acquiring it in
diff --git a/lib/masterd/instance.py b/lib/masterd/instance.py
index 4f21725..a15baf9 100644
--- a/lib/masterd/instance.py
+++ b/lib/masterd/instance.py
@@ -1554,7 +1554,7 @@ def CheckRemoteExportDiskInfo(cds, disk_index, disk_info):
   if not utils.VerifySha1Hmac(cds, msg, hmac_digest, salt=hmac_salt):
     raise errors.GenericError("HMAC is wrong")
 
-  return (netutils.HostInfo.NormalizeName(host),
+  return (netutils.Hostname.GetNormalizedName(host),
           utils.ValidateServiceName(port),
           magic)
 
diff --git a/lib/netutils.py b/lib/netutils.py
index f5f5bb1..edbebb4 100644
--- a/lib/netutils.py
+++ b/lib/netutils.py
@@ -62,44 +62,48 @@ def GetSocketCredentials(sock):
   return struct.unpack(_STRUCT_UCRED, peercred)
 
 
-def GetHostInfo(name=None):
-  """Lookup host name and raise an OpPrereqError for failures"""
+def GetHostname(name=None, family=None):
+  """Returns a Hostname object.
 
+  @type name: str
+  @param name: hostname or None
+  @type family: int
+  @param family: AF_INET | AF_INET6 | None
+  @rtype: L{Hostname}
+  @return: Hostname object
+  @raise: errors.OpPrereqError
+
+  """
   try:
-    return HostInfo(name)
+    return Hostname(name=name, family=family)
   except errors.ResolverError, err:
     raise errors.OpPrereqError("The given name (%s) does not resolve: %s" %
                                (err[0], err[2]), errors.ECODE_RESOLVER)
 
 
-class HostInfo:
-  """Class implementing resolver and hostname functionality
+class Hostname:
+  """Class implementing resolver and hostname functionality.
 
   """
-  _VALID_NAME_RE = re.compile("^[a-z0-9._-]{1,255}$")
-
-  def __init__(self, name=None):
+  def __init__(self, name=None, family=None):
     """Initialize the host name object.
 
-    If the name argument is not passed, it will use this system's
-    name.
+    If the name argument is None, it will use this system's name.
+
+    @type family: int
+    @param family: AF_INET | AF_INET6 | None
+    @type name: str
+    @param name: hostname or None
 
     """
     if name is None:
-      name = self.SysName()
-
-    self.query = name
-    self.name, self.aliases, self.ipaddrs = self.LookupHostname(name)
-    self.ip = self.ipaddrs[0]
+      name = self.GetSysName()
 
-  def ShortName(self):
-    """Returns the hostname without domain.
-
-    """
-    return self.name.split('.')[0]
+    self.name = self.GetNormalizedName(name)
+    self.ip = self.GetIP(self.name, family=family)
 
   @staticmethod
-  def SysName():
+  def GetSysName():
     """Return the current system's name.
 
     This is simply a wrapper over C{socket.gethostname()}.
@@ -108,29 +112,37 @@ class HostInfo:
     return socket.gethostname()
 
   @staticmethod
-  def LookupHostname(hostname):
-    """Look up hostname
+  def GetIP(hostname, family=None):
+    """Return IP address of given hostname.
+
+    Supports both IPv4 and IPv6.
 
     @type hostname: str
     @param hostname: hostname to look up
-
-    @rtype: tuple
-    @return: a tuple (name, aliases, ipaddrs) as returned by
-        C{socket.gethostbyname_ex}
+    @type family: int
+    @param family: AF_INET | AF_INET6 | None
+    @rtype: str
+    @return: IP address
     @raise errors.ResolverError: in case of errors in resolving
 
     """
     try:
-      result = socket.gethostbyname_ex(hostname)
+      if family in (socket.AF_INET, socket.AF_INET6):
+        result = socket.getaddrinfo(hostname, None, family)
+      else:
+        result = socket.getaddrinfo(hostname, None, socket.AF_INET)
     except (socket.gaierror, socket.herror, socket.error), err:
       # hostname not found in DNS, or other socket exception in the
       # (code, description format)
       raise errors.ResolverError(hostname, err.args[0], err.args[1])
 
-    return result
+    # 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]
 
-  @classmethod
-  def NormalizeName(cls, hostname):
+  @staticmethod
+  def GetNormalizedName(hostname):
     """Validate and normalize the given hostname.
 
     @attention: the validation is a bit more relaxed than the standards
@@ -138,8 +150,9 @@ class HostInfo:
     @raise errors.OpPrereqError: when the name is not valid
 
     """
+    valid_name_re = re.compile("^[a-z0-9._-]{1,255}$")
     hostname = hostname.lower()
-    if (not cls._VALID_NAME_RE.match(hostname) or
+    if (not valid_name_re.match(hostname) or
         # double-dots, meaning empty label
         ".." in hostname or
         # empty initial label
diff --git a/lib/rpc.py b/lib/rpc.py
index 2b26e62..e31a529 100644
--- a/lib/rpc.py
+++ b/lib/rpc.py
@@ -259,7 +259,7 @@ class RpcResult(object):
 
 def _AddressLookup(node_list,
                    ssc=ssconf.SimpleStore,
-                   nslookup_fn=netutils.HostInfo.LookupHostname):
+                   nslookup_fn=netutils.Hostname.GetIP):
   """Return addresses for given node names.
 
   @type node_list: list
@@ -272,22 +272,14 @@ def _AddressLookup(node_list,
   @returns: List of corresponding addresses, if found
 
   """
-  def _NSLookup(name):
-    _, _, addrs = nslookup_fn(name)
-    return addrs[0]
-
+  iplist = ssc().GetNodePrimaryIPList()
   addresses = []
-  try:
-    iplist = ssc().GetNodePrimaryIPList()
-    ipmap = dict(entry.split() for entry in iplist)
-    for node in node_list:
-      address = ipmap.get(node)
-      if address is None:
-        address = _NSLookup(node)
-      addresses.append(address)
-  except errors.ConfigurationError:
-    # Address not found in so we do a NS lookup
-    addresses = [_NSLookup(node) for node in node_list]
+  ipmap = dict(entry.split() for entry in iplist)
+  for node in node_list:
+    address = ipmap.get(node)
+    if address is None:
+      address = nslookup_fn(node)
+    addresses.append(address)
 
   return addresses
 
diff --git a/lib/ssconf.py b/lib/ssconf.py
index c29d63c..6ed9d12 100644
--- a/lib/ssconf.py
+++ b/lib/ssconf.py
@@ -1,7 +1,7 @@
 #
 #
 
-# Copyright (C) 2006, 2007, 2008, 2010 Google Inc.
+# Copyright (C) 2006, 2007, 2008, 2010 Google Inc.
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -478,7 +478,7 @@ def GetMasterAndMyself(ss=None):
   """
   if ss is None:
     ss = SimpleStore()
-  return ss.GetMasterNode(), netutils.HostInfo().name
+  return ss.GetMasterNode(), netutils.Hostname.GetSysName()
 
 
 def CheckMaster(debug, ss=None):
diff --git a/lib/utils.py b/lib/utils.py
index 441e5bb..51886c0 100644
--- a/lib/utils.py
+++ b/lib/utils.py
@@ -1461,8 +1461,8 @@ def AddHostToEtcHosts(hostname):
       L{constants.ETC_HOSTS}
 
   """
-  hi = netutils.HostInfo(name=hostname)
-  SetEtcHostsEntry(constants.ETC_HOSTS, hi.ip, hi.name, [hi.ShortName()])
+  SetEtcHostsEntry(constants.ETC_HOSTS, netutils.Hostname.GetIP(hostname),
+                   hostname, [hostname.split(".")[0]])
 
 
 def RemoveEtcHostsEntry(file_name, hostname):
@@ -1518,9 +1518,8 @@ def RemoveHostFromEtcHosts(hostname):
       L{constants.ETC_HOSTS}
 
   """
-  hi = netutils.HostInfo(name=hostname)
-  RemoveEtcHostsEntry(constants.ETC_HOSTS, hi.name)
-  RemoveEtcHostsEntry(constants.ETC_HOSTS, hi.ShortName())
+  RemoveEtcHostsEntry(constants.ETC_HOSTS, hostname)
+  RemoveEtcHostsEntry(constants.ETC_HOSTS, hostname.split(".")[0])
 
 
 def TimestampForFilename():
diff --git a/scripts/gnt-node b/scripts/gnt-node
index b3d911f..2b65c49 100755
--- a/scripts/gnt-node
+++ b/scripts/gnt-node
@@ -135,8 +135,7 @@ def AddNode(opts, args):
 
   """
   cl = GetClient()
-  dns_data = netutils.GetHostInfo(netutils.HostInfo.NormalizeName(args[0]))
-  node = dns_data.name
+  node = netutils.GetHostname(name=args[0]).name
   readd = opts.readd
 
   try:
diff --git a/test/ganeti.backend_unittest.py b/test/ganeti.backend_unittest.py
index fa81dd4..ff9a33c 100755
--- a/test/ganeti.backend_unittest.py
+++ b/test/ganeti.backend_unittest.py
@@ -74,7 +74,8 @@ class TestX509Certificates(unittest.TestCase):
 class TestNodeVerify(testutils.GanetiTestCase):
   def testMasterIPLocalhost(self):
     # this a real functional test, but requires localhost to be reachable
-    local_data = (netutils.HostInfo().name, constants.IP4_ADDRESS_LOCALHOST)
+    local_data = (netutils.Hostname.GetSysName(),
+                  constants.IP4_ADDRESS_LOCALHOST)
     result = backend.VerifyNode({constants.NV_MASTERIP: local_data}, None)
     self.failUnless(constants.NV_MASTERIP in result,
                     "Master IP data not returned")
diff --git a/test/ganeti.config_unittest.py b/test/ganeti.config_unittest.py
index 48aa590..32a8cb8 100755
--- a/test/ganeti.config_unittest.py
+++ b/test/ganeti.config_unittest.py
@@ -1,7 +1,7 @@
 #!/usr/bin/python
 #
 
-# Copyright (C) 2006, 2007, 2010 Google Inc.
+# Copyright (C) 2006, 2007, 2010 Google Inc.
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -60,7 +60,7 @@ class TestConfigRunner(unittest.TestCase):
 
   def _init_cluster(self, cfg):
     """Initializes the cfg object"""
-    me = netutils.HostInfo()
+    me = netutils.Hostname()
     ip = constants.IP4_ADDRESS_LOCALHOST
 
     cluster_config = objects.Cluster(
diff --git a/test/ganeti.netutils_unittest.py b/test/ganeti.netutils_unittest.py
index 71c93c5..3dbb5d4 100755
--- a/test/ganeti.netutils_unittest.py
+++ b/test/ganeti.netutils_unittest.py
@@ -102,21 +102,21 @@ class TestGetSocketCredentials(unittest.TestCase):
     self.assertEqual(gid, os.getgid())
 
 
-class TestHostInfo(unittest.TestCase):
-  """Testing case for HostInfo"""
+class TestHostname(unittest.TestCase):
+  """Testing case for Hostname"""
 
   def testUppercase(self):
     data = "AbC.example.com"
-    self.failUnlessEqual(netutils.HostInfo.NormalizeName(data), data.lower())
+    self.assertEqual(netutils.Hostname.GetNormalizedName(data), data.lower())
 
   def testTooLongName(self):
     data = "a.b." + "c" * 255
-    self.failUnlessRaises(errors.OpPrereqError,
-                          netutils.HostInfo.NormalizeName, data)
+    self.assertRaises(errors.OpPrereqError,
+                      netutils.Hostname.GetNormalizedName, data)
 
   def testTrailingDot(self):
     data = "a.b.c"
-    self.failUnlessEqual(netutils.HostInfo.NormalizeName(data + "."), data)
+    self.assertEqual(netutils.Hostname.GetNormalizedName(data + "."), data)
 
   def testInvalidName(self):
     data = [
@@ -126,8 +126,8 @@ class TestHostInfo(unittest.TestCase):
       "a..b",
       ]
     for value in data:
-      self.failUnlessRaises(errors.OpPrereqError,
-                            netutils.HostInfo.NormalizeName, value)
+      self.assertRaises(errors.OpPrereqError,
+                        netutils.Hostname.GetNormalizedName, value)
 
   def testValidName(self):
     data = [
@@ -137,7 +137,7 @@ class TestHostInfo(unittest.TestCase):
       "a.b.c",
       ]
     for value in data:
-      netutils.HostInfo.NormalizeName(value)
+      self.assertEqual(netutils.Hostname.GetNormalizedName(value), value)
 
 
 class TestIPAddress(unittest.TestCase):
diff --git a/test/ganeti.rpc_unittest.py b/test/ganeti.rpc_unittest.py
index d59d790..0453702 100755
--- a/test/ganeti.rpc_unittest.py
+++ b/test/ganeti.rpc_unittest.py
@@ -248,7 +248,7 @@ class TestClient(unittest.TestCase):
     node_list = ["node%d.example.com" % n for n in range(0, 255, 13)]
     ssc = GetFakeSimpleStoreClass(lambda s: [])
     node_addr_map = dict(zip(node_list, addr_list))
-    nslookup_fn = lambda name: (None, None, [node_addr_map.get(name)])
+    nslookup_fn = lambda name: node_addr_map.get(name)
     result = rpc._AddressLookup(node_list, ssc=ssc, nslookup_fn=nslookup_fn)
     self.assertEqual(result, addr_list)
 
@@ -259,7 +259,7 @@ class TestClient(unittest.TestCase):
     node_addr_list = [ " ".join(t) for t in zip(node_list[n:], addr_list[n:])]
     ssc = GetFakeSimpleStoreClass(lambda s: node_addr_list)
     node_addr_map = dict(zip(node_list[:n], addr_list[:n]))
-    nslookup_fn = lambda name: (None, None, [node_addr_map.get(name)])
+    nslookup_fn = lambda name: node_addr_map.get(name)
     result = rpc._AddressLookup(node_list, ssc=ssc, nslookup_fn=nslookup_fn)
     self.assertEqual(result, addr_list)
 
diff --git a/test/mocks.py b/test/mocks.py
index 1450ad1..b2fb139 100644
--- a/test/mocks.py
+++ b/test/mocks.py
@@ -1,7 +1,7 @@
 #
 #
 
-# Copyright (C) 2006, 2007, 2010 Google Inc.
+# Copyright (C) 2006, 2007, 2010 Google Inc.
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -50,7 +50,7 @@ class FakeConfig:
         return "test.cluster"
 
     def GetMasterNode(self):
-        return netutils.HostInfo().name
+        return netutils.Hostname.GetSysName()
 
     def GetDefaultIAllocator(Self):
         return "testallocator"
-- 
1.7.1

Reply via email to