Add Contrail Python modules
Now using normalized attributes names
diff --git a/collectd/files/plugin/collectd_contrail_apis.py b/collectd/files/plugin/collectd_contrail_apis.py
new file mode 100644
index 0000000..0125a22
--- /dev/null
+++ b/collectd/files/plugin/collectd_contrail_apis.py
@@ -0,0 +1,134 @@
+#!/usr/bin/python
+#
+# Copyright 2016 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 collectd
+import requests
+import xml.dom.minidom
+import xml
+
+import collectd_base as base
+
+
+NAME = 'contrail'
+# Default sampling interval
+INTERVAL = 60
+
+
+def check_state(item, state):
+ return item.getElementsByTagName(
+ "state")[0].childNodes[0].toxml() == state
+
+
+class ContrailApiPlugin(base.Base):
+
+ def __init__(self, *args, **kwargs):
+ super(ContrailApiPlugin, self).__init__(*args, **kwargs)
+ self.plugin = NAME
+ self.session = requests.Session()
+ self.session.mount(
+ 'http://',
+ requests.adapters.HTTPAdapter(max_retries=self.max_retries)
+ )
+ self.session.mount(
+ 'https://',
+ requests.adapters.HTTPAdapter(max_retries=self.max_retries)
+ )
+ self.urls = {}
+ self.xml_element = {}
+ self.result_type = {}
+ self.state = {}
+
+ def config_callback(self, config):
+ super(ContrailApiPlugin, self).config_callback(config)
+ for node in config.children:
+ self.logger.debug("Got config request for '{}': {} {}".format(
+ node.key.lower(), node.values[0], node.values[1])
+ )
+ if node.key.lower() == "url":
+ self.urls[node.values[0]] = node.values[1]
+ elif node.key.lower() == 'xml_element':
+ self.xml_element[node.values[0]] = node.values[1]
+ elif node.key.lower() == 'result_type':
+ self.result_type[node.values[0]] = node.values[1]
+ elif node.key.lower() == 'state':
+ self.state[node.values[0]] = node.values[1]
+
+ def itermetrics(self):
+ for name, url in self.urls.items():
+ self.logger.debug("Requesting {} URL {}".format(
+ name, url)
+ )
+ try:
+ r = self.session.get(url, timeout=self.timeout)
+ except Exception as e:
+ msg = "Got exception for '{}': {}".format(name, e)
+ raise base.CheckException(msg)
+ else:
+ if r.status_code != 200:
+ self.logger.error(
+ ("{} ({}) responded with code {} "
+ "").format(name, url,
+ r.status_code))
+ yield {'type_instance': name, 'values': self.FAIL}
+ else:
+ try:
+ self.logger.debug(
+ "Got response from {}: '{}'"
+ "".format(url, r.text))
+ px = xml.dom.minidom.parseString(r.text)
+ itemlist = px.getElementsByTagName(
+ self.xml_element[name]
+ )
+ if name not in self.result_type:
+ count = 0
+ state = self.state.get('name')
+ for i in itemlist:
+ if state is None or check_state(i, state):
+ count = count + 1
+ self.logger.debug(
+ "Got count for {}: '{}'".format(name, count))
+ yield {'type_instance': name, 'values': count}
+ else:
+ rval = itemlist[0].getElementsByTagName(
+ self.result_type[name]
+ )[0].childNodes[0].toxml()
+ self.logger.debug(
+ "Got val for {}: '{}'".format(name, rval))
+ yield {'type_instance': name, 'values': rval}
+ except Exception as e:
+ msg = ("Got exception while parsing "
+ "response for '{}': {}").format(name, e)
+ raise base.CheckException(msg)
+
+
+plugin = ContrailApiPlugin(collectd)
+
+
+def config_callback(conf):
+ plugin.config_callback(conf)
+
+
+def notification_callback(notification):
+ plugin.notification_callback(notification)
+
+
+def read_callback():
+ plugin.conditional_read_callback()
+
+collectd.register_config(config_callback)
+collectd.register_notification(notification_callback)
+collectd.register_read(read_callback, INTERVAL)
diff --git a/collectd/files/plugin/contrail_ifmap_elements_count.py b/collectd/files/plugin/contrail_ifmap_elements_count.py
new file mode 100644
index 0000000..a9831d2
--- /dev/null
+++ b/collectd/files/plugin/contrail_ifmap_elements_count.py
@@ -0,0 +1,79 @@
+#!/usr/bin/python
+#
+# Copyright 2016 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 time
+import signal
+import string
+import subprocess
+import sys
+
+plugin_name = "contrail"
+plugin_instance = "ifmap-elements-count"
+plugin_interval = 90
+plugin_type = 'gauge'
+
+command = "/usr/bin/ifmap-view visual visual 2>&1 | wc -l"
+
+
+def restore_sigchld():
+ signal.signal(signal.SIGCHLD, signal.SIG_DFL)
+
+
+def log_verbose(msg):
+ collectd.info('%s plugin [verbose]: %s' % (plugin_name, msg))
+
+
+def payload():
+ ifmap_view_number_of_elements = subprocess.check_output(
+ command, shell=True)
+ return ifmap_view_number_of_elements
+
+
+def configure_callback(conf):
+ for node in conf.children:
+ val = str(node.values[0])
+
+
+def payload_callback():
+ value = payload()
+ # log_verbose(
+ # 'Sending value: %s.%s=%s' % (
+ # plugin_name, '-'.join([val.plugin, val.type]), value))
+ val = collectd.Values(
+ plugin=plugin_name, # metric source
+ plugin_instance=plugin_instance,
+ type=plugin_type,
+ type_instance=plugin_name,
+ interval=plugin_interval,
+ meta={'0': True},
+ values=[value]
+ )
+
+ val.dispatch()
+
+
+if __name__ == '__main__':
+ print "Plugin: " + plugin_name
+ payload = payload()
+ print("%s" % (payload))
+ sys.exit(0)
+else:
+ import collectd
+
+ collectd.register_init(restore_sigchld)
+ collectd.register_config(configure_callback)
+ collectd.register_read(payload_callback, plugin_interval)