ManageIQ/manageiq-appliance_console

View on GitHub
bin/appliance_console

Summary

Maintainability
Test Coverage
#!/usr/bin/env ruby
# description: ManageIQ appliance console
#
 
require 'bundler'
Bundler.setup
 
require 'manageiq/appliance_console'
 
require 'fileutils'
# defines globally /via kernal: agree(), ask(), choose() and say()
require 'highline/import'
require 'rubygems'
require 'bcrypt'
require 'linux_admin'
require 'awesome_spawn'
 
require 'manageiq/appliance_console/i18n'
 
HighLine.default_instance.tap do |highline|
highline.wrap_at = 80
highline.page_at = 35
end
 
def summary_entry(field, value)
dfield = "#{field}:"
"#{dfield.ljust(24)} #{value}"
end
 
def ensure_key_configured
key_config = ManageIQ::ApplianceConsole::KeyConfiguration.new
unless key_config.key_exist?
say "No encryption key found.\n"
say "For migrations, copy encryption key from a hardened appliance."
say "For worker and multi-region setups, copy key from another appliance.\n"
say "If this is your first appliance, just generate one now.\n\n"
 
if key_config.ask_question_loop
say("\nEncryption key now configured.\n\n")
else
say("\nEncryption key not configured.")
press_any_key
raise ManageIQ::ApplianceConsole::MiqSignalError
end
end
end
 
[:INT, :TERM, :ABRT, :TSTP].each { |s| trap(s) { raise ManageIQ::ApplianceConsole::MiqSignalError } }
 
VERSION_FILE = ManageIQ::ApplianceConsole::RAILS_ROOT.join("VERSION")
LOGFILE = ManageIQ::ApplianceConsole::RAILS_ROOT.join("log", "appliance_console.log")
DB_RESTORE_FILE = "/tmp/evm_db.backup".freeze
 
AS_OPTIONS = I18n.t("advanced_settings.menu_order").collect do |item|
I18n.t("advanced_settings.#{item}")
end
 
require 'manageiq-password'
ManageIQ::Password.key_root = ManageIQ::ApplianceConsole::RAILS_ROOT.join("certs").to_s
 
# Load appliance_console libraries
include ManageIQ::ApplianceConsole::Prompts
 
# Restore database choices
RESTORE_LOCAL = "Local file".freeze
RESTORE_NFS = "Network File System (NFS)".freeze
RESTORE_SMB = "Samba (SMB)".freeze
RESTORE_OPTIONS = [RESTORE_LOCAL, RESTORE_NFS, RESTORE_SMB, ManageIQ::ApplianceConsole::CANCEL].freeze
 
# Restart choices
RE_RESTART = "Restart".freeze
RE_DELLOGS = "Restart and Clean Logs".freeze
RE_OPTIONS = [RE_RESTART, RE_DELLOGS, ManageIQ::ApplianceConsole::CANCEL].freeze
 
CLOUD_INIT_NETWORK_CONFIG_FILE = "/etc/cloud/cloud.cfg.d/99_miq_disable_network_config.cfg".freeze
CLOUD_INIT_DISABLE_NETWORK_CONFIG = "network: {config: disabled}\n".freeze
 
module ManageIQ
module ApplianceConsole
# Get a list of network interfaces
nics = LinuxAdmin::NetworkInterface.list.reject(&:loopback?)
# Because it takes a few seconds, get the region once in the outside loop
region = ManageIQ::ApplianceConsole::DatabaseConfiguration.region
 
# Calling stty to provide the equivalent line settings when the console is run via an ssh session or
# over the virtual machine console.
system("stty -echoprt ixany iexten echoe echok")
 
loop do
begin
dns = LinuxAdmin::Dns.new
host = LinuxAdmin::Hosts.new.hostname
dns1, dns2 = dns.nameservers
order = dns.search_order.join(' ')
timezone = LinuxAdmin::TimeDate.system_timezone
version = File.read(VERSION_FILE).chomp if File.exist?(VERSION_FILE)
dbhost = ManageIQ::ApplianceConsole::DatabaseConfiguration.database_host
database = ManageIQ::ApplianceConsole::DatabaseConfiguration.database_name
messaging = ManageIQ::ApplianceConsole::MessageConfiguration.configured?
messaging_broker = ManageIQ::ApplianceConsole::MessageServerConfiguration.configured?
evm_status = if ManageIQ::ApplianceConsole::EvmServer.running?
"running"
elsif ManageIQ::ApplianceConsole::EvmServer.runnable?
"not running"
else
"not configured"
end
 
summary_attributes = [summary_entry("Hostname", host)]
 
nics.each(&:reload)
nics.each do |nic|
next if nic.address.nil? && nic.address6.nil?
 
summary_attributes += [
summary_entry("#{nic.interface} IPv4 Address", "#{nic.address}/#{nic.prefix}"),
summary_entry("#{nic.interface} IPv4 Gateway", nic.gateway),
summary_entry("#{nic.interface} IPv6 Address", nic.address6 ? "#{nic.address6}/#{nic.prefix6}" : ""),
summary_entry("#{nic.interface} IPv6 Gateway", nic.gateway6),
summary_entry("#{nic.interface} MAC Address", nic.mac_address)
]
end
 
summary_attributes += [
summary_entry("Primary DNS", dns1),
summary_entry("Secondary DNS", dns2),
summary_entry("Search Order", order),
summary_entry("Timezone", timezone),
summary_entry("Local Database Server", PostgresAdmin.local_server_status),
summary_entry("#{I18n.t("product.name")} Server", evm_status),
summary_entry("#{I18n.t("product.name")} Database", dbhost || "not configured"),
summary_entry("Database/Region", database ? "#{database} / #{region.to_i}" : "not configured"),
summary_entry("Messaging", messaging ? "configured" : "not configured"),
summary_entry("Local Messaging Broker", messaging_broker ? "configured" : "not configured"),
summary_entry("External Auth", ExternalHttpdAuthentication.config_status),
summary_entry("#{I18n.t("product.name")} Version", version),
]
 
clear_screen
 
say(<<-EOL)
Welcome to the #{I18n.t("product.name")} Virtual Appliance.
 
To modify the configuration, use a web browser to access the management page.
 
#{HighLine.default_instance.list(summary_attributes)}
EOL
 
press_any_key
 
clear_screen
selection = ask_with_menu("Advanced Setting", AS_OPTIONS, nil, true)
case selection
when I18n.t("advanced_settings.httpdauth")
say("#{selection}\n\n")
 
httpd_auth = ExternalHttpdAuthentication.new(host)
if httpd_auth.ask_questions && httpd_auth.activate
httpd_auth.post_activation
say("\nExternal Authentication configured successfully.\n")
press_any_key
else
say("\nExternal Authentication configuration failed!\n")
press_any_key
raise MiqSignalError
end
 
when I18n.t("advanced_settings.extauth_opts")
say("#{selection}\n\n")
 
extauth_options = ExternalAuthOptions.new
if extauth_options.ask_questions && extauth_options.any_updates?
extauth_options.update_configuration
say("\nExternal Authentication Options updated successfully.\n")
else
say("\nExternal Authentication Options not updated.\n")
end
press_any_key
 
when I18n.t("advanced_settings.evmstop")
say("#{selection}\n\n")
if ManageIQ::ApplianceConsole::EvmServer.running?
if ask_yn? "\nNote: It may take up to a few minutes for all #{I18n.t("product.name")} server processes to exit gracefully. Stop #{I18n.t("product.name")}"
say("\nStopping #{I18n.t("product.name")} Server...")
logger.info("EVM server stop initiated by appliance console.")
ManageIQ::ApplianceConsole::EvmServer.stop
end
else
say("\n#{I18n.t("product.name")} Server is not running...")
end
press_any_key
 
when I18n.t("advanced_settings.evmstart")
say("#{selection}\n\n")
if ask_yn?("\nStart #{I18n.t("product.name")}")
say("\nStarting #{I18n.t("product.name")} Server...")
logger.info("EVM server start initiated by appliance console.")
ManageIQ::ApplianceConsole::EvmServer.start
press_any_key
end
 
when I18n.t("advanced_settings.dbbackup")
db_admin = ManageIQ::ApplianceConsole::DatabaseAdmin.new(:backup)
db_admin.ask_questions && db_admin.activate
 
when I18n.t("advanced_settings.dbdump")
db_admin = ManageIQ::ApplianceConsole::DatabaseAdmin.new(:dump)
db_admin.ask_questions && db_admin.activate
 
when I18n.t("advanced_settings.dbrestore")
db_admin = ManageIQ::ApplianceConsole::DatabaseAdmin.new(:restore)
db_admin.ask_questions && db_admin.activate
 
when I18n.t("advanced_settings.key_gen")
say("#{selection}\n\n")
 
key_config = ManageIQ::ApplianceConsole::KeyConfiguration.new
if key_config.ask_question_loop
say("\nEncryption key now configured.")
press_any_key
else
say("\nEncryption key not configured.")
press_any_key
raise MiqSignalError
end
 
when I18n.t("advanced_settings.app_config")
say("#{selection}\n\n")
 
ensure_key_configured
 
options = {
"Create Internal Database" => "create_internal",
"Create Region in External Database" => "create_external",
"Join Region in External Database" => "join_external",
"Reset Configured Database" => "reset_region",
"Make No Database Changes" => "no_changes"
}
database_action = ask_with_menu("Database Operation", options)
 
messaging_options = {
"Configure this appliance as a messaging server" => "message_server",
"Connect to an external messaging system" => "message_client",
"Make No messaging changes" => "no_changes"
}
 
messaging_action = ask_with_menu("Configure Messaging", messaging_options)
 
changes_requested = database_action != "no_changes" || messaging_action != "no_changes"
 
# Stop evmserver while we make changes to the database and/or messaging configuration
if changes_requested
say("\nStopping #{I18n.t("product.name")} Server...")
ManageIQ::ApplianceConsole::EvmServer.stop
end
 
database_configuration =
case database_action
when "create_internal"
ManageIQ::ApplianceConsole::InternalDatabaseConfiguration.new
when /_external/
ManageIQ::ApplianceConsole::ExternalDatabaseConfiguration.new(:action => database_action.split("_").first.to_sym)
else
ManageIQ::ApplianceConsole::DatabaseConfiguration.new
end
 
case database_action
when "reset_region"
if database_configuration.reset_region
say("Database reset successfully")
say("Start the server processes via '#{I18n.t("advanced_settings.evmstart")}'.")
else
say("Failed to reset database")
end
when "create_internal", /_external/
database_configuration.run_interactive
end
# Get the region again because it may have changed
region = ManageIQ::ApplianceConsole::DatabaseConfiguration.region
 
case messaging_action
when "message_server"
say("#{selection}\n\n")
 
message_server = MessageServerConfiguration.new
if !MessageServerConfiguration.available?
say("\nMessage Server configuration is unavailable!\n")
press_any_key
raise MiqSignalError
elsif message_server.ask_questions && message_server.configure
say("\nMessage Server configured successfully.\n")
else
say("\nMessage Server configuration failed!\n")
press_any_key
raise MiqSignalError
end
when "message_client"
say("#{selection}\n\n")
 
message_client = MessageClientConfiguration.new
if !MessageClientConfiguration.available?
say("\nMessage Client configuration is unavailable!\n")
press_any_key
raise MiqSignalError
elsif message_client.ask_questions && message_client.configure
say("\nMessage Client configured successfully.\n")
else
say("\nMessage Client configuration failed!\n")
press_any_key
raise MiqSignalError
end
end
 
# Start evmserverd if database and/or messaging were set up and we are supposed to run as an evmserver
if changes_requested && database_configuration.run_as_evm_server
say("\nStarting #{I18n.t("product.name")} Server...")
ManageIQ::ApplianceConsole::EvmServer.start(:enable => true)
end
 
press_any_key
 
when I18n.t("advanced_settings.db_replication")
say("#{selection}\n\n")
 
options = {
"Configure Server as Primary" => "primary",
"Configure Server as Standby" => "standby"
}
 
action = ask_with_menu("Database replication Operation", options)
 
case action
when "primary"
db_replication = ManageIQ::ApplianceConsole::DatabaseReplicationPrimary.new
logger.info("Configuring Server as Primary")
when "standby"
db_replication = ManageIQ::ApplianceConsole::DatabaseReplicationStandby.new
logger.info("Configuring Server as Standby")
ensure_key_configured
end
 
if db_replication.ask_questions && db_replication.activate
say("Database Replication configured")
logger.info("Database Replication configured")
press_any_key
else
say("Database Replication not configured")
logger.info("Database Replication not configured")
press_any_key
raise MiqSignalError
end
when I18n.t("advanced_settings.failover_monitor")
say("#{selection}\n\n")
 
options = {
"Start Database Failover Monitor" => "start",
"Stop Database Failover Monitor" => "stop"
}
 
action = ask_with_menu("Failover Monitor Configuration", options)
failover_service = LinuxAdmin::Service.new("evm-failover-monitor")
 
begin
case action
when "start"
logger.info("Starting and enabling evm-failover-monitor service")
failover_service.enable.start
when "stop"
logger.info("Stopping and disabling evm-failover-monitor service")
failover_service.disable.stop
end
rescue AwesomeSpawn::CommandResultError => e
say("Failed to configure failover monitor")
logger.error("Failed to configure evm-failover-monitor service")
say(e.result.output)
say(e.result.error)
say("")
press_any_key
raise MiqSignalError
end
 
say("Failover Monitor Service configured successfully")
press_any_key
 
when I18n.t("advanced_settings.log_config")
say("#{selection}\n\n")
log_config = ManageIQ::ApplianceConsole::LogfileConfiguration.new
if log_config.ask_questions && log_config.activate
say("Log file configuration updated.")
say("The appliance may take a few minutes to fully restart.")
press_any_key
else
say("Log file configuration unchanged")
press_any_key
raise MiqSignalError
end
 
when I18n.t("advanced_settings.tmp_config")
say("#{selection}\n\n")
tmp_config = ManageIQ::ApplianceConsole::TempStorageConfiguration.new
if tmp_config.ask_questions && tmp_config.activate
say("Temp storage disk configured")
press_any_key
else
say("Temp storage disk not configured")
press_any_key
raise MiqSignalError
end
 
when I18n.t("advanced_settings.restart")
case ask_with_menu("Restart Option", RE_OPTIONS, nil, false)
when ManageIQ::ApplianceConsole::CANCEL
# don't do anything
when RE_RESTART
if are_you_sure?("restart the appliance now")
logger.info("Appliance restart initiated by appliance console.")
ManageIQ::ApplianceConsole::EvmServer.stop
LinuxAdmin::System.reboot!
end
when RE_DELLOGS
if are_you_sure?("restart the appliance now")
logger.info("Appliance restart with clean logs initiated by appliance console.")
ManageIQ::ApplianceConsole::EvmServer.stop
LinuxAdmin::Service.new("miqtop").stop
LinuxAdmin::Service.new("miqvmstat").stop
LinuxAdmin::Service.new("httpd").stop
FileUtils.rm_rf(Dir.glob("/var/www/miq/vmdb/log/*.log*"))
FileUtils.rm_rf(Dir.glob("/var/www/miq/vmdb/log/apache/*.log*"))
logger.info("Logs cleaned and appliance rebooted by appliance console.")
LinuxAdmin::System.reboot!
end
end
 
when I18n.t("advanced_settings.shutdown")
say("#{selection}\n\n")
if are_you_sure?("shut down the appliance now")
say("\nShutting down appliance... This process may take a few minutes.\n\n")
logger.info("Appliance shutdown initiated by appliance console")
ManageIQ::ApplianceConsole::EvmServer.stop
LinuxAdmin::System.shutdown!
end
 
when I18n.t("advanced_settings.scap")
say("#{selection}\n\n")
ManageIQ::ApplianceConsole::Scap.new.lockdown
press_any_key
 
when I18n.t("advanced_settings.summary")
# Do nothing
 
when I18n.t("advanced_settings.quit")
break
end
rescue MiqSignalError
# If a signal is caught anywhere in the inner (after login) loop, go back to the summary screen
next
end
end
end
end