lib/forj/process/ForjProcess.rb in forj-1.0.9 vs lib/forj/process/ForjProcess.rb in forj-1.0.10

- old
+ new

@@ -55,11 +55,11 @@ o_address = hParams.refresh[:public_ip, :ObjectData] s_status = active_server?(server, o_address, boot_options[:keys], boot_options[:coherent], s_status) - till_server_active(s_status, server, o_address, boot_options) + till_server_active(s_status, hParams, o_address, boot_options) o_forge = get_forge(sObjectType, config[:instance_name], hParams) read_blueprint_implemented(o_forge, hParams) o_forge @@ -152,11 +152,11 @@ predef_keypair end def active_server?(o_server, o_address, private_key_file, keypair_coherent, s_status - ) + ) if o_server[:attrs][:status] == :active image = server_get_image o_server s_msg = format('Your forj Maestro server is up and running and is '\ "publically accessible through IP '%s'.\n\n"\ @@ -189,14 +189,18 @@ end s_status end end +# rubocop:disable Metrics/ClassLength + # Functions for boot - build_forge class ForjCoreProcess + # TODO: Rewrite this function to break it for rubocop. # rubocop:disable CyclomaticComplexity + # Function displaying the server status def maestro_create_status(sStatus, iCurAct = 4, pending_count = 0) s_activity = '/-\\|?' if iCurAct < 4 s_cur_act = 'ACTIVE' else @@ -226,30 +230,58 @@ end # TODO: Rewrite this function to break it for rubocop. # rubocop: disable PerceivedComplexity # rubocop: disable Metrics/MethodLength + # rubocop: disable Metrics/AbcSize - def till_server_active(s_status, o_server, o_address, boot_options) + # Loop until server is active + def till_server_active(s_status, hParams, o_address, boot_options) m_cloud_init_error = [] i_cur_act = 0 o_old_log = '' pending_count = 0 + server_error = 0 + o_server = hParams.refresh[:server, :ObjectData] while s_status != :active if i_cur_act == 4 pending_count += 1 else pending_count = 0 end maestro_create_status(s_status, i_cur_act, pending_count) i_cur_act += 1 i_cur_act = i_cur_act % 4 + + if s_status == :restart + process_delete(:server) + PrcLib.message("Bad server '%s' removed. Creating a new one...", + o_server[:name]) + sleep(5) + process_create(:internet_server) + s_status = :starting + o_server = hParams.refresh[:server, :ObjectData] + next + end + o_server = load_server(o_server) - # s_status = o_server[:attrs][:status] + + if o_server[:status] == :error + if server_error == 1 + PrcLib.fatal(1, 'Server tried to be rebuilt but failed again.') + end + server_error = 1 + PrcLib.warning("The creation of server '%s' has currently failed. "\ + 'Trying to rebuild it, once before give up.', + o_server[:name]) + s_status = :restart + next + end + if s_status == :starting - s_status = :assign_ip if o_server[:attrs][:status] == :active + s_status = :assign_ip if o_server[:status] == :active elsif s_status == :assign_ip s_status = assign_ip_boot(o_address, boot_options, s_status, o_server) else # analyze the log output output_options = { :status => s_status, :error => m_cloud_init_error, :old_log => o_old_log, :cur_act => i_cur_act @@ -340,11 +372,11 @@ sleep 5 done END s_msg = format(s_msg, o_server[:name], image[:ssh_user], o_address[:public_ip], boot_options[:keys] - ) + ) unless boot_options[:coherent] s_msg += ANSI.bold("\nUnfortunatelly") + " your current keypair' \ ' is not usable to connect to your server.\nYou need to fix' \ ' this issue to gain access to your server." end @@ -494,11 +526,11 @@ entr = { :key => rand(36**10).to_s(36), :salt => Time.now.to_i.to_s, :iv => Base64.strict_encode64( OpenSSL::Cipher::Cipher.new('aes-256-cbc').random_iv - ) + ) } PrcLib.debug("Writing '%s' key file", key_file) File.open(key_file, 'w') do |out| out.write(Base64.encode64(entr.to_yaml)) @@ -642,18 +674,19 @@ else h_result[:maestro_repo] = File.join(path_maestro, 'maestro') clone_maestro_repo(maestro_url, path_maestro, config) end rescue => e - PrcLib.error('Error while cloning the repo from %s\n%s\n%s', - maestro_url, e.message, e.backtrace.join("\n")) - PrcLib.info( - 'If this error persist you could clone the repo manually in ~/.forj/' - ) + PrcLib.error("Error while cloning the repo from %s\n%s\n%s"\ + "\nIf this error persist you could clone the repo manually"\ + " in '%s'", + maestro_url, e.message, e.backtrace.join("\n"), + h_result[:maestro_repo]) end o_maestro = register(h_result, sObjectType) o_maestro[:maestro_repo] = h_result[:maestro_repo] + o_maestro[:maestro_repo_exist?] = File.directory?(h_result[:maestro_repo]) o_maestro end end # Functions for boot - create_or_use_infra @@ -894,11 +927,11 @@ "mime file '%s' not found.", mime ) unless File.exist?(mime) end - def build_userdata(sObjectType, hParams) + def build_userdata(sObjectType, hParams) # rubocop: disable Metrics/AbcSize # get the paths for maestro and infra repositories # maestro_path = hParams[:maestro_repository].values # infra_path = hParams[:infra_repository].values # concatenate the paths for boothook and cloud_config files @@ -909,10 +942,17 @@ mime = File.join( Forj.build_path, format('userdata.mime.%s', rand(36**5).to_s(36)) ) + unless hParams[:maestro_repository, :maestro_repo_exist?] + PrcLib.fatal(1, "Maestro repository doesn't exist. This is required for "\ + "cloud_init user_data build. Check why '%s' "\ + "doesn't exist.", + hParams[:maestro_repository, :maestro_repo]) + end + meta_data = JSON.generate(hParams[:metadata, :meta_data]) build_tmpl_dir = File.expand_path(File.join(LIB_PATH, 'build_tmpl')) PrcLib.state("Preparing user_data - file '%s'", mime) @@ -1089,11 +1129,11 @@ # # This function is can be executed only if we copy files to internal # forj keypair storage. Otherwise this update is ignored. def save_sequences(private_key_file, forj_private_key_file, public_key_file, forj_public_key_file, key_name - ) + ) PrcLib.info('Importing key pair to FORJ keypairs list.') FileUtils.copy(private_key_file, forj_private_key_file) FileUtils.copy(public_key_file, forj_public_key_file) # Attaching this keypair to the account @@ -1105,11 +1145,11 @@ # # This function is can be executed only if we copy files to internal # forj keypair storage. Otherwise this update is ignored. def save_md5(private_key_file, forj_private_key_file, public_key_file, forj_public_key_file - ) + ) # Checking source/dest files content if Digest::MD5.file(private_key_file).hexdigest != Digest::MD5.file(forj_private_key_file).hexdigest PrcLib.info( 'Updating private key keypair piece to FORJ keypairs list.' @@ -1136,11 +1176,11 @@ # Saving internal copy of private key file for forj use. config.set(:keypair_base, keys[:keypair_name], :name => 'account') PrcLib.info("Configured forj keypair '%s' with '%s'", keys[:keypair_name], File.join(keys[:keypair_path], keys[:key_basename]) - ) + ) end # keypair_files post setup # # This function will get the keypair_files setup by user and it will: @@ -1212,20 +1252,20 @@ # Used in keypair_name pre-step at setup time. # return true to not skip the data. # def update_keypair_config(_ = nil) %w(local account).each do |config_name| - next if config.exist?(:keypair_base, :names => [config_name]) - + next if config.latest_version?(config_name) keypair_path = config.get(:keypair_path, nil, :name => config_name) - next if keypair_path.nil? - - options = { :name => config_name } - options.merge!(:section => :default) if config_name == 'local' - config.set(:keypair_base, File.basename(keypair_path), options) - config.set(:keypair_path, File.dirname(keypair_path), options) + unless keypair_path.nil? + options = { :name => config_name } + options.merge!(:section => :default) if config_name == 'local' + config.set(:keypair_base, File.basename(keypair_path), options) + config.set(:keypair_path, File.dirname(keypair_path), options) + end + config.version_set(config_name, Forj.file_version) end true end def forj_dns_settings @@ -1294,34 +1334,53 @@ def forj_check_cloud_keypair key_name = config[:keypair_name] return true if key_name.nil? config[:key_cloud_coherence] = false cloud_key = process_get(:keypairs, key_name) + register(cloud_key) if !cloud_key.empty? if cloud_key[:coherent] config[:key_cloud_coherence] = true return true end else return true end keypair_display(cloud_key) - s_ask = 'Do you still want to create new key?' - PrcLib.fatal(1, 'This keypair name cannot be used. ' \ - 'You may check keypair_path setting ' \ - 'in your account.') unless agree(s_ask) + + return true unless cloud_key[:public_key_exist?] + + PrcLib.message("You need to create a new keypair instead of '%s'"\ + 'or quit the setup to get the original key and retry.', + key_name) + s_ask = 'Do you want to create new keypair?' + + PrcLib.fatal(1, 'Quitting setup per your request.') unless agree(s_ask) false end # pre process before asking keypair files # return true continue to ask keypair files # return false skip asking keypair files def forj_cloud_keypair_coherent?(_keypair_files) + return true unless config.exist?(:key_cloud_coherence) + + keypair = data_objects(:keypairs) + + return true unless keypair.nil? || keypair[:private_key_exist?] + if config[:key_cloud_coherence] PrcLib.message('Your local ssh keypair is detected ' \ 'and valid to access the box.') return false end + match = ANSI.bold(format('matching %s keypair name previously set', + ANSI.red(config[:keypair_name]))) + desc = 'the base keypair file name (with absolute path) ' + match + + Lorj.data.set(:sections, :credentials, :keypair_files, + { :desc => desc }, 'setup') + true end end # Funtions for get