Class: Beaker::OpenStack

Inherits:
Hypervisor show all
Defined in:
lib/beaker/hypervisor/openstack.rb

Overview

Beaker support for OpenStack This code is EXPERIMENTAL! Please file any issues/concerns at github.com/puppetlabs/beaker/issues

Constant Summary collapse

SLEEPWAIT =
5

Constants inherited from Hypervisor

Hypervisor::CHARMAP

Constants included from HostPrebuiltSteps

HostPrebuiltSteps::APT_CFG, HostPrebuiltSteps::CUMULUS_PACKAGES, HostPrebuiltSteps::DEBIAN_PACKAGES, HostPrebuiltSteps::ETC_HOSTS_PATH, HostPrebuiltSteps::ETC_HOSTS_PATH_SOLARIS, HostPrebuiltSteps::IPS_PKG_REPO, HostPrebuiltSteps::NTPSERVER, HostPrebuiltSteps::ROOT_KEYS_SCRIPT, HostPrebuiltSteps::ROOT_KEYS_SYNC_CMD, HostPrebuiltSteps::SLES_PACKAGES, HostPrebuiltSteps::TRIES, HostPrebuiltSteps::UNIX_PACKAGES, HostPrebuiltSteps::WINDOWS_PACKAGES

Instance Method Summary collapse

Methods inherited from Hypervisor

#configure, create, #generate_host_name, #proxy_package_manager, #validate

Methods included from HostPrebuiltSteps

#add_el_extras, #additive_hash_merge, #apt_get_update, #check_and_install_packages_if_needed, #construct_env, #copy_file_to_remote, #copy_ssh_to_root, #disable_iptables, #disable_se_linux, #echo_on_host, #enable_root_login, #epel_info_for, #get_domain_name, #get_ip, #hack_etc_hosts, #package_proxy, #proxy_config, #set_env, #set_etc_hosts, #sync_root_keys, #timesync, #validate_host

Methods included from DSL::Patterns

#block_on

Constructor Details

#initialize(openstack_hosts, options) ⇒ OpenStack

Create a new instance of the OpenStack hypervisor object

Parameters:

  • openstack_hosts (<Host>)

    The array of OpenStack hosts to provision

  • options (Hash{Symbol=>String})

    The options hash containing configuration values

Options Hash (options):

  • :openstack_api_key (String)

    The key to access the OpenStack instance with (required)

  • :openstack_username (String)

    The username to access the OpenStack instance with (required)

  • :openstack_auth_url (String)

    The URL to access the OpenStack instance with (required)

  • :openstack_tenant (String)

    The tenant to access the OpenStack instance with (required)

  • :openstack_network (String)

    The network that each OpenStack instance should be contacted through (required)

  • :openstack_keyname (String)

    The name of an existing key pair that should be auto-loaded onto each OpenStack instance (optional)

  • :jenkins_build_url (String)

    Added as metadata to each OpenStack instance

  • :department (String)

    Added as metadata to each OpenStack instance

  • :project (String)

    Added as metadata to each OpenStack instance

  • :timeout (Integer)

    The amount of time to attempt execution before quiting and exiting with failure



23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/beaker/hypervisor/openstack.rb', line 23

def initialize(openstack_hosts, options)
  require 'fog'
  @options = options
  @logger = options[:logger]
  @hosts = openstack_hosts
  @vms = []

  raise 'You must specify an Openstack API key (:oopenstack_api_key) for OpenStack instances!' unless @options[:openstack_api_key]
  raise 'You must specify an Openstack username (:openstack_username) for OpenStack instances!' unless @options[:openstack_username]
  raise 'You must specify an Openstack auth URL (:openstack_auth_url) for OpenStack instances!' unless @options[:openstack_auth_url]
  raise 'You must specify an Openstack tenant (:openstack_tenant) for OpenStack instances!' unless @options[:openstack_tenant]
  raise 'You must specify an Openstack network (:openstack_network) for OpenStack instances!' unless @options[:openstack_network]
  @compute_client ||= Fog::Compute.new(:provider => :openstack,
                                       :openstack_api_key => @options[:openstack_api_key],
                                       :openstack_username => @options[:openstack_username],
                                       :openstack_auth_url => @options[:openstack_auth_url],
                                       :openstack_tenant => @options[:openstack_tenant])
  if not @compute_client
    raise "Unable to create OpenStack Compute instance (api key: #{@options[:openstack_api_key]}, username: #{@options[:openstack_username]}, auth_url: #{@options[:openstack_auth_url]}, tenant: #{@options[:openstack_tenant]})"
  end
  @network_client ||= Fog::Network.new(
    :provider => :openstack,
    :openstack_api_key => @options[:openstack_api_key],
    :openstack_username => @options[:openstack_username],
    :openstack_auth_url => @options[:openstack_auth_url])
  if not @network_client

    raise "Unable to create OpenStack Network instance (api_key: #{@options[:openstack_api_key]}, username: #{@options[:openstack_username]}, auth_url: #{@options[:openstack_auth_url]}, tenant: #{@options[:openstack_tenant]})"
                                                                                                                                  end
end

Instance Method Details

#cleanupObject

Destroy any OpenStack instances



141
142
143
144
145
146
147
148
149
150
151
152
153
# File 'lib/beaker/hypervisor/openstack.rb', line 141

def cleanup
  @logger.notify "Cleaning up OpenStack"
  @vms.each do |vm|
    @logger.debug "Release floating IPs for OpenStack host #{vm.name}"
    floating_ips = vm.all_addresses # fetch and release its floating IPs
    floating_ips.each do |address|
      @compute_client.disassociate_address(vm.id, address['ip'])
      @compute_client.release_address(address['id'])
    end
    @logger.debug "Destroying OpenStack host #{vm.name}"
    vm.destroy
  end
end

#enable_root(host) ⇒ void

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

This method returns an undefined value.

Enables root access for a host when username is not root



169
170
171
172
173
174
175
176
# File 'lib/beaker/hypervisor/openstack.rb', line 169

def enable_root(host)
  if host['user'] != 'root'
    copy_ssh_to_root(host, @options)
    (host, @options)
    host['user'] = 'root'
    host.close
  end
end

#enable_root_on_hostsvoid

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

This method returns an undefined value.

Enables root for instances with custom username like ubuntu-amis



159
160
161
162
163
# File 'lib/beaker/hypervisor/openstack.rb', line 159

def enable_root_on_hosts
  @hosts.each do |host|
    enable_root(host)
  end
end

#flavor(f) ⇒ String

Provided a flavor name return the OpenStack id for that flavor

Parameters:

  • f (String)

    The flavor name

Returns:

  • (String)

    Openstack id for provided flavor name



57
58
59
60
# File 'lib/beaker/hypervisor/openstack.rb', line 57

def flavor f
  @logger.debug "OpenStack: Looking up flavor '#{f}'"
  @compute_client.flavors.find { |x| x.name == f } || raise("Couldn't find flavor: #{f}")
end

#image(i) ⇒ String

Provided an image name return the OpenStack id for that image

Parameters:

  • i (String)

    The image name

Returns:

  • (String)

    Openstack id for provided image name



65
66
67
68
# File 'lib/beaker/hypervisor/openstack.rb', line 65

def image i
  @logger.debug "OpenStack: Looking up image '#{i}'"
  @compute_client.images.find { |x| x.name == i } || raise("Couldn't find image: #{i}")
end

#network(n) ⇒ String

Provided a network name return the OpenStack id for that network

Parameters:

  • n (String)

    The network name

Returns:

  • (String)

    Openstack id for provided network name



73
74
75
76
# File 'lib/beaker/hypervisor/openstack.rb', line 73

def network n
  @logger.debug "OpenStack: Looking up network '#{n}'"
  @network_client.networks.find { |x| x.name == n } || raise("Couldn't find network: #{n}")
end

#provisionObject

Create new instances in OpenStack



79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/beaker/hypervisor/openstack.rb', line 79

def provision
  @logger.notify "Provisioning OpenStack"

  @hosts.each do |host|
    host[:vmhostname] = generate_host_name
    @logger.debug "Provisioning #{host.name} (#{host[:vmhostname]})"
    options = {
      :flavor_ref => flavor(host[:flavor]).id,
      :image_ref => image(host[:image]).id,
      :nics => [ {'net_id' => network(@options[:openstack_network]).id } ],
      :name => host[:vmhostname],
    }
    if @options[:openstack_keyname]
      @logger.debug "Adding optional key_name #{@options[:openstack_keyname]} to #{host.name} (#{host[:vmhostname]})"
      options[:key_name] = @options[:openstack_keyname]
    end
    vm = @compute_client.servers.create(options)

    #wait for the new instance to start up
    start = Time.now
    try = 1
    attempts = @options[:timeout].to_i / SLEEPWAIT

    while try <= attempts
      begin
        vm.wait_for(5) { ready? }
        break
      rescue Fog::Errors::TimeoutError => e
        if try >= attempts
          @logger.debug "Failed to connect to new OpenStack instance #{host.name} (#{host[:vmhostname]})"
          raise e
        end
        @logger.debug "Timeout connecting to instance #{host.name} (#{host[:vmhostname]}), trying again..."
      end
      sleep SLEEPWAIT
      try += 1
    end

    # Associate a public IP to the server
    # Create if there are no floating ips available
    #
    ip = @compute_client.addresses.find { |ip| ip.instance_id.nil? }
    if ip.nil?
      @logger.debug "Creating IP for #{host.name} (#{host[:vmhostname]})"
      ip = @compute_client.addresses.create
    end
    ip.server = vm
    host[:ip] = ip.ip
    @logger.debug "OpenStack host #{host.name} (#{host[:vmhostname]}) assigned ip: #{host[:ip]}"

    #set metadata
    vm..update({:jenkins_build_url => @options[:jenkins_build_url].to_s,
                        :department        => @options[:department].to_s,
                        :project           => @options[:project].to_s })
    @vms << vm

    #enable root if user is not root
    enable_root_on_hosts()
  end
end