miq_utilities 0.2.2 → 0.2.4
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.
- checksums.yaml +4 -4
- data/.gitignore +11 -0
- data/.rubocop.yml +29 -0
- data/Gemfile +2 -2
- data/Gemfile.lock +3 -28
- data/README.md +11 -12
- data/lib/miq_utilities/chef.rb +112 -0
- data/lib/miq_utilities/general.rb +46 -0
- data/lib/miq_utilities/infoblox.rb +6 -6
- data/lib/miq_utilities/logging.rb +7 -4
- data/lib/miq_utilities/notification.rb +33 -41
- data/lib/miq_utilities/sql.rb +8 -7
- data/lib/miq_utilities/ssh.rb +33 -0
- data/lib/miq_utilities/version.rb +1 -1
- data/lib/miq_utilities/vmware.rb +15 -10
- data/lib/miq_utilities/winrm.rb +5 -5
- data/lib/miq_utilities.rb +4 -0
- data/miq_utilities.gemspec +1 -0
- metadata +20 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 85f2ae04d311c596c5309f1f79bf31a8b407b02e754dc756dabb016c557b4572
|
|
4
|
+
data.tar.gz: 498e1d8d0c3ad8dfa112791d937d99aad1a259e2ce411ba15b00e5823522553c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1a239b30ffc757799835233191fd57c9533838a9a637c0a0a8d9f6d0f2ca804e55132b53ce6496efecb250ec60d52cfaa1b9d5250a3dae8da52b88085dc03594
|
|
7
|
+
data.tar.gz: d95c06245eddba23773ac1164e701c0b5efd3a1975113a973a657ae71f1b222cf43bfc7440b37cfdc138c394186575a68bc2402dd2c64b153c48862780acd3fd
|
data/.gitignore
CHANGED
data/.rubocop.yml
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
AllCops:
|
|
2
|
+
TargetRubyVersion: 2.4
|
|
3
|
+
Exclude:
|
|
4
|
+
- vendor/**/*
|
|
5
|
+
- Guardfile
|
|
6
|
+
|
|
7
|
+
ClassLength:
|
|
8
|
+
Enabled: false
|
|
9
|
+
CyclomaticComplexity:
|
|
10
|
+
Enabled: false
|
|
11
|
+
GlobalVars:
|
|
12
|
+
AllowedVariables:
|
|
13
|
+
- $evm
|
|
14
|
+
LineLength:
|
|
15
|
+
Enabled: false
|
|
16
|
+
MethodLength:
|
|
17
|
+
Enabled: false
|
|
18
|
+
Metrics/AbcSize:
|
|
19
|
+
Enabled: false
|
|
20
|
+
Metrics/LineLength:
|
|
21
|
+
Enabled: false
|
|
22
|
+
Metrics/ModuleLength:
|
|
23
|
+
Enabled: false
|
|
24
|
+
Metrics/PerceivedComplexity:
|
|
25
|
+
Enabled: false
|
|
26
|
+
Metrics/ParameterLists:
|
|
27
|
+
Enabled: false
|
|
28
|
+
Style/RescueStandardError:
|
|
29
|
+
Enabled: false
|
data/Gemfile
CHANGED
|
@@ -4,11 +4,11 @@ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
|
|
|
4
4
|
|
|
5
5
|
# Specify your gem's dependencies in miq_utilities.gemspec
|
|
6
6
|
gemspec
|
|
7
|
-
gem 'slack-
|
|
7
|
+
gem 'slack-notifier'
|
|
8
8
|
gem 'eventmachine'
|
|
9
9
|
gem 'faye-websocket'
|
|
10
10
|
gem 'rbvmomi'
|
|
11
11
|
gem 'tiny_tds'
|
|
12
12
|
gem 'winrm'
|
|
13
13
|
gem 'rest-client'
|
|
14
|
-
gem 'json'
|
|
14
|
+
gem 'json'
|
data/Gemfile.lock
CHANGED
|
@@ -1,41 +1,27 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: .
|
|
3
3
|
specs:
|
|
4
|
-
miq_utilities (0.2.
|
|
4
|
+
miq_utilities (0.2.3)
|
|
5
5
|
|
|
6
6
|
GEM
|
|
7
7
|
remote: https://rubygems.org/
|
|
8
8
|
specs:
|
|
9
|
-
activesupport (5.2.0)
|
|
10
|
-
concurrent-ruby (~> 1.0, >= 1.0.2)
|
|
11
|
-
i18n (>= 0.7, < 2)
|
|
12
|
-
minitest (~> 5.1)
|
|
13
|
-
tzinfo (~> 1.1)
|
|
14
9
|
builder (3.2.3)
|
|
15
|
-
concurrent-ruby (1.0.5)
|
|
16
10
|
domain_name (0.5.20180417)
|
|
17
11
|
unf (>= 0.0.5, < 1.0.0)
|
|
18
12
|
erubis (2.7.0)
|
|
19
13
|
eventmachine (1.2.6-x64-mingw32)
|
|
20
|
-
faraday (0.15.0)
|
|
21
|
-
multipart-post (>= 1.2, < 3)
|
|
22
|
-
faraday_middleware (0.12.2)
|
|
23
|
-
faraday (>= 0.7.4, < 1.0)
|
|
24
14
|
faye-websocket (0.10.7)
|
|
25
15
|
eventmachine (>= 0.12.0)
|
|
26
16
|
websocket-driver (>= 0.5.1)
|
|
27
17
|
ffi (1.9.23-x64-mingw32)
|
|
28
|
-
gli (2.17.1)
|
|
29
18
|
gssapi (1.2.0)
|
|
30
19
|
ffi (>= 1.0.1)
|
|
31
20
|
gyoku (1.3.1)
|
|
32
21
|
builder (>= 2.1.2)
|
|
33
|
-
hashie (3.5.7)
|
|
34
22
|
http-cookie (1.0.3)
|
|
35
23
|
domain_name (~> 0.5)
|
|
36
24
|
httpclient (2.8.3)
|
|
37
|
-
i18n (1.0.1)
|
|
38
|
-
concurrent-ruby (~> 1.0)
|
|
39
25
|
json (2.1.0)
|
|
40
26
|
little-plugger (1.1.4)
|
|
41
27
|
logging (2.2.2)
|
|
@@ -45,9 +31,7 @@ GEM
|
|
|
45
31
|
mime-types-data (~> 3.2015)
|
|
46
32
|
mime-types-data (3.2016.0521)
|
|
47
33
|
mini_portile2 (2.3.0)
|
|
48
|
-
minitest (5.11.3)
|
|
49
34
|
multi_json (1.13.1)
|
|
50
|
-
multipart-post (2.0.0)
|
|
51
35
|
netrc (0.11.0)
|
|
52
36
|
nokogiri (1.8.2-x64-mingw32)
|
|
53
37
|
mini_portile2 (~> 2.3.0)
|
|
@@ -64,18 +48,9 @@ GEM
|
|
|
64
48
|
mime-types (>= 1.16, < 4.0)
|
|
65
49
|
netrc (~> 0.8)
|
|
66
50
|
rubyntlm (0.6.2)
|
|
67
|
-
slack-
|
|
68
|
-
activesupport
|
|
69
|
-
faraday (>= 0.9)
|
|
70
|
-
faraday_middleware
|
|
71
|
-
gli
|
|
72
|
-
hashie
|
|
73
|
-
websocket-driver
|
|
74
|
-
thread_safe (0.3.6)
|
|
51
|
+
slack-notifier (2.3.2)
|
|
75
52
|
tiny_tds (2.1.1-x64-mingw32)
|
|
76
53
|
trollop (2.1.2)
|
|
77
|
-
tzinfo (1.2.5)
|
|
78
|
-
thread_safe (~> 0.1)
|
|
79
54
|
unf (0.1.4)
|
|
80
55
|
unf_ext
|
|
81
56
|
unf_ext (0.0.7.5-x64-mingw32)
|
|
@@ -104,7 +79,7 @@ DEPENDENCIES
|
|
|
104
79
|
rake (~> 10.0)
|
|
105
80
|
rbvmomi
|
|
106
81
|
rest-client
|
|
107
|
-
slack-
|
|
82
|
+
slack-notifier
|
|
108
83
|
tiny_tds
|
|
109
84
|
winrm
|
|
110
85
|
|
data/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
## Installation
|
|
4
4
|
|
|
5
|
-
$
|
|
5
|
+
$ bundle install
|
|
6
6
|
|
|
7
7
|
## Usage
|
|
8
8
|
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
3. rbvmomi ~> 1.11.3
|
|
16
16
|
4. tiny_tds ~> 2.1.0
|
|
17
17
|
5. winrm ~> 2.2.3
|
|
18
|
-
6. slack-
|
|
18
|
+
6. slack-notifier ~> 2.3.2
|
|
19
19
|
7. rest-client ~> 1.8.0 x64-mingw32
|
|
20
20
|
8. json ~> 2.0.4
|
|
21
21
|
|
|
@@ -214,7 +214,7 @@ password ¦ String ¦ The users password
|
|
|
214
214
|
|
|
215
215
|
## Notification (NotificationClass)
|
|
216
216
|
|
|
217
|
-
This Class is used to notify users and log messages accordingly. This Class utilises the
|
|
217
|
+
This Class is used to notify users and log messages accordingly. This Class utilises the slack-notifier Ruby Gem (version => 2.3.2).
|
|
218
218
|
|
|
219
219
|
### Class Method Summary
|
|
220
220
|
|
|
@@ -229,8 +229,8 @@ event_level ¦ String ¦ info, warn, error
|
|
|
229
229
|
event_message ¦ String ¦ The message to be used
|
|
230
230
|
email_to ¦ String ¦ Who to send an email to
|
|
231
231
|
email_from ¦ String ¦ Sent from which email address
|
|
232
|
-
|
|
233
|
-
|
|
232
|
+
signature ¦ String ¦ Who the emails from
|
|
233
|
+
webhookURL ¦ String ¦ The webhook to be used
|
|
234
234
|
```
|
|
235
235
|
|
|
236
236
|
##### Method usage
|
|
@@ -240,7 +240,7 @@ slack_channel ¦ Boolean ¦ The slcak channel to send the message to
|
|
|
240
240
|
logger.log('error', 'An error occured!', false, true)
|
|
241
241
|
```
|
|
242
242
|
|
|
243
|
-
#### Levels
|
|
243
|
+
#### Levels (event_level)
|
|
244
244
|
```
|
|
245
245
|
Level | Action
|
|
246
246
|
----------------------------------------------------------------------------------------------
|
|
@@ -260,7 +260,7 @@ message ¦ String ¦ The message to be used
|
|
|
260
260
|
subject ¦ String ¦ The Subject to be used
|
|
261
261
|
to_email ¦ String ¦ Recipient email
|
|
262
262
|
from_email ¦ String ¦ Sender email
|
|
263
|
-
|
|
263
|
+
signature ¦ String ¦ Who the emails from
|
|
264
264
|
```
|
|
265
265
|
##### Method usage
|
|
266
266
|
|
|
@@ -275,11 +275,10 @@ from ¦ String ¦ Sent from
|
|
|
275
275
|
_Sends a Slcak message_
|
|
276
276
|
##### Parameters
|
|
277
277
|
```
|
|
278
|
-
Name
|
|
278
|
+
Name | Type | Description
|
|
279
279
|
--------------------------------------------------------------
|
|
280
|
-
message
|
|
281
|
-
|
|
282
|
-
token ¦ String ¦ The API token used to authenticate
|
|
280
|
+
message ¦ String ¦ The message to be used
|
|
281
|
+
webhookURL ¦ String ¦ The webhook to be used
|
|
283
282
|
```
|
|
284
283
|
|
|
285
284
|
##### Method usage
|
|
@@ -287,7 +286,7 @@ token ¦ String ¦ The API token used to authenticate
|
|
|
287
286
|
```$xslt
|
|
288
287
|
require 'miq_utilities'
|
|
289
288
|
notify = NotificationCLass.new
|
|
290
|
-
notify.send_slack_message('This a Slack post!', '
|
|
289
|
+
notify.send_slack_message('This a Slack post!', 'https://hooks.slack.com/services/token')
|
|
291
290
|
```
|
|
292
291
|
|
|
293
292
|
#### **on_screen_message**
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
#
|
|
4
|
+
# This Class is used wrap the chef methods used
|
|
5
|
+
#
|
|
6
|
+
|
|
7
|
+
require_relative 'logging.rb'
|
|
8
|
+
|
|
9
|
+
# Wrapper class to interact with chef
|
|
10
|
+
class ChefClass
|
|
11
|
+
# rubocop:disable Naming/AccessorMethodName
|
|
12
|
+
def initialize(name)
|
|
13
|
+
@logger = LoggingClass.new(name)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def call_chef(cmd, timeout = 20, pre_cmd = nil)
|
|
17
|
+
# unset the variables for knife
|
|
18
|
+
pre_cmd ||= 'unset GEM_HOME GEM_PATH IRBRC MY_RUBY_HOME'
|
|
19
|
+
|
|
20
|
+
require 'linux_admin'
|
|
21
|
+
require 'timeout'
|
|
22
|
+
|
|
23
|
+
begin
|
|
24
|
+
Timeout.timeout(timeout) do
|
|
25
|
+
@logger.log(level: 'info', message: "Executing [#{cmd}] with timeout of #{timeout} seconds")
|
|
26
|
+
result = LinuxAdmin::Common.run("#{pre_cmd};#{cmd}")
|
|
27
|
+
@logger.log(level: 'info', message: "success?: #{result.success?}")
|
|
28
|
+
@logger.log(level: 'info', message: "exit_status: #{result.exit_status}") unless result.exit_status.blank?
|
|
29
|
+
@logger.log(level: 'info', message: "output: #{result.output}")
|
|
30
|
+
@logger.log(level: 'info', message: "error: #{result.error}") unless result.error.blank?
|
|
31
|
+
return result
|
|
32
|
+
end
|
|
33
|
+
rescue => timeout
|
|
34
|
+
@logger.log(level: 'error', message: "Error executing chef: #{timeout.class} #{timeout} #{timeout.backtrace.join("\n")}")
|
|
35
|
+
return false
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def get_chef_environment_name(ws_values = {})
|
|
40
|
+
chef_environment = $evm.object['chef_environment']
|
|
41
|
+
chef_environment ||= $evm.root['dialog_chef_environment']
|
|
42
|
+
if @task
|
|
43
|
+
env = @task.get_tags[:environment]
|
|
44
|
+
region = @task.get_option(:cmdb)[:ProvisionCMDBDetails]['CountryCode'].downcase
|
|
45
|
+
chef_environment = @task.get_tags[:chef_environment] || ws_values[:chef_environment] || @task.get_option(:chef_environment)
|
|
46
|
+
chef_environment ||= case env
|
|
47
|
+
when 'production'
|
|
48
|
+
"#{region}_prod"
|
|
49
|
+
when 'quality_excellence'
|
|
50
|
+
"#{region}_qe"
|
|
51
|
+
when 'development'
|
|
52
|
+
"#{region}_dev"
|
|
53
|
+
else
|
|
54
|
+
'_default'
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
chef_environment ||= '_default'
|
|
58
|
+
@logger.log(level: 'info', message: "chef_environment: #{chef_environment}")
|
|
59
|
+
chef_environment
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def get_chef_type
|
|
63
|
+
chef_type = $evm.object['chef_type']
|
|
64
|
+
chef_type ||= $evm.root['dialog_chef_type']
|
|
65
|
+
chef_type ||= 'role'
|
|
66
|
+
@logger.log(level: 'info', message: "chef_type: #{chef_type}")
|
|
67
|
+
chef_type
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def get_chef_node_name
|
|
71
|
+
chef_node_name = begin
|
|
72
|
+
@vm.hostnames.first
|
|
73
|
+
rescue
|
|
74
|
+
nil
|
|
75
|
+
end
|
|
76
|
+
domain_suffix = get_domain_suffix
|
|
77
|
+
chef_node_name ||= @task.get_option(:vm_target_hostname) if @task
|
|
78
|
+
chef_node_name ||= @vm.name.to_s
|
|
79
|
+
chef_node_name = "#{chef_node_name}.#{domain_suffix}" unless domain_suffix.nil? || chef_node_name.include?(domain_suffix)
|
|
80
|
+
|
|
81
|
+
@logger.log(level: 'info', message: "chef_node_name: #{chef_node_name}")
|
|
82
|
+
chef_node_name.downcase
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def get_chef_role(ws_values = {})
|
|
86
|
+
chef_role = $evm.object['chef_role']
|
|
87
|
+
chef_role ||= $evm.root['dialog_chef_role']
|
|
88
|
+
if @task
|
|
89
|
+
chef_role = @task.get_tags[:chef_role] || ws_values[:chef_role] || @task.get_option(:chef_role)
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
chef_role ||= ''
|
|
93
|
+
@logger.log(level: 'info', message: "chef_role: #{chef_role}")
|
|
94
|
+
chef_role
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def get_domain_suffix
|
|
98
|
+
domain_suffix = nil
|
|
99
|
+
domain_suffix ||= $evm.object['domain_suffix']
|
|
100
|
+
domain_suffix ||= $evm.root['dialog_domain_suffix']
|
|
101
|
+
domain_suffix ||= @task.get_tags[:domain_suffix] if @task
|
|
102
|
+
@logger.log(level: 'info', message: "domain_suffix: #{domain_suffix}")
|
|
103
|
+
domain_suffix
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def get_chef_version(chef_version = nil)
|
|
107
|
+
chef_version ||= $evm.object['chef_version']
|
|
108
|
+
@logger.log(level: 'info', message: "chef_version: #{chef_version}")
|
|
109
|
+
chef_version
|
|
110
|
+
end
|
|
111
|
+
# rubocop:enable Naming/AccessorMethodName
|
|
112
|
+
end
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
#
|
|
4
|
+
# This Class is used to hold general methods used within this GEM
|
|
5
|
+
#
|
|
6
|
+
# Methods Summary:
|
|
7
|
+
# > Name > Description/Params
|
|
8
|
+
#
|
|
9
|
+
|
|
10
|
+
require_relative 'logging.rb'
|
|
11
|
+
|
|
12
|
+
# Wrapper class to interact with linux machines via ssh
|
|
13
|
+
class GeneralClass
|
|
14
|
+
def initialize(name)
|
|
15
|
+
@logger = LoggingClass.new(name)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# basic retry logic
|
|
19
|
+
def retry_method(retry_time = 1.minute)
|
|
20
|
+
@logger.log(level: 'info', message: "Sleeping for #{retry_time} seconds")
|
|
21
|
+
$evm.root['ae_result'] = 'retry'
|
|
22
|
+
$evm.root['ae_retry_interval'] = retry_time
|
|
23
|
+
exit(MIQ_OK)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# process tags
|
|
27
|
+
def process_tags(category, category_description, single_value, tag, tag_description)
|
|
28
|
+
# Convert to lower case and replace all non-word characters with underscores
|
|
29
|
+
category_name = category.to_s.downcase.gsub(/\W/, '_')
|
|
30
|
+
tag_name = tag.to_s.downcase.gsub(/\W|:/, '_')
|
|
31
|
+
@logger.log(level: 'info', message: "Converted category name:<#{category_name}> Converted tag name: <#{tag_name}>")
|
|
32
|
+
# if the category exists else create it
|
|
33
|
+
unless $evm.execute('category_exists?', category_name)
|
|
34
|
+
@logger.log(level: 'info', message: "Category <#{category_name}> doesn't exist, creating category")
|
|
35
|
+
$evm.execute('category_create', name: category_name, single_value: single_value, description: category_description.to_s)
|
|
36
|
+
end
|
|
37
|
+
# if the tag exists else create it
|
|
38
|
+
@logger.log(level: 'info', message: "Adding new tag <#{tag_name}> description <#{tag_description}> in Category <#{category_name}>") unless $evm.execute('tag_exists?', category_name, tag_name)
|
|
39
|
+
$evm.execute('tag_create', category_name, name: tag_name, description: tag_description.to_s) unless $evm.execute('tag_exists?', category_name, tag_name)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def update_vm_custom_attributes(key, value)
|
|
43
|
+
@logger.log(level: 'debug', message: "#{key} #{value}")
|
|
44
|
+
@vm.custom_set(key, value)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -40,7 +40,7 @@ require 'rest-client'
|
|
|
40
40
|
require 'json'
|
|
41
41
|
require_relative 'logging.rb'
|
|
42
42
|
|
|
43
|
-
#
|
|
43
|
+
# Wrapper class to interact with Infoblox
|
|
44
44
|
class InfobloxClass
|
|
45
45
|
private def process_args(inargs, inurl)
|
|
46
46
|
loops = 1
|
|
@@ -106,7 +106,7 @@ class InfobloxClass
|
|
|
106
106
|
url
|
|
107
107
|
end
|
|
108
108
|
|
|
109
|
-
@logger.log('info', "URL: \"#{url}\"")
|
|
109
|
+
@logger.log(level: 'info', message: "URL: \"#{url}\"")
|
|
110
110
|
|
|
111
111
|
params = {
|
|
112
112
|
method: action,
|
|
@@ -119,18 +119,18 @@ class InfobloxClass
|
|
|
119
119
|
|
|
120
120
|
if body_type == :json
|
|
121
121
|
params[:payload] = JSON.generate(body) if body
|
|
122
|
-
@logger.log('info', "Calling -> Infoblox:<#{url}> action:<#{action}> payload:<#{params[:payload]}>") if body
|
|
122
|
+
@logger.log(level: 'info', message: "Calling -> Infoblox:<#{url}> action:<#{action}> payload:<#{params[:payload]}>") if body
|
|
123
123
|
elsif body
|
|
124
124
|
params[:payload] = body
|
|
125
125
|
end
|
|
126
126
|
|
|
127
127
|
response = RestClient::Request.new(params).execute
|
|
128
128
|
if response.code == 200 || response.code == 201
|
|
129
|
-
@logger.log('info', "Success <- Infoblox Response:<#{response.code}>")
|
|
129
|
+
@logger.log(level: 'info', message: "Success <- Infoblox Response:<#{response.code}>")
|
|
130
130
|
else
|
|
131
131
|
err_msg = "Error calling infoblox. <#{response.inspect}>"
|
|
132
|
-
@logger.log('error', err_msg,
|
|
132
|
+
@logger.log(level: 'error', message: err_msg, notify: true)
|
|
133
133
|
end
|
|
134
134
|
response
|
|
135
135
|
end
|
|
136
|
-
end
|
|
136
|
+
end
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
#
|
|
17
17
|
require_relative 'notification.rb'
|
|
18
18
|
|
|
19
|
-
#
|
|
19
|
+
# Wrapper class for logging
|
|
20
20
|
class LoggingClass
|
|
21
21
|
# initialize class
|
|
22
22
|
def initialize(name)
|
|
@@ -24,18 +24,21 @@ class LoggingClass
|
|
|
24
24
|
@notification = NotificationClass.new
|
|
25
25
|
end
|
|
26
26
|
|
|
27
|
-
def log(level
|
|
28
|
-
levelvalid = %w[info warn error].any? { |msglevel| level.upcase.include? msglevel.to_s.upcase }
|
|
27
|
+
def log(level:, message:, logtoscreenonly: false, notify: false, email_to: nil, email_from: nil, signature: nil, webhookurl: nil, subjecttype: nil, update_message: false)
|
|
28
|
+
levelvalid = %w[info warn error debug].any? { |msglevel| level.upcase.include? msglevel.to_s.upcase }
|
|
29
29
|
|
|
30
30
|
if $evm.nil? || logtoscreenonly
|
|
31
31
|
puts "#{level}: #{@initializer} - #{message}"
|
|
32
32
|
elsif levelvalid
|
|
33
33
|
$evm.log(level, "#{@initializer} - #{message}")
|
|
34
|
+
@task.message = message if @task && (level.casecmp('ERROR').zero? || update_message)
|
|
34
35
|
else
|
|
35
36
|
$evm.log('info', "#{@initializer} - #{message}")
|
|
36
37
|
end
|
|
37
38
|
|
|
38
39
|
# Notify - Only if flag (notify) is set to TRUE
|
|
39
|
-
@notification.notify(level, message) if notify
|
|
40
|
+
@notification.notify(event_level: level, event_message: message, email_to: email_to, email_from: email_from, signature: signature, webhookurl: webhookurl, subjecttype: subjecttype) if notify
|
|
41
|
+
rescue => err
|
|
42
|
+
raise("Oopps! Something went wrong.\nError:<#{err}>")
|
|
40
43
|
end
|
|
41
44
|
end
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
# .SYNOPSIS
|
|
4
|
-
# This Class utilises the slack-
|
|
4
|
+
# This Class utilises the slack-notifier Ruby Gem (version => 2.3.2).
|
|
5
5
|
#
|
|
6
6
|
# Methods Summary:
|
|
7
7
|
# > Name > Description/Params
|
|
@@ -10,48 +10,49 @@
|
|
|
10
10
|
# event_message - String : The message to be used
|
|
11
11
|
# email_to - String : Who to send an email to
|
|
12
12
|
# email_from - String : Sent from which email address
|
|
13
|
-
#
|
|
14
|
-
#
|
|
13
|
+
# signature - String : Who the emails from
|
|
14
|
+
# webhookurl - String : The slcak channel to send the message to
|
|
15
15
|
#
|
|
16
16
|
# send_email - Sends an email to the specified user
|
|
17
17
|
# message - String : The message to be used
|
|
18
18
|
# subject - String : The Subject to be used
|
|
19
|
-
# to_email - String : Recipient email
|
|
20
19
|
# from_email - String : Sender email
|
|
21
|
-
#
|
|
20
|
+
# signature - String : Who the emails from
|
|
21
|
+
# to_email - String : Recipient email
|
|
22
22
|
#
|
|
23
23
|
# send_slack_message - Sends a Slcak message
|
|
24
|
-
# message
|
|
25
|
-
#
|
|
26
|
-
# token - String : The API token used to authenticate
|
|
24
|
+
# message - String : The message to be used
|
|
25
|
+
# webhookurl - String : The webhook to be used
|
|
27
26
|
#
|
|
28
27
|
# on_screen_message - Sends an on-screen notification
|
|
29
28
|
# level - String : info, warn, error
|
|
30
29
|
# message - String : The message to be used
|
|
31
30
|
# subject - String : The Subject to be used
|
|
32
31
|
# WIP
|
|
33
|
-
require 'slack-
|
|
32
|
+
require 'slack-notifier'
|
|
34
33
|
|
|
35
|
-
#
|
|
34
|
+
# Wrapper class to notify stakeholders
|
|
36
35
|
class NotificationClass
|
|
37
|
-
|
|
38
|
-
|
|
36
|
+
def notify(event_level:, event_message:, email_to: nil, email_from: nil, signature: nil, webhookurl: nil, subjecttype: nil)
|
|
37
|
+
signature ||= 'ManageIQ'
|
|
39
38
|
case event_level.upcase
|
|
40
39
|
when %w[WARN WARNING]
|
|
41
|
-
|
|
42
|
-
|
|
40
|
+
subject = 'ManageIQ Warning'
|
|
41
|
+
send_email(message: event_message, subject: subject, from_email: email_from, signature: signature, to_email: email_to)
|
|
42
|
+
send_slack_message(message: event_message, webhookurl: webhookurl)
|
|
43
43
|
when %w[ERR ERROR]
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
44
|
+
subject = 'ManageIQ Error'
|
|
45
|
+
send_email(message: event_message, subject: subject, from_email: email_from, signature: signature, to_email: email_to)
|
|
46
|
+
send_slack_message(message: event_message, webhookurl: webhookurl)
|
|
47
|
+
on_screen_message(level: event_level, message: event_message, type: subjecttype)
|
|
47
48
|
when 'NOTE'
|
|
48
|
-
on_screen_message(event_level, event_message)
|
|
49
|
+
on_screen_message(level: event_level, message: event_message, type: subjecttype)
|
|
49
50
|
end
|
|
50
51
|
rescue => err
|
|
51
52
|
raise("Oopps! Something went wrong trying to notify. Error:<#{err}>")
|
|
52
53
|
end
|
|
53
54
|
|
|
54
|
-
def send_email(message
|
|
55
|
+
def send_email(message:, subject:, from_email:, signature:, to_email: nil)
|
|
55
56
|
# Look in the current object for a VM
|
|
56
57
|
vm = $evm.object['vm']
|
|
57
58
|
if vm.nil?
|
|
@@ -95,47 +96,38 @@ class NotificationClass
|
|
|
95
96
|
body = 'Hello, '
|
|
96
97
|
body += message
|
|
97
98
|
body += 'Thank you,'
|
|
98
|
-
body +=
|
|
99
|
+
body += signature
|
|
99
100
|
|
|
100
101
|
$evm.execute(:send_email, to, from_email, subject, body)
|
|
101
102
|
rescue => err
|
|
102
103
|
raise("Oopps! Something went wrong trying to send an email to:<#{to}>. Error:<#{err}>")
|
|
103
104
|
end
|
|
104
105
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
config.token = ENV['SLACK_API_TOKEN']
|
|
111
|
-
raise 'Missing ENV[SLACK_API_TOKEN]!' unless config.token
|
|
112
|
-
end
|
|
113
|
-
else
|
|
114
|
-
config.token = token
|
|
115
|
-
end
|
|
116
|
-
|
|
117
|
-
begin
|
|
118
|
-
client = Slack::Web::Client.new
|
|
119
|
-
client.auth_test
|
|
120
|
-
client.chat_postMessage(channel: channel, text: message, as_user: true)
|
|
121
|
-
rescue => err
|
|
122
|
-
raise("Oopps! Something went wrong trying to send a Slack notification. Error:<#{err}>")
|
|
123
|
-
end
|
|
106
|
+
def send_slack_message(message:, webhookurl:)
|
|
107
|
+
notifier = Slack::Notifier.new webhookurl
|
|
108
|
+
notifier.ping message
|
|
109
|
+
rescue => err
|
|
110
|
+
raise("Oopps! Something went wrong trying to send a Slack notification. Error:<#{err}>")
|
|
124
111
|
end
|
|
125
112
|
|
|
126
|
-
def on_screen_message(level
|
|
113
|
+
def on_screen_message(level:, message:, subject: nil, type: nil)
|
|
127
114
|
if subject.nil?
|
|
128
115
|
vm = $evm.root['vm']
|
|
129
116
|
prov = $evm.root['miq_provision']
|
|
130
117
|
subject ||= vm unless vm.nil?
|
|
131
118
|
subject ||= prov.miq_request unless prov.miq_request.nil?
|
|
119
|
+
prov.message = message unless prov.nil?
|
|
132
120
|
end
|
|
133
121
|
|
|
134
122
|
levelvalid = %w[info warn error].any? { |msglevel| level.upcase.include? msglevel.to_s.upcase }
|
|
135
123
|
level = 'info' unless levelvalid
|
|
136
124
|
|
|
137
125
|
begin
|
|
138
|
-
|
|
126
|
+
if type.nil?
|
|
127
|
+
$evm.create_notification(level: level, subject: subject, message: message)
|
|
128
|
+
else
|
|
129
|
+
$evm.create_notification(type: type, subject: subject)
|
|
130
|
+
end
|
|
139
131
|
rescue => err
|
|
140
132
|
raise("Oopps! Something went wrong trying to display on-screen notification. Error:<#{err}>")
|
|
141
133
|
end
|
data/lib/miq_utilities/sql.rb
CHANGED
|
@@ -9,9 +9,9 @@
|
|
|
9
9
|
# user - String : Username
|
|
10
10
|
# password - String : Password
|
|
11
11
|
# host - String : The host name to connect to
|
|
12
|
-
# port - String : The port to use, default (nil) 1433
|
|
13
12
|
# database - String : The database name to connect to
|
|
14
13
|
# azure - Boolean : Set to true when connecting to Azure
|
|
14
|
+
# port - String : The port to use, default (nil) 1433
|
|
15
15
|
#
|
|
16
16
|
# get_client - returns the client to utilise the tiny_tds functionality
|
|
17
17
|
#
|
|
@@ -21,17 +21,18 @@
|
|
|
21
21
|
# close_connection - closes the connection to the client
|
|
22
22
|
#
|
|
23
23
|
require 'tiny_tds'
|
|
24
|
+
require_relative 'logging.rb'
|
|
24
25
|
|
|
25
|
-
#
|
|
26
|
+
# Wrapper class to interact with sql server
|
|
26
27
|
class SqlClass
|
|
27
28
|
# Initialize Class
|
|
28
|
-
def initialize(user, password, host, port = nil
|
|
29
|
+
def initialize(user, password, host, database, azure, port = nil)
|
|
29
30
|
# Logging
|
|
30
31
|
@logger = LoggingClass.new('SQL')
|
|
31
32
|
|
|
32
33
|
# Default port
|
|
33
|
-
unless port.nil?
|
|
34
|
-
@logger.log('info', 'Using default port 1433')
|
|
34
|
+
unless port.nil?
|
|
35
|
+
@logger.log(level: 'info', message: 'Using default port 1433')
|
|
35
36
|
port = '1433'
|
|
36
37
|
end
|
|
37
38
|
|
|
@@ -53,7 +54,7 @@ class SqlClass
|
|
|
53
54
|
# Run Sql query
|
|
54
55
|
def run_sql_query(sql)
|
|
55
56
|
if @client.nil?
|
|
56
|
-
@logger.log('warn', 'SQL Server Connection Not Established! Query hasn\'t been run!')
|
|
57
|
+
@logger.log(level: 'warn', message: 'SQL Server Connection Not Established! Query hasn\'t been run!')
|
|
57
58
|
else
|
|
58
59
|
@client.execute(sql)
|
|
59
60
|
end
|
|
@@ -62,6 +63,6 @@ class SqlClass
|
|
|
62
63
|
# Close the connection to the sql client
|
|
63
64
|
def close_connection
|
|
64
65
|
@client.close unless @client.closed?
|
|
65
|
-
@logger.log('info', 'Connection to SQL Client Closed Successfully.') if @client.closed?
|
|
66
|
+
@logger.log(level: 'info', message: 'Connection to SQL Client Closed Successfully.') if @client.closed?
|
|
66
67
|
end
|
|
67
68
|
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
#
|
|
4
|
+
# This Class is used to handle the logging for ManageIQ and an IDE
|
|
5
|
+
#
|
|
6
|
+
# Methods Summary:
|
|
7
|
+
# > Name > Description/Params
|
|
8
|
+
# ssh_run - Run script via ssh
|
|
9
|
+
# script - String : The script to run
|
|
10
|
+
# ipaddress - String : The message
|
|
11
|
+
# linux_user - String : User to login as
|
|
12
|
+
# linux_password - String : password to use
|
|
13
|
+
#
|
|
14
|
+
|
|
15
|
+
require 'net/ssh'
|
|
16
|
+
require_relative 'logging.rb'
|
|
17
|
+
|
|
18
|
+
# This wrapper class is used to run ssh commands on linux machines
|
|
19
|
+
class SshClass
|
|
20
|
+
def ssh_run(ipaddr, script, linux_user = nil, linux_password = nil)
|
|
21
|
+
@logger = LoggingClass.new('ssh_run')
|
|
22
|
+
linux_password ||= $evm.object.decrypt('linux_password').to_s
|
|
23
|
+
linux_user ||= 'root'
|
|
24
|
+
|
|
25
|
+
Net::SSH.start(ipaddr, linux_user, password: linux_password, paranoid: Net::SSH::Verifiers::Null.new) do |ssh|
|
|
26
|
+
command = script
|
|
27
|
+
output = ssh.exec!(command)
|
|
28
|
+
@logger.log(level: 'info', message: "ssh command being run on #{ipaddr}")
|
|
29
|
+
@logger.log(level: 'info', message: "ssh script being run is #{script}")
|
|
30
|
+
@logger.log(level: 'info', message: "SSH output = #{output}")
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
data/lib/miq_utilities/vmware.rb
CHANGED
|
@@ -12,13 +12,18 @@
|
|
|
12
12
|
# user - String : The user to connect with
|
|
13
13
|
# password - String : The users password
|
|
14
14
|
#
|
|
15
|
-
#
|
|
16
|
-
# vsphereconn - connection : The return of "get_vsphere_connection"
|
|
17
|
-
# dcname - String : The name of the datacenter
|
|
15
|
+
# retrieve_data_center - returns the datacenter based on the connection and datacenter
|
|
18
16
|
#
|
|
17
|
+
#
|
|
18
|
+
# find_vm - Get the VM details from vmware
|
|
19
|
+
# datacenter - String : retrieve_data_center return value
|
|
20
|
+
# vmname - String : The vmname
|
|
21
|
+
#
|
|
22
|
+
# upg_tools - Get the VM details from vmware
|
|
23
|
+
# vmobj - Object : find_vm return value
|
|
19
24
|
require 'rbvmomi'
|
|
20
25
|
|
|
21
|
-
#
|
|
26
|
+
# Wrapper class to interact with vmware
|
|
22
27
|
class VmwareClass
|
|
23
28
|
def initialize(host_name)
|
|
24
29
|
@host_name = host_name
|
|
@@ -34,10 +39,10 @@ class VmwareClass
|
|
|
34
39
|
raise("No connection established!\nUse the \"get_vsphere_connection\" method to connect.") if @connection.nil?
|
|
35
40
|
end
|
|
36
41
|
|
|
37
|
-
def find_vm(
|
|
42
|
+
def find_vm(datacenter, vmname)
|
|
38
43
|
vm = {}
|
|
39
|
-
|
|
40
|
-
vm[:instance] = datastore.vm.find { |x| x.name ==
|
|
44
|
+
datacenter.datastoreFolder.childEntity.collect do |datastore|
|
|
45
|
+
vm[:instance] = datastore.vm.find { |x| x.name == vmname }
|
|
41
46
|
if vm[:instance]
|
|
42
47
|
vm[:datastore] = datastore.name
|
|
43
48
|
break
|
|
@@ -46,10 +51,10 @@ class VmwareClass
|
|
|
46
51
|
vm
|
|
47
52
|
end
|
|
48
53
|
|
|
49
|
-
def upg_tools(
|
|
50
|
-
instopts = if
|
|
54
|
+
def upg_tools(vmobj)
|
|
55
|
+
instopts = if vmobj[:instance][:guest][:guestFamily] == 'windowsGuest'
|
|
51
56
|
'/s /v "/qn REBOOT=ReallySuppress"'
|
|
52
57
|
end
|
|
53
|
-
|
|
58
|
+
vmobj[:instance].UpgradeTools_Task(installerOptions: instopts).wait_for_completion
|
|
54
59
|
end
|
|
55
60
|
end
|
data/lib/miq_utilities/winrm.rb
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
require 'winrm'
|
|
15
15
|
require 'logging.rb'
|
|
16
16
|
|
|
17
|
-
#
|
|
17
|
+
# Wrapper class to interact with winrm
|
|
18
18
|
class WinrmClass
|
|
19
19
|
def winrm_run(ps_script, host, user, password)
|
|
20
20
|
@logger = LoggingClass.new('WinRM')
|
|
@@ -31,9 +31,9 @@ class WinrmClass
|
|
|
31
31
|
|
|
32
32
|
conn = WinRM::Connection.new(opts)
|
|
33
33
|
|
|
34
|
-
@logger.log('info', "WinRM is connecting to #{opts[:endpoint]}")
|
|
34
|
+
@logger.log(level: 'info', message: "WinRM is connecting to #{opts[:endpoint]}")
|
|
35
35
|
msg = ps1.to_s.gsub(password.to_s, '****')
|
|
36
|
-
@logger.log('info', "Running PowerShell script: #{msg}")
|
|
36
|
+
@logger.log(level: 'info', message: "Running PowerShell script: #{msg}")
|
|
37
37
|
|
|
38
38
|
conn.shell(:powershell) do |shell|
|
|
39
39
|
err = ''
|
|
@@ -42,9 +42,9 @@ class WinrmClass
|
|
|
42
42
|
err = stderr
|
|
43
43
|
end
|
|
44
44
|
if output.exitcode.zero?
|
|
45
|
-
@logger.log('info', "PS script finished with exit code #{output.exitcode} - Output: <#{value.to_s.strip}>")
|
|
45
|
+
@logger.log(level: 'info', message: "PS script finished with exit code #{output.exitcode} - Output: <#{value.to_s.strip}>")
|
|
46
46
|
else
|
|
47
|
-
@logger.log('error', "PS script failed with exit code #{output.exitcode} and error message #{err}. STDOUT: #{value.to_s.strip}")
|
|
47
|
+
@logger.log(level: 'error', message: "PS script failed with exit code #{output.exitcode} and error message #{err}. STDOUT: #{value.to_s.strip}")
|
|
48
48
|
end
|
|
49
49
|
end
|
|
50
50
|
value.to_s.strip
|
data/lib/miq_utilities.rb
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
|
|
3
|
+
# Module to include resources
|
|
2
4
|
module MiqUtilities
|
|
3
5
|
require_relative 'miq_utilities/version'
|
|
4
6
|
require_relative 'miq_utilities/infoblox.rb'
|
|
@@ -7,4 +9,6 @@ module MiqUtilities
|
|
|
7
9
|
require_relative 'miq_utilities/sql.rb'
|
|
8
10
|
require_relative 'miq_utilities/winrm.rb'
|
|
9
11
|
require_relative 'miq_utilities/vmware.rb'
|
|
12
|
+
require_relative 'miq_utilities/ssh.rb'
|
|
13
|
+
require_relative 'miq_utilities/chef.rb'
|
|
10
14
|
end
|
data/miq_utilities.gemspec
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: miq_utilities
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.2.
|
|
4
|
+
version: 0.2.4
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Aaron McCatty
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2018-05-
|
|
11
|
+
date: 2018-05-15 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: bundler
|
|
@@ -108,6 +108,20 @@ dependencies:
|
|
|
108
108
|
- - "~>"
|
|
109
109
|
- !ruby/object:Gem::Version
|
|
110
110
|
version: '2.0'
|
|
111
|
+
- !ruby/object:Gem::Dependency
|
|
112
|
+
name: slack-notifier
|
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
|
114
|
+
requirements:
|
|
115
|
+
- - "~>"
|
|
116
|
+
- !ruby/object:Gem::Version
|
|
117
|
+
version: '2.3'
|
|
118
|
+
type: :development
|
|
119
|
+
prerelease: false
|
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
121
|
+
requirements:
|
|
122
|
+
- - "~>"
|
|
123
|
+
- !ruby/object:Gem::Version
|
|
124
|
+
version: '2.3'
|
|
111
125
|
description: " This Gem was written to hold utilities commonly used within ManageIQ/Cloudforms. "
|
|
112
126
|
email:
|
|
113
127
|
- aaronmccatty@hotmail.co.uk
|
|
@@ -116,6 +130,7 @@ extensions: []
|
|
|
116
130
|
extra_rdoc_files: []
|
|
117
131
|
files:
|
|
118
132
|
- ".gitignore"
|
|
133
|
+
- ".rubocop.yml"
|
|
119
134
|
- Gemfile
|
|
120
135
|
- Gemfile.lock
|
|
121
136
|
- LICENSE.txt
|
|
@@ -124,10 +139,13 @@ files:
|
|
|
124
139
|
- bin/console
|
|
125
140
|
- bin/setup
|
|
126
141
|
- lib/miq_utilities.rb
|
|
142
|
+
- lib/miq_utilities/chef.rb
|
|
143
|
+
- lib/miq_utilities/general.rb
|
|
127
144
|
- lib/miq_utilities/infoblox.rb
|
|
128
145
|
- lib/miq_utilities/logging.rb
|
|
129
146
|
- lib/miq_utilities/notification.rb
|
|
130
147
|
- lib/miq_utilities/sql.rb
|
|
148
|
+
- lib/miq_utilities/ssh.rb
|
|
131
149
|
- lib/miq_utilities/version.rb
|
|
132
150
|
- lib/miq_utilities/vmware.rb
|
|
133
151
|
- lib/miq_utilities/winrm.rb
|