[lnst] XmlParser: Moving the parser from DOM to etree
by Jiří Pírko
commit 211c3b8769a4f0063560842643bea72bac070c18
Author: Radek Pazdera <rpazdera(a)redhat.com>
Date: Wed Aug 28 16:41:25 2013 +0200
XmlParser: Moving the parser from DOM to etree
In this patch, the old and big DOM parser is removed and replaced by a
way more lighweight variant using the etree.
With the etree, LNST can use the RelaxNG schemes to verify the XML
syntax so almost all error checks were removed from the code.
Signed-off-by: Radek Pazdera <rpazdera(a)redhat.com>
Signed-off-by: Jiri Pirko <jiri(a)resnulli.us>
lnst/Common/XmlParser.py | 303 +++++++++-------------------------------------
1 files changed, 60 insertions(+), 243 deletions(-)
---
diff --git a/lnst/Common/XmlParser.py b/lnst/Common/XmlParser.py
index 86c9959..68d3c76 100644
--- a/lnst/Common/XmlParser.py
+++ b/lnst/Common/XmlParser.py
@@ -11,261 +11,78 @@ rpazdera(a)redhat.com (Radek Pazdera)
"""
import os
+import sys
import logging
-from xml.dom.minidom import parseString
-from xml import sax
+from lxml import etree
from lnst.Common.XmlTemplates import XmlTemplates, XmlTemplateError
-from lnst.Common.RecipePath import RecipePath
-from lnst.Common.XmlProcessing import XmlProcessingError, XmlDomTreeInit
-from lnst.Common.XmlProcessing import XmlData
+from lnst.Common.XmlProcessing import XmlProcessingError, XmlData
class XmlParser(object):
- """ Parent class for XML processors
-
- This class handles manipulation of XML DOM objects
- that are used for processing XML files.
-
- The standard DOM objects are extended with position data
- (file name, line number and column number) that can be
- used in error reporting.
- """
-
- def _process_child_nodes(self, parent, scheme, params=None,
- default_handler=None):
- child_nodes = parent.childNodes
-
- if not params:
- params = {}
-
- for node in child_nodes:
- if node.nodeType == node.COMMENT_NODE or \
- node.nodeType == node.TEXT_NODE:
- continue
- elif node.nodeType == node.ELEMENT_NODE:
- node_name = node.nodeName
- if node_name in scheme:
- handler = scheme[node_name]
- self._process_node(node, handler, params)
- elif default_handler:
- self._process_node(node, default_handler, params)
- else:
- msg = "Unexpected '%s' tag under '%s'" % (node_name,
- parent.nodeName)
- raise XmlProcessingError(msg, node)
+ def __init__(self, schema_file, xml_path):
+ # locate the schema file
+ # try git path
+ dirname = os.path.dirname(sys.argv[0])
+ schema_path = os.path.join(dirname, schema_file)
+ if not os.path.exists(schema_path):
+ # try configuration
+ res_dir = lnst_config.get_option("environment", "resource_dir")
+ schema_path = os.path.join(res_dir, schema_file)
+
+ if not os.path.exists(schema_path):
+ raise Exception("The recipe schema file was not found. " + \
+ "Your LNST installation is corrupt!")
+
+ self._template_proc = XmlTemplates()
+
+ self._path = xml_path
+ relaxng_doc = etree.parse(schema_path)
+ self._schema = etree.RelaxNG(relaxng_doc)
+
+ def parse(self):
+ try:
+ doc = etree.parse(self._path)
+ doc.xinclude()
+ except Exception as err:
+ # A workaround for cases when lxml (quite strangely)
+ # sets the filename to <string>.
+ if err.error_log[0].filename == "<string>":
+ filename = self._path
else:
- msg = "Only XML elements are allowed here!"
- raise XmlProcessingError(msg, node)
-
- def _process_node(self, node, handler, params):
- handler(node, params)
-
- @staticmethod
- def _convert_string(node, string, conversion_cb):
- if conversion_cb:
- try:
- converted = conversion_cb(string)
- except ValueError as err:
- raise XmlProcessingError("Conversion error: " + str(err), node)
- return converted
-
- return string
-
- def _has_attribute(self, node, attr_name):
- return node.hasAttribute(attr_name)
-
- def _get_attribute(self, node, attr_name, conversion_cb=None):
- if not self._has_attribute(node, attr_name):
- msg = "Expected attribute '%s' missing" % attr_name
- raise XmlProcessingError(msg, node)
- attr_val = str(node.getAttribute(attr_name))
- return self._convert_string(node, attr_val, conversion_cb)
-
- def _get_text_content(self, node, conversion_cb=None):
- content = []
- for child in node.childNodes:
- if child.nodeType == child.TEXT_NODE:
- content.append(child.nodeValue)
-
- text = str(''.join(content).strip())
- return self._convert_string(node, text, conversion_cb)
-
- def _get_all_attributes(self, node):
- res = {}
- for i in range(0, node.attributes.length):
- attr = node.attributes.item(i)
- res[attr.name] = attr.value
+ filename = err.error_log[0].filename
+ loc = {"file": os.path.basename(filename),
+ "line": err.error_log[0].line,
+ "col": err.error_log[0].column}
+ exc = XmlProcessingError(err.error_log[0].message)
+ exc.set_loc(loc)
+ raise exc
- return res
+ root_tag = doc.getroot()
+ self._template_proc.process_aliases(root_tag)
-class LnstParser(XmlParser):
- """ Enhanced XmlParser
-
- This class enhances XmlParser with advanced features that are
- used in parsing LNST XML files. All (sub)parsers should
- use this as their base class.
- """
-
- _data = None
- _template_proc = None
- _include_root = None
- _events_enabled = None
- _event_handlers = None
-
- def __init__(self, parent=None):
- super(LnstParser, self).__init__()
-
- if parent:
- self._data = parent._data
- self._template_proc = parent._template_proc
- self._include_root = parent._include_root
- self._events_enabled = parent._events_enabled
- self._event_handlers = parent._event_handlers
- else:
- self._data = None
- self._template_proc = XmlTemplates()
- self._include_root = os.getcwd()
- self._events_enabled = True
- self._event_handlers = {}
+ try:
+ self._schema.assertValid(doc)
+ except:
+ err = self._schema.error_log[0]
+ loc = {"file": os.path.basename(err.filename),
+ "line": err.line, "col": err.column}
+ exc = XmlProcessingError(err.message)
+ exc.set_loc(loc)
+ raise exc
- def set_target(self, data_dict):
- self._data = data_dict
+ return self._process(root_tag)
- def get_data(self):
- return self._data
+ def _process(self, root_tag):
+ pass
def set_machines(self, machines):
self._template_proc.set_machines(machines)
- def set_definitions(self, defs):
- self._template_proc.set_definitions(defs)
-
- def set_include_root(self, include_root_path):
- self._include_root = include_root_path
-
- def enable_events(self):
- self._events_enabled = True
-
- def disable_events(self):
- self._events_enabled = False
-
- def register_event_handler(self, event_id, handler):
- self._event_handlers[event_id] = handler
-
- def _trigger_event(self, event_id, args):
- if not self._events_enabled:
- return
-
- try:
- handler = self._event_handlers[event_id]
- except KeyError as err:
- logging.warn("No handler found for %s event, ignoring", event_id)
- return
-
- handler(**args)
+ def _has_attribute(self, element, attr):
+ return attr in element.attrib
- def _process_child_nodes(self, node, scheme, params=None,
- default_handler=None, new_ns_level=True):
- scheme["define"] = self._define_handler
+ def _get_attribute(self, element, attr):
+ return self._template_proc.expand_functions(element.attrib[attr])
- if not params:
- params = {}
-
- if new_ns_level:
- self._template_proc.add_namespace_level()
-
- parent = super(LnstParser, self)
- result = parent._process_child_nodes(node, scheme, params,
- default_handler)
-
- if new_ns_level:
- self._template_proc.drop_namespace_level()
-
- return result
-
- def _process_node(self, node, handler, params):
- old_include_root = None
- if self._has_attribute(node, "source"):
- source = str(self._get_attribute(node, "source"))
-
- source_rp = RecipePath(self._include_root, source)
-
- old_include_root = self._include_root
- self._include_root = source_rp.get_root()
- xmlstr = source_rp.to_str()
-
- dom_init = XmlDomTreeInit()
- try:
- dom = dom_init.parse_string(xmlstr,
- filename=source_rp.abs_path())
- except IOError as err:
- msg = "Unable to resolve include: %s" % str(err)
- raise XmlProcessingError(msg, node)
-
- loaded_node = None
- try:
- loaded_node = dom.getElementsByTagName(node.nodeName)[0]
- except Exception:
- msg = ("No '%s' element present in included file '%s'."
- % (node.nodeName, source_rp.abs_path()))
- raise XmlProcessingError(msg, node)
-
- old_attrs = self._get_all_attributes(node)
-
- parent = node.parentNode
- parent.replaceChild(loaded_node, node)
- node = loaded_node
-
- # copy all of the original attributes to the sourced node
- for name, value in old_attrs.iteritems():
- # do not overwrite sourced attributes
- if not node.hasAttribute(name):
- node.setAttribute(name, value)
-
- parent = super(LnstParser, self)
- parent._process_node(node, handler, params)
-
- if old_include_root:
- self._include_root = old_include_root
-
- def _get_attribute(self, node, attr_name, conversion_cb=None):
- parent = super(LnstParser, self)
- raw_attr_val = parent._get_attribute(node, attr_name)
-
- try:
- attr_val = self._template_proc.expand_string(raw_attr_val, node)
- except XmlTemplateError as err:
- raise XmlProcessingError(str(err), node)
-
- return self._convert_string(node, attr_val, conversion_cb)
-
- def _get_text_content(self, node, conversion_cb=None):
- parent = super(LnstParser, self)
- raw_content = parent._get_text_content(node)
-
- try:
- content = self._template_proc.expand_string(raw_content, node)
- except XmlTemplateError as err:
- raise XmlProcessingError(str(err), node)
-
- return self._convert_string(node, content, conversion_cb)
-
- def _define_handler(self, node, params):
- scheme = {"alias": self._alias_handler}
- self._process_child_nodes(node, scheme, new_ns_level=False)
-
- def _alias_handler(self, node, params):
- if self._has_attribute(node, "name"):
- name = str(self._get_attribute(node, "name"))
- else:
- msg = "Alias tag must have the 'name' attribute"
- raise XmlProcessingError(msg, node)
-
- if self._has_attribute(node, "value"):
- value = str(self._get_attribute(node, "value"))
- else:
- value = self._get_text_content(node)
-
- try:
- self._template_proc.define_alias(name, value)
- except XmlTemplateError as err:
- raise XmlProcessingError(str(err), node)
+ def _get_content(self, element):
+ text = etree.tostring(element, method="text")
+ return self._template_proc.expand_functions(text)
10 years, 7 months
[lnst] install: Adding schemes to the distribution
by Jiří Pírko
commit 35efa46f1e3a6edf1f45f9be3e822e00ea9201b5
Author: Radek Pazdera <rpazdera(a)redhat.com>
Date: Wed Aug 28 16:41:24 2013 +0200
install: Adding schemes to the distribution
The schemes need to be installed with the controller so it can use them
during the runtime. This patch adds them to the setup.py script.
By default, they are stored in /usr/share/lnst/, but the path can be
configured in the controller config file using the 'resource_dir'
option.
Signed-off-by: Radek Pazdera <rpazdera(a)redhat.com>
Signed-off-by: Jiri Pirko <jiri(a)resnulli.us>
install/lnst-ctl.conf.in | 65 +++++++++++++++++++++++++--------------------
lnst/Common/Config.py | 5 +++
setup.py | 8 ++++-
3 files changed, 47 insertions(+), 31 deletions(-)
---
diff --git a/install/lnst-ctl.conf.in b/install/lnst-ctl.conf.in
index 576a562..c95a264 100644
--- a/install/lnst-ctl.conf.in
+++ b/install/lnst-ctl.conf.in
@@ -1,45 +1,52 @@
-#This file is used for system-wide controller configuration. It serves mainly
-#to set the default values which will be used when no user configuration is
-#found. Users should set their own configuration in the file
+# This file is used for system-wide controller configuration. It serves mainly
+# to set the default values which will be used when no user configuration is
+# found. Users should set their own configuration in the file
# $HOME$/.lnst/lnst-ctl.conf which will be automatically created when it
-#doesn't exist.
+# doesn't exist.
-#The section environment contains generic options mostly related to the
-#machine the controller is being run on.
+# The section environment contains generic options mostly related to the
+# machine the controller is being run on.
[environment]
-#mac_pool_range is used to specify the range of mac addresses that
-#will be used when creating new devices in virtual machines.
-#The option accepts two valid mac addresses separated by white spaces.
+# 'mac_pool_range' is used to specify the range of mac addresses that will
+# be used when creating new devices in virtual machines. The option accepts
+# two valid mac addresses separated by white spaces.
mac_pool_range = 52:54:01:00:00:01 52:54:01:FF:FF:FF
-#The rpcport options specifies the default port we will be connecting to, when
-#connecting to slave rpc servers.
-#The option accepts a single integer value.
+# The 'rpcport' options specifies the default port we will be connecting to,
+# when connecting to slave rpc servers. The option accepts a single integer
+# value.
rpcport = 9999
-#machine_pool_dirs specifies where the controller should look for specifications
-#of machines that can be used for matching templates inside recipes. This
-#option accepts a variable number of directory paths separated by white spaces.
-#It is also important to note that you can use the operator += to add to the
-#list of directories. If the operator = is used, the previous list is replaced.
+# This option specifies where the controller should look for specifications
+# of machines that can be used for matching templates inside recipes. It
+# accepts a variable number of directory paths separated by white spaces.
+# It is also important to note that you can use the operator += to add to
+# the list of directories. If the operator = is used, the previous list is
+# replaced.
machine_pool_dirs =
-#test_tool_dirs specifies where the controller looks for custom tools that
-#are used in tests. Every tool has it's own subdirectory in one of the
-#directories in this list. The option behaves the same way as the option
-#machine_pool_dirs, it accepts a list of directory paths and both operators,
+# 'test_tool_dirs' specifies where the controller looks for custom tools that
+# are used in tests. Every tool has it's own subdirectory in one of the
+# directories in this list. The option behaves the same way as the option
+# machine_pool_dirs, it accepts a list of directory paths and both operators,
# += and = can be used
test_tool_dirs = @ctl_tools_locations@
-#test_module_dirs specifies where the controller looks for custom test modules
-#the test modules need to be named Test<name>.py otherwise they won't be
-#recognized. The behaviour of the option is the same as test_tool_dirs, it
-#accepts a list of directory paths and both operators, += and = can be used.
+# 'test_module_dirs' specifies where the controller looks for custom test
+# modules the test modules need to be named Test<name>.py otherwise they won't
+# be recognized. The behaviour of the option is the same as test_tool_dirs, it
+# accepts a list of directory paths and both operators, += and = can be used.
test_module_dirs = @ctl_modules_locations@
-#log_dir option redirects the location of where logs are stored. Every run of
-#the application creates its own timestamped subdirectory in the path specified
-#in this option. The option accepts one directory path that will be created if
-#it doesn't exist. You cannot use the operator += here.
+# The 'resource_dir' option specifies, where are the generic resources
+# for LNST (such as XML schemas) installed. This option is set during the
+# installation and generally doesn't need to be changed (unless you know
+# what you're doing!).
+resource_dir = @ctl_resource_dir@
+
+# The 'log_dir' option redirects the location of where logs are stored. Every
+# run of the application creates its own timestamped subdirectory in the path
+# specified in this option. The option accepts one directory path that will
+# be created if it doesn't exist. You cannot use the operator += here.
log_dir = @ctl_logs_dir@
diff --git a/lnst/Common/Config.py b/lnst/Common/Config.py
index 67921d4..40e70da 100644
--- a/lnst/Common/Config.py
+++ b/lnst/Common/Config.py
@@ -64,6 +64,11 @@ class Config():
"additive" : False,
"action" : self.optionPath,
"name" : "log_dir"}
+ self.options['environment']['resource_dir'] = {\
+ "value" : "",
+ "additive" : False,
+ "action" : self.optionPath,
+ "name" : "resource_dir"}
self.colours_scheme()
diff --git a/setup.py b/setup.py
index 9fc6ebe..8f12344 100755
--- a/setup.py
+++ b/setup.py
@@ -45,6 +45,7 @@ MAN_DIR = "/usr/share/man/man1/"
CTL_MODULES_LOCATIONS = "/usr/share/lnst/test_modules/"
CTL_TOOLS_LOCATIONS = "/usr/share/lnst/test_tools/"
+CTL_RESOURCE_DIR = "/usr/share/lnst/"
CTL_LOGS_DIR = "~/.lnst/logs/"
SLAVE_LOGS_DIR = "/var/log/lnst"
@@ -57,6 +58,7 @@ TEMPLATES_VALUES = {
"ctl_modules_locations": CTL_MODULES_LOCATIONS,
"ctl_tools_locations": CTL_TOOLS_LOCATIONS,
+"ctl_resource_dir": CTL_RESOURCE_DIR,
"ctl_logs_dir": CTL_LOGS_DIR,
"slave_logs_dir": SLAVE_LOGS_DIR,
@@ -143,9 +145,11 @@ MULTICAST_TEST_TOOLS = [
MAN_PAGES = [(MAN_DIR, ["install/lnst-ctl.1.gz", "install/lnst-slave.1.gz"])]
-CONFIG = [("/etc/", ["install/lnst-ctl.conf", "install/lnst-slave.conf"])]
+CONFIG = [(CONF_DIR, ["install/lnst-ctl.conf", "install/lnst-slave.conf"])]
-DATA_FILES = CONFIG + TEST_MODULES + MULTICAST_TEST_TOOLS + MAN_PAGES
+SCHEMAS = [(CTL_RESOURCE_DIR, ["schema-recipe.rng", "schema-sm.rng"])]
+
+DATA_FILES = CONFIG + TEST_MODULES + MULTICAST_TEST_TOOLS + MAN_PAGES + SCHEMAS
setup(name="lnst",
version="git",
10 years, 7 months
[lnst] schema: Adding a schema for slavemachine xml
by Jiří Pírko
commit bf0870592cd41f3e2c047aac472760ec4e2fc343
Author: Radek Pazdera <rpazdera(a)redhat.com>
Date: Wed Aug 28 16:41:23 2013 +0200
schema: Adding a schema for slavemachine xml
Signed-off-by: Radek Pazdera <rpazdera(a)redhat.com>
Signed-off-by: Jiri Pirko <jiri(a)resnulli.us>
schema-sm.rng | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 82 insertions(+), 0 deletions(-)
---
diff --git a/schema-sm.rng b/schema-sm.rng
new file mode 100644
index 0000000..454dde1
--- /dev/null
+++ b/schema-sm.rng
@@ -0,0 +1,82 @@
+<grammar xmlns="http://relaxng.org/ns/structure/1.0"
+ datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes">
+ <start>
+ <element name="slavemachine">
+ <interleave>
+ <optional>
+ <ref name="define"/>
+ </optional>
+
+ <zeroOrMore>
+ <ref name="params"/>
+ </zeroOrMore>
+
+ <zeroOrMore>
+ <ref name="interfaces"/>
+ </zeroOrMore>
+ </interleave>
+ </element>
+ </start>
+
+ <define name="define">
+ <element name="define">
+ <oneOrMore>
+ <element name="alias">
+ <attribute name="name"/>
+ <attribute name="value"/>
+ <text/>
+ </element>
+ </oneOrMore>
+ </element>
+ </define>
+
+ <define name="params">
+ <element name="params">
+ <interleave>
+ <optional>
+ <ref name="define"/>
+ </optional>
+
+ <zeroOrMore>
+ <element name="param">
+ <attribute name="name"/>
+ <choice>
+ <attribute name="value"/>
+ <text/>
+ </choice>
+ </element>
+ </zeroOrMore>
+ </interleave>
+ </element>
+ </define>
+
+ <define name="interfaces">
+ <element name="interfaces">
+ <interleave>
+ <optional>
+ <ref name="define"/>
+ </optional>
+
+ <zeroOrMore>
+ <ref name="eth"/>
+ </zeroOrMore>
+ </interleave>
+ </element>
+ </define>
+
+ <define name="eth">
+ <element name="eth">
+ <attribute name="id"/>
+ <attribute name="network"/>
+ <interleave>
+ <optional>
+ <ref name="define"/>
+ </optional>
+
+ <oneOrMore>
+ <ref name="params"/>
+ </oneOrMore>
+ </interleave>
+ </element>
+ </define>
+</grammar>
10 years, 7 months
[lnst] schema: Removing 'source' and changing 'defines'
by Jiří Pírko
commit de873e9acc2ce77aaf2ccb000cc0b4cee0fa7a46
Author: Radek Pazdera <rpazdera(a)redhat.com>
Date: Wed Aug 28 16:41:22 2013 +0200
schema: Removing 'source' and changing 'defines'
The 'source' attribute will no longer be supported (it will be replaced
by XInclude).
This patch also changes the 'define' tags in the scheme from zeroOrMore
to optional, which results in better error reports.
Signed-off-by: Radek Pazdera <rpazdera(a)redhat.com>
Signed-off-by: Jiri Pirko <jiri(a)resnulli.us>
recipe-schema.rng => schema-recipe.rng | 127 +++++++------------------------
1 files changed, 29 insertions(+), 98 deletions(-)
---
diff --git a/recipe-schema.rng b/schema-recipe.rng
similarity index 77%
rename from recipe-schema.rng
rename to schema-recipe.rng
index 23b2236..7e417cb 100644
--- a/recipe-schema.rng
+++ b/schema-recipe.rng
@@ -3,9 +3,9 @@
<start>
<element name="lnstrecipe">
<interleave>
- <zeroOrMore>
+ <optional>
<ref name="define"/>
- </zeroOrMore>
+ </optional>
<ref name="machines"/>
@@ -18,29 +18,22 @@
<define name="define">
<element name="define">
- <optional>
- <attribute name="source"/>
- </optional>
- <zeroOrMore>
+ <oneOrMore>
<element name="alias">
<attribute name="name"/>
<attribute name="value"/>
<text/>
</element>
- </zeroOrMore>
+ </oneOrMore>
</element>
</define>
<define name="machines">
<element name="machines">
- <optional>
- <attribute name="source"/>
- </optional>
-
<interleave>
- <zeroOrMore>
+ <optional>
<ref name="define"/>
- </zeroOrMore>
+ </optional>
<oneOrMore>
<ref name="machine"/>
@@ -56,10 +49,7 @@
</optional>
<optional>
- <choice>
- <attribute name="source"/>
- <attribute name="python"/>
- </choice>
+ <attribute name="python"/>
</optional>
<optional>
@@ -74,9 +64,9 @@
</optional>
<interleave>
- <zeroOrMore>
+ <optional>
<ref name="define"/>
- </zeroOrMore>
+ </optional>
<zeroOrMore>
<ref name="config"/>
@@ -103,23 +93,17 @@
<define name="machine">
<element name="machine">
<attribute name="id"/>
- <optional>
- <attribute name="source"/>
- </optional>
<interleave>
- <zeroOrMore>
+ <optional>
<ref name="define"/>
- </zeroOrMore>
+ </optional>
<zeroOrMore>
<ref name="params"/>
</zeroOrMore>
<element name="interfaces">
- <optional>
- <attribute name="source"/>
- </optional>
<zeroOrMore>
<choice>
<ref name="eth"/>
@@ -139,13 +123,10 @@
<element name="eth">
<attribute name="id"/>
<attribute name="network"/>
- <optional>
- <attribute name="source"/>
- </optional>
<interleave>
- <zeroOrMore>
+ <optional>
<ref name="define"/>
- </zeroOrMore>
+ </optional>
<zeroOrMore>
<ref name="params"/>
@@ -161,9 +142,6 @@
<define name="bond">
<element name="bond">
<attribute name="id"/>
- <optional>
- <attribute name="source"/>
- </optional>
<ref name="softdevice"/>
</element>
</define>
@@ -171,9 +149,6 @@
<define name="bridge">
<element name="bridge">
<attribute name="id"/>
- <optional>
- <attribute name="source"/>
- </optional>
<ref name="softdevice"/>
</element>
</define>
@@ -181,9 +156,6 @@
<define name="vlan">
<element name="vlan">
<attribute name="id"/>
- <optional>
- <attribute name="source"/>
- </optional>
<ref name="softdevice"/>
</element>
</define>
@@ -191,9 +163,6 @@
<define name="macvlan">
<element name="macvlan">
<attribute name="id"/>
- <optional>
- <attribute name="source"/>
- </optional>
<ref name="softdevice"/>
</element>
</define>
@@ -201,18 +170,15 @@
<define name="team">
<element name="team">
<attribute name="id"/>
- <optional>
- <attribute name="source"/>
- </optional>
<ref name="softdevice"/>
</element>
</define>
<define name="softdevice">
<interleave>
- <zeroOrMore>
+ <optional>
<ref name="define"/>
- </zeroOrMore>
+ </optional>
<optional>
<ref name="options"/>
@@ -220,28 +186,20 @@
<optional>
<element name="slaves">
- <optional>
- <attribute name="source"/>
- </optional>
-
<interleave>
- <zeroOrMore>
+ <optional>
<ref name="define"/>
- </zeroOrMore>
+ </optional>
<zeroOrMore>
<element name="slave">
<attribute name="id"/>
<optional>
- <attribute name="source"/>
- </optional>
-
- <optional>
<interleave>
- <zeroOrMore>
+ <optional>
<ref name="define"/>
- </zeroOrMore>
+ </optional>
<zeroOrMore>
<ref name="options"/>
@@ -263,20 +221,13 @@
<define name="options">
<element name="options">
- <optional>
- <attribute name="source"/>
- </optional>
-
<interleave>
- <zeroOrMore>
+ <optional>
<ref name="define"/>
- </zeroOrMore>
+ </optional>
<zeroOrMore>
<element name="option">
- <optional>
- <attribute name="source"/>
- </optional>
<attribute name="name"/>
<choice>
<attribute name="value"/>
@@ -290,20 +241,13 @@
<define name="addresses">
<element name="addresses">
- <optional>
- <attribute name="source"/>
- </optional>
-
<interleave>
- <zeroOrMore>
+ <optional>
<ref name="define"/>
- </zeroOrMore>
+ </optional>
<zeroOrMore>
<element name="address">
- <optional>
- <attribute name="source"/>
- </optional>
<attribute name="value"/>
<text/>
</element>
@@ -314,23 +258,18 @@
<define name="params">
<element name="params">
- <optional>
- <attribute name="source"/>
- </optional>
-
<interleave>
- <zeroOrMore>
+ <optional>
<ref name="define"/>
- </zeroOrMore>
+ </optional>
<zeroOrMore>
<element name="param">
- <optional>
- <attribute name="source"/>
- </optional>
<attribute name="name"/>
- <attribute name="value"/>
- <text/>
+ <choice>
+ <attribute name="value"/>
+ <text/>
+ </choice>
</element>
</zeroOrMore>
</interleave>
@@ -371,10 +310,6 @@
</optional>
<optional>
- <attribute name="source"/>
- </optional>
-
- <optional>
<ref name="options"/>
</optional>
</element>
@@ -408,10 +343,6 @@
</optional>
<optional>
- <attribute name="source"/>
- </optional>
-
- <optional>
<ref name="options"/>
</optional>
</element>
10 years, 7 months
[lnst] schema: Updating the cmd-sequence to task
by Jiří Pírko
commit 3203626b5c855b1a2049efd567e4b441cd4b2b68
Author: Radek Pazdera <rpazdera(a)redhat.com>
Date: Wed Aug 28 16:41:21 2013 +0200
schema: Updating the cmd-sequence to task
The command sequence changed to task. This patch updates the relax-ng
scheme to reflect those changes.
Signed-off-by: Radek Pazdera <rpazdera(a)redhat.com>
Signed-off-by: Jiri Pirko <jiri(a)resnulli.us>
recipe-schema.rng | 299 ++++++++++++++++++++++-------------------------------
1 files changed, 122 insertions(+), 177 deletions(-)
---
diff --git a/recipe-schema.rng b/recipe-schema.rng
index 9f109af..23b2236 100644
--- a/recipe-schema.rng
+++ b/recipe-schema.rng
@@ -10,7 +10,7 @@
<ref name="machines"/>
<oneOrMore>
- <ref name="command_sequence"/>
+ <ref name="task"/>
</oneOrMore>
</interleave>
</element>
@@ -49,10 +49,17 @@
</element>
</define>
- <define name="command_sequence">
- <element name="command_sequence">
+ <define name="task">
+ <element name="task">
<optional>
- <attribute name="source"/>
+ <attribute name="label"/>
+ </optional>
+
+ <optional>
+ <choice>
+ <attribute name="source"/>
+ <attribute name="python"/>
+ </choice>
</optional>
<optional>
@@ -60,6 +67,8 @@
<choice>
<value>yes</value>
<value>no</value>
+ <value>true</value>
+ <value>false</value>
</choice>
</attribute>
</optional>
@@ -70,7 +79,22 @@
</zeroOrMore>
<zeroOrMore>
- <ref name="command"/>
+ <ref name="config"/>
+ </zeroOrMore>
+ <zeroOrMore>
+ <ref name="run"/>
+ </zeroOrMore>
+ <zeroOrMore>
+ <ref name="wait"/>
+ </zeroOrMore>
+ <zeroOrMore>
+ <ref name="intr"/>
+ </zeroOrMore>
+ <zeroOrMore>
+ <ref name="kill"/>
+ </zeroOrMore>
+ <zeroOrMore>
+ <ref name="ctl_wait"/>
</zeroOrMore>
</interleave>
</element>
@@ -313,203 +337,124 @@
</element>
</define>
- <define name="command">
- <element name="command">
- <choice>
- <ref name="ctl_wait"/>
- <ref name="exec"/>
- <ref name="system_config"/>
- <ref name="test"/>
- <ref name="control_commands"/>
- </choice>
+ <define name="config">
+ <element name="config">
+ <attribute name="machine"/>
<optional>
- <ref name="options"/>
+ <attribute name="option"/>
+ <attribute name="value"/>
</optional>
- </element>
- </define>
-
- <define name="ctl_wait">
- <attribute name="type">
- <value>ctl_wait</value>
- </attribute>
-
- <optional>
- <attribute name="value">
- <data type="integer"/>
- </attribute>
- </optional>
- </define>
- <define name="exec">
- <attribute name="machine_id"/>
-
- <attribute name="type">
- <value>exec</value>
- </attribute>
-
- <optional>
- <attribute name="bg_id"/>
- </optional>
-
- <optional>
- <attribute name="value"/>
- </optional>
-
- <optional>
- <attribute name="timeout">
- <data type="integer"/>
- </attribute>
- </optional>
-
- <optional>
- <attribute name="option"/>
- </optional>
+ <!-- Should config have timeout? -->
+ <optional>
+ <attribute name="timeout">
+ <data type="integer"/>
+ </attribute>
+ </optional>
- <optional>
- <attribute name="desc"/>
- </optional>
+ <optional>
+ <attribute name="persistent">
+ <choice>
+ <value>true</value>
+ <value>false</value>
+ <value>yes</value>
+ <value>no</value>
+ <value>1</value>
+ <value>0</value>
+ </choice>
+ </attribute>
+ </optional>
- <optional>
- <attribute name="from"/>
- </optional>
+ <optional>
+ <attribute name="desc"/>
+ </optional>
- <optional>
- <attribute name="source"/>
- </optional>
+ <optional>
+ <attribute name="source"/>
+ </optional>
- <optional>
- <attribute name="pass_result">
- <choice>
- <value>true</value>
- <value>false</value>
- </choice>
- </attribute>
- </optional>
+ <optional>
+ <ref name="options"/>
+ </optional>
+ </element>
</define>
- <define name="system_config">
- <attribute name="machine_id"/>
+ <define name="run">
+ <element name="run">
+ <attribute name="machine"/>
- <attribute name="type">
- <value>system_config</value>
- </attribute>
+ <choice>
+ <attribute name="module"/>
+ <ref name="run_command"/>
+ </choice>
- <optional>
- <attribute name="value"/>
- </optional>
+ <optional>
+ <attribute name="bg_id"/>
+ </optional>
- <optional>
- <attribute name="timeout">
- <data type="integer"/>
- </attribute>
- </optional>
+ <optional>
+ <attribute name="expect"/>
+ </optional>
- <optional>
- <attribute name="option"/>
- </optional>
+ <optional>
+ <attribute name="timeout">
+ <data type="integer"/>
+ </attribute>
+ </optional>
- <optional>
- <attribute name="persistent">
- <choice>
- <value>true</value>
- <value>false</value>
- </choice>
- </attribute>
- </optional>
+ <optional>
+ <attribute name="desc"/>
+ </optional>
- <optional>
- <attribute name="desc"/>
- </optional>
+ <optional>
+ <attribute name="source"/>
+ </optional>
- <optional>
- <attribute name="source"/>
- </optional>
+ <optional>
+ <ref name="options"/>
+ </optional>
+ </element>
</define>
- <define name="test">
- <attribute name="machine_id"/>
-
- <attribute name="type">
- <value>test</value>
- </attribute>
-
- <optional>
- <attribute name="bg_id"/>
- </optional>
-
- <optional>
- <attribute name="value"/>
- </optional>
-
- <optional>
- <attribute name="timeout">
- <data type="integer"/>
- </attribute>
- </optional>
-
- <optional>
- <attribute name="option"/>
- </optional>
-
- <optional>
- <attribute name="desc"/>
- </optional>
-
- <optional>
- <attribute name="source"/>
- </optional>
-
- <optional>
- <attribute name="pass_result">
- <choice>
- <value>true</value>
- <value>false</value>
- </choice>
- </attribute>
- </optional>
+ <define name="run_command">
+ <choice>
+ <attribute name="command"/>
+ <ref name="run_tool"/>
+ </choice>
</define>
- <define name="control_commands">
- <attribute name="machine_id"/>
-
- <attribute name="type">
- <choice>
- <value>wait</value>
- <value>intr</value>
- <value>kill</value>
- </choice>
- </attribute>
-
- <optional>
- <attribute name="value"/>
- </optional>
+ <define name="run_tool">
+ <attribute name="command"/>
+ <attribute name="from"/>
+ </define>
- <optional>
- <attribute name="timeout">
- <data type="integer"/>
- </attribute>
- </optional>
+ <define name="wait">
+ <element name="wait">
+ <ref name="signal_command"/>
+ </element>
+ </define>
- <optional>
- <attribute name="option"/>
- </optional>
+ <define name="intr">
+ <element name="intr">
+ <ref name="signal_command"/>
+ </element>
+ </define>
- <optional>
- <attribute name="desc"/>
- </optional>
+ <define name="kill">
+ <element name="kill">
+ <ref name="signal_command"/>
+ </element>
+ </define>
- <optional>
- <attribute name="source"/>
- </optional>
+ <define name="signal_command">
+ <attribute name="machine"/>
+ <attribute name="bg_id"/>
+ </define>
- <optional>
- <attribute name="pass_result">
- <choice>
- <value>true</value>
- <value>false</value>
- </choice>
- </attribute>
- </optional>
+ <define name="ctl_wait">
+ <element name="ctl_wait">
+ <attribute name="seconds"/>
+ </element>
</define>
</grammar>
10 years, 7 months
[lnst trac] #76: config_only does not work for dynamically created interfaces
by fedora-badges
#76: config_only does not work for dynamically created interfaces
----------------------+-----------------------------
Reporter: jtluka | Owner:
Type: defect | Status: new
Priority: minor | Milestone: Stable Release
Component: lnst-ctl | Version: git
Keywords: | Blocked By:
Blocking: |
----------------------+-----------------------------
In case when virtual guest's interfaces are created from the scratch and
config_only mode is used the devices get destroyed. I'm not quite sure
whether this is a real bug and not a feature since we want to have clean
setup on every run. On other hand it would be handy in case when someone
wants to check his scenario with virtual guests.
--
Ticket URL: <https://fedorahosted.org/lnst/ticket/76>
lnst <https://fedorahosted.org/lnst/>
Linux Network Stack Test
10 years, 7 months
[lnst trac] #75: fix dump_recipe mode
by fedora-badges
#75: fix dump_recipe mode
----------------------+-----------------------------
Reporter: jtluka | Owner:
Type: defect | Status: new
Priority: major | Milestone: Stable Release
Component: lnst-ctl | Version:
Keywords: | Blocked By:
Blocking: |
----------------------+-----------------------------
The dump_recipe mode can be useful for integration with other tools.
Currently it is broken and does not work correctly.
--
Ticket URL: <https://fedorahosted.org/lnst/ticket/75>
lnst <https://fedorahosted.org/lnst/>
Linux Network Stack Test
10 years, 7 months
[PATCH] Fix unhandled error with bad slavemachine xml file
by Jan Tluka
If a slavemachine xml file in pool directory contains xml that does not
start with <slavemachine> tag the controller fails with not very useful
info. This patch checks the first tag is valid and in case it's not the
controller will print the error along with the corrupted filename.
Signed-off-by: Jan Tluka <jtluka(a)redhat.com>
---
lnst/Controller/SlavePool.py | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/lnst/Controller/SlavePool.py b/lnst/Controller/SlavePool.py
index e8baf83..7deb912 100644
--- a/lnst/Controller/SlavePool.py
+++ b/lnst/Controller/SlavePool.py
@@ -67,7 +67,12 @@ class SlavePool:
m_id = re.sub("\.[xX][mM][lL]$", "", basename)
- slavemachine = dom.getElementsByTagName("slavemachine")[0]
+ sm_tag = dom.getElementsByTagName("slavemachine")
+ if len(sm_tag) == 0:
+ msg = "File %s does not contain <slavemachine> tag." % filepath
+ raise Exception(msg)
+
+ slavemachine = sm_tag[0]
xml_data = parser.parse(slavemachine)
machine_spec = self._process_machine_xml_data(m_id, xml_data)
--
1.8.1.4
10 years, 7 months