[Tooling update] health_checks
* Added:
- Retrieve contrail vrouter agent status from analyticsdb
- Retrieve filtered contrail vrouter agent info from analyticsdb
- Remove unwanted debug print from entropy_check function
Related-Prod: PROD-29236
Change-Id: I272a1fea3e39ec597647947cad798993f09e536a
diff --git a/README.rst b/README.rst
index 55b079c..fc8366b 100644
--- a/README.rst
+++ b/README.rst
@@ -865,6 +865,18 @@
salt -C cmp001* health_checks.contrail_vrouter_agent_status
+Retrieve contrail vrouter agent status from analyticsdb
+
+.. code-block:: bash
+
+ salt-call health_checks.contrail_collector_agent_status
+
+Retrieve filtered contrail vrouter agent info from analyticsdb
+
+.. code-block:: bash
+
+ salt-call health_checks.contrail_vrouter_agent_info cmp001
+
Fetch libvirt supported machine types for compute node
.. code-block:: bash
diff --git a/_modules/health_checks.py b/_modules/health_checks.py
index ad43343..6180023 100644
--- a/_modules/health_checks.py
+++ b/_modules/health_checks.py
@@ -6,6 +6,7 @@
import os
import re
import json
+import yaml
__author__ = "Dzmitry Stremkouski"
__copyright__ = "Copyright 2019, Mirantis Inc."
@@ -15,6 +16,53 @@
stream = logging.StreamHandler()
logger.addHandler(stream)
+try:
+ from yaml import CLoader as Loader, CDumper as Dumper
+except ImportError:
+ from yaml import Loader, Dumper
+
+default_vrouter_info_map = yaml.load("""
+ContrailConfig:
+- deleted
+- elements:uuid
+- elements:virtual_router_dpdk_enabled
+- elements:virtual_router_type
+VrouterAgent:
+- build_info:build-info:0:build-version
+- build_info:build-info:0:build-number
+- collector_server_list_cfg
+- config_file
+- control_ip
+- control_node_list_cfg
+- dns_server_list_cfg
+- dns_servers
+- down_interface_count
+- eth_name
+- headless_mode_cfg
+- hostname_cfg
+- hypervisor
+- mode
+- phy_if
+- platform
+- self_ip_list
+- total_interface_count
+- tunnel_type
+- vhost_cfg
+- vhost_if
+- vr_limits:max_interfaces
+- vr_limits:max_labels
+- vr_limits:max_mirror_entries
+- vr_limits:max_nexthops
+- vr_limits:max_vrfs
+- vr_limits:vrouter_max_bridge_entries
+- vr_limits:vrouter_max_flow_entries
+- vr_limits:vrouter_max_oflow_bridge_entries
+- vr_limits:vrouter_max_oflow_entries
+- xmpp_peer_list:*:ip
+- xmpp_peer_list:*:primary
+- xmpp_peer_list:*:status
+""", Loader=Loader)
+
def _failed_minions(out, agent, failed_minions):
@@ -1044,7 +1092,6 @@
failed_minions = []
verified_minions = []
- print out
for minion in out:
verified_minions.append(minion)
entropy = int(out[minion]['ret'])
@@ -1315,6 +1362,94 @@
return "Unsupported xml tree for this function %s" % str(req.text)
+def contrail_collector_agent_status(vr_name, api_host='auto', api_port=9081):
+
+ ''' Retrieve contrail vrouter agent status from analyticsdb '''
+
+ if api_host[0:4] == 'http':
+ url = api_host + ':' + str(api_port)
+ elif api_host == 'auto':
+ my_ip = __salt__['pillar.get']('_param:opencontrail_analytics_address')
+ url = 'http://' + my_ip+ ':' + str(api_port)
+ else:
+ url = 'http://' + api_host + ':' + str(api_port)
+
+ req = requests.get(url + '/analytics/uves/vrouter/' + vr_name + '?flat')
+ if int(req.status_code) != 200:
+ return "Could not fetch data from vrouter agent via %s.\nGot bad status code: %s\n%s" % (url, str(req.status_code), str(req.text))
+
+ return json.loads(req.text)
+
+
+def _get_object(json_obj, obj_path):
+
+ ''' Retrieve subelemet of an JSON object or value '''
+
+ if ':' in obj_path:
+ splitter = obj_path.split(':')
+ k = splitter[0]
+ v = ':'.join(splitter[1:])
+ if k.isdigit():
+ # Return specific element path
+ return [ _get_object(json_obj[int(k)], v) ]
+ elif k == '*':
+ l = []
+ for el in json_obj:
+ l.append(_get_object(el, v))
+ # Return all list elements from the path
+ return l
+ else:
+ # Contrail output may have nested JSON
+ if isinstance(json_obj, str) or isinstance(json_obj, unicode):
+ json_obj = json.loads(json_obj)
+ # Assume list. Return it
+ return { k: _get_object(json_obj[k], v) }
+ else:
+ return { obj_path: json_obj[obj_path] }
+
+
+def _deepmerge(o1, o2):
+
+ ''' Deep merge JSON objects '''
+
+ o3 = {}
+ if type(o1) == type(o2):
+ if type(o1) == dict or type(o1) == tuple:
+ for k in set(o1.keys() + o2.keys()):
+ if k in o1:
+ if k in o2:
+ o3[k] = _deepmerge(o1[k], o2[k])
+ else:
+ o3[k] = o1[k]
+ else:
+ o3[k] = o2[k]
+ elif type(o1) == list or type(o1) == set:
+ o3 = [] + o2
+ for el in o3:
+ i = o3.index(el)
+ o3[i] = _deepmerge(o1[i], o2[i])
+ else:
+ o3 = o2
+ else:
+ o3 = o2
+
+ return o3
+
+
+def contrail_vrouter_agent_info(vr_name, filter_map=default_vrouter_info_map):
+
+ ''' Retrieve filtered contrail vrouter agent info from analyticsdb '''
+
+ vr_agent_status = contrail_collector_agent_status(vr_name)
+ vr_info = {}
+ for conf in filter_map:
+ vr_info[conf] = {}
+ for el_path in filter_map[conf]:
+ vr_info = _deepmerge(vr_info, { conf: _get_object(vr_agent_status[conf], el_path) } )
+
+ return vr_info
+
+
def libvirt_capabilities():
''' JSON formatted libvirtcapabilities list '''