From 976e1df8ecf3445c6bc76ec3bb4f083086a2f55e Mon Sep 17 00:00:00 2001
From: Viacheslav Hletenko <v.gletenko@vyos.io>
Date: Thu, 7 Jul 2022 17:40:07 +0000
Subject: monitoring: T4411: Migrate influxdb options to influxdb node

As we have specific configuration for each plugin:
set service monitoring telegraf xxx
 - azure-data-explorer
 - prometheus-client
 - splunk

We should to move configuration that related to influxdb under
influxdb node

Replace:
set service monitoring telegraf
 - authentication xxx
 - bucket xxx
 - port xxx
 - url

To:
set service monitoring telegraf influxdb xxx
---
 data/templates/monitoring/override.conf.j2         |  2 +-
 data/templates/monitoring/telegraf.j2              |  8 +--
 .../include/version/monitoring-version.xml.i       |  3 +
 .../service-monitoring-telegraf.xml.in             | 67 +++++++++++---------
 src/conf_mode/service_monitoring_telegraf.py       | 22 +++----
 src/migration-scripts/monitoring/0-to-1            | 71 ++++++++++++++++++++++
 6 files changed, 127 insertions(+), 46 deletions(-)
 create mode 100644 interface-definitions/include/version/monitoring-version.xml.i
 create mode 100755 src/migration-scripts/monitoring/0-to-1

diff --git a/data/templates/monitoring/override.conf.j2 b/data/templates/monitoring/override.conf.j2
index f8f150791..9f1b4ebec 100644
--- a/data/templates/monitoring/override.conf.j2
+++ b/data/templates/monitoring/override.conf.j2
@@ -2,6 +2,6 @@
 After=vyos-router.service
 ConditionPathExists=/run/telegraf/vyos-telegraf.conf
 [Service]
-Environment=INFLUX_TOKEN={{ authentication.token }}
+Environment=INFLUX_TOKEN={{ influxdb.authentication.token }}
 CapabilityBoundingSet=CAP_NET_RAW CAP_NET_ADMIN CAP_SYS_ADMIN
 AmbientCapabilities=CAP_NET_RAW CAP_NET_ADMIN
diff --git a/data/templates/monitoring/telegraf.j2 b/data/templates/monitoring/telegraf.j2
index a732fb5de..6b395692b 100644
--- a/data/templates/monitoring/telegraf.j2
+++ b/data/templates/monitoring/telegraf.j2
@@ -31,14 +31,14 @@
 {%     endif %}
 ### End Azure Data Explorer ###
 {% endif %}
-{% if influxdb_configured is vyos_defined %}
+{% if influxdb is vyos_defined %}
 ### InfluxDB2 ###
 [[outputs.influxdb_v2]]
-  urls = ["{{ url }}:{{ port }}"]
+  urls = ["{{ influxdb.url }}:{{ influxdb.port }}"]
   insecure_skip_verify = true
   token = "$INFLUX_TOKEN"
-  organization = "{{ authentication.organization }}"
-  bucket = "{{ bucket }}"
+  organization = "{{ influxdb.authentication.organization }}"
+  bucket = "{{ influxdb.bucket }}"
 ### End InfluxDB2 ###
 {% endif %}
 {% if prometheus_client is vyos_defined %}
diff --git a/interface-definitions/include/version/monitoring-version.xml.i b/interface-definitions/include/version/monitoring-version.xml.i
new file mode 100644
index 000000000..6a275a5d8
--- /dev/null
+++ b/interface-definitions/include/version/monitoring-version.xml.i
@@ -0,0 +1,3 @@
+<!-- include start from include/version/monitoring-version.xml.i -->
+<syntaxVersion component='monitoring' version='1'></syntaxVersion>
+<!-- include end -->
diff --git a/interface-definitions/service-monitoring-telegraf.xml.in b/interface-definitions/service-monitoring-telegraf.xml.in
index d0d9202c1..36f40a539 100644
--- a/interface-definitions/service-monitoring-telegraf.xml.in
+++ b/interface-definitions/service-monitoring-telegraf.xml.in
@@ -13,32 +13,50 @@
               <help>Telegraf monitoring</help>
             </properties>
             <children>
-              <node name="authentication">
+              <node name="influxdb">
                 <properties>
-                  <help>Authentication parameters</help>
+                  <help>Output plugin InfluxDB</help>
                 </properties>
                 <children>
-                  <leafNode name="organization">
+                  <node name="authentication">
                     <properties>
-                      <help>Authentication organization for InfluxDB v2</help>
-                      <constraint>
-                        <regex>[a-zA-Z][1-9a-zA-Z@_\-.]{2,50}</regex>
-                      </constraint>
-                      <constraintErrorMessage>Organization name must be alphanumeric and can contain hyphens, underscores and at symbol.</constraintErrorMessage>
+                      <help>Authentication parameters</help>
                     </properties>
-                  </leafNode>
-                  <leafNode name="token">
+                    <children>
+                      <leafNode name="organization">
+                        <properties>
+                          <help>Authentication organization for InfluxDB v2</help>
+                          <constraint>
+                            <regex>[a-zA-Z][1-9a-zA-Z@_\-.]{2,50}</regex>
+                          </constraint>
+                          <constraintErrorMessage>Organization name must be alphanumeric and can contain hyphens, underscores and at symbol.</constraintErrorMessage>
+                        </properties>
+                      </leafNode>
+                      <leafNode name="token">
+                        <properties>
+                          <help>Authentication token for InfluxDB v2</help>
+                          <valueHelp>
+                            <format>txt</format>
+                            <description>Authentication token</description>
+                          </valueHelp>
+                          <constraint>
+                            <regex>[a-zA-Z0-9-_]{86}==</regex>
+                          </constraint>
+                          <constraintErrorMessage>Token must be 88 characters long and must contain only [a-zA-Z0-9-_] and '==' characters.</constraintErrorMessage>
+                        </properties>
+                      </leafNode>
+                    </children>
+                  </node>
+                  <leafNode name="bucket">
                     <properties>
-                      <help>Authentication token for InfluxDB v2</help>
-                      <valueHelp>
-                        <format>txt</format>
-                        <description>Authentication token</description>
-                      </valueHelp>
-                      <constraint>
-                        <regex>[a-zA-Z0-9-_]{86}==</regex>
-                      </constraint>
-                      <constraintErrorMessage>Token must be 88 characters long and must contain only [a-zA-Z0-9-_] and '==' characters.</constraintErrorMessage>
+                      <help>Remote bucket</help>
                     </properties>
+                    <defaultValue>main</defaultValue>
+                  </leafNode>
+                  #include <include/monitoring/url.xml.i>
+                  #include <include/port-number.xml.i>
+                  <leafNode name="port">
+                    <defaultValue>8086</defaultValue>
                   </leafNode>
                 </children>
               </node>
@@ -130,12 +148,6 @@
                   #include <include/monitoring/url.xml.i>
                 </children>
               </node>
-              <leafNode name="bucket">
-                <properties>
-                  <help>Remote bucket</help>
-                </properties>
-                <defaultValue>main</defaultValue>
-              </leafNode>
               <leafNode name="source">
                 <properties>
                   <help>Source parameters for monitoring</help>
@@ -294,11 +306,6 @@
                   </leafNode>
                 </children>
               </node>
-              #include <include/monitoring/url.xml.i>
-              #include <include/port-number.xml.i>
-              <leafNode name="port">
-                <defaultValue>8086</defaultValue>
-              </leafNode>
             </children>
           </node>
         </children>
diff --git a/src/conf_mode/service_monitoring_telegraf.py b/src/conf_mode/service_monitoring_telegraf.py
index daf75d740..62f5e1ddf 100755
--- a/src/conf_mode/service_monitoring_telegraf.py
+++ b/src/conf_mode/service_monitoring_telegraf.py
@@ -99,10 +99,6 @@ def get_config(config=None):
     monitoring['interfaces_ethernet'] = get_interfaces('ethernet', vlan=False)
     monitoring['nft_chains'] = get_nft_filter_chains()
 
-    if 'authentication' in monitoring or \
-       'url' in monitoring:
-        monitoring['influxdb_configured'] = True
-
     # Redefine azure group-metrics 'single-table' and 'table-per-metric'
     if 'azure_data_explorer' in monitoring:
         if 'single-table' in monitoring['azure_data_explorer']['group_metrics']:
@@ -119,6 +115,9 @@ def get_config(config=None):
 
     # Ignore default XML values if config doesn't exists
     # Delete key from dict
+    if not conf.exists(base + ['influxdb']):
+        del monitoring['influxdb']
+
     if not conf.exists(base + ['prometheus-client']):
         del monitoring['prometheus_client']
 
@@ -132,14 +131,15 @@ def verify(monitoring):
     if not monitoring:
         return None
 
-    if 'influxdb_configured' in monitoring:
-        if 'authentication' not in monitoring or \
-           'organization' not in monitoring['authentication'] or \
-           'token' not in monitoring['authentication']:
-            raise ConfigError(f'Authentication "organization and token" are mandatory!')
+    # Verify influxdb
+    if 'influxdb' in monitoring:
+        if 'authentication' not in monitoring['influxdb'] or \
+           'organization' not in monitoring['influxdb']['authentication'] or \
+           'token' not in monitoring['influxdb']['authentication']:
+            raise ConfigError(f'influxdb authentication "organization and token" are mandatory!')
 
-        if 'url' not in monitoring:
-            raise ConfigError(f'Monitoring "url" is mandatory!')
+        if 'url' not in monitoring['influxdb']:
+            raise ConfigError(f'Monitoring influxdb "url" is mandatory!')
 
     # Verify azure-data-explorer
     if 'azure_data_explorer' in monitoring:
diff --git a/src/migration-scripts/monitoring/0-to-1 b/src/migration-scripts/monitoring/0-to-1
new file mode 100755
index 000000000..803cdb49c
--- /dev/null
+++ b/src/migration-scripts/monitoring/0-to-1
@@ -0,0 +1,71 @@
+#!/usr/bin/env python3
+#
+# Copyright (C) 2022 VyOS maintainers and contributors
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 or later as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# T3417: migrate IS-IS tagNode to node as we can only have one IS-IS process
+
+from sys import argv
+from sys import exit
+
+from vyos.configtree import ConfigTree
+
+if (len(argv) < 1):
+    print("Must specify file name!")
+    exit(1)
+
+file_name = argv[1]
+
+with open(file_name, 'r') as f:
+    config_file = f.read()
+
+base = ['service', 'monitoring', 'telegraf']
+config = ConfigTree(config_file)
+
+if not config.exists(base):
+    # Nothing to do
+    exit(0)
+
+if config.exists(base + ['authentication', 'organization']):
+    tmp = config.return_value(base + ['authentication', 'organization'])
+    config.delete(base + ['authentication', 'organization'])
+    config.set(base + ['influxdb', 'authentication', 'organization'], value=tmp)
+
+if config.exists(base + ['authentication', 'token']):
+    tmp = config.return_value(base + ['authentication', 'token'])
+    config.delete(base + ['authentication', 'token'])
+    config.set(base + ['influxdb', 'authentication', 'token'], value=tmp)
+
+if config.exists(base + ['bucket']):
+    tmp = config.return_value(base + ['bucket'])
+    config.delete(base + ['bucket'])
+    config.set(base + ['influxdb', 'bucket'], value=tmp)
+
+if config.exists(base + ['port']):
+    tmp = config.return_value(base + ['port'])
+    config.delete(base + ['port'])
+    config.set(base + ['influxdb', 'port'], value=tmp)
+
+if config.exists(base + ['url']):
+    tmp = config.return_value(base + ['url'])
+    config.delete(base + ['url'])
+    config.set(base + ['influxdb', 'url'], value=tmp)
+
+
+try:
+    with open(file_name, 'w') as f:
+        f.write(config.to_string())
+except OSError as e:
+    print(f'Failed to save the modified config: {e}')
+    exit(1)
-- 
cgit v1.2.3