Revision 08f8c82c lib/cmdlib.py
b/lib/cmdlib.py | ||
---|---|---|
11875 | 11875 |
return self.op.new_name |
11876 | 11876 |
|
11877 | 11877 |
|
11878 |
class LUGroupEvacuate(LogicalUnit): |
|
11879 |
HPATH = "group-evacuate" |
|
11880 |
HTYPE = constants.HTYPE_GROUP |
|
11881 |
REQ_BGL = False |
|
11882 |
|
|
11883 |
def ExpandNames(self): |
|
11884 |
# This raises errors.OpPrereqError on its own: |
|
11885 |
self.group_uuid = self.cfg.LookupNodeGroup(self.op.group_name) |
|
11886 |
|
|
11887 |
if self.op.target_groups: |
|
11888 |
self.req_target_uuids = map(self.cfg.LookupNodeGroup, |
|
11889 |
self.op.target_groups) |
|
11890 |
else: |
|
11891 |
self.req_target_uuids = [] |
|
11892 |
|
|
11893 |
if self.group_uuid in self.req_target_uuids: |
|
11894 |
raise errors.OpPrereqError("Group to be evacuated (%s) can not be used" |
|
11895 |
" as a target group (targets are %s)" % |
|
11896 |
(self.group_uuid, |
|
11897 |
utils.CommaJoin(self.req_target_uuids)), |
|
11898 |
errors.ECODE_INVAL) |
|
11899 |
|
|
11900 |
if not self.op.iallocator: |
|
11901 |
# Use default iallocator |
|
11902 |
self.op.iallocator = self.cfg.GetDefaultIAllocator() |
|
11903 |
|
|
11904 |
if not self.op.iallocator: |
|
11905 |
raise errors.OpPrereqError("No iallocator was specified, neither in the" |
|
11906 |
" opcode nor as a cluster-wide default", |
|
11907 |
errors.ECODE_INVAL) |
|
11908 |
|
|
11909 |
self.share_locks = dict.fromkeys(locking.LEVELS, 1) |
|
11910 |
self.needed_locks = { |
|
11911 |
locking.LEVEL_INSTANCE: [], |
|
11912 |
locking.LEVEL_NODEGROUP: [], |
|
11913 |
locking.LEVEL_NODE: [], |
|
11914 |
} |
|
11915 |
|
|
11916 |
def DeclareLocks(self, level): |
|
11917 |
if level == locking.LEVEL_INSTANCE: |
|
11918 |
assert not self.needed_locks[locking.LEVEL_INSTANCE] |
|
11919 |
|
|
11920 |
# Lock instances optimistically, needs verification once node and group |
|
11921 |
# locks have been acquired |
|
11922 |
self.needed_locks[locking.LEVEL_INSTANCE] = \ |
|
11923 |
self.cfg.GetNodeGroupInstances(self.group_uuid) |
|
11924 |
|
|
11925 |
elif level == locking.LEVEL_NODEGROUP: |
|
11926 |
assert not self.needed_locks[locking.LEVEL_NODEGROUP] |
|
11927 |
|
|
11928 |
if self.req_target_uuids: |
|
11929 |
lock_groups = set([self.group_uuid] + self.req_target_uuids) |
|
11930 |
|
|
11931 |
# Lock all groups used by instances optimistically; this requires going |
|
11932 |
# via the node before it's locked, requiring verification later on |
|
11933 |
lock_groups.update(group_uuid |
|
11934 |
for instance_name in |
|
11935 |
self.glm.list_owned(locking.LEVEL_INSTANCE) |
|
11936 |
for group_uuid in |
|
11937 |
self.cfg.GetInstanceNodeGroups(instance_name)) |
|
11938 |
else: |
|
11939 |
# No target groups, need to lock all of them |
|
11940 |
lock_groups = locking.ALL_SET |
|
11941 |
|
|
11942 |
self.needed_locks[locking.LEVEL_NODEGROUP] = lock_groups |
|
11943 |
|
|
11944 |
elif level == locking.LEVEL_NODE: |
|
11945 |
# This will only lock the nodes in the group to be evacuated which |
|
11946 |
# contain actual instances |
|
11947 |
self.recalculate_locks[locking.LEVEL_NODE] = constants.LOCKS_APPEND |
|
11948 |
self._LockInstancesNodes() |
|
11949 |
|
|
11950 |
# Lock all nodes in group to be evacuated |
|
11951 |
assert self.group_uuid in self.glm.list_owned(locking.LEVEL_NODEGROUP) |
|
11952 |
member_nodes = self.cfg.GetNodeGroup(self.group_uuid).members |
|
11953 |
self.needed_locks[locking.LEVEL_NODE].extend(member_nodes) |
|
11954 |
|
|
11955 |
def CheckPrereq(self): |
|
11956 |
owned_instances = frozenset(self.glm.list_owned(locking.LEVEL_INSTANCE)) |
|
11957 |
owned_groups = frozenset(self.glm.list_owned(locking.LEVEL_NODEGROUP)) |
|
11958 |
owned_nodes = frozenset(self.glm.list_owned(locking.LEVEL_NODE)) |
|
11959 |
|
|
11960 |
assert owned_groups.issuperset(self.req_target_uuids) |
|
11961 |
assert self.group_uuid in owned_groups |
|
11962 |
|
|
11963 |
# Check if locked instances are still correct |
|
11964 |
wanted_instances = self.cfg.GetNodeGroupInstances(self.group_uuid) |
|
11965 |
if owned_instances != wanted_instances: |
|
11966 |
raise errors.OpPrereqError("Instances in node group to be evacuated (%s)" |
|
11967 |
" changed since locks were acquired, wanted" |
|
11968 |
" %s, have %s; retry the operation" % |
|
11969 |
(self.group_uuid, |
|
11970 |
utils.CommaJoin(wanted_instances), |
|
11971 |
utils.CommaJoin(owned_instances))) |
|
11972 |
|
|
11973 |
# Get instance information |
|
11974 |
self.instances = dict((name, self.cfg.GetInstanceInfo(name)) |
|
11975 |
for name in owned_instances) |
|
11976 |
|
|
11977 |
# Check if node groups for locked instances are still correct |
|
11978 |
for instance_name in owned_instances: |
|
11979 |
inst = self.instances[instance_name] |
|
11980 |
assert self.group_uuid in self.cfg.GetInstanceNodeGroups(instance_name), \ |
|
11981 |
"Instance %s has no node in group %s" % (instance_name, self.group_uuid) |
|
11982 |
assert owned_nodes.issuperset(inst.all_nodes), \ |
|
11983 |
"Instance %s's nodes changed while we kept the lock" % instance_name |
|
11984 |
|
|
11985 |
inst_groups = self.cfg.GetInstanceNodeGroups(instance_name) |
|
11986 |
if not owned_groups.issuperset(inst_groups): |
|
11987 |
raise errors.OpPrereqError("Instance's node groups changed since locks" |
|
11988 |
" were acquired, current groups are '%s'," |
|
11989 |
" owning groups '%s'; retry the operation" % |
|
11990 |
(utils.CommaJoin(inst_groups), |
|
11991 |
utils.CommaJoin(owned_groups))) |
|
11992 |
|
|
11993 |
if self.req_target_uuids: |
|
11994 |
# User requested specific target groups |
|
11995 |
self.target_uuids = self.req_target_uuids |
|
11996 |
else: |
|
11997 |
# All groups except the one to be evacuated are potential targets |
|
11998 |
self.target_uuids = [group_uuid for group_uuid in owned_groups |
|
11999 |
if group_uuid != self.group_uuid] |
|
12000 |
|
|
12001 |
if not self.target_uuids: |
|
12002 |
raise errors.OpExecError("There are no possible target groups") |
|
12003 |
|
|
12004 |
def BuildHooksEnv(self): |
|
12005 |
"""Build hooks env. |
|
12006 |
|
|
12007 |
""" |
|
12008 |
return { |
|
12009 |
"GROUP_NAME": self.op.group_name, |
|
12010 |
"TARGET_GROUPS": " ".join(self.target_uuids), |
|
12011 |
} |
|
12012 |
|
|
12013 |
def BuildHooksNodes(self): |
|
12014 |
"""Build hooks nodes. |
|
12015 |
|
|
12016 |
""" |
|
12017 |
mn = self.cfg.GetMasterNode() |
|
12018 |
|
|
12019 |
assert self.group_uuid in self.glm.list_owned(locking.LEVEL_NODEGROUP) |
|
12020 |
|
|
12021 |
run_nodes = [mn] + self.cfg.GetNodeGroup(self.group_uuid).members |
|
12022 |
|
|
12023 |
return (run_nodes, run_nodes) |
|
12024 |
|
|
12025 |
def Exec(self, feedback_fn): |
|
12026 |
instances = list(self.glm.list_owned(locking.LEVEL_INSTANCE)) |
|
12027 |
|
|
12028 |
assert self.group_uuid not in self.target_uuids |
|
12029 |
|
|
12030 |
ial = IAllocator(self.cfg, self.rpc, constants.IALLOCATOR_MODE_CHG_GROUP, |
|
12031 |
instances=instances, target_groups=self.target_uuids) |
|
12032 |
|
|
12033 |
ial.Run(self.op.iallocator) |
|
12034 |
|
|
12035 |
if not ial.success: |
|
12036 |
raise errors.OpPrereqError("Can't compute group evacuation using" |
|
12037 |
" iallocator '%s': %s" % |
|
12038 |
(self.op.iallocator, ial.info), |
|
12039 |
errors.ECODE_NORES) |
|
12040 |
|
|
12041 |
jobs = _LoadNodeEvacResult(self, ial.result, self.op.early_release, False) |
|
12042 |
|
|
12043 |
self.LogInfo("Iallocator returned %s job(s) for evacuating node group %s", |
|
12044 |
len(jobs), self.op.group_name) |
|
12045 |
|
|
12046 |
return ResultWithJobs(jobs) |
|
12047 |
|
|
12048 |
|
|
11878 | 12049 |
class TagsLU(NoHooksLU): # pylint: disable-msg=W0223 |
11879 | 12050 |
"""Generic tags LU. |
11880 | 12051 |
|
Also available in: Unified diff