Skip to content

Commit

Permalink
Dev: parse: cli_to_xml: populate advised monitor/start/stop operation…
Browse files Browse the repository at this point in the history
…s values

Changes include:
- Set the advised operation values if monitor/start/stop not input in command line
- Complete advised operation values if miss interval or timeout attributes
- Keep origin configured RA unchanged
  • Loading branch information
liangxin1300 committed Oct 24, 2022
1 parent 3480aa0 commit 91879fb
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 7 deletions.
3 changes: 1 addition & 2 deletions crmsh/cibconfig.py
Original file line number Diff line number Diff line change
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_advised=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:
57 changes: 52 additions & 5 deletions crmsh/parse.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import re
import inspect
from lxml import etree
from . import ra
from . import constants
from .ra import disambiguate_ra_type, ra_type_validate
from . import schema
Expand Down Expand Up @@ -169,12 +170,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_advised):
"""
Called by CliParser. Calls parse()
Parsers should pass their return value through this method.
"""
self.ignore_empty = ignore_empty
self.complete_op_advised = complete_op_advised
out = self.parse(cmd)
if self.has_tokens():
self.err("Unknown arguments: " + ' '.join(self._cmd[self._currtok:]))
Expand Down Expand Up @@ -653,6 +655,51 @@ def match_arguments(self, out, name_map, implicit_initial=None, terminator=None)
else:
break

self.complete_advised_ops(out)

def complete_advised_ops(self, out):
"""
Complete operation actions advised values
"""
if not self.complete_op_advised or out.tag != "primitive":
return
ra_inst = ra.RAInfo(out.get('class'), out.get('type'), out.get('provider'))
ra_actions_dict = ra_inst.actions()
if not ra_actions_dict:
return

# get a dict only has interval and timeout value for each action
action_advised_attr_dict = {}
for action in constants.DEFAULT_ACTION_LIST:
action_advised_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_advised_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_advised_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:
op_node = op_action_node_dict[action]
for attr in ['interval', 'timeout']:
# some attributes not configured
if not op_node.get(attr):
op_node.set(attr, action_advised_attr_dict[action][attr])
# some actions not configured
else:
op_node = xmlutil.new('op', name=action, **action_advised_attr_dict[action])
operations_node.append(op_node)

def match_container(self, out, _type):
container_node = None
self.match(_type)
Expand Down Expand Up @@ -697,8 +744,8 @@ def match_op(self, out, pfx='op'):
op_type = self.match_identifier()
all_attrs = self.match_nvpairs(minpairs=0)
node = xmlutil.new('op', name=op_type)
if not any(nvp.get('name') == 'interval' for nvp in all_attrs):
all_attrs.append(xmlutil.nvpair('interval', '0'))
if not any(nvp.get('name') == 'interval' for nvp in all_attrs) and op_type != "monitor":
all_attrs.append(xmlutil.nvpair('interval', '0s'))
valid_attrs = validator.op_attributes()
inst_attrs = None
for nvp in all_attrs:
Expand Down Expand Up @@ -1703,7 +1750,7 @@ def parse(self):
return ret


def parse(s, comments=None, ignore_empty=True):
def parse(s, comments=None, ignore_empty=True, complete_op_advised=False):
'''
Input: a list of tokens (or a CLI format string).
Return: a cibobject
Expand Down Expand Up @@ -1749,7 +1796,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_advised)
if ret is not None and len(comments) > 0:
if ret.tag in constants.defaults_tags:
xmlutil.stuff_comments(ret[0], comments)
Expand Down
2 changes: 2 additions & 0 deletions crmsh/ra.py
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,8 @@ def actions(self):
value = elem.get(key)
if value:
d[key] = value
if 'interval' not in d:
d['interval'] = '0s'
if name == "monitor":
actions_dict[name].append(d)
else:
Expand Down

0 comments on commit 91879fb

Please sign in to comment.