lib/forj/process/ForjProcess.rb in forj-1.0.5 vs lib/forj/process/ForjProcess.rb in forj-1.0.6

- old
+ new

@@ -31,13 +31,13 @@ # Functions for boot - build_forge class ForjCoreProcess def build_forge(sObjectType, hParams) forge_exist?(sObjectType) - o_server = data_objects(:server, :ObjectData) + o_server = hParams.refresh[:server, :ObjectData] - boot_options = boot_keypairs(o_server) + boot_options = boot_keypairs(hParams) # Define the log lines to get and test. config.set(:log_lines, 5) PrcLib.info("Maestro server '%s' id is '%s'.", @@ -45,21 +45,21 @@ # Waiting for server to come online before assigning a public IP. s_status = :checking maestro_create_status(s_status) - o_address = data_objects(:public_ip, :ObjectData) + o_address = hParams.refresh[:public_ip, :ObjectData] s_status = active_server?(o_server, o_address, boot_options[:keys], boot_options[:coherent], s_status ) till_server_active(s_status, o_server, o_address, boot_options) o_forge = get_forge(sObjectType, config[:instance_name], hParams) - read_blueprint_implemented(o_forge, o_address) + read_blueprint_implemented(o_forge, hParams) o_forge end def forge_exist?(sObjectType) o_forge = process_get(sObjectType, config[:instance_name]) @@ -91,31 +91,21 @@ PrcLib.high_level_msg("\nBuilding your forge...\n") end end - def boot_keypairs(o_server) - # Get keypairs - h_keys = keypair_detect( - o_server[:key_name], - File.join(Forj.keypairs_path, o_server[:key_name]) - ) + def boot_keypairs(params) + o_server = params[:server, :ObjectData] + h_keys = params[:keypairs] - private_key_file = File.join( - h_keys[:keypair_path], - h_keys[:private_key_name] - ) - # public_key_file = File.join( - # h_keys[:keypair_path], - # h_keys[:public_key_name] - # ) + if h_keys.nil? || o_server[:key_name] != h_keys[:name] + h_keys = process_get(:keypairs, o_server[:key_name]) + end + private_key_file = File.join(h_keys[:keypair_path], + h_keys[:private_key_name]) - o_server_key = process_get(:keypairs, o_server[:key_name]) - - keypair_coherent = coherent_keypair?(h_keys, o_server_key) - boot_options = { :keys => private_key_file, :coherent => keypair_coherent } - boot_options + { :keys => private_key_file, :coherent => h_keys[:coherent] } end def active_server?(o_server, o_address, private_key_file, keypair_coherent, s_status ) @@ -156,16 +146,18 @@ end # Functions for boot - build_forge class ForjCoreProcess # rubocop:disable CyclomaticComplexity - def maestro_create_status(sStatus, iCurAct = 4) + + def maestro_create_status(sStatus, iCurAct = 4, pending_count = 0) s_activity = '/-\\|?' if iCurAct < 4 s_cur_act = 'ACTIVE' else - s_cur_act = ANSI.bold('PENDING') + s_cur_act = format('%s - %d s', ANSI.bold('PENDING'), + (pending_count + 1) * 5) end case sStatus when :checking PrcLib.state('Checking server status') @@ -184,19 +176,28 @@ PrcLib.state('RESTARTING - Currently restarting maestro box. Be patient.') when :active PrcLib.info('Server is active') end end - # rubocop:enable CyclomaticComplexity + # TODO: Rewrite this function to break it for rubocop. + # rubocop: disable PerceivedComplexity + # rubocop: disable Metrics/MethodLength + def till_server_active(s_status, o_server, o_address, boot_options) m_cloud_init_error = [] i_cur_act = 0 o_old_log = '' + pending_count = 0 while s_status != :active - maestro_create_status(s_status, i_cur_act) + 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 o_server = load_server(o_server) # s_status = o_server[:attrs][:status] if s_status == :starting @@ -210,27 +211,62 @@ output_options = analyze_log_output(output_options, s_status) s_status = output_options[:status] m_cloud_init_error = output_options[:error] o_old_log = output_options[:old_log] i_cur_act = output_options[:cur_act] + if pending_count == 60 + image = server_get_image o_server + highlight = ANSI.yellow('-' * 40) + PrcLib.warning("No more server activity detected.\n"\ + "#{highlight}\n"\ + "%s\n"\ + "#{highlight}\n"\ + "The server '%s' is not providing any output log for"\ + " more than 5 minutes.\nPlease review the current"\ + 'output show below to determine if this a normal '\ + "situation.\nYou can connect to the server if you "\ + "want to.\nTo connect, use:\n"\ + 'ssh %s@%s -o StrictHostKeyChecking=no -i %s', + o_old_log, o_server[:name], image[:ssh_user], + o_address[:public_ip], boot_options[:keys]) + end end sleep(5) if s_status != :active end end + # Function to get the image data from the server + # + + def server_get_image(server) + image = data_objects(:image, :ObjectData) + return image unless image.nil? + + image = process_get(:image, server[:image_id]) + + return Lorj::Data.new if image.nil? + + register(image) + end + + # rubocop:enable CyclomaticComplexity + # rubocop:enable PerceivedComplexity + # Function to get the server, tracking errors # # *return* # - Server found. # def load_server(server) begin found_server = process_get(:server, server[:attrs][:id]) rescue => e PrcLib.error(e.message) + else + return found_server end - (found_server.nil? ? server : found_server) + server end end # Functions for boot - build_forge class ForjCoreProcess @@ -244,21 +280,23 @@ o_address = process_create(:public_ip) else o_address = o_addresses[0] end end + + image = data_objects[:image, :ObjectData] s_msg = <<-END Public IP for server '%s' is assigned. Now, as soon as the server respond to the ssh port, you will be able to get a tail of the build with: while [ 1 = 1 ] do - ssh ubuntu@%s -o StrictHostKeyChecking=no -i %s tail -f /var/log/cloud-init.log + ssh %s@%s -o StrictHostKeyChecking=no -i %s tail -f /var/log/cloud-init.log sleep 5 done END - s_msg = format(s_msg, o_server[:name], + s_msg = format(s_msg, o_server[:name], image[: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' \ @@ -269,32 +307,30 @@ s_status = :cloud_init s_status end def analyze_log_output(output_options, s_status) - # m_cloud_init_error = [] - # o_old_log = '' - o_log = process_get(:server_log, 25)[:attrs][:output] - # i_cur_act = 4 if o_log == o_old_log - output_options[:cur_act] = 4 if o_log == output_options[:old_log] - # o_old_log = o_log - output_options[:old_log] = o_log - if /cloud-init boot finished/ =~ o_log - # s_status = :active + o_log = process_get(:server_log, 25) + return output_options if o_log.nil? || o_log.empty? + + log = o_log[:attrs][:output] + output_options[:cur_act] = 4 if log == output_options[:old_log] + output_options[:old_log] = log + if /cloud-init boot finished/ =~ log output_options[:status] = :active output_options[:error] = display_boot_moving_error( output_options[:error] ) - elsif /\[CRITICAL\]/ =~ o_log - m_critical = o_log.scan(/.*\[CRITICAL\].*\n/) + elsif /\[CRITICAL\]/ =~ log + m_critical = log.scan(/.*\[CRITICAL\].*\n/) output_options[:error] = display_boot_critical_error( output_options[:error], m_critical ) else # validate server status - output_options = analyze_server_status(s_status, o_log, output_options) + output_options = analyze_server_status(s_status, log, output_options) end output_options end def display_boot_critical_error(m_cloud_init_error, m_critical) @@ -346,38 +382,36 @@ output_options[:status] = :starting end output_options end - def read_blueprint_implemented(o_forge, o_address) + def read_blueprint_implemented(o_forge, params) + o_address = params[:public_ip, :ObjectData] + blueprint = params[:blueprint] + instance_name = params[:instance_name] s_msg = format( "Your Forge '%s' is ready and accessible from" \ " IP #{o_address[:public_ip]}.", - config[:instance_name] + instance_name ) # TODO: read the blueprint/layout to identify which services # are implemented and can be accessible. - if config[:blueprint] + if blueprint s_msg += format( "\n" + 'Maestro has implemented the following server(s) for your' \ " blueprint '%s':", - config[:blueprint] + blueprint ) server_options = display_servers_with_ip(o_forge, s_msg) s_msg += server_options[:message] i_count = server_options[:count] if i_count > 0 s_msg += format("\n%d server(s) identified.\n", i_count) else s_msg = 'No servers found except maestro' - PrcLib.warning( - format( - 'Something went wrong, while creating nodes for blueprint' \ - " '%s'. check maestro logs.", - config[:blueprint] - ) - ) + PrcLib.warning('Something went wrong, while creating nodes for '\ + "blueprint '%s'. check maestro logs.", blueprint) end else s_msg += "\nMaestro has NOT implemented any servers, because you did" \ ' not provided a blueprint. Connect to Maestro, and ask Maestro to' \ ' implement any kind of blueprint you need. (Feature currently' \ @@ -859,11 +893,11 @@ PrcLib.fatal(1, e.message) end if PrcLib.core_level < 5 File.delete(mime) else - ForjLib.debug(5, "user_data temp file '%s' kept", mime) + Lorj.debug(5, "user_data temp file '%s' kept", mime) end config[:user_data] = user_data o_user_data = register(hParams, sObjectType) @@ -933,58 +967,37 @@ keys end def create_keys_automatically(keys, private_key_file) return if keys[:private_key_exist?] - # Need to create a key. ask if we need so. - PrcLib.message("The private key file attached to keypair named '%s' is not"\ - ' found. Running ssh-keygen to create it.', - keys[:keypair_name]) unless File.exist?(private_key_file) + # Need to create a key. ask if we need so. + PrcLib.message("The private key file attached to keypair named '%s' is "\ + 'not found. Running ssh-keygen to create it.', + keys[:keypair_name]) PrcLib.ensure_dir_exists(File.dirname(private_key_file)) command = format('ssh-keygen -t rsa -f %s', private_key_file) PrcLib.debug(format("Executing '%s'", command)) system(command) end - if !File.exist?(private_key_file) - PrcLib.fatal(1, "'%s' not found. Unable to add your keypair to hpcloud."\ - ' Create it yourself and provide it with -p option. '\ - 'Then retry.', private_key_file) - else - PrcLib.fatal(1, 'ssh-keygen did not created your key pairs. Aborting.'\ + return if File.exist?(private_key_file) + PrcLib.fatal(1, 'ssh-keygen did not created your key pairs. Aborting.'\ ' Please review errors in ~/.forj/forj.log') - end end end # Functions for setup class ForjCoreProcess - def load_key_with_passphrase(keys, public_key_file, private_key_file) - # unless keys[:public_key_exist?] - return if keys[:private_key_exist?] - PrcLib.message("Your public key '%s' was not found. Getting it from the" \ - ' private one. It may require your passphrase.', - public_key_file) - command = format( - 'ssh-keygen -y -f %s > %s', - private_key_file, - public_key_file - ) - PrcLib.debug("Executing '%s'", command) - system(command) - # end - end - 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 - @hAccountData.rh_set(key_name, :credentials, 'keypair_name') - @hAccountData.rh_set(forj_private_key_file, :credentials, 'keypair_path') + config.set(:keypair_name, key_name, :name => 'account') + config.set(:keypair_path, forj_private_key_file, :name => 'account') config.local_set(key_name.to_s, private_key_file, :imported_keys) end def save_md5(private_key_file, forj_private_key_file, public_key_file, forj_public_key_file @@ -1013,11 +1026,11 @@ # Functions for setup class ForjCoreProcess def save_internal_key(forj_private_key_file, keys) # Saving internal copy of private key file for forj use. - config.set(:keypair_path, forj_private_key_file) + config.set(:keypair_path, forj_private_key_file, :name => 'account') PrcLib.info("Configured forj keypair '%s' with '%s'", keys[:keypair_name], File.join(keys[:keypair_path], keys[:key_basename]) ) end @@ -1041,14 +1054,12 @@ public_key_file = File.join(keys[:keypair_path], keys[:public_key_name]) # Creation sequences create_keys_automatically(keys, private_key_file) - load_key_with_passphrase(keys, public_key_file, private_key_file) - forj_private_key_file = File.join(Forj.keypairs_path, key_name) - # forj_public_key_file = File.join($FORJ_KEYPAIRS_PATH, key_name + '.pub') + forj_public_key_file = File.join(Forj.keypairs_path, key_name + '.pub') # Saving sequences if keys[:keypair_path] != Forj.keypairs_path if !File.exist?(forj_private_key_file) || !File.exist?(forj_public_key_file) @@ -1066,20 +1077,21 @@ true # forj_setup_keypairs_files successfull end def forj_dns_settings s_ask = 'Optionally, you can ask Maestro to use/manage a domain name on' \ - " your cloud. It requires your DNS cloud service to be enabled.\nDo " \ + " your cloud. It requires your DNS cloud service to be enabled.\nDo" \ ' you want to configure it?' config.set(:dns_settings, agree(s_ask)) true end def forj_dns_settings?(sKey) # Return true to ask the question. false otherwise unless config.get(:dns_settings) - config.set(sKey, nil) + section = Lorj.data.first_section(sKey) + config.del(sKey, :name => 'account', :section => section) return false # Do not ask end true end @@ -1270,20 +1282,14 @@ # Functions for ssh class ForjCoreProcess def setup_ssh_user(_sCloudObj, hParams) images = process_query(:image, :name => hParams[:image_name]) - case images.length - when 0 - s_default = hParams[:default_value] - else - if images[0, :ssh_user].nil? - s_default = hParams[:default_value] - else - s_default = images[0, :ssh_user] - end + result = { :list => config[:users] } + if images.length >= 1 && !images[0, :ssh_user].nil? + result[:default_value] = images[0, :ssh_user] end - { :default_value => s_default, :list => config[:users] } + result end def ssh_login(options, user, public_ip) s_opts = '-o StrictHostKeyChecking=no -o ServerAliveInterval=180' s_opts += format(' -i %s', options[:keys]) if options[:keys]