Class: Beaker::GoogleComputeHelper
- Inherits:
-
Object
- Object
- Beaker::GoogleComputeHelper
- Defined in:
- lib/beaker/hypervisor/google_compute_helper.rb
Overview
Beaker helper module for doing API level Google Compute Engine interaction.
Defined Under Namespace
Classes: GoogleComputeError
Constant Summary collapse
- SLEEPWAIT =
5
- AUTH_URL =
'https://www.googleapis.com/auth/compute'
- API_VERSION =
'v1'
- BASE_URL =
"https://www.googleapis.com/compute/#{API_VERSION}/projects/"
- CENTOS_PROJECT =
'centos-cloud'
- DEBIAN_PROJECT =
'debian-cloud'
- DEFAULT_ZONE_NAME =
'us-central1-a'
- DEFAULT_MACHINE_TYPE =
'n1-highmem-2'
- DEFAULT_DISK_SIZE =
25
Instance Method Summary collapse
-
#authenticate(keyfile, password, email, start, attempts) ⇒ Object
Creates an authenticated connection to the Google Compute Engine API.
-
#create_disk(name, img, start, attempts) ⇒ Object
Create a Google Compute disk on the current connection.
-
#create_firewall(name, network, start, attempts) ⇒ Object
Create a Google Compute firewall on the current connection.
-
#create_instance(name, img, machineType, disk, start, attempts) ⇒ Object
Create a Google Compute instance on the current connection.
-
#default_network ⇒ Object
Determines the default Google Compute network based upon defaults and options.
-
#default_zone ⇒ Object
Determines the default Google Compute zone based upon options and defaults.
-
#delete_disk(name, start, attempts) ⇒ Object
Delete a Google Compute disk on the current connection.
-
#delete_firewall(name, start, attempts) ⇒ Object
Delete a Google Compute firewall on the current connection.
-
#delete_instance(name, start, attempts) ⇒ Object
Delete a Google Compute instance on the current connection.
-
#disk_delete_req(name) ⇒ Hash
Create a Google Compute disk delete request.
-
#disk_get_req(name) ⇒ Hash
Create a Google Compute get disk request.
-
#disk_insert_req(name, source) ⇒ Hash
Create a Google Compute disk create request.
-
#disk_list_req ⇒ Hash
Create a Google Compute list all disks request.
-
#execute(req, start, attempts) ⇒ Object
Executes a provided Google Compute request using a previously configured and authenticated Google Compute client connection.
-
#firewall_delete_req(name) ⇒ Hash
Create a Google Compute delete firewall request.
-
#firewall_get_req(name) ⇒ Hash
Create a Google Compute get firewall request.
-
#firewall_insert_req(name, network) ⇒ Hash
Create a Google Compute insert firewall request, open ports 443, 8140 and 61613.
-
#firewall_list_req ⇒ Hash
Create a Google Compute list firewall request.
-
#get_latest_image(platform, start, attempts) ⇒ Hash
Determines the latest image available for the provided platform name.
-
#get_machineType(start, attempts) ⇒ Hash
Determines the Google Compute machineType object based upon the selected gce_machine_type option.
-
#get_network(start, attempts) ⇒ Hash
Determines the Google Compute network object in use for the current connection.
-
#get_platform_project(name) ⇒ Object
Determines the Google Compute project which contains bases instances of type name.
-
#image_list_req(name) ⇒ Hash
Create a Google Compute list all images request.
-
#initialize(options) ⇒ GoogleComputeHelper
constructor
Create a new instance of the Google Compute Engine helper object.
-
#instance_delete_req(name) ⇒ Hash
Create a Google Compute instance delete request.
-
#instance_get_req(name) ⇒ Hash
Create a Google Compute get instance request.
-
#instance_insert_req(name, image, machineType, disk) ⇒ Hash
Create a Google Compute instance create request.
-
#instance_list_req ⇒ Hash
Create a Google Compute list instance request.
-
#instance_setMetadata_req(name, fingerprint, data) ⇒ Hash
Set tags on a Google Compute instance.
-
#list_disks(start, attempts) ⇒ Array[Hash]
Determines a list of existing Google Compute disks.
-
#list_firewalls(start, attempts) ⇒ Array[Hash]
Determines a list of existing Google Compute firewalls.
-
#list_instances(start, attempts) ⇒ Array[Hash]
Determines a list of existing Google Compute instances.
-
#machineType_get_req ⇒ Hash
Create a Google Compute machineType get request.
-
#network_get_req(name = 'default') ⇒ Hash
Create a Google Compute get network request.
-
#operation_get_req(name) ⇒ Hash
Create a Google Compute zone operation request.
-
#set_client(version) ⇒ Object
Create the Google APIClient object which will be used for accessing the Google Compute API.
-
#set_compute_api(version, start, attempts) ⇒ Object
Discover the currently active Google Compute API.
-
#setMetadata_on_instance(name, fingerprint, data, start, attempts) ⇒ Object
Add key/value pairs to a Google Compute instance on the current connection.
Constructor Details
#initialize(options) ⇒ GoogleComputeHelper
Create a new instance of the Google Compute Engine helper object
32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
# File 'lib/beaker/hypervisor/google_compute_helper.rb', line 32 def initialize() @options = @logger = [:logger] try = 1 attempts = @options[:timeout].to_i / SLEEPWAIT start = Time.now set_client(Beaker::Version::STRING) set_compute_api(API_VERSION, start, attempts) raise 'You must specify a gce_project for Google Compute Engine instances!' unless @options[:gce_project] raise 'You must specify a gce_keyfile for Google Compute Engine instances!' unless @options[:gce_keyfile] raise 'You must specify a gce_password for Google Compute Engine instances!' unless @options[:gce_password] raise 'You must specify a gce_email for Google Compute Engine instances!' unless @options[:gce_email] authenticate(@options[:gce_keyfile], @options[:gce_password], @options[:gce_email], start, attempts) end |
Instance Method Details
#authenticate(keyfile, password, email, start, attempts) ⇒ Object
Creates an authenticated connection to the Google Compute Engine API
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 |
# File 'lib/beaker/hypervisor/google_compute_helper.rb', line 113 def authenticate(keyfile, password, email, start, attempts) # OAuth authentication, using the service account key = Google::APIClient::PKCS12.load_key(keyfile, password) service_account = Google::APIClient::JWTAsserter.new( email, AUTH_URL, key) try = (Time.now - start) / SLEEPWAIT while try <= attempts begin @client. = service_account. @logger.debug("Authorized to use Google Compute") return rescue => e @logger.debug("Failed to authorize to use Google Compute") if try >= attempts raise e end end try += 1 end end |
#create_disk(name, img, start, attempts) ⇒ Object
Create a Google Compute disk on the current connection
270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 |
# File 'lib/beaker/hypervisor/google_compute_helper.rb', line 270 def create_disk(name, img, start, attempts) #create a new boot disk for this instance disk = execute( disk_insert_req( name, img['selfLink'] ), start, attempts ) status = '' try = (Time.now - start) / SLEEPWAIT while status !~ /READY/ and try <= attempts begin disk = execute( disk_get_req( name ), start, attempts ) status = disk['status'] rescue GoogleComputeError => e @logger.debug("Waiting for #{name} disk creation") sleep(SLEEPWAIT) end try += 1 end if status == '' raise "Unable to create disk #{name}" end disk end |
#create_firewall(name, network, start, attempts) ⇒ Object
Create a Google Compute firewall on the current connection
259 260 261 |
# File 'lib/beaker/hypervisor/google_compute_helper.rb', line 259 def create_firewall(name, network, start, attempts) execute( firewall_insert_req( name, network['selfLink'] ), start, attempts ) end |
#create_instance(name, img, machineType, disk, start, attempts) ⇒ Object
Create a Google Compute instance on the current connection
301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 |
# File 'lib/beaker/hypervisor/google_compute_helper.rb', line 301 def create_instance(name, img, machineType, disk, start, attempts) #add a new instance of the image instance = execute( instance_insert_req( name, img['selfLink'], machineType['selfLink'], disk['selfLink'] ), start, attempts) status = '' try = (Time.now - start) / SLEEPWAIT while status !~ /RUNNING/ and try <= attempts begin instance = execute( instance_get_req( name ), start, attempts ) status = instance['status'] rescue GoogleComputeError => e @logger.debug("Waiting for #{name} instance creation") sleep(SLEEPWAIT) end try += 1 end if status == '' raise "Unable to create instance #{name}" end instance end |
#default_network ⇒ Object
Determines the default Google Compute network based upon defaults and options
58 59 60 |
# File 'lib/beaker/hypervisor/google_compute_helper.rb', line 58 def default_network BASE_URL + @options[:gce_project] + '/global/networks/default' end |
#default_zone ⇒ Object
Determines the default Google Compute zone based upon options and defaults
52 53 54 |
# File 'lib/beaker/hypervisor/google_compute_helper.rb', line 52 def default_zone BASE_URL + @options[:gce_project] + '/global/zones/' + DEFAULT_ZONE_NAME end |
#delete_disk(name, start, attempts) ⇒ Object
Delete a Google Compute disk on the current connection
380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 |
# File 'lib/beaker/hypervisor/google_compute_helper.rb', line 380 def delete_disk(name, start, attempts) result = execute( disk_delete_req( name ), start, attempts ) #ensure deletion of disk try = (Time.now - start) / SLEEPWAIT while try <= attempts begin disk = execute( disk_get_req( name ), start, attempts ) @logger.debug("Waiting for #{name} disk deletion") sleep(SLEEPWAIT) rescue GoogleComputeError => e @logger.debug("#{name} disk deleted!") return end try += 1 end @logger.debug("#{name} disk was not removed before timeout, may still exist") end |
#delete_firewall(name, start, attempts) ⇒ Object
Delete a Google Compute firewall on the current connection
404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 |
# File 'lib/beaker/hypervisor/google_compute_helper.rb', line 404 def delete_firewall(name, start, attempts) result = execute( firewall_delete_req( name ), start, attempts ) #ensure deletion of disk try = (Time.now - start) / SLEEPWAIT while try <= attempts begin firewall = execute( firewall_get_req( name ), start, attempts ) @logger.debug("Waiting for #{name} firewall deletion") sleep(SLEEPWAIT) rescue GoogleComputeError => e @logger.debug("#{name} firewall deleted!") return end try += 1 end @logger.debug("#{name} firewall was not removed before timeout, may still exist") end |
#delete_instance(name, start, attempts) ⇒ Object
Delete a Google Compute instance on the current connection
356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 |
# File 'lib/beaker/hypervisor/google_compute_helper.rb', line 356 def delete_instance(name, start, attempts) result = execute( instance_delete_req( name ), start, attempts ) #ensure deletion of instance try = (Time.now - start) / SLEEPWAIT while try <= attempts begin result = execute( instance_get_req( name ), start, attempts ) @logger.debug("Waiting for #{name} instance deletion") sleep(SLEEPWAIT) rescue GoogleComputeError => e @logger.debug("#{name} instance deleted!") return end try += 1 end @logger.debug("#{name} instance was not removed before timeout, may still exist") end |
#disk_delete_req(name) ⇒ Hash
Create a Google Compute disk delete request
449 450 451 452 |
# File 'lib/beaker/hypervisor/google_compute_helper.rb', line 449 def disk_delete_req(name) { :api_method => @compute.disks.delete, :parameters => { 'project' => @options[:gce_project], 'zone' => DEFAULT_ZONE_NAME, 'disk' => name } } end |
#disk_get_req(name) ⇒ Hash
Create a Google Compute get disk request
441 442 443 444 |
# File 'lib/beaker/hypervisor/google_compute_helper.rb', line 441 def disk_get_req(name) { :api_method => @compute.disks.get, :parameters => { 'project' => @options[:gce_project], 'zone' => DEFAULT_ZONE_NAME, 'disk' => name } } end |
#disk_insert_req(name, source) ⇒ Hash
Create a Google Compute disk create request
458 459 460 461 462 |
# File 'lib/beaker/hypervisor/google_compute_helper.rb', line 458 def disk_insert_req(name, source) { :api_method => @compute.disks.insert, :parameters => { 'project' => @options[:gce_project], 'zone' => DEFAULT_ZONE_NAME, 'sourceImage' => source }, :body_object => { 'name' => name, 'sizeGb' => DEFAULT_DISK_SIZE } } end |
#disk_list_req ⇒ Hash
Create a Google Compute list all disks request
433 434 435 436 |
# File 'lib/beaker/hypervisor/google_compute_helper.rb', line 433 def disk_list_req { :api_method => @compute.disks.list, :parameters => { 'project' => @options[:gce_project], 'zone' => DEFAULT_ZONE_NAME } } end |
#execute(req, start, attempts) ⇒ Object
Executes a provided Google Compute request using a previously configured and authenticated Google Compute client connection
142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 |
# File 'lib/beaker/hypervisor/google_compute_helper.rb', line 142 def execute req, start, attempts last_error = parsed = nil try = (Time.now - start) / SLEEPWAIT while try <= attempts begin result = @client.execute(req) parsed = JSON.parse(result.body) if not result.success? error_code = parsed["error"] ? parsed["error"]["code"] : 0 if error_code == 404 raise GoogleComputeError, "Resource Not Found: #{result.body}" elsif error_code == 400 raise GoogleComputeError, "Bad Request: #{result.body}" else raise GoogleComputeError, "Error attempting Google Compute API execute: #{result.body}" end end return parsed #retry errors rescue Faraday::Error::ConnectionFailed => e @logger.debug "ConnectionFailed attempting Google Compute execute command" try += 1 last_error = e end end #we only get down here if we've used up all our tries raise last_error end |
#firewall_delete_req(name) ⇒ Hash
Create a Google Compute delete firewall request
488 489 490 491 |
# File 'lib/beaker/hypervisor/google_compute_helper.rb', line 488 def firewall_delete_req(name) { :api_method => @compute.firewalls.delete, :parameters => { 'project' => @options[:gce_project], 'zone' => DEFAULT_ZONE_NAME, 'firewall' => name } } end |
#firewall_get_req(name) ⇒ Hash
Create a Google Compute get firewall request
467 468 469 470 |
# File 'lib/beaker/hypervisor/google_compute_helper.rb', line 467 def firewall_get_req(name) { :api_method => @compute.firewalls.get, :parameters => { 'project' => @options[:gce_project], 'zone' => DEFAULT_ZONE_NAME, 'firewall' => name } } end |
#firewall_insert_req(name, network) ⇒ Hash
Create a Google Compute insert firewall request, open ports 443, 8140 and 61613
476 477 478 479 480 481 482 483 |
# File 'lib/beaker/hypervisor/google_compute_helper.rb', line 476 def firewall_insert_req(name, network) { :api_method => @compute.firewalls.insert, :parameters => { 'project' => @options[:gce_project], 'zone' => DEFAULT_ZONE_NAME }, :body_object => { 'name' => name, 'allowed'=> [ { 'IPProtocol' => 'tcp', "ports" => [ '443', '8140', '61613', '8080', '8081' ]} ], 'network'=> network, 'sourceRanges' => [ "0.0.0.0/0" ] } } end |
#firewall_list_req ⇒ Hash
Create a Google Compute list firewall request
495 496 497 498 |
# File 'lib/beaker/hypervisor/google_compute_helper.rb', line 495 def firewall_list_req() { :api_method => @compute.firewalls.list, :parameters => { 'project' => @options[:gce_project], 'zone' => DEFAULT_ZONE_NAME } } end |
#get_latest_image(platform, start, attempts) ⇒ Hash
Determines the latest image available for the provided platform name. We currently only support debian-7 and centos-6 platforms.
178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 |
# File 'lib/beaker/hypervisor/google_compute_helper.rb', line 178 def get_latest_image(platform, start, attempts) #use the platform version numbers instead of codenames platform = platform.with_version_number #break up my platform for information platform_name, platform_version, platform_extra_info = platform.split('-', 3) #find latest image to use result = execute( image_list_req(get_platform_project(platform_name)), start, attempts ) images = result["items"] #reject images of the wrong version of the given platform images.delete_if { |image| image['name'] !~ /^#{platform_name}-#{platform_version}/} #reject deprecated images images.delete_if { |image| image['deprecated']} #find a match based upon platform type if images.length != 1 raise "Unable to find a single matching image for #{platform}, found #{images}" end images[0] end |
#get_machineType(start, attempts) ⇒ Hash
Determines the Google Compute machineType object based upon the selected gce_machine_type option
203 204 205 |
# File 'lib/beaker/hypervisor/google_compute_helper.rb', line 203 def get_machineType(start, attempts) execute( machineType_get_req, start, attempts ) end |
#get_network(start, attempts) ⇒ Hash
Determines the Google Compute network object in use for the current connection
213 214 215 |
# File 'lib/beaker/hypervisor/google_compute_helper.rb', line 213 def get_network(start, attempts) execute( network_get_req, start, attempts) end |
#get_platform_project(name) ⇒ Object
Determines the Google Compute project which contains bases instances of type name
66 67 68 69 70 71 72 73 74 |
# File 'lib/beaker/hypervisor/google_compute_helper.rb', line 66 def get_platform_project(name) if name =~ /debian/ return DEBIAN_PROJECT elsif name =~ /centos/ return CENTOS_PROJECT else raise "Unsupported platform for Google Compute Engine: #{name}" end end |
#image_list_req(name) ⇒ Hash
Create a Google Compute list all images request
426 427 428 429 |
# File 'lib/beaker/hypervisor/google_compute_helper.rb', line 426 def image_list_req(name) { :api_method => @compute.images.list, :parameters => { 'project' => name } } end |
#instance_delete_req(name) ⇒ Hash
Create a Google Compute instance delete request
545 546 547 548 |
# File 'lib/beaker/hypervisor/google_compute_helper.rb', line 545 def instance_delete_req(name) { :api_method => @compute.instances.delete, :parameters => { 'project' => @options[:gce_project], 'zone' => DEFAULT_ZONE_NAME, 'instance' => name } } end |
#instance_get_req(name) ⇒ Hash
Create a Google Compute get instance request
537 538 539 540 |
# File 'lib/beaker/hypervisor/google_compute_helper.rb', line 537 def instance_get_req(name) { :api_method => @compute.instances.get, :parameters => { 'project' => @options[:gce_project], 'zone' => DEFAULT_ZONE_NAME, 'instance' => name } } end |
#instance_insert_req(name, image, machineType, disk) ⇒ Hash
Create a Google Compute instance create request
556 557 558 559 560 561 562 563 564 565 566 567 |
# File 'lib/beaker/hypervisor/google_compute_helper.rb', line 556 def instance_insert_req(name, image, machineType, disk) { :api_method => @compute.instances.insert, :parameters => { 'project' => @options[:gce_project], 'zone' => DEFAULT_ZONE_NAME }, :body_object => { 'name' => name, 'image' => image, 'zone' => default_zone, 'machineType' => machineType, 'disks' => [ { 'source' => disk, 'type' => 'PERSISTENT', 'boot' => 'true'} ], 'networkInterfaces' => [ { 'accessConfigs' => [{ 'type' => 'ONE_TO_ONE_NAT', 'name' => 'External NAT' }], 'network' => default_network } ] } } end |
#instance_list_req ⇒ Hash
Create a Google Compute list instance request
529 530 531 532 |
# File 'lib/beaker/hypervisor/google_compute_helper.rb', line 529 def instance_list_req { :api_method => @compute.instances.list, :parameters => { 'project' => @options[:gce_project], 'zone' => DEFAULT_ZONE_NAME } } end |
#instance_setMetadata_req(name, fingerprint, data) ⇒ Hash
Set tags on a Google Compute instance
518 519 520 521 522 523 524 525 |
# File 'lib/beaker/hypervisor/google_compute_helper.rb', line 518 def instance_setMetadata_req(name, fingerprint, data) { :api_method => @compute.instances., :parameters => { 'project' => @options[:gce_project], 'zone' => DEFAULT_ZONE_NAME, 'instance' => name }, :body_object => { 'kind' => 'compute#metadata', 'fingerprint' => fingerprint, 'items' => data } } end |
#list_disks(start, attempts) ⇒ Array[Hash]
Determines a list of existing Google Compute disks
234 235 236 237 |
# File 'lib/beaker/hypervisor/google_compute_helper.rb', line 234 def list_disks(start, attempts) disks = execute( disk_list_req(), start, attempts ) disks["items"] end |
#list_firewalls(start, attempts) ⇒ Array[Hash]
Determines a list of existing Google Compute firewalls
245 246 247 248 249 250 |
# File 'lib/beaker/hypervisor/google_compute_helper.rb', line 245 def list_firewalls(start, attempts) result = execute( firewall_list_req(), start, attempts ) firewalls = result["items"] firewalls.delete_if{|f| f['name'] =~ /default-allow-internal|default-ssh/} firewalls end |
#list_instances(start, attempts) ⇒ Array[Hash]
Determines a list of existing Google Compute instances
223 224 225 226 |
# File 'lib/beaker/hypervisor/google_compute_helper.rb', line 223 def list_instances(start, attempts) instances = execute( instance_list_req(), start, attempts ) instances["items"] end |
#machineType_get_req ⇒ Hash
Create a Google Compute machineType get request
571 572 573 574 |
# File 'lib/beaker/hypervisor/google_compute_helper.rb', line 571 def machineType_get_req() { :api_method => @compute.machine_types.get, :parameters => { 'project' => @options[:gce_project], 'zone' => DEFAULT_ZONE_NAME, 'machineType' => @options[:gce_machine_type] || DEFAULT_MACHINE_TYPE } } end |
#network_get_req(name = 'default') ⇒ Hash
Create a Google Compute get network request
503 504 505 506 |
# File 'lib/beaker/hypervisor/google_compute_helper.rb', line 503 def network_get_req(name = 'default') { :api_method => @compute.networks.get, :parameters => { 'project' => @options[:gce_project], 'zone' => DEFAULT_ZONE_NAME, 'network' => name } } end |
#operation_get_req(name) ⇒ Hash
Create a Google Compute zone operation request
510 511 512 513 |
# File 'lib/beaker/hypervisor/google_compute_helper.rb', line 510 def operation_get_req(name) { :api_method => @compute.zone_operations.get, :parameters => { 'project' => @options[:gce_project], 'zone' => DEFAULT_ZONE_NAME, 'operation' => name } } end |
#set_client(version) ⇒ Object
Create the Google APIClient object which will be used for accessing the Google Compute API
78 79 80 |
# File 'lib/beaker/hypervisor/google_compute_helper.rb', line 78 def set_client(version) @client = Google::APIClient.new({:application_name => "Beaker", :application_version => version}) end |
#set_compute_api(version, start, attempts) ⇒ Object
Discover the currently active Google Compute API
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
# File 'lib/beaker/hypervisor/google_compute_helper.rb', line 88 def set_compute_api version, start, attempts try = (Time.now - start) / SLEEPWAIT while try <= attempts begin @compute = @client.discovered_api('compute', version) @logger.debug("Google Compute API discovered") return rescue => e @logger.debug("Failed to discover Google Compute API") if try >= attempts raise e end end try += 1 end end |
#setMetadata_on_instance(name, fingerprint, data, start, attempts) ⇒ Object
Add key/value pairs to a Google Compute instance on the current connection
330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 |
# File 'lib/beaker/hypervisor/google_compute_helper.rb', line 330 def setMetadata_on_instance(name, fingerprint, data, start, attempts) zone_operation = execute( instance_setMetadata_req( name, fingerprint, data), start, attempts ) status = '' try = (Time.now - start) / SLEEPWAIT while status !~ /DONE/ and try <= attempts begin operation = execute( operation_get_req( zone_operation['name'] ), start, attempts ) status = operation['status'] rescue GoogleComputeError => e @logger.debug("Waiting for tags to be added to #{name}") sleep(SLEEPWAIT) end try += 1 end if status == '' raise "Unable to set metaData (#{.to_s}) on #{name}" end zone_operation end |