Class: Beaker::OpenStack
- Inherits:
-
Hypervisor
- Object
- Hypervisor
- Beaker::OpenStack
- 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
Constants included from HostPrebuiltSteps
HostPrebuiltSteps::APT_CFG, HostPrebuiltSteps::CUMULUS_PACKAGES, HostPrebuiltSteps::DEBIAN_PACKAGES, HostPrebuiltSteps::ETC_HOSTS_PATH, HostPrebuiltSteps::ETC_HOSTS_PATH_SOLARIS, HostPrebuiltSteps::FREEBSD_PACKAGES, HostPrebuiltSteps::IPS_PKG_REPO, HostPrebuiltSteps::NTPSERVER, HostPrebuiltSteps::PSWINDOWS_PACKAGES, HostPrebuiltSteps::ROOT_KEYS_SCRIPT, HostPrebuiltSteps::ROOT_KEYS_SYNC_CMD, HostPrebuiltSteps::SLES10_PACKAGES, HostPrebuiltSteps::SLES_PACKAGES, HostPrebuiltSteps::TRIES, HostPrebuiltSteps::UNIX_PACKAGES, HostPrebuiltSteps::WINDOWS_PACKAGES
Instance Method Summary collapse
-
#cleanup ⇒ Object
Destroy any OpenStack instances.
-
#enable_root(host) ⇒ Object
enable root on a single host (the current one presumably) but only if the username isn’t ‘root’.
-
#enable_root_on_hosts ⇒ void
private
Enables root access for a host when username is not root This method ripped from the aws_sdk implementation and is probably wrong because it iterates on a collection when there’s no guarantee the collection has all been brought up in openstack yet and will thus explode.
-
#flavor(f) ⇒ String
Provided a flavor name return the OpenStack id for that flavor.
-
#image(i) ⇒ String
Provided an image name return the OpenStack id for that image.
-
#initialize(openstack_hosts, options) ⇒ OpenStack
constructor
Create a new instance of the OpenStack hypervisor object.
-
#key_name(host) ⇒ String
private
Get key_name from options or generate a new rsa key and add it to OpenStack keypairs.
-
#network(n) ⇒ String
Provided a network name return the OpenStack id for that network.
-
#provision ⇒ Object
Create new instances in OpenStack.
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
Constructor Details
#initialize(openstack_hosts, options) ⇒ OpenStack
Create a new instance of the OpenStack hypervisor object
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 53 |
# File 'lib/beaker/hypervisor/openstack.rb', line 23 def initialize(openstack_hosts, ) require 'fog' @options = @logger = [: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], :openstack_tenant => @options[:openstack_tenant]) 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
#cleanup ⇒ Object
Destroy any OpenStack instances
154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 |
# File 'lib/beaker/hypervisor/openstack.rb', line 154 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 if @options[:openstack_keyname].nil? @logger.debug "Deleting random keypair" @compute_client.delete_key_pair vm.name end end end |
#enable_root(host) ⇒ Object
enable root on a single host (the current one presumably) but only if the username isn’t ‘root’
186 187 188 189 190 191 192 193 |
# File 'lib/beaker/hypervisor/openstack.rb', line 186 def enable_root(host) if host['user'] != 'root' copy_ssh_to_root(host, @options) enable_root_login(host, @options) host['user'] = 'root' host.close end end |
#enable_root_on_hosts ⇒ 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 This method ripped from the aws_sdk implementation and is probably wrong because it iterates on a collection when there’s no guarantee the collection has all been brought up in openstack yet and will thus explode
178 179 180 181 182 |
# File 'lib/beaker/hypervisor/openstack.rb', line 178 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
58 59 60 61 |
# File 'lib/beaker/hypervisor/openstack.rb', line 58 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
66 67 68 69 |
# File 'lib/beaker/hypervisor/openstack.rb', line 66 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 |
#key_name(host) ⇒ String
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.
Get key_name from options or generate a new rsa key and add it to OpenStack keypairs
201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 |
# File 'lib/beaker/hypervisor/openstack.rb', line 201 def key_name(host) if @options[:openstack_keyname] @logger.debug "Adding optional key_name #{@options[:openstack_keyname]} to #{host.name} (#{host[:vmhostname]})" @options[:openstack_keyname] else @logger.debug "Generate a new rsa key" key = OpenSSL::PKey::RSA.new 2048 type = key.ssh_type data = [ key.to_blob ].pack('m0') @logger.debug "Creating Openstack keypair for public key '#{type} #{data}'" @compute_client.create_key_pair host[:vmhostname], "#{type} #{data}" host['ssh'][:key_data] = [ key.to_pem ] host[:vmhostname] end end |
#network(n) ⇒ String
Provided a network name return the OpenStack id for that network
74 75 76 77 |
# File 'lib/beaker/hypervisor/openstack.rb', line 74 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 |
#provision ⇒ Object
Create new instances in OpenStack
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 139 140 141 142 143 144 145 146 147 148 149 150 151 |
# File 'lib/beaker/hypervisor/openstack.rb', line 80 def provision @logger.notify "Provisioning OpenStack" @hosts.each do |host| host[:vmhostname] = generate_host_name @logger.debug "Provisioning #{host.name} (#{host[:vmhostname]})" = { :flavor_ref => flavor(host[:flavor]).id, :image_ref => image(host[:image]).id, :nics => [ {'net_id' => network(@options[:openstack_network]).id } ], :name => host[:vmhostname], } [:key_name] = key_name(host) vm = @compute_client.servers.create() #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 # # Do we already have an address? @logger.debug vm.addresses begin if vm.addresses[@options[:openstack_network]] address = vm.addresses[@options[:openstack_network]].map{ |network| network['addr'] }.first end rescue NoMethodError @logger.debug "No current address retrievable from OpenStack data" end unless address 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 address = ip.ip end host[:ip] = address @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(host) end end |