['hypervisor'].each do |lib| require "beaker/#{lib}" end module Beaker # Object that holds all the provisioned and non-provisioned virtual machines. # Controls provisioning, configuration, validation and cleanup of those virtual machines. class NetworkManager # Determine if a given host should be provisioned. # Provision if: # - only if we are running with ---provision # - only if we have a hypervisor # - only if either the specific hosts has no specification or has 'provision' in its config # - always if it is a vagrant box (vagrant boxes are always provisioned as # they always need ssh key hacking.) def provision? options, host command_line_says = options[:provision] host_says = host['hypervisor'] && (host.has_key?('provision') ? host['provision'] : true) (command_line_says && host_says) or host['hypervisor'].include?('vagrant') end attr_accessor :hosts, :hypervisors def initialize(options, logger) @logger = logger @options = options @hosts = [] @machines = {} @hypervisors = nil # user provided prefix has top priority if not @options[:log_prefix] # name it after the hosts file @options[:log_prefix] = if @options[:hosts_file] File.basename(@options[:hosts_file], '.yml') else # here be the default @options[:default_log_prefix] end end @options[:timestamp] = Time.now unless @options.has_key?(:timestamp) @options[:xml_dated_dir] = Beaker::Logger.generate_dated_log_folder(@options[:xml_dir], @options[:log_prefix], @options[:timestamp]) @options[:log_dated_dir] = Beaker::Logger.generate_dated_log_folder(@options[:log_dir], @options[:log_prefix], @options[:timestamp]) @options[:logger_sut] = Beaker::Logger.new(File.join(@options[:log_dated_dir], @options[:log_sut_event]), { :quiet => true }) end # Provision all virtual machines. Provision machines according to their set hypervisor, if no hypervisor # is selected assume that the described hosts are already up and reachable and do no provisioning. def provision cleanup if @hypervisors @hypervisors = {} # sort hosts by their hypervisor, use hypervisor 'none' if no hypervisor is specified hostless_options = Beaker::Options::OptionsHash.new.merge(@options.select { |k, _v| !k.to_s.include?('HOSTS') }) @options['HOSTS'].each_key do |name| host_hash = @options['HOSTS'][name] hypervisor = host_hash['hypervisor'] if @options[:provision] hypervisor = provision?(@options, host_hash) ? host_hash['hypervisor'] : 'none' end @logger.debug "Hypervisor for #{name} is #{hypervisor}" @machines[hypervisor] = [] unless @machines[hypervisor] hostless_options[:timesync] = host_hash[:timesync] if host_hash[:timesync] != nil host_itself = Beaker::Host.create(name, host_hash, hostless_options) host_itself.validate_setup @machines[hypervisor] << host_itself end @machines.each_key do |type| @hypervisors[type] = Beaker::Hypervisor.create(type, @machines[type], @options) @hosts << @machines[type] @machines[type].each do |host| log_sut_event host, true end end @hosts = @hosts.flatten @hosts end # Validate all provisioned machines, ensure that required packages are installed - if they are missing # attempt to add them. # @raise [Exception] Raise an exception if virtual machines fail to be validated def validate return unless @hypervisors @hypervisors.each_key do |type| @hypervisors[type].validate end end # Configure all provisioned machines, adding any packages or settings required for SUTs # @raise [Exception] Raise an exception if virtual machines fail to be configured def configure return unless @hypervisors @hypervisors.each_key do |type| @hypervisors[type].configure end end # configure proxy on all provioned machines # @raise [Exception] Raise an exception if virtual machines fail to be configured def proxy_package_manager return unless @hypervisors @hypervisors.each_key do |type| @hypervisors[type].proxy_package_manager end end # Shut down network connections and revert all provisioned virtual machines def cleanup # shut down connections @hosts.each { |host| host.close } if @hypervisors @hypervisors.each_key do |type| @hypervisors[type].cleanup @hypervisors[type].instance_variable_get(:@hosts).each do |host| log_sut_event host, false end end end @hypervisors = nil end # logs provisioning events # # @param [Host] host The host that the event is happening to # @param [Boolean] create Whether the event is creation or cleaning up # # @return [String] the log line created for this event def log_sut_event host, create raise ArgumentError.new "log_sut_event called before sut logger created. skipping #{host}, #{create}" unless @options.has_key?(:logger_sut) sut_logger = @options[:logger_sut] time = Time.new stamp = time.strftime('%Y-%m-%d %H:%M:%S') verb = create ? '+' : '-' line = "#{stamp}\t[#{verb}]\t#{host['hypervisor']}\t#{host['platform']}\t#{host.log_prefix}" sut_logger.notify line line end end end