Merge "Enable OpenVSwitch alerts only when using OVS."
diff --git a/telegraf/files/script/reclass_monitor.py b/telegraf/files/script/reclass_monitor.py
new file mode 100644
index 0000000..c209ae9
--- /dev/null
+++ b/telegraf/files/script/reclass_monitor.py
@@ -0,0 +1,47 @@
+#!/usr/bin/env python
+import argparse
+import subprocess
+import sys
+
+def call_process(*args, **kwargs):
+    _result = subprocess.check_output(*args, **kwargs)
+    return _result.decode("utf-8") if sys.version_info.major > 2 else _result
+
+def parse_args():
+    parser = argparse.ArgumentParser()
+    parser.add_argument("--git-dir", default="/srv/salt/reclass")
+    parser.add_argument("--remote", default="origin")
+    parser.add_argument("--branch", default="master")
+    return parser.parse_args()
+
+CHANGES_FORMAT = '''reclass_staged_changes,directory={dir} value={staged}
+reclass_unstaged_changes,directory={dir} value={unstaged}'''
+
+if __name__ == "__main__":
+    args = parse_args()
+    git_dir = args.git_dir.strip()
+
+    staged, unstaged = [], []
+    for file_status in call_process(
+        str.split('git status --porcelain'), cwd=git_dir
+    ).splitlines():
+        if file_status[0] not in (' ', '?'):
+            staged.append(file_status[3:].strip())
+        if file_status[1] != ' ':
+            unstaged.append(file_status[3:].strip())
+
+    print(CHANGES_FORMAT.format(
+        dir=git_dir, staged=len(staged), unstaged=len(unstaged)
+    ))
+
+    if args.remote.strip() in call_process(
+        str.split('git remote show'), cwd=git_dir
+    ).splitlines():
+        # 0 if local branch is synced with remote, 1 otherwise
+        print('reclass_remote_desync,directory={dir} value={val}'.format(
+            dir=git_dir, val=int(bool(call_process(
+                str.split("git diff {branch}..{remote}/{branch}".format(
+                    branch=args.branch.strip(), remote=args.remote.strip()
+                )), cwd=git_dir
+            )))
+        ))
diff --git a/telegraf/meta/prometheus.yml b/telegraf/meta/prometheus.yml
index 5d8b320..c4a1131 100644
--- a/telegraf/meta/prometheus.yml
+++ b/telegraf/meta/prometheus.yml
@@ -36,6 +36,46 @@
         summary: "Telegraf failed to gather metrics"
         description: "Telegraf has gathering errors on the {{ $labels.host }} node for the last 10 minutes."
 {%- endraw %}
+{%- if pillar.reclass is defined %}
+  {%- if pillar.reclass.get('storage', {}).get('enabled', False) and pillar.reclass.get('storage', {}).get('data_source',{}).get('engine',"") == "local" %}
+    ReclassUnstagedChanges:
+      if: >-
+        reclass_files_unstaged_changes > 0
+      for: 30m
+      labels:
+        severity: warning
+        service: reclass
+      annotations:
+        summary: 'Reclass model has been modified'
+        {%- raw %}
+        description: '{{ $labels.value }} files under {{ $labels.directory }} have been modified without being committed'
+        {%- endraw %}
+    ReclassStagedChanges:
+      if: >-
+        reclass_files_staged_changes > 0
+      for: 30m
+      labels:
+        severity: warning
+        service: reclass
+      annotations:
+        summary: 'Reclass model has diverged from expected local state'
+        {%- raw %}
+        description: '{{ $labels.value }} files under {{ $labels.directory }} have diverged from expected local state'
+        {%- endraw %}
+    ReclassRemoteDesync:
+      if: >-
+        reclass_remote_desync > 0
+      for: 30m
+      labels:
+        severity: warning
+        service: reclass
+      annotations:
+        summary: 'Local Reclass model state has diverted from remote state'
+        {%- raw %}
+        description: '{{ $labels.value }} local files under {{ $labels.directory }} have diverged from expected remote state'
+        {%- endraw %}
+  {%- endif %}
+{%- endif %}
 {%- if pillar.neutron is defined %}
   {%- for component in ['gateway', 'compute'] %}
     {%- set neutron_config = pillar.neutron.get(component, {}) %}
diff --git a/telegraf/meta/telegraf.yml b/telegraf/meta/telegraf.yml
index 3436bf0..036a788 100644
--- a/telegraf/meta/telegraf.yml
+++ b/telegraf/meta/telegraf.yml
@@ -1,3 +1,17 @@
+{%- if pillar.reclass is defined %}
+  {%- if pillar.reclass.get('storage', {}).get('enabled', False) and pillar.reclass.get('storage', {}).get('data_source',{}).get('engine',"") == "local" %}
+    {%- set reclass_dir = pillar.reclass.get('storage', {}).get('base_dir',"") %}
+agent:
+  input:
+    reclass_git:
+      template: telegraf/files/input/exec.conf
+      commands:
+      - /usr/local/bin/reclass_monitor.py --git-dir {{ reclass_dir }}
+      data_format: influx
+      interval: 45s
+  {%- endif %}
+{%- endif %}
+
 {%- if pillar.neutron is defined %}
   {%- for component in ['gateway', 'compute'] %}
     {%- set neutron_config = pillar.neutron.get(component, {}) %}
diff --git a/telegraf/script.sls b/telegraf/script.sls
index 2845888..ef9b354 100644
--- a/telegraf/script.sls
+++ b/telegraf/script.sls
@@ -1,3 +1,16 @@
+{%- if pillar.reclass is defined %}
+  {%- if pillar.reclass.get('storage', {}).get('enabled', False) and pillar.reclass.get('storage', {}).get('data_source',{}).get('engine',"") == "local" %}
+
+reclass_monitor_telegraf_script:
+  file.managed:
+  - name: /usr/local/bin/reclass_monitor.py
+  - source: salt://telegraf/files/script/reclass_monitor.py
+  - template: jinja
+  - mode: 755
+
+  {%- endif %}
+{%- endif %}
+
 {%- if pillar.neutron is defined %}
   {%- for component in ['gateway', 'compute'] %}
     {%- set neutron_config = pillar.neutron.get(component, {}) %}