chef-metal 0.4 → 0.5
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|