Revision 21232d04
b/lib/cmdlib.py | ||
---|---|---|
3797 | 3797 |
class LUSetNodeParams(LogicalUnit): |
3798 | 3798 |
"""Modifies the parameters of a node. |
3799 | 3799 |
|
3800 |
@cvar _F2R: a dictionary from tuples of flags (mc, drained, offline) |
|
3801 |
to the node role (as _ROLE_*) |
|
3802 |
@cvar _R2F: a dictionary from node role to tuples of flags |
|
3803 |
@cvar _FLAGS: a list of attribute names corresponding to the flags |
|
3804 |
|
|
3800 | 3805 |
""" |
3801 | 3806 |
HPATH = "node-modify" |
3802 | 3807 |
HTYPE = constants.HTYPE_NODE |
... | ... | |
3809 | 3814 |
_PForce, |
3810 | 3815 |
] |
3811 | 3816 |
REQ_BGL = False |
3817 |
(_ROLE_CANDIDATE, _ROLE_DRAINED, _ROLE_OFFLINE, _ROLE_REGULAR) = range(4) |
|
3818 |
_F2R = { |
|
3819 |
(True, False, False): _ROLE_CANDIDATE, |
|
3820 |
(False, True, False): _ROLE_DRAINED, |
|
3821 |
(False, False, True): _ROLE_OFFLINE, |
|
3822 |
(False, False, False): _ROLE_REGULAR, |
|
3823 |
} |
|
3824 |
_R2F = dict((v, k) for k, v in _F2R.items()) |
|
3825 |
_FLAGS = ["master_candidate", "drained", "offline"] |
|
3812 | 3826 |
|
3813 | 3827 |
def CheckArguments(self): |
3814 | 3828 |
self.op.node_name = _ExpandNodeName(self.cfg, self.op.node_name) |
3815 | 3829 |
all_mods = [self.op.offline, self.op.master_candidate, self.op.drained] |
3816 |
if all_mods.count(None) == 3:
|
|
3830 |
if all_mods.count(None) == len(all_mods):
|
|
3817 | 3831 |
raise errors.OpPrereqError("Please pass at least one modification", |
3818 | 3832 |
errors.ECODE_INVAL) |
3819 | 3833 |
if all_mods.count(True) > 1: |
... | ... | |
3821 | 3835 |
" state at the same time", |
3822 | 3836 |
errors.ECODE_INVAL) |
3823 | 3837 |
|
3824 |
# Boolean value that tells us whether we're offlining or draining the node |
|
3825 |
self.offline_or_drain = (self.op.offline == True or |
|
3826 |
self.op.drained == True) |
|
3827 |
self.deoffline_or_drain = (self.op.offline == False or |
|
3828 |
self.op.drained == False) |
|
3838 |
# Boolean value that tells us whether we might be demoting from MC |
|
3829 | 3839 |
self.might_demote = (self.op.master_candidate == False or |
3830 |
self.offline_or_drain) |
|
3840 |
self.op.offline == True or |
|
3841 |
self.op.drained == True) |
|
3831 | 3842 |
|
3832 | 3843 |
self.lock_all = self.op.auto_promote and self.might_demote |
3833 | 3844 |
|
3834 |
|
|
3835 | 3845 |
def ExpandNames(self): |
3836 | 3846 |
if self.lock_all: |
3837 | 3847 |
self.needed_locks = {locking.LEVEL_NODE: locking.ALL_SET} |
... | ... | |
3881 | 3891 |
if mc_remaining < mc_should: |
3882 | 3892 |
raise errors.OpPrereqError("Not enough master candidates, please" |
3883 | 3893 |
" pass auto_promote to allow promotion", |
3884 |
errors.ECODE_INVAL)
|
|
3894 |
errors.ECODE_STATE)
|
|
3885 | 3895 |
|
3886 |
if (self.op.master_candidate == True and |
|
3887 |
((node.offline and not self.op.offline == False) or |
|
3888 |
(node.drained and not self.op.drained == False))): |
|
3889 |
raise errors.OpPrereqError("Node '%s' is offline or drained, can't set" |
|
3890 |
" to master_candidate" % node.name, |
|
3891 |
errors.ECODE_INVAL) |
|
3896 |
self.old_flags = old_flags = (node.master_candidate, |
|
3897 |
node.drained, node.offline) |
|
3898 |
assert old_flags in self._F2R, "Un-handled old flags %s" % str(old_flags) |
|
3899 |
self.old_role = self._F2R[old_flags] |
|
3892 | 3900 |
|
3893 |
# If we're being deofflined/drained, we'll MC ourself if needed |
|
3894 |
if (self.deoffline_or_drain and not self.offline_or_drain and not |
|
3895 |
self.op.master_candidate == True and not node.master_candidate): |
|
3896 |
self.op.master_candidate = _DecideSelfPromotion(self) |
|
3897 |
if self.op.master_candidate: |
|
3898 |
self.LogInfo("Autopromoting node to master candidate") |
|
3901 |
# Check for ineffective changes |
|
3902 |
for attr in self._FLAGS: |
|
3903 |
if (getattr(self.op, attr) == False and getattr(node, attr) == False): |
|
3904 |
self.LogInfo("Ignoring request to unset flag %s, already unset", attr) |
|
3905 |
setattr(self.op, attr, None) |
|
3899 | 3906 |
|
3900 |
return |
|
3907 |
# Past this point, any flag change to False means a transition |
|
3908 |
# away from the respective state, as only real changes are kept |
|
3909 |
|
|
3910 |
# If we're being deofflined/drained, we'll MC ourself if needed |
|
3911 |
if self.op.drained == False or self.op.offline == False: |
|
3912 |
if _DecideSelfPromotion(self): |
|
3913 |
self.op.master_candidate = True |
|
3914 |
self.LogInfo("Auto-promoting node to master candidate") |
|
3901 | 3915 |
|
3902 | 3916 |
def Exec(self, feedback_fn): |
3903 | 3917 |
"""Modifies a node. |
3904 | 3918 |
|
3905 | 3919 |
""" |
3906 | 3920 |
node = self.node |
3921 |
old_role = self.old_role |
|
3922 |
|
|
3923 |
assert [getattr(self.op, attr) for attr in self._FLAGS].count(True) <= 1 |
|
3924 |
|
|
3925 |
# compute new flags |
|
3926 |
if self.op.master_candidate: |
|
3927 |
new_role = self._ROLE_CANDIDATE |
|
3928 |
elif self.op.drained: |
|
3929 |
new_role = self._ROLE_DRAINED |
|
3930 |
elif self.op.offline: |
|
3931 |
new_role = self._ROLE_OFFLINE |
|
3932 |
elif False in [self.op.master_candidate, self.op.drained, self.op.offline]: |
|
3933 |
# False is still in new flags, which means we're un-setting (the |
|
3934 |
# only) True flag |
|
3935 |
new_role = self._ROLE_REGULAR |
|
3936 |
else: # no new flags, nothing, keep old role |
|
3937 |
new_role = old_role |
|
3907 | 3938 |
|
3908 | 3939 |
result = [] |
3909 |
changed_mc = False |
|
3910 |
|
|
3911 |
if self.op.offline is not None: |
|
3912 |
node.offline = self.op.offline |
|
3913 |
result.append(("offline", str(self.op.offline))) |
|
3914 |
if self.op.offline == True: |
|
3915 |
if node.master_candidate: |
|
3916 |
node.master_candidate = False |
|
3917 |
changed_mc = True |
|
3918 |
result.append(("master_candidate", "auto-demotion due to offline")) |
|
3919 |
if node.drained: |
|
3920 |
node.drained = False |
|
3921 |
result.append(("drained", "clear drained status due to offline")) |
|
3922 |
|
|
3923 |
if self.op.master_candidate is not None: |
|
3924 |
node.master_candidate = self.op.master_candidate |
|
3925 |
changed_mc = True |
|
3926 |
result.append(("master_candidate", str(self.op.master_candidate))) |
|
3927 |
if self.op.master_candidate == False: |
|
3928 |
rrc = self.rpc.call_node_demote_from_mc(node.name) |
|
3929 |
msg = rrc.fail_msg |
|
3930 |
if msg: |
|
3931 |
self.LogWarning("Node failed to demote itself: %s" % msg) |
|
3932 |
|
|
3933 |
if self.op.drained is not None: |
|
3934 |
node.drained = self.op.drained |
|
3935 |
result.append(("drained", str(self.op.drained))) |
|
3936 |
if self.op.drained == True: |
|
3937 |
if node.master_candidate: |
|
3938 |
node.master_candidate = False |
|
3939 |
changed_mc = True |
|
3940 |
result.append(("master_candidate", "auto-demotion due to drain")) |
|
3941 |
rrc = self.rpc.call_node_demote_from_mc(node.name) |
|
3942 |
msg = rrc.fail_msg |
|
3943 |
if msg: |
|
3944 |
self.LogWarning("Node failed to demote itself: %s" % msg) |
|
3945 |
if node.offline: |
|
3946 |
node.offline = False |
|
3947 |
result.append(("offline", "clear offline status due to drain")) |
|
3940 |
changed_mc = [old_role, new_role].count(self._ROLE_CANDIDATE) == 1 |
|
3941 |
|
|
3942 |
# Tell the node to demote itself, if no longer MC and not offline |
|
3943 |
if (old_role == self._ROLE_CANDIDATE and |
|
3944 |
new_role != self._ROLE_OFFLINE and new_role != old_role): |
|
3945 |
msg = self.rpc.call_node_demote_from_mc(node.name).fail_msg |
|
3946 |
if msg: |
|
3947 |
self.LogWarning("Node failed to demote itself: %s", msg) |
|
3948 |
|
|
3949 |
new_flags = self._R2F[new_role] |
|
3950 |
for of, nf, desc in zip(self.old_flags, new_flags, self._FLAGS): |
|
3951 |
if of != nf: |
|
3952 |
result.append((desc, str(nf))) |
|
3953 |
(node.master_candidate, node.drained, node.offline) = new_flags |
|
3948 | 3954 |
|
3949 | 3955 |
# we locked all nodes, we adjust the CP before updating this node |
3950 | 3956 |
if self.lock_all: |
Also available in: Unified diff