Introduce an HTTP server that exports the OVS metrics.
The exporter can be configured in:

  /etc/openvswitch/ovs-exporter.conf:
  [exporter]
  port = 6103
  extended = no
  debug = no

It is started / stopped with systemd:

  systemctl start ovs-exporter
  systemctl stop ovs-exporter

Alternatively, if no package was installed, ovs-ctl can be used:

  /usr/share/openvswitch/scripts/ovs-ctl start-ovs-exporter
  /usr/share/openvswitch/scripts/ovs-ctl stop-ovs-exporter

When started by systemd or ovs-ctl, a log file is used:

  /var/log/openvswitchd/ovs-exporter.log

The Prometheus client library is used to parse the output from
ovs-vswitchd, collect it and expose it through an HTTP server.

Signed-off-by: Gaetan Rivet <[email protected]>
---
 Documentation/automake.mk                     |   1 +
 Documentation/conf.py                         |   2 +
 Documentation/ref/index.rst                   |   1 +
 Documentation/ref/ovs-exporter.8.rst          |  78 +++++++
 debian/automake.mk                            |   2 +
 debian/openvswitch-switch.install             |   3 +
 debian/openvswitch-switch.ovs-exporter.conf   |   4 +
 .../openvswitch-switch.ovs-exporter.service   |  18 ++
 debian/rules                                  |   2 +
 rhel/automake.mk                              |   2 +
 rhel/etc_openvswitch_ovs-exporter.conf        |   4 +
 rhel/openvswitch-fedora.spec.in               |   9 +-
 ...sr_lib_systemd_system_ovs-exporter.service |  18 ++
 utilities/.gitignore                          |   1 +
 utilities/automake.mk                         |   3 +
 utilities/ovs-ctl.in                          |  22 ++
 utilities/ovs-exporter.in                     | 216 ++++++++++++++++++
 17 files changed, 385 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/ref/ovs-exporter.8.rst
 create mode 100644 debian/openvswitch-switch.ovs-exporter.conf
 create mode 100644 debian/openvswitch-switch.ovs-exporter.service
 create mode 100644 rhel/etc_openvswitch_ovs-exporter.conf
 create mode 100644 rhel/usr_lib_systemd_system_ovs-exporter.service
 create mode 100755 utilities/ovs-exporter.in

diff --git a/Documentation/automake.mk b/Documentation/automake.mk
index 1bfaa16e4f..17f81127d6 100644
--- a/Documentation/automake.mk
+++ b/Documentation/automake.mk
@@ -162,6 +162,7 @@ RST_MANPAGES = \
        ovs-actions.7.rst \
        ovs-appctl.8.rst \
        ovs-ctl.8.rst \
+       ovs-exporter.8.rst \
        ovs-flowviz.8.rst \
        ovs-l3ping.8.rst \
        ovs-metrics.8.rst \
diff --git a/Documentation/conf.py b/Documentation/conf.py
index 7a9e971f71..50ebf2e61d 100644
--- a/Documentation/conf.py
+++ b/Documentation/conf.py
@@ -130,6 +130,8 @@ _man_pages = [
      u'utility for configuring running Open vSwitch daemons'),
     ('ovs-ctl.8',
      u'OVS startup helper script'),
+    ('ovs-exporter.8',
+     u'OVS metrics exporter'),
     ('ovs-flowviz.8',
      u'utility for visualizing OpenFlow and datapath flows'),
     ('ovs-l3ping.8',
diff --git a/Documentation/ref/index.rst b/Documentation/ref/index.rst
index e4ff945c98..87dfe3257b 100644
--- a/Documentation/ref/index.rst
+++ b/Documentation/ref/index.rst
@@ -42,6 +42,7 @@ time:
    ovs-actions.7
    ovs-appctl.8
    ovs-ctl.8
+   ovs-exporter.8
    ovs-flowviz.8
    ovs-metrics.8
    ovs-l3ping.8
diff --git a/Documentation/ref/ovs-exporter.8.rst 
b/Documentation/ref/ovs-exporter.8.rst
new file mode 100644
index 0000000000..b56de2d07b
--- /dev/null
+++ b/Documentation/ref/ovs-exporter.8.rst
@@ -0,0 +1,78 @@
+============
+ovs-exporter
+============
+
+Synopsis
+========
+
+   ovs-exporter [-h] [-p <uint>] [-x] [-d] [-c [CONFIG]] [--unixctl]
+                [--detach] [--no-chdir] [--monitor] [--pidfile [PIDFILE]] 
[--overwrite-pidfile]
+                [--log-file [LOG_FILE]] [-v [VERBOSE ...]]
+
+Description
+===========
+
+``ovs-exporter`` starts an HTTP server to export the OVS metrics.
+
+This process is usually started using ``ovs-ctl start-ovs-exporter``, as it
+will provide the required parameters for proper interfacing.
+
+Options
+=======
+
+*  ``-p <uint>, --port <uint>``
+
+  TCP port to listen on.
+
+*  ``-x, --extended``
+
+  Also export the extended metrics page
+
+*  ``-d, --debug``
+
+  Also export the debug metrics page
+
+*  ``-c, --config [CONFIG]``
+
+  Read configuration from file (default /etc/openvswitch/ovs-exporter.conf)
+
+* ``--unixctl``
+
+  Start a ``unixctl`` server in the process.
+  This server allows the Open vSwitch scripts to interface with the process,
+  for e.g. clean exit.
+
+*  ``--detach``
+
+  Run in background as a daemon.
+
+*  ``--no-chdir``
+
+  Do not chdir to '/'.
+
+*  ``--monitor``
+
+  Monitor ovs-exporter process.
+
+*  ``--pidfile [PIDFILE]``
+
+  Create pidfile (default /var/run/openvswitch/ovs-exporter.pid).
+
+*  ``--overwrite-pidfile``
+
+  With --pidfile, start even if already running.
+
+*  ``--log-file [LOG_FILE]``
+
+  Enables logging to a file. Default log file is used if LOG_FILE is omitted.
+
+*  ``-v [VERBOSE ...], --verbose [VERBOSE ...]``
+
+  Sets logging levels, see ovs-vswitchd(8). Defaults to dbg.
+
+See Also
+========
+
+   /etc/openvswitch/ovs-exporter.conf
+
+``ovs-metrics(8)``, ``ovs-vswitchd(8)``
diff --git a/debian/automake.mk b/debian/automake.mk
index 7ae4e00e58..5f05d51869 100644
--- a/debian/automake.mk
+++ b/debian/automake.mk
@@ -40,6 +40,8 @@ EXTRA_DIST += \
        debian/openvswitch-switch.ovs-record-hostname.service \
        debian/openvswitch-switch.ovs-vswitchd.service \
        debian/openvswitch-switch.ovsdb-server.service \
+       debian/openvswitch-switch.ovs-exporter.service \
+       debian/openvswitch-switch.ovs-exporter.conf \
        debian/openvswitch-switch.postinst \
        debian/openvswitch-switch.postrm \
        debian/openvswitch-switch.preinst \
diff --git a/debian/openvswitch-switch.install 
b/debian/openvswitch-switch.install
index ca20d35f8b..537a5b9e89 100755
--- a/debian/openvswitch-switch.install
+++ b/debian/openvswitch-switch.install
@@ -1,6 +1,7 @@
 #!/usr/bin/dh-exec
 debian/ifupdown.sh usr/share/openvswitch/scripts
 debian/openvswitch-switch.default => 
/usr/share/openvswitch/switch/default.template
+debian/openvswitch-switch.ovs-exporter.conf => 
/etc/openvswitch/ovs-exporter.conf
 debian/ovs-systemd-reload /usr/share/openvswitch/scripts
 etc/bash_completion.d/ovs-vsctl-bashcomp.bash 
usr/share/bash-completion/completions
 usr/bin/ovs-dpctl
@@ -11,6 +12,7 @@ usr/bin/ovs-tcpundump
 usr/bin/ovs-vlan-test
 usr/bin/ovs-vsctl
 usr/bin/ovs-metrics
+usr/bin/ovs-exporter
 usr/sbin/ovs-vswitchd usr/lib/openvswitch-switch/
 usr/share/man/man1/ovs-pcap.1
 usr/share/man/man1/ovs-tcpundump.1
@@ -24,6 +26,7 @@ usr/share/man/man8/ovs-vlan-test.8
 usr/share/man/man8/ovs-vsctl.8
 usr/share/man/man8/ovs-vswitchd.8
 usr/share/man/man8/ovs-metrics.8
+usr/share/man/man8/ovs-exporter.8
 usr/share/openvswitch/scripts/ovs-check-dead-ifs
 usr/share/openvswitch/scripts/ovs-ctl
 usr/share/openvswitch/scripts/ovs-kmod-ctl
diff --git a/debian/openvswitch-switch.ovs-exporter.conf 
b/debian/openvswitch-switch.ovs-exporter.conf
new file mode 100644
index 0000000000..0cebe83541
--- /dev/null
+++ b/debian/openvswitch-switch.ovs-exporter.conf
@@ -0,0 +1,4 @@
+[exporter]
+port = 6103
+extended = no
+debug = no
diff --git a/debian/openvswitch-switch.ovs-exporter.service 
b/debian/openvswitch-switch.ovs-exporter.service
new file mode 100644
index 0000000000..56ca0cc51e
--- /dev/null
+++ b/debian/openvswitch-switch.ovs-exporter.service
@@ -0,0 +1,18 @@
+[Unit]
+Description=Open vSwitch Metrics Exporter
+After=ovs-vswitchd.service network-pre.target
+Wants=ovs-vswitchd.service
+DefaultDependencies=no
+
+[Service]
+Type=forking
+PIDFile=/run/openvswitch/ovs-exporter.pid
+Restart=on-failure
+Environment=HOME=/var/run/openvswitch
+EnvironmentFile=-/etc/openvswitch/ovs-exporter
+ExecStart=/usr/share/openvswitch/scripts/ovs-ctl --no-monitor 
start-ovs-exporter $OVS_CTL_OPTS
+ExecStop=/usr/share/openvswitch/scripts/ovs-ctl stop-ovs-exporter
+TimeoutSec=10
+
+[Install]
+WantedBy=ovs-vswitchd.service
diff --git a/debian/rules b/debian/rules
index b2a68c6833..92c5e8071f 100755
--- a/debian/rules
+++ b/debian/rules
@@ -121,11 +121,13 @@ override_dh_installinit:
        dh_installinit -popenvswitch-switch --name=ovsdb-server --no-start
        dh_installinit -popenvswitch-switch --name=ovs-vswitchd --no-start
        dh_installinit -popenvswitch-switch --name=ovs-record-hostname 
--no-start
+       dh_installinit -popenvswitch-switch --name=ovs-exporter --no-start 
--no-enable
 
 override_dh_installsystemd:
        dh_installsystemd -popenvswitch-switch --name=ovsdb-server --no-start
        dh_installsystemd -popenvswitch-switch --name=ovs-vswitchd --no-start
        dh_installsystemd -popenvswitch-switch --name=ovs-record-hostname 
--no-start
+       dh_installsystemd -popenvswitch-switch --name=ovs-exporter --no-start 
--no-enable
        dh_installsystemd --restart-after-upgrade -Xovs-vswitchd.service 
-Xovsdb-server.service -Xovs-record-hostname.service
 
 override_dh_strip:
diff --git a/rhel/automake.mk b/rhel/automake.mk
index 246bfb51e4..9988cd408d 100644
--- a/rhel/automake.mk
+++ b/rhel/automake.mk
@@ -11,6 +11,7 @@ EXTRA_DIST += \
        rhel/etc_init.d_openvswitch \
        rhel/etc_logrotate.d_openvswitch \
        rhel/etc_openvswitch_default.conf \
+       rhel/etc_openvswitch_ovs-exporter.conf \
        rhel/etc_sysconfig_network-scripts_ifdown-ovs \
        rhel/etc_sysconfig_network-scripts_ifup-ovs \
        rhel/openvswitch.spec \
@@ -24,6 +25,7 @@ EXTRA_DIST += \
        rhel/usr_lib_systemd_system_openvswitch.service \
        rhel/usr_lib_systemd_system_ovsdb-server.service \
        rhel/usr_lib_systemd_system_ovs-vswitchd.service.in \
+       rhel/usr_lib_systemd_system_ovs-exporter.service \
        rhel/usr_lib_systemd_system_ovs-delete-transient-ports.service \
        rhel/usr_lib_systemd_system_openvswitch-ipsec.service
 
diff --git a/rhel/etc_openvswitch_ovs-exporter.conf 
b/rhel/etc_openvswitch_ovs-exporter.conf
new file mode 100644
index 0000000000..0cebe83541
--- /dev/null
+++ b/rhel/etc_openvswitch_ovs-exporter.conf
@@ -0,0 +1,4 @@
+[exporter]
+port = 6103
+extended = no
+debug = no
diff --git a/rhel/openvswitch-fedora.spec.in b/rhel/openvswitch-fedora.spec.in
index f7801024bd..a454f55379 100644
--- a/rhel/openvswitch-fedora.spec.in
+++ b/rhel/openvswitch-fedora.spec.in
@@ -225,7 +225,7 @@ install -p -D -m 0644 \
         rhel/usr_share_openvswitch_scripts_systemd_sysconfig.template \
         $RPM_BUILD_ROOT/%{_sysconfdir}/sysconfig/openvswitch
 for service in openvswitch ovsdb-server ovs-vswitchd 
ovs-delete-transient-ports \
-                openvswitch-ipsec; do
+                openvswitch-ipsec ovs-exporter; do
         install -p -D -m 0644 \
                         rhel/usr_lib_systemd_system_${service}.service \
                         $RPM_BUILD_ROOT%{_unitdir}/${service}.service
@@ -236,6 +236,9 @@ install -m 0755 rhel/etc_init.d_openvswitch \
 install -p -D -m 0644 rhel/etc_openvswitch_default.conf \
         $RPM_BUILD_ROOT/%{_sysconfdir}/openvswitch/default.conf
 
+install -p -D -m 0644 rhel/etc_openvswitch_ovs-exporter.conf \
+        $RPM_BUILD_ROOT/%{_sysconfdir}/openvswitch/ovs-exporter.conf
+
 install -p -D -m 0644 rhel/etc_logrotate.d_openvswitch \
         $RPM_BUILD_ROOT/%{_sysconfdir}/logrotate.d/openvswitch
 
@@ -450,6 +453,7 @@ fi
 %endif
 %dir %{_sysconfdir}/openvswitch
 %{_sysconfdir}/openvswitch/default.conf
+%{_sysconfdir}/openvswitch/ovs-exporter.conf
 %config %ghost %{_sharedstatedir}/openvswitch/conf.db
 %ghost %{_sharedstatedir}/openvswitch/.conf.db.~lock~
 %config %ghost %{_sysconfdir}/openvswitch/system-id.conf
@@ -461,6 +465,7 @@ fi
 %{_unitdir}/openvswitch.service
 %{_unitdir}/ovsdb-server.service
 %{_unitdir}/ovs-vswitchd.service
+%{_unitdir}/ovs-exporter.service
 %{_unitdir}/ovs-delete-transient-ports.service
 %{_datadir}/openvswitch/scripts/openvswitch.init
 %if ! (0%{?rhel} > 7 || (0%{?fedora} > 28 && 0%{?fedora} < 41))
@@ -483,6 +488,7 @@ fi
 %{_bindir}/ovs-docker
 %{_bindir}/ovs-dpctl
 %{_bindir}/ovs-dpctl-top
+%{_bindir}/ovs-exporter
 %{_bindir}/ovs-metrics
 %{_bindir}/ovs-ofctl
 %{_bindir}/ovs-vsctl
@@ -514,6 +520,7 @@ fi
 %{_mandir}/man8/ovs-dpctl.8*
 %{_mandir}/man8/ovs-dpctl-top.8*
 %{_mandir}/man8/ovs-kmod-ctl.8*
+%{_mandir}/man8/ovs-exporter.8*
 %{_mandir}/man8/ovs-metrics.8*
 %{_mandir}/man8/ovs-ofctl.8*
 %{_mandir}/man8/ovs-pki.8*
diff --git a/rhel/usr_lib_systemd_system_ovs-exporter.service 
b/rhel/usr_lib_systemd_system_ovs-exporter.service
new file mode 100644
index 0000000000..4107766bd8
--- /dev/null
+++ b/rhel/usr_lib_systemd_system_ovs-exporter.service
@@ -0,0 +1,18 @@
+[Unit]
+Description=Open vSwitch Metrics Exporter
+After=ovs-vswitchd.service network-pre.target
+Wants=ovs-vswitchd.service
+AssertPathIsReadWrite=/run/openvswitch
+
+[Service]
+Type=forking
+PIDFile=/run/openvswitch/ovs-exporter.pid
+Restart=on-failure
+Environment=XDG_RUNTIME_DIR=/run/openvswitch
+EnvironmentFile=-/etc/openvswitch/ovs-exporter
+ExecStart=/usr/share/openvswitch/scripts/ovs-ctl --no-monitor 
start-ovs-exporter $OVS_CTL_OPTS
+ExecStop=/usr/share/openvswitch/scripts/ovs-ctl stop-ovs-exporter
+TimeoutSec=10
+
+[Install]
+WantedBy=ovs-vswitchd.service
diff --git a/utilities/.gitignore b/utilities/.gitignore
index 5f0ec41da9..1393772621 100644
--- a/utilities/.gitignore
+++ b/utilities/.gitignore
@@ -18,6 +18,7 @@
 /ovs-l3ping.8
 /ovs-lib
 /ovs-metrics
+/ovs-exporter
 /ovs-ofctl
 /ovs-ofctl.8
 /ovs-parse-backtrace
diff --git a/utilities/automake.mk b/utilities/automake.mk
index ba076d7704..82d3d447a2 100644
--- a/utilities/automake.mk
+++ b/utilities/automake.mk
@@ -6,6 +6,7 @@ bin_PROGRAMS += \
        utilities/ovs-vsctl
 bin_SCRIPTS += utilities/ovs-docker \
        utilities/ovs-metrics \
+       utilities/ovs-exporter \
        utilities/ovs-pki \
        utilities/ovs-pcap \
        utilities/ovs-tcpdump \
@@ -57,6 +58,7 @@ EXTRA_DIST += \
        utilities/ovs-l3ping.in \
        utilities/ovs-lib.in \
        utilities/ovs-metrics.in \
+       utilities/ovs-exporter.in \
        utilities/ovs-parse-backtrace.in \
        utilities/ovs-pcap.in \
        utilities/ovs-pipegen.py \
@@ -152,6 +154,7 @@ FLAKE8_PYFILES += utilities/ovs-pcap.in \
        utilities/gdb/ovs_gdb.py \
        utilities/ovs-check-dead-ifs.in \
        utilities/ovs-metrics.in \
+       utilities/ovs-exporter.in \
        utilities/ovs-tcpdump.in \
        utilities/ovs-pipegen.py \
        utilities/usdt-scripts/dpif_op_nl_monitor.py \
diff --git a/utilities/ovs-ctl.in b/utilities/ovs-ctl.in
index c65c76812e..48a52b2ee4 100644
--- a/utilities/ovs-ctl.in
+++ b/utilities/ovs-ctl.in
@@ -259,6 +259,16 @@ start_ovs_ipsec () {
     return 0
 }
 
+start_ovs_exporter () {
+    if daemon_is_running ovs-exporter; then
+        log_success_msg "ovs-exporter is already running"
+    else
+        set ovs-exporter --unixctl
+        set "$@" -vconsole:emer -vsyslog:err -vfile:info
+        start_daemon "-10" "" "" "$@" || return 1
+    fi
+}
+
 ## ---- ##
 ## stop ##
 ## ---- ##
@@ -279,6 +289,10 @@ stop_ovs_ipsec () {
     stop_daemon ovs-monitor-ipsec
 }
 
+stop_ovs_exporter () {
+    stop_daemon ovs-exporter
+}
+
 ## --------------- ##
 ## enable-protocol ##
 ## --------------- ##
@@ -416,6 +430,8 @@ Commands:
                               ports
   start-ovs-ipsec             start Open vSwitch ipsec daemon
   stop-ovs-ipsec              stop Open vSwitch ipsec daemon
+  start-ovs-exporter          start Open vSwitch metrics exporter
+  stop-ovs-exporter           stop Open vSwitch metrics exporter
   record-hostname-if-not-set  determine the system hostname and record it in
                               the Open vSwitch database if not already set
   help                        display this help message
@@ -613,6 +629,12 @@ case $command in
     stop-ovs-ipsec)
         stop_ovs_ipsec
         ;;
+    start-ovs-exporter)
+        start_ovs_exporter
+        ;;
+    stop-ovs-exporter)
+        stop_ovs_exporter
+        ;;
     record-hostname-if-not-set)
         set_hostname
         ;;
diff --git a/utilities/ovs-exporter.in b/utilities/ovs-exporter.in
new file mode 100755
index 0000000000..7ff2784430
--- /dev/null
+++ b/utilities/ovs-exporter.in
@@ -0,0 +1,216 @@
+#! @PYTHON3@
+#
+# Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
+#
+# 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.
+
+import argparse
+import configparser
+import signal
+import sys
+import time
+
+try:
+    import ovs.daemon
+    from ovs.metrics import get_metrics_families, MetricsReadError
+    import ovs.vlog
+    import ovs.unixctl
+    import ovs.unixctl.server
+    import ovs.util
+except ModuleNotFoundError:
+    print(u"""\
+ERROR: Missing dependencies.
+Please install the Open vSwitch python libraries: python3-@PACKAGE_NAME@ 
(version @VERSION@).
+Alternatively, install them from source: ( cd ovs/python ; python3 setup.py 
install ).
+Alternatively, check that your PYTHONPATH is pointing to the correct 
location.""")
+    sys.exit(1)
+
+try:
+    import prometheus_client
+    from prometheus_client import start_http_server
+    from prometheus_client.core import REGISTRY
+except Exception as e:
+    print("ERROR: Missing python module: %s" % e.name)
+    sys.exit(1)
+
+exiting = False
+vlog = ovs.vlog.Vlog(ovs.util.PROGRAM_NAME)
+DEFAULT_PORT = 6103
+DEFAULT_CONFIG_FILE = "%s/%s.conf" % (ovs.dirs.DBDIR, ovs.util.PROGRAM_NAME)
+
+# We do not want to report the metrics related to this web server,
+# only the ones from OVS. Unregister the default Collectors.
+
+REGISTRY.unregister(prometheus_client.GC_COLLECTOR)
+REGISTRY.unregister(prometheus_client.PLATFORM_COLLECTOR)
+REGISTRY.unregister(prometheus_client.PROCESS_COLLECTOR)
+
+
+class OVSCollector(object):
+    """Collector for OVS-DOCA metrics."""
+
+    def __init__(self, extended=False, debug=False, registry=REGISTRY):
+        self._extended = extended
+        self._debug = debug
+        if registry:
+            registry.register(self)
+        vlog.dbg("Registered OVS metrics collector: extended=%s, debug=%s" % 
(extended, debug))
+        self._inited = True
+
+    def collect(self):
+        if hasattr(self, '_inited'):
+            vlog.info("Collecting requested metrics")
+        try:
+            return get_metrics_families(extended=self._extended, 
debug=self._debug)
+        except MetricsReadError as e:
+            vlog.err(str(e))
+            return {}
+
+
+def sigint_handler(sig, frame):
+    global exiting
+    exiting = True
+    vlog.info("Exiting")
+signal.signal(signal.SIGINT, sigint_handler)
+
+
+def unixctl_exit(conn, unused_argv, aux):
+    global exiting
+    vlog.info("Exiting")
+    exiting = True
+    conn.reply(None)
+
+
+def uint(s):
+    i = int(s)
+    if i < 0:
+        raise Exception("%s is not a positive integer" % s)
+    return i
+
+
+def push_config_into_args(config, args):
+    if not 'exporter' in config:
+        return
+
+    exporter = config['exporter']
+
+    if args.port is None and 'port' in exporter:
+        try:
+            args.port = uint(exporter['port'])
+        except Exception as e:
+            vlog.err("Failed to parse port: %s" % str(e))
+
+    if not args.extended and 'extended' in exporter:
+        args.extended = exporter['extended'] == 'yes'
+
+    if not args.debug and 'debug' in exporter:
+        args.debug = exporter['debug'] == 'yes'
+
+
+def argparse_port(s):
+    try:
+        p = uint(s)
+    except Exception as e:
+        raise argparse.ArgumentTypeError(str(e))
+    if p > 65535:
+        raise argparse.ArgumentTypeError("%s is not within [0, %d]" % (s, 
2**16 - 1))
+    return p
+
+
+def main():
+    config = configparser.ConfigParser()
+
+    parser = argparse.ArgumentParser(description=u'Open vSwitch metrics 
exporter.')
+
+    configfile = DEFAULT_CONFIG_FILE
+
+    group = parser.add_argument_group(title="Exporter Options")
+    group.add_argument('-p', '--port', type=argparse_port, metavar='<uint>',
+                       help='TCP port to listen on')
+    group.add_argument('-x', '--extended', action='count', default=0,
+                       help='Also export the extended metrics page')
+    group.add_argument('-d', '--debug', action='count', default=0,
+                       help='Also export the debug metrics page')
+    group.add_argument('-c', '--config', nargs="?", default=configfile,
+                       help='Read configuration from file (default %s)' % 
configfile)
+    group.add_argument('--unixctl', action='store_true',
+                       help='Create a unixctl server')
+    group.add_argument('--version', action='store_true',
+                       help='Print the version')
+
+    ovs.daemon.add_args(parser)
+    ovs.vlog.add_args(parser)
+    args = parser.parse_args()
+
+    if args.version:
+        print("%s @VERSION@" % ovs.util.PROGRAM_NAME)
+        sys.exit(0)
+
+    ovs.daemon.handle_args(args)
+    ovs.vlog.handle_args(args)
+
+    try:
+        config.read(args.config)
+    except:
+        sys.stderr.write("Unable to find configuration file %s: %s" % 
args.config)
+
+    push_config_into_args(config, args)
+
+    # Set the default values, only after arguments were parsed and
+    # potential config read. The 'default' of argparse cannot be used,
+    # as it would prevent proper precedence with the configuration.
+
+    args.port = args.port or DEFAULT_PORT
+    args.extended = bool(args.extended) or False
+    args.debug = bool(args.debug) or False
+
+    ovs.daemon.daemonize_start()
+
+    if args.unixctl:
+        error, server = ovs.unixctl.server.UnixctlServer.create(None)
+        if error:
+            ovs.util.ovs_fatal(error, "could not create unixctl server", vlog)
+        ovs.unixctl.command_register("exit", "", 0, 0, unixctl_exit, 
"aux_exit")
+    else:
+        server = None
+
+    ovs_collector = OVSCollector(extended=args.extended, debug=args.debug)
+
+    vlog.info("Starting HTTP server on port %d" % args.port)
+    try:
+        start_http_server(args.port)
+    except OSError as e:
+        vlog.err("Failed to start HTTP server: %s" % e.strerror)
+
+    ovs.daemon.daemonize_complete()
+
+    if server is not None:
+        vlog.info("Entering run loop.")
+        poller = ovs.poller.Poller()
+        while not exiting:
+            server.run()
+            server.wait(poller)
+            if exiting:
+                poller.immediate_wake()
+            poller.block()
+        server.close()
+    else:
+        while True and not exiting:
+            time.sleep(1)
+    vlog.info("Stopping the HTTP server")
+
+
+if __name__ == '__main__':
+    main()
+
+# vi: filetype=python
-- 
2.34.1

_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to