icinga2 0.5.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,140 @@
1
+ #!/usr/bin/ruby
2
+ #
3
+ #
4
+ #
5
+ #
6
+
7
+ require 'rest-client'
8
+ require 'openssl'
9
+
10
+ require 'json'
11
+ require 'net/http'
12
+ require 'uri'
13
+
14
+ require_relative 'logging'
15
+ require_relative 'icinga2/version'
16
+ require_relative 'icinga2/network'
17
+ require_relative 'icinga2/status'
18
+ require_relative 'icinga2/converts'
19
+ require_relative 'icinga2/tools'
20
+ require_relative 'icinga2/downtimes'
21
+ require_relative 'icinga2/notifications'
22
+ require_relative 'icinga2/hosts'
23
+ require_relative 'icinga2/hostgroups'
24
+ require_relative 'icinga2/services'
25
+ require_relative 'icinga2/servicegroups'
26
+ require_relative 'icinga2/users'
27
+ require_relative 'icinga2/usergroups'
28
+
29
+ # -------------------------------------------------------------------------------------------------------------------
30
+
31
+ module Icinga2
32
+
33
+ class Client
34
+
35
+ include Logging
36
+
37
+ include Icinga2::Version
38
+ include Icinga2::Network
39
+ include Icinga2::Status
40
+ include Icinga2::Converts
41
+ include Icinga2::Tools
42
+ include Icinga2::Downtimes
43
+ include Icinga2::Notifications
44
+ include Icinga2::Hosts
45
+ include Icinga2::Hostgroups
46
+ include Icinga2::Services
47
+ include Icinga2::Servicegroups
48
+ include Icinga2::Users
49
+ include Icinga2::Usergroups
50
+
51
+
52
+ def initialize( settings = {} )
53
+
54
+ @icingaHost = settings.dig(:icinga, :host) || 'localhost'
55
+ @icingaApiPort = settings.dig(:icinga, :api, :port) || 5665
56
+ @icingaApiUser = settings.dig(:icinga, :api, :user)
57
+ @icingaApiPass = settings.dig(:icinga, :api, :password)
58
+ @icingaCluster = settings.dig(:icinga, :cluster) || false
59
+ @icingaSatellite = settings.dig(:icinga, :satellite)
60
+ @icingaNotifications = settings.dig(:icinga, :notifications) || false
61
+
62
+ @icingaApiUrlBase = sprintf( 'https://%s:%d', @icingaHost, @icingaApiPort )
63
+ @nodeName = Socket.gethostbyname( Socket.gethostname ).first
64
+
65
+ date = '2017-06-08'
66
+
67
+ logger.info( '-----------------------------------------------------------------' )
68
+ logger.info( ' Icinga2 Management' )
69
+ logger.info( " Version #{VERSION} (#{date})" )
70
+ logger.info( ' Copyright 2016-2017 Bodo Schulz' )
71
+ logger.info( " Backendsystem #{@icingaApiUrlBase}" )
72
+ logger.info( sprintf( ' cluster enabled: %s', @icingaCluster ? 'true' : 'false' ) )
73
+ logger.info( sprintf( ' notifications enabled: %s', @icingaNotifications ? 'true' : 'false' ) )
74
+ if( @icingaCluster )
75
+ logger.info( sprintf( ' satellite endpoint: %s', @icingaSatellite ) )
76
+ end
77
+ logger.info( '-----------------------------------------------------------------' )
78
+ logger.info( '' )
79
+
80
+ logger.debug( sprintf( ' server : %s', @icingaHost ) )
81
+ logger.debug( sprintf( ' port : %s', @icingaApiPort ) )
82
+ logger.debug( sprintf( ' api url : %s', @icingaApiUrlBase ) )
83
+ logger.debug( sprintf( ' api user : %s', @icingaApiUser ) )
84
+ logger.debug( sprintf( ' api pass : %s', @icingaApiPass ) )
85
+ logger.debug( sprintf( ' node name: %s', @nodeName ) )
86
+
87
+ @hasCert = self.checkCert( { :user => @icingaApiUser, :password => @icingaApiPass } )
88
+ @headers = { "Content-Type" => "application/json", "Accept" => "application/json" }
89
+
90
+ return self
91
+
92
+ end
93
+
94
+
95
+ def checkCert( params = {} )
96
+
97
+ nodeName = params.dig(:nodeName) || 'localhost'
98
+
99
+ user = params.dig(:user) || 'admin'
100
+ password = params.dig(:password) || ''
101
+
102
+ # check whether pki files are there, otherwise use basic auth
103
+ if File.file?( sprintf( 'pki/%s.crt', nodeName ) )
104
+
105
+ logger.debug( "PKI found, using client certificates for connection to Icinga 2 API" )
106
+
107
+ sslCertFile = File.read( sprintf( 'pki/%s.crt', nodeName ) )
108
+ sslKeyFile = File.read( sprintf( 'pki/%s.key', nodeName ) )
109
+ sslCAFile = File.read( 'pki/ca.crt' )
110
+
111
+ cert = OpenSSL::X509::Certificate.new( sslCertFile )
112
+ key = OpenSSL::PKey::RSA.new( sslKeyFile )
113
+
114
+ @options = {
115
+ :ssl_client_cert => cert,
116
+ :ssl_client_key => key,
117
+ :ssl_ca_file => sslCAFile,
118
+ :verify_ssl => OpenSSL::SSL::VERIFY_NONE
119
+ }
120
+
121
+ return true
122
+ else
123
+
124
+ logger.debug( "PKI not found, using basic auth for connection to Icinga 2 API" )
125
+
126
+ @options = {
127
+ :user => user,
128
+ :password => password,
129
+ :verify_ssl => OpenSSL::SSL::VERIFY_NONE
130
+ }
131
+
132
+ return false
133
+ end
134
+
135
+ end
136
+
137
+ end
138
+ end
139
+
140
+ # EOF
@@ -0,0 +1,77 @@
1
+
2
+
3
+ module Icinga2
4
+
5
+ module Converts
6
+
7
+ def self.stateToString( state, is_host = false )
8
+
9
+ if( is_host == true )
10
+
11
+ state = case state
12
+ when 0
13
+ 'Up'
14
+ when 1
15
+ 'Down'
16
+ else
17
+ 'Undefined'
18
+ end
19
+ else
20
+
21
+ state = case state
22
+ when 0
23
+ 'OK'
24
+ when 1
25
+ 'Warning'
26
+ when 2
27
+ 'Critical'
28
+ when 3
29
+ 'Unknown'
30
+ else
31
+ 'Undefined'
32
+ end
33
+ end
34
+
35
+ return state
36
+
37
+ end
38
+
39
+ def self.stateToColor( state, is_host = false )
40
+
41
+ if( is_host == true )
42
+
43
+ state = case state
44
+ when 0
45
+ 'green'
46
+ when 1
47
+ 'red'
48
+ else
49
+ 'blue'
50
+ end
51
+ else
52
+
53
+ state = case state
54
+ when 0
55
+ 'green'
56
+ when 1
57
+ 'yellow'
58
+ when 2
59
+ 'red'
60
+ when 3
61
+ 'purple'
62
+ else
63
+ 'blue'
64
+ end
65
+ end
66
+
67
+ return state
68
+ end
69
+
70
+ def self.formatService( name )
71
+ service_map = name.split('!', 2)
72
+ service_map.join( ' - ' )
73
+ end
74
+
75
+ end
76
+
77
+ end
@@ -0,0 +1,173 @@
1
+
2
+ module Icinga2
3
+
4
+ module Downtimes
5
+
6
+
7
+ def addDowntime( params = {} )
8
+
9
+ name = params.dig(:name)
10
+ hostName = params.dig(:host)
11
+ # serviceName = params.dig(:service)
12
+ hostGroup = params.dig(:host_group)
13
+ startTime = params.dig(:start_time) || Time.now.to_i
14
+ endTime = params.dig(:end_time)
15
+ author = params.dig(:author)
16
+ comment = params.dig(:comment)
17
+ type = params.dig(:type)
18
+ filter = nil
19
+
20
+ # sanitychecks
21
+ #
22
+ if( name == nil )
23
+
24
+ return {
25
+ :status => 404,
26
+ :message => 'missing downtime name'
27
+ }
28
+ end
29
+
30
+ if( ['host','service'].include?(type.downcase) == false )
31
+
32
+ return {
33
+ :status => 404,
34
+ :message => "wrong downtype type. only 'host' or' service' allowed ('#{type}' giving"
35
+ }
36
+ else
37
+ # we need the first char as Uppercase
38
+ type.capitalize!
39
+ end
40
+
41
+ if( hostGroup != nil && hostName != nil )
42
+
43
+ return {
44
+ :status => 404,
45
+ :message => 'choose host or host_group, not both'
46
+ }
47
+
48
+ end
49
+
50
+ if( hostName != nil )
51
+
52
+ filter = sprintf( 'host.name=="%s"', hostName )
53
+ elsif( hostGroup != nil )
54
+
55
+ # check if hostgroup available ?
56
+ #
57
+ filter = sprintf( '"%s" in host.groups', hostGroup )
58
+ else
59
+
60
+ return {
61
+ :status => 404,
62
+ :message => 'missing host or host_group for downtime'
63
+ }
64
+ end
65
+
66
+ if( comment == nil )
67
+
68
+ return {
69
+ :status => 404,
70
+ :message => 'missing downtime comment'
71
+ }
72
+ end
73
+
74
+ if( author == nil )
75
+
76
+ return {
77
+ :status => 404,
78
+ :message => 'missing downtime author'
79
+ }
80
+ else
81
+
82
+ if( self.existsUser?( author ) == false )
83
+
84
+ return {
85
+ :status => 404,
86
+ :message => "these author ar not exists: #{author}"
87
+ }
88
+ end
89
+ end
90
+
91
+
92
+ if( endTime == nil )
93
+
94
+ return {
95
+ :status => 404,
96
+ :message => 'missing end_time'
97
+ }
98
+ else
99
+
100
+ if( endTime.to_i <= startTime )
101
+
102
+ return {
103
+ :status => 404,
104
+ :message => 'end_time are equal or smaller then start_time'
105
+ }
106
+ end
107
+ end
108
+
109
+ # logger.debug( Time.at( startTime ).strftime( '%Y-%m-%d %H:%M:%S' ) )
110
+ # logger.debug( Time.at( endTime ).strftime( '%Y-%m-%d %H:%M:%S' ) )
111
+
112
+ payload = {
113
+ "type" => type,
114
+ "start_time" => startTime,
115
+ "end_time" => endTime,
116
+ "author" => author,
117
+ "comment" => comment,
118
+ "fixed" => true,
119
+ "duration" => 30,
120
+ "filter" => filter
121
+ }
122
+
123
+ # logger.debug( JSON.pretty_generate( payload ) )
124
+
125
+ result = Network.post( {
126
+ :host => name,
127
+ :url => sprintf( '%s/v1/actions/schedule-downtime', @icingaApiUrlBase ),
128
+ :headers => @headers,
129
+ :options => @options,
130
+ :payload => payload
131
+ } )
132
+
133
+ logger.debug( result.class.to_s )
134
+
135
+ return JSON.pretty_generate( result )
136
+
137
+
138
+ # schedule downtime for a host
139
+ # --data '{ "type": "Host", "filter": "host.name==\"api_dummy_host_1\"", ... }'
140
+
141
+ # schedule downtime for all services of a host
142
+ # --data '{ "type": "Service", "filter": "host.name==\"api_dummy_host_1\"", ... }'
143
+
144
+ # schedule downtime for all hosts and services in a hostgroup
145
+ # --data '{ "type": "Host", "filter": "\"api_dummy_hostgroup\" in host.groups", ... }'
146
+
147
+ # --data '{ "type": "Service", "filter": "\"api_dummy_hostgroup\" in host.groups)", ... }'
148
+
149
+
150
+
151
+ end
152
+
153
+
154
+ def listDowntimes( params = {} )
155
+
156
+ name = params.dig(:name)
157
+
158
+ result = Network.get( {
159
+ :host => name,
160
+ :url => sprintf( '%s/v1/objects/downtimes/%s', @icingaApiUrlBase, name ),
161
+ :headers => @headers,
162
+ :options => @options
163
+ } )
164
+
165
+ return JSON.pretty_generate( result )
166
+
167
+
168
+ end
169
+
170
+
171
+ end
172
+
173
+ end
@@ -0,0 +1,98 @@
1
+
2
+ module Icinga2
3
+
4
+ module Hostgroups
5
+
6
+ def addHostgroup( params = {} )
7
+
8
+ name = params.dig(:name)
9
+ displayName = params.dig(:display_name)
10
+
11
+ if( name == nil )
12
+
13
+ return {
14
+ :status => 404,
15
+ :message => 'no name for the hostgroup'
16
+ }
17
+ end
18
+
19
+ payload = {
20
+ "attrs" => {
21
+ "display_name" => displayName
22
+ }
23
+ }
24
+
25
+ result = Network.put( {
26
+ :url => sprintf( '%s/v1/objects/hostgroups/%s', @icingaApiUrlBase, name ),
27
+ :headers => @headers,
28
+ :options => @options,
29
+ :payload => payload
30
+ } )
31
+
32
+ return JSON.pretty_generate( result )
33
+
34
+ end
35
+
36
+
37
+ def deleteHostgroup( params = {} )
38
+
39
+ name = params.dig(:name)
40
+
41
+ if( name == nil )
42
+
43
+ return {
44
+ :status => 404,
45
+ :message => 'no name for the hostgroup'
46
+ }
47
+ end
48
+
49
+ result = Network.delete( {
50
+ :host => name,
51
+ :url => sprintf( '%s/v1/objects/hostgroups/%s?cascade=1', @icingaApiUrlBase, name ),
52
+ :headers => @headers,
53
+ :options => @options
54
+ } )
55
+
56
+ return JSON.pretty_generate( result )
57
+
58
+ end
59
+
60
+
61
+ def listHostgroups( params = {} )
62
+
63
+ name = params.dig(:name)
64
+
65
+ result = Network.get( {
66
+ :host => name,
67
+ :url => sprintf( '%s/v1/objects/hostgroups/%s', @icingaApiUrlBase, name ),
68
+ :headers => @headers,
69
+ :options => @options
70
+ } )
71
+
72
+ return JSON.pretty_generate( result )
73
+
74
+ end
75
+
76
+
77
+ def existsHostgroup?( name )
78
+
79
+ result = self.listHostgroups( { :name => name } )
80
+
81
+ if( result.is_a?( String ) )
82
+ result = JSON.parse( result )
83
+ end
84
+
85
+ status = result.dig('status')
86
+
87
+ if( status != nil && status == 200 )
88
+ return true
89
+ end
90
+
91
+ return false
92
+
93
+ end
94
+
95
+
96
+ end
97
+
98
+ end