def _validate_move_ban_clear_analyzer(resource_element): resource_is_bundle = False resource_is_clone = False resource_is_in_clone = False resource_is_promotable_clone = False resource_is_in_promotable_clone = False promotable_clone_element = None if is_bundle(resource_element): resource_is_bundle = True elif is_any_clone(resource_element): resource_is_clone = True if is_master(resource_element) or is_promotable_clone(resource_element): resource_is_promotable_clone = True promotable_clone_element = resource_element elif get_parent_any_clone(resource_element) is not None: parent_clone = get_parent_any_clone(resource_element) resource_is_in_clone = True if is_master(parent_clone) or is_promotable_clone(parent_clone): resource_is_in_promotable_clone = True promotable_clone_element = parent_clone return _MoveBanClearAnalysis( resource_is_bundle, resource_is_clone, resource_is_in_clone, resource_is_promotable_clone, resource_is_in_promotable_clone, ( promotable_clone_element.get("id") if promotable_clone_element is not None else None ) )
def find_resources_to_delete(resource_el: _Element) -> List[_Element]: """ Get resources to delete, children and parents of the given resource if necessary. If element is a primitive which is in a clone and you specify one of them, you will get elements for both of them. If you specify group element which is in a clone then will you get clone, group, and all primitive elements in a group and etc. resource_el - resource element (bundle, clone, group, primitive) """ result = [resource_el] # childrens of bundle, clone, group, clone-with-group inner_resource_list = get_inner_resources(resource_el) if inner_resource_list: result.extend(inner_resource_list) inner_resource = inner_resource_list[0] if is_group(inner_resource): result.extend(get_inner_resources(inner_resource)) # parents of primitive if needed (group, clone) parent_el = get_parent_resource(resource_el) if parent_el is None or is_bundle(parent_el): return result if is_any_clone(parent_el): result.insert(0, parent_el) if is_group(parent_el): group_inner_resources = get_group_inner_resources(parent_el) if len(group_inner_resources) <= 1: result = [parent_el] + group_inner_resources clone_el = get_parent_resource(parent_el) if clone_el is not None: result.insert(0, clone_el) return result
def find_resources_to_manage(resource_el): """ Get resources to manage to manage the specified resource succesfully etree resource_el -- resource element """ # If the resource_el is a primitive in a group, we set both the group and # the primitive to managed mode. Otherwise the resource_el, all its # children and parents need to be set to managed mode. We do it to make # sure to remove the unmanaged flag form the whole tree. The flag could be # put there manually. If we didn't do it, the resource may stay unmanaged, # as a managed primitive in an unmanaged clone / group is still unmanaged # and vice versa. # Bundle resources cannot be set as unmanaged - pcmk currently doesn't # support that. Resources in a bundle are supposed to be treated separately. if is_bundle(resource_el): return [] res_id = resource_el.attrib["id"] return ( [resource_el] # the resource itself + # its parents find_parent(resource_el, "resources").xpath( """ (./master|./clone)[(group|group/primitive|primitive)[@id='{r}']] | //group[primitive[@id='{r}']] """ .format(r=res_id) ) + # its children resource_el.xpath("(./group|./primitive|./group/primitive)") )
def is_wrapper_resource(resource_el: Element) -> bool: """ Return True for resource_el of types that can contain other resource(s) (these are: group, bundle, clone) and False otherwise. resource_el -- resource element to check """ return (is_group(resource_el) or is_bundle(resource_el) or is_any_clone(resource_el))
def find_resources_to_enable(resource_el): """ Get resources to enable in order to enable specified resource succesfully etree resource_el -- resource element """ if is_bundle(resource_el): to_enable = [resource_el] in_bundle = get_bundle_inner_resource(resource_el) if in_bundle is not None: to_enable.append(in_bundle) return to_enable if is_any_clone(resource_el): return [resource_el, get_clone_inner_resource(resource_el)] to_enable = [resource_el] parent = resource_el.getparent() if is_any_clone(parent) or is_bundle(parent): to_enable.append(parent) return to_enable
def find_resources_to_unmanage(resource_el): """ Get resources to unmanage to unmanage the specified resource succesfully etree resource_el -- resource element """ # resource hierarchy - specified resource - what to return # a primitive - the primitive - the primitive # # a cloned primitive - the primitive - the primitive # a cloned primitive - the clone - the primitive # The resource will run on all nodes after unclone. However that doesn't # seem to be bad behavior. Moreover, if monitor operations were disabled, # they wouldn't enable on unclone, but the resource would become managed, # which is definitely bad. # # a primitive in a group - the primitive - the primitive # Otherwise all primitives in the group would become unmanaged. # a primitive in a group - the group - all primitives in the group # If only the group was set to unmanaged, setting any primitive in the # group to managed would set all the primitives in the group to managed. # If the group as well as all its primitives were set to unmanaged, any # primitive added to the group would become unmanaged. This new primitive # would become managed if any original group primitive becomes managed. # Therefore changing one primitive influences another one, which we do # not want to happen. # # a primitive in a cloned group - the primitive - the primitive # a primitive in a cloned group - the group - all primitives in the group # See group notes above # a primitive in a cloned group - the clone - all primitives in the group # See clone notes above # # a bundled primitive - the primitive - the primitive # a bundled primitive - the bundle - the bundle and the primitive # We need to unmanage implicit resources create by pacemaker and there is # no other way to do it than unmanage the bundle itself. # Since it is not possible to unbundle a resource, the concers described # at unclone don't apply here. However to prevent future bugs, in case # unbundling becomes possible, we unmanage the primitive as well. # an empty bundle - the bundle - the bundle # There is nothing else to unmanage. if is_bundle(resource_el): in_bundle = get_bundle_inner_resource(resource_el) return ( [resource_el, in_bundle] if in_bundle is not None else [resource_el] ) if is_any_clone(resource_el): resource_el = get_clone_inner_resource(resource_el) if is_group(resource_el): return get_group_inner_resources(resource_el) if is_primitive(resource_el): return [resource_el] return []
def find_primitives(resource_el): """ Get list of primitives contained in a given resource etree resource_el -- resource element """ if is_bundle(resource_el): in_bundle = get_bundle_inner_resource(resource_el) return [in_bundle] if in_bundle is not None else [] if is_any_clone(resource_el): resource_el = get_clone_inner_resource(resource_el) if is_group(resource_el): return get_group_inner_resources(resource_el) if is_primitive(resource_el): return [resource_el] return []
def get_inner_resources(resource_el: _Element) -> List[_Element]: """ Return list of inner resources (direct descendants) of a resource specified as resource_el. Example: for clone containing a group, this function will return only group and not resource inside the group resource_el -- resource element to get its inner resources """ if is_bundle(resource_el): in_bundle = get_bundle_inner_resource(resource_el) return [in_bundle] if in_bundle is not None else [] if is_any_clone(resource_el): return [get_clone_inner_resource(resource_el)] if is_group(resource_el): return get_group_inner_resources(resource_el) return []
def find_resources_to_enable(resource_el): """ Get resources to enable in order to enable specified resource succesfully etree resource_el -- resource element """ if is_bundle(resource_el): # bundles currently cannot be disabled - pcmk does not support that # inner resources are supposed to be managed separately return [] if is_any_clone(resource_el): return [resource_el, get_clone_inner_resource(resource_el)] to_enable = [resource_el] parent = resource_el.getparent() if is_any_clone(parent): to_enable.append(parent) return to_enable
def test_is_bundle(self): self.assertTrue(bundle.is_bundle(etree.fromstring("<bundle/>"))) self.assertFalse(bundle.is_bundle(etree.fromstring("<clone/>"))) self.assertFalse(bundle.is_bundle(etree.fromstring("<group/>")))
def test_is_bundle(self): self.assertTrue(bundle.is_bundle(etree.fromstring("<bundle/>"))) self.assertFalse(bundle.is_bundle(etree.fromstring("<clone/>"))) self.assertFalse(bundle.is_bundle(etree.fromstring("<group/>")))