beaker 3.20.0 → 3.21.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +8 -8
  2. data/beaker.gemspec +4 -5
  3. data/docs/how_to/hypervisors/README.md +7 -3
  4. data/docs/tutorials/quick_start_rake_tasks.md +1 -1
  5. data/lib/beaker/command.rb +1 -1
  6. data/lib/beaker/host.rb +6 -4
  7. data/lib/beaker/host/windows/exec.rb +10 -0
  8. data/lib/beaker/host/windows/pkg.rb +1 -29
  9. data/lib/beaker/host_prebuilt_steps.rb +1 -0
  10. data/lib/beaker/hypervisor.rb +26 -37
  11. data/lib/beaker/ssh_connection.rb +8 -15
  12. data/lib/beaker/version.rb +1 -1
  13. data/spec/beaker/dsl/install_utils/windows_utils_spec.rb +1 -1
  14. data/spec/beaker/host/windows/exec_spec.rb +18 -0
  15. data/spec/beaker/host/windows/pkg_spec.rb +0 -7
  16. data/spec/beaker/host_prebuilt_steps_spec.rb +1 -0
  17. data/spec/beaker/host_spec.rb +31 -40
  18. data/spec/beaker/hypervisor/hypervisor_spec.rb +20 -34
  19. data/spec/beaker/ssh_connection_spec.rb +18 -19
  20. data/spec/spec_helper.rb +0 -1
  21. metadata +23 -57
  22. data/docs/how_to/hypervisors/aws.md +0 -149
  23. data/docs/how_to/hypervisors/ec2.md +0 -81
  24. data/docs/how_to/hypervisors/google_compute_engine.md +0 -41
  25. data/docs/how_to/hypervisors/vagrant.md +0 -165
  26. data/docs/how_to/hypervisors/vagrant_hosts_file_examples.md +0 -60
  27. data/docs/how_to/hypervisors/vagrant_libvirt.md +0 -58
  28. data/docs/how_to/hypervisors/vmware_fusion.md +0 -36
  29. data/docs/how_to/hypervisors/vsphere.md +0 -54
  30. data/lib/beaker/hypervisor/aws_sdk.rb +0 -989
  31. data/lib/beaker/hypervisor/ec2_helper.rb +0 -41
  32. data/lib/beaker/hypervisor/fusion.rb +0 -65
  33. data/lib/beaker/hypervisor/google_compute.rb +0 -164
  34. data/lib/beaker/hypervisor/google_compute_helper.rb +0 -577
  35. data/lib/beaker/hypervisor/vagrant.rb +0 -286
  36. data/lib/beaker/hypervisor/vagrant_custom.rb +0 -11
  37. data/lib/beaker/hypervisor/vagrant_fusion.rb +0 -17
  38. data/lib/beaker/hypervisor/vagrant_libvirt.rb +0 -41
  39. data/lib/beaker/hypervisor/vagrant_parallels.rb +0 -18
  40. data/lib/beaker/hypervisor/vagrant_virtualbox.rb +0 -76
  41. data/lib/beaker/hypervisor/vagrant_workstation.rb +0 -13
  42. data/lib/beaker/hypervisor/vsphere.rb +0 -85
  43. data/lib/beaker/hypervisor/vsphere_helper.rb +0 -204
  44. data/spec/beaker/hypervisor/aws_sdk_spec.rb +0 -980
  45. data/spec/beaker/hypervisor/ec2_helper_spec.rb +0 -44
  46. data/spec/beaker/hypervisor/fusion_spec.rb +0 -41
  47. data/spec/beaker/hypervisor/vagrant_custom_spec.rb +0 -46
  48. data/spec/beaker/hypervisor/vagrant_fusion_spec.rb +0 -32
  49. data/spec/beaker/hypervisor/vagrant_libvirt_spec.rb +0 -61
  50. data/spec/beaker/hypervisor/vagrant_parallels_spec.rb +0 -44
  51. data/spec/beaker/hypervisor/vagrant_spec.rb +0 -479
  52. data/spec/beaker/hypervisor/vagrant_virtualbox_spec.rb +0 -44
  53. data/spec/beaker/hypervisor/vagrant_workstation_spec.rb +0 -32
  54. data/spec/beaker/hypervisor/vsphere_helper_spec.rb +0 -163
  55. data/spec/beaker/hypervisor/vsphere_spec.rb +0 -90
@@ -1,41 +0,0 @@
1
- module Beaker
2
- class EC2Helper
3
- # Return a list of open ports for testing based on a hosts role
4
- #
5
- # @todo horribly hard-coded
6
- # @param [Host] host to find ports for
7
- # @return [Array<Number>] array of port numbers
8
- # @api private
9
- def self.amiports(host)
10
- ports = [22, 61613, 8139]
11
-
12
- roles = host['roles']
13
-
14
- if roles.include? 'database'
15
- ports << 5432
16
- ports << 8080
17
- ports << 8081
18
- end
19
-
20
- if roles.include? 'master'
21
- ports << 8140
22
- end
23
-
24
- if roles.include? 'dashboard'
25
- ports << 443
26
- ports << 4433
27
- ports << 4435
28
- end
29
-
30
- # If they only specified one port in the host config file, YAML will have converted it
31
- # into a string, but if it was more than one, an array.
32
- user_ports = []
33
- if host.has_key?('additional_ports')
34
- user_ports = host['additional_ports'].is_a?(Array) ? host['additional_ports'] : [host['additional_ports']]
35
- end
36
-
37
- additional_ports = ports + user_ports
38
- additional_ports.uniq
39
- end
40
- end
41
- end
@@ -1,65 +0,0 @@
1
- module Beaker
2
- class Fusion < Beaker::Hypervisor
3
-
4
- def initialize(fusion_hosts, options)
5
- require 'rubygems' unless defined?(Gem)
6
- begin
7
- require 'fission'
8
- rescue LoadError
9
- raise "Unable to load fission, please ensure it is installed!"
10
- end
11
- @logger = options[:logger]
12
- @options = options
13
- @hosts = fusion_hosts
14
- #check preconditions for fusion
15
- @hosts.each do |host|
16
- raise "You must specify a snapshot for Fusion instances, no snapshot defined for #{host.name}!" unless host["snapshot"]
17
- end
18
- @fission = Fission::VM
19
- end
20
-
21
- def provision
22
- available = @fission.all.data.collect{|vm| vm.name}.sort.join(", ")
23
- @logger.notify "Available VM names: #{available}"
24
-
25
- @hosts.each do |host|
26
- vm_name = host["vmname"] || host.name
27
- vm = @fission.new vm_name
28
- raise "Could not find VM '#{vm_name}' for #{host.name}!" unless vm.exists?
29
-
30
- vm_snapshots = vm.snapshots.data
31
- if vm_snapshots.nil? or vm_snapshots.empty?
32
- raise "No snapshots available for VM #{host.name} (vmname: '#{vm_name}')"
33
- end
34
-
35
- available_snapshots = vm_snapshots.sort.join(", ")
36
- @logger.notify "Available snapshots for #{host.name}: #{available_snapshots}"
37
- snap_name = host["snapshot"]
38
- raise "Could not find snapshot '#{snap_name}' for host #{host.name}!" unless vm.snapshots.data.include? snap_name
39
-
40
- @logger.notify "Reverting #{host.name} to snapshot '#{snap_name}'"
41
- start = Time.now
42
- vm.revert_to_snapshot snap_name
43
- while vm.running?.data
44
- sleep 1
45
- end
46
- time = Time.now - start
47
- @logger.notify "Spent %.2f seconds reverting" % time
48
-
49
- @logger.notify "Resuming #{host.name}"
50
- start = Time.now
51
- vm.start :headless => true
52
- until vm.running?.data
53
- sleep 1
54
- end
55
- time = Time.now - start
56
- @logger.notify "Spent %.2f seconds resuming VM" % time
57
- end
58
- end #revert_fusion
59
-
60
- def cleanup
61
- @logger.notify "No cleanup for fusion boxes"
62
- end
63
-
64
- end
65
- end
@@ -1,164 +0,0 @@
1
- require 'time'
2
-
3
- module Beaker
4
- #Beaker support for the Google Compute Engine.
5
- class GoogleCompute < Beaker::Hypervisor
6
-
7
- SLEEPWAIT = 5
8
- #number of hours before an instance is considered a zombie
9
- ZOMBIE = 3
10
-
11
- #Create the array of metaData, each member being a hash with a :key and a :value. Sets
12
- #:department, :project and :jenkins_build_url.
13
- def format_metadata
14
- [ {:key => :department, :value => @options[:department]},
15
- {:key => :project, :value => @options[:project]},
16
- {:key => :jenkins_build_url, :value => @options[:jenkins_build_url]} ].delete_if { |member| member[:value].nil? or member[:value].empty?}
17
- end
18
-
19
- #Create a new instance of the Google Compute Engine hypervisor object
20
- #@param [<Host>] google_hosts The array of google hosts to provision, may ONLY be of platforms /centos-6-.*/ and
21
- # /debian-7-.*/. We currently only support the Google Compute provided templates.
22
- #@param [Hash{Symbol=>String}] options The options hash containing configuration values
23
- #@option options [String] :gce_project The Google Compute Project name to connect to
24
- #@option options [String] :gce_keyfile The location of the Google Compute service account keyfile
25
- #@option options [String] :gce_password The password for the Google Compute service account key
26
- #@option options [String] :gce_email The email address for the Google Compute service account
27
- #@option options [String] :gce_machine_type A Google Compute machine type used to create instances, defaults to n1-highmem-2
28
- #@option options [Integer] :timeout The amount of time to attempt execution before quiting and exiting with failure
29
- def initialize(google_hosts, options)
30
- require 'beaker/hypervisor/google_compute_helper'
31
- @options = options
32
- @logger = options[:logger]
33
- @hosts = google_hosts
34
- @firewall = ''
35
- @gce_helper = GoogleComputeHelper.new(options)
36
- end
37
-
38
- #Create and configure virtual machines in the Google Compute Engine, including their associated disks and firewall rules
39
- #Currently ONLY supports Google Compute provided templates of CENTOS-6 and DEBIAN-7
40
- def provision
41
- try = 1
42
- attempts = @options[:timeout].to_i / SLEEPWAIT
43
- start = Time.now
44
-
45
- #get machineType resource, used by all instances
46
- machineType = @gce_helper.get_machineType(start, attempts)
47
-
48
- #set firewall to open pe ports
49
- network = @gce_helper.get_network(start, attempts)
50
- @firewall = generate_host_name
51
- @gce_helper.create_firewall(@firewall, network, start, attempts)
52
-
53
- @logger.debug("Created Google Compute firewall #{@firewall}")
54
-
55
-
56
- @hosts.each do |host|
57
- gplatform = Platform.new(host[:image] || host[:platform])
58
- img = @gce_helper.get_latest_image(gplatform, start, attempts)
59
- host['diskname'] = generate_host_name
60
- disk = @gce_helper.create_disk(host['diskname'], img, start, attempts)
61
- @logger.debug("Created Google Compute disk for #{host.name}: #{host['diskname']}")
62
-
63
- #create new host name
64
- host['vmhostname'] = generate_host_name
65
- #add a new instance of the image
66
- instance = @gce_helper.create_instance(host['vmhostname'], img, machineType, disk, start, attempts)
67
- @logger.debug("Created Google Compute instance for #{host.name}: #{host['vmhostname']}")
68
-
69
- #add metadata to instance, if there is any to set
70
- mdata = format_metadata
71
- if not mdata.empty?
72
- @gce_helper.setMetadata_on_instance(host['vmhostname'], instance['metadata']['fingerprint'],
73
- mdata,
74
- start, attempts)
75
- @logger.debug("Added tags to Google Compute instance #{host.name}: #{host['vmhostname']}")
76
- end
77
-
78
- #get ip for this host
79
- host['ip'] = instance['networkInterfaces'][0]['accessConfigs'][0]['natIP']
80
-
81
- #configure ssh
82
- default_user = host['user']
83
- host['user'] = 'google_compute'
84
-
85
- disable_se_linux(host, @options)
86
- copy_ssh_to_root(host, @options)
87
- enable_root_login(host, @options)
88
- host['user'] = default_user
89
-
90
- #shut down connection, will reconnect on next exec
91
- host.close
92
-
93
- @logger.debug("Instance ready: #{host['vmhostname']} for #{host.name}}")
94
- end
95
- end
96
-
97
- #Shutdown and destroy virtual machines in the Google Compute Engine, including their associated disks and firewall rules
98
- def cleanup()
99
- attempts = @options[:timeout].to_i / SLEEPWAIT
100
- start = Time.now
101
-
102
- @gce_helper.delete_firewall(@firewall, start, attempts)
103
-
104
- @hosts.each do |host|
105
- @gce_helper.delete_instance(host['vmhostname'], start, attempts)
106
- @logger.debug("Deleted Google Compute instance #{host['vmhostname']} for #{host.name}")
107
- @gce_helper.delete_disk(host['diskname'], start, attempts)
108
- @logger.debug("Deleted Google Compute disk #{host['diskname']} for #{host.name}")
109
- end
110
-
111
- end
112
-
113
- #Shutdown and destroy Google Compute instances (including their associated disks and firewall rules)
114
- #that have been alive longer than ZOMBIE hours.
115
- def kill_zombies(max_age = ZOMBIE)
116
- now = start = Time.now
117
- attempts = @options[:timeout].to_i / SLEEPWAIT
118
-
119
- #get rid of old instances
120
- instances = @gce_helper.list_instances(start, attempts)
121
- if instances
122
- instances.each do |instance|
123
- created = Time.parse(instance['creationTimestamp'])
124
- alive = (now - created ) /60 /60
125
- if alive >= max_age
126
- #kill it with fire!
127
- @logger.debug("Deleting zombie instance #{instance['name']}")
128
- @gce_helper.delete_instance( instance['name'], start, attempts )
129
- end
130
- end
131
- else
132
- @logger.debug("No zombie instances found")
133
- end
134
- #get rid of old disks
135
- disks = @gce_helper.list_disks(start, attempts)
136
- if disks
137
- disks.each do |disk|
138
- created = Time.parse(disk['creationTimestamp'])
139
- alive = (now - created ) /60 /60
140
- if alive >= max_age
141
- #kill it with fire!
142
- @logger.debug("Deleting zombie disk #{disk['name']}")
143
- @gce_helper.delete_disk( disk['name'], start, attempts )
144
- end
145
- end
146
- else
147
- @logger.debug("No zombie disks found")
148
- end
149
- #get rid of non-default firewalls
150
- firewalls = @gce_helper.list_firewalls( start, attempts)
151
-
152
- if firewalls and not firewalls.empty?
153
- firewalls.each do |firewall|
154
- @logger.debug("Deleting non-default firewall #{firewall['name']}")
155
- @gce_helper.delete_firewall( firewall['name'], start, attempts )
156
- end
157
- else
158
- @logger.debug("No zombie firewalls found")
159
- end
160
-
161
- end
162
-
163
- end
164
- end
@@ -1,577 +0,0 @@
1
- require 'google/api_client'
2
- require 'json'
3
- require 'time'
4
- require 'ostruct'
5
-
6
- module Beaker
7
- #Beaker helper module for doing API level Google Compute Engine interaction.
8
- class GoogleComputeHelper
9
-
10
- class GoogleComputeError < StandardError
11
- end
12
-
13
- SLEEPWAIT = 5
14
-
15
- AUTH_URL = 'https://www.googleapis.com/auth/compute'
16
- API_VERSION = 'v1'
17
- BASE_URL = "https://www.googleapis.com/compute/#{API_VERSION}/projects/"
18
- CENTOS_PROJECT = 'centos-cloud'
19
- DEBIAN_PROJECT = 'debian-cloud'
20
- DEFAULT_ZONE_NAME = 'us-central1-a'
21
- DEFAULT_MACHINE_TYPE = 'n1-highmem-2'
22
- DEFAULT_DISK_SIZE = 25
23
-
24
- #Create a new instance of the Google Compute Engine helper object
25
- #@param [Hash{Symbol=>String}] options The options hash containing configuration values
26
- #@option options [String] :gce_project The Google Compute Project name to connect to
27
- #@option options [String] :gce_keyfile The location of the Google Compute service account keyfile
28
- #@option options [String] :gce_password The password for the Google Compute service account key
29
- #@option options [String] :gce_email The email address for the Google Compute service account
30
- #@option options [String] :gce_machine_type A Google Compute machine type used to create instances, defaults to n1-highmem-2
31
- #@option options [Integer] :timeout The amount of time to attempt execution before quiting and exiting with failure
32
- def initialize(options)
33
- @options = options
34
- @logger = options[:logger]
35
- try = 1
36
- attempts = @options[:timeout].to_i / SLEEPWAIT
37
- start = Time.now
38
-
39
- set_client(Beaker::Version::STRING)
40
- set_compute_api(API_VERSION, start, attempts)
41
-
42
- raise 'You must specify a gce_project for Google Compute Engine instances!' unless @options[:gce_project]
43
- raise 'You must specify a gce_keyfile for Google Compute Engine instances!' unless @options[:gce_keyfile]
44
- raise 'You must specify a gce_password for Google Compute Engine instances!' unless @options[:gce_password]
45
- raise 'You must specify a gce_email for Google Compute Engine instances!' unless @options[:gce_email]
46
-
47
- authenticate(@options[:gce_keyfile], @options[:gce_password], @options[:gce_email], start, attempts)
48
- end
49
-
50
- #Determines the default Google Compute zone based upon options and defaults
51
- #@return The full URL to the default zone in which Google Compute requests will be sent
52
- def default_zone
53
- BASE_URL + @options[:gce_project] + '/global/zones/' + DEFAULT_ZONE_NAME
54
- end
55
-
56
- #Determines the default Google Compute network based upon defaults and options
57
- #@return The full URL to the default network in which Google Compute instances will operate
58
- def default_network
59
- BASE_URL + @options[:gce_project] + '/global/networks/default'
60
- end
61
-
62
- #Determines the Google Compute project which contains bases instances of type name
63
- #@param [String] name The platform type to search for
64
- #@return The Google Compute project name
65
- #@raise [Exception] If the provided platform type name is unsupported
66
- def get_platform_project(name)
67
- if name =~ /debian/
68
- return DEBIAN_PROJECT
69
- elsif name =~ /centos/
70
- return CENTOS_PROJECT
71
- else
72
- raise "Unsupported platform for Google Compute Engine: #{name}"
73
- end
74
- end
75
-
76
- #Create the Google APIClient object which will be used for accessing the Google Compute API
77
- #@param version The version number of Beaker currently running
78
- def set_client(version)
79
- @client = Google::APIClient.new({:application_name => "Beaker", :application_version => version})
80
- end
81
-
82
- #Discover the currently active Google Compute API
83
- #@param [String] version The version of the Google Compute API to discover
84
- #@param [Integer] start The time when we started code execution, it is compared to Time.now to determine how many
85
- # further code execution attempts remain
86
- #@param [Integer] attempts The total amount of attempts to execute that we are willing to allow
87
- #@raise [Exception] Raised if we fail to discover the Google Compute API, either through errors or running out of attempts
88
- def set_compute_api version, start, attempts
89
- try = (Time.now - start) / SLEEPWAIT
90
- while try <= attempts
91
- begin
92
- @compute = @client.discovered_api('compute', version)
93
- @logger.debug("Google Compute API discovered")
94
- return
95
- rescue => e
96
- @logger.debug("Failed to discover Google Compute API")
97
- if try >= attempts
98
- raise e
99
- end
100
- end
101
- try += 1
102
- end
103
- end
104
-
105
- #Creates an authenticated connection to the Google Compute Engine API
106
- #@param [String] keyfile The location of the Google Compute Service Account keyfile to use for authentication
107
- #@param [String] password The password for the provided Google Compute Service Account key
108
- #@param [String] email The email address of the Google Compute Service Account we are using to connect
109
- #@param [Integer] start The time when we started code execution, it is compared to Time.now to determine how many
110
- # further code execution attempts remain
111
- #@param [Integer] attempts The total amount of attempts to execute that we are willing to allow
112
- #@raise [Exception] Raised if we fail to create an authenticated connection to the Google Compute API, either through errors or running out of attempts
113
- def authenticate(keyfile, password, email, start, attempts)
114
- # OAuth authentication, using the service account
115
- key = Google::APIClient::PKCS12.load_key(keyfile, password)
116
- service_account = Google::APIClient::JWTAsserter.new(
117
- email,
118
- AUTH_URL,
119
- key)
120
- try = (Time.now - start) / SLEEPWAIT
121
- while try <= attempts
122
- begin
123
- @client.authorization = service_account.authorize
124
- @logger.debug("Authorized to use Google Compute")
125
- return
126
- rescue => e
127
- @logger.debug("Failed to authorize to use Google Compute")
128
- if try >= attempts
129
- raise e
130
- end
131
- end
132
- try += 1
133
- end
134
- end
135
-
136
- #Executes a provided Google Compute request using a previously configured and authenticated Google Compute client connection
137
- #@param [Hash] req A correctly formatted Google Compute request object
138
- #@param [Integer] start The time when we started code execution, it is compared to Time.now to determine how many
139
- # further code execution attempts remain
140
- #@param [Integer] attempts The total amount of attempts to execute that we are willing to allow
141
- #@raise [Exception] Raised if we fail to execute the request, either through errors or running out of attempts
142
- def execute req, start, attempts
143
- last_error = parsed = nil
144
- try = (Time.now - start) / SLEEPWAIT
145
- while try <= attempts
146
- begin
147
- result = @client.execute(req)
148
- parsed = JSON.parse(result.body)
149
- if not result.success?
150
- error_code = parsed["error"] ? parsed["error"]["code"] : 0
151
- if error_code == 404
152
- raise GoogleComputeError, "Resource Not Found: #{result.body}"
153
- elsif error_code == 400
154
- raise GoogleComputeError, "Bad Request: #{result.body}"
155
- else
156
- raise GoogleComputeError, "Error attempting Google Compute API execute: #{result.body}"
157
- end
158
- end
159
- return parsed
160
- #retry errors
161
- rescue Faraday::Error::ConnectionFailed => e
162
- @logger.debug "ConnectionFailed attempting Google Compute execute command"
163
- try += 1
164
- last_error = e
165
- end
166
- end
167
- #we only get down here if we've used up all our tries
168
- raise last_error
169
- end
170
-
171
- #Determines the latest image available for the provided platform name. We currently only support debian-7 and centos-6 platforms.
172
- #@param [String] platform The platform type to search for an instance of, must be one of /debian-7-.*/ or /centos-6-.*/
173
- #@param [Integer] start The time when we started code execution, it is compared to Time.now to determine how many
174
- # further code execution attempts remain
175
- #@param [Integer] attempts The total amount of attempts to execute that we are willing to allow
176
- #@return [Hash] The image hash of the latest, non-deprecated image for the provided platform
177
- #@raise [Exception] Raised if we fail to execute the request, either through errors or running out of attempts
178
- def get_latest_image(platform, start, attempts)
179
- #use the platform version numbers instead of codenames
180
- platform = platform.with_version_number
181
- #break up my platform for information
182
- platform_name, platform_version, platform_extra_info = platform.split('-', 3)
183
- #find latest image to use
184
- result = execute( image_list_req(get_platform_project(platform_name)), start, attempts )
185
- images = result["items"]
186
- #reject images of the wrong version of the given platform
187
- images.delete_if { |image| image['name'] !~ /^#{platform_name}-#{platform_version}/}
188
- #reject deprecated images
189
- images.delete_if { |image| image['deprecated']}
190
- #find a match based upon platform type
191
- if images.length != 1
192
- raise "Unable to find a single matching image for #{platform}, found #{images}"
193
- end
194
- images[0]
195
- end
196
-
197
- #Determines the Google Compute machineType object based upon the selected gce_machine_type option
198
- #@param [Integer] start The time when we started code execution, it is compared to Time.now to determine how many
199
- # further code execution attempts remain
200
- #@param [Integer] attempts The total amount of attempts to execute that we are willing to allow
201
- #@return [Hash] The machineType hash
202
- #@raise [Exception] Raised if we fail get the machineType, either through errors or running out of attempts
203
- def get_machineType(start, attempts)
204
- execute( machineType_get_req, start, attempts )
205
- end
206
-
207
- #Determines the Google Compute network object in use for the current connection
208
- #@param [Integer] start The time when we started code execution, it is compared to Time.now to determine how many
209
- # further code execution attempts remain
210
- #@param [Integer] attempts The total amount of attempts to execute that we are willing to allow
211
- #@return [Hash] The network hash
212
- #@raise [Exception] Raised if we fail get the network, either through errors or running out of attempts
213
- def get_network(start, attempts)
214
- execute( network_get_req, start, attempts)
215
- end
216
-
217
- #Determines a list of existing Google Compute instances
218
- #@param [Integer] start The time when we started code execution, it is compared to Time.now to determine how many
219
- # further code execution attempts remain
220
- #@param [Integer] attempts The total amount of attempts to execute that we are willing to allow
221
- #@return [Array[Hash]] The instances array of hashes
222
- #@raise [Exception] Raised if we fail determine the list of existing instances, either through errors or running out of attempts
223
- def list_instances(start, attempts)
224
- instances = execute( instance_list_req(), start, attempts )
225
- instances["items"]
226
- end
227
-
228
- #Determines a list of existing Google Compute disks
229
- #@param [Integer] start The time when we started code execution, it is compared to Time.now to determine how many
230
- # further code execution attempts remain
231
- #@param [Integer] attempts The total amount of attempts to execute that we are willing to allow
232
- #@return [Array[Hash]] The disks array of hashes
233
- #@raise [Exception] Raised if we fail determine the list of existing disks, either through errors or running out of attempts
234
- def list_disks(start, attempts)
235
- disks = execute( disk_list_req(), start, attempts )
236
- disks["items"]
237
- end
238
-
239
- #Determines a list of existing Google Compute firewalls
240
- #@param [Integer] start The time when we started code execution, it is compared to Time.now to determine how many
241
- # further code execution attempts remain
242
- #@param [Integer] attempts The total amount of attempts to execute that we are willing to allow
243
- #@return [Array[Hash]] The firewalls array of hashes
244
- #@raise [Exception] Raised if we fail determine the list of existing firewalls, either through errors or running out of attempts
245
- def list_firewalls(start, attempts)
246
- result = execute( firewall_list_req(), start, attempts )
247
- firewalls = result["items"]
248
- firewalls.delete_if{|f| f['name'] =~ /default-allow-internal|default-ssh/}
249
- firewalls
250
- end
251
-
252
- #Create a Google Compute firewall on the current connection
253
- #@param [String] name The name of the firewall to create
254
- #@param [Hash] network The Google Compute network hash in which to create the firewall
255
- #@param [Integer] start The time when we started code execution, it is compared to Time.now to determine how many
256
- # further code execution attempts remain
257
- #@param [Integer] attempts The total amount of attempts to execute that we are willing to allow
258
- #@raise [Exception] Raised if we fail create the firewall, either through errors or running out of attempts
259
- def create_firewall(name, network, start, attempts)
260
- execute( firewall_insert_req( name, network['selfLink'] ), start, attempts )
261
- end
262
-
263
- #Create a Google Compute disk on the current connection
264
- #@param [String] name The name of the disk to create
265
- #@param [Hash] img The Google Compute image to use for instance creation
266
- #@param [Integer] start The time when we started code execution, it is compared to Time.now to determine how many
267
- # further code execution attempts remain
268
- #@param [Integer] attempts The total amount of attempts to execute that we are willing to allow
269
- #@raise [Exception] Raised if we fail create the disk, either through errors or running out of attempts
270
- def create_disk(name, img, start, attempts)
271
- #create a new boot disk for this instance
272
- disk = execute( disk_insert_req( name, img['selfLink'] ), start, attempts )
273
-
274
- status = ''
275
- try = (Time.now - start) / SLEEPWAIT
276
- while status !~ /READY/ and try <= attempts
277
- begin
278
- disk = execute( disk_get_req( name ), start, attempts )
279
- status = disk['status']
280
- rescue GoogleComputeError => e
281
- @logger.debug("Waiting for #{name} disk creation")
282
- sleep(SLEEPWAIT)
283
- end
284
- try += 1
285
- end
286
- if status == ''
287
- raise "Unable to create disk #{name}"
288
- end
289
- disk
290
- end
291
-
292
- #Create a Google Compute instance on the current connection
293
- #@param [String] name The name of the instance to create
294
- #@param [Hash] img The Google Compute image to use for instance creation
295
- #@param [Hash] machineType The Google Compute machineType
296
- #@param [Hash] disk The Google Compute disk to attach to the newly created instance
297
- #@param [Integer] start The time when we started code execution, it is compared to Time.now to determine how many
298
- # further code execution attempts remain
299
- #@param [Integer] attempts The total amount of attempts to execute that we are willing to allow
300
- #@raise [Exception] Raised if we fail create the instance, either through errors or running out of attempts
301
- def create_instance(name, img, machineType, disk, start, attempts)
302
- #add a new instance of the image
303
- instance = execute( instance_insert_req( name, img['selfLink'], machineType['selfLink'], disk['selfLink'] ), start, attempts)
304
- status = ''
305
- try = (Time.now - start) / SLEEPWAIT
306
- while status !~ /RUNNING/ and try <= attempts
307
- begin
308
- instance = execute( instance_get_req( name ), start, attempts )
309
- status = instance['status']
310
- rescue GoogleComputeError => e
311
- @logger.debug("Waiting for #{name} instance creation")
312
- sleep(SLEEPWAIT)
313
- end
314
- try += 1
315
- end
316
- if status == ''
317
- raise "Unable to create instance #{name}"
318
- end
319
- instance
320
- end
321
-
322
- #Add key/value pairs to a Google Compute instance on the current connection
323
- #@param [String] name The name of the instance to add metadata to
324
- #@param [String] fingerprint A hash of the metadata's contents of the given instance
325
- #@param [Array<Hash>] data An array of hashes. Each hash should have a key and a value.
326
- #@param [Integer] start The time when we started code execution, it is compared to Time.now to determine how many
327
- # further code execution attempts remain
328
- #@param [Integer] attempts The total amount of attempts to execute that we are willing to allow
329
- #@raise [Exception] Raised if we fail to add metadata, either through errors or running out of attempts
330
- def setMetadata_on_instance(name, fingerprint, data, start, attempts)
331
- zone_operation = execute( instance_setMetadata_req( name, fingerprint, data), start, attempts )
332
- status = ''
333
- try = (Time.now - start) / SLEEPWAIT
334
- while status !~ /DONE/ and try <= attempts
335
- begin
336
- operation = execute( operation_get_req( zone_operation['name'] ), start, attempts )
337
- status = operation['status']
338
- rescue GoogleComputeError => e
339
- @logger.debug("Waiting for tags to be added to #{name}")
340
- sleep(SLEEPWAIT)
341
- end
342
- try += 1
343
- end
344
- if status == ''
345
- raise "Unable to set metaData (#{tags.to_s}) on #{name}"
346
- end
347
- zone_operation
348
- end
349
-
350
- #Delete a Google Compute instance on the current connection
351
- #@param [String] name The name of the instance to delete
352
- #@param [Integer] start The time when we started code execution, it is compared to Time.now to determine how many
353
- # further code execution attempts remain
354
- #@param [Integer] attempts The total amount of attempts to execute that we are willing to allow
355
- #@raise [Exception] Raised if we fail delete the instance, either through errors or running out of attempts
356
- def delete_instance(name, start, attempts)
357
- result = execute( instance_delete_req( name ), start, attempts )
358
- #ensure deletion of instance
359
- try = (Time.now - start) / SLEEPWAIT
360
- while try <= attempts
361
- begin
362
- result = execute( instance_get_req( name ), start, attempts )
363
- @logger.debug("Waiting for #{name} instance deletion")
364
- sleep(SLEEPWAIT)
365
- rescue GoogleComputeError => e
366
- @logger.debug("#{name} instance deleted!")
367
- return
368
- end
369
- try += 1
370
- end
371
- @logger.debug("#{name} instance was not removed before timeout, may still exist")
372
- end
373
-
374
- #Delete a Google Compute disk on the current connection
375
- #@param [String] name The name of the disk to delete
376
- #@param [Integer] start The time when we started code execution, it is compared to Time.now to determine how many
377
- # further code execution attempts remain
378
- #@param [Integer] attempts The total amount of attempts to execute that we are willing to allow
379
- #@raise [Exception] Raised if we fail delete the disk, either through errors or running out of attempts
380
- def delete_disk(name, start, attempts)
381
- result = execute( disk_delete_req( name ), start, attempts )
382
- #ensure deletion of disk
383
- try = (Time.now - start) / SLEEPWAIT
384
- while try <= attempts
385
- begin
386
- disk = execute( disk_get_req( name ), start, attempts )
387
- @logger.debug("Waiting for #{name} disk deletion")
388
- sleep(SLEEPWAIT)
389
- rescue GoogleComputeError => e
390
- @logger.debug("#{name} disk deleted!")
391
- return
392
- end
393
- try += 1
394
- end
395
- @logger.debug("#{name} disk was not removed before timeout, may still exist")
396
- end
397
-
398
- #Delete a Google Compute firewall on the current connection
399
- #@param [String] name The name of the firewall to delete
400
- #@param [Integer] start The time when we started code execution, it is compared to Time.now to determine how many
401
- # further code execution attempts remain
402
- #@param [Integer] attempts The total amount of attempts to execute that we are willing to allow
403
- #@raise [Exception] Raised if we fail delete the firewall, either through errors or running out of attempts
404
- def delete_firewall(name, start, attempts)
405
- result = execute( firewall_delete_req( name ), start, attempts )
406
- #ensure deletion of disk
407
- try = (Time.now - start) / SLEEPWAIT
408
- while try <= attempts
409
- begin
410
- firewall = execute( firewall_get_req( name ), start, attempts )
411
- @logger.debug("Waiting for #{name} firewall deletion")
412
- sleep(SLEEPWAIT)
413
- rescue GoogleComputeError => e
414
- @logger.debug("#{name} firewall deleted!")
415
- return
416
- end
417
- try += 1
418
- end
419
- @logger.debug("#{name} firewall was not removed before timeout, may still exist")
420
- end
421
-
422
-
423
- #Create a Google Compute list all images request
424
- #@param [String] name The Google Compute project name to query
425
- #@return [Hash] A correctly formatted Google Compute request hash
426
- def image_list_req(name)
427
- { :api_method => @compute.images.list,
428
- :parameters => { 'project' => name } }
429
- end
430
-
431
- #Create a Google Compute list all disks request
432
- #@return [Hash] A correctly formatted Google Compute request hash
433
- def disk_list_req
434
- { :api_method => @compute.disks.list,
435
- :parameters => { 'project' => @options[:gce_project], 'zone' => DEFAULT_ZONE_NAME } }
436
- end
437
-
438
- #Create a Google Compute get disk request
439
- #@param [String] name The name of the disk to query for
440
- #@return [Hash] A correctly formatted Google Compute request hash
441
- def disk_get_req(name)
442
- { :api_method => @compute.disks.get,
443
- :parameters => { 'project' => @options[:gce_project], 'zone' => DEFAULT_ZONE_NAME, 'disk' => name } }
444
- end
445
-
446
- #Create a Google Compute disk delete request
447
- #@param [String] name The name of the disk delete
448
- #@return [Hash] A correctly formatted Google Compute request hash
449
- def disk_delete_req(name)
450
- { :api_method => @compute.disks.delete,
451
- :parameters => { 'project' => @options[:gce_project], 'zone' => DEFAULT_ZONE_NAME, 'disk' => name } }
452
- end
453
-
454
- #Create a Google Compute disk create request
455
- #@param [String] name The name of the disk to create
456
- #@param [String] source The link to a Google Compute image to base the disk creation on
457
- #@return [Hash] A correctly formatted Google Compute request hash
458
- def disk_insert_req(name, source)
459
- { :api_method => @compute.disks.insert,
460
- :parameters => { 'project' => @options[:gce_project], 'zone' => DEFAULT_ZONE_NAME, 'sourceImage' => source },
461
- :body_object => { 'name' => name, 'sizeGb' => DEFAULT_DISK_SIZE } }
462
- end
463
-
464
- #Create a Google Compute get firewall request
465
- #@param [String] name The name of the firewall to query fo
466
- #@return [Hash] A correctly formatted Google Compute request hash
467
- def firewall_get_req(name)
468
- { :api_method => @compute.firewalls.get,
469
- :parameters => { 'project' => @options[:gce_project], 'zone' => DEFAULT_ZONE_NAME, 'firewall' => name } }
470
- end
471
-
472
- #Create a Google Compute insert firewall request, open ports 443, 8140 and 61613
473
- #@param [String] name The name of the firewall to create
474
- #@param [String] network The link to the Google Compute network to attach this firewall to
475
- #@return [Hash] A correctly formatted Google Compute request hash
476
- def firewall_insert_req(name, network)
477
- { :api_method => @compute.firewalls.insert,
478
- :parameters => { 'project' => @options[:gce_project], 'zone' => DEFAULT_ZONE_NAME },
479
- :body_object => { 'name' => name,
480
- 'allowed'=> [ { 'IPProtocol' => 'tcp', "ports" => [ '443', '8140', '61613', '8080', '8081' ]} ],
481
- 'network'=> network,
482
- 'sourceRanges' => [ "0.0.0.0/0" ] } }
483
- end
484
-
485
- #Create a Google Compute delete firewall request
486
- #@param [String] name The name of the firewall to delete
487
- #@return [Hash] A correctly formatted Google Compute request hash
488
- def firewall_delete_req(name)
489
- { :api_method => @compute.firewalls.delete,
490
- :parameters => { 'project' => @options[:gce_project], 'zone' => DEFAULT_ZONE_NAME, 'firewall' => name } }
491
- end
492
-
493
- #Create a Google Compute list firewall request
494
- #@return [Hash] A correctly formatted Google Compute request hash
495
- def firewall_list_req()
496
- { :api_method => @compute.firewalls.list,
497
- :parameters => { 'project' => @options[:gce_project], 'zone' => DEFAULT_ZONE_NAME } }
498
- end
499
-
500
- #Create a Google Compute get network request
501
- #@param [String] name (default) The name of the network to access information about
502
- #@return [Hash] A correctly formatted Google Compute request hash
503
- def network_get_req(name = 'default')
504
- { :api_method => @compute.networks.get,
505
- :parameters => { 'project' => @options[:gce_project], 'zone' => DEFAULT_ZONE_NAME, 'network' => name } }
506
- end
507
-
508
- #Create a Google Compute zone operation request
509
- #@return [Hash] A correctly formatted Google Compute request hash
510
- def operation_get_req(name)
511
- { :api_method => @compute.zone_operations.get,
512
- :parameters => { 'project' => @options[:gce_project], 'zone' => DEFAULT_ZONE_NAME, 'operation' => name } }
513
- end
514
-
515
- #Set tags on a Google Compute instance
516
- #@param [Array<String>] data An array of tags to be added to an instance
517
- #@return [Hash] A correctly formatted Google Compute request hash
518
- def instance_setMetadata_req(name, fingerprint, data)
519
- { :api_method => @compute.instances.set_metadata,
520
- :parameters => { 'project' => @options[:gce_project], 'zone' => DEFAULT_ZONE_NAME, 'instance' => name },
521
- :body_object => { 'kind' => 'compute#metadata',
522
- 'fingerprint' => fingerprint,
523
- 'items' => data }
524
- }
525
- end
526
-
527
- #Create a Google Compute list instance request
528
- #@return [Hash] A correctly formatted Google Compute request hash
529
- def instance_list_req
530
- { :api_method => @compute.instances.list,
531
- :parameters => { 'project' => @options[:gce_project], 'zone' => DEFAULT_ZONE_NAME } }
532
- end
533
-
534
- #Create a Google Compute get instance request
535
- #@param [String] name The name of the instance to query for
536
- #@return [Hash] A correctly formatted Google Compute request hash
537
- def instance_get_req(name)
538
- { :api_method => @compute.instances.get,
539
- :parameters => { 'project' => @options[:gce_project], 'zone' => DEFAULT_ZONE_NAME, 'instance' => name } }
540
- end
541
-
542
- #Create a Google Compute instance delete request
543
- #@param [String] name The name of the instance to delete
544
- #@return [Hash] A correctly formatted Google Compute request hash
545
- def instance_delete_req(name)
546
- { :api_method => @compute.instances.delete,
547
- :parameters => { 'project' => @options[:gce_project], 'zone' => DEFAULT_ZONE_NAME, 'instance' => name } }
548
- end
549
-
550
- #Create a Google Compute instance create request
551
- #@param [String] name The name of the instance to create
552
- #@param [String] image The link to the image to use for instance create
553
- #@param [String] machineType The link to the type of Google Compute instance to create (indicates cpus and memory size)
554
- #@param [String] disk The link to the disk to be used by the newly created instance
555
- #@return [Hash] A correctly formatted Google Compute request hash
556
- def instance_insert_req(name, image, machineType, disk)
557
- { :api_method => @compute.instances.insert,
558
- :parameters => { 'project' => @options[:gce_project], 'zone' => DEFAULT_ZONE_NAME },
559
- :body_object => { 'name' => name,
560
- 'image' => image,
561
- 'zone' => default_zone,
562
- 'machineType' => machineType,
563
- 'disks' => [ { 'source' => disk,
564
- 'type' => 'PERSISTENT', 'boot' => 'true'} ],
565
- 'networkInterfaces' => [ { 'accessConfigs' => [{ 'type' => 'ONE_TO_ONE_NAT', 'name' => 'External NAT' }],
566
- 'network' => default_network } ] } }
567
- end
568
-
569
- #Create a Google Compute machineType get request
570
- #@return [Hash] A correctly formatted Google Compute request hash
571
- def machineType_get_req()
572
- { :api_method => @compute.machine_types.get,
573
- :parameters => { 'project' => @options[:gce_project], 'zone' => DEFAULT_ZONE_NAME, 'machineType' => @options[:gce_machine_type] || DEFAULT_MACHINE_TYPE } }
574
- end
575
-
576
- end
577
- end