icinga2 0.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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