Merge "Add redis password parameter"
diff --git a/.kitchen.yml b/.kitchen.yml
index 7501126..d4e87cf 100644
--- a/.kitchen.yml
+++ b/.kitchen.yml
@@ -51,7 +51,7 @@
 platforms:
   - name: <%=ENV['PLATFORM'] ||  'saltstack-ubuntu-xenial-salt-stable' %>
     driver_config:
-      image: <%=ENV['PLATFORM'] || 'epcim/salt:saltstack-ubuntu-xenial-salt-stable'%>
+      image: <%=ENV['PLATFORM'] || 'docker-dev-local.docker.mirantis.net/epcim/salt/saltstack-ubuntu-xenial-salt-stable/salt:2018_11_19'%>
       platform: ubuntu
 
 suites:
diff --git a/.travis.yml b/.travis.yml
index e5487d4..32abc3c 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -9,83 +9,52 @@
   - pip install PyYAML
   - pip install virtualenv
   - |
-    test -e Gemfile || cat <<EOF > Gemfile
-    source 'https://rubygems.org'
-    gem 'rake'
-    gem 'test-kitchen'
-    gem 'kitchen-docker'
-    gem 'kitchen-vagrant'
-    gem 'kitchen-inspec'
-    gem 'inspec'
-    gem 'kitchen-salt', :git => 'https://github.com/salt-formulas/kitchen-salt.git'
+    if [ ! -e Gemfile ]; then
+       curl -s -o ./Gemfile 'https://gerrit.mcp.mirantis.com/gitweb?p=salt-formulas/salt-formulas-scripts.git;a=blob_plain;f=Gemfile;hb=refs/heads/master'
+    fi
   - bundle install
 
 env:
-  - PLATFORM=epcim/salt:saltstack-ubuntu-trusty-salt-2016.3 OC_REPO=oc311 SUITE=single3
-  - PLATFORM=epcim/salt:saltstack-ubuntu-trusty-salt-2016.3 OC_REPO=oc311 SUITE=analytics3
-  - PLATFORM=epcim/salt:saltstack-ubuntu-trusty-salt-2016.3 OC_REPO=oc311 SUITE=control3
-  - PLATFORM=epcim/salt:saltstack-ubuntu-trusty-salt-2016.3 OC_REPO=oc311 SUITE=cluster3
-  - PLATFORM=epcim/salt:saltstack-ubuntu-xenial-salt-2016.3 OC_REPO=oc311 SUITE=vrouter3
-  - PLATFORM=epcim/salt:saltstack-ubuntu-trusty-salt-2016.3 OC_REPO=oc323 SUITE=single3
-  - PLATFORM=epcim/salt:saltstack-ubuntu-trusty-salt-2016.3 OC_REPO=oc323 SUITE=analytics3
-  - PLATFORM=epcim/salt:saltstack-ubuntu-trusty-salt-2016.3 OC_REPO=oc323 SUITE=control3
-  - PLATFORM=epcim/salt:saltstack-ubuntu-trusty-salt-2016.3 OC_REPO=oc323 SUITE=cluster3
-  - PLATFORM=epcim/salt:saltstack-ubuntu-xenial-salt-2016.3 OC_REPO=oc323 SUITE=vrouter3
-  - PLATFORM=epcim/salt:saltstack-ubuntu-xenial-salt-2016.3 OC_REPO=oc40 SUITE=single40
-  - PLATFORM=epcim/salt:saltstack-ubuntu-xenial-salt-2016.3 OC_REPO=oc40 SUITE=analytics40
-  - PLATFORM=epcim/salt:saltstack-ubuntu-xenial-salt-2016.3 OC_REPO=oc40 SUITE=control40
-  - PLATFORM=epcim/salt:saltstack-ubuntu-xenial-salt-2016.3 OC_REPO=oc40 SUITE=cluster40
-  - PLATFORM=epcim/salt:saltstack-ubuntu-xenial-salt-2016.3 OC_REPO=oc40 SUITE=vrouter40
-  - PLATFORM=epcim/salt:saltstack-ubuntu-trusty-salt-2017.7 OC_REPO=oc311 SUITE=single3
-  - PLATFORM=epcim/salt:saltstack-ubuntu-trusty-salt-2017.7 OC_REPO=oc311 SUITE=analytics3
-  - PLATFORM=epcim/salt:saltstack-ubuntu-trusty-salt-2017.7 OC_REPO=oc311 SUITE=control3
-  - PLATFORM=epcim/salt:saltstack-ubuntu-trusty-salt-2017.7 OC_REPO=oc311 SUITE=cluster3
-  - PLATFORM=epcim/salt:saltstack-ubuntu-xenial-salt-2017.7 OC_REPO=oc311 SUITE=vrouter3
-  - PLATFORM=epcim/salt:saltstack-ubuntu-trusty-salt-2017.7 OC_REPO=oc323 SUITE=single3
-  - PLATFORM=epcim/salt:saltstack-ubuntu-trusty-salt-2017.7 OC_REPO=oc323 SUITE=analytics3
-  - PLATFORM=epcim/salt:saltstack-ubuntu-trusty-salt-2017.7 OC_REPO=oc323 SUITE=control3
-  - PLATFORM=epcim/salt:saltstack-ubuntu-trusty-salt-2017.7 OC_REPO=oc323 SUITE=cluster3
-  - PLATFORM=epcim/salt:saltstack-ubuntu-xenial-salt-2017.7 OC_REPO=oc323 SUITE=vrouter3
-  - PLATFORM=epcim/salt:saltstack-ubuntu-xenial-salt-2017.7 OC_REPO=oc40 SUITE=single40
-  - PLATFORM=epcim/salt:saltstack-ubuntu-xenial-salt-2017.7 OC_REPO=oc40 SUITE=analytics40
-  - PLATFORM=epcim/salt:saltstack-ubuntu-xenial-salt-2017.7 OC_REPO=oc40 SUITE=control40
-  - PLATFORM=epcim/salt:saltstack-ubuntu-xenial-salt-2017.7 OC_REPO=oc40 SUITE=cluster40
-  - PLATFORM=epcim/salt:saltstack-ubuntu-xenial-salt-2017.7 OC_REPO=oc40 SUITE=vrouter40
-  - PLATFORM=epcim/salt:saltstack-ubuntu-trusty-salt-stable OC_REPO=oc323 SUITE=single3
-  - PLATFORM=epcim/salt:saltstack-ubuntu-trusty-salt-stable OC_REPO=oc323 SUITE=analytics3
-  - PLATFORM=epcim/salt:saltstack-ubuntu-trusty-salt-stable OC_REPO=oc323 SUITE=control3
-  - PLATFORM=epcim/salt:saltstack-ubuntu-trusty-salt-stable OC_REPO=oc323 SUITE=cluster3
-  - PLATFORM=epcim/salt:saltstack-ubuntu-xenial-salt-stable OC_REPO=oc323 SUITE=vrouter3
-  - PLATFORM=epcim/salt:saltstack-ubuntu-xenial-salt-stable OC_REPO=oc40 SUITE=single40
-  - PLATFORM=epcim/salt:saltstack-ubuntu-xenial-salt-stable OC_REPO=oc40 SUITE=analytics40
-  - PLATFORM=epcim/salt:saltstack-ubuntu-xenial-salt-stable OC_REPO=oc40 SUITE=control40
-  - PLATFORM=epcim/salt:saltstack-ubuntu-xenial-salt-stable OC_REPO=oc40 SUITE=cluster40
-  - PLATFORM=epcim/salt:saltstack-ubuntu-xenial-salt-stable OC_REPO=oc40 SUITE=vrouter40
-  # - PLATFORM=epcim/salt:saltstack-ubuntu-bionic-salt-2017.7 OC_REPO=oc311 SUITE=single3
-  # - PLATFORM=epcim/salt:saltstack-ubuntu-bionic-salt-2017.7 OC_REPO=oc311 SUITE=analytics3
-  # - PLATFORM=epcim/salt:saltstack-ubuntu-bionic-salt-2017.7 OC_REPO=oc311 SUITE=control3
-  # - PLATFORM=epcim/salt:saltstack-ubuntu-bionic-salt-2017.7 OC_REPO=oc311 SUITE=cluster3
-  # - PLATFORM=epcim/salt:saltstack-ubuntu-bionic-salt-2017.7 OC_REPO=oc311 SUITE=vrouter3
-  # - PLATFORM=epcim/salt:saltstack-ubuntu-bionic-salt-2017.7 OC_REPO=oc323 SUITE=single3
-  # - PLATFORM=epcim/salt:saltstack-ubuntu-bionic-salt-2017.7 OC_REPO=oc323 SUITE=analytics3
-  # - PLATFORM=epcim/salt:saltstack-ubuntu-bionic-salt-2017.7 OC_REPO=oc323 SUITE=control3
-  # - PLATFORM=epcim/salt:saltstack-ubuntu-bionic-salt-2017.7 OC_REPO=oc323 SUITE=cluster3
-  # - PLATFORM=epcim/salt:saltstack-ubuntu-bionic-salt-2017.7 OC_REPO=oc323 SUITE=vrouter3
-  # - PLATFORM=epcim/salt:saltstack-ubuntu-bionic-salt-2017.7 OC_REPO=oc40 SUITE=single40
-  # - PLATFORM=epcim/salt:saltstack-ubuntu-bionic-salt-2017.7 OC_REPO=oc40 SUITE=analytics40
-  # - PLATFORM=epcim/salt:saltstack-ubuntu-bionic-salt-2017.7 OC_REPO=oc40 SUITE=control40
-  # - PLATFORM=epcim/salt:saltstack-ubuntu-bionic-salt-2017.7 OC_REPO=oc40 SUITE=cluster40
-  # - PLATFORM=epcim/salt:saltstack-ubuntu-bionic-salt-2017.7 OC_REPO=oc40 SUITE=vrouter40
-  # - PLATFORM=epcim/salt:saltstack-ubuntu-bionic-salt-2018.3 OC_REPO=oc323 SUITE=single3
-  # - PLATFORM=epcim/salt:saltstack-ubuntu-bionic-salt-2018.3 OC_REPO=oc323 SUITE=analytics3
-  # - PLATFORM=epcim/salt:saltstack-ubuntu-bionic-salt-2018.3 OC_REPO=oc323 SUITE=control3
-  # - PLATFORM=epcim/salt:saltstack-ubuntu-bionic-salt-2018.3 OC_REPO=oc323 SUITE=cluster3
-  # - PLATFORM=epcim/salt:saltstack-ubuntu-bionic-salt-2018.3 OC_REPO=oc323 SUITE=vrouter3
-  # - PLATFORM=epcim/salt:saltstack-ubuntu-bionic-salt-2018.3 OC_REPO=oc40 SUITE=single40
-  # - PLATFORM=epcim/salt:saltstack-ubuntu-bionic-salt-2018.3 OC_REPO=oc40 SUITE=analytics40
-  # - PLATFORM=epcim/salt:saltstack-ubuntu-bionic-salt-2018.3 OC_REPO=oc40 SUITE=control40
-  # - PLATFORM=epcim/salt:saltstack-ubuntu-bionic-salt-2018.3 OC_REPO=oc40 SUITE=cluster40
-  # - PLATFORM=epcim/salt:saltstack-ubuntu-bionic-salt-2018.3 OC_REPO=oc40 SUITE=vrouter40
+  - PLATFORM=docker-dev-local.docker.mirantis.net/epcim/salt/saltstack-ubuntu-trusty-salt-2016.3/salt:2018_11_19 OC_REPO=oc311 SUITE=single3
+  - PLATFORM=docker-dev-local.docker.mirantis.net/epcim/salt/saltstack-ubuntu-trusty-salt-2016.3/salt:2018_11_19 OC_REPO=oc311 SUITE=analytics3
+  - PLATFORM=docker-dev-local.docker.mirantis.net/epcim/salt/saltstack-ubuntu-trusty-salt-2016.3/salt:2018_11_19 OC_REPO=oc311 SUITE=control3
+  - PLATFORM=docker-dev-local.docker.mirantis.net/epcim/salt/saltstack-ubuntu-trusty-salt-2016.3/salt:2018_11_19 OC_REPO=oc311 SUITE=cluster3
+  - PLATFORM=docker-dev-local.docker.mirantis.net/epcim/salt/saltstack-ubuntu-xenial-salt-2016.3/salt:2018_11_19 OC_REPO=oc311 SUITE=vrouter3
+  - PLATFORM=docker-dev-local.docker.mirantis.net/epcim/salt/saltstack-ubuntu-trusty-salt-2016.3/salt:2018_11_19 OC_REPO=oc323 SUITE=single3
+  - PLATFORM=docker-dev-local.docker.mirantis.net/epcim/salt/saltstack-ubuntu-trusty-salt-2016.3/salt:2018_11_19 OC_REPO=oc323 SUITE=analytics3
+  - PLATFORM=docker-dev-local.docker.mirantis.net/epcim/salt/saltstack-ubuntu-trusty-salt-2016.3/salt:2018_11_19 OC_REPO=oc323 SUITE=control3
+  - PLATFORM=docker-dev-local.docker.mirantis.net/epcim/salt/saltstack-ubuntu-trusty-salt-2016.3/salt:2018_11_19 OC_REPO=oc323 SUITE=cluster3
+  - PLATFORM=docker-dev-local.docker.mirantis.net/epcim/salt/saltstack-ubuntu-xenial-salt-2016.3/salt:2018_11_19 OC_REPO=oc323 SUITE=vrouter3
+  - PLATFORM=docker-dev-local.docker.mirantis.net/epcim/salt/saltstack-ubuntu-xenial-salt-2016.3/salt:2018_11_19 OC_REPO=oc40 SUITE=single40
+  - PLATFORM=docker-dev-local.docker.mirantis.net/epcim/salt/saltstack-ubuntu-xenial-salt-2016.3/salt:2018_11_19 OC_REPO=oc40 SUITE=analytics40
+  - PLATFORM=docker-dev-local.docker.mirantis.net/epcim/salt/saltstack-ubuntu-xenial-salt-2016.3/salt:2018_11_19 OC_REPO=oc40 SUITE=control40
+  - PLATFORM=docker-dev-local.docker.mirantis.net/epcim/salt/saltstack-ubuntu-xenial-salt-2016.3/salt:2018_11_19 OC_REPO=oc40 SUITE=cluster40
+  - PLATFORM=docker-dev-local.docker.mirantis.net/epcim/salt/saltstack-ubuntu-xenial-salt-2016.3/salt:2018_11_19 OC_REPO=oc40 SUITE=vrouter40
+  - PLATFORM=docker-dev-local.docker.mirantis.net/epcim/salt/saltstack-ubuntu-trusty-salt-2017.7/salt:2018_11_19 OC_REPO=oc311 SUITE=single3
+  - PLATFORM=docker-dev-local.docker.mirantis.net/epcim/salt/saltstack-ubuntu-trusty-salt-2017.7/salt:2018_11_19 OC_REPO=oc311 SUITE=analytics3
+  - PLATFORM=docker-dev-local.docker.mirantis.net/epcim/salt/saltstack-ubuntu-trusty-salt-2017.7/salt:2018_11_19 OC_REPO=oc311 SUITE=control3
+  - PLATFORM=docker-dev-local.docker.mirantis.net/epcim/salt/saltstack-ubuntu-trusty-salt-2017.7/salt:2018_11_19 OC_REPO=oc311 SUITE=cluster3
+  - PLATFORM=docker-dev-local.docker.mirantis.net/epcim/salt/saltstack-ubuntu-xenial-salt-2017.7/salt:2018_11_19 OC_REPO=oc311 SUITE=vrouter3
+  - PLATFORM=docker-dev-local.docker.mirantis.net/epcim/salt/saltstack-ubuntu-trusty-salt-2017.7/salt:2018_11_19 OC_REPO=oc323 SUITE=single3
+  - PLATFORM=docker-dev-local.docker.mirantis.net/epcim/salt/saltstack-ubuntu-trusty-salt-2017.7/salt:2018_11_19 OC_REPO=oc323 SUITE=analytics3
+  - PLATFORM=docker-dev-local.docker.mirantis.net/epcim/salt/saltstack-ubuntu-trusty-salt-2017.7/salt:2018_11_19 OC_REPO=oc323 SUITE=control3
+  - PLATFORM=docker-dev-local.docker.mirantis.net/epcim/salt/saltstack-ubuntu-trusty-salt-2017.7/salt:2018_11_19 OC_REPO=oc323 SUITE=cluster3
+  - PLATFORM=docker-dev-local.docker.mirantis.net/epcim/salt/saltstack-ubuntu-xenial-salt-2017.7/salt:2018_11_19 OC_REPO=oc323 SUITE=vrouter3
+  - PLATFORM=docker-dev-local.docker.mirantis.net/epcim/salt/saltstack-ubuntu-xenial-salt-2017.7/salt:2018_11_19 OC_REPO=oc40 SUITE=single40
+  - PLATFORM=docker-dev-local.docker.mirantis.net/epcim/salt/saltstack-ubuntu-xenial-salt-2017.7/salt:2018_11_19 OC_REPO=oc40 SUITE=analytics40
+  - PLATFORM=docker-dev-local.docker.mirantis.net/epcim/salt/saltstack-ubuntu-xenial-salt-2017.7/salt:2018_11_19 OC_REPO=oc40 SUITE=control40
+  - PLATFORM=docker-dev-local.docker.mirantis.net/epcim/salt/saltstack-ubuntu-xenial-salt-2017.7/salt:2018_11_19 OC_REPO=oc40 SUITE=cluster40
+  - PLATFORM=docker-dev-local.docker.mirantis.net/epcim/salt/saltstack-ubuntu-xenial-salt-2017.7/salt:2018_11_19 OC_REPO=oc40 SUITE=vrouter40
+  - PLATFORM=docker-dev-local.docker.mirantis.net/epcim/salt/saltstack-ubuntu-trusty-salt-stable/salt:2018_11_19 OC_REPO=oc323 SUITE=single3
+  - PLATFORM=docker-dev-local.docker.mirantis.net/epcim/salt/saltstack-ubuntu-trusty-salt-stable/salt:2018_11_19 OC_REPO=oc323 SUITE=analytics3
+  - PLATFORM=docker-dev-local.docker.mirantis.net/epcim/salt/saltstack-ubuntu-trusty-salt-stable/salt:2018_11_19 OC_REPO=oc323 SUITE=control3
+  - PLATFORM=docker-dev-local.docker.mirantis.net/epcim/salt/saltstack-ubuntu-trusty-salt-stable/salt:2018_11_19 OC_REPO=oc323 SUITE=cluster3
+  - PLATFORM=docker-dev-local.docker.mirantis.net/epcim/salt/saltstack-ubuntu-xenial-salt-stable/salt:2018_11_19 OC_REPO=oc323 SUITE=vrouter3
+  - PLATFORM=docker-dev-local.docker.mirantis.net/epcim/salt/saltstack-ubuntu-xenial-salt-stable/salt:2018_11_19 OC_REPO=oc40 SUITE=single40
+  - PLATFORM=docker-dev-local.docker.mirantis.net/epcim/salt/saltstack-ubuntu-xenial-salt-stable/salt:2018_11_19 OC_REPO=oc40 SUITE=analytics40
+  - PLATFORM=docker-dev-local.docker.mirantis.net/epcim/salt/saltstack-ubuntu-xenial-salt-stable/salt:2018_11_19 OC_REPO=oc40 SUITE=control40
+  - PLATFORM=docker-dev-local.docker.mirantis.net/epcim/salt/saltstack-ubuntu-xenial-salt-stable/salt:2018_11_19 OC_REPO=oc40 SUITE=cluster40
+  - PLATFORM=docker-dev-local.docker.mirantis.net/epcim/salt/saltstack-ubuntu-xenial-salt-stable/salt:2018_11_19 OC_REPO=oc40 SUITE=vrouter40
 
 before_script:
   - set -o pipefail
diff --git a/Makefile b/Makefile
index d166862..fb69046 100644
--- a/Makefile
+++ b/Makefile
@@ -18,7 +18,11 @@
 JOBS := 1
 endif
 
+ifeq (,$(wildcard ./.kitchen.openstack.yml))
+KITCHEN_LOCAL_YAML?=.kitchen.openstack.yml
+else
 KITCHEN_LOCAL_YAML?=.kitchen.yml
+endif
 KITCHEN_OPTS?="--concurrency=$(JOBS)"
 KITCHEN_OPTS_CREATE?=""
 KITCHEN_OPTS_CONVERGE?=""
diff --git a/README.rst b/README.rst
index c8724e4..2a6883c 100644
--- a/README.rst
+++ b/README.rst
@@ -939,7 +939,8 @@
     opencontrail:
       ...
       config:
-        api_workers: 3
+        api:
+          workers_count: 3
       ...
 
 Increase number of alarm-gen workers
@@ -1351,7 +1352,43 @@
           port: 8443
       ....
 
+Configure TCP_TW_RECYCLE in kernel
+------------------------------------
 
+Enable fast recycling of TIME-WAIT sockets. To enable set parameter to 1, which is
+default value in formula. To turn off this option set parameter to 0:
+
+.. code-block:: yaml
+
+    opencontrail:
+      ....
+      common
+        ....
+        tcp_tw_recycle: 0
+        ....
+
+Define extra states for contrail services health check
+------------------------------------------------------
+
+Service health check procedure verifies that all available contrail services are in ``active``
+state.
+Additional states could be defined for every service as expected states for validation procedure.
+
+.. code-block:: yaml
+
+    config:
+      ....
+      services_extra_states:
+        contrail-schema:
+          - backup
+        contrail-device-manager
+          - backup
+        contrail-svc-monitor:
+          - backup
+      ....
+
+``contrail-schema``, ``contrail-device-manager`` and ``contrail-svc-monitor`` config services already
+have additional ``backup`` state by default.
 
 Usage
 =====
diff --git a/_modules/contrail_health.py b/_modules/contrail_health.py
new file mode 100644
index 0000000..750cd8c
--- /dev/null
+++ b/_modules/contrail_health.py
@@ -0,0 +1,80 @@
+#!/usr/bin/python
+# Copyright 2018 Mirantis, 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.
+import logging
+import os
+import subprocess
+
+
+MODULE_NAME = 'contrail_health'
+LOG = logging.getLogger(__name__)
+
+
+def __virtual__():
+    '''
+    Only load this module if contrail-status or doctrail utility
+    (in case of containerized contrail version) is available.
+    '''
+    if _is_cmd_available('contrail-status') or _is_cmd_available('doctrail'):
+        return MODULE_NAME
+    return False
+
+
+def _is_cmd_available(cmd_name):
+    try:
+        with open(os.devnull) as devnull:
+            subprocess.Popen(
+                [cmd_name], stdout=devnull, stderr=devnull
+            ).communicate()
+    except OSError as e:
+        if e.errno == os.errno.ENOENT:
+            return False
+    return True
+
+
+def get_services_status():
+    cs_out = None
+
+    if _is_cmd_available('contrail-status'):
+        LOG.info('Trying to get status of contrail services '
+                 'using contrail-status utility on host ...')
+        try:
+            cs_out = str(subprocess.check_output(['contrail-status']))
+        except subprocess.CalledProcessError as e:
+            LOG.warn('Status of contrail services cannot be checked '
+                     'by contrail-status utility from host')
+    if cs_out is None and _is_cmd_available('doctrail'):
+        LOG.info('Trying to get status of contrail services inside containers '
+                 'using doctrail utility ...')
+        try:
+            cs_out = str(subprocess.check_output(
+                ['doctrail', 'all', 'contrail-status'])
+            )
+        except subprocess.CalledProcessError as e:
+            LOG.warn('Status of contrail services inside containers cannot '
+                     'be checked by contrail-status utility via doctrail cmd')
+
+    status_map = {}
+
+    if cs_out:
+        for line in cs_out.split('\n'):
+            line_list = line.split()
+            if (not line.startswith("==") and "FOR NODE" not in line and
+                    len(line_list) >= 2):
+                status_map[line_list[0].split(":")[0]] = line_list[1]
+    else:
+        LOG.error('Status of contrail services cannot be checked '
+                  'by {0} module.'.format(MODULE_NAME))
+
+    return status_map
diff --git a/_states/contrail_health.py b/_states/contrail_health.py
new file mode 100644
index 0000000..c6c4202
--- /dev/null
+++ b/_states/contrail_health.py
@@ -0,0 +1,58 @@
+#!/usr/bin/python
+# Copyright 2018 Mirantis, 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.
+'''
+Verification of Contrail services states
+'''
+
+
+def __virtual__():
+    '''
+    Load Contrail Health state module
+    '''
+    return 'contrail_health'
+
+
+def services_health(name, healthy_states=None, extra_states_map=None):
+    services_states = __salt__['contrail_health.get_services_status']()
+
+    healthy_states = healthy_states or ['active']
+    extra_states_map = extra_states_map or {}
+
+    if services_states:
+
+        nonhealthy_services = []
+
+        for service_name, state in services_states.items():
+            if (state not in healthy_states and
+                    state not in extra_states_map.get(service_name, [])):
+                nonhealthy_services.append(service_name)
+
+        if nonhealthy_services:
+            comment = ("The following services didn't pass health check:\n" +
+                       "\n".join(nonhealthy_services))
+            result = False
+        else:
+            comment = ("All contrail services have health state:\n" +
+                       "\n".join(services_states.keys()))
+            result = True
+
+    else:
+        comment = ("Contrail services states could not be verified.\n"
+                   "If contrail services are working inside container(s) "
+                   "(starting from version 4.0), please check "
+                   "that related container(s) is (are) started.")
+        result = False
+
+    return {'name': name, 'changes': {}, 'comment': comment, 'result': result}
diff --git a/metadata/service/control/cluster.yml b/metadata/service/control/cluster.yml
index df3aa74..d98a19e 100644
--- a/metadata/service/control/cluster.yml
+++ b/metadata/service/control/cluster.yml
@@ -69,6 +69,13 @@
         id: 2
       - host: ${_param:cluster_node03_address}
         id: 3
+      services_extra_states:
+        contrail-schema:
+        - backup
+        contrail-svc-monitor:
+        - backup
+        contrail-device-manager:
+        - backup
     control:
       version: ${_param:opencontrail_version}
       enabled: true
diff --git a/metadata/service/control/control.yml b/metadata/service/control/control.yml
index 079e222..d033ccf 100644
--- a/metadata/service/control/control.yml
+++ b/metadata/service/control/control.yml
@@ -69,6 +69,13 @@
         id: 2
       - host: ${_param:cluster_node03_address}
         id: 3
+      services_extra_states:
+        contrail-schema:
+        - backup
+        contrail-svc-monitor:
+        - backup
+        contrail-device-manager:
+        - backup
     control:
       version: ${_param:opencontrail_version}
       enabled: true
diff --git a/opencontrail/common.sls b/opencontrail/common.sls
index 7628815..76d2ec9 100644
--- a/opencontrail/common.sls
+++ b/opencontrail/common.sls
@@ -48,7 +48,7 @@
 # TODO: Remove this for Ubuntu Bionic (4.15 is the default kernel)
 net.ipv4.tcp_tw_recycle:
   sysctl.present:
-    - value: 1
+    - value: {{ common.get('tcp_tw_recycle', 1) }}
 {% endif %}
 
 net.ipv4.tcp_tw_reuse:
@@ -99,12 +99,6 @@
   file.directory
 
 {%- if common.identity.engine == "keystone" %}
-/etc/contrail/service.token:
-  file.managed:
-  - contents: "{{ common.identity.token }}"
-  - require:
-    - file: /etc/contrail
-
 /etc/contrail/ctrl-details:
   file.managed:
   - source: salt://opencontrail/files/{{ common.version }}/ctrl-details
diff --git a/opencontrail/files/3.0/contrail-api.ini b/opencontrail/files/3.0/contrail-api.ini
index 4caaeb3..f6b6af2 100644
--- a/opencontrail/files/3.0/contrail-api.ini
+++ b/opencontrail/files/3.0/contrail-api.ini
@@ -1,11 +1,11 @@
 {%- from "opencontrail/map.jinja" import config with context -%}
 [program:contrail-api]
-{%- if config.get('api_workers', 1) < 2 %}
+{%- if config.get('api', {}).get('workers_count', 1) < 2 %}
 command=/usr/bin/contrail-api --conf_file /etc/contrail/contrail-api.conf --conf_file /etc/contrail/contrail-keystone-auth.conf --worker_id %(process_num)s
 numprocs=1
 {%- else %}
 command=/usr/bin/contrail-api --conf_file /etc/contrail/contrail-api.conf --conf_file /etc/contrail/contrail-keystone-auth.conf --worker_id %(process_num)s --listen_port 910%(process_num)s --admin_port 819%(process_num)s --http_server_port 828%(process_num)s --log_file /var/log/contrail/contrail-api-%(process_num)s.log
-numprocs={{ config.api_workers }}
+numprocs={{ config.api.workers_count }}
 {%- endif %}
 process_name=%(process_num)s
 redirect_stderr=true
diff --git a/opencontrail/files/3.0/contrail-control.conf b/opencontrail/files/3.0/contrail-control.conf
index ef85dc4..cfcc314 100644
--- a/opencontrail/files/3.0/contrail-control.conf
+++ b/opencontrail/files/3.0/contrail-control.conf
@@ -25,7 +25,12 @@
   log_level=SYS_NOTICE
   log_local=1
 # test_mode=0
-# xmpp_server_port=5269
+{%- if pillar.get('salt', {}).get('minion', {}).get('cert', {}).opencontrail_xmpp is defined %}
+xmpp_auth_enable=true
+xmpp_server_cert={{ pillar.salt.minion.cert.opencontrail_xmpp.get('cert_file', '/etc/contrail/ssl/certs/server.pem') }}
+xmpp_server_key={{ pillar.salt.minion.cert.opencontrail_xmpp.get('key_file', '/etc/contrail/ssl/private/server-privkey.pem') }}
+xmpp_ca_cert={{ pillar.salt.minion.cert.opencontrail_xmpp.get('ca_file', '/etc/contrail/ssl/certs/ca-cert.pem') }}
+{%- endif %}
 
 [DISCOVERY]
 # port=5998
diff --git a/opencontrail/files/3.0/contrail-vrouter-agent.conf b/opencontrail/files/3.0/contrail-vrouter-agent.conf
index e0104b5..b7e861e 100644
--- a/opencontrail/files/3.0/contrail-vrouter-agent.conf
+++ b/opencontrail/files/3.0/contrail-vrouter-agent.conf
@@ -91,6 +91,13 @@
 gateway_mode={{ compute.gateway_mode }}
 {%- endif %}
 
+{%- if pillar.get('salt', {}).get('minion', {}).get('cert', {}).opencontrail_xmpp is defined %}
+xmpp_auth_enable=true
+xmpp_server_cert={{ pillar.salt.minion.cert.opencontrail_xmpp.get('cert_file', '/etc/contrail/ssl/certs/server.pem') }}
+xmpp_server_key={{ pillar.salt.minion.cert.opencontrail_xmpp.get('key_file', '/etc/contrail/ssl/private/server-privkey.pem') }}
+xmpp_ca_cert={{ pillar.salt.minion.cert.opencontrail_xmpp.get('ca_file', '/etc/contrail/ssl/certs/ca-cert.pem') }}
+{%- endif %}
+
 [DISCOVERY]
 # If COLLECTOR and/or CONTROL-NODE and/or DNS is not specified this section is
 # mandatory. Else this section is optional
diff --git a/opencontrail/files/4.0/contrail-api.ini b/opencontrail/files/4.0/contrail-api.ini
index 4caaeb3..f6b6af2 100644
--- a/opencontrail/files/4.0/contrail-api.ini
+++ b/opencontrail/files/4.0/contrail-api.ini
@@ -1,11 +1,11 @@
 {%- from "opencontrail/map.jinja" import config with context -%}
 [program:contrail-api]
-{%- if config.get('api_workers', 1) < 2 %}
+{%- if config.get('api', {}).get('workers_count', 1) < 2 %}
 command=/usr/bin/contrail-api --conf_file /etc/contrail/contrail-api.conf --conf_file /etc/contrail/contrail-keystone-auth.conf --worker_id %(process_num)s
 numprocs=1
 {%- else %}
 command=/usr/bin/contrail-api --conf_file /etc/contrail/contrail-api.conf --conf_file /etc/contrail/contrail-keystone-auth.conf --worker_id %(process_num)s --listen_port 910%(process_num)s --admin_port 819%(process_num)s --http_server_port 828%(process_num)s --log_file /var/log/contrail/contrail-api-%(process_num)s.log
-numprocs={{ config.api_workers }}
+numprocs={{ config.api.workers_count }}
 {%- endif %}
 process_name=%(process_num)s
 redirect_stderr=true
diff --git a/opencontrail/files/4.0/contrail-config-nodemgr.conf b/opencontrail/files/4.0/contrail-config-nodemgr.conf
index d9964ca..6653427 100644
--- a/opencontrail/files/4.0/contrail-config-nodemgr.conf
+++ b/opencontrail/files/4.0/contrail-config-nodemgr.conf
@@ -1,7 +1,7 @@
 {%- from "opencontrail/map.jinja" import config,database with context %}
 {%- if database is defined and config.version >= 4.0 %}
 [DEFAULTS]
-minimum_diskGB={{ database.get('minimum_disk', 80) }}
+minimum_diskGB={{ database.get('minimum_disk', 150) }}
 hostip={{ database.bind.get('host', '127.0.0.1') }}
 db_port={{ database.bind.get('port_configdb', database.bind.get('port', 9042)) }}
 {%- endif %}
diff --git a/opencontrail/files/4.0/contrail-control.conf b/opencontrail/files/4.0/contrail-control.conf
index 23a39f6..19bf68b 100644
--- a/opencontrail/files/4.0/contrail-control.conf
+++ b/opencontrail/files/4.0/contrail-control.conf
@@ -27,11 +27,12 @@
 log_level=SYS_NOTICE
 log_local=1
 # test_mode=0
-# xmpp_server_port=5269
-# xmpp_auth_enable=0
-# xmpp_server_cert=/etc/contrail/ssl/certs/server.pem
-# xmpp_server_key=/etc/contrail/ssl/private/server-privkey.pem
-# xmpp_ca_cert=/etc/contrail/ssl/certs/ca-cert.pem
+{%- if pillar.get('salt', {}).get('minion', {}).get('cert', {}).opencontrail_xmpp is defined %}
+xmpp_auth_enable=true
+xmpp_server_cert={{ pillar.salt.minion.cert.opencontrail_xmpp.get('cert_file', '/etc/contrail/ssl/certs/server.pem') }}
+xmpp_server_key={{ pillar.salt.minion.cert.opencontrail_xmpp.get('key_file', '/etc/contrail/ssl/private/server-privkey.pem') }}
+xmpp_ca_cert={{ pillar.salt.minion.cert.opencontrail_xmpp.get('ca_file', '/etc/contrail/ssl/certs/ca-cert.pem') }}
+{%- endif %}
 
 # Sandesh send rate limit can be used to throttle system logs transmitted per
 # second. System logs are dropped if the sending rate is exceeded
diff --git a/opencontrail/files/4.0/contrail-svc-monitor.conf b/opencontrail/files/4.0/contrail-svc-monitor.conf
index 8ebc4ee..d1e2dcc 100644
--- a/opencontrail/files/4.0/contrail-svc-monitor.conf
+++ b/opencontrail/files/4.0/contrail-svc-monitor.conf
@@ -44,7 +44,6 @@
 #admin_user=
 #admin_password=
 #admin_tenant_name=
-#admin_token=
 
 [SECURITY]
 use_certs=False
diff --git a/opencontrail/files/4.0/contrail-vrouter-agent.conf b/opencontrail/files/4.0/contrail-vrouter-agent.conf
index e4ad418..6724afa 100644
--- a/opencontrail/files/4.0/contrail-vrouter-agent.conf
+++ b/opencontrail/files/4.0/contrail-vrouter-agent.conf
@@ -6,14 +6,14 @@
 [CONTROL-NODE]
 # List of IPAdress:Port of control-node's separated by space.(Mandatory)
 # servers=10.0.0.1:5269 10.0.0.2:5260 10.0.0.3:5260
-servers={% for member in compute.control.members %}{{ member.host }}:5269 {% endfor %}
+servers={% for member in compute.control.members %}{{ member.host }}:5269{% if not loop.last %} {% endif %}{% endfor %}
 
 [DEFAULT]
 # Everything in this section is optional
 
 # IP address and port to be used to connect to collector.
 # Multiple IP:port strings separated by space can be provided
-collectors = {% for member in compute.collector.members %}{{ member.host }}:8086 {% endfor %}
+collectors = {% for member in compute.collector.members %}{{ member.host }}:8086{% if not loop.last %} {% endif %}{% endfor %}
 
 # Agent mode : can be vrouter / tsn / tor (default is vrouter)
 # agent_mode=
@@ -88,11 +88,12 @@
 # sandesh_send_rate_limit=
 
 # Enable/Disable SSL based XMPP Authentication
-# xmpp_auth_enable=false
-# xmpp_dns_auth_enable=false
-# xmpp_server_cert=/etc/contrail/ssl/certs/server.pem
-# xmpp_server_key=/etc/contrail/ssl/private/server-privkey.pem
-# xmpp_ca_cert=/etc/contrail/ssl/certs/ca-cert.pem
+{%- if pillar.get('salt', {}).get('minion', {}).get('cert', {}).opencontrail_xmpp is defined %}
+xmpp_auth_enable=true
+xmpp_server_cert={{ pillar.salt.minion.cert.opencontrail_xmpp.get('cert_file', '/etc/contrail/ssl/certs/server.pem') }}
+xmpp_server_key={{ pillar.salt.minion.cert.opencontrail_xmpp.get('key_file', '/etc/contrail/ssl/private/server-privkey.pem') }}
+xmpp_ca_cert={{ pillar.salt.minion.cert.opencontrail_xmpp.get('ca_file', '/etc/contrail/ssl/certs/ca-cert.pem') }}
+{%- endif %}
 
 # Gateway mode : can be server/ vcpe (default is none)
 # gateway_mode=
@@ -133,6 +134,7 @@
 
 # List of IPAdress:Port of DNS Servers separated by space.
 # servers=10.0.0.1:53 10.0.0.2:53 10.0.0.3:53
+servers={% for member in compute.control.members %}{{ member.host }}:53{% if not loop.last %} {% endif %}{% endfor %}
 
 # Timeout for DNS server queries in milli-seconds
 # dns_timeout=
diff --git a/opencontrail/files/4.0/contrail-webui-userauth.js b/opencontrail/files/4.0/contrail-webui-userauth.js
index 29424ea..1490f8c 100644
--- a/opencontrail/files/4.0/contrail-webui-userauth.js
+++ b/opencontrail/files/4.0/contrail-webui-userauth.js
@@ -6,18 +6,17 @@
 /****************************************************************************
  * Specify the authentication parameters for admin user
  ****************************************************************************/
- {%- if web.identity.engine == "keystone" %}
 var auth = {};
+auth.admin_token = '';
+{%- if web.identity.engine == "keystone" %}
 auth.admin_user = '{{ web.identity.user }}';
 auth.admin_password = '{{ web.identity.password }}';
-auth.admin_token = '{{ web.identity.token }}';
 auth.admin_tenant_name = '{{ web.identity.tenant }}';
+{%- else %}
+/* NOTE(ivasilevskaya) should be configured at the model level */
+auth.admin_user = 'admin';
+/* NOTE(ivasilevskaya) should be configured at the model level */
+auth.admin_password = 'contrail123';
+{%- endif %}
 
 module.exports = auth;
-{%- else %}
-var auth = {};
-auth.admin_user = 'admin';
-auth.admin_password = 'contrail123';
-auth.admin_token = '';
-module.exports = auth;
-{%- endif %}
\ No newline at end of file
diff --git a/opencontrail/files/4.0/database/cassandra-env.sh b/opencontrail/files/4.0/database/cassandra-env.sh
index 7f2145c..e3ad874 100644
--- a/opencontrail/files/4.0/database/cassandra-env.sh
+++ b/opencontrail/files/4.0/database/cassandra-env.sh
@@ -93,13 +93,14 @@
 jvmver=`echo "$java_ver_output" | grep '[openjdk|java] version' | awk -F'"' 'NR==1 {print $2}'`
 JVM_VERSION=${jvmver%_*}
 JVM_PATCH_VERSION=${jvmver#*_}
+COMPARE_CMD="dpkg --compare-versions"
 
-if [ "$JVM_VERSION" -lt "1.7" ] ; then
+if $COMPARE_CMD "$JVM_VERSION" lt "1.7"  ; then
     echo "Cassandra 2.0 and later require Java 7u25 or later."
     exit 1;
 fi
 
-if [ "$JVM_VERSION" -lt "1.8" ] && [ "$JVM_PATCH_VERSION" -lt "25" ] ; then
+if $COMPARE_CMD "$JVM_VERSION" lt "1.8"  && $COMPARE_CMD "$JVM_PATCH_VERSION" lt "25" ; then
     echo "Cassandra 2.0 and later require Java 7u25 or later."
     exit 1;
 fi
@@ -229,7 +230,7 @@
 JVM_OPTS="$JVM_OPTS -XX:CMSWaitDuration=10000"
 
 # note: bash evals '1.7.x' as > '1.7' so this is really a >= 1.7 jvm check
-if { [ "$JVM_VERSION" -gt "1.7" ] && [ "$JVM_VERSION" -lt "1.8.0" ] && [ "$JVM_PATCH_VERSION" -ge "60" ]; } || [ "$JVM_VERSION" -gt "1.8" ] ; then
+if { $COMPARE_CMD "$JVM_VERSION" gt "1.7" && $COMPARE_CMD "$JVM_VERSION" lt "1.8.0" && $COMPARE_CMD "$JVM_PATCH_VERSION" ge "60" ; } || $COMPARE_CMD "$JVM_VERSION" gt "1.8" ; then
     JVM_OPTS="$JVM_OPTS -XX:+CMSParallelInitialMarkEnabled -XX:+CMSEdenChunksRecordAlways -XX:CMSWaitDuration=10000"
 fi
 
diff --git a/opencontrail/files/grafana_dashboards/contrail_4_controller_prometheus.json b/opencontrail/files/grafana_dashboards/contrail_4_controller_prometheus.json
index 3411f28..72422ea 100644
--- a/opencontrail/files/grafana_dashboards/contrail_4_controller_prometheus.json
+++ b/opencontrail/files/grafana_dashboards/contrail_4_controller_prometheus.json
@@ -334,18 +334,18 @@
       "steppedLine": false,
       "targets": [
         {
-          "expr": "min(haproxy_scur{host=~\"$host\", proxy=~\"contrail.api\", sv=\"BACKEND\"}) by (host)",
+          "expr": "sum(label_replace(haproxy_scur{proxy=~\"contrail.api\", type=\"server\"}, \"sv_new\", \"$1\", \"sv\", \"([a-zA-Z0-9_]+)(?:-.*)?\")) by (sv_new)",
           "format": "time_series",
           "intervalFactor": 2,
-          "legendFormat": "contrail @{{ host }}",
+          "legendFormat": "contrail @{{ sv_new }}",
           "refId": "A",
           "step": 2
         },
         {
-          "expr": "min(haproxy_scur{host=~\"$host\",proxy=~\"contrail.analytics\", sv=\"BACKEND\"}) by (host)",
+          "expr": "sum(label_replace(haproxy_scur{proxy=~\"contrail.analytics\", type=\"server\"}, \"sv_new\", \"$1\", \"sv\", \"([a-zA-Z0-9_]+)(?:-.*)?\")) by (sv_new)",
           "format": "time_series",
           "intervalFactor": 2,
-          "legendFormat": "analytics @{{ host }}",
+          "legendFormat": "analytics @{{ sv_new }}",
           "refId": "B",
           "step": 2
         }
diff --git a/opencontrail/files/grafana_dashboards/contrail_4_vrouter_prometheus.json b/opencontrail/files/grafana_dashboards/contrail_4_vrouter_prometheus.json
new file mode 100644
index 0000000..3d96063
--- /dev/null
+++ b/opencontrail/files/grafana_dashboards/contrail_4_vrouter_prometheus.json
@@ -0,0 +1,1481 @@
+{% raw %}
+{
+  "annotations": {
+    "list": [
+      {
+        "builtIn": 1,
+        "datasource": "prometheus",
+        "enable": true,
+        "hide": true,
+        "iconColor": "rgba(0, 211, 255, 1)",
+        "name": "Annotations & Alerts",
+        "type": "dashboard"
+      }
+    ]
+  },
+  "description": "Monitors Contrail vRouter cluster using Prometheus. Shows overall cluster processes and usage.",
+  "editable": true,
+  "gnetId": null,
+  "graphTooltip": 1,
+  "id": null,
+  "iteration": 1540544225082,
+  "links": [],
+  "panels": [
+    {
+      "collapsed": false,
+      "gridPos": {
+        "h": 1,
+        "w": 24,
+        "x": 0,
+        "y": 0
+      },
+      "id": 29,
+      "panels": [],
+      "title": "Cluster Status",
+      "type": "row"
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": false,
+      "colorValue": true,
+      "colors": [
+        "#d44a3a",
+        "rgba(237, 129, 40, 0.89)",
+        "#299c46"
+      ],
+      "datasource": null,
+      "format": "percentunit",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 6,
+        "w": 3,
+        "x": 0,
+        "y": 1
+      },
+      "id": 31,
+      "interval": null,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "postfix": " UP",
+      "postfixFontSize": "80%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": false,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": true
+      },
+      "tableColumn": "",
+      "targets": [
+        {
+          "expr": "sum(http_response_status{service=\"contrail-vrouter\"} == 1) / count(http_response_status{service=\"contrail-vrouter\"})",
+          "format": "time_series",
+          "intervalFactor": 1,
+          "refId": "A"
+        }
+      ],
+      "thresholds": "0.3,0.7",
+      "title": "vRouters state",
+      "type": "singlestat",
+      "valueFontSize": "80%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "N/A",
+          "value": "null"
+        }
+      ],
+      "valueName": "current"
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": false,
+      "colorValue": false,
+      "colors": [
+        "#d44a3a",
+        "rgba(237, 129, 40, 0.89)",
+        "#299c46"
+      ],
+      "datasource": null,
+      "format": "none",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 6,
+        "w": 3,
+        "x": 3,
+        "y": 1
+      },
+      "id": 34,
+      "interval": null,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "postfix": "",
+      "postfixFontSize": "80%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": false,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": false
+      },
+      "tableColumn": "",
+      "targets": [
+        {
+          "expr": "count(http_response_status{service=\"contrail-vrouter\"})",
+          "format": "time_series",
+          "intervalFactor": 1,
+          "refId": "A"
+        }
+      ],
+      "thresholds": "",
+      "title": "Total vRouters",
+      "type": "singlestat",
+      "valueFontSize": "80%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "N/A",
+          "value": "null"
+        }
+      ],
+      "valueName": "current"
+    },
+    {
+      "collapsed": false,
+      "gridPos": {
+        "h": 1,
+        "w": 24,
+        "x": 0,
+        "y": 7
+      },
+      "id": 21,
+      "panels": [],
+      "repeat": null,
+      "title": "Service Status",
+      "type": "row"
+    },
+    {
+      "cacheTimeout": null,
+      "colorBackground": true,
+      "colorValue": false,
+      "colors": [
+        "rgba(245, 54, 54, 0.9)",
+        "rgba(237, 129, 40, 0.89)",
+        "#299c46"
+      ],
+      "datasource": null,
+      "format": "none",
+      "gauge": {
+        "maxValue": 100,
+        "minValue": 0,
+        "show": false,
+        "thresholdLabels": false,
+        "thresholdMarkers": true
+      },
+      "gridPos": {
+        "h": 3,
+        "w": 24,
+        "x": 0,
+        "y": 8
+      },
+      "id": 2,
+      "interval": null,
+      "links": [],
+      "mappingType": 1,
+      "mappingTypes": [
+        {
+          "name": "value to text",
+          "value": 1
+        },
+        {
+          "name": "range to text",
+          "value": 2
+        }
+      ],
+      "maxDataPoints": 100,
+      "minSpan": 3,
+      "nullPointMode": "connected",
+      "nullText": null,
+      "postfix": "",
+      "postfixFontSize": "50%",
+      "prefix": "",
+      "prefixFontSize": "50%",
+      "rangeMaps": [
+        {
+          "from": "null",
+          "text": "N/A",
+          "to": "null"
+        }
+      ],
+      "repeat": "host",
+      "repeatDirection": "h",
+      "scopedVars": {
+        "host": {
+          "selected": true,
+          "text": "cmp1",
+          "value": "cmp1"
+        }
+      },
+      "sparkline": {
+        "fillColor": "rgba(31, 118, 189, 0.18)",
+        "full": false,
+        "lineColor": "rgb(31, 120, 193)",
+        "show": false
+      },
+      "tableColumn": "",
+      "targets": [
+        {
+          "expr": "http_response_status{host=~\"$host\", service=\"contrail-vrouter\"}",
+          "format": "time_series",
+          "intervalFactor": 2,
+          "legendFormat": "",
+          "refId": "A",
+          "step": 20
+        }
+      ],
+      "thresholds": "0,1",
+      "title": "contrail-vrouter@$host",
+      "type": "singlestat",
+      "valueFontSize": "80%",
+      "valueMaps": [
+        {
+          "op": "=",
+          "text": "N/A",
+          "value": "null"
+        },
+        {
+          "op": "=",
+          "text": "Fail",
+          "value": "0"
+        },
+        {
+          "op": "=",
+          "text": "OK",
+          "value": "1"
+        }
+      ],
+      "valueName": "current"
+    },
+    {
+      "collapsed": false,
+      "gridPos": {
+        "h": 1,
+        "w": 24,
+        "x": 0,
+        "y": 14
+      },
+      "id": 23,
+      "panels": [],
+      "repeat": null,
+      "title": "LLS",
+      "type": "row"
+    },
+    {
+      "aliasColors": {},
+      "bars": false,
+      "dashLength": 10,
+      "dashes": false,
+      "datasource": null,
+      "decimals": 0,
+      "fill": 1,
+      "gridPos": {
+        "h": 7,
+        "w": 24,
+        "x": 0,
+        "y": 15
+      },
+      "id": 9,
+      "legend": {
+        "alignAsTable": true,
+        "avg": false,
+        "current": false,
+        "max": false,
+        "min": false,
+        "rightSide": true,
+        "show": true,
+        "total": false,
+        "values": false
+      },
+      "lines": true,
+      "linewidth": 1,
+      "links": [],
+      "nullPointMode": "null as zero",
+      "percentage": false,
+      "pointradius": 5,
+      "points": false,
+      "renderer": "flot",
+      "seriesOverrides": [],
+      "spaceLength": 10,
+      "stack": false,
+      "steppedLine": false,
+      "targets": [
+        {
+          "expr": "min(contrail_vrouter_lls{host=~\"$host\"}) by (host)",
+          "format": "time_series",
+          "intervalFactor": 2,
+          "legendFormat": "{{ host }}",
+          "refId": "A",
+          "step": 2
+        }
+      ],
+      "thresholds": [],
+      "timeFrom": null,
+      "timeShift": null,
+      "title": "vRouters LLS",
+      "tooltip": {
+        "shared": true,
+        "sort": 0,
+        "value_type": "individual"
+      },
+      "type": "graph",
+      "xaxis": {
+        "buckets": null,
+        "mode": "time",
+        "name": null,
+        "show": true,
+        "values": []
+      },
+      "yaxes": [
+        {
+          "format": "short",
+          "label": null,
+          "logBase": 1,
+          "max": null,
+          "min": "0",
+          "show": true
+        },
+        {
+          "format": "short",
+          "label": null,
+          "logBase": 1,
+          "max": null,
+          "min": null,
+          "show": true
+        }
+      ],
+      "yaxis": {
+        "align": false,
+        "alignLevel": null
+      }
+    },
+    {
+      "collapsed": false,
+      "gridPos": {
+        "h": 1,
+        "w": 24,
+        "x": 0,
+        "y": 22
+      },
+      "id": 24,
+      "panels": [],
+      "repeat": null,
+      "title": "vRouters Statistics",
+      "type": "row"
+    },
+    {
+      "aliasColors": {},
+      "bars": false,
+      "dashLength": 10,
+      "dashes": false,
+      "datasource": null,
+      "decimals": 0,
+      "fill": 1,
+      "gridPos": {
+        "h": 7,
+        "w": 12,
+        "x": 0,
+        "y": 23
+      },
+      "id": 10,
+      "legend": {
+        "alignAsTable": true,
+        "avg": false,
+        "current": false,
+        "max": false,
+        "min": false,
+        "rightSide": true,
+        "show": true,
+        "total": false,
+        "values": false
+      },
+      "lines": true,
+      "linewidth": 1,
+      "links": [],
+      "nullPointMode": "null as zero",
+      "percentage": false,
+      "pointradius": 5,
+      "points": false,
+      "renderer": "flot",
+      "seriesOverrides": [],
+      "spaceLength": 10,
+      "stack": false,
+      "steppedLine": false,
+      "targets": [
+        {
+          "expr": "min(contrail_vrouter_flows_active{host=~\"$host\"}) by (host)",
+          "format": "time_series",
+          "intervalFactor": 2,
+          "legendFormat": "{{ host }}",
+          "refId": "A",
+          "step": 2
+        }
+      ],
+      "thresholds": [],
+      "timeFrom": null,
+      "timeShift": null,
+      "title": "vRouters Flows: Active",
+      "tooltip": {
+        "shared": true,
+        "sort": 0,
+        "value_type": "individual"
+      },
+      "type": "graph",
+      "xaxis": {
+        "buckets": null,
+        "mode": "time",
+        "name": null,
+        "show": true,
+        "values": []
+      },
+      "yaxes": [
+        {
+          "format": "short",
+          "label": null,
+          "logBase": 1,
+          "max": null,
+          "min": "0",
+          "show": true
+        },
+        {
+          "format": "short",
+          "label": null,
+          "logBase": 1,
+          "max": null,
+          "min": null,
+          "show": true
+        }
+      ],
+      "yaxis": {
+        "align": false,
+        "alignLevel": null
+      }
+    },
+    {
+      "aliasColors": {},
+      "bars": false,
+      "dashLength": 10,
+      "dashes": false,
+      "datasource": null,
+      "decimals": 0,
+      "fill": 1,
+      "gridPos": {
+        "h": 7,
+        "w": 12,
+        "x": 12,
+        "y": 23
+      },
+      "id": 11,
+      "legend": {
+        "alignAsTable": true,
+        "avg": false,
+        "current": false,
+        "max": false,
+        "min": false,
+        "rightSide": true,
+        "show": true,
+        "total": false,
+        "values": false
+      },
+      "lines": true,
+      "linewidth": 1,
+      "links": [],
+      "nullPointMode": "null as zero",
+      "percentage": false,
+      "pointradius": 5,
+      "points": false,
+      "renderer": "flot",
+      "seriesOverrides": [],
+      "spaceLength": 10,
+      "stack": false,
+      "steppedLine": false,
+      "targets": [
+        {
+          "expr": "min(contrail_vrouter_flows_aged{host=~\"$host\"}) by (host)",
+          "format": "time_series",
+          "intervalFactor": 2,
+          "legendFormat": "{{ host }}",
+          "refId": "A",
+          "step": 2
+        }
+      ],
+      "thresholds": [],
+      "timeFrom": null,
+      "timeShift": null,
+      "title": "vRouters Flows: Aged",
+      "tooltip": {
+        "shared": true,
+        "sort": 0,
+        "value_type": "individual"
+      },
+      "type": "graph",
+      "xaxis": {
+        "buckets": null,
+        "mode": "time",
+        "name": null,
+        "show": true,
+        "values": []
+      },
+      "yaxes": [
+        {
+          "format": "short",
+          "label": null,
+          "logBase": 1,
+          "max": null,
+          "min": "0",
+          "show": true
+        },
+        {
+          "format": "short",
+          "label": null,
+          "logBase": 1,
+          "max": null,
+          "min": null,
+          "show": true
+        }
+      ],
+      "yaxis": {
+        "align": false,
+        "alignLevel": null
+      }
+    },
+    {
+      "collapsed": false,
+      "gridPos": {
+        "h": 1,
+        "w": 24,
+        "x": 0,
+        "y": 30
+      },
+      "id": 25,
+      "panels": [],
+      "repeat": null,
+      "title": "vRouters Errors",
+      "type": "row"
+    },
+    {
+      "aliasColors": {},
+      "bars": false,
+      "dashLength": 10,
+      "dashes": false,
+      "datasource": null,
+      "decimals": 0,
+      "fill": 1,
+      "gridPos": {
+        "h": 7,
+        "w": 8,
+        "x": 0,
+        "y": 31
+      },
+      "id": 12,
+      "legend": {
+        "alignAsTable": true,
+        "avg": false,
+        "current": false,
+        "max": false,
+        "min": false,
+        "rightSide": true,
+        "show": true,
+        "total": false,
+        "values": false
+      },
+      "lines": true,
+      "linewidth": 1,
+      "links": [],
+      "nullPointMode": "null as zero",
+      "percentage": false,
+      "pointradius": 5,
+      "points": false,
+      "renderer": "flot",
+      "seriesOverrides": [],
+      "spaceLength": 10,
+      "stack": false,
+      "steppedLine": false,
+      "targets": [
+        {
+          "expr": "min(contrail_vrouter_flows_composite_invalid_interface{host=~\"$host\"}) by (host)",
+          "format": "time_series",
+          "intervalFactor": 2,
+          "legendFormat": "{{ host }}",
+          "refId": "A",
+          "step": 2
+        }
+      ],
+      "thresholds": [],
+      "timeFrom": null,
+      "timeShift": null,
+      "title": "vRouters Flows: Invalid Interface",
+      "tooltip": {
+        "shared": true,
+        "sort": 0,
+        "value_type": "individual"
+      },
+      "type": "graph",
+      "xaxis": {
+        "buckets": null,
+        "mode": "time",
+        "name": null,
+        "show": true,
+        "values": []
+      },
+      "yaxes": [
+        {
+          "format": "short",
+          "label": null,
+          "logBase": 1,
+          "max": null,
+          "min": "0",
+          "show": true
+        },
+        {
+          "format": "short",
+          "label": null,
+          "logBase": 1,
+          "max": null,
+          "min": null,
+          "show": true
+        }
+      ],
+      "yaxis": {
+        "align": false,
+        "alignLevel": null
+      }
+    },
+    {
+      "aliasColors": {},
+      "bars": false,
+      "dashLength": 10,
+      "dashes": false,
+      "datasource": null,
+      "decimals": 0,
+      "fill": 1,
+      "gridPos": {
+        "h": 7,
+        "w": 8,
+        "x": 8,
+        "y": 31
+      },
+      "id": 13,
+      "legend": {
+        "alignAsTable": true,
+        "avg": false,
+        "current": false,
+        "max": false,
+        "min": false,
+        "rightSide": true,
+        "show": true,
+        "total": false,
+        "values": false
+      },
+      "lines": true,
+      "linewidth": 1,
+      "links": [],
+      "nullPointMode": "null as zero",
+      "percentage": false,
+      "pointradius": 5,
+      "points": false,
+      "renderer": "flot",
+      "seriesOverrides": [],
+      "spaceLength": 10,
+      "stack": false,
+      "steppedLine": false,
+      "targets": [
+        {
+          "expr": "min(contrail_vrouter_flows_created{host=~\"$host\"}) by (host)",
+          "format": "time_series",
+          "intervalFactor": 2,
+          "legendFormat": "{{ host }}",
+          "refId": "A",
+          "step": 2
+        }
+      ],
+      "thresholds": [],
+      "timeFrom": null,
+      "timeShift": null,
+      "title": "vRouters Flows: Created",
+      "tooltip": {
+        "shared": true,
+        "sort": 0,
+        "value_type": "individual"
+      },
+      "type": "graph",
+      "xaxis": {
+        "buckets": null,
+        "mode": "time",
+        "name": null,
+        "show": true,
+        "values": []
+      },
+      "yaxes": [
+        {
+          "format": "short",
+          "label": null,
+          "logBase": 1,
+          "max": null,
+          "min": "0",
+          "show": true
+        },
+        {
+          "format": "short",
+          "label": null,
+          "logBase": 1,
+          "max": null,
+          "min": null,
+          "show": true
+        }
+      ],
+      "yaxis": {
+        "align": false,
+        "alignLevel": null
+      }
+    },
+    {
+      "aliasColors": {},
+      "bars": false,
+      "dashLength": 10,
+      "dashes": false,
+      "datasource": null,
+      "decimals": 0,
+      "fill": 1,
+      "gridPos": {
+        "h": 7,
+        "w": 8,
+        "x": 16,
+        "y": 31
+      },
+      "id": 14,
+      "legend": {
+        "alignAsTable": true,
+        "avg": false,
+        "current": false,
+        "max": false,
+        "min": false,
+        "rightSide": true,
+        "show": true,
+        "total": false,
+        "values": false
+      },
+      "lines": true,
+      "linewidth": 1,
+      "links": [],
+      "nullPointMode": "null as zero",
+      "percentage": false,
+      "pointradius": 5,
+      "points": false,
+      "renderer": "flot",
+      "seriesOverrides": [],
+      "spaceLength": 10,
+      "stack": false,
+      "steppedLine": false,
+      "targets": [
+        {
+          "expr": "min(contrail_vrouter_flows_discard{host=~\"$host\"}) by (host)",
+          "format": "time_series",
+          "intervalFactor": 2,
+          "legendFormat": "{{ host }}",
+          "refId": "A",
+          "step": 2
+        }
+      ],
+      "thresholds": [],
+      "timeFrom": null,
+      "timeShift": null,
+      "title": "vRouters Flows: Discard",
+      "tooltip": {
+        "shared": true,
+        "sort": 0,
+        "value_type": "individual"
+      },
+      "type": "graph",
+      "xaxis": {
+        "buckets": null,
+        "mode": "time",
+        "name": null,
+        "show": true,
+        "values": []
+      },
+      "yaxes": [
+        {
+          "format": "short",
+          "label": null,
+          "logBase": 1,
+          "max": null,
+          "min": "0",
+          "show": true
+        },
+        {
+          "format": "short",
+          "label": null,
+          "logBase": 1,
+          "max": null,
+          "min": null,
+          "show": true
+        }
+      ],
+      "yaxis": {
+        "align": false,
+        "alignLevel": null
+      }
+    },
+    {
+      "aliasColors": {},
+      "bars": false,
+      "dashLength": 10,
+      "dashes": false,
+      "datasource": null,
+      "decimals": 0,
+      "fill": 1,
+      "gridPos": {
+        "h": 7,
+        "w": 8,
+        "x": 0,
+        "y": 38
+      },
+      "id": 15,
+      "legend": {
+        "alignAsTable": true,
+        "avg": false,
+        "current": false,
+        "max": false,
+        "min": false,
+        "rightSide": true,
+        "show": true,
+        "total": false,
+        "values": false
+      },
+      "lines": true,
+      "linewidth": 1,
+      "links": [],
+      "nullPointMode": "null as zero",
+      "percentage": false,
+      "pointradius": 5,
+      "points": false,
+      "renderer": "flot",
+      "seriesOverrides": [],
+      "spaceLength": 10,
+      "stack": false,
+      "steppedLine": false,
+      "targets": [
+        {
+          "expr": "min(contrail_vrouter_flows_flow_action_drop{host=~\"$host\"}) by (host)",
+          "format": "time_series",
+          "intervalFactor": 2,
+          "legendFormat": "{{ host }}",
+          "refId": "A",
+          "step": 2
+        }
+      ],
+      "thresholds": [],
+      "timeFrom": null,
+      "timeShift": null,
+      "title": "vRouters Flows: Drop",
+      "tooltip": {
+        "shared": true,
+        "sort": 0,
+        "value_type": "individual"
+      },
+      "type": "graph",
+      "xaxis": {
+        "buckets": null,
+        "mode": "time",
+        "name": null,
+        "show": true,
+        "values": []
+      },
+      "yaxes": [
+        {
+          "format": "short",
+          "label": null,
+          "logBase": 1,
+          "max": null,
+          "min": "0",
+          "show": true
+        },
+        {
+          "format": "short",
+          "label": null,
+          "logBase": 1,
+          "max": null,
+          "min": null,
+          "show": true
+        }
+      ],
+      "yaxis": {
+        "align": false,
+        "alignLevel": null
+      }
+    },
+    {
+      "aliasColors": {},
+      "bars": false,
+      "dashLength": 10,
+      "dashes": false,
+      "datasource": null,
+      "decimals": 0,
+      "fill": 1,
+      "gridPos": {
+        "h": 7,
+        "w": 8,
+        "x": 8,
+        "y": 38
+      },
+      "id": 16,
+      "legend": {
+        "alignAsTable": true,
+        "avg": false,
+        "current": false,
+        "max": false,
+        "min": false,
+        "rightSide": true,
+        "show": true,
+        "total": false,
+        "values": false
+      },
+      "lines": true,
+      "linewidth": 1,
+      "links": [],
+      "nullPointMode": "null as zero",
+      "percentage": false,
+      "pointradius": 5,
+      "points": false,
+      "renderer": "flot",
+      "seriesOverrides": [],
+      "spaceLength": 10,
+      "stack": false,
+      "steppedLine": false,
+      "targets": [
+        {
+          "expr": "min(contrail_vrouter_flows_flow_queue_limit_exceeded{host=~\"$host\"}) by (host)",
+          "format": "time_series",
+          "intervalFactor": 2,
+          "legendFormat": "{{ host }}",
+          "refId": "A",
+          "step": 2
+        }
+      ],
+      "thresholds": [],
+      "timeFrom": null,
+      "timeShift": null,
+      "title": "vRouters Flows: Queue Limit Exceeded",
+      "tooltip": {
+        "shared": true,
+        "sort": 0,
+        "value_type": "individual"
+      },
+      "type": "graph",
+      "xaxis": {
+        "buckets": null,
+        "mode": "time",
+        "name": null,
+        "show": true,
+        "values": []
+      },
+      "yaxes": [
+        {
+          "format": "short",
+          "label": null,
+          "logBase": 1,
+          "max": null,
+          "min": "0",
+          "show": true
+        },
+        {
+          "format": "short",
+          "label": null,
+          "logBase": 1,
+          "max": null,
+          "min": null,
+          "show": true
+        }
+      ],
+      "yaxis": {
+        "align": false,
+        "alignLevel": null
+      }
+    },
+    {
+      "aliasColors": {},
+      "bars": false,
+      "dashLength": 10,
+      "dashes": false,
+      "datasource": null,
+      "decimals": 0,
+      "fill": 1,
+      "gridPos": {
+        "h": 7,
+        "w": 8,
+        "x": 16,
+        "y": 38
+      },
+      "id": 17,
+      "legend": {
+        "alignAsTable": true,
+        "avg": false,
+        "current": false,
+        "max": false,
+        "min": false,
+        "rightSide": true,
+        "show": true,
+        "total": false,
+        "values": false
+      },
+      "lines": true,
+      "linewidth": 1,
+      "links": [],
+      "nullPointMode": "null as zero",
+      "percentage": false,
+      "pointradius": 5,
+      "points": false,
+      "renderer": "flot",
+      "seriesOverrides": [],
+      "spaceLength": 10,
+      "stack": false,
+      "steppedLine": false,
+      "targets": [
+        {
+          "expr": "min(contrail_vrouter_flows_flow_table_full{host=~\"$host\"}) by (host)",
+          "format": "time_series",
+          "intervalFactor": 2,
+          "legendFormat": "{{ host }}",
+          "refId": "A",
+          "step": 2
+        }
+      ],
+      "thresholds": [],
+      "timeFrom": null,
+      "timeShift": null,
+      "title": "vRouters Flows: Table Full",
+      "tooltip": {
+        "shared": true,
+        "sort": 0,
+        "value_type": "individual"
+      },
+      "type": "graph",
+      "xaxis": {
+        "buckets": null,
+        "mode": "time",
+        "name": null,
+        "show": true,
+        "values": []
+      },
+      "yaxes": [
+        {
+          "format": "short",
+          "label": null,
+          "logBase": 1,
+          "max": null,
+          "min": "0",
+          "show": true
+        },
+        {
+          "format": "short",
+          "label": null,
+          "logBase": 1,
+          "max": null,
+          "min": null,
+          "show": true
+        }
+      ],
+      "yaxis": {
+        "align": false,
+        "alignLevel": null
+      }
+    },
+    {
+      "aliasColors": {},
+      "bars": false,
+      "dashLength": 10,
+      "dashes": false,
+      "datasource": null,
+      "decimals": 0,
+      "fill": 1,
+      "gridPos": {
+        "h": 7,
+        "w": 8,
+        "x": 0,
+        "y": 45
+      },
+      "id": 18,
+      "legend": {
+        "alignAsTable": true,
+        "avg": false,
+        "current": false,
+        "max": false,
+        "min": false,
+        "rightSide": true,
+        "show": true,
+        "total": false,
+        "values": false
+      },
+      "lines": true,
+      "linewidth": 1,
+      "links": [],
+      "nullPointMode": "null as zero",
+      "percentage": false,
+      "pointradius": 5,
+      "points": false,
+      "renderer": "flot",
+      "seriesOverrides": [],
+      "spaceLength": 10,
+      "stack": false,
+      "steppedLine": false,
+      "targets": [
+        {
+          "expr": "min(contrail_vrouter_flows_frag_err{host=~\"$host\"}) by (host)",
+          "format": "time_series",
+          "intervalFactor": 2,
+          "legendFormat": "{{ host }}",
+          "refId": "A",
+          "step": 2
+        }
+      ],
+      "thresholds": [],
+      "timeFrom": null,
+      "timeShift": null,
+      "title": "vRouters Flows: Fragmentation Error",
+      "tooltip": {
+        "shared": true,
+        "sort": 0,
+        "value_type": "individual"
+      },
+      "type": "graph",
+      "xaxis": {
+        "buckets": null,
+        "mode": "time",
+        "name": null,
+        "show": true,
+        "values": []
+      },
+      "yaxes": [
+        {
+          "format": "short",
+          "label": null,
+          "logBase": 1,
+          "max": null,
+          "min": "0",
+          "show": true
+        },
+        {
+          "format": "short",
+          "label": null,
+          "logBase": 1,
+          "max": null,
+          "min": null,
+          "show": true
+        }
+      ],
+      "yaxis": {
+        "align": false,
+        "alignLevel": null
+      }
+    },
+    {
+      "aliasColors": {},
+      "bars": false,
+      "dashLength": 10,
+      "dashes": false,
+      "datasource": null,
+      "decimals": 0,
+      "fill": 1,
+      "gridPos": {
+        "h": 7,
+        "w": 8,
+        "x": 8,
+        "y": 45
+      },
+      "id": 19,
+      "legend": {
+        "alignAsTable": true,
+        "avg": false,
+        "current": false,
+        "max": false,
+        "min": false,
+        "rightSide": true,
+        "show": true,
+        "total": false,
+        "values": false
+      },
+      "lines": true,
+      "linewidth": 1,
+      "links": [],
+      "nullPointMode": "null as zero",
+      "percentage": false,
+      "pointradius": 5,
+      "points": false,
+      "renderer": "flot",
+      "seriesOverrides": [],
+      "spaceLength": 10,
+      "stack": false,
+      "steppedLine": false,
+      "targets": [
+        {
+          "expr": "min(contrail_vrouter_flows_invalid_label{host=~\"$host\"}) by (host)",
+          "format": "time_series",
+          "intervalFactor": 2,
+          "legendFormat": "{{ host }}",
+          "refId": "A",
+          "step": 2
+        }
+      ],
+      "thresholds": [],
+      "timeFrom": null,
+      "timeShift": null,
+      "title": "vRouters Flows: Invalid Label",
+      "tooltip": {
+        "shared": true,
+        "sort": 0,
+        "value_type": "individual"
+      },
+      "type": "graph",
+      "xaxis": {
+        "buckets": null,
+        "mode": "time",
+        "name": null,
+        "show": true,
+        "values": []
+      },
+      "yaxes": [
+        {
+          "format": "short",
+          "label": null,
+          "logBase": 1,
+          "max": null,
+          "min": "0",
+          "show": true
+        },
+        {
+          "format": "short",
+          "label": null,
+          "logBase": 1,
+          "max": null,
+          "min": null,
+          "show": true
+        }
+      ],
+      "yaxis": {
+        "align": false,
+        "alignLevel": null
+      }
+    },
+    {
+      "aliasColors": {},
+      "bars": false,
+      "dashLength": 10,
+      "dashes": false,
+      "datasource": null,
+      "decimals": 0,
+      "fill": 1,
+      "gridPos": {
+        "h": 7,
+        "w": 8,
+        "x": 16,
+        "y": 45
+      },
+      "id": 20,
+      "legend": {
+        "alignAsTable": true,
+        "avg": false,
+        "current": false,
+        "max": false,
+        "min": false,
+        "rightSide": true,
+        "show": true,
+        "total": false,
+        "values": false
+      },
+      "lines": true,
+      "linewidth": 1,
+      "links": [],
+      "nullPointMode": "null as zero",
+      "percentage": false,
+      "pointradius": 5,
+      "points": false,
+      "renderer": "flot",
+      "seriesOverrides": [],
+      "spaceLength": 10,
+      "stack": false,
+      "steppedLine": false,
+      "targets": [
+        {
+          "expr": "min(contrail_vrouter_flows_invalid_nh{host=~\"$host\"}) by (host)",
+          "format": "time_series",
+          "intervalFactor": 2,
+          "legendFormat": "{{ host }}",
+          "refId": "A",
+          "step": 2
+        }
+      ],
+      "thresholds": [],
+      "timeFrom": null,
+      "timeShift": null,
+      "title": "vRouters Flows: Invalid Next Hop",
+      "tooltip": {
+        "shared": true,
+        "sort": 0,
+        "value_type": "individual"
+      },
+      "type": "graph",
+      "xaxis": {
+        "buckets": null,
+        "mode": "time",
+        "name": null,
+        "show": true,
+        "values": []
+      },
+      "yaxes": [
+        {
+          "format": "short",
+          "label": null,
+          "logBase": 1,
+          "max": null,
+          "min": "0",
+          "show": true
+        },
+        {
+          "format": "short",
+          "label": null,
+          "logBase": 1,
+          "max": null,
+          "min": null,
+          "show": true
+        }
+      ],
+      "yaxis": {
+        "align": false,
+        "alignLevel": null
+      }
+    }
+  ],
+  "refresh": "1m",
+  "schemaVersion": 16,
+  "style": "dark",
+  "tags": [
+    "contrail"
+  ],
+  "templating": {
+    "list": [
+      {
+        "allValue": null,
+        "current": {
+          "selected": false,
+          "text": "cmp1",
+          "value": "cmp1"
+        },
+        "datasource": "prometheus",
+        "hide": 0,
+        "includeAll": false,
+        "label": null,
+        "multi": true,
+        "name": "host",
+        "options": [],
+        "query": "label_values(http_response_status{service=\"contrail-vrouter\"},host)",
+        "refresh": 1,
+        "refresh_on_load": true,
+        "regex": "",
+        "sort": 1,
+        "tagValuesQuery": "",
+        "tags": [],
+        "tagsQuery": "",
+        "type": "query",
+        "useTags": false
+      }
+    ]
+  },
+  "time": {
+    "from": "now-1h",
+    "to": "now"
+  },
+  "timepicker": {
+    "refresh_intervals": [
+      "5s",
+      "10s",
+      "30s",
+      "1m",
+      "5m",
+      "15m",
+      "30m",
+      "1h",
+      "2h",
+      "1d"
+    ],
+    "time_options": [
+      "5m",
+      "15m",
+      "1h",
+      "6h",
+      "12h",
+      "24h",
+      "2d",
+      "7d",
+      "30d"
+    ]
+  },
+  "timezone": "browser",
+  "title": "OpenContrail vRouter",
+  "uid": null,
+  "version": 1
+}
+{% endraw %}
diff --git a/opencontrail/files/grafana_dashboards/contrail_controller_prometheus.json b/opencontrail/files/grafana_dashboards/contrail_controller_prometheus.json
index ab8fcae..ecbad3b 100644
--- a/opencontrail/files/grafana_dashboards/contrail_controller_prometheus.json
+++ b/opencontrail/files/grafana_dashboards/contrail_controller_prometheus.json
@@ -416,26 +416,26 @@
       "steppedLine": false,
       "targets": [
         {
-          "expr": "min(haproxy_scur{host=~\"$host\", proxy=~\"contrail.api\", sv=\"BACKEND\"}) by (host)",
+          "expr": "sum(label_replace(haproxy_scur{proxy=~\"contrail.api\", type=\"server\"}, \"sv_new\", \"$1\", \"sv\", \"([a-zA-Z0-9_]+)(?:-.*)?\")) by (sv_new)",
           "format": "time_series",
           "intervalFactor": 2,
-          "legendFormat": "contrail @{{ host }}",
+          "legendFormat": "contrail @{{ sv_new }}",
           "refId": "A",
           "step": 2
         },
         {
-          "expr": "min(haproxy_scur{host=~\"$host\",proxy=~\"contrail.analytics\", sv=\"BACKEND\"}) by (host)",
+          "expr": "sum(label_replace(haproxy_scur{proxy=~\"contrail.analytics\", type=\"server\"}, \"sv_new\", \"$1\", \"sv\", \"([a-zA-Z0-9_]+)(?:-.*)?\")) by (sv_new)",
           "format": "time_series",
           "intervalFactor": 2,
-          "legendFormat": "analytics @{{ host }}",
+          "legendFormat": "analytics @{{ sv_new }}",
           "refId": "B",
           "step": 2
         },
         {
-          "expr": "min(haproxy_scur{host=~\"$host\",proxy=~\"contrail.discovery\", sv=\"BACKEND\"}) by (host)",
+          "expr": "sum(label_replace(haproxy_scur{proxy=~\"contrail.discovery\", type=\"server\"}, \"sv_new\", \"$1\", \"sv\", \"([a-zA-Z0-9_]+)(?:-.*)?\")) by (sv_new)",
           "format": "time_series",
           "intervalFactor": 2,
-          "legendFormat": "discovery @{{ host }}",
+          "legendFormat": "discovery @{{ sv_new }}",
           "refId": "C"
         }
       ],
diff --git a/opencontrail/files/grafana_dashboards/contrail_vrouter_prometheus.json b/opencontrail/files/grafana_dashboards/contrail_vrouter_prometheus.json
index c5fc292..3de0227 100644
--- a/opencontrail/files/grafana_dashboards/contrail_vrouter_prometheus.json
+++ b/opencontrail/files/grafana_dashboards/contrail_vrouter_prometheus.json
@@ -321,7 +321,7 @@
       "id": 23,
       "panels": [],
       "repeat": null,
-      "title": "BGP, XMPP, DNS-XMPP & LLS",
+      "title": "DNS-XMPP & LLS",
       "type": "row"
     },
     {
diff --git a/opencontrail/meta/grafana.yml b/opencontrail/meta/grafana.yml
index 3b535b2..7bbbc87 100644
--- a/opencontrail/meta/grafana.yml
+++ b/opencontrail/meta/grafana.yml
@@ -23,7 +23,11 @@
   contrail_vrouter_prometheus:
     datasource: prometheus
     format: json
+{%- if version < 4.0 %}
     template: opencontrail/files/grafana_dashboards/contrail_vrouter_prometheus.json
+{%- else %}
+    template: opencontrail/files/grafana_dashboards/contrail_4_vrouter_prometheus.json
+{%- endif %}
   zookeeper_influxdb:
     datasource: influxdb
     format: json
diff --git a/opencontrail/meta/prometheus.yml b/opencontrail/meta/prometheus.yml
index acc522b..d08b385 100644
--- a/opencontrail/meta/prometheus.yml
+++ b/opencontrail/meta/prometheus.yml
@@ -253,10 +253,13 @@
       annotations:
         summary: "OpenContrail vRouter XMPP sessions changes reached the limit of {%- endraw %}{{ vrouter_xmpp_variation_threshold }}{%- raw %}"
         description: "The OpenContrail vRouter XMPP sessions on the {{ $labels.host }} node have changed {{ $value }} times."
+{%- endraw %}
+  {%- if version < 4.0 %}
     ContrailVrouterDNSXMPPSessionsZero:
       if: >-
         min(contrail_vrouter_dns_xmpp) by (host) == 0
       for: 2m
+{%- raw %}
       labels:
         severity: warning
         service: contrail
@@ -289,6 +292,7 @@
         summary: "OpenContrail vRouter DNS-XMPP sessions changes reached the limit of {%- endraw %}{{ vrouter_dns_xmpp_variation_threshold }}{%- raw %}"
         description: "The OpenContrail vRouter DNS-XMPP sessions on the {{ $labels.host }} node have changed {{ $value }} times."
 {%- endraw %}
+  {%- endif %}
     ContrailVrouterLLSSessionsTooHigh:
       if: >-
     {%- set vrouter_lls_toohigh_threshold = monitoring.vrouter_lls_too_high_threshold %}
diff --git a/opencontrail/meta/telegraf.yml b/opencontrail/meta/telegraf.yml
index ef973fc..f4736f6 100644
--- a/opencontrail/meta/telegraf.yml
+++ b/opencontrail/meta/telegraf.yml
@@ -230,10 +230,12 @@
           url: "http://{{ bind_addr }}:8085/Snh_KDropStatsReq"
           xml_element: "KDropStatsResp"
           result_type: "ds_invalid_nh"
+      {%- if version < 4.0 %}
         vrouter_dns_xmpp:
           url: "http://{{ bind_addr }}:8085/Snh_AgentDnsXmppConnectionStatusReq"
           xml_element: "AgentXmppDnsData"
           state: "Established"
+      {%- endif %}
         vrouter_lls:
           url: "http://{{ bind_addr }}:8085/Snh_LinkLocalServiceInfo"
           xml_element: "LinkLocalServiceData"
@@ -243,4 +245,9 @@
           state: "Established"
     {%- endif %}
   {%- endif %}
+  {%- if pillar.haproxy is defined and pillar.haproxy.proxy is defined %}
+    haproxy:
+      tagdrop:
+        proxy: ["contrail_collector_stats", "contrail_config_stats", "contrail_openstack_stats"]
+  {%- endif %}
 {%- endif %}
diff --git a/opencontrail/upgrade/verify/_service.sls b/opencontrail/upgrade/verify/_service.sls
new file mode 100644
index 0000000..9151bd1
--- /dev/null
+++ b/opencontrail/upgrade/verify/_service.sls
@@ -0,0 +1,18 @@
+{%- from "opencontrail/map.jinja" import control, config, collector, web, database, compute with context %}
+
+{%- set extra_states_map = {} %}
+
+{%- for data in [control, config, collector, web, database, compute] %}
+
+{%- if data.get('enabled', False) %}
+  {%- if data.get('services_extra_states', False) %}
+    {% do extra_states_map.update(data.get('services_extra_states')) %}
+  {%- endif %}
+{%- endif %}
+
+{%- endfor %}
+
+contrail_services_health_check:
+  contrail_health.services_health:
+    - healthy_states: ['active']
+    - extra_states_map: {{ extra_states_map }}
diff --git a/opencontrail/upgrade/verify/init.sls b/opencontrail/upgrade/verify/init.sls
new file mode 100644
index 0000000..c40bb57
--- /dev/null
+++ b/opencontrail/upgrade/verify/init.sls
@@ -0,0 +1,2 @@
+include:
+- opencontrail.upgrade.verify._service