Class: ManageIQ::ApplianceConsole::DatabaseConfiguration

Inherits:
Object
  • Object
show all
Includes:
Logging, ManageiqUserMixin
Defined in:
lib/manageiq/appliance_console/database_configuration.rb

Defined Under Namespace

Classes: ModelWithNoBackingTable

Constant Summary collapse

DB_YML =
ManageIQ::ApplianceConsole::RAILS_ROOT.join("config/database.yml")
DB_YML_TMPL =
ManageIQ::ApplianceConsole::RAILS_ROOT.join("config/database.pg.yml")
CREATE_REGION_AGREE =
"WARNING: Creating a database region will destroy any existing data and cannot be undone.\n\nAre you sure you want to continue? (Y/N):".freeze
FAILED_WITH_ERROR_HYPHEN =
"failed with error -".freeze
REGION_RANGE =

PG 9.2 bigint max 9223372036854775807 / ArRegion::DEFAULT_RAILS_SEQUENCE_FACTOR = 9223372 www.postgresql.org/docs/9.2/static/datatype-numeric.html 9223372 won’t be a full region though, so we’re not including it. TODO: This information should be shared outside of appliance console code and MiqRegion.

0..9223371
DEFAULT_PORT =
5432

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Logging

#error_and_logging_from_command_result_error, #error_and_logging_from_standard_error, #interactive, #interactive=, interactive?, #interactive?, #log_and_feedback, #log_and_feedback_exception, #log_and_feedback_info, #log_error, #log_prefix, #logger, #logger=, #say_error, #say_info

Methods included from ManageiqUserMixin

#manageiq_gid, #manageiq_uid, #run_as_manageiq!

Constructor Details

#initialize(hash = {}) ⇒ DatabaseConfiguration

Returns a new instance of DatabaseConfiguration.



36
37
38
39
40
41
42
# File 'lib/manageiq/appliance_console/database_configuration.rb', line 36

def initialize(hash = {})
  initialize_from_hash(hash)
  @adapter ||= "postgresql"
  # introduced by Logging
  self.interactive = true unless hash.key?(:interactive)
  self.run_as_evm_server = true unless hash.key?(:run_as_evm_server)
end

Instance Attribute Details

#adapterObject

Returns the value of attribute adapter.



15
16
17
# File 'lib/manageiq/appliance_console/database_configuration.rb', line 15

def adapter
  @adapter
end

#databaseObject

Returns the value of attribute database.



15
16
17
# File 'lib/manageiq/appliance_console/database_configuration.rb', line 15

def database
  @database
end

#hostObject

Returns the value of attribute host.



15
16
17
# File 'lib/manageiq/appliance_console/database_configuration.rb', line 15

def host
  @host
end

#passwordObject

Returns the value of attribute password.



16
17
18
# File 'lib/manageiq/appliance_console/database_configuration.rb', line 16

def password
  @password
end

#portObject

Returns the value of attribute port.



15
16
17
# File 'lib/manageiq/appliance_console/database_configuration.rb', line 15

def port
  @port
end

#regionObject

Returns the value of attribute region.



15
16
17
# File 'lib/manageiq/appliance_console/database_configuration.rb', line 15

def region
  @region
end

#run_as_evm_serverObject

Returns the value of attribute run_as_evm_server.



15
16
17
# File 'lib/manageiq/appliance_console/database_configuration.rb', line 15

def run_as_evm_server
  @run_as_evm_server
end

#usernameObject

Returns the value of attribute username.



15
16
17
# File 'lib/manageiq/appliance_console/database_configuration.rb', line 15

def username
  @username
end

Class Method Details

.currentObject



177
178
179
# File 'lib/manageiq/appliance_console/database_configuration.rb', line 177

def self.current
  decrypt_password(load_current)
end

.database_hostObject



185
186
187
# File 'lib/manageiq/appliance_console/database_configuration.rb', line 185

def self.database_host
  database_yml_configured? ? current[rails_env]['host'] || "localhost" : nil
end

.database_nameObject



189
190
191
# File 'lib/manageiq/appliance_console/database_configuration.rb', line 189

def self.database_name
  database_yml_configured? ? current[rails_env]['database'] : nil
end

.database_yml_configured?Boolean

Returns:

  • (Boolean)


181
182
183
# File 'lib/manageiq/appliance_console/database_configuration.rb', line 181

def self.database_yml_configured?
  File.exist?(DB_YML) && File.exist?(KEY_FILE)
end

.decrypt_password(settings) ⇒ Object



173
174
175
# File 'lib/manageiq/appliance_console/database_configuration.rb', line 173

def self.decrypt_password(settings)
  encrypt_decrypt_password(settings) { |pass| ManageIQ::Password.try_decrypt(pass) }
end

.encrypt_decrypt_password(settings) ⇒ Object



221
222
223
224
225
226
227
# File 'lib/manageiq/appliance_console/database_configuration.rb', line 221

def self.encrypt_decrypt_password(settings)
  new_settings = {}
  settings.each_key { |section| new_settings[section] = settings[section].dup }
  pass = new_settings["production"]["password"]
  new_settings["production"]["password"] = yield(pass) if pass
  new_settings
end

.encrypt_password(settings) ⇒ Object



169
170
171
# File 'lib/manageiq/appliance_console/database_configuration.rb', line 169

def self.encrypt_password(settings)
  encrypt_decrypt_password(settings) { |pass| ManageIQ::Password.try_encrypt(pass) }
end

.load_currentObject



229
230
231
232
233
234
235
236
237
238
239
240
241
242
# File 'lib/manageiq/appliance_console/database_configuration.rb', line 229

def self.load_current
  require 'yaml'
  unless File.exist?(DB_YML)
    require 'fileutils'
    FileUtils.cp(DB_YML_TMPL, DB_YML) if File.exist?(DB_YML_TMPL)
  end

  data = File.read(DB_YML)
  if YAML.respond_to?(:safe_load)
    YAML.safe_load(data, :aliases => true)
  else
    YAML.load(data) # rubocop:disable Security/YAMLLoad
  end
end

.regionObject



193
194
195
# File 'lib/manageiq/appliance_console/database_configuration.rb', line 193

def self.region
  database_yml_configured? ? ManageIQ::ApplianceConsole::Utilities.db_region : nil
end

Instance Method Details

#activateObject



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/manageiq/appliance_console/database_configuration.rb', line 67

def activate
  return false unless validated

  original = self.class.current
  success  = false

  begin
    save
    success = create_or_join_region
    validate_encryption_key!
  rescue
    success = false
  ensure
    save(original) unless success
  end
end

#ask_for_database_credentials(password_twice = true) ⇒ Object



119
120
121
122
123
124
125
# File 'lib/manageiq/appliance_console/database_configuration.rb', line 119

def ask_for_database_credentials(password_twice = true)
  self.host     = ask_for_ip_or_hostname("database hostname or IP address", host) if host.blank? || !local?
  self.port     = ask_for_integer("port number", nil, port) unless local?
  self.database = just_ask("name of the database on #{host}", database) unless local?
  self.username = just_ask("username", username) unless local?
  self.password = ask_for_new_password("database password on #{host}", :default => password, :confirm_password => password_twice)
end

#create_new_region_questions(warn = true) ⇒ Object

Raises:



111
112
113
114
115
116
117
# File 'lib/manageiq/appliance_console/database_configuration.rb', line 111

def create_new_region_questions(warn = true)
  clear_screen
  say("\n\nNote: Creating a new database region requires an empty database.") if warn
  say("Each database region number must be unique.\n")
  self.region = ask_for_integer("database region number", REGION_RANGE)
  raise MiqSignalError if warn && !agree(CREATE_REGION_AGREE)
end

#create_or_join_regionObject



84
85
86
# File 'lib/manageiq/appliance_console/database_configuration.rb', line 84

def create_or_join_region
  region ? create_region : join_region
end

#create_regionObject



88
89
90
91
92
93
94
# File 'lib/manageiq/appliance_console/database_configuration.rb', line 88

def create_region
  hint = "Please stop the EVM server process on all appliances in the region"
  ManageIQ::ApplianceConsole::Utilities.bail_if_db_connections("preventing the setup of a database region.\n#{hint}")
  log_and_feedback(__method__) do
    ManageIQ::ApplianceConsole::Utilities.rake("evm:db:region", {}, {'REGION' => region.to_s, 'VERBOSE' => 'false'})
  end
end

#friendly_inspectObject



127
128
129
130
131
132
133
134
135
136
# File 'lib/manageiq/appliance_console/database_configuration.rb', line 127

def friendly_inspect
  output = <<-FRIENDLY
Host:     #{host}
Username: #{username}
Database: #{database}
FRIENDLY
  output << "Port:     #{port}\n" if port
  output << "Region:   #{region}\n" if region
  output
end

#join_regionObject



96
97
98
# File 'lib/manageiq/appliance_console/database_configuration.rb', line 96

def join_region
  ManageIQ::ApplianceConsole::Utilities.rake("evm:join_region", {})
end

#local?Boolean

Returns:

  • (Boolean)


59
60
61
# File 'lib/manageiq/appliance_console/database_configuration.rb', line 59

def local?
  host.blank? || host.in?(%w(localhost 127.0.0.1))
end

#merged_settingsObject

merge all the non specified setings for all the basic attributes, overwrite from this object (including blank values)



151
152
153
154
155
156
157
158
159
160
161
# File 'lib/manageiq/appliance_console/database_configuration.rb', line 151

def merged_settings
  merged = self.class.current
  settings_hash.each do |k, v|
    if v.present?
      merged['production'][k] = v
    else
      merged['production'].delete(k)
    end
  end
  merged
end

#reset_regionObject



100
101
102
103
104
105
106
107
108
109
# File 'lib/manageiq/appliance_console/database_configuration.rb', line 100

def reset_region
  say("Warning: RESETTING A DATABASE WILL DESTROY ANY EXISTING DATA AND CANNOT BE UNDONE.\n\n")
  raise MiqSignalError unless are_you_sure?("reset the configured database")

  create_new_region_questions(false)
  ENV["DISABLE_DATABASE_ENVIRONMENT_CHECK"] = "1"
  create_region
ensure
  ENV["DISABLE_DATABASE_ENVIRONMENT_CHECK"] = nil
end

#run_interactiveObject



44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/manageiq/appliance_console/database_configuration.rb', line 44

def run_interactive
  ask_questions

  clear_screen
  say "Activating the configuration using the following settings...\n#{friendly_inspect}\n"

  raise MiqSignalError unless activate

  say("\nConfiguration activated successfully.\n")
rescue RuntimeError => e
  puts "Configuration failed#{": " + e.message unless e.class == MiqSignalError}"
  press_any_key
  raise MiqSignalError
end

#save(settings = nil) ⇒ Object



163
164
165
166
167
# File 'lib/manageiq/appliance_console/database_configuration.rb', line 163

def save(settings = nil)
  settings ||= merged_settings
  settings = self.class.encrypt_password(settings)
  do_save(settings)
end

#settings_hashObject



138
139
140
141
142
143
144
145
146
147
# File 'lib/manageiq/appliance_console/database_configuration.rb', line 138

def settings_hash
  {
    'adapter'  => 'postgresql',
    'host'     => local? ? "localhost" : host,
    'port'     => port,
    'username' => username,
    'password' => password.presence,
    'database' => database
  }
end

#validate!Object



205
206
207
208
209
210
211
212
# File 'lib/manageiq/appliance_console/database_configuration.rb', line 205

def validate!
  pool = ModelWithNoBackingTable.establish_connection(settings_hash.delete_if { |_n, v| v.blank? })
  begin
    pool.with_connection { |conn| conn.connect! && conn.connected? }
  ensure
    ModelWithNoBackingTable.remove_connection
  end
end

#validatedObject



197
198
199
200
201
202
203
# File 'lib/manageiq/appliance_console/database_configuration.rb', line 197

def validated
  !!validate!
rescue => err
  log_error(__method__, err.message)
  say_error(__method__, err.message)
  false
end