Merge "Add sandesh_send_rate_limit parameter" into release/2019.2.0
diff --git a/README.rst b/README.rst
index 6220886..bf4fe01 100644
--- a/README.rst
+++ b/README.rst
@@ -644,18 +644,23 @@
 
   opencontrail:
     compute:
-      enabled: true
+      enabled: True
       tor:
-        enabled: true
-        bind:
-          port: 8086
+        enabled: True
         agent:
           tor01:
             id: 0
-            port: 6632
-            host: 127.0.0.1
             address: 127.0.0.1
-
+            tor_name: TOR1
+            tor_ip: 10.11.0.100
+            tor_ovs_port: 6640
+            tor_ovs_protocol: tcp
+            http_server_port: 9090
+            tsn_ip: 127.0.0.1
+            tor_tunnel_ip: 10.10.0.100
+            tor_vendor_name: ovs
+            xmpp_auth_enable: False
+            xmpp_dns_auth_enable: False
 
 Set up metadata secret for the Vrouter
 --------------------------------------
diff --git a/metadata/service/compute/tor/cluster.yml b/metadata/service/compute/tor/cluster.yml
index 5115598..e913cb4 100644
--- a/metadata/service/compute/tor/cluster.yml
+++ b/metadata/service/compute/tor/cluster.yml
@@ -4,13 +4,18 @@
   opencontrail:
     compute:
       tor:
-        enabled: true
-        bind:
-          port: 8086
+        enabled: True
         agent:
           tor01:
             id: 0
-            address: ${_param:single_address}
-            port: 6632
-            ssl:
-              enabled: True
+            address: ${_param:cluster_local_address}
+            tor_name: TOR01
+            tor_ip: 127.0.0.1
+            tor_ovs_port: 6640
+            tor_ovs_protocol: tcp
+            http_server_port: 9090
+            tsn_ip: ${_param:cluster_vip_address}
+            tor_tunnel_ip: 127.0.0.1
+            tor_vendor_name: ovs
+            xmpp_auth_enable: False
+            xmpp_dns_auth_enable: False
diff --git a/metadata/service/compute/tor/single.yml b/metadata/service/compute/tor/single.yml
index 969b1ef..dcd4e80 100644
--- a/metadata/service/compute/tor/single.yml
+++ b/metadata/service/compute/tor/single.yml
@@ -4,12 +4,18 @@
   opencontrail:
     compute:
       tor:
-        enabled: true
-        bind:
-          port: 8086
+        enabled: True
         agent:
           tor01:
             id: 0
-            port: 6632
-            host: ${_param:tor_device01_address}
             address: ${_param:single_address}
+            tor_name: TOR01
+            tor_ip: 127.0.0.1
+            tor_ovs_port: 6640
+            tor_ovs_protocol: tcp
+            http_server_port: 9090
+            tsn_ip: ${_param:single_address}
+            tor_tunnel_ip: 127.0.0.1
+            tor_vendor_name: ovs
+            xmpp_auth_enable: False
+            xmpp_dns_auth_enable: False
diff --git a/opencontrail/compute.sls b/opencontrail/compute.sls
index 1593abb..6e4e179 100644
--- a/opencontrail/compute.sls
+++ b/opencontrail/compute.sls
@@ -206,6 +206,8 @@
 
 {%- if compute.get('tor', {}).get('enabled', False) %}
 
+{%- if compute.version < 4.0 %}
+
 {% for agent_name, agent in compute.tor.agent.iteritems() %}
 
 /etc/contrail/contrail-tor-agent-{{ agent.id }}.conf:
@@ -217,7 +219,7 @@
   - watch_in:
     - service: opencontrail_compute_services
 
-{%- if compute.version < 4.0 or grains.get('init') != 'systemd' %}
+{%- if grains.get('init') != 'systemd' %}
 
 /etc/contrail/supervisord_vrouter_files/contrail-tor-agent-{{ agent.id }}.ini:
   file.managed:
@@ -229,8 +231,20 @@
     - service: opencontrail_compute_services
 
 {%- endif %}
-
 {%- endfor %}
+
+{%- else %}
+
+provision_tor_agents:
+  cmd.script:
+  - source: "salt://opencontrail/files/{{ compute.version }}/tor/provision_tor_agents.sh"
+  - template: jinja
+  - cwd: /
+  - require:
+    - pkg: opencontrail_vrouter_package_vrouter_agent
+
+{%- endif %}
+
 {%- endif %}
 
 opencontrail_compute_services:
diff --git a/opencontrail/files/3.0/check_contrail_health.py b/opencontrail/files/3.0/check_contrail_health.py
new file mode 100644
index 0000000..8449f40
--- /dev/null
+++ b/opencontrail/files/3.0/check_contrail_health.py
@@ -0,0 +1,48 @@
+#!/usr/bin/env python
+import subprocess
+import sys
+
+
+CMD = "contrail-status"
+
+SERVICE_EXTRA_STATES = {'contrail-schema': 'backup',
+                        'contrail-svc-monitor': 'backup',
+                        'contrail-device-manager': 'backup'}
+
+
+def check(output=sys.stdout):
+    cmd = subprocess.check_output(CMD.split(' '))
+    result = {}
+    for l in [l.strip() for l in cmd.split('\n') if l.strip() != '']:
+        if l.startswith('=='):
+            # role detected
+            role = l.strip('==').strip().replace(' ', '_')
+            result[role] = []
+        else:
+            state_info = [a for a in l.split(' ') if a != '']
+            service = state_info[0].split(':')[0]
+            status = ("%s %s" % (state_info[1], " ".join(state_info[2:]))
+                      if len(state_info) > 2 else state_info[1])
+            if status != 'active' and SERVICE_EXTRA_STATES.get(service) != status:
+                exit_code = 1
+            else:
+                exit_code = 0
+            result[role].append({'service': service, 'status': status,
+                                 'exit_code': exit_code})
+    # output all collected info
+    # NOTE(ivasilevskaya) ignore contrail database in favor of supervisor
+    # database
+    result.pop('Contrail_Database', None)
+    for role, services in result.iteritems():
+        for info in services:
+            output.write(("%(workload)s,contrail_service=%(service)s,role=%(role)s "
+                          "exit_code=%(exit_code)s\n") %
+                          {'workload': 'contrail_health',
+                           'service': info['service'],
+                           'exit_code': info['exit_code'],
+                           'role': role})
+    return result
+
+
+if __name__ == "__main__":
+    check()
diff --git a/opencontrail/files/3.0/check_global_vrouter_config.py b/opencontrail/files/3.0/check_global_vrouter_config.py
new file mode 100644
index 0000000..12d4d8f
--- /dev/null
+++ b/opencontrail/files/3.0/check_global_vrouter_config.py
@@ -0,0 +1,21 @@
+#!/usr/bin/env python
+import sys
+from vnc_api import vnc_api
+
+
+def check(output=sys.stdout):
+    try:
+        vnc_cli = vnc_api.VncApi(conf_file='/etc/contrail/vnc_api_lib.ini')
+        out = vnc_cli._objects_list('global-vrouter-config')
+        exit_code = 0 if len(out.get('global-vrouter-configs', [])) == 1 else 1
+    # XXX FIXME narrow down exception type
+    except Exception:
+        exit_code = 1
+    res = {'workload': 'contrail_global_vrouter_config',
+           'exit_code': exit_code}
+    # output result
+    output.write('%(workload)s exit_code=%(exit_code)s\n' % res)
+
+
+if __name__ == "__main__":
+    check()
diff --git a/opencontrail/files/3.0/contrail-vrouter-agent.conf b/opencontrail/files/3.0/contrail-vrouter-agent.conf
index 9170aee..29fce04 100644
--- a/opencontrail/files/3.0/contrail-vrouter-agent.conf
+++ b/opencontrail/files/3.0/contrail-vrouter-agent.conf
@@ -9,7 +9,7 @@
 # value provided by discovery service will be used. (Optional)
 # server=10.0.0.1 10.0.0.2
 {%- if not compute.discovery.get('enabled', True) %}
-server={% for member in compute.control.members %}{{ member.host }}{% if not loop.last %} {% endif %}{% endfor %}
+server={% for member in compute.control.members[0:2] %}{{ member.host }}{% if not loop.last %} {% endif %}{% endfor %}
 {%- endif %}
 
 [DEFAULT]
@@ -20,7 +20,7 @@
 # IP:port strings separated by space can be provided
 # collectors=127.0.0.1:8086
 {%- if not compute.discovery.get('enabled', True) %}
-server={% for member in compute.collector.members %}{{ member.host }}:8086{% if not loop.last %} {% endif %}{% endfor %}
+collectors={% for member in compute.collector.members[0:2] %}{{ member.host }}:8086{% if not loop.last %} {% endif %}{% endfor %}
 {%- endif %}
 
 # Agent mode : can be vrouter / tsn / tor (default is vrouter)
@@ -118,7 +118,7 @@
 # the value provided by discovery service will be used.
 # server=10.0.0.1:53 10.0.0.2:53
 {%- if not compute.discovery.get('enabled', True) %}
-server={% for member in compute.control.members %}{{ member.host }}:53{% if not loop.last %} {% endif %}{% endfor %}
+server={% for member in compute.control.members[0:2] %}{{ member.host }}:53{% if not loop.last %} {% endif %}{% endfor %}
 {%- endif %}
 
 # Client port used by vrouter-agent while connecting to contrail-named
diff --git a/opencontrail/files/3.0/contrail-vrouter-nodemgr.conf b/opencontrail/files/3.0/contrail-vrouter-nodemgr.conf
index e3f1957..1efe1f2 100644
--- a/opencontrail/files/3.0/contrail-vrouter-nodemgr.conf
+++ b/opencontrail/files/3.0/contrail-vrouter-nodemgr.conf
@@ -1,7 +1,9 @@
 {%- from "opencontrail/map.jinja" import compute with context %}
+{%- if compute.discovery.get('enabled', True) %}
 [DISCOVERY]
 server={{ compute.discovery.host }}
 port=5998
-
+{%- else %}
 [COLLECTOR]
-#server_list=ip1:port1 ip2:port2
+server_list={% for member in compute.collector.members %}{{ member.host }}:8086{% if not loop.last %} {% endif %}{% endfor %}
+{%- endif %}
diff --git a/opencontrail/files/3.0/vnc_api_lib.ini b/opencontrail/files/3.0/vnc_api_lib.ini
index bdf16b6..62c9066 100644
--- a/opencontrail/files/3.0/vnc_api_lib.ini
+++ b/opencontrail/files/3.0/vnc_api_lib.ini
@@ -25,6 +25,7 @@
 {%- else %}
 AUTHN_URL = /v2.0/tokens
 {%- endif %}
+insecure = true
 
 
 {%- endif %}
diff --git a/opencontrail/files/4.0/check_contrail_health.py b/opencontrail/files/4.0/check_contrail_health.py
new file mode 100644
index 0000000..3617553
--- /dev/null
+++ b/opencontrail/files/4.0/check_contrail_health.py
@@ -0,0 +1,49 @@
+#!/usr/bin/env python
+import subprocess
+import sys
+
+CMD = "doctrail all contrail-status"
+
+SERVICE_EXTRA_STATES = {'contrail-schema': 'backup',
+                        'contrail-svc-monitor': 'backup',
+                        'contrail-device-manager': 'backup'}
+
+
+def check(output=sys.stdout):
+    cmd = subprocess.check_output(CMD.split(' '))
+    result = {}
+    for l in [l.strip() for l in cmd.split('\n') if l.strip() != '']:
+        if l.startswith("FOR NODE") or l.startswith("*******"):
+            continue
+        if l.startswith('=='):
+            # role detected
+            role = l.strip('==').strip().replace(' ', '_')
+            result[role] = []
+        else:
+            state_info = [a for a in l.split(' ') if a != '']
+            service = state_info[0].split(':')[0]
+            status = ("%s %s" % (state_info[1], " ".join(state_info[2:]))
+                      if len(state_info) > 2 else state_info[1])
+            if status != 'active' and SERVICE_EXTRA_STATES.get(service) != status:
+                exit_code = 1
+            else:
+                exit_code = 0
+            result[role].append({'service': service, 'status': status,
+                                 'exit_code': exit_code})
+    # output all collected info
+    # NOTE(ivasilevskaya) ignore contrail database in favor of supervisor
+    # database
+    # result.pop('Contrail_Database', None)
+    for role, services in result.iteritems():
+        for info in services:
+            output.write(("%(workload)s,contrail_service=%(service)s,role=%(role)s "
+                          "exit_code=%(exit_code)s\n") %
+                          {'workload': 'contrail_health',
+                           'service': info['service'],
+                           'exit_code': info['exit_code'],
+                           'role': role})
+    return result
+
+
+if __name__ == "__main__":
+    check()
diff --git a/opencontrail/files/4.0/check_global_vrouter_config.py b/opencontrail/files/4.0/check_global_vrouter_config.py
new file mode 100644
index 0000000..12d4d8f
--- /dev/null
+++ b/opencontrail/files/4.0/check_global_vrouter_config.py
@@ -0,0 +1,21 @@
+#!/usr/bin/env python
+import sys
+from vnc_api import vnc_api
+
+
+def check(output=sys.stdout):
+    try:
+        vnc_cli = vnc_api.VncApi(conf_file='/etc/contrail/vnc_api_lib.ini')
+        out = vnc_cli._objects_list('global-vrouter-config')
+        exit_code = 0 if len(out.get('global-vrouter-configs', [])) == 1 else 1
+    # XXX FIXME narrow down exception type
+    except Exception:
+        exit_code = 1
+    res = {'workload': 'contrail_global_vrouter_config',
+           'exit_code': exit_code}
+    # output result
+    output.write('%(workload)s exit_code=%(exit_code)s\n' % res)
+
+
+if __name__ == "__main__":
+    check()
diff --git a/opencontrail/files/4.0/config.global.js b/opencontrail/files/4.0/config.global.js
index 01da5df..ade860a 100644
--- a/opencontrail/files/4.0/config.global.js
+++ b/opencontrail/files/4.0/config.global.js
@@ -139,7 +139,7 @@
 config.imageManager = {};
 config.imageManager.ip = '{{ web.identity.host }}';
 config.imageManager.port = '9292';
-config.imageManager.authProtocol = '{{ web.identity.protocol }};
+config.imageManager.authProtocol = '{{ web.identity.protocol }}';
 config.imageManager.apiVersion = ['v1', 'v2'];
 config.imageManager.strictSSL = false;
 config.imageManager.ca = '';
diff --git a/opencontrail/files/4.0/contrail-tor-agent.conf b/opencontrail/files/4.0/contrail-tor-agent.conf
deleted file mode 100644
index cc8c05d..0000000
--- a/opencontrail/files/4.0/contrail-tor-agent.conf
+++ /dev/null
@@ -1,111 +0,0 @@
-{%- from "opencontrail/map.jinja" import compute with context %}
-
-{%- set agent = salt['pillar.get']('opencontrail:compute:tor:agent:'+agent_name) %}
-{%- set port = compute.tor.bind.port + agent.id %}
-# Vnswad configuration options
-#
-
-[CONTROL-NODE]
-# IP address to be used to connect to control-node. Maximum of 2 IP addresses
-# (separated by a space) can be provided. If no IP is configured then the
-# value provided by discovery service will be used. (optional)
-# server=10.0.0.1 10.0.0.2
-
-[DEFAULT]
-agent_name={{ pillar.linux.system.name }}-{{ agent.id }}
-# Everything in this section is optional
-
-# IP address and port to be used to connect to collector. If these are not
-# configured, value provided by discovery service will be used. Multiple
-# IP:port strings separated by space can be provided
-# collectors=127.0.0.1:8086
-
-# Enable/disable debug logging. Possible values are 0 (disable) and 1 (enable)
-# debug=0
-
-# Aging time for flow-records in seconds
-# flow_cache_timeout=0
-
-# Hostname of compute-node. If this is not configured value from `hostname`
-# will be taken
-# hostname=
-
-# Category for logging. Default value is '*'
-# log_category=
-
-# Local log file name
-log_file=/var/log/contrail/contrail-tor-agent-{{ agent.id }}.log
-
-# Log severity levels. Possible values are SYS_EMERG, SYS_ALERT, SYS_CRIT,
-# SYS_ERR, SYS_WARN, SYS_NOTICE, SYS_INFO and SYS_DEBUG. Default is SYS_DEBUG
-# log_level=SYS_DEBUG
-
-# Enable/Disable local file logging. Possible values are 0 (disable) and 1 (enable)
-# log_local=0
-
-# Enable/Disable local flow message logging. Possible values are 0 (disable) and 1 (enable)
-# log_flow=0
-# Encapsulation type for tunnel. Possible values are MPLSoGRE, MPLSoUDP, VXLAN
-# tunnel_type=
-
-# Enable/Disable headless mode for agent. In headless mode agent retains last
-# known good configuration from control node when all control nodes are lost.
-# Possible values are true(enable) and false(disable)
-# headless_mode=
-
-# Define agent mode. Only supported value is "tor"
-agent_mode=tor
-
-
-# Http server port for inspecting vnswad state (useful for debugging)
-# http_server_port=8085
-http_server_port={{ port }}
-
-[DNS]
-# IP address to be used to connect to dns-node. Maximum of 2 IP addresses
-# (separated by a space) can be provided. If no IP is configured then the
-# value provided by discovery service will be used. (Optional)
-# server=10.0.0.1 10.0.0.2
-
-[NETWORKS]
-# control-channel IP address used by WEB-UI to connect to vnswad to fetch
-# required information (Optional)
-{%- if compute.bind is defined %}
-control_network_ip={{ compute.bind.address }}
-{%- else %}
-control_network_ip={{ compute.interface.address }}
-{%- endif %}
-
-[TOR]
-{%- if agent.ssl is not defined %}
-# IP address of the TOR to manage
-tor_ip={{ agent.host }}
-{%- endif %}
-
-# Identifier for ToR. Agent will subscribe to ifmap-configuration by this name
-tor_id={{ agent.id }}
-
-# ToR management scheme is based on this type. Only supported value is "ovs"
-tor_type=ovs
-
-# OVS server port number on the ToR
-tor_ovs_port={{ agent.get('port', 6632) }}
-
-# IP-Transport protocol used to connect to tor. Only supported value is "tcp"
-{%- if agent.ssl is defined %}
-tor_ovs_protocol=pssl
-{%- else %}
-tor_ovs_protocol=tcp
-{%- endif %}
-
-tsn_ip={{ compute.interface.address }}
-
-tor_keepalive_interval={{ agent.get('tor_keepalive_interval', 10000) }}
-
-{%- if agent.ssl is defined %}
-ssl_cert={{ agent.ssl.get('cert', '/etc/contrail/ssl/certs/tor.crt') }}
-
-ssl_privkey={{ agent.ssl.get('key', '/etc/contrail/ssl/certs/tor.key') }}
-
-ssl_cacert={{ agent.ssl.get('ca', '/etc/contrail/ssl/certs/ca.crt') }}
-{%- endif %}
\ No newline at end of file
diff --git a/opencontrail/files/4.0/tor/contrail-tor-agent.ini b/opencontrail/files/4.0/tor/contrail-tor-agent.ini
deleted file mode 100644
index 22a8918..0000000
--- a/opencontrail/files/4.0/tor/contrail-tor-agent.ini
+++ /dev/null
@@ -1,14 +0,0 @@
-{%- from "opencontrail/map.jinja" import compute with context %}
-{%- set agent = salt['pillar.get']('opencontrail:compute:tor:agent:'+agent_name) %}
-[program:contrail-tor-agent-{{ agent.id }}]
-command=/usr/bin/contrail-tor-agent --config_file /etc/contrail/contrail-tor-agent-{{ agent.id }}.conf
-priority=420
-autostart=true
-killasgroup=true
-stopsignal=KILL
-stdout_capture_maxbytes=1MB
-redirect_stderr=true
-stdout_logfile=/var/log/contrail/contrail-tor-agent-{{ agent.id }}-stdout.log
-stderr_logfile=/dev/null
-startsecs=5
-exitcodes=0                   ; 'expected' exit codes for process (default 0,2)
\ No newline at end of file
diff --git a/opencontrail/files/4.0/tor/provision_tor_agents.sh b/opencontrail/files/4.0/tor/provision_tor_agents.sh
new file mode 100644
index 0000000..5681a94
--- /dev/null
+++ b/opencontrail/files/4.0/tor/provision_tor_agents.sh
@@ -0,0 +1,33 @@
+{%- from "opencontrail/map.jinja" import client, compute with context -%}
+
+{%- for agent_name, agent in compute.tor.agent.iteritems() %}
+
+contrail-toragent-setup --cfgm_ip {{ client.api.host }} \
+--self_ip {{ agent.address }} \
+--control-nodes {% for member in compute.control.members %}{{ member.host }}{% if not loop.last %} {% endif %}{% endfor %} \
+--collectors {% for member in compute.collector.members %}{{ member.host }}{% if not loop.last %} {% endif %}{% endfor %} \
+--authserver_ip {{ client.identity.host }} \
+--admin_user {{ client.identity.user }} \
+--admin_password {{ client.identity.password }} \
+--admin_tenant_name {{ client.identity.tenant }} \
+--auth_protocol http \
+--tor_name {{ agent.tor_name }} \
+--http_server_port {{ agent.http_server_port }} \
+--tor_ip {{ agent.tor_ip }} \
+--tor_id {{ agent.id }} \
+--tsn_ip {{ agent.tsn_ip }} \
+--tor_tunnel_ip {{ agent.tor_tunnel_ip }} \
+{%- if agent.get('xmpp_auth_enable', False) == True %}
+--xmpp_auth_enable \
+{%- endif %}
+{%- if agent.get('xmpp_dns_auth_enable', False) == True %}
+--xmpp_dns_auth_enable \
+{%- endif %}
+--tor_ovs_port {{ agent.tor_ovs_port }} \
+--tor_ovs_protocol {{ agent.tor_ovs_protocol }} \
+{%- if agent.tor_product_name is defined %}
+----tor_product_name {{ agent.tor_product_name }} \
+{%- endif %}
+--tor_vendor_name {{ agent.tor_vendor_name }}
+
+{%- endfor %}
diff --git a/opencontrail/files/4.0/vnc_api_lib.ini b/opencontrail/files/4.0/vnc_api_lib.ini
index bdf16b6..62c9066 100644
--- a/opencontrail/files/4.0/vnc_api_lib.ini
+++ b/opencontrail/files/4.0/vnc_api_lib.ini
@@ -25,6 +25,7 @@
 {%- else %}
 AUTHN_URL = /v2.0/tokens
 {%- endif %}
+insecure = true
 
 
 {%- endif %}
diff --git a/opencontrail/init.sls b/opencontrail/init.sls
index ee862a7..09a204a 100644
--- a/opencontrail/init.sls
+++ b/opencontrail/init.sls
@@ -23,4 +23,9 @@
 {%- endif %}
 {% if pillar.opencontrail.common is defined %}
 - opencontrail.common
-{% endif %}
\ No newline at end of file
+{% endif %}
+{%- if pillar.opencontrail.collector is defined or
+       pillar.opencontrail.control is defined or
+       pillar.opencontrail.database is defined %}
+- opencontrail.monitoring
+{%- endif %}
diff --git a/opencontrail/map.jinja b/opencontrail/map.jinja
index 41f837b..def00f4 100644
--- a/opencontrail/map.jinja
+++ b/opencontrail/map.jinja
@@ -93,7 +93,11 @@
   Debian:
     pkgs:
     - 'contrail-config-openstack'
+    {%- if version < 4.0 %}
+    {%- if ifmap == 'irond' %}
     - 'ifmap-server'
+    {%- endif %}
+    {%- endif %}
     services:
     {%- if version < 4.0 %}
     {%- if ifmap == 'irond' %}
diff --git a/opencontrail/meta/prometheus.yml b/opencontrail/meta/prometheus.yml
index d7cf03f..7f8ef15 100644
--- a/opencontrail/meta/prometheus.yml
+++ b/opencontrail/meta/prometheus.yml
@@ -133,6 +133,42 @@
     {%- raw %}
         summary: "{{ $labels.name }} service outage"
         description: "All {{ $labels.process_name }} processes are down."
+    ContrailHealthCheckDisabled:
+      if: >-
+        absent(contrail_health_exit_code) == 1
+      labels:
+        severity: critical
+        service: contrail
+      annotations:
+        summary: "Contrail healthcheck disabled"
+        description: "Contrail healthcheck is disabled."
+    ContrailHealthCheckFailed:
+      if: >-
+        contrail_health_exit_code != 0
+      labels:
+        severity: critical
+        service: contrail
+      annotations:
+        summary: "Contrail healthcheck failed"
+        description: "Contrail healthcheck failed for the {{ $labels.contrail_service }} on the {{ $labels.host }} node."
+    ContrailGlobalVrouterConfigCheckDisabled:
+      if: >-
+        absent(contrail_global_vrouter_config_exit_code) == 1
+      labels:
+        severity: critical
+        service: contrail
+      annotations:
+        summary: "Contrail global vrouter config check disabled"
+        description: "Contrail global vrouter config check is disabled."
+    ContrailGlobalVrouterConfigCheckFailed:
+      if: >-
+        contrail_global_vrouter_config_exit_code != 0
+      labels:
+        severity: critical
+        service: contrail
+      annotations:
+        summary: "Contrail global vrouter config check failed"
+        description: "Contrail global vrouter config check failed on the {{ $labels.host }} node."
     ContrailBGPSessionsNoEstablished:
       if: >-
         max(contrail_bgp_session_count) by (host) == 0
diff --git a/opencontrail/meta/salt.yml b/opencontrail/meta/salt.yml
index 21080ce..968da5d 100644
--- a/opencontrail/meta/salt.yml
+++ b/opencontrail/meta/salt.yml
@@ -40,4 +40,10 @@
     require:
     - salt: opencontrail.config
     - salt: opencontrail.collector
+dependency:
+  {% from "opencontrail/map.jinja" import client with context %}
+  {%- if client.get('enabled', False)  %}
+  engine: pkg
+  pkgs: {{ client.pkgs }}
+  {%- endif %}
 
diff --git a/opencontrail/meta/telegraf.yml b/opencontrail/meta/telegraf.yml
index 118750e..21cc5d3 100644
--- a/opencontrail/meta/telegraf.yml
+++ b/opencontrail/meta/telegraf.yml
@@ -12,6 +12,24 @@
       data_format: "json"
       timeout: "10s"
     {%- endif %}
+    {%- if pillar.opencontrail.collector is defined or
+           pillar.opencontrail.control is defined or
+           pillar.opencontrail.database is defined %}
+    monitor_contrail_health:
+      template: telegraf/files/input/exec.conf
+      commands:
+      - /usr/local/bin/check_contrail_health.py
+      data_format: influx
+      interval: 30s
+    {%- endif %}
+    {%- if pillar.opencontrail.control is defined %}
+    monitor_global_vrouter_config:
+      template: telegraf/files/input/exec.conf
+      commands:
+      - /usr/local/bin/check_global_vrouter_config.py
+      data_format: influx
+      interval: 30s
+    {%- endif %}
     procstat:
       process:
     {%- if collector.get('enabled', False) %}
diff --git a/opencontrail/monitoring.sls b/opencontrail/monitoring.sls
new file mode 100644
index 0000000..30a0bf1
--- /dev/null
+++ b/opencontrail/monitoring.sls
@@ -0,0 +1,31 @@
+{%- if pillar.opencontrail is defined and pillar.telegraf is defined %}
+  {%- if pillar.opencontrail.collector is defined %}
+    {%- set version = pillar.opencontrail.collector.version %}
+  {%- endif %}
+  {%- if pillar.opencontrail.control is defined %}
+    {%- set version = pillar.opencontrail.control.version %}
+  {%- endif %}
+  {%- if pillar.opencontrail.database is defined %}
+    {%- set version = pillar.opencontrail.database.version %}
+  {%- endif %}
+
+  {%- if pillar.opencontrail.collector is defined or
+         pillar.opencontrail.control is defined or
+         pillar.opencontrail.database is defined %}
+contrail_control_status_check_telegraf_script:
+  file.managed:
+  - name: /usr/local/bin/check_contrail_health.py
+  - source: salt://opencontrail/files/{{ version }}/check_contrail_health.py
+  - template: jinja
+  - mode: 755
+  {%- endif %}
+
+  {%- if pillar.opencontrail.control is defined %}
+contrail_control_vrouter_check_telegraf_script:
+  file.managed:
+  - name: /usr/local/bin/check_global_vrouter_config.py
+  - source: salt://opencontrail/files/{{ version }}/check_global_vrouter_config.py
+  - template: jinja
+  - mode: 755
+  {%- endif %}
+{%- endif %}
diff --git a/tests/pillar/vrouter40.sls b/tests/pillar/vrouter40.sls
index a810b82..b77c2ca 100644
--- a/tests/pillar/vrouter40.sls
+++ b/tests/pillar/vrouter40.sls
@@ -12,6 +12,14 @@
       engine: neutron
       host: 127.0.0.1
       port: 9696
+  client:
+    api:
+      host: 127.0.0.1
+    identity:
+      host: 127.0.0.1
+      user: contrail
+      password: contrail
+      tenant: admin
   compute:
     version: 4.0
     enabled: True
@@ -35,16 +43,21 @@
       dns: 127.0.0.1
       mtu: 9000
     tor:
-      enabled: true
-      bind:
-        port: 8086
+      enabled: false
       agent:
         tor01:
           id: 0
           address: 127.0.0.1
-          port: 6632
-          ssl:
-            enabled: True
+          tor_name: TOR01
+          tor_ip: 127.0.0.1
+          tor_ovs_protocol: tcp
+          tor_ovs_port: 6640
+          http_server_port: 9090
+          tsn_ip: 127.0.0.1
+          tor_tunnel_ip: 127.0.0.1
+          tor_vendor_name: ovs
+          xmpp_auth_enable: False
+          xmpp_dns_auth_enable: False
     lbaas:
       enabled: true
       secret_manager: