class Beaker::GoogleCompute

Beaker support for the Google Compute Engine.

Constants

SLEEPWAIT
ZOMBIE

Hours before an instance is considered a zombie

Public Class Methods

new(google_hosts, options) click to toggle source

Create a new instance of the Google Compute Engine hypervisor object

@param [<Host>] google_hosts The Array of google hosts to provision, may ONLY be of platforms /centos-*/, /debian-*/, /rhel-*/, /suse-*/. Only supports the Google Compute provided templates.

@param [Hash{Symbol=>String}] options The options hash containing configuration values @option options [String] :gce_project The Google Compute Project name to connect to

@option options [String] :gce_keyfile The location of the Google Compute service account keyfile

@option options [String] :gce_password The password for the Google Compute service account key

@option options [String] :gce_email The email address for the Google Compute service account

@option options [String] :gce_machine_type A Google Compute machine type used to create instances, defaults to n1-highmem-2

@option options [Integer] :timeout The amount of time to attempt execution before quiting and exiting with failure

# File lib/beaker/hypervisor/google_compute.rb, line 60
def initialize(google_hosts, options)
  require 'beaker/hypervisor/google_compute_helper'

  @options = options
  @logger = options[:logger]
  @hosts = google_hosts
  @firewall = ''
  @gce_helper = GoogleComputeHelper.new(options)
end

Public Instance Methods

cleanup() click to toggle source

Shutdown and destroy virtual machines in the Google Compute Engine, including their associated disks and firewall rules

# File lib/beaker/hypervisor/google_compute.rb, line 141
def cleanup()
  attempts = @options[:timeout].to_i / SLEEPWAIT
  start = Time.now

  @gce_helper.delete_firewall(@firewall, start, attempts)

  @hosts.each do |host|
    @gce_helper.delete_instance(host['vmhostname'], start, attempts)
    @logger.debug("Deleted Google Compute instance #{host['vmhostname']} for #{host.name}")
    @gce_helper.delete_disk(host['diskname'], start, attempts)
    @logger.debug("Deleted Google Compute disk #{host['diskname']} for #{host.name}")
  end

end
find_google_ssh_public_key() click to toggle source

Do some reasonable sleuthing on the SSH public key for GCE

# File lib/beaker/hypervisor/google_compute.rb, line 14
def find_google_ssh_public_key
  keyfile = ENV.fetch('BEAKER_gce_ssh_public_key', File.join(ENV['HOME'], '.ssh', 'google_compute_engine.pub'))

  if @options[:gce_ssh_public_key] && !File.exist?(keyfile)
    keyfile = @options[:gce_ssh_public_key]
  end

  raise("Could not find GCE Public SSH Key at '#{keyfile}'") unless File.exist?(keyfile)

  return keyfile
end
format_metadata() click to toggle source

Create the array of metaData, each member being a hash with a :key and a :value. Sets :department, :project and :jenkins_build_url.

# File lib/beaker/hypervisor/google_compute.rb, line 28
def format_metadata
  [ {:key => :department, :value => @options[:department]},
    {:key => :project, :value => @options[:project]},
    {:key => :jenkins_build_url, :value => @options[:jenkins_build_url]},
    {:key => :sshKeys, :value => "google_compute:#{File.read(find_google_ssh_public_key).strip}" }
  ].delete_if { |member| member[:value].nil? or member[:value].empty?}
end
kill_zombies(max_age = ZOMBIE) click to toggle source

Shutdown and destroy Google Compute instances (including their associated disks and firewall rules) that have been alive longer than ZOMBIE hours.

# File lib/beaker/hypervisor/google_compute.rb, line 158
def kill_zombies(max_age = ZOMBIE)
  now = start = Time.now
  attempts = @options[:timeout].to_i / SLEEPWAIT

  # get rid of old instances
  instances = @gce_helper.list_instances(start, attempts)
  if instances
    instances.each do |instance|
      created = Time.parse(instance['creationTimestamp'])
      alive = (now - created )/60/60
      if alive >= max_age
        #kill it with fire!
        @logger.debug("Deleting zombie instance #{instance['name']}")
        @gce_helper.delete_instance( instance['name'], start, attempts )
      end
    end
  else
    @logger.debug("No zombie instances found")
  end

  # get rid of old disks
  disks = @gce_helper.list_disks(start, attempts)
  if disks
    disks.each do |disk|
      created = Time.parse(disk['creationTimestamp'])
      alive = (now - created )/60/60
      if alive >= max_age

        # kill it with fire!
        @logger.debug("Deleting zombie disk #{disk['name']}")
        @gce_helper.delete_disk( disk['name'], start, attempts )
      end
    end
  else
    @logger.debug("No zombie disks found")
  end

  # get rid of non-default firewalls
  firewalls = @gce_helper.list_firewalls( start, attempts)

  if firewalls && !firewalls.empty?
    firewalls.each do |firewall|
      @logger.debug("Deleting non-default firewall #{firewall['name']}")
      @gce_helper.delete_firewall( firewall['name'], start, attempts )
    end
  else
    @logger.debug("No zombie firewalls found")
  end
end
provision() click to toggle source

Create and configure virtual machines in the Google Compute Engine, including their associated disks and firewall rules

# File lib/beaker/hypervisor/google_compute.rb, line 72
def provision
  attempts = @options[:timeout].to_i / SLEEPWAIT
  start = Time.now

  test_group_identifier = "beaker-#{start.to_i}-"

  # get machineType resource, used by all instances
  machineType = @gce_helper.get_machineType(start, attempts)

  # set firewall to open pe ports
  network = @gce_helper.get_network(start, attempts)
  @firewall = test_group_identifier + generate_host_name
  @gce_helper.create_firewall(@firewall, network, start, attempts)

  @logger.debug("Created Google Compute firewall #{@firewall}")


  @hosts.each do |host|
    if host[:image]
      gplatform = host[:image]
    elsif host[:platform]
      gplatform = Platform.new(host[:platform])
    else
      raise('You must specify either :image or :platform, or both as necessary')
    end

    img = @gce_helper.get_latest_image(gplatform, start, attempts)

    unique_host_id = test_group_identifier + generate_host_name

    host['diskname'] = unique_host_id
    disk = @gce_helper.create_disk(host['diskname'], img, start, attempts)
    @logger.debug("Created Google Compute disk for #{host.name}: #{host['diskname']}")

    # create new host name
    host['vmhostname'] = unique_host_id
    #add a new instance of the image
    instance = @gce_helper.create_instance(host['vmhostname'], img, machineType, disk, start, attempts)
    @logger.debug("Created Google Compute instance for #{host.name}: #{host['vmhostname']}")

    # add metadata to instance, if there is any to set
    mdata = format_metadata
    unless mdata.empty?
      @gce_helper.setMetadata_on_instance(host['vmhostname'], instance['metadata']['fingerprint'],
                                          mdata,
                                          start, attempts)
      @logger.debug("Added tags to Google Compute instance #{host.name}: #{host['vmhostname']}")
    end

    # get ip for this host
    host['ip'] = instance['networkInterfaces'][0]['accessConfigs'][0]['natIP']

    # configure ssh
    default_user = host['user']
    host['user'] = 'google_compute'

    copy_ssh_to_root(host, @options)
    enable_root_login(host, @options)
    host['user'] = default_user

    # shut down connection, will reconnect on next exec
    host.close

    @logger.debug("Instance ready: #{host['vmhostname']} for #{host.name}}")
  end
end