chef-metal 0.4 → 0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -9,16 +9,16 @@ module ChefMetal
9
9
  # Sets up everything necessary for convergence to happen on the machine.
10
10
  # The node MUST be saved as part of this procedure. Other than that,
11
11
  # nothing is guaranteed except that converge() will work when this is done.
12
- def setup_convergence(provider)
12
+ def setup_convergence(action_handler)
13
13
  raise "setup_convergence not overridden on #{self.class}"
14
14
  end
15
15
 
16
- def converge(provider)
16
+ def converge(action_handler)
17
17
  raise "converge not overridden on #{self.class}"
18
18
  end
19
19
 
20
20
 
21
- def execute(provider, command)
21
+ def execute(action_handler, command)
22
22
  raise "execute not overridden on #{self.class}"
23
23
  end
24
24
 
@@ -26,24 +26,24 @@ module ChefMetal
26
26
  raise "read_file not overridden on #{self.class}"
27
27
  end
28
28
 
29
- def download_file(provider, path, local_path)
29
+ def download_file(action_handler, path, local_path)
30
30
  raise "read_file not overridden on #{self.class}"
31
31
  end
32
32
 
33
- def write_file(provider, path, content)
33
+ def write_file(action_handler, path, content)
34
34
  raise "write_file not overridden on #{self.class}"
35
35
  end
36
36
 
37
- def upload_file(provider, local_path, path)
37
+ def upload_file(action_handler, local_path, path)
38
38
  raise "write_file not overridden on #{self.class}"
39
39
  end
40
40
 
41
- def create_dir(provider, path)
41
+ def create_dir(action_handler, path)
42
42
  raise "create_dir not overridden on #{self.class}"
43
43
  end
44
44
 
45
45
  # Delete file
46
- def delete_file(provider, path)
46
+ def delete_file(action_handler, path)
47
47
  raise "delete_file not overridden on #{self.class}"
48
48
  end
49
49
 
@@ -58,7 +58,7 @@ module ChefMetal
58
58
  end
59
59
 
60
60
  # Set file attributes { mode, :owner, :group }
61
- def set_attributes(provider, path, attributes)
61
+ def set_attributes(action_handler, path, attributes)
62
62
  raise "set_attributes not overridden on #{self.class}"
63
63
  end
64
64
 
@@ -76,13 +76,13 @@ module ChefMetal
76
76
  raise "disconnect not overridden on #{self.class}"
77
77
  end
78
78
 
79
- # TODO get rid of the provider attribute, that is ridiculous
79
+ # TODO get rid of the action_handler attribute, that is ridiculous
80
80
  # Detect the OS on the machine (assumes the machine is up)
81
81
  # Returns a triplet:
82
- # platform, platform_version, machine_architecture = machine.detect_os(provider)
82
+ # platform, platform_version, machine_architecture = machine.detect_os(action_handler)
83
83
  # This triplet is suitable for passing to the Chef metadata API:
84
84
  # https://www.opscode.com/chef/metadata?p=#{platform}&pv=#{platform_version}&m=#{machine_architecture}
85
- def detect_os(provider)
85
+ def detect_os(action_handler)
86
86
  raise "detect_os not overridden on #{self.class}"
87
87
  end
88
88
  end
@@ -15,16 +15,16 @@ module ChefMetal
15
15
  # Sets up everything necessary for convergence to happen on the machine.
16
16
  # The node MUST be saved as part of this procedure. Other than that,
17
17
  # nothing is guaranteed except that converge() will work when this is done.
18
- def setup_convergence(provider, machine_resource)
19
- convergence_strategy.setup_convergence(provider, self, machine_resource)
18
+ def setup_convergence(action_handler, machine_resource)
19
+ convergence_strategy.setup_convergence(action_handler, self, machine_resource)
20
20
  end
21
21
 
22
- def converge(provider)
23
- convergence_strategy.converge(provider, self)
22
+ def converge(action_handler)
23
+ convergence_strategy.converge(action_handler, self)
24
24
  end
25
25
 
26
- def execute(provider, command)
27
- provider.converge_by "run '#{command}' on #{node['name']}" do
26
+ def execute(action_handler, command)
27
+ action_handler.converge_by "run '#{command}' on #{node['name']}" do
28
28
  transport.execute(command).error!
29
29
  end
30
30
  end
@@ -37,31 +37,31 @@ module ChefMetal
37
37
  transport.read_file(path)
38
38
  end
39
39
 
40
- def download_file(provider, path, local_path)
40
+ def download_file(action_handler, path, local_path)
41
41
  if files_different?(path, local_path)
42
- provider.converge_by "download file #{path} on #{node['name']} to #{local_path}" do
42
+ action_handler.converge_by "download file #{path} on #{node['name']} to #{local_path}" do
43
43
  transport.download_file(path, local_path)
44
44
  end
45
45
  end
46
46
  end
47
47
 
48
- def write_file(provider, path, content, options = {})
48
+ def write_file(action_handler, path, content, options = {})
49
49
  if files_different?(path, nil, content)
50
50
  if options[:ensure_dir]
51
- create_dir(provider, dirname_on_machine(path))
51
+ create_dir(action_handler, dirname_on_machine(path))
52
52
  end
53
- provider.converge_by "write file #{path} on #{node['name']}" do
53
+ action_handler.converge_by "write file #{path} on #{node['name']}" do
54
54
  transport.write_file(path, content)
55
55
  end
56
56
  end
57
57
  end
58
58
 
59
- def upload_file(provider, local_path, path, options = {})
59
+ def upload_file(action_handler, local_path, path, options = {})
60
60
  if files_different?(path, local_path)
61
61
  if options[:ensure_dir]
62
- create_dir(provider, dirname_on_machine(path))
62
+ create_dir(action_handler, dirname_on_machine(path))
63
63
  end
64
- provider.converge_by "upload file #{local_path} to #{path} on #{node['name']}" do
64
+ action_handler.converge_by "upload file #{local_path} to #{path} on #{node['name']}" do
65
65
  transport.upload_file(local_path, path)
66
66
  end
67
67
  end
@@ -16,9 +16,9 @@ module ChefMetal
16
16
  attr_reader :options
17
17
 
18
18
  # Delete file
19
- def delete_file(provider, path)
19
+ def delete_file(action_handler, path)
20
20
  if file_exists?(path)
21
- provider.converge_by "delete file #{path} on #{node['name']}" do
21
+ action_handler.converge_by "delete file #{path} on #{node['name']}" do
22
22
  transport.execute("rm -f #{path}").error!
23
23
  end
24
24
  end
@@ -53,30 +53,30 @@ module ChefMetal
53
53
  remote_sum != digest.hexdigest
54
54
  end
55
55
 
56
- def create_dir(provider, path)
56
+ def create_dir(action_handler, path)
57
57
  if !file_exists?(path)
58
- provider.converge_by "create directory #{path} on #{node['name']}" do
58
+ action_handler.converge_by "create directory #{path} on #{node['name']}" do
59
59
  transport.execute("mkdir #{path}").error!
60
60
  end
61
61
  end
62
62
  end
63
63
 
64
64
  # Set file attributes { mode, :owner, :group }
65
- def set_attributes(provider, path, attributes)
65
+ def set_attributes(action_handler, path, attributes)
66
66
  if attributes[:mode] || attributes[:owner] || attributes[:group]
67
- current_attributes = get_file_attributes(path)
68
- if attributes[:mode] && current_attributes[:mode] != attributes[:mode]
69
- provider.converge_by "change mode of #{path} on #{node['name']} from #{current_attributes[:mode].to_i(8)} to #{attributes[:mode].to_i(8)}" do
70
- transport.execute("chmod #{attributes[:mode].to_i(8)} #{path}").error!
67
+ current_attributes = get_attributes(path)
68
+ if attributes[:mode] && current_attributes[:mode].to_i != attributes[:mode].to_i
69
+ action_handler.converge_by "change mode of #{path} on #{node['name']} from #{current_attributes[:mode].to_i} to #{attributes[:mode].to_i}" do
70
+ transport.execute("chmod #{attributes[:mode].to_i} #{path}").error!
71
71
  end
72
72
  end
73
73
  if attributes[:owner] && current_attributes[:owner] != attributes[:owner]
74
- provider.converge_by "change group of #{path} on #{node['name']} from #{current_attributes[:owner]} to #{attributes[:owner]}" do
74
+ action_handler.converge_by "change group of #{path} on #{node['name']} from #{current_attributes[:owner]} to #{attributes[:owner]}" do
75
75
  transport.execute("chown #{attributes[:owner]} #{path}").error!
76
76
  end
77
77
  end
78
78
  if attributes[:group] && current_attributes[:group] != attributes[:group]
79
- provider.converge_by "change group of #{path} on #{node['name']} from #{current_attributes[:group]} to #{attributes[:group]}" do
79
+ action_handler.converge_by "change group of #{path} on #{node['name']} from #{current_attributes[:group]} to #{attributes[:group]}" do
80
80
  transport.execute("chgrp #{attributes[:group]} #{path}").error!
81
81
  end
82
82
  end
@@ -85,21 +85,15 @@ module ChefMetal
85
85
 
86
86
  # Get file attributes { :mode, :owner, :group }
87
87
  def get_attributes(path)
88
- file_info = transport.execute("ls -ld #{path}").stdout.split(/\s+/)
88
+ file_info = transport.execute("stat -c '%a %U %G %n' #{path}").stdout.split(/\s+/)
89
89
  if file_info.size <= 1
90
90
  raise "#{path} does not exist in set_attributes()"
91
91
  end
92
92
  result = {
93
- :mode => 0,
94
- :owner => file_info[2],
95
- :group => file_info[3]
93
+ :mode => file_info[0],
94
+ :owner => file_info[1],
95
+ :group => file_info[2]
96
96
  }
97
- attribute_string = file_info[0]
98
- 0.upto(attribute_string.length-1).each do |i|
99
- result[:mode] <<= 1
100
- result[:mode] += (attribute_string[i] == '-' ? 0 : 1)
101
- end
102
- result
103
97
  end
104
98
 
105
99
  def dirname_on_machine(path)
@@ -107,12 +101,12 @@ module ChefMetal
107
101
  end
108
102
  end
109
103
 
110
- def detect_os(provider)
104
+ def detect_os(action_handler)
111
105
  #
112
106
  # Use detect.sh to detect the operating system of the remote machine
113
107
  #
114
108
  # TODO do this in terms of commands rather than writing a shell script
115
- self.write_file(provider, "#{@tmp_dir}/detect.sh", detect_sh)
109
+ self.write_file(action_handler, "#{@tmp_dir}/detect.sh", detect_sh)
116
110
  detected = self.execute_always("sh #{@tmp_dir}/detect.sh")
117
111
  if detected.exitstatus != 0
118
112
  raise "detect.sh exited with nonzero exit status: #{detected.exitstatus}"
@@ -13,9 +13,9 @@ module ChefMetal
13
13
  attr_reader :options
14
14
 
15
15
  # Delete file
16
- def delete_file(provider, path)
16
+ def delete_file(action_handler, path)
17
17
  if file_exists?(path)
18
- provider.converge_by "delete file #{escape(path)} on #{node['name']}" do
18
+ action_handler.converge_by "delete file #{escape(path)} on #{node['name']}" do
19
19
  transport.execute("Remove-Item #{escape(path)}").error!
20
20
  end
21
21
  end
@@ -58,16 +58,16 @@ EOM
58
58
  remote_sum != digest.hexdigest
59
59
  end
60
60
 
61
- def create_dir(provider, path)
61
+ def create_dir(action_handler, path)
62
62
  if !file_exists?(path)
63
- provider.converge_by "create directory #{path} on #{node['name']}" do
63
+ action_handler.converge_by "create directory #{path} on #{node['name']}" do
64
64
  transport.execute("New-Item #{escape(path)} -Type directory")
65
65
  end
66
66
  end
67
67
  end
68
68
 
69
69
  # Set file attributes { :owner, :group, :rights }
70
- # def set_attributes(provider, path, attributes)
70
+ # def set_attributes(action_handler, path, attributes)
71
71
  # end
72
72
 
73
73
  # Get file attributes { :owner, :group, :rights }
@@ -91,4 +91,4 @@ EOM
91
91
  end
92
92
  end
93
93
  end
94
- end
94
+ end
@@ -0,0 +1,41 @@
1
+ # -*- encoding: utf-8 -*-
2
+ #
3
+ # Author:: Douglas Triggs (<doug@getchef.com>)
4
+ #
5
+ # Copyright (C) 2014, Chef, Inc.
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+
19
+ # This is included in the metal provisioners to proxy from generic requests needed
20
+ # to specific provider actions
21
+ module ChefMetal
22
+ module ProviderActionHandler
23
+ # Implementation of ActionHandler interface
24
+
25
+ def recipe_context
26
+ self.run_context
27
+ end
28
+
29
+ def updated!
30
+ self.new_resource.updated_by_last_action(true)
31
+ end
32
+
33
+ def perform_action(description, &block)
34
+ self.converge_by(description, &block)
35
+ end
36
+
37
+ def debug_name
38
+ self.cookbook_name
39
+ end
40
+ end
41
+ end
@@ -1,5 +1,17 @@
1
1
  module ChefMetal
2
2
  class Provisioner
3
+ # Inflate a provisioner from node information; we don't want to force the
4
+ # driver to figure out what the provisioner really needs, since it varies
5
+ # from provisioner to provisioner.
6
+ #
7
+ # ## Parameters
8
+ # node - node to inflate the provisioner for
9
+ #
10
+ # returns a should return a Privisoner from the information provided
11
+ def self.inflate(node)
12
+ raise "#{self.class} does not override self.inflate"
13
+ end
14
+
3
15
  # Acquire a machine, generally by provisioning it. Returns a Machine
4
16
  # object pointing at the machine, allowing useful actions like setup,
5
17
  # converge, execute, file and directory. The Machine object will have a
@@ -7,7 +19,10 @@ module ChefMetal
7
19
  # different from the original node object).
8
20
  #
9
21
  # ## Parameters
10
- # provider - the provider object that is calling this method.
22
+ # action_handler - the action_handler object that is calling this method; this
23
+ # is generally a provider, but could be anything that can support the
24
+ # interface (i.e., in the case of the test kitchen metal driver for
25
+ # acquiring and destroying VMs).
11
26
  # node - node object (deserialized json) representing this machine. If
12
27
  # the node has a provisioner_options hash in it, these will be used
13
28
  # instead of options provided by the provisioner. TODO compare and
@@ -23,7 +38,7 @@ module ChefMetal
23
38
  #
24
39
  # -- provisioner_url: <provisioner url>
25
40
  #
26
- def acquire_machine(provider, node)
41
+ def acquire_machine(action_handler, node)
27
42
  raise "#{self.class} does not override acquire_machine"
28
43
  end
29
44
 
@@ -42,12 +57,12 @@ module ChefMetal
42
57
 
43
58
  # Delete the given machine (idempotent). Should destroy the machine,
44
59
  # returning things to the state before acquire_machine was called.
45
- def delete_machine(provider, node)
60
+ def delete_machine(action_handler, node)
46
61
  raise "#{self.class} does not override delete_machine"
47
62
  end
48
63
 
49
64
  # Stop the given machine.
50
- def stop_machine(provider, node)
65
+ def stop_machine(action_handler, node)
51
66
  raise "#{self.class} does not override stop_machine"
52
67
  end
53
68
 
@@ -2,6 +2,8 @@ require 'chef_metal/provisioner'
2
2
  require 'chef_metal/aws_credentials'
3
3
  require 'chef_metal/openstack_credentials'
4
4
  require 'chef_metal/version'
5
+ require 'fog/compute'
6
+ require 'fog'
5
7
 
6
8
  module ChefMetal
7
9
  class Provisioner
@@ -17,7 +19,13 @@ module ChefMetal
17
19
  :ssh_timeout => 20
18
20
  }
19
21
 
20
- # Create a new vagrant provisioner.
22
+ def self.inflate(node)
23
+ url = node['normal']['provisioner_output']['provisioner_url']
24
+ scheme, provider, id = url.split(':', 3)
25
+ FogProvisioner.new({ :provider => provider }, id)
26
+ end
27
+
28
+ # Create a new fog provisioner.
21
29
  #
22
30
  # ## Parameters
23
31
  # compute_options - hash of options to be passed to Fog::Compute.new
@@ -32,7 +40,9 @@ module ChefMetal
32
40
  # - :create_timeout - the time to wait for the instance to boot to ssh (defaults to 600)
33
41
  # - :start_timeout - the time to wait for the instance to start (defaults to 600)
34
42
  # - :ssh_timeout - the time to wait for ssh to be available if the instance is detected as up (defaults to 20)
35
- def initialize(compute_options)
43
+ # id - the ID in the provisioner_url (fog:PROVIDER:ID)
44
+ def initialize(compute_options, id=nil)
45
+ @compute_options = compute_options
36
46
  @base_bootstrap_options = compute_options.delete(:base_bootstrap_options) || {}
37
47
 
38
48
  case compute_options[:provider]
@@ -46,6 +56,11 @@ module ChefMetal
46
56
  end
47
57
  compute_options[:aws_access_key_id] ||= @aws_credentials.default[:access_key_id]
48
58
  compute_options[:aws_secret_access_key] ||= @aws_credentials.default[:secret_access_key]
59
+ # TODO actually find a key with the proper id
60
+ # TODO let the user specify credentials and provider profiles that we can use
61
+ if id && aws_login_info[0] != id
62
+ raise "Default AWS credentials point at AWS account #{aws_login_info[0]}, but inflating from URL #{id}"
63
+ end
49
64
  when 'OpenStack'
50
65
  openstack_credentials = compute_options.delete(:openstack_credentials)
51
66
  if openstack_credentials
@@ -61,7 +76,6 @@ module ChefMetal
61
76
  compute_options[:openstack_tenant] ||= @openstack_credentials.default[:openstack_tenant]
62
77
  end
63
78
  @key_pairs = {}
64
- @compute_options = compute_options
65
79
  @base_bootstrap_options_for = {}
66
80
  end
67
81
 
@@ -82,6 +96,17 @@ module ChefMetal
82
96
  result
83
97
  end
84
98
 
99
+ # Inflate a provisioner from node information; we don't want to force the
100
+ # driver to figure out what the provisioner really needs, since it varies
101
+ # from provisioner to provisioner.
102
+ #
103
+ # ## Parameters
104
+ # node - node to inflate the provisioner for
105
+ #
106
+ # returns a FogProvisioner
107
+ # TODO: def self.inflate(node)
108
+ # right now, not implemented, will raise error from base class until overridden
109
+
85
110
  # Acquire a machine, generally by provisioning it. Returns a Machine
86
111
  # object pointing at the machine, allowing useful actions like setup,
87
112
  # converge, execute, file and directory. The Machine object will have a
@@ -89,7 +114,11 @@ module ChefMetal
89
114
  # different from the original node object).
90
115
  #
91
116
  # ## Parameters
92
- # provider - the provider object that is calling this method.
117
+ # action_handler - the action_handler object that is calling this method; this
118
+ # is generally a action_handler, but could be anything that can support the
119
+ # ChefMetal::ActionHandler interface (i.e., in the case of the test
120
+ # kitchen metal driver for acquiring and destroying VMs; see the base
121
+ # class for what needs providing).
93
122
  # node - node object (deserialized json) representing this machine. If
94
123
  # the node has a provisioner_options hash in it, these will be used
95
124
  # instead of options provided by the provisioner. TODO compare and
@@ -116,7 +145,7 @@ module ChefMetal
116
145
  # -- provisioner_url: fog:<relevant_fog_options>
117
146
  # -- server_id: the ID of the server so it can be found again
118
147
  #
119
- def acquire_machine(provider, node)
148
+ def acquire_machine(action_handler, node)
120
149
  # Set up the modified node data
121
150
  provisioner_output = node['normal']['provisioner_output'] || {
122
151
  'provisioner_url' => provisioner_url,
@@ -131,7 +160,7 @@ module ChefMetal
131
160
  provisioner_output['provisioner_version'] ||= ChefMetal::VERSION
132
161
  provisioner_output['creator'] ||= aws_login_info[1]
133
162
  else
134
- raise "Switching providers for a machine is not currently supported! Use machine :destroy and then re-create the machine on the new provider."
163
+ raise "Switching providers for a machine is not currently supported! Use machine :destroy and then re-create the machine on the new action_handler."
135
164
  end
136
165
  end
137
166
 
@@ -152,10 +181,10 @@ module ChefMetal
152
181
  else
153
182
  need_to_create = false
154
183
  if !server.ready?
155
- provider.converge_by "start machine #{node['name']} (#{server.id} on #{provisioner_url})" do
184
+ action_handler.perform_action "start machine #{node['name']} (#{server.id} on #{provisioner_url})" do
156
185
  server.start
157
186
  end
158
- provider.converge_by "wait for machine #{node['name']} (#{server.id} on #{provisioner_url}) to be ready" do
187
+ action_handler.perform_action "wait for machine #{node['name']} (#{server.id} on #{provisioner_url}) to be ready" do
159
188
  wait_until_ready(server, option_for(node, :start_timeout))
160
189
  end
161
190
  else
@@ -168,8 +197,8 @@ module ChefMetal
168
197
 
169
198
  if need_to_create
170
199
  # If the server does not exist, create it
171
- bootstrap_options = bootstrap_options_for(provider.new_resource, node)
172
- bootstrap_options.merge(:name => provider.new_resource.name)
200
+ bootstrap_options = bootstrap_options_for(action_handler.new_resource, node)
201
+ bootstrap_options.merge(:name => action_handler.new_resource.name)
173
202
 
174
203
  start_time = Time.now
175
204
  timeout = option_for(node, :create_timeout)
@@ -177,11 +206,11 @@ module ChefMetal
177
206
  description = [ "create machine #{node['name']} on #{provisioner_url}" ]
178
207
  bootstrap_options.each_pair { |key,value| description << " #{key}: #{value.inspect}" }
179
208
  server = nil
180
- provider.converge_by description do
209
+ action_handler.perform_action description do
181
210
  server = compute.servers.create(bootstrap_options)
182
211
  provisioner_output['server_id'] = server.id
183
212
  # Save quickly in case something goes wrong
184
- save_node(provider, node, provider.new_resource.chef_server)
213
+ save_node(action_handler, node, action_handler.new_resource.chef_server)
185
214
  end
186
215
 
187
216
  if server
@@ -191,22 +220,22 @@ module ChefMetal
191
220
  if bootstrap_options[:floating_ip_pool]
192
221
  Chef::Log.info 'Attaching IP from pool'
193
222
  server.wait_for { ready? }
194
- provider.converge_by "attach floating IP from #{bootstrap_options[:floating_ip_pool]} pool" do
223
+ action_handler.perform_action "attach floating IP from #{bootstrap_options[:floating_ip_pool]} pool" do
195
224
  attach_ip_from_pool(server, bootstrap_options[:floating_ip_pool])
196
225
  end
197
226
  elsif bootstrap_options[:floating_ip]
198
227
  Chef::Log.info 'Attaching given IP'
199
228
  server.wait_for { ready? }
200
- provider.converge_by "attach floating IP #{bootstrap_options[:floating_ip]}" do
229
+ action_handler.perform_action "attach floating IP #{bootstrap_options[:floating_ip]}" do
201
230
  attach_ip(server, bootstrap_options[:floating_ip])
202
231
  end
203
232
  end
204
- provider.converge_by "machine #{node['name']} created as #{server.id} on #{provisioner_url}" do
233
+ action_handler.perform_action "machine #{node['name']} created as #{server.id} on #{provisioner_url}" do
205
234
  end
206
235
  # Wait for the machine to come up and for ssh to start listening
207
236
  transport = nil
208
237
  _self = self
209
- provider.converge_by "wait for machine #{node['name']} to boot" do
238
+ action_handler.perform_action "wait for machine #{node['name']} to boot" do
210
239
  server.wait_for(timeout - (Time.now - start_time)) do
211
240
  if ready?
212
241
  transport ||= _self.transport_for(server)
@@ -232,10 +261,10 @@ module ChefMetal
232
261
  # some other problem. If this is the case, we restart the server
233
262
  # to unstick it. Reboot covers a multitude of sins.
234
263
  Chef::Log.warn "Machine #{node['name']} (#{server.id} on #{provisioner_url}) was started but SSH did not come up. Rebooting machine in an attempt to unstick it ..."
235
- provider.converge_by "reboot machine #{node['name']} to try to unstick it" do
264
+ action_handler.perform_action "reboot machine #{node['name']} to try to unstick it" do
236
265
  server.reboot
237
266
  end
238
- provider.converge_by "wait for machine #{node['name']} to be ready after reboot" do
267
+ action_handler.perform_action "wait for machine #{node['name']} to be ready after reboot" do
239
268
  wait_until_ready(server, option_for(node, :start_timeout))
240
269
  end
241
270
  end
@@ -276,21 +305,21 @@ module ChefMetal
276
305
  machine_for(node)
277
306
  end
278
307
 
279
- def delete_machine(provider, node)
308
+ def delete_machine(action_handler, node)
280
309
  if node['normal']['provisioner_output'] && node['normal']['provisioner_output']['server_id']
281
310
  server = compute.servers.get(node['normal']['provisioner_output']['server_id'])
282
- provider.converge_by "destroy machine #{node['name']} (#{node['normal']['provisioner_output']['server_id']} at #{provisioner_url})" do
311
+ action_handler.perform_action "destroy machine #{node['name']} (#{node['normal']['provisioner_output']['server_id']} at #{provisioner_url})" do
283
312
  server.destroy
284
313
  end
285
- convergence_strategy_for(node).delete_chef_objects(provider, node)
314
+ convergence_strategy_for(node).cleanup_convergence(action_handler, node)
286
315
  end
287
316
  end
288
317
 
289
- def stop_machine(provider, node)
318
+ def stop_machine(action_handler, node)
290
319
  # If the machine doesn't exist, we silently do nothing
291
320
  if node['normal']['provisioner_output'] && node['normal']['provisioner_output']['server_id']
292
321
  server = compute.servers.get(node['normal']['provisioner_output']['server_id'])
293
- provider.converge_by "stop machine #{node['name']} (#{server.id} at #{provisioner_url})" do
322
+ action_handler.perform_action "stop machine #{node['name']} (#{server.id} at #{provisioner_url})" do
294
323
  server.stop
295
324
  end
296
325
  end
@@ -302,11 +331,7 @@ module ChefMetal
302
331
 
303
332
 
304
333
  def compute
305
- @compute ||= begin
306
- require 'fog/compute'
307
- require 'fog'
308
- Fog::Compute.new(compute_options)
309
- end
334
+ @compute ||= Fog::Compute.new(compute_options)
310
335
  end
311
336
 
312
337
  def provisioner_url
@@ -499,6 +524,9 @@ module ChefMetal
499
524
  raise "Server #{server.id} has no private or public IP address!"
500
525
  end
501
526
 
527
+ #Enable pty by default
528
+ options[:ssh_pty_enable] = true
529
+
502
530
  ChefMetal::Transport::SSH.new(remote_host, username, ssh_options, options)
503
531
  end
504
532