manageiq-appliance_console 1.0.0
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 +7 -0
- data/.codeclimate.yml +47 -0
- data/.gitignore +12 -0
- data/.rspec +4 -0
- data/.rspec_ci +4 -0
- data/.rubocop.yml +4 -0
- data/.rubocop_cc.yml +5 -0
- data/.rubocop_local.yml +2 -0
- data/.travis.yml +19 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +202 -0
- data/README.md +45 -0
- data/Rakefile +6 -0
- data/bin/appliance_console +661 -0
- data/bin/appliance_console_cli +7 -0
- data/lib/manageiq-appliance_console.rb +51 -0
- data/lib/manageiq/appliance_console/certificate.rb +146 -0
- data/lib/manageiq/appliance_console/certificate_authority.rb +140 -0
- data/lib/manageiq/appliance_console/cli.rb +363 -0
- data/lib/manageiq/appliance_console/database_configuration.rb +286 -0
- data/lib/manageiq/appliance_console/database_maintenance.rb +35 -0
- data/lib/manageiq/appliance_console/database_maintenance_hourly.rb +58 -0
- data/lib/manageiq/appliance_console/database_maintenance_periodic.rb +84 -0
- data/lib/manageiq/appliance_console/database_replication.rb +146 -0
- data/lib/manageiq/appliance_console/database_replication_primary.rb +59 -0
- data/lib/manageiq/appliance_console/database_replication_standby.rb +166 -0
- data/lib/manageiq/appliance_console/date_time_configuration.rb +117 -0
- data/lib/manageiq/appliance_console/errors.rb +5 -0
- data/lib/manageiq/appliance_console/external_auth_options.rb +153 -0
- data/lib/manageiq/appliance_console/external_database_configuration.rb +34 -0
- data/lib/manageiq/appliance_console/external_httpd_authentication.rb +157 -0
- data/lib/manageiq/appliance_console/external_httpd_authentication/external_httpd_configuration.rb +249 -0
- data/lib/manageiq/appliance_console/internal_database_configuration.rb +187 -0
- data/lib/manageiq/appliance_console/key_configuration.rb +118 -0
- data/lib/manageiq/appliance_console/logfile_configuration.rb +117 -0
- data/lib/manageiq/appliance_console/logger.rb +23 -0
- data/lib/manageiq/appliance_console/logging.rb +102 -0
- data/lib/manageiq/appliance_console/logical_volume_management.rb +94 -0
- data/lib/manageiq/appliance_console/principal.rb +46 -0
- data/lib/manageiq/appliance_console/prompts.rb +211 -0
- data/lib/manageiq/appliance_console/scap.rb +53 -0
- data/lib/manageiq/appliance_console/temp_storage_configuration.rb +79 -0
- data/lib/manageiq/appliance_console/timezone_configuration.rb +58 -0
- data/lib/manageiq/appliance_console/utilities.rb +67 -0
- data/lib/manageiq/appliance_console/version.rb +5 -0
- data/locales/appliance/en.yml +42 -0
- data/locales/container/en.yml +30 -0
- data/manageiq-appliance_console.gemspec +40 -0
- data/zanata.xml +7 -0
- metadata +317 -0
@@ -0,0 +1,187 @@
|
|
1
|
+
require "pathname"
|
2
|
+
require "util/postgres_admin"
|
3
|
+
require "pg"
|
4
|
+
require "linux_admin"
|
5
|
+
|
6
|
+
module ManageIQ
|
7
|
+
module ApplianceConsole
|
8
|
+
class InternalDatabaseConfiguration < DatabaseConfiguration
|
9
|
+
attr_accessor :disk, :ssl, :run_as_evm_server
|
10
|
+
|
11
|
+
DEDICATED_DB_SHARED_BUFFERS = "'1GB'".freeze
|
12
|
+
SHARED_DB_SHARED_BUFFERS = "'128MB'".freeze
|
13
|
+
|
14
|
+
def self.postgres_dir
|
15
|
+
PostgresAdmin.data_directory.relative_path_from(Pathname.new("/"))
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.postgresql_template
|
19
|
+
PostgresAdmin.template_directory.join(postgres_dir)
|
20
|
+
end
|
21
|
+
|
22
|
+
def initialize(hash = {})
|
23
|
+
set_defaults
|
24
|
+
super
|
25
|
+
end
|
26
|
+
|
27
|
+
def set_defaults
|
28
|
+
self.host = 'localhost'
|
29
|
+
self.username = "root"
|
30
|
+
self.database = "vmdb_production"
|
31
|
+
self.run_as_evm_server = true
|
32
|
+
end
|
33
|
+
|
34
|
+
def activate
|
35
|
+
if PostgresAdmin.initialized?
|
36
|
+
say(<<-EOF.gsub!(/^\s+/, ""))
|
37
|
+
An internal database already exists.
|
38
|
+
Choose "Reset Configured Database" to reset the existing installation
|
39
|
+
EOF
|
40
|
+
return false
|
41
|
+
end
|
42
|
+
initialize_postgresql_disk if disk
|
43
|
+
initialize_postgresql
|
44
|
+
return super if run_as_evm_server
|
45
|
+
true
|
46
|
+
end
|
47
|
+
|
48
|
+
def ask_questions
|
49
|
+
choose_disk
|
50
|
+
check_disk_is_mount_point
|
51
|
+
self.run_as_evm_server = !ask_yn?(<<-EOS.gsub!(/^ +/m, ""), "N")
|
52
|
+
|
53
|
+
Should this appliance run as a standalone database server?
|
54
|
+
|
55
|
+
NOTE:
|
56
|
+
* The #{I18n.t("product.name")} application will not be running.
|
57
|
+
* This is required when using highly available database deployments.
|
58
|
+
* CAUTION: This is not reversible.
|
59
|
+
|
60
|
+
EOS
|
61
|
+
# TODO: Assume we want to create a region for a new internal database disk
|
62
|
+
# until we allow for the internal selection against an already initialized disk.
|
63
|
+
create_new_region_questions(false) if run_as_evm_server
|
64
|
+
ask_for_database_credentials
|
65
|
+
end
|
66
|
+
|
67
|
+
def choose_disk
|
68
|
+
@disk = ask_for_disk("database disk")
|
69
|
+
end
|
70
|
+
|
71
|
+
def check_disk_is_mount_point
|
72
|
+
error_message = "The disk for database must be a mount point"
|
73
|
+
raise error_message unless disk || pg_mount_point?
|
74
|
+
end
|
75
|
+
|
76
|
+
def initialize_postgresql_disk
|
77
|
+
log_and_feedback(__method__) do
|
78
|
+
LogicalVolumeManagement.new(:disk => disk,
|
79
|
+
:mount_point => mount_point,
|
80
|
+
:name => "pg",
|
81
|
+
:volume_group_name => PostgresAdmin.volume_group_name,
|
82
|
+
:filesystem_type => PostgresAdmin.database_disk_filesystem,
|
83
|
+
:logical_volume_path => PostgresAdmin.logical_volume_path).setup
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def initialize_postgresql
|
88
|
+
log_and_feedback(__method__) do
|
89
|
+
PostgresAdmin.prep_data_directory
|
90
|
+
run_initdb
|
91
|
+
relabel_postgresql_dir
|
92
|
+
configure_postgres
|
93
|
+
start_postgres
|
94
|
+
create_postgres_root_user
|
95
|
+
create_postgres_database
|
96
|
+
apply_initial_configuration
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def configure_postgres
|
101
|
+
self.ssl = File.exist?(PostgresAdmin.certificate_location.join("postgres.key"))
|
102
|
+
|
103
|
+
copy_template "postgresql.conf"
|
104
|
+
copy_template "pg_hba.conf.erb"
|
105
|
+
copy_template "pg_ident.conf"
|
106
|
+
end
|
107
|
+
|
108
|
+
def post_activation
|
109
|
+
start_evm if run_as_evm_server
|
110
|
+
end
|
111
|
+
|
112
|
+
private
|
113
|
+
|
114
|
+
def mount_point
|
115
|
+
PostgresAdmin.mount_point
|
116
|
+
end
|
117
|
+
|
118
|
+
def copy_template(src, src_dir = self.class.postgresql_template, dest_dir = PostgresAdmin.data_directory)
|
119
|
+
full_src = src_dir.join(src)
|
120
|
+
if src.include?(".erb")
|
121
|
+
full_dest = dest_dir.join(src.gsub(".erb", ""))
|
122
|
+
File.open(full_dest, "w") { |f| f.puts ERB.new(File.read(full_src), nil, '-').result(binding) }
|
123
|
+
else
|
124
|
+
FileUtils.cp full_src, dest_dir
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
def pg_mount_point?
|
129
|
+
LinuxAdmin::LogicalVolume.mount_point_exists?(mount_point.to_s)
|
130
|
+
end
|
131
|
+
|
132
|
+
def run_initdb
|
133
|
+
AwesomeSpawn.run!("service", :params => {nil => [PostgresAdmin.service_name, "initdb"]})
|
134
|
+
end
|
135
|
+
|
136
|
+
def start_postgres
|
137
|
+
LinuxAdmin::Service.new(PostgresAdmin.service_name).enable.start
|
138
|
+
block_until_postgres_accepts_connections
|
139
|
+
end
|
140
|
+
|
141
|
+
def restart_postgres
|
142
|
+
LinuxAdmin::Service.new(PostgresAdmin.service_name).restart
|
143
|
+
block_until_postgres_accepts_connections
|
144
|
+
end
|
145
|
+
|
146
|
+
def block_until_postgres_accepts_connections
|
147
|
+
loop do
|
148
|
+
break if AwesomeSpawn.run("psql -U postgres -c 'select 1'").success?
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
def create_postgres_root_user
|
153
|
+
with_pg_connection do |conn|
|
154
|
+
esc_pass = conn.escape_string(password)
|
155
|
+
conn.exec("CREATE ROLE #{username} WITH LOGIN CREATEDB SUPERUSER PASSWORD '#{esc_pass}'")
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
def create_postgres_database
|
160
|
+
with_pg_connection do |conn|
|
161
|
+
conn.exec("CREATE DATABASE #{database} OWNER #{username} ENCODING 'utf8'")
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
def relabel_postgresql_dir
|
166
|
+
AwesomeSpawn.run!("/sbin/restorecon -R -v #{mount_point}")
|
167
|
+
end
|
168
|
+
|
169
|
+
def with_pg_connection
|
170
|
+
conn = PG.connect(:user => "postgres", :dbname => "postgres")
|
171
|
+
yield conn
|
172
|
+
ensure
|
173
|
+
conn.close
|
174
|
+
end
|
175
|
+
|
176
|
+
def apply_initial_configuration
|
177
|
+
shared_buffers = run_as_evm_server ? SHARED_DB_SHARED_BUFFERS : DEDICATED_DB_SHARED_BUFFERS
|
178
|
+
with_pg_connection do |conn|
|
179
|
+
conn.exec("ALTER SYSTEM SET ssl TO on") if ssl
|
180
|
+
conn.exec("ALTER SYSTEM SET shared_buffers TO #{shared_buffers}")
|
181
|
+
end
|
182
|
+
|
183
|
+
restart_postgres
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
@@ -0,0 +1,118 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
require 'fileutils'
|
3
|
+
require 'net/scp'
|
4
|
+
require 'active_support/all'
|
5
|
+
require 'util/miq-password'
|
6
|
+
|
7
|
+
module ManageIQ
|
8
|
+
module ApplianceConsole
|
9
|
+
CERT_DIR = ENV['KEY_ROOT'] || ManageIQ::ApplianceConsole::RAILS_ROOT.join("certs")
|
10
|
+
KEY_FILE = "#{CERT_DIR}/v2_key".freeze
|
11
|
+
NEW_KEY_FILE = "#{KEY_FILE}.tmp".freeze
|
12
|
+
|
13
|
+
class KeyConfiguration
|
14
|
+
attr_accessor :host, :login, :password, :key_path, :action, :force
|
15
|
+
|
16
|
+
def initialize(options = {})
|
17
|
+
options.each { |k, v| public_send("#{k}=", v) }
|
18
|
+
@action ||= :create
|
19
|
+
@login ||= "root"
|
20
|
+
@key_path ||= KEY_FILE
|
21
|
+
end
|
22
|
+
|
23
|
+
def ask_questions
|
24
|
+
if key_exist?
|
25
|
+
@force = agree("Overwrite existing encryption key (v2_key)? (Y/N): ")
|
26
|
+
return false unless @force
|
27
|
+
end
|
28
|
+
|
29
|
+
@action = ask_for_action(@action)
|
30
|
+
|
31
|
+
if fetch_key?
|
32
|
+
say("")
|
33
|
+
@host = ask_for_ip_or_hostname("hostname for appliance with encryption key", @host)
|
34
|
+
@login = ask_for_string("appliance SSH login", @login)
|
35
|
+
@password = ask_for_password("appliance SSH password", @password)
|
36
|
+
@key_path = ask_for_string("path of remote encryption key", @key_path)
|
37
|
+
end
|
38
|
+
@action
|
39
|
+
end
|
40
|
+
|
41
|
+
def ask_question_loop
|
42
|
+
loop do
|
43
|
+
return false unless ask_questions
|
44
|
+
return true if activate
|
45
|
+
return false unless agree("Try again? (Y/N) ")
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def activate
|
50
|
+
if !key_exist? || force
|
51
|
+
if get_new_key
|
52
|
+
save_new_key
|
53
|
+
else
|
54
|
+
remove_new_key_if_any
|
55
|
+
false
|
56
|
+
end
|
57
|
+
else
|
58
|
+
# probably only got here via the cli
|
59
|
+
$stderr.puts
|
60
|
+
$stderr.puts "Only generate one encryption key (v2_key) per installation."
|
61
|
+
$stderr.puts "Chances are you did not want to overwrite this file."
|
62
|
+
$stderr.puts "If you do this all encrypted secrets in the database will not be readable."
|
63
|
+
$stderr.puts "Please backup your key and run this command again with --force-key."
|
64
|
+
$stderr.puts
|
65
|
+
false
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def save_new_key
|
70
|
+
begin
|
71
|
+
FileUtils.mv(NEW_KEY_FILE, KEY_FILE, :force => true)
|
72
|
+
rescue => e
|
73
|
+
say("Failed to overwrite original key, original key kept. #{e.message}")
|
74
|
+
return false
|
75
|
+
end
|
76
|
+
FileUtils.chmod(0o400, KEY_FILE)
|
77
|
+
end
|
78
|
+
|
79
|
+
def remove_new_key_if_any
|
80
|
+
FileUtils.rm(NEW_KEY_FILE) if File.exist?(NEW_KEY_FILE)
|
81
|
+
end
|
82
|
+
|
83
|
+
def key_exist?
|
84
|
+
File.exist?(KEY_FILE)
|
85
|
+
end
|
86
|
+
|
87
|
+
def fetch_key?
|
88
|
+
@action == :fetch
|
89
|
+
end
|
90
|
+
|
91
|
+
def create_key
|
92
|
+
MiqPassword.generate_symmetric(NEW_KEY_FILE) && true
|
93
|
+
end
|
94
|
+
|
95
|
+
def fetch_key
|
96
|
+
# use :verbose => 1 (or :debug for later versions) to see actual errors
|
97
|
+
Net::SCP.start(host, login, :password => password) do |scp|
|
98
|
+
scp.download!(key_path, NEW_KEY_FILE)
|
99
|
+
end
|
100
|
+
File.exist?(NEW_KEY_FILE)
|
101
|
+
rescue => e
|
102
|
+
say("Failed to fetch key: #{e.message}")
|
103
|
+
false
|
104
|
+
end
|
105
|
+
|
106
|
+
private
|
107
|
+
|
108
|
+
def ask_for_action(default_action)
|
109
|
+
options = {'Create key' => :create, 'Fetch key from remote machine' => :fetch}
|
110
|
+
ask_with_menu("Encryption Key", options, default_action, false)
|
111
|
+
end
|
112
|
+
|
113
|
+
def get_new_key
|
114
|
+
fetch_key? ? fetch_key : create_key
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
require 'linux_admin'
|
2
|
+
require 'pathname'
|
3
|
+
require 'fileutils'
|
4
|
+
require 'util/miq-system.rb'
|
5
|
+
|
6
|
+
module ManageIQ
|
7
|
+
module ApplianceConsole
|
8
|
+
class LogfileConfiguration
|
9
|
+
LOGFILE_DIRECTORY = Pathname.new("/var/www/miq/vmdb/log").freeze
|
10
|
+
LOGFILE_NAME = "miq_logs".freeze
|
11
|
+
MIQ_LOGS_CONF = Pathname.new("/etc/logrotate.d/miq_logs.conf").freeze
|
12
|
+
|
13
|
+
attr_accessor :size, :disk, :current_logrotate_count, :new_logrotate_count, :evm_was_running
|
14
|
+
|
15
|
+
include ManageIQ::ApplianceConsole::Logging
|
16
|
+
|
17
|
+
def initialize(config = {})
|
18
|
+
self.disk = config[:disk]
|
19
|
+
self.new_logrotate_count = nil
|
20
|
+
|
21
|
+
self.size = MiqSystem.disk_usage(LOGFILE_DIRECTORY)[0][:total_bytes]
|
22
|
+
self.current_logrotate_count = /rotate\s+(\d+)/.match(File.read(MIQ_LOGS_CONF))[1]
|
23
|
+
self.evm_was_running = LinuxAdmin::Service.new("evmserverd").running?
|
24
|
+
end
|
25
|
+
|
26
|
+
def activate
|
27
|
+
activate_new_disk && activate_new_logrotate_count
|
28
|
+
end
|
29
|
+
|
30
|
+
def ask_questions
|
31
|
+
clear_screen
|
32
|
+
choose_disk if use_new_disk
|
33
|
+
choose_logrotate_count if set_new_logrotate_count?
|
34
|
+
confirm_selection
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def confirm_selection
|
40
|
+
return false unless disk || new_logrotate_count
|
41
|
+
|
42
|
+
clear_screen
|
43
|
+
if disk
|
44
|
+
say("\t#{disk.path} with #{disk.size.to_i / 1.gigabyte} GB will be configured as the new logfile disk.")
|
45
|
+
end
|
46
|
+
|
47
|
+
if new_logrotate_count
|
48
|
+
say("\tThe number of saved logratations will be updated to: #{new_logrotate_count}")
|
49
|
+
end
|
50
|
+
|
51
|
+
agree("Confirm continue with these updates (Y/N):")
|
52
|
+
end
|
53
|
+
|
54
|
+
def use_new_disk
|
55
|
+
agree("Configure a new logfile disk volume? (Y/N):")
|
56
|
+
end
|
57
|
+
|
58
|
+
def choose_disk
|
59
|
+
self.disk = ask_for_disk("logfile disk")
|
60
|
+
end
|
61
|
+
|
62
|
+
def set_new_logrotate_count?
|
63
|
+
agree("Change the saved logrotate count from #{current_logrotate_count}? (Y/N):")
|
64
|
+
end
|
65
|
+
|
66
|
+
def choose_logrotate_count
|
67
|
+
say "\t1 GB of disk space is recommended for each saved log rotation."
|
68
|
+
if disk
|
69
|
+
say "\tThe proposed new disk is #{disk.size.to_i / 1.gigabyte} GB"
|
70
|
+
else
|
71
|
+
say "\tThe current log disk is #{size.to_i / 1.gigabyte} GB"
|
72
|
+
end
|
73
|
+
|
74
|
+
self.new_logrotate_count = ask_for_integer("new log rotate count")
|
75
|
+
end
|
76
|
+
|
77
|
+
def activate_new_logrotate_count
|
78
|
+
return true unless new_logrotate_count
|
79
|
+
say 'Activating new logrotate count'
|
80
|
+
data = File.read(MIQ_LOGS_CONF)
|
81
|
+
data.gsub!(/rotate\s+\d+/, "rotate #{new_logrotate_count}")
|
82
|
+
File.write(MIQ_LOGS_CONF, data)
|
83
|
+
true
|
84
|
+
end
|
85
|
+
|
86
|
+
def activate_new_disk
|
87
|
+
return true unless disk
|
88
|
+
stop_evm if evm_was_running
|
89
|
+
initialize_logfile_disk
|
90
|
+
start_evm if evm_was_running
|
91
|
+
true
|
92
|
+
end
|
93
|
+
|
94
|
+
def initialize_logfile_disk
|
95
|
+
say 'Initializing logfile disk'
|
96
|
+
LogicalVolumeManagement.new(:disk => disk, :mount_point => LOGFILE_DIRECTORY, :name => LOGFILE_NAME).setup
|
97
|
+
|
98
|
+
FileUtils.mkdir_p("#{LOGFILE_DIRECTORY}/apache")
|
99
|
+
AwesomeSpawn.run!('/usr/sbin/semanage fcontext -a -t httpd_log_t "#{LOGFILE_DIRECTORY.to_path}(/.*)?"')
|
100
|
+
AwesomeSpawn.run!("/sbin/restorecon -R -v #{LOGFILE_DIRECTORY.to_path}") if File.executable?("/sbin/restorecon")
|
101
|
+
true
|
102
|
+
end
|
103
|
+
|
104
|
+
def start_evm
|
105
|
+
say 'Starting EVM'
|
106
|
+
LinuxAdmin::Service.new("evmserverd").enable.start
|
107
|
+
LinuxAdmin::Service.new("httpd").enable.start
|
108
|
+
end
|
109
|
+
|
110
|
+
def stop_evm
|
111
|
+
say 'Stopping EVM'
|
112
|
+
LinuxAdmin::Service.new("evmserverd").stop
|
113
|
+
LinuxAdmin::Service.new("httpd").stop
|
114
|
+
end
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'logger'
|
2
|
+
|
3
|
+
module ManageIQ
|
4
|
+
module ApplianceConsole
|
5
|
+
class Logger < ::Logger
|
6
|
+
def self.log_dir
|
7
|
+
@log_dir ||= ManageIQ::ApplianceConsole::RAILS_ROOT.join("log")
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.log_file
|
11
|
+
@log_file ||= log_dir.join("appliance_console.log").to_s
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.instance
|
15
|
+
@instance ||= begin
|
16
|
+
require 'fileutils'
|
17
|
+
FileUtils.mkdir_p(log_dir.to_s)
|
18
|
+
new(log_file).tap { |l| l.level = Logger::INFO }
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
require 'awesome_spawn'
|
2
|
+
require 'active_support/all'
|
3
|
+
|
4
|
+
module ManageIQ
|
5
|
+
module ApplianceConsole
|
6
|
+
module Logging
|
7
|
+
class << self
|
8
|
+
attr_accessor :interactive
|
9
|
+
|
10
|
+
def interactive?
|
11
|
+
@interactive != false
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def interactive=(interactive)
|
16
|
+
ManageIQ::ApplianceConsole::Logging.interactive = interactive
|
17
|
+
end
|
18
|
+
|
19
|
+
def interactive?
|
20
|
+
ManageIQ::ApplianceConsole::Logging.interactive?
|
21
|
+
end
|
22
|
+
|
23
|
+
def interactive
|
24
|
+
ManageIQ::ApplianceConsole::Logging.interactive
|
25
|
+
end
|
26
|
+
|
27
|
+
def logger=(logger)
|
28
|
+
ManageIQ::ApplianceConsole.logger = logger
|
29
|
+
end
|
30
|
+
|
31
|
+
def logger
|
32
|
+
ManageIQ::ApplianceConsole.logger
|
33
|
+
end
|
34
|
+
|
35
|
+
# TODO: move say_error and say_info to prompting module?
|
36
|
+
def say_error(method, output)
|
37
|
+
log = "\nSee #{ManageIQ::ApplianceConsole::Logger.log_file} for details."
|
38
|
+
text = "#{method.to_s.humanize} failed with error - #{output.truncate(200)}.#{log}"
|
39
|
+
say(text)
|
40
|
+
press_any_key if interactive?
|
41
|
+
raise ManageIQ::ApplianceConsole::MiqSignalError
|
42
|
+
end
|
43
|
+
|
44
|
+
def say_info(method, output)
|
45
|
+
say("#{method.to_s.humanize} #{output}")
|
46
|
+
end
|
47
|
+
|
48
|
+
def log_and_feedback(method)
|
49
|
+
raise ArgumentError, "No block given" unless block_given?
|
50
|
+
|
51
|
+
log_and_feedback_info(method, "starting")
|
52
|
+
|
53
|
+
result = nil
|
54
|
+
begin
|
55
|
+
result = yield
|
56
|
+
rescue => err
|
57
|
+
log_and_feedback_exception(err, method)
|
58
|
+
else
|
59
|
+
log_and_feedback_info(method, "complete")
|
60
|
+
end
|
61
|
+
result
|
62
|
+
end
|
63
|
+
|
64
|
+
def log_prefix(method)
|
65
|
+
"MIQ(#{self.class.name}##{method}) "
|
66
|
+
end
|
67
|
+
|
68
|
+
def log_and_feedback_info(method, message)
|
69
|
+
logger.info("#{log_prefix(method)}: #{message}")
|
70
|
+
say_info(method, message)
|
71
|
+
end
|
72
|
+
|
73
|
+
def log_and_feedback_exception(error, failed_method)
|
74
|
+
feedback_error, logging = case error
|
75
|
+
when AwesomeSpawn::CommandResultError
|
76
|
+
error_and_logging_from_command_result_error(error)
|
77
|
+
else
|
78
|
+
error_and_logging_from_standard_error(error)
|
79
|
+
end
|
80
|
+
|
81
|
+
log_error(failed_method, logging)
|
82
|
+
say_error(failed_method, feedback_error)
|
83
|
+
end
|
84
|
+
|
85
|
+
def error_and_logging_from_command_result_error(error)
|
86
|
+
result = error.result
|
87
|
+
location = error.backtrace.detect { |loc| !loc.match(/(linux_admin|awesome_spawn)/) }
|
88
|
+
return error.message, "Command failed: #{error.message}. Error: #{result.error}. Output: #{result.output}. At: #{location}"
|
89
|
+
end
|
90
|
+
|
91
|
+
def error_and_logging_from_standard_error(error)
|
92
|
+
debugging = "Error: #{error.class.name} with message: #{error.message}"
|
93
|
+
logging = "#{debugging}. Failed at: #{error.backtrace[0]}"
|
94
|
+
return debugging, logging
|
95
|
+
end
|
96
|
+
|
97
|
+
def log_error(failed_method, debugging)
|
98
|
+
logger.error("#{log_prefix(failed_method)} #{debugging}")
|
99
|
+
end
|
100
|
+
end # module Logging
|
101
|
+
end # module ApplicationConsole
|
102
|
+
end
|