@cryptotaxi247 / netdata-1 / commits / cda9a8ed2

move ExecutableService to a separate file

lgz committed Oct 13, 2017 at 00:14 UTC cda9a8ed2aad51ed6cedf8284cf6679d10c2d7fe
1 file changed +82
python.d/python_modules/bases/FrameworkServices/ExecutableService.py new
+82
@@ -0,0 +1,82 @@
1 +# -*- coding: utf-8 -*-
2 +# Description:
3 +# Author: Pawel Krupa (paulfantom)
4 +# Author: Ilya Mashchenko (l2isbad)
5 +
6 +from subprocess import Popen, PIPE
7 +
8 +from bases.FrameworkServices.SimpleService import SimpleService
9 +
10 +
11 +class ExecutableService(SimpleService):
12 + def __init__(self, configuration=None, name=None):
13 + SimpleService.__init__(self, configuration=configuration, name=name)
14 + self.command = None
15 +
16 + def _get_raw_data(self, stderr=False):
17 + """
18 + Get raw data from executed command
19 + :return: <list>
20 + """
21 + try:
22 + p = Popen(self.command, stdout=PIPE, stderr=PIPE)
23 + except Exception as error:
24 + self.error('Executing command {command} resulted in error: {error}'.format(command=self.command,
25 + error=error))
26 + return None
27 + data = list()
28 + std = p.stderr if stderr else p.stdout
29 + for line in std:
30 + data.append(line.decode())
31 +
32 + return data or None
33 +
34 + def check(self):
35 + """
36 + Parse basic configuration, check if command is whitelisted and is returning values
37 + :return: <boolean>
38 + """
39 + # Preference: 1. "command" from configuration file 2. "command" from plugin (if specified)
40 + if 'command' in self.configuration:
41 + self.command = self.configuration['command']
42 +
43 + # "command" must be: 1.not None 2. type <str>
44 + if not (self.command and isinstance(self.command, str)):
45 + self.error('Command is not defined or command type is not <str>')
46 + return False
47 +
48 + # Split "command" into: 1. command <str> 2. options <list>
49 + command, opts = self.command.split()[0], self.command.split()[1:]
50 +
51 + # Check for "bad" symbols in options. No pipes, redirects etc.
52 + opts_list = ['&', '|', ';', '>', '<']
53 + bad_opts = set(''.join(opts)) & set(opts_list)
54 + if bad_opts:
55 + self.error("Bad command argument(s): {opts}".format(opts=bad_opts))
56 + return False
57 +
58 + # Find absolute path ('echo' => '/bin/echo')
59 + if '/' not in command:
60 + command = self.functions.find_binary(command)
61 + if not command:
62 + self.error('Can\'t locate "{command}" binary'.format(command=self.command))
63 + return False
64 + # Check if binary exist and executable
65 + else:
66 + if not (self.functions.is_file_executable(command)):
67 + self.error('"{binary}" is not a file or not executable'.format(binary=command))
68 + return False
69 +
70 + self.command = [command] + opts if opts else [command]
71 +
72 + try:
73 + data = self._get_data()
74 + except Exception as error:
75 + self.error('_get_data() failed. Command: {command}. Error: error'.format(command=self.command,
76 + error=error))
77 + return False
78 +
79 + if isinstance(data, dict) and data:
80 + return True
81 + self.error('Command "{command}" returned no data'.format(command=self.command))
82 + return False