xmlbuilder: Make XMLManualActions work more like XMLChildProperty

This will help us in upcoming patches add xpath subarguments to
cli device options

Signed-off-by: Cole Robinson <crobinso@redhat.com>
This commit is contained in:
Cole Robinson 2022-02-27 11:38:13 -05:00
parent e1b168c69b
commit 6c47fa56b9
2 changed files with 57 additions and 59 deletions

View File

@ -1580,38 +1580,11 @@ class VirtCLIParser(metaclass=_InitClass):
# --xml parsing # # --xml parsing #
################# #################
class _XMLCLIInstance:
"""
Helper class to parse --xml content into.
Generates XMLManualAction which actually performs the work
"""
def __init__(self):
self.xpath_delete = None
self.xpath_set = None
self.xpath_create = None
self.xpath_value = None
def build_action(self):
from .xmlbuilder import XMLManualAction
if self.xpath_delete:
return XMLManualAction(self.xpath_delete,
action=XMLManualAction.ACTION_DELETE)
if self.xpath_create:
return XMLManualAction(self.xpath_create,
action=XMLManualAction.ACTION_CREATE)
xpath = self.xpath_set
if self.xpath_value:
val = self.xpath_value
else:
if "=" not in str(xpath):
fail("%s: Setting xpath must be in the form of XPATH=VALUE" %
xpath)
xpath, val = xpath.rsplit("=", 1)
return XMLManualAction(xpath, val or None)
class ParserXML(VirtCLIParser): class ParserXML(VirtCLIParser):
"""
Parser to set values on XMLManualAction instances, which are tracked
in XMLBuilder.xml_actions
"""
cli_arg_name = "xml" cli_arg_name = "xml"
supports_clearxml = False supports_clearxml = False
@ -1633,14 +1606,13 @@ class ParserXML(VirtCLIParser):
def parse_xmlcli(guest, options): def parse_xmlcli(guest, options):
""" """
Parse --xml option strings and add the resulting XMLManualActions Parse --xml option string into XMLManualAction instances and append
to the Guest instance to guest.xml_actions.
""" """
for optstr in options.xml: for optstr in options.xml:
inst = _XMLCLIInstance() inst = guest.xml_actions.new()
ParserXML(optstr).parse(inst) ParserXML(optstr).parse(inst)
manualaction = inst.build_action() guest.xml_actions.append(inst)
guest.add_xml_manual_action(manualaction)
######################## ########################

View File

@ -34,24 +34,49 @@ class XMLManualAction(object):
ACTION_CREATE = 1 ACTION_CREATE = 1
ACTION_DELETE = 2 ACTION_DELETE = 2
ACTION_SET = 3 ACTION_SET = 3
def __init__(self, xpath, value=None, action=-1):
self.xpath = xpath
self._value = value
self._action = self.ACTION_SET xpath_delete = None
if action != -1: xpath_create = None
self._action = action xpath_value = None
xpath_set = None
def _process_args(self):
def _ret(x, a, v=None):
return (x, a, v)
if self.xpath_delete:
return _ret(self.xpath_delete, XMLManualAction.ACTION_DELETE)
if self.xpath_create:
return _ret(self.xpath_create, XMLManualAction.ACTION_CREATE)
xpath = self.xpath_set
if self.xpath_value:
val = self.xpath_value
else:
if "=" not in str(xpath):
raise Exception(
"%s: Setting xpath must be in the form of XPATH=VALUE" %
xpath)
xpath, val = xpath.rsplit("=", 1)
return _ret(xpath, XMLManualAction.ACTION_SET, val)
def perform(self, xmlstate): def perform(self, xmlstate):
xpath = self.xpath if (not self.xpath_delete and
not self.xpath_create and
not self.xpath_value and
not self.xpath_set):
return
xpath, action, value = self._process_args()
if xpath.startswith("."): if xpath.startswith("."):
xpath = xmlstate.make_abs_xpath(self.xpath) xpath = xmlstate.make_abs_xpath(xpath)
if self._action == self.ACTION_DELETE:
if action == self.ACTION_DELETE:
setval = False setval = False
elif self._action == self.ACTION_CREATE: elif action == self.ACTION_CREATE:
setval = True setval = True
else: else:
setval = self._value setval = value or None
xmlstate.xmlapi.set_xpath_content(xpath, setval) xmlstate.xmlapi.set_xpath_content(xpath, setval)
@ -95,10 +120,11 @@ class _XMLChildList(list):
This is just to insert a dynamically created add_new() function This is just to insert a dynamically created add_new() function
which instantiates and appends a new child object which instantiates and appends a new child object
""" """
def __init__(self, childclass, copylist, xmlbuilder): def __init__(self, childclass, copylist, xmlbuilder, is_xml=True):
list.__init__(self) list.__init__(self)
self._childclass = childclass self._childclass = childclass
self._xmlbuilder = xmlbuilder self._xmlbuilder = xmlbuilder
self._is_xml = is_xml
for i in copylist: for i in copylist:
self.append(i) self.append(i)
@ -106,14 +132,20 @@ class _XMLChildList(list):
""" """
Instantiate a new child object and return it Instantiate a new child object and return it
""" """
return self._childclass(self._xmlbuilder.conn) args = ()
if self._is_xml:
args = (self._xmlbuilder.conn,)
return self._childclass(*args)
def add_new(self): def add_new(self):
""" """
Instantiate a new child object, append it, and return it Instantiate a new child object, append it, and return it
""" """
obj = self.new() obj = self.new()
if self._is_xml:
self._xmlbuilder.add_child(obj) self._xmlbuilder.add_child(obj)
else:
self.append(obj)
return obj return obj
@ -518,7 +550,8 @@ class XMLBuilder(object):
self._validate_xmlbuilder() self._validate_xmlbuilder()
self._initial_child_parse() self._initial_child_parse()
self._manual_actions = [] self.xml_actions = _XMLChildList(
XMLManualAction, [], self, is_xml=False)
def _validate_xmlbuilder(self): def _validate_xmlbuilder(self):
# This is one time validation we run once per XMLBuilder class # This is one time validation we run once per XMLBuilder class
@ -652,13 +685,6 @@ class XMLBuilder(object):
return 0 return 0
return int(xpath.rsplit("[", 1)[1].strip("]")) - 1 return int(xpath.rsplit("[", 1)[1].strip("]")) - 1
def add_xml_manual_action(self, manualaction):
"""
Register a manual XML action to perform at the end of the
XML building step. Triggered via --xml on the command line
"""
self._manual_actions.append(manualaction)
################ ################
# Internal API # # Internal API #
@ -841,5 +867,5 @@ class XMLBuilder(object):
for obj in xmlutil.listify(getattr(self, key)): for obj in xmlutil.listify(getattr(self, key)):
obj._add_parse_bits(self._xmlstate.xmlapi) obj._add_parse_bits(self._xmlstate.xmlapi)
for manualaction in self._manual_actions: for manualaction in self.xml_actions:
manualaction.perform(self._xmlstate) manualaction.perform(self._xmlstate)