from ganeti import bdev
from ganeti import netutils
from ganeti import backend
+from ganeti import luxi
+
# ec_id for InitConfig's temporary reservation manager
_INITCONF_ECID = "initconfig-ecid"
+#: After how many seconds daemon must be responsive
+_DAEMON_READY_TIMEOUT = 10.0
+
def _InitSSHSetup():
"""Setup the SSH configuration for the cluster.
raise utils.RetryAgain()
try:
- utils.Retry(_CheckNodeDaemon, 1.0, 10.0)
+ utils.Retry(_CheckNodeDaemon, 1.0, _DAEMON_READY_TIMEOUT)
except utils.RetryTimeout:
raise errors.OpExecError("Node daemon on %s didn't answer queries within"
- " 10 seconds" % node_name)
+ " %s seconds" % (node_name, _DAEMON_READY_TIMEOUT))
+
+
+def _WaitForMasterDaemon():
+ """Wait for master daemon to become responsive.
+
+ """
+ def _CheckMasterDaemon():
+ try:
+ cl = luxi.Client()
+ (cluster_name, ) = cl.QueryConfigValues(["cluster_name"])
+ except Exception:
+ raise utils.RetryAgain()
+
+ logging.debug("Received cluster name %s from master", cluster_name)
+
+ try:
+ utils.Retry(_CheckMasterDaemon, 1.0, _DAEMON_READY_TIMEOUT)
+ except utils.RetryTimeout:
+ raise errors.OpExecError("Master daemon didn't answer queries within"
+ " %s seconds" % _DAEMON_READY_TIMEOUT)
def _InitFileStorage(file_storage_dir):
return file_storage_dir
-#pylint: disable-msg=R0913
-def InitCluster(cluster_name, mac_prefix,
+def InitCluster(cluster_name, mac_prefix, # pylint: disable-msg=R0913
master_netdev, file_storage_dir, candidate_pool_size,
secondary_ip=None, vg_name=None, beparams=None,
nicparams=None, hvparams=None, enabled_hypervisors=None,
modify_etc_hosts=True, modify_ssh_setup=True,
maintain_node_health=False, drbd_helper=None,
uid_pool=None, default_iallocator=None,
- primary_ip_version=None):
+ primary_ip_version=None, prealloc_wipe_disks=False):
"""Initialise the cluster.
@type candidate_pool_size: int
drbd_usermode_helper=drbd_helper,
default_iallocator=default_iallocator,
primary_ip_family=ipcls.family,
+ prealloc_wipe_disks=prealloc_wipe_disks,
)
master_node_config = objects.Node(name=hostname.name,
primary_ip=hostname.ip,
# set up the inter-node password and certificate
_InitGanetiServerSetup(hostname.name)
- # start the master ip
- # TODO: Review rpc call from bootstrap
- # TODO: Warn on failed start master
- rpc.RpcRunner.call_node_start_master(hostname.name, True, False)
+ logging.debug("Starting daemons")
+ result = utils.RunCmd([constants.DAEMON_UTIL, "start-all"])
+ if result.failed:
+ raise errors.OpExecError("Could not start daemons, command %s"
+ " had exitcode %s and error %s" %
+ (result.cmd, result.exit_code, result.output))
+
+ _WaitForMasterDaemon()
def InitConfig(version, cluster_config, master_node_config,
logging.info("Setting master to %s, old master: %s", new_master, old_master)
+ try:
+ # instantiate a real config writer, as we now know we have the
+ # configuration data
+ cfg = config.ConfigWriter(accept_foreign=True)
+
+ cluster_info = cfg.GetClusterInfo()
+ cluster_info.master_node = new_master
+ # this will also regenerate the ssconf files, since we updated the
+ # cluster info
+ cfg.Update(cluster_info, logging.error)
+ except errors.ConfigurationError, err:
+ logging.error("Error while trying to set the new master: %s",
+ str(err))
+ return 1
+
+ # if cfg.Update worked, then it means the old master daemon won't be
+ # able now to write its own config file (we rely on locking in both
+ # backend.UploadFile() and ConfigWriter._Write(); hence the next
+ # step is to kill the old master
+
+ logging.info("Stopping the master daemon on node %s", old_master)
+
result = rpc.RpcRunner.call_node_stop_master(old_master, True)
msg = result.fail_msg
if msg:
logging.error("Could not disable the master role on the old master"
" %s, please disable manually: %s", old_master, msg)
+ logging.info("Checking master IP non-reachability...")
+
master_ip = sstore.GetMasterIP()
total_timeout = 30
# Here we have a phase where no master should be running
" continuing but activating the master on the current"
" node will probably fail", total_timeout)
- # instantiate a real config writer, as we now know we have the
- # configuration data
- cfg = config.ConfigWriter()
-
- cluster_info = cfg.GetClusterInfo()
- cluster_info.master_node = new_master
- # this will also regenerate the ssconf files, since we updated the
- # cluster info
- cfg.Update(cluster_info, logging.error)
+ logging.info("Starting the master daemons on the new master")
result = rpc.RpcRunner.call_node_start_master(new_master, True, no_voting)
msg = result.fail_msg
" %s, please check: %s", new_master, msg)
rcode = 1
+ logging.info("Master failed over from %s to %s", old_master, new_master)
return rcode