From 3b4383696f7f6892c20fb3547d444e948d64139d Mon Sep 17 00:00:00 2001 From: Lars Kruse Date: Fri, 24 Aug 2018 20:29:48 +0200 Subject: [PATCH 1/6] Plugin bitcoind_: reformat documentation header --- plugins/currency/bitcoin/bitcoind_ | 83 +++++++++++++++++------------- 1 file changed, 48 insertions(+), 35 deletions(-) diff --git a/plugins/currency/bitcoin/bitcoind_ b/plugins/currency/bitcoin/bitcoind_ index 5b5408dd..7e2b7f0d 100755 --- a/plugins/currency/bitcoin/bitcoind_ +++ b/plugins/currency/bitcoin/bitcoind_ @@ -1,39 +1,52 @@ #!/usr/bin/env python -# bitcoind_ Munin plugin for Bitcoin Server Variables -# -# by Mike Koss -# Feb 14, 2012, MIT License -# -# You need to be able to authenticate to the bitcoind server to issue rpc's. -# This plugin supporst 2 ways to do that: -# -# 1) In /etc/munin/plugin-conf.d/bitcoin.conf place: -# -# [bitcoind_*] -# user your-username -# -# Then be sure your $HOME/.bitcoin/bitcoin.conf has the correct authentication info: -# rpcconnect, rpcport, rpcuser, rpcpassword -# -# 2) Place your bitcoind authentication directly in /etc/munin/plugin-conf.d/bitcoin.conf -# -# [bitcoind_*] -# env.rpcport 8332 -# env.rpcconnect 127.0.0.1 -# env.rpcuser your-username-here -# env.rpcpassword your-password-here -# -# To install all available graphs: -# -# sudo munin-node-configure --libdir=. --suggest --shell | sudo bash -# -# Leave out the "| bash" to get a list of commands you can select from to install -# individual graphs. -# -# Munin plugin tags: -# -#%# family=auto -#%# capabilities=autoconf suggest + +"""=cut +=head1 NAME + + bitcoind_ - Track Bitcoin Server Variables + +=head1 CONFIGURATION + +You need to be able to authenticate to the bitcoind server to issue rpc's. +This plugin supports two ways to do that: + +1) In /etc/munin/plugin-conf.d/bitcoin.conf place: + + [bitcoind_*] + user your-username + + Then be sure your $HOME/.bitcoin/bitcoin.conf has the correct authentication info: + rpcconnect, rpcport, rpcuser, rpcpassword + +2) Place your bitcoind authentication directly in /etc/munin/plugin-conf.d/bitcoin.conf + + [bitcoind_*] + env.rpcport 8332 + env.rpcconnect 127.0.0.1 + env.rpcuser your-username-here + env.rpcpassword your-password-here + +To install all available graphs: + + sudo munin-node-configure --libdir=. --suggest --shell | sudo bash + +Leave out the "| bash" to get a list of commands you can select from to install +individual graphs. + +=head1 MAGIC MARKERS + + #%# family=auto + #%# capabilities=autoconf suggest + +=head1 LICENSE + +MIT License + +=head1 AUTHOR + +Copyright (C) 2012 Mike Koss + +=cut""" import os import sys From fffb536e26adeadc3b019035353c45fa1ce49089 Mon Sep 17 00:00:00 2001 From: Lars Kruse Date: Fri, 24 Aug 2018 20:31:14 +0200 Subject: [PATCH 2/6] Plugin bitcoind_: fix flake8 and python3 issues --- plugins/currency/bitcoin/bitcoind_ | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/plugins/currency/bitcoin/bitcoind_ b/plugins/currency/bitcoin/bitcoind_ index 7e2b7f0d..369fbc63 100755 --- a/plugins/currency/bitcoin/bitcoind_ +++ b/plugins/currency/bitcoin/bitcoind_ @@ -79,15 +79,15 @@ def main(): if command == 'suggest': for var_name in request_labels.keys(): - print var_name + print(var_name) return if command == 'config': - print 'graph_category htc' - print 'graph_title Bitcoin %s' % labels[0] - print 'graph_vlabel %s' % labels[1] + print('graph_category htc') + print('graph_title Bitcoin %s' % labels[0]) + print('graph_vlabel %s' % labels[1]) for label in line_labels: - print '%s.label %s' % (label, label) + print('%s.label %s' % (label, label)) return # Munin should send connection options via environment vars @@ -110,7 +110,7 @@ def main(): if error: if command == 'autoconf': - print 'no' + print('no') return else: # TODO: Better way to report errors to Munin-node. @@ -128,11 +128,11 @@ def main(): info['waiting'] = len(memory_pool) if command == 'autoconf': - print 'yes' + print('yes') return for label in line_labels: - print "%s.value %s" % (label, info[label]) + print("%s.value %s" % (label, info[label])) def parse_conf(filename): @@ -151,7 +151,8 @@ def parse_conf(filename): continue (var, value) = (m.group(1), m.group(2).strip()) options[var] = value - except: + except OSError: + # the config file may be missing pass return options @@ -212,9 +213,9 @@ class Proxy(object): def __call__(self, *args): if DEBUG: arg_strings = [json.dumps(arg) for arg in args] - print "Calling %s(%s) @ %s" % (self.method, + print("Calling %s(%s) @ %s" % (self.method, ', '.join(arg_strings), - self.service.url) + self.service.url)) data = { 'method': self.method, @@ -229,15 +230,15 @@ class Proxy(object): try: body = urllib2.urlopen(request).read() - except Exception, e: + except urllib2.URLError as e: return (None, e) if DEBUG: - print 'RPC Response (%s): %s' % (self.method, json.dumps(body, indent=4)) + print('RPC Response (%s): %s' % (self.method, json.dumps(body, indent=4))) try: data = json.loads(body) - except ValueError, e: + except ValueError as e: return (None, e.message) # TODO: Check that id matches? return (data['result'], data['error']) From bc20826c4e7dd9d88d8c7db85a11433d5364a0a7 Mon Sep 17 00:00:00 2001 From: Lars Kruse Date: Fri, 24 Aug 2018 20:37:57 +0200 Subject: [PATCH 3/6] Plugin bitcoind_: switch to Python3 --- plugins/currency/bitcoin/bitcoind_ | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/plugins/currency/bitcoin/bitcoind_ b/plugins/currency/bitcoin/bitcoind_ index 369fbc63..48de665c 100755 --- a/plugins/currency/bitcoin/bitcoind_ +++ b/plugins/currency/bitcoin/bitcoind_ @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 """=cut =head1 NAME @@ -48,12 +48,13 @@ Copyright (C) 2012 Mike Koss =cut""" +import json import os +import re import sys import time -import re -import urllib2 -import json +import urllib.error +import urllib.request DEBUG = False @@ -222,15 +223,15 @@ class Proxy(object): 'params': args, 'id': self.id, } - request = urllib2.Request(self.service.url, json.dumps(data)) + request = urllib.request.Request(self.service.url, json.dumps(data)) if self.service.username: # Strip the newline from the b64 encoding! b64 = ('%s:%s' % (self.service.username, self.service.password)).encode('base64')[:-1] request.add_header('Authorization', 'Basic %s' % b64) try: - body = urllib2.urlopen(request).read() - except urllib2.URLError as e: + body = urllib.request.urlopen(request).read() + except urllib.error.URLError as e: return (None, e) if DEBUG: @@ -245,8 +246,8 @@ class Proxy(object): def get_json_url(url): - request = urllib2.Request(url) - body = urllib2.urlopen(request).read() + request = urllib.request.Request(url) + body = urllib.request.urlopen(request).read() data = json.loads(body) return data From 675f1f696290fc7e2199eb155f67626a2b4aa2a1 Mon Sep 17 00:00:00 2001 From: Lars Kruse Date: Fri, 24 Aug 2018 20:45:46 +0200 Subject: [PATCH 4/6] Plugin bitcoind_: retrieve debug state from environment --- plugins/currency/bitcoin/bitcoind_ | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/currency/bitcoin/bitcoind_ b/plugins/currency/bitcoin/bitcoind_ index 48de665c..5d110479 100755 --- a/plugins/currency/bitcoin/bitcoind_ +++ b/plugins/currency/bitcoin/bitcoind_ @@ -57,7 +57,7 @@ import urllib.error import urllib.request -DEBUG = False +DEBUG = os.getenv('MUNIN_DEBUG') == '1' def main(): From 0a090e5be5daaf94a10871239679f8e1f76b0026 Mon Sep 17 00:00:00 2001 From: Lars Kruse Date: Fri, 24 Aug 2018 21:52:11 +0200 Subject: [PATCH 5/6] Plugin bitcoind_: improved error output --- plugins/currency/bitcoin/bitcoind_ | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/plugins/currency/bitcoin/bitcoind_ b/plugins/currency/bitcoin/bitcoind_ index 5d110479..142382ce 100755 --- a/plugins/currency/bitcoin/bitcoind_ +++ b/plugins/currency/bitcoin/bitcoind_ @@ -115,7 +115,8 @@ def main(): return else: # TODO: Better way to report errors to Munin-node. - raise ValueError("Could not connect to Bitcoin server.") + print("Could not connect to Bitcoin server.", file=sys.stderr) + sys.exit(1) if request_var in ('transactions', 'block_age'): (info, error) = bitcoin.getblockhash(info['blocks']) @@ -180,9 +181,9 @@ class Options(dict): if self.get(name) is None: missing.append(name) if len(missing) > 0: - raise ValueError("Missing required setting%s: %s." % - ('s' if len(missing) > 1 else '', - ', '.join(missing))) + print("Missing required setting%s: %s." + % ('s' if len(missing) > 1 else '', ', '.join(missing)), file=sys.stderr) + sys.exit(1) class ServiceProxy(object): From abdeb7ec6500b14bd833f8afbd262a9d24bc16d8 Mon Sep 17 00:00:00 2001 From: Lars Kruse Date: Fri, 24 Aug 2018 21:52:34 +0200 Subject: [PATCH 6/6] Plugin bitcoind_: introduce explicit configuration file path The home directory of the currently effective UID cannot be easily inferred in python via os.path.expanduser. Since there is no other simple way for reaching this goal, an explicit environemnt setting is introduced. --- plugins/currency/bitcoin/bitcoind_ | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/plugins/currency/bitcoin/bitcoind_ b/plugins/currency/bitcoin/bitcoind_ index 142382ce..293b72cc 100755 --- a/plugins/currency/bitcoin/bitcoind_ +++ b/plugins/currency/bitcoin/bitcoind_ @@ -14,8 +14,10 @@ This plugin supports two ways to do that: [bitcoind_*] user your-username + env.bitcoin_configfile /home/your-username/.bitcoin/bitcoin.conf - Then be sure your $HOME/.bitcoin/bitcoin.conf has the correct authentication info: + Then be sure that the file referenced above (typically: $HOME/.bitcoin/bitcoin.conf) + has the correct authentication info: rpcconnect, rpcport, rpcuser, rpcpassword 2) Place your bitcoind authentication directly in /etc/munin/plugin-conf.d/bitcoin.conf @@ -97,8 +99,16 @@ def main(): bitcoin_options.rpcport = bitcoin_options.get('rpcport', '8332') if bitcoin_options.get('rpcuser') is None: - conf_file = os.path.join(os.path.expanduser('~/.bitcoin'), 'bitcoin.conf') - bitcoin_options = parse_conf(conf_file) + conf_file = os.getenv("bitcoin_configfile") + if not conf_file: + print("Missing environment settings (rpcuser/rcpassword or bitcoin_configfile)", + file=sys.stderr) + sys.exit(1) + elif not os.path.exists(conf_file): + print("Configuration file does not exist: {}".format(conf_file), file=sys.stderr) + sys.exit(1) + else: + bitcoin_options = parse_conf(conf_file) bitcoin_options.require('rpcuser', 'rpcpassword')