On Wed, Apr 08, 2015 at 01:32:57PM +0200, 'Klaus Aehlig' via ganeti-devel wrote:
commit a3514e86527a3369757a95418298b102c4abc0d5 Merge: 6b7ecdc 8351486 Author: Klaus Aehlig <[email protected]> Date: Wed Apr 8 13:18:34 2015 +0200 Merge branch 'stable-2.11' into stable-2.12 * stable-2.11 (no changes) * stable-2.10 fix typos in design-file-based-storage.rst doc Switch to our osminor Provide an alternative for os.minor working around its bug Fix typo CanTieredAlloc test: make instances big enough After master-failover verify reachability of master IP Report failure to deactivate old master IP in exit code Expose warnings during master-failover Fix manpage for gnt-cluster copyfile Conflicts: lib/bootstrap.py: adapt function to new IO specification lib/utils/storage.py: trivial Signed-off-by: Klaus Aehlig <[email protected]> diff --cc lib/bootstrap.py index a083f87,bb9b473..8a75548 --- a/lib/bootstrap.py +++ b/lib/bootstrap.py @@@ -1085,41 -1052,38 +1087,47 @@@ def MasterFailover(no_voting=False) # this will also regenerate the ssconf files, since we updated the # cluster info cfg.Update(cluster_info, logging.error) + + # 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) + + runner = rpc.BootstrapRunner() + master_params = cfg.GetMasterNetworkParameters() + master_params.uuid = old_master_node.uuid + ems = cfg.GetUseExternalMipScript() + result = runner.call_node_deactivate_master_ip(old_master, + master_params, ems) + + msg = result.fail_msg + if msg: - logging.warning("Could not disable the master IP: %s", msg) ++ warning = "Could not disable the master IP: %s" % (msg,) ++ logging.warning("%s", warning) ++ warnings.append(warning) + + result = runner.call_node_stop_master(old_master) + 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) ++ warning = ("Could not disable the master role on the old master" ++ " %s, please disable manually: %s" % (old_master, msg)) ++ logging.error("%s", warning) ++ warnings.append(warning) 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) - - runner = rpc.BootstrapRunner() - master_params = cfg.GetMasterNetworkParameters() - master_params.uuid = old_master_node.uuid - ems = cfg.GetUseExternalMipScript() - result = runner.call_node_deactivate_master_ip(old_master, - master_params, ems) - - msg = result.fail_msg - if msg: - warning = "Could not disable the master IP: %s" % (msg,) - logging.warning("%s", warning) - warnings.append(warning) - - result = runner.call_node_stop_master(old_master) - msg = result.fail_msg - if msg: - warning = ("Could not disable the master role on the old master" - " %s, please disable manually: %s" % (old_master, msg)) - logging.error("%s", warning) - warnings.append(warning) ++ return 1, warnings + finally: + # stop WConfd again: + result = utils.RunCmd([pathutils.DAEMON_UTIL, "stop", constants.WCONFD]) + if result.failed: - logging.error("Could not stop the configuration daemon," - " command %s had exitcode %s and error %s", - result.cmd, result.exit_code, result.output) ++ warning = ("Could not stop the configuration daemon," ++ " command %s had exitcode %s and error %s" ++ % (result.cmd, result.exit_code, result.output)) ++ logging.error("%s", warning) ++ rcode = 1 logging.info("Checking master IP non-reachability...") diff --cc lib/utils/storage.py index 6e3ac87,ca488ed..e742d5e --- a/lib/utils/storage.py +++ b/lib/utils/storage.py @@@ -184,34 -184,11 +184,44 @@@ def LookupSpaceInfoByStorageType(storag return result +def GetDiskLabels(prefix, num_disks, start=0): + """Generate disk labels for a number of disks + + Note that disk labels are generated in the range [start..num_disks[ + (e.g., as in range(start, num_disks)) + + @type prefix: string + @param prefix: disk label prefix (e.g., "/dev/sd") + + @type num_disks: int + @param num_disks: number of disks (i.e., disk labels) + + @type start: int + @param start: optional start index + + @rtype: generator + @return: generator for the disk labels + + """ + def _GetDiskSuffix(i): + n = ord('z') - ord('a') + 1 + if i < n: + return chr(ord('a') + i) + else: + mod = int(i % n) + pref = _GetDiskSuffix((i - mod) / (n + 1)) + suf = _GetDiskSuffix(mod) + return pref + suf + + for i in range(start, num_disks): + yield prefix + _GetDiskSuffix(i) ++ ++ + def osminor(dev): + """Return the device minor number from a raw device number. + + This is a replacement for os.minor working around the issue that + Python's os.minor still has the old definition. See Ganeti issue + 1058 for more details. + """ + return (dev & 0xff) | ((dev >> 12) & ~0xff) -- Klaus Aehlig Google Germany GmbH, Dienerstr. 12, 80331 Muenchen Registergericht und -nummer: Hamburg, HRB 86891 Sitz der Gesellschaft: Hamburg Geschaeftsfuehrer: Graham Law, Christine Elizabeth Flores
LGTM, thanks
