Re: [ovs-dev] [PATCH v1 09/12] python: ovs: flowviz: Add datapath html format.

2024-02-29 Thread Eelco Chaudron



On 19 Feb 2024, at 9:14, Adrian Moreno wrote:

> Using the existing FlowTree and HTMLFormatter, create an HTML tree
> visualization that also supports collapsing and expanding entire flow
> trees and subtrees.
>
> Examples:
> $ ovs-appcl dpctl/dump-flows | ovs-flowviz --highlight drop datapath
> html > /tmp/flows.html
> $ ovs-appcl dpctl/dump-flows | ovs-flowviz -f "output.port=3"
> datapath html > /tmp/flows.html
>
> Acked-by: Eelco Chaudron 
> Signed-off-by: Adrian Moreno 

Thanks for adding the example to the commit message.

Acked-by: Eelco Chaudron 

___
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev


[ovs-dev] [PATCH v1 09/12] python: ovs: flowviz: Add datapath html format.

2024-02-19 Thread Adrian Moreno
Using the existing FlowTree and HTMLFormatter, create an HTML tree
visualization that also supports collapsing and expanding entire flow
trees and subtrees.

Examples:
$ ovs-appcl dpctl/dump-flows | ovs-flowviz --highlight drop datapath
html > /tmp/flows.html
$ ovs-appcl dpctl/dump-flows | ovs-flowviz -f "output.port=3"
datapath html > /tmp/flows.html

Acked-by: Eelco Chaudron 
Signed-off-by: Adrian Moreno 
---
 python/automake.mk |   1 +
 python/ovs/flowviz/odp/cli.py  |  10 ++
 python/ovs/flowviz/odp/html.py | 259 +
 3 files changed, 270 insertions(+)
 create mode 100644 python/ovs/flowviz/odp/html.py

diff --git a/python/automake.mk b/python/automake.mk
index 449daf023..44e9e08ab 100644
--- a/python/automake.mk
+++ b/python/automake.mk
@@ -71,6 +71,7 @@ ovs_flowviz = \
python/ovs/flowviz/main.py \
python/ovs/flowviz/odp/__init__.py \
python/ovs/flowviz/odp/cli.py \
+   python/ovs/flowviz/odp/html.py \
python/ovs/flowviz/odp/tree.py \
python/ovs/flowviz/ofp/__init__.py \
python/ovs/flowviz/ofp/cli.py \
diff --git a/python/ovs/flowviz/odp/cli.py b/python/ovs/flowviz/odp/cli.py
index 4740e753e..059dd708e 100644
--- a/python/ovs/flowviz/odp/cli.py
+++ b/python/ovs/flowviz/odp/cli.py
@@ -14,6 +14,7 @@
 
 import click
 from ovs.flowviz.main import maincli
+from ovs.flowviz.odp.html import HTMLTreeProcessor
 from ovs.flowviz.odp.tree import ConsoleTreeProcessor
 from ovs.flowviz.process import (
 DatapathFactory,
@@ -82,3 +83,12 @@ def tree(opts, heat_map):
 processor = ConsoleTreeProcessor(opts)
 processor.process()
 processor.print(heat_map)
+
+
+@datapath.command()
+@click.pass_obj
+def html(opts):
+"""Print the flows in an HTML list sorted by recirc_id."""
+processor = HTMLTreeProcessor(opts)
+processor.process()
+processor.print()
diff --git a/python/ovs/flowviz/odp/html.py b/python/ovs/flowviz/odp/html.py
new file mode 100644
index 0..4aa08dc70
--- /dev/null
+++ b/python/ovs/flowviz/odp/html.py
@@ -0,0 +1,259 @@
+# Copyright (c) 2023 Red Hat, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at:
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from ovs.flowviz.html_format import HTMLBuffer, HTMLFormatter
+from ovs.flowviz.odp.tree import FlowElem, FlowTree
+from ovs.flowviz.process import DatapathFactory, FileProcessor
+
+
+class HTMLTreeProcessor(DatapathFactory, FileProcessor):
+def __init__(self, opts):
+super().__init__(opts)
+self.data = dict()
+
+def start_file(self, name, filename):
+self.tree = HTMLTree(name, self.opts)
+
+def process_flow(self, flow, name):
+self.tree.add(flow)
+
+def process(self):
+super().process(False)
+
+def stop_file(self, name, filename):
+self.data[name] = self.tree
+
+def print(self):
+html_obj = ""
+for name, tree in self.data.items():
+html_obj += ""
+html_obj += "{}".format(name)
+tree.build()
+if self.opts.get("filter"):
+tree.filter(self.opts.get("filter"))
+html_obj += tree.render()
+html_obj += ""
+print(html_obj)
+
+
+class HTMLTree(FlowTree):
+"""HTMLTree is a Flowtree that prints the tree in html format.
+
+Args:
+opts(dict): Options dictionary
+flows(dict[int, list[DPFlow]): Optional; initial flows
+"""
+
+html_header = """
+
+.flow{
+background-color:white;
+display: inline-block;
+text-align: left;
+font-family: monospace;
+}
+.active{
+border: 2px solid #0008ff;
+}
+input[type='checkbox'] { display: none; }
+.wrap-collabsible {
+margin: 1.2rem 0;
+}
+.lbl-toggle-main {
+font-weight: bold;
+font-family: monospace;
+font-size: 1.5rem;
+text-transform: uppercase;
+text-align: center;
+padding: 1rem;
+#cursor: pointer;
+border-radius: 7px;
+transition: all 0.25s ease-out;
+}
+.lbl-toggle-flow {
+font-family: monospace;
+font-size: 1.0rem;
+text-transform: uppercase;
+text-align: center;
+padding: 1rem;
+#cursor: pointer;
+border-radius: 7px;
+transition: all 0.25s ease-out;
+}
+.lbl-toggle:hover {
+color: #0008ff;
+}
+.lbl-toggle::before {
+content: ' ';
+display: inline-block;
+