Revision c06e0c83

b/lib/backend.py
246 246
  return (master_netdev, master_ip, master_node, primary_ip_family)
247 247

  
248 248

  
249
def StartMaster(start_daemons, no_voting):
249
def ActivateMasterIp():
250
  """Activate the IP address of the master daemon.
251

  
252
  """
253
  # GetMasterInfo will raise an exception if not able to return data
254
  master_netdev, master_ip, _, family = GetMasterInfo()
255

  
256
  err_msg = None
257
  if netutils.TcpPing(master_ip, constants.DEFAULT_NODED_PORT):
258
    if netutils.IPAddress.Own(master_ip):
259
      # we already have the ip:
260
      logging.debug("Master IP already configured, doing nothing")
261
    else:
262
      err_msg = "Someone else has the master ip, not activating"
263
      logging.error(err_msg)
264
  else:
265
    ipcls = netutils.IP4Address
266
    if family == netutils.IP6Address.family:
267
      ipcls = netutils.IP6Address
268

  
269
    result = utils.RunCmd([constants.IP_COMMAND_PATH, "address", "add",
270
                           "%s/%d" % (master_ip, ipcls.iplen),
271
                           "dev", master_netdev, "label",
272
                           "%s:0" % master_netdev])
273
    if result.failed:
274
      err_msg = "Can't activate master IP: %s" % result.output
275
      logging.error(err_msg)
276

  
277
    # we ignore the exit code of the following cmds
278
    if ipcls == netutils.IP4Address:
279
      utils.RunCmd(["arping", "-q", "-U", "-c 3", "-I", master_netdev, "-s",
280
                    master_ip, master_ip])
281
    elif ipcls == netutils.IP6Address:
282
      try:
283
        utils.RunCmd(["ndisc6", "-q", "-r 3", master_ip, master_netdev])
284
      except errors.OpExecError:
285
        # TODO: Better error reporting
286
        logging.warning("Can't execute ndisc6, please install if missing")
287

  
288
  if err_msg:
289
    _Fail(err_msg)
290

  
291

  
292
def StartMasterDaemons(no_voting):
250 293
  """Activate local node as master node.
251 294

  
252
  The function will either try activate the IP address of the master
253
  (unless someone else has it) or also start the master daemons, based
254
  on the start_daemons parameter.
295
  The function will start the master daemons (ganeti-masterd and ganeti-rapi).
255 296

  
256
  @type start_daemons: boolean
257
  @param start_daemons: whether to start the master daemons
258
      (ganeti-masterd and ganeti-rapi), or (if false) activate the
259
      master ip
260 297
  @type no_voting: boolean
261 298
  @param no_voting: whether to start ganeti-masterd without a node vote
262
      (if start_daemons is True), but still non-interactively
299
      but still non-interactively
263 300
  @rtype: None
264 301

  
265 302
  """
266
  # GetMasterInfo will raise an exception if not able to return data
267
  master_netdev, master_ip, _, family = GetMasterInfo()
268 303

  
269
  err_msgs = []
270
  # either start the master and rapi daemons
271
  if start_daemons:
272
    if no_voting:
273
      masterd_args = "--no-voting --yes-do-it"
274
    else:
275
      masterd_args = ""
276

  
277
    env = {
278
      "EXTRA_MASTERD_ARGS": masterd_args,
279
      }
280

  
281
    result = utils.RunCmd([constants.DAEMON_UTIL, "start-master"], env=env)
282
    if result.failed:
283
      msg = "Can't start Ganeti master: %s" % result.output
284
      logging.error(msg)
285
      err_msgs.append(msg)
286
  # or activate the IP
304
  if no_voting:
305
    masterd_args = "--no-voting --yes-do-it"
287 306
  else:
288
    if netutils.TcpPing(master_ip, constants.DEFAULT_NODED_PORT):
289
      if netutils.IPAddress.Own(master_ip):
290
        # we already have the ip:
291
        logging.debug("Master IP already configured, doing nothing")
292
      else:
293
        msg = "Someone else has the master ip, not activating"
294
        logging.error(msg)
295
        err_msgs.append(msg)
296
    else:
297
      ipcls = netutils.IP4Address
298
      if family == netutils.IP6Address.family:
299
        ipcls = netutils.IP6Address
300

  
301
      result = utils.RunCmd([constants.IP_COMMAND_PATH, "address", "add",
302
                             "%s/%d" % (master_ip, ipcls.iplen),
303
                             "dev", master_netdev, "label",
304
                             "%s:0" % master_netdev])
305
      if result.failed:
306
        msg = "Can't activate master IP: %s" % result.output
307
        logging.error(msg)
308
        err_msgs.append(msg)
309

  
310
      # we ignore the exit code of the following cmds
311
      if ipcls == netutils.IP4Address:
312
        utils.RunCmd(["arping", "-q", "-U", "-c 3", "-I", master_netdev, "-s",
313
                      master_ip, master_ip])
314
      elif ipcls == netutils.IP6Address:
315
        try:
316
          utils.RunCmd(["ndisc6", "-q", "-r 3", master_ip, master_netdev])
317
        except errors.OpExecError:
318
          # TODO: Better error reporting
319
          logging.warning("Can't execute ndisc6, please install if missing")
320

  
321
  if err_msgs:
322
    _Fail("; ".join(err_msgs))
307
    masterd_args = ""
323 308

  
309
  env = {
310
    "EXTRA_MASTERD_ARGS": masterd_args,
311
    }
324 312

  
325
def StopMaster(stop_daemons):
326
  """Deactivate this node as master.
313
  result = utils.RunCmd([constants.DAEMON_UTIL, "start-master"], env=env)
314
  if result.failed:
315
    msg = "Can't start Ganeti master: %s" % result.output
316
    logging.error(msg)
317
    _Fail(msg)
327 318

  
328
  The function will always try to deactivate the IP address of the
329
  master. It will also stop the master daemons depending on the
330
  stop_daemons parameter.
331 319

  
332
  @type stop_daemons: boolean
333
  @param stop_daemons: whether to also stop the master daemons
334
      (ganeti-masterd and ganeti-rapi)
335
  @rtype: None
320
def DeactivateMasterIp():
321
  """Deactivate the master IP on this node.
336 322

  
337 323
  """
338 324
  # TODO: log and report back to the caller the error failures; we
......
352 338
    logging.error("Can't remove the master IP, error: %s", result.output)
353 339
    # but otherwise ignore the failure
354 340

  
355
  if stop_daemons:
356
    result = utils.RunCmd([constants.DAEMON_UTIL, "stop-master"])
357
    if result.failed:
358
      logging.error("Could not stop Ganeti master, command %s had exitcode %s"
359
                    " and error %s",
360
                    result.cmd, result.exit_code, result.output)
341

  
342
def StopMasterDaemons():
343
  """Stop the master daemons on this node.
344

  
345
  Stop the master daemons (ganeti-masterd and ganeti-rapi) on this node.
346

  
347
  @rtype: None
348

  
349
  """
350
  # TODO: log and report back to the caller the error failures; we
351
  # need to decide in which case we fail the RPC for this
352

  
353
  result = utils.RunCmd([constants.DAEMON_UTIL, "stop-master"])
354
  if result.failed:
355
    logging.error("Could not stop Ganeti master, command %s had exitcode %s"
356
                  " and error %s",
357
                  result.cmd, result.exit_code, result.output)
361 358

  
362 359

  
363 360
def EtcHostsModify(mode, host, ip):
b/lib/bootstrap.py
560 560
  """
561 561
  cfg = config.ConfigWriter()
562 562
  modify_ssh_setup = cfg.GetClusterInfo().modify_ssh_setup
563
  result = rpc.RpcRunner.call_node_stop_master(master, True)
563
  result = rpc.RpcRunner.call_node_stop_master(master)
564 564
  msg = result.fail_msg
565 565
  if msg:
566 566
    logging.warning("Could not disable the master role: %s", msg)
......
692 692

  
693 693
  logging.info("Stopping the master daemon on node %s", old_master)
694 694

  
695
  result = rpc.RpcRunner.call_node_stop_master(old_master, True)
695
  result = rpc.RpcRunner.call_node_stop_master(old_master)
696 696
  msg = result.fail_msg
697 697
  if msg:
698 698
    logging.error("Could not disable the master role on the old master"
......
721 721

  
722 722
  logging.info("Starting the master daemons on the new master")
723 723

  
724
  result = rpc.RpcRunner.call_node_start_master(new_master, True, no_voting)
724
  result = rpc.RpcRunner.call_node_start_master_daemons(new_master, no_voting)
725 725
  msg = result.fail_msg
726 726
  if msg:
727 727
    logging.error("Could not start the master role on the new master"
b/lib/cmdlib.py
1355 1355
    # Run post hooks on master node before it's removed
1356 1356
    _RunPostHook(self, master)
1357 1357

  
1358
    result = self.rpc.call_node_stop_master(master, False)
1358
    result = self.rpc.call_node_deactivate_master_ip(master)
1359 1359
    result.Raise("Could not disable the master role")
1360 1360

  
1361 1361
    return master
......
3297 3297

  
3298 3298
    # shutdown the master IP
3299 3299
    master = self.cfg.GetMasterNode()
3300
    result = self.rpc.call_node_stop_master(master, False)
3300
    result = self.rpc.call_node_deactivate_master_ip(master)
3301 3301
    result.Raise("Could not disable the master role")
3302 3302

  
3303 3303
    try:
......
3315 3315
        pass
3316 3316
      _UploadHelper(self, node_list, constants.SSH_KNOWN_HOSTS_FILE)
3317 3317
    finally:
3318
      result = self.rpc.call_node_start_master(master, False, False)
3318
      result = self.rpc.call_node_activate_master_ip(master)
3319 3319
      msg = result.fail_msg
3320 3320
      if msg:
3321 3321
        self.LogWarning("Could not re-enable the master role on"
......
3648 3648
      master = self.cfg.GetMasterNode()
3649 3649
      feedback_fn("Shutting down master ip on the current netdev (%s)" %
3650 3650
                  self.cluster.master_netdev)
3651
      result = self.rpc.call_node_stop_master(master, False)
3651
      result = self.rpc.call_node_deactivate_master_ip(master)
3652 3652
      result.Raise("Could not disable the master ip")
3653 3653
      feedback_fn("Changing master_netdev from %s to %s" %
3654 3654
                  (self.cluster.master_netdev, self.op.master_netdev))
......
3659 3659
    if self.op.master_netdev:
3660 3660
      feedback_fn("Starting the master ip on the new master netdev (%s)" %
3661 3661
                  self.op.master_netdev)
3662
      result = self.rpc.call_node_start_master(master, False, False)
3662
      result = self.rpc.call_node_activate_master_ip(master)
3663 3663
      if result.fail_msg:
3664 3664
        self.LogWarning("Could not re-enable the master ip on"
3665 3665
                        " the master, please restart manually: %s",
b/lib/rpc.py
919 919

  
920 920
  @classmethod
921 921
  @_RpcTimeout(_TMO_FAST)
922
  def call_node_start_master(cls, node, start_daemons, no_voting):
923
    """Tells a node to activate itself as a master.
922
  def call_node_start_master_daemons(cls, node, no_voting):
923
    """Starts master daemons on a node.
924 924

  
925 925
    This is a single-node call.
926 926

  
927 927
    """
928
    return cls._StaticSingleNodeCall(node, "node_start_master",
929
                                     [start_daemons, no_voting])
928
    return cls._StaticSingleNodeCall(node, "node_start_master_daemons",
929
                                     [no_voting])
930 930

  
931 931
  @classmethod
932 932
  @_RpcTimeout(_TMO_FAST)
933
  def call_node_stop_master(cls, node, stop_daemons):
934
    """Tells a node to demote itself from master status.
933
  def call_node_activate_master_ip(cls, node):
934
    """Activates master IP on a node.
935 935

  
936 936
    This is a single-node call.
937 937

  
938 938
    """
939
    return cls._StaticSingleNodeCall(node, "node_stop_master", [stop_daemons])
939
    return cls._StaticSingleNodeCall(node, "node_activate_master_ip", [])
940

  
941
  @classmethod
942
  @_RpcTimeout(_TMO_FAST)
943
  def call_node_stop_master(cls, node):
944
    """Deactivates master IP and stops master daemons on a node.
945

  
946
    This is a single-node call.
947

  
948
    """
949
    return cls._StaticSingleNodeCall(node, "node_stop_master", [])
950

  
951
  @classmethod
952
  @_RpcTimeout(_TMO_FAST)
953
  def call_node_deactivate_master_ip(cls, node):
954
    """Deactivates master IP on a node.
955

  
956
    This is a single-node call.
957

  
958
    """
959
    return cls._StaticSingleNodeCall(node, "node_deactivate_master_ip", [])
940 960

  
941 961
  @classmethod
942 962
  @_RpcTimeout(_TMO_URGENT)
b/lib/server/masterd.py
524 524
def ActivateMasterIP():
525 525
  # activate ip
526 526
  master_node = ssconf.SimpleStore().GetMasterNode()
527
  result = rpc.RpcRunner.call_node_start_master(master_node, False, False)
527
  result = rpc.RpcRunner.call_node_activate_master_ip(master_node)
528 528
  msg = result.fail_msg
529 529
  if msg:
530 530
    logging.error("Can't activate master IP address: %s", msg)
b/lib/server/noded.py
677 677
    return backend.VerifyNode(params[0], params[1])
678 678

  
679 679
  @staticmethod
680
  def perspective_node_start_master(params):
681
    """Promote this node to master status.
680
  def perspective_node_start_master_daemons(params):
681
    """Start the master daemons on this node.
682 682

  
683 683
    """
684
    return backend.StartMaster(params[0], params[1])
684
    return backend.StartMasterDaemons(params[0])
685

  
686
  @staticmethod
687
  def perspective_node_activate_master_ip(params):
688
    """Activate the master IP on this node.
689

  
690
    """
691
    return backend.ActivateMasterIp()
692

  
693
  @staticmethod
694
  def perspective_node_deactivate_master_ip(params):
695
    """Deactivate the master IP on this node.
696

  
697
    """
698
    return backend.DeactivateMasterIp()
685 699

  
686 700
  @staticmethod
687 701
  def perspective_node_stop_master(params):
688
    """Demote this node from master status.
702
    """Deactivate the master IP and stops master daemons on this node.
703

  
704
    Sometimes both operations need to be executed at the same time (doing one of
705
    the two would make impossible to do the other one).
689 706

  
690 707
    """
691
    return backend.StopMaster(params[0])
708
    backend.DeactivateMasterIp()
709
    return backend.StopMasterDaemons()
692 710

  
693 711
  @staticmethod
694 712
  def perspective_node_leave_cluster(params):

Also available in: Unified diff