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.
- checksums.yaml +4 -4
- data/lib/chef/provider/fog_key_pair.rb +3 -0
- data/lib/chef/provider/machine.rb +3 -0
- data/lib/chef/provider/machine_file.rb +8 -1
- data/lib/chef/provider/vagrant_cluster.rb +3 -0
- data/lib/chef/resource/machine_file.rb +4 -0
- data/lib/chef_metal.rb +16 -2
- data/lib/chef_metal/action_handler.rb +49 -0
- data/lib/chef_metal/convergence_strategy.rb +5 -5
- data/lib/chef_metal/convergence_strategy/install_cached.rb +19 -19
- data/lib/chef_metal/convergence_strategy/install_msi.rb +4 -4
- data/lib/chef_metal/convergence_strategy/install_sh.rb +5 -5
- data/lib/chef_metal/convergence_strategy/no_converge.rb +34 -0
- data/lib/chef_metal/convergence_strategy/precreate_chef_objects.rb +13 -12
- data/lib/chef_metal/inline_resource.rb +16 -13
- data/lib/chef_metal/machine.rb +12 -12
- data/lib/chef_metal/machine/basic_machine.rb +14 -14
- data/lib/chef_metal/machine/unix_machine.rb +17 -23
- data/lib/chef_metal/machine/windows_machine.rb +6 -6
- data/lib/chef_metal/provider_action_handler.rb +41 -0
- data/lib/chef_metal/provisioner.rb +19 -4
- data/lib/chef_metal/provisioner/fog_provisioner.rb +56 -28
- data/lib/chef_metal/provisioner/vagrant_provisioner.rb +32 -15
- data/lib/chef_metal/provisioner_init/fog_init.rb +4 -0
- data/lib/chef_metal/provisioner_init/vagrant_cluster_init.rb +4 -0
- data/lib/chef_metal/transport/ssh.rb +9 -1
- data/lib/chef_metal/version.rb +1 -1
- metadata +7 -2
data/lib/chef_metal/machine.rb
CHANGED
@@ -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(
|
12
|
+
def setup_convergence(action_handler)
|
13
13
|
raise "setup_convergence not overridden on #{self.class}"
|
14
14
|
end
|
15
15
|
|
16
|
-
def converge(
|
16
|
+
def converge(action_handler)
|
17
17
|
raise "converge not overridden on #{self.class}"
|
18
18
|
end
|
19
19
|
|
20
20
|
|
21
|
-
def execute(
|
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(
|
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(
|
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(
|
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(
|
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(
|
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(
|
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
|
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(
|
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(
|
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(
|
19
|
-
convergence_strategy.setup_convergence(
|
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(
|
23
|
-
convergence_strategy.converge(
|
22
|
+
def converge(action_handler)
|
23
|
+
convergence_strategy.converge(action_handler, self)
|
24
24
|
end
|
25
25
|
|
26
|
-
def execute(
|
27
|
-
|
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(
|
40
|
+
def download_file(action_handler, path, local_path)
|
41
41
|
if files_different?(path, local_path)
|
42
|
-
|
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(
|
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(
|
51
|
+
create_dir(action_handler, dirname_on_machine(path))
|
52
52
|
end
|
53
|
-
|
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(
|
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(
|
62
|
+
create_dir(action_handler, dirname_on_machine(path))
|
63
63
|
end
|
64
|
-
|
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(
|
19
|
+
def delete_file(action_handler, path)
|
20
20
|
if file_exists?(path)
|
21
|
-
|
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(
|
56
|
+
def create_dir(action_handler, path)
|
57
57
|
if !file_exists?(path)
|
58
|
-
|
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(
|
65
|
+
def set_attributes(action_handler, path, attributes)
|
66
66
|
if attributes[:mode] || attributes[:owner] || attributes[:group]
|
67
|
-
current_attributes =
|
68
|
-
if attributes[:mode] && current_attributes[:mode] != attributes[:mode]
|
69
|
-
|
70
|
-
transport.execute("chmod #{attributes[:mode].to_i
|
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
|
-
|
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
|
-
|
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("
|
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[
|
95
|
-
:group => file_info[
|
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(
|
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(
|
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(
|
16
|
+
def delete_file(action_handler, path)
|
17
17
|
if file_exists?(path)
|
18
|
-
|
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(
|
61
|
+
def create_dir(action_handler, path)
|
62
62
|
if !file_exists?(path)
|
63
|
-
|
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(
|
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
|
-
#
|
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(
|
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(
|
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(
|
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
|
-
|
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
|
-
|
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
|
-
#
|
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(
|
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
|
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
|
-
|
184
|
+
action_handler.perform_action "start machine #{node['name']} (#{server.id} on #{provisioner_url})" do
|
156
185
|
server.start
|
157
186
|
end
|
158
|
-
|
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(
|
172
|
-
bootstrap_options.merge(: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
|
-
|
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(
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
264
|
+
action_handler.perform_action "reboot machine #{node['name']} to try to unstick it" do
|
236
265
|
server.reboot
|
237
266
|
end
|
238
|
-
|
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(
|
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
|
-
|
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).
|
314
|
+
convergence_strategy_for(node).cleanup_convergence(action_handler, node)
|
286
315
|
end
|
287
316
|
end
|
288
317
|
|
289
|
-
def stop_machine(
|
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
|
-
|
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 ||=
|
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
|
|