Revision 89e1fc26

b/daemons/ganeti-master
35 35

  
36 36
import os
37 37
import sys
38
import socket
39 38

  
40 39
from optparse import OptionParser
41 40

  
......
150 149
  """
151 150
  options, args = ParseOptions()
152 151
  debug = options.debug
152
  try:
153
    myself = utils.HostInfo()
154
  except errors.ResolverError, err:
155
    sys.stderr.write("Cannot resolve my own name (%s)\n" % err.args[0])
156
    return EXIT_NODESETUP_ERROR
157

  
153 158
  result = CheckNodeSetup(debug)
154 159
  if not result:
155 160
    if debug:
......
157 162
    return EXIT_NODESETUP_ERROR
158 163

  
159 164
  master_node, master_netdev, master_ip = result
160
  if socket.gethostname() != master_node and args[0] == "start":
165
  if myself.name != master_node and args[0] == "start":
161 166
    if debug:
162 167
      sys.stderr.write("Not master, ignoring request.\n")
163 168
    return EXIT_NOTMASTER
b/daemons/ganeti-watcher
39 39
import time
40 40
import fcntl
41 41
import errno
42
import socket
43 42
from optparse import OptionParser
44 43

  
45 44

  
46 45
from ganeti import utils
47 46
from ganeti import constants
48 47
from ganeti import ssconf
48
from ganeti import errors
49 49

  
50 50

  
51 51
class Error(Exception):
......
263 263
  def __init__(self):
264 264
    sstore = ssconf.SimpleStore()
265 265
    master = sstore.GetMasterNode()
266
    if master != socket.gethostname():
266
    if master != utils.HostInfo().name:
267 267
      raise NotMasterError("This is not the master node")
268 268
    self.instances = InstanceList()
269 269
    self.messages = []
......
357 357
    if options.debug:
358 358
      sys.stderr.write("Not master, exiting.\n")
359 359
    sys.exit(constants.EXIT_NOTMASTER)
360
  except errors.ResolverError, err:
361
    sys.stderr.write("Cannot resolve hostname '%s', exiting.\n" % err.args[0])
362
    sys.exit(constants.EXIT_NODESETUP_ERROR)
360 363
  except Error, err:
361 364
    print err
362 365

  
b/lib/cli.py
296 296
    except errors.HooksFailure, err:
297 297
      logger.ToStderr("Failure: hooks general failure: %s" % str(err))
298 298
      result = 1
299
    except errors.ResolverError, err:
300
      this_host = utils.HostInfo.SysName()
301
      if err.args[0] == this_host:
302
        msg = "Failure: can't resolve my own hostname ('%s')"
303
      else:
304
        msg = "Failure: can't resolve hostname '%s'"
305
      logger.ToStderr(msg % err.args[0])
306
      result = 1
299 307
    except errors.OpPrereqError, err:
300 308
      logger.ToStderr("Failure: prerequisites not met for this"
301 309
                      " operation:\n%s" % str(err))
b/lib/cmdlib.py
85 85
                                   " use 'gnt-cluster init' first.")
86 86
      if self.REQ_MASTER:
87 87
        master = sstore.GetMasterNode()
88
        if master != socket.gethostname():
88
        if master != utils.HostInfo().name:
89 89
          raise errors.OpPrereqError("Commands must be run on the master"
90 90
                                     " node %s" % master)
91 91

  
......
558 558
    if config.ConfigWriter.IsCluster():
559 559
      raise errors.OpPrereqError("Cluster is already initialised")
560 560

  
561
    hostname_local = socket.gethostname()
562
    self.hostname = hostname = utils.LookupHostname(hostname_local)
563
    if not hostname:
564
      raise errors.OpPrereqError("Cannot resolve my own hostname ('%s')" %
565
                                 hostname_local)
566

  
567
    if hostname.name != hostname_local:
568
      raise errors.OpPrereqError("My own hostname (%s) does not match the"
569
                                 " resolver (%s): probably not using FQDN"
570
                                 " for hostname." %
571
                                 (hostname_local, hostname.name))
561
    self.hostname = hostname = utils.HostInfo()
572 562

  
573 563
    if hostname.ip.startswith("127."):
574 564
      raise errors.OpPrereqError("This host's IP resolves to the private"
575 565
                                 " range (%s). Please fix DNS or /etc/hosts." %
576 566
                                 (hostname.ip,))
577 567

  
578
    self.clustername = clustername = utils.LookupHostname(self.op.cluster_name)
579
    if not clustername:
580
      raise errors.OpPrereqError("Cannot resolve given cluster name ('%s')"
581
                                 % self.op.cluster_name)
568
    self.clustername = clustername = utils.HostInfo(self.op.cluster_name)
582 569

  
583 570
    result = utils.RunCmd(["fping", "-S127.0.0.1", "-q", hostname.ip])
584 571
    if result.failed:
......
961 948
    """Verify that the passed name is a valid one.
962 949

  
963 950
    """
964
    hostname = utils.LookupHostname(self.op.name)
965
    if not hostname:
966
      raise errors.OpPrereqError("Cannot resolve the new cluster name ('%s')" %
967
                                 self.op.name)
951
    hostname = utils.HostInfo(self.op.name)
968 952

  
969 953
    new_name = hostname.name
970 954
    self.ip = new_ip = hostname.ip
......
1404 1388
    node_name = self.op.node_name
1405 1389
    cfg = self.cfg
1406 1390

  
1407
    dns_data = utils.LookupHostname(node_name)
1408
    if not dns_data:
1409
      raise errors.OpPrereqError("Node %s is not resolvable" % node_name)
1391
    dns_data = utils.HostInfo(node_name)
1410 1392

  
1411 1393
    node = dns_data.name
1412 1394
    primary_ip = self.op.primary_ip = dns_data.ip
......
1614 1596
    This checks that we are not already the master.
1615 1597

  
1616 1598
    """
1617
    self.new_master = socket.gethostname()
1618

  
1599
    self.new_master = utils.HostInfo().name
1619 1600
    self.old_master = self.sstore.GetMasterNode()
1620 1601

  
1621 1602
    if self.old_master == self.new_master:
......
1716 1697
    """
1717 1698
    filename = self.op.filename
1718 1699

  
1719
    myname = socket.gethostname()
1700
    myname = utils.HostInfo().name
1720 1701

  
1721 1702
    for node in self.nodes:
1722 1703
      if node == myname:
......
2152 2133
    self.instance = instance
2153 2134

  
2154 2135
    # new name verification
2155
    hostname1 = utils.LookupHostname(self.op.new_name)
2156
    if not hostname1:
2157
      raise errors.OpPrereqError("New instance name '%s' not found in dns" %
2158
                                 self.op.new_name)
2136
    name_info = utils.HostInfo(self.op.new_name)
2159 2137

  
2160
    self.op.new_name = new_name = hostname1.name
2138
    self.op.new_name = new_name = name_info.name
2161 2139
    if not getattr(self.op, "ignore_ip", False):
2162
      command = ["fping", "-q", hostname1.ip]
2140
      command = ["fping", "-q", name_info.ip]
2163 2141
      result = utils.RunCmd(command)
2164 2142
      if not result.failed:
2165 2143
        raise errors.OpPrereqError("IP %s of instance %s already in use" %
2166
                                   (hostname1.ip, new_name))
2144
                                   (name_info.ip, new_name))
2167 2145

  
2168 2146

  
2169 2147
  def Exec(self, feedback_fn):
......
2839 2817
                                 " primary node"  % self.op.os_type)
2840 2818

  
2841 2819
    # instance verification
2842
    hostname1 = utils.LookupHostname(self.op.instance_name)
2843
    if not hostname1:
2844
      raise errors.OpPrereqError("Instance name '%s' not found in dns" %
2845
                                 self.op.instance_name)
2820
    hostname1 = utils.HostInfo(self.op.instance_name)
2846 2821

  
2847 2822
    self.op.instance_name = instance_name = hostname1.name
2848 2823
    instance_list = self.cfg.GetInstanceList()
b/lib/config.py
35 35
"""
36 36

  
37 37
import os
38
import socket
39 38
import tempfile
40 39
import random
41 40

  
......
78 77
    else:
79 78
      self._cfg_file = cfg_file
80 79
    self._temporary_ids = set()
80
    # Note: in order to prevent errors when resolving our name in
81
    # _DistributeConfig, we compute it here once and reuse it; it's
82
    # better to raise an error before starting to modify the config
83
    # file than after it was modified
84
    self._my_hostname = utils.HostInfo().name
81 85

  
82 86
  # this method needs to be static, so that we can call it on the class
83 87
  @staticmethod
......
527 531
      return True
528 532
    bad = False
529 533
    nodelist = self.GetNodeList()
530
    myhostname = socket.gethostname()
534
    myhostname = self._my_hostname
531 535

  
532 536
    tgt_list = []
533 537
    for node in nodelist:
b/lib/errors.py
151 151
  """
152 152

  
153 153

  
154
class ResolverError(GenericError):
155
  """Host name cannot be resolved.
156

  
157
  This is not a normal situation for Ganeti, as we rely on having a
158
  working resolver.
159

  
160
  The non-resolvable hostname is available as the first element of the
161
  args tuple; the other two elements of the tuple are the first two
162
  args of the socket.gaierror exception (error code and description).
163

  
164
  """
165

  
166

  
154 167
class HooksFailure(GenericError):
155 168
  """A generic hook failure.
156 169

  
b/lib/utils.py
397 397

  
398 398

  
399 399
class HostInfo:
400
  """Class holding host info as returned by gethostbyname
400
  """Class implementing resolver and hostname functionality
401 401

  
402 402
  """
403
  def __init__(self, name, aliases, ipaddrs):
403
  def __init__(self, name=None):
404 404
    """Initialize the host name object.
405 405

  
406
    Arguments are the same as returned by socket.gethostbyname_ex()
406
    If the name argument is not passed, it will use this system's
407
    name.
407 408

  
408 409
    """
409
    self.name = name
410
    self.aliases = aliases
411
    self.ipaddrs = ipaddrs
410
    if name is None:
411
      name = self.SysName()
412

  
413
    self.query = name
414
    self.name, self.aliases, self.ipaddrs = self.LookupHostname(name)
412 415
    self.ip = self.ipaddrs[0]
413 416

  
417
  @staticmethod
418
  def SysName():
419
    """Return the current system's name.
414 420

  
415
def LookupHostname(hostname):
416
  """Look up hostname
421
    This is simply a wrapper over socket.gethostname()
417 422

  
418
  Args:
419
    hostname: hostname to look up, can be also be a non FQDN
423
    """
424
    return socket.gethostname()
420 425

  
421
  Returns:
422
    a HostInfo object
426
  @staticmethod
427
  def LookupHostname(hostname):
428
    """Look up hostname
423 429

  
424
  """
425
  try:
426
    (name, aliases, ipaddrs) = socket.gethostbyname_ex(hostname)
427
  except socket.gaierror:
428
    # hostname not found in DNS
429
    return None
430
    Args:
431
      hostname: hostname to look up
432

  
433
    Returns:
434
      a tuple (name, aliases, ipaddrs) as returned by socket.gethostbyname_ex
435
      in case of errors in resolving, we raise a ResolverError
436

  
437
    """
438
    try:
439
      result = socket.gethostbyname_ex(hostname)
440
    except socket.gaierror, err:
441
      # hostname not found in DNS
442
      raise errors.ResolverError(hostname, err.args[0], err.args[1])
430 443

  
431
  return HostInfo(name, aliases, ipaddrs)
444
    return result
432 445

  
433 446

  
434 447
def ListVolumeGroups():
b/test/ganeti.config_unittest.py
54 54

  
55 55
  def _init_cluster(self, cfg):
56 56
    """Initializes the cfg object"""
57
    cfg.InitConfig(socket.gethostname(), '127.0.0.1', None, '', 'aa:00:00',
57
    cfg.InitConfig(utils.HostInfo().name, '127.0.0.1', None, '', 'aa:00:00',
58 58
                   'xenvg', constants.DEFAULT_BRIDGE)
59 59

  
60 60
  def _create_instance(self):
b/test/mocks.py
22 22
"""Module implementing a fake ConfigWriter"""
23 23

  
24 24
import socket
25
from ganeti import utils
25 26

  
26 27
class FakeConfig:
27 28
    """Fake configuration object"""
......
33 34
        return ["a", "b", "c"]
34 35

  
35 36
    def GetMaster(self):
36
        return socket.gethostname()
37
        return utils.HostInfo().name
37 38

  
38 39

  
39 40
class FakeSStore:
......
43 44
        return "test.cluster"
44 45

  
45 46
    def GetMasterNode(self):
46
        return socket.gethostname()
47
        return utils.HostInfo().name

Also available in: Unified diff