Revision 313b2dd4

b/lib/backend.py
551 551
      tmpr.append("The procfs filesystem doesn't seem to be mounted"
552 552
                  " under /proc, missing required directory /proc/sys and"
553 553
                  " the file /proc/sysrq-trigger")
554

  
555
  if constants.NV_TIME in what:
556
    result[constants.NV_TIME] = utils.SplitTime(time.time())
557

  
554 558
  return result
555 559

  
556 560

  
b/lib/cmdlib.py
944 944
  ENODESSH = (TNODE, "ENODESSH")
945 945
  ENODEVERSION = (TNODE, "ENODEVERSION")
946 946
  ENODESETUP = (TNODE, "ENODESETUP")
947
  ENODETIME = (TNODE, "ENODETIME")
947 948

  
948 949
  ETYPE_FIELD = "code"
949 950
  ETYPE_ERROR = "ERROR"
......
1326 1327
      constants.NV_VERSION: None,
1327 1328
      constants.NV_HVINFO: self.cfg.GetHypervisorType(),
1328 1329
      constants.NV_NODESETUP: None,
1330
      constants.NV_TIME: None,
1329 1331
      }
1332

  
1330 1333
    if vg_name is not None:
1331 1334
      node_verify_param[constants.NV_VGLIST] = None
1332 1335
      node_verify_param[constants.NV_LVLIST] = vg_name
1333 1336
      node_verify_param[constants.NV_PVLIST] = [vg_name]
1334 1337
      node_verify_param[constants.NV_DRBDLIST] = None
1338

  
1339
    # Due to the way our RPC system works, exact response times cannot be
1340
    # guaranteed (e.g. a broken node could run into a timeout). By keeping the
1341
    # time before and after executing the request, we can at least have a time
1342
    # window.
1343
    nvinfo_starttime = time.time()
1335 1344
    all_nvinfo = self.rpc.call_node_verify(nodelist, node_verify_param,
1336 1345
                                           self.cfg.GetClusterName())
1346
    nvinfo_endtime = time.time()
1337 1347

  
1338 1348
    cluster = self.cfg.GetClusterInfo()
1339 1349
    master_node = self.cfg.GetMasterNode()
......
1380 1390
        else:
1381 1391
          instance = instanceinfo[instance]
1382 1392
          node_drbd[minor] = (instance.name, instance.admin_up)
1393

  
1383 1394
      self._VerifyNode(node_i, file_names, local_checksums,
1384 1395
                       nresult, master_files, node_drbd, vg_name)
1385 1396

  
......
1413 1424
      if test:
1414 1425
        continue
1415 1426

  
1427
      # Node time
1428
      ntime = nresult.get(constants.NV_TIME, None)
1429
      try:
1430
        ntime_merged = utils.MergeTime(ntime)
1431
      except (ValueError, TypeError):
1432
        _ErrorIf(test, self.ENODETIME, node, "Node returned invalid time")
1433

  
1434
      if ntime_merged < (nvinfo_starttime - constants.NODE_MAX_CLOCK_SKEW):
1435
        ntime_diff = abs(nvinfo_starttime - ntime_merged)
1436
      elif ntime_merged > (nvinfo_endtime + constants.NODE_MAX_CLOCK_SKEW):
1437
        ntime_diff = abs(ntime_merged - nvinfo_endtime)
1438
      else:
1439
        ntime_diff = None
1440

  
1441
      _ErrorIf(ntime_diff is not None, self.ENODETIME, node,
1442
               "Node time diverges by at least %0.1fs from master node time",
1443
               ntime_diff)
1444

  
1445
      if ntime_diff is not None:
1446
        continue
1447

  
1416 1448
      try:
1417 1449
        node_info[node] = {
1418 1450
          "mfree": int(nodeinfo['memory_free']),
b/lib/constants.py
320 320
LVM_STRIPECOUNT = _autoconf.LVM_STRIPECOUNT
321 321
# default maximum instance wait time, in seconds.
322 322
DEFAULT_SHUTDOWN_TIMEOUT = 120
323

  
323
NODE_MAX_CLOCK_SKEW = 150
324 324

  
325 325
# RPC constants
326 326
(RPC_ENCODING_NONE,
......
526 526
NV_PVLIST = "pvlist"
527 527
NV_DRBDLIST = "drbd-list"
528 528
NV_NODESETUP = "nodesetup"
529
NV_TIME = "time"
529 530

  
530 531
# Allocator framework constants
531 532
IALLOCATOR_VERSION = 2
......
722 723
# Each request is "salted" by the current timestamp.
723 724
# This constants decides how many seconds of skew to accept.
724 725
# TODO: make this a default and allow the value to be more configurable
725
CONFD_MAX_CLOCK_SKEW = 300
726
CONFD_MAX_CLOCK_SKEW = 2 * NODE_MAX_CLOCK_SKEW
726 727

  
727 728
# When we haven't reloaded the config for more than this amount of seconds, we
728 729
# force a test to see if inotify is betraying us.
b/test/ganeti.constants_unittest.py
60 60
    self.failUnless(constants.LDS_OKAY < constants.LDS_UNKNOWN)
61 61
    self.failUnless(constants.LDS_UNKNOWN < constants.LDS_FAULTY)
62 62

  
63
  def testClockSkew(self):
64
    self.failUnless(constants.NODE_MAX_CLOCK_SKEW <
65
                    (0.8 * constants.CONFD_MAX_CLOCK_SKEW))
66

  
63 67

  
64 68
class TestParameterNames(unittest.TestCase):
65 69
  """HV/BE parameter tests"""
......
81 85

  
82 86
  def testFourCc(self):
83 87
    self.failUnlessEqual(len(constants.CONFD_MAGIC_FOURCC), 4,
84
                    "Invalid fourcc len, should be 4")
88
                         "Invalid fourcc len, should be 4")
85 89

  
86 90
  def _IsUniqueSequence(self, sequence):
87 91
    seen = set()

Also available in: Unified diff