-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmk-inv.py
210 lines (170 loc) · 6.91 KB
/
mk-inv.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# (c) 2015, Ravi Bhure <ravibhure@gmail.com>
#
# This file is not a part of Ansible,but is forked from a file that is.
# As such, it falls under the GNU General Public license of the parent file.
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
######################################################################
# Changes by Patrick Gavin
#
# 10/25/2017
# Added hostgroups option to allow ansible inventory grouping based on
# check_mk hostgroups.
#
# 6/3/2022
# Adding socketurl argument to query livestatus on remote servers
# and get rid of the .ini file.
#
# 6/13/2022
# Added basic SSL support- cert checking is off. Nothing fancypants.
#
# 6/20/2022
# Switched to socketurls nargs argument to allow multiple queries to
# livestatus servers and aggregating the results.
#
"""
Check_MK / OMD Server external inventory script.
================================================
Returns hosts and hostgroups from Check_MK / OMD Server using LQL to livestatus socket.
Tested with Check_MK
For more details, see: https://mathias-kettner.de/checkmk_livestatus.html
"""
import os,sys
import socket
import ssl
import argparse
try:
import json
except:
import simplejson as json
def do_connect(socketurl):
""" Initialize socket connection """
url = socketurl
parts = url.split(":")
if parts[0] == "unix":
if len(parts) != 2:
raise Exception("Invalid livestatus unix url: %s. "
"Correct example is 'unix:/var/run/nagios/rw/live'" % url)
clearSocket = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM)
target = parts[1]
elif parts[0] == "tcp" or parts[0] == "ssl":
try:
host = parts[1]
port = int(parts[2])
except:
raise Exception("Invalid livestatus tcp url '%s'. "
"Correct example is 'tcp:somehost:6557'" % url)
clearSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
target = (host, port)
else:
raise Exception("Invalid livestatus url '%s'. "
"Must begin with 'tcp:', 'ssl:', or 'unix:'" % url)
# If using ssl, wrap the clear socket with an ssl socket
if (parts[0] == "ssl"):
context = ssl.create_default_context()
context.check_hostname = False
context.verify_mode = ssl.CERT_NONE
sslSocket = context.wrap_socket(clearSocket)
useSocket = sslSocket
else:
useSocket = clearSocket
# Create connection
try:
useSocket.connect(target)
except Exception, e:
print >>sys.stderr, 'Error while connecting to socket on %s - %s' % (target,e)
sys.exit(1)
# Return the connected socket
return useSocket
def inventory_data(socketurl, query):
""" Generate inventory data """
s = do_connect(socketurl)
s.send(query)
answer = ''
read_buff = s.recv(4096)
while (read_buff != ""):
answer += read_buff
read_buff = s.recv(4096)
s.close()
table = answer.split('\n')[:-1]
return table
def print_table(table, table_name='hosts'):
print json.dumps({table_name: table}, sort_keys=True, indent=2)
def print_list(socketurls, fields):
""" Returns all host """
master_table = []
for socketurl in socketurls:
query = "GET hosts \nColumns: %s \n\n" % fields
master_table += inventory_data(socketurl, query)
print_table(master_table)
def print_host(socketurls, host, fields):
""" Returns a host """
master_table = []
for socketurl in socketurls:
query = "GET hosts \nColumns: %s \nFilter: host_name = %s\n\n" % (fields, host)
master_table += inventory_data(socketurl, query)
print_table(master_table)
def print_group(socketurls, hostgroup, fields, extra_filter):
""" Returns a list of all hosts in given hostgroup """
master_table = []
for socketurl in socketurls:
query = "GET hosts \nColumns: %s \nFilter: host_groups >= %s\n%s\n\n" % (fields, hostgroup, extra_filter)
master_table += inventory_data(socketurl, query)
print_table(master_table)
def print_all_hostgroups(socketurls, fields, extra_filter):
""" Prints a list of all defined hostgroups and the hosts in them"""
collection = {}
for socketurl in socketurls:
query = "GET hostgroups \nColumns: name \n\n"
hostgroups = inventory_data(socketurl, query)
for hostgroup in hostgroups:
query = "GET hosts \nColumns: %s \nFilter: host_groups >= %s\n%s\n\n" % (fields, hostgroup, extra_filter)
if hostgroup in collection:
collection[hostgroup] += (inventory_data(socketurl, query))
else:
collection[hostgroup] = (inventory_data(socketurl, query))
print json.dumps(collection, sort_keys=True, indent=2)
def get_args(args_list):
parser = argparse.ArgumentParser(
description='ansible inventory script reading from check_mk / omd monitoring')
mutex_group = parser.add_mutually_exclusive_group(required=True)
help_list = 'list all hosts from check_mk / omd server'
mutex_group.add_argument('--list', action='store_true', help=help_list)
mutex_group.add_argument('--host', help='display variables for a host')
help_hostgroup = 'display variables for a hostgroup'
mutex_group.add_argument('--hostgroup', help=help_hostgroup)
mutex_group.add_argument('--hostgroups', action='store_true', help='List all hostgroups and the hosts in them')
parser.add_argument('--fields', default='host_name', help='Space delimited list of fields to return')
parser.add_argument('--filtergroup', help='Additional group filter like dev_servers or prd_servers')
parser.add_argument('socketurls', nargs='+', help='socket URLs i.e. tcp:mk.foobar.com:6557 or ssl:mk.foobar.com:6557')
return parser.parse_args(args_list)
def main(args_list):
args = get_args(args_list)
if args.filtergroup:
add_filter = "Filter: host_groups >= %s\n" % args.filtergroup
else:
add_filter = ''
if args.list:
print_list(args.socketurls, args.fields)
if args.host:
print_host(args.socketurls, args.host, args.fields)
if args.hostgroup:
print_group(args.socketurls, args.hostgroup, args.fields, add_filter)
if args.hostgroups:
print_all_hostgroups(args.socketurls, args.fields, add_filter)
if __name__ == '__main__':
main(sys.argv[1:])