Skip to content

Commit

Permalink
Dev: parse: Populate some default operations when configuring primiti…
Browse files Browse the repository at this point in the history
…ve resource
  • Loading branch information
liangxin1300 committed Oct 17, 2022
1 parent 3480aa0 commit 4e65062
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 19 deletions.
5 changes: 2 additions & 3 deletions crmsh/cibconfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
from . import crm_gv
from . import ui_utils
from . import userdir
from .ra import get_ra, get_properties_list, get_pe_meta, get_properties_meta
from .ra import get_ra, get_properties_list, get_pe_meta, get_properties_meta, ra_agent_for_cpt
from .utils import ext_cmd, safe_open_w, pipe_string, safe_close_w, crm_msec
from .utils import ask, lines2cli, olist
from .utils import page_string, cibadmin_can_patch, str2tmp, ensure_sudo_readable
Expand Down Expand Up @@ -830,14 +830,13 @@ def parse_cli_to_xml(cli, oldnode=None):
for s in lines2cli(cli):
node = parse.parse(s, comments=comments)
else: # should be a pre-tokenized list
node = parse.parse(cli, comments=comments, ignore_empty=False)
node = parse.parse(cli, comments=comments, ignore_empty=False, complete_op_default=True)
if node is False:
return None, None, None
elif node is None:
return None, None, None
return postprocess_cli(node, oldnode)


#
# cib element classes (CibObject the parent class)
#
Expand Down
2 changes: 2 additions & 0 deletions crmsh/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -523,4 +523,6 @@
REJOIN_COUNT = 60
REJOIN_INTERVAL = 10
DC_DEADTIME_DEFAULT = 20

DEFAULT_ACTION_LIST = ['monitor', 'start', 'stop']
# vim:ts=4:sw=4:et:
54 changes: 50 additions & 4 deletions crmsh/parse.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import inspect
from lxml import etree
from . import constants
from .ra import disambiguate_ra_type, ra_type_validate
from .ra import disambiguate_ra_type, ra_type_validate, ra_agent_for_cpt
from . import schema
from .utils import keyword_cmp, verify_boolean, lines2cli
from .utils import get_boolean, olist, canonical_boolean
Expand Down Expand Up @@ -169,12 +169,13 @@ def begin_dispatch(self, cmd, min_args=-1):
self.begin(cmd, min_args=min_args)
return self.match_dispatch(errmsg="Unknown command")

def do_parse(self, cmd, ignore_empty):
def do_parse(self, cmd, ignore_empty, complete_op_default):
"""
Called by CliParser. Calls parse()
Parsers should pass their return value through this method.
"""
self.ignore_empty = ignore_empty
self.complete_op_default = complete_op_default
out = self.parse(cmd)
if self.has_tokens():
self.err("Unknown arguments: " + ' '.join(self._cmd[self._currtok:]))
Expand Down Expand Up @@ -653,6 +654,51 @@ def match_arguments(self, out, name_map, implicit_initial=None, terminator=None)
else:
break

self.complete_op_action_default_value(out)

def complete_op_action_default_value(self, out):
"""
Complete operation actions default values
"""
if not self.complete_op_default or out.tag != "primitive":
return
ra_inst = ra_agent_for_cpt(out.get('type'))
if not ra_inst:
return
ra_actions_dict = ra_inst.actions()

# get a dict only has interval and timeout value for each action
action_default_attr_dict = {}
for action in constants.DEFAULT_ACTION_LIST:
action_default_attr_dict[action] = {}
if action in ra_actions_dict:
_dict = ra_actions_dict[action][0] if isinstance(ra_actions_dict[action], list) else ra_actions_dict[action]
action_default_attr_dict[action] = {k:v for k, v in _dict.items() if k in ['interval', 'timeout']}

operations_node = out.find("operations")
# no operation configured
if operations_node is None:
operations_node = xmlutil.child(out, 'operations')
for action in constants.DEFAULT_ACTION_LIST:
op_node = xmlutil.new('op', name=action, **action_default_attr_dict[action])
operations_node.append(op_node)
out.append(operations_node)
else:
op_nodes_list = operations_node.findall("op")
op_action_node_dict = {op_node.get('name'):op_node for op_node in op_nodes_list}
for action in constants.DEFAULT_ACTION_LIST:
# some actions configured
if action in op_action_node_dict:
for attr in ['interval', 'timeout']:
op_node = op_action_node_dict[action]
# some attributes not configured
if not op_node.get(attr):
op_node.set(attr, action_default_attr_dict[action][attr])
# some actions not configured
else:
op_node = xmlutil.new('op', name=action, **action_default_attr_dict[action])
operations_node.append(op_node)

def match_container(self, out, _type):
container_node = None
self.match(_type)
Expand Down Expand Up @@ -1703,7 +1749,7 @@ def parse(self):
return ret


def parse(s, comments=None, ignore_empty=True):
def parse(s, comments=None, ignore_empty=True, complete_op_default=False):
'''
Input: a list of tokens (or a CLI format string).
Return: a cibobject
Expand Down Expand Up @@ -1749,7 +1795,7 @@ def parse(s, comments=None, ignore_empty=True):
return False

try:
ret = parser.do_parse(s, ignore_empty)
ret = parser.do_parse(s, ignore_empty, complete_op_default)
if ret is not None and len(comments) > 0:
if ret.tag in constants.defaults_tags:
xmlutil.stuff_comments(ret[0], comments)
Expand Down
15 changes: 13 additions & 2 deletions crmsh/ra.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import re
import glob
from lxml import etree
from collections import OrderedDict
from . import cache
from . import constants
from . import config
Expand Down Expand Up @@ -428,9 +429,10 @@ def actions(self):
name = elem.get("name")
if not name or name in self.skip_ops:
continue
d = {}
d = OrderedDict()
d['interval'] = elem.get('interval') if 'interval' in elem.attrib else '0s'
for key in list(elem.attrib.keys()):
if key in self.skip_op_attr:
if key in self.skip_op_attr or d == 'interval':
continue
value = elem.get(key)
if value:
Expand Down Expand Up @@ -866,6 +868,15 @@ def disambiguate_ra_type(s):
return cl, pr, tp


def ra_agent_for_cpt(cpt):
'''class:provider:type -> ra.agent'''
agent = None
ra_class, provider, rsc_type = disambiguate_ra_type(cpt)
if ra_type_validate(cpt, ra_class, provider, rsc_type):
agent = RAInfo(ra_class, rsc_type, provider)
return agent


def can_validate_agent(agent):
if utils.getuser() != 'root':
return False
Expand Down
11 changes: 1 addition & 10 deletions crmsh/ui_configure.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,15 +182,6 @@ def ra_agent_for_template(tmpl):
return ra.get_ra(obj.node)


def ra_agent_for_cpt(cpt):
'''class:provider:type -> ra.agent'''
agent = None
ra_class, provider, rsc_type = ra.disambiguate_ra_type(cpt)
if ra.ra_type_validate(cpt, ra_class, provider, rsc_type):
agent = ra.RAInfo(ra_class, rsc_type, provider)
return agent


class CompletionHelp(object):
'''
Print some help on whatever last word in the line.
Expand Down Expand Up @@ -316,7 +307,7 @@ def primitive_complete_complex(args):
if with_template:
agent = ra_agent_for_template(type_word)
else:
agent = ra_agent_for_cpt(type_word)
agent = ra.ra_agent_for_cpt(type_word)
if agent is None:
return []

Expand Down

0 comments on commit 4e65062

Please sign in to comment.