[ovs-dev] [RFC PATCH 01/10] python: introduce scheleton of ovs_ofparse utility
Adrian Moreno
amorenoz at redhat.com
Mon Nov 22 15:01:48 UTC 2021
ovs-ofparse is a python program that uses ovs.flows library to provide
rich formatting of openflow and datapath flows.
It uses 'click' as the command line argument framework and has the
following syntax:
ovs-ofparse [OPTIONS] [openflow | datapath] FORMAT [FORMAT OPTIONS]
OPTIONS: describe general options that apply to any protocol or format
[openflow | datapath] defines the flow protocol to parse
FORMAT: specifies the format to print the output in
[FORMAT OPTIONS] are optional format-specific options
A generic configuration file called ovs-ofparse.conf is supported
Signed-off-by: Adrian Moreno <amorenoz at redhat.com>
---
python/automake.mk | 8 ++-
python/ovs/ovs_ofparse/__init__.py | 2 +
python/ovs/ovs_ofparse/datapath.py | 10 ++++
python/ovs/ovs_ofparse/main.py | 89 ++++++++++++++++++++++++++++++
python/ovs/ovs_ofparse/openflow.py | 11 ++++
python/ovs/ovs_ofparse/ovs-ofparse | 6 ++
python/setup.py | 8 ++-
7 files changed, 131 insertions(+), 3 deletions(-)
create mode 100644 python/ovs/ovs_ofparse/__init__.py
create mode 100644 python/ovs/ovs_ofparse/datapath.py
create mode 100644 python/ovs/ovs_ofparse/main.py
create mode 100644 python/ovs/ovs_ofparse/openflow.py
create mode 100755 python/ovs/ovs_ofparse/ovs-ofparse
diff --git a/python/automake.mk b/python/automake.mk
index 56cd9b7dc..cfe91c17b 100644
--- a/python/automake.mk
+++ b/python/automake.mk
@@ -51,7 +51,13 @@ ovs_pyfiles = \
python/ovs/flows/ofp_act.py \
python/ovs/flows/odp.py \
python/ovs/flows/filter.py \
- python/ovs/flows/deps.py
+ python/ovs/flows/deps.py \
+ python/ovs/ovs_ofparse/__init__.py \
+ python/ovs/ovs_ofparse/main.py \
+ python/ovs/ovs_ofparse/datapath.py \
+ python/ovs/ovs_ofparse/openflow.py \
+ python/ovs/ovs_ofparse/ovs-ofparse
+
ovs_tests = \
python/ovs/tests/test_kv.py \
diff --git a/python/ovs/ovs_ofparse/__init__.py b/python/ovs/ovs_ofparse/__init__.py
new file mode 100644
index 000000000..ba3a4e7e8
--- /dev/null
+++ b/python/ovs/ovs_ofparse/__init__.py
@@ -0,0 +1,2 @@
+import ovs.ovs_ofparse.openflow # noqa: F401
+import ovs.ovs_ofparse.datapath # noqa: F401
diff --git a/python/ovs/ovs_ofparse/datapath.py b/python/ovs/ovs_ofparse/datapath.py
new file mode 100644
index 000000000..c5bb43fa9
--- /dev/null
+++ b/python/ovs/ovs_ofparse/datapath.py
@@ -0,0 +1,10 @@
+import click
+
+from ovs.ovs_ofparse.main import maincli
+
+
+ at maincli.group(subcommand_metavar="FORMAT")
+ at click.pass_obj
+def datapath(opts):
+ """Process DPIF Flows"""
+ pass
diff --git a/python/ovs/ovs_ofparse/main.py b/python/ovs/ovs_ofparse/main.py
new file mode 100644
index 000000000..09fb08460
--- /dev/null
+++ b/python/ovs/ovs_ofparse/main.py
@@ -0,0 +1,89 @@
+import click
+import os.path
+import configparser
+
+from pkg_resources import resource_filename
+
+_default_config_file = "ovs-ofparse.conf"
+_default_config_path = os.path.abspath(
+ os.path.join(resource_filename(__name__, ""), "etc", _default_config_file)
+)
+
+
+class Options(dict):
+ """Options dictionary"""
+
+ pass
+
+
+def validate_input(ctx, param, value):
+ """Validate the "-i" option"""
+ result = list()
+ for input_str in value:
+ parts = input_str.strip().split(",")
+ if len(parts) == 2:
+ parts = tuple(parts)
+ elif len(parts) == 1:
+ parts = tuple(["Filename: " + parts[0], parts[0]])
+ else:
+ raise click.BadParameter(
+ "input filename should have the following format: "
+ "[alias,]FILENAME"
+ )
+
+ if not os.path.isfile(parts[1]):
+ raise click.BadParameter(
+ "input filename %s does not exist" % parts[1]
+ )
+ result.append(parts)
+ return result
+
+
+ at click.group(
+ subcommand_metavar="TYPE",
+ context_settings=dict(help_option_names=["-h", "--help"]),
+)
+ at click.option(
+ "-c",
+ "--config",
+ help="Use config file",
+ type=click.Path(),
+ default=_default_config_path,
+ show_default=True,
+)
+ at click.option(
+ "-i",
+ "--input",
+ "filename",
+ help="Read flows from specified filepath. If not provided, flows will be"
+ " read from stdin. This option can be specified multiple times."
+ " Format [alias,]FILENAME. Where alias is a name that shall be used to"
+ " refer to this FILENAME",
+ multiple=True,
+ type=click.Path(),
+ callback=validate_input,
+)
+ at click.pass_context
+def maincli(ctx, config, filename):
+ """
+ OpenFlow Parse utility.
+
+ It parses openflow and datapath flows
+ (such as the output of ovs-ofctl dump-flows or ovs-appctl dpctl/dump-flows)
+ and prints them in different formats.
+
+ """
+ ctx.obj = Options()
+ ctx.obj["filename"] = filename or None
+
+ config_file = config or _default_config_path
+ parser = configparser.ConfigParser()
+ parser.read(config_file)
+
+ ctx.obj["config"] = parser
+
+def main():
+ """
+ Main Function
+ """
+ maincli()
diff --git a/python/ovs/ovs_ofparse/openflow.py b/python/ovs/ovs_ofparse/openflow.py
new file mode 100644
index 000000000..0035c8118
--- /dev/null
+++ b/python/ovs/ovs_ofparse/openflow.py
@@ -0,0 +1,11 @@
+import click
+
+
+from ovs.ovs_ofparse.main import maincli
+
+
+ at maincli.group(subcommand_metavar="FORMAT")
+ at click.pass_obj
+def openflow(opts):
+ """Process OpenFlow Flows"""
+ pass
diff --git a/python/ovs/ovs_ofparse/ovs-ofparse b/python/ovs/ovs_ofparse/ovs-ofparse
new file mode 100755
index 000000000..32c503e9d
--- /dev/null
+++ b/python/ovs/ovs_ofparse/ovs-ofparse
@@ -0,0 +1,6 @@
+#!/usr/bin/env python3
+
+from ovs.ovs_ofparse import main
+
+if __name__ == '__main__':
+ main.main()
diff --git a/python/setup.py b/python/setup.py
index 4e8a9761a..6643f59cd 100644
--- a/python/setup.py
+++ b/python/setup.py
@@ -71,7 +71,7 @@ setup_args = dict(
author='Open vSwitch',
author_email='dev at openvswitch.org',
packages=['ovs', 'ovs.compat', 'ovs.compat.sortedcontainers',
- 'ovs.db', 'ovs.unixctl', 'ovs.flows'],
+ 'ovs.db', 'ovs.unixctl', 'ovs.flows', 'ovs.ovs_ofparse'],
keywords=['openvswitch', 'ovs', 'OVSDB'],
license='Apache 2.0',
classifiers=[
@@ -87,7 +87,11 @@ setup_args = dict(
ext_modules=[setuptools.Extension("ovs._json", sources=["ovs/_json.c"],
libraries=['openvswitch'])],
cmdclass={'build_ext': try_build_ext},
- install_requires=['sortedcontainers', 'netaddr', 'pyparsing'],
+ install_requires=['sortedcontainers',
+ 'netaddr',
+ 'pyparsing',
+ 'click'],
+ scripts=['ovs/ovs_ofparse/ovs-ofparse'],
extras_require={':sys_platform == "win32"': ['pywin32 >= 1.0']},
)
--
2.31.1
More information about the dev
mailing list