Skip to content

Commit

Permalink
move resource move/ban/clear to pcs.lib
Browse files Browse the repository at this point in the history
  • Loading branch information
tomjelinek committed Mar 12, 2019
1 parent d67ef6d commit 601b765
Show file tree
Hide file tree
Showing 13 changed files with 1,009 additions and 58 deletions.
114 changes: 114 additions & 0 deletions pcs/cli/common/console_report.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

from collections import defaultdict, Iterable
from functools import partial
import re
import sys

from pcs.common import report_codes as codes
Expand Down Expand Up @@ -326,6 +327,75 @@ def service_version_mismatch(info):
))
return "; ".join(parts)

def resource_move_ban_clear_master_resource_not_promotable(info):
return (
"when specifying --master you must use the promotable clone id{_id}"
.format(
_id=format_optional(info["promotable_id"], " ({0})"),
)
)

def resource_move_ban_pcmk_error(info, action):
new_lines = [f"error {action} resource '{info['resource_id']}'"]
for line in info["stdout"].splitlines() + info["stderr"].splitlines():
if not line.strip():
continue
line = line.replace(
"--ban --master --node <name>",
"pcs resource ban {resource_id} <node> --master".format(**info)
)
line = line.replace(
"--ban --node <name>",
"pcs resource ban {resource_id} <node>".format(**info)
)
new_lines.append(line)
return "\n".join(new_lines)

def resource_unmove_unban_pcmk_error(info):
new_lines = [f"error clearing resource '{info['resource_id']}'"]
for line in info["stdout"].splitlines() + info["stderr"].splitlines():
if line.strip():
new_lines.append(line)
return "\n".join(new_lines)

def resource_move_ban_pcmk_success(info):
warning_re = re.compile(
r"WARNING: Creating rsc_location constraint '([^']+)' "
r"with a score of -INFINITY for resource ([\S]+) on (.+)\."
)
new_lines = []
for line in info["stdout"].splitlines() + info["stderr"].splitlines():
if not line.strip():
continue
warning_match = warning_re.search(line)
if warning_match:
new_lines.append(
(
"Warning: Creating location constraint {0} with a score "
"of -INFINITY for resource {1} on node {2}"
).format(*warning_match.group(1, 2, 3))
)
continue
if (
"the constraint is removed using the clear option or by editing "
"the CIB with an appropriate tool"
) in line:
new_lines.append(line.replace(
" using the clear option or by editing the CIB with an "
"appropriate tool",
""
))
continue
new_lines.append(line)
return "\n".join(new_lines)

def resource_unmove_unban_pcmk_success(info):
new_lines = []
for line in info["stdout"].splitlines() + info["stderr"].splitlines():
if line.strip():
new_lines.append(line)
return "\n".join(new_lines)

def build_node_description(node_types):
if not node_types:
return "Node"
Expand Down Expand Up @@ -1958,4 +2028,48 @@ def joined_list(item_list, optional_transformations=None):
**info
)
,

codes.CANNOT_MOVE_RESOURCE_BUNDLE: "cannot move bundle resources",
codes.CANNOT_MOVE_RESOURCE_CLONE: "cannot move cloned resources",
codes.CANNOT_MOVE_RESOURCE_MASTER_RESOURCE_NOT_PROMOTABLE:
resource_move_ban_clear_master_resource_not_promotable
,
codes.CANNOT_MOVE_RESOURCE_PROMOTABLE_NOT_MASTER: lambda info:
(
"to move promotable clone resources you must use --master and the "
"promotable clone id ({promotable_id})"
).format(**info)
,
codes.CANNOT_MOVE_RESOURCE_STOPPED_NO_NODE_SPECIFIED:
# Use both "moving" and "banning" to let user know using "ban" instead
# of "move" will not help
"You must specify a node when moving/banning a stopped resource"
,
codes.RESOURCE_MOVE_PCMK_ERROR: lambda info:
resource_move_ban_pcmk_error(info, "moving")
,
codes.RESOURCE_MOVE_PCMK_SUCCESS: resource_move_ban_pcmk_success,

codes.CANNOT_BAN_RESOURCE_MASTER_RESOURCE_NOT_PROMOTABLE:
resource_move_ban_clear_master_resource_not_promotable
,
codes.CANNOT_BAN_RESOURCE_STOPPED_NO_NODE_SPECIFIED:
# Use both "moving" and "banning" to let user know using "move" instead
# of "ban" will not help
"You must specify a node when moving/banning a stopped resource"
,
codes.RESOURCE_BAN_PCMK_ERROR: lambda info:
resource_move_ban_pcmk_error(info, "banning")
,
codes.RESOURCE_BAN_PCMK_SUCCESS: resource_move_ban_pcmk_success,

codes.CANNOT_UNMOVE_UNBAN_RESOURCE_MASTER_RESOURCE_NOT_PROMOTABLE:
resource_move_ban_clear_master_resource_not_promotable
,
codes.RESOURCE_UNMOVE_UNBAN_PCMK_ERROR:
resource_unmove_unban_pcmk_error
,
codes.RESOURCE_UNMOVE_UNBAN_PCMK_SUCCESS:
resource_unmove_unban_pcmk_success
,
}
3 changes: 3 additions & 0 deletions pcs/cli/common/lib_wrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,7 @@ def load_module(env, middleware_factory, name):
middleware_factory.corosync_conf_existing,
),
{
"ban": resource.ban,
"bundle_create": resource.bundle_create,
"bundle_reset": resource.bundle_reset,
"bundle_update": resource.bundle_update,
Expand All @@ -347,7 +348,9 @@ def load_module(env, middleware_factory, name):
"get_failcounts": resource.get_failcounts,
"group_add": resource.group_add,
"manage": resource.manage,
"move": resource.move,
"unmanage": resource.unmanage,
"unmove_unban": resource.unmove_unban,
}
)

Expand Down
4 changes: 2 additions & 2 deletions pcs/cli/routing/resource.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
"describe": resource.resource_list_options,
"create": resource.resource_create,
"move": resource.resource_move,
"ban": partial(resource.resource_move, ban=True),
"clear": partial(resource.resource_move, clear=True),
"ban": resource.resource_ban,
"clear": resource.resource_unmove_unban,
"standards": resource.resource_standards,
"providers": resource.resource_providers,
"agents": resource.resource_agents,
Expand Down
22 changes: 18 additions & 4 deletions pcs/common/report_codes.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,14 +60,22 @@
BOOTH_TICKET_OPERATION_FAILED = "BOOTH_TICKET_OPERATION_FAILED"
BOOTH_TICKET_STATUS_ERROR = "BOOTH_TICKET_STATUS_ERROR"
BOOTH_UNSUPORTED_FILE_LOCATION = "BOOTH_UNSUPORTED_FILE_LOCATION"
CANNOT_BAN_RESOURCE_MASTER_RESOURCE_NOT_PROMOTABLE = "CANNOT_BAN_RESOURCE_MASTER_RESOURCE_NOT_PROMOTABLE"
CANNOT_BAN_RESOURCE_STOPPED_NO_NODE_SPECIFIED = "CANNOT_BAN_RESOURCE_STOPPED_NO_NODE_SPECIFIED"
CANNOT_GROUP_RESOURCE_ADJACENT_RESOURCE_FOR_NEW_GROUP = "CANNOT_GROUP_RESOURCE_ADJACENT_RESOURCE_FOR_NEW_GROUP"
CANNOT_GROUP_RESOURCE_ADJACENT_RESOURCE_NOT_IN_GROUP = "CANNOT_GROUP_RESOURCE_ADJACENT_RESOURCE_NOT_IN_GROUP"
CANNOT_GROUP_RESOURCE_ALREADY_IN_THE_GROUP = "CANNOT_GROUP_RESOURCE_ALREADY_IN_THE_GROUP"
CANNOT_GROUP_RESOURCE_NEXT_TO_ITSELF = "CANNOT_GROUP_RESOURCE_NEXT_TO_ITSELF"
CANNOT_GROUP_RESOURCE_MORE_THAN_ONCE = "CANNOT_GROUP_RESOURCE_MORE_THAN_ONCE"
CANNOT_GROUP_RESOURCE_NEXT_TO_ITSELF = "CANNOT_GROUP_RESOURCE_NEXT_TO_ITSELF"
CANNOT_GROUP_RESOURCE_NO_RESOURCES = "CANNOT_GROUP_RESOURCE_NO_RESOURCES"
CANNOT_GROUP_RESOURCE_WRONG_TYPE = "CANNOT_GROUP_RESOURCE_WRONG_TYPE"
CANNOT_MOVE_RESOURCE_BUNDLE = "CANNOT_MOVE_RESOURCE_BUNDLE"
CANNOT_MOVE_RESOURCE_CLONE = "CANNOT_MOVE_RESOURCE_CLONE"
CANNOT_MOVE_RESOURCE_MASTER_RESOURCE_NOT_PROMOTABLE = "CANNOT_MOVE_RESOURCE_MASTER_RESOURCE_NOT_PROMOTABLE"
CANNOT_MOVE_RESOURCE_PROMOTABLE_NOT_MASTER = "CANNOT_MOVE_RESOURCE_PROMOTABLE_NOT_MASTER"
CANNOT_MOVE_RESOURCE_STOPPED_NO_NODE_SPECIFIED = "CANNOT_MOVE_RESOURCE_STOPPED_NO_NODE_SPECIFIED"
CANNOT_REMOVE_ALL_CLUSTER_NODES = "CANNOT_REMOVE_ALL_CLUSTER_NODES"
CANNOT_UNMOVE_UNBAN_RESOURCE_MASTER_RESOURCE_NOT_PROMOTABLE = "CANNOT_UNMOVE_UNBAN_RESOURCE_MASTER_RESOURCE_NOT_PROMOTABLE"
CIB_ACL_ROLE_IS_ALREADY_ASSIGNED_TO_TARGET = "CIB_ACL_ROLE_IS_ALREADY_ASSIGNED_TO_TARGET"
CIB_ACL_ROLE_IS_NOT_ASSIGNED_TO_TARGET = "CIB_ACL_ROLE_IS_NOT_ASSIGNED_TO_TARGET"
CIB_ACL_TARGET_ALREADY_EXISTS = "CIB_ACL_TARGET_ALREADY_EXISTS"
Expand Down Expand Up @@ -230,21 +238,27 @@
QDEVICE_USED_BY_CLUSTERS = "QDEVICE_USED_BY_CLUSTERS"
REQUIRED_OPTION_IS_MISSING = "REQUIRED_OPTION_IS_MISSING"
REQUIRED_OPTION_OF_ALTERNATIVES_IS_MISSING = "REQUIRED_OPTION_OF_ALTERNATIVES_IS_MISSING"
RESOURCE_BAN_PCMK_ERROR = "RESOURCE_BAN_PCMK_ERROR"
RESOURCE_BAN_PCMK_SUCCESS = "RESOURCE_BAN_PCMK_SUCCESS"
RESOURCE_BUNDLE_ALREADY_CONTAINS_A_RESOURCE = "RESOURCE_BUNDLE_ALREADY_CONTAINS_A_RESOURCE"
RESOURCE_BUNDLE_UNSUPPORTED_CONTAINER_TYPE = "RESOURCE_BUNDLE_UNSUPPORTED_CONTAINER_TYPE"
RESOURCE_IN_BUNDLE_NOT_ACCESSIBLE = "RESOURCE_IN_BUNDLE_NOT_ACCESSIBLE"
RESOURCE_CLEANUP_ERROR = "RESOURCE_CLEANUP_ERROR"
RESOURCE_DOES_NOT_RUN = "RESOURCE_DOES_NOT_RUN"
RESOURCE_FOR_CONSTRAINT_IS_MULTIINSTANCE = 'RESOURCE_FOR_CONSTRAINT_IS_MULTIINSTANCE'
RESOURCE_IN_BUNDLE_NOT_ACCESSIBLE = "RESOURCE_IN_BUNDLE_NOT_ACCESSIBLE"
RESOURCE_INSTANCE_ATTR_VALUE_NOT_UNIQUE = "RESOURCE_INSTANCE_ATTR_VALUE_NOT_UNIQUE"
RESOURCE_IS_GUEST_NODE_ALREADY = "RESOURCE_IS_GUEST_NODE_ALREADY"
RESOURCE_IS_UNMANAGED = "RESOURCE_IS_UNMANAGED"
RESOURCE_MANAGED_NO_MONITOR_ENABLED = "RESOURCE_MANAGED_NO_MONITOR_ENABLED"
RESOURCE_OPERATION_INTERVAL_DUPLICATION = "RESOURCE_OPERATION_INTERVAL_DUPLICATION"
RESOURCE_MOVE_PCMK_ERROR = "RESOURCE_MOVE_PCMK_ERROR"
RESOURCE_MOVE_PCMK_SUCCESS = "RESOURCE_MOVE_PCMK_SUCCESS"
RESOURCE_OPERATION_INTERVAL_ADAPTED = "RESOURCE_OPERATION_INTERVAL_ADAPTED"
RESOURCE_OPERATION_INTERVAL_DUPLICATION = "RESOURCE_OPERATION_INTERVAL_DUPLICATION"
RESOURCE_REFRESH_ERROR = "RESOURCE_REFRESH_ERROR"
RESOURCE_REFRESH_TOO_TIME_CONSUMING = 'RESOURCE_REFRESH_TOO_TIME_CONSUMING'
RESOURCE_RUNNING_ON_NODES = "RESOURCE_RUNNING_ON_NODES"
RESOURCE_INSTANCE_ATTR_VALUE_NOT_UNIQUE = "RESOURCE_INSTANCE_ATTR_VALUE_NOT_UNIQUE"
RESOURCE_UNMOVE_UNBAN_PCMK_ERROR = "RESOURCE_UNMOVE_UNBAN_PCMK_ERROR"
RESOURCE_UNMOVE_UNBAN_PCMK_SUCCESS = "RESOURCE_UNMOVE_UNBAN_PCMK_SUCCESS"
RUN_EXTERNAL_PROCESS_ERROR = "RUN_EXTERNAL_PROCESS_ERROR"
RUN_EXTERNAL_PROCESS_FINISHED = "RUN_EXTERNAL_PROCESS_FINISHED"
RUN_EXTERNAL_PROCESS_STARTED = "RUN_EXTERNAL_PROCESS_STARTED"
Expand Down
36 changes: 34 additions & 2 deletions pcs/lib/cib/resource/clone.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
"""
from lxml import etree

from pcs.lib.cib.nvpair import append_new_meta_attributes
from pcs.lib.cib import nvpair
from pcs.lib.pacemaker.values import is_true


TAG_CLONE = "clone"
Expand All @@ -25,6 +26,37 @@ def is_master(resource_el):
def is_any_clone(resource_el):
return resource_el.tag in ALL_TAGS

def is_promotable_clone(resource_el):
"""
Return True if resource_el is a promotable clone, False on clone and master
"""
return (
is_clone(resource_el)
and
is_true(nvpair.get_value(
nvpair.META_ATTRIBUTES_TAG,
resource_el,
"promotable",
default="false",
))
)

def get_parent_any_clone(resource_el):
"""
Get any parent clone of a primitive (may be in a group) or group
etree.Element resource_el -- the primitive or group to get its parent clone
"""
element = resource_el
for _ in range(2):
parent_el = element.getparent()
if parent_el is None:
return None
if is_any_clone(parent_el):
return parent_el
element = parent_el
return None

def append_new(resources_section, id_provider, primitive_element, options):
"""
Append a new clone element (containing the primitive_element) to the
Expand All @@ -45,7 +77,7 @@ def append_new(resources_section, id_provider, primitive_element, options):
clone_element.append(primitive_element)

if options:
append_new_meta_attributes(clone_element, options, id_provider)
nvpair.append_new_meta_attributes(clone_element, options, id_provider)

return clone_element

Expand Down

0 comments on commit 601b765

Please sign in to comment.