ironfan 3.1.0.rc1
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.
- data/.gitignore +51 -0
- data/.rspec +3 -0
- data/CHANGELOG.md +130 -0
- data/Gemfile +26 -0
- data/LICENSE.md +201 -0
- data/README.md +328 -0
- data/Rakefile +104 -0
- data/TODO.md +16 -0
- data/VERSION +1 -0
- data/chefignore +41 -0
- data/cluster_chef-knife.gemspec +123 -0
- data/cluster_chef.gemspec +111 -0
- data/config/client.rb +59 -0
- data/config/proxy.pac +12 -0
- data/config/ubuntu10.04-ironfan.erb +157 -0
- data/config/ubuntu11.10-ironfan.erb +145 -0
- data/ironfan.gemspec +121 -0
- data/lib/chef/knife/bootstrap/ubuntu10.04-ironfan.erb +157 -0
- data/lib/chef/knife/bootstrap/ubuntu11.10-ironfan.erb +145 -0
- data/lib/chef/knife/cluster_bootstrap.rb +74 -0
- data/lib/chef/knife/cluster_kick.rb +94 -0
- data/lib/chef/knife/cluster_kill.rb +73 -0
- data/lib/chef/knife/cluster_launch.rb +164 -0
- data/lib/chef/knife/cluster_list.rb +50 -0
- data/lib/chef/knife/cluster_proxy.rb +126 -0
- data/lib/chef/knife/cluster_show.rb +61 -0
- data/lib/chef/knife/cluster_ssh.rb +141 -0
- data/lib/chef/knife/cluster_start.rb +40 -0
- data/lib/chef/knife/cluster_stop.rb +43 -0
- data/lib/chef/knife/cluster_sync.rb +77 -0
- data/lib/chef/knife/generic_command.rb +66 -0
- data/lib/chef/knife/knife_common.rb +195 -0
- data/lib/ironfan.rb +143 -0
- data/lib/ironfan/chef_layer.rb +299 -0
- data/lib/ironfan/cloud.rb +412 -0
- data/lib/ironfan/cluster.rb +118 -0
- data/lib/ironfan/compute.rb +153 -0
- data/lib/ironfan/deprecated.rb +33 -0
- data/lib/ironfan/discovery.rb +177 -0
- data/lib/ironfan/dsl_object.rb +124 -0
- data/lib/ironfan/facet.rb +144 -0
- data/lib/ironfan/fog_layer.rb +150 -0
- data/lib/ironfan/private_key.rb +130 -0
- data/lib/ironfan/role_implications.rb +58 -0
- data/lib/ironfan/security_group.rb +119 -0
- data/lib/ironfan/server.rb +281 -0
- data/lib/ironfan/server_slice.rb +260 -0
- data/lib/ironfan/volume.rb +157 -0
- data/spec/ironfan/cluster_spec.rb +13 -0
- data/spec/ironfan/facet_spec.rb +69 -0
- data/spec/ironfan/server_slice_spec.rb +19 -0
- data/spec/ironfan/server_spec.rb +112 -0
- data/spec/ironfan_spec.rb +193 -0
- data/spec/spec_helper.rb +50 -0
- data/spec/spec_helper/dummy_chef.rb +25 -0
- data/spec/test_config.rb +20 -0
- data/tasks/chef_config.rake +38 -0
- data/tasks/jeweler_use_alt_branch.rake +53 -0
- metadata +217 -0
@@ -0,0 +1,145 @@
|
|
1
|
+
bash <<EOF || echo "Chef bootstrap failed!"
|
2
|
+
|
3
|
+
# This is the ubuntu oneiric bootstrap script from infochimps' ironfan. It is
|
4
|
+
# based on the opscode bootstrap script, with the important differences being it:
|
5
|
+
#
|
6
|
+
# * installs ruby 1.9.2 (not 1.8.7) using the system ruby
|
7
|
+
# * upgrades rubygems rather than installing from source
|
8
|
+
# * pushes the node identity into the first-boot.json
|
9
|
+
# * installs the chef-client service and kicks off the first run of chef
|
10
|
+
|
11
|
+
set -e
|
12
|
+
|
13
|
+
<%= (@config[:verbosity].to_i > 1 ? 'set -v' : '') %>
|
14
|
+
|
15
|
+
RUBY_VERSION=1.9.1
|
16
|
+
CHEF_VERSION=<%= bootstrap_version_string.gsub(/.*[\s=]/,"") %>
|
17
|
+
|
18
|
+
mkdir -p /tmp/knife-bootstrap
|
19
|
+
chmod 700 /tmp/knife-bootstrap
|
20
|
+
cd /tmp/knife-bootstrap
|
21
|
+
|
22
|
+
<%= "export http_proxy=\"#{knife_config[:bootstrap_proxy]}\"" if knife_config[:bootstrap_proxy] -%>
|
23
|
+
eval `cat /etc/lsb-release `
|
24
|
+
export DEBIAN_FRONTEND=noninteractive
|
25
|
+
|
26
|
+
date > /etc/box_build_time
|
27
|
+
|
28
|
+
# source for sun java if you want to install it later
|
29
|
+
apt-get install -y python-software-properties
|
30
|
+
add-apt-repository -y ppa:ferramroberto/java
|
31
|
+
|
32
|
+
echo -e "`date` \n\n**** \n**** apt update:\n****\n"
|
33
|
+
apt-get -y update
|
34
|
+
apt-get -y upgrade
|
35
|
+
|
36
|
+
echo -e "`date` \n\n**** \n**** Installing base packages:\n****\n"
|
37
|
+
apt-get -y install build-essential make wget curl runit zlib1g-dev libssl-dev openssl libcurl4-openssl-dev libxml2-dev libxslt-dev libyaml-dev libreadline6 libreadline6-dev
|
38
|
+
apt-get clean
|
39
|
+
|
40
|
+
if [ ! -f /usr/bin/chef-client ]; then
|
41
|
+
echo -e "`date` \n\n**** \n**** Installing ruby version ${RUBY_VERSION}:\n****\n"
|
42
|
+
|
43
|
+
apt-get install -y ruby1.9.1 ruby1.9.1-dev
|
44
|
+
|
45
|
+
if ruby -e "exit(%x{gem --version} < \"1.6.2\" ? 0 : -1 )" ; then
|
46
|
+
echo -e "`date` \n\n**** \n**** Updating rubygems:\n****\n"
|
47
|
+
# screw you Debian
|
48
|
+
REALLY_GEM_UPDATE_SYSTEM=1 gem update --system
|
49
|
+
# screw you rubygems
|
50
|
+
for foo in /usr/lib/ruby/site_ruby/*/rubygems/deprecate.rb ; do
|
51
|
+
# Don't have to be any such deprecations, in which case $foo won't exist
|
52
|
+
[ -f "$foo" ] && sudo sed -i.bak 's!@skip ||= false!true!' "$foo"
|
53
|
+
done
|
54
|
+
fi
|
55
|
+
|
56
|
+
echo -e "`date` \n\n**** \n**** Installing chef:\n****\n"
|
57
|
+
gem install ohai --no-rdoc --no-ri
|
58
|
+
gem install chef --no-rdoc --no-ri <%= bootstrap_version_string %>
|
59
|
+
# gems needed for the client.rb or so generically useful you want them at hand
|
60
|
+
gem install --no-rdoc --no-ri extlib bundler json right_aws pry
|
61
|
+
|
62
|
+
else # no chef-client
|
63
|
+
echo -e "`date` \n\n**** \n**** Chef is present -- skipping apt/ruby/chef installation\n****\n"
|
64
|
+
fi # end ruby+chef install
|
65
|
+
|
66
|
+
# fix a bug in chef that prevents debugging template errors
|
67
|
+
# will not work with --prerelease but that's OK hopefully opscode patches this crap soon
|
68
|
+
bad_template_file="/usr/lib/ruby/gems/${RUBY_VERSION}/gems/chef-${CHEF_VERSION}/lib/chef/mixin/template.rb"
|
69
|
+
if echo "0505c482b8b0b333ac71bbc8a1795d19 $bad_template_file" | md5sum -c - 2>/dev/null ; then
|
70
|
+
curl https://github.com/mrflip/chef/commit/655a1967253a8759afb54f30b818bbcb7c309198.patch | sudo patch $bad_template_file
|
71
|
+
fi
|
72
|
+
|
73
|
+
echo -e "`date` \n\n**** \n**** Knifing in the chef client config files:\n****\n"
|
74
|
+
mkdir -p /etc/chef
|
75
|
+
|
76
|
+
<%- if @config[:client_key] %>
|
77
|
+
(
|
78
|
+
cat <<'EOP'
|
79
|
+
<%= @config[:client_key] %>
|
80
|
+
EOP
|
81
|
+
) > /tmp/knife-bootstrap/client.pem
|
82
|
+
awk NF /tmp/knife-bootstrap/client.pem > /etc/chef/client.pem
|
83
|
+
<%- else %>
|
84
|
+
(
|
85
|
+
cat <<'EOP'
|
86
|
+
<%= validation_key %>
|
87
|
+
EOP
|
88
|
+
) > /tmp/knife-bootstrap/validation.pem
|
89
|
+
awk NF /tmp/knife-bootstrap/validation.pem > /etc/chef/validation.pem
|
90
|
+
<%- end %>
|
91
|
+
|
92
|
+
echo -e "`date` \n\n**** \n**** Nuking our temp files:\n****\n"
|
93
|
+
|
94
|
+
cd /tmp
|
95
|
+
rm -rf /tmp/knife-bootstrap
|
96
|
+
|
97
|
+
echo -e "`date` \n\n**** \n**** Creating chef client script:\n****\n"
|
98
|
+
|
99
|
+
(
|
100
|
+
cat <<'EOP'
|
101
|
+
<%= config_content %>
|
102
|
+
<%= @config[:node].chef_client_script_content %>
|
103
|
+
EOP
|
104
|
+
) > /etc/chef/client.rb
|
105
|
+
|
106
|
+
(
|
107
|
+
cat <<'EOP'
|
108
|
+
<%= { "run_list" => @run_list, "cluster_name" => @config[:node].cluster_name, "facet_name" => @config[:node].facet_name, "facet_index" => @config[:node].facet_index }.to_json %>
|
109
|
+
EOP
|
110
|
+
) > /etc/chef/first-boot.json
|
111
|
+
|
112
|
+
echo -e "`date` \n\n**** \n**** Adding chef client runit scripts:\n****\n"
|
113
|
+
( service chef-client stop >/dev/null 2>&1 ; sleep 1 ; killall chef-client 2>/dev/null ) || true
|
114
|
+
mkdir -p /var/log/chef /var/chef /etc/service /etc/sv/chef-client/{log/main,supervise}
|
115
|
+
cat > /etc/sv/chef-client/log/run <<EOP
|
116
|
+
#!/bin/bash
|
117
|
+
exec svlogd -tt ./main
|
118
|
+
EOP
|
119
|
+
cat > /etc/sv/chef-client/run <<EOP
|
120
|
+
#!/bin/bash
|
121
|
+
exec 2>&1
|
122
|
+
exec /usr/bin/env chef-client -i 43200 -s 20 -L /var/log/chef/client.log
|
123
|
+
EOP
|
124
|
+
chmod +x /etc/sv/chef-client/log/run /etc/sv/chef-client/run
|
125
|
+
ln -nfs /usr/bin/sv /etc/init.d/chef-client
|
126
|
+
|
127
|
+
service chef-client stop >/dev/null 2>&1 || true
|
128
|
+
|
129
|
+
<%- if (@config[:bootstrap_runs_chef_client].to_s == 'true') || (@chef_config.knife[:bootstrap_runs_chef_client].to_s == 'true') %>
|
130
|
+
echo -e "`date` \n\n**** \n**** First run of chef:\n****\n"
|
131
|
+
set -e
|
132
|
+
<%= start_chef %>
|
133
|
+
set +e
|
134
|
+
<%- end %>
|
135
|
+
|
136
|
+
echo -e "`date` \n\n**** \n**** Cleanup:\n****\n"
|
137
|
+
# make locate work good
|
138
|
+
updatedb
|
139
|
+
|
140
|
+
echo -e "`date` \n\n**** \n**** Enabling chef client service:\n****\n"
|
141
|
+
ln -nfs /etc/sv/chef-client /etc/service/chef-client
|
142
|
+
service chef-client start
|
143
|
+
|
144
|
+
echo -e "`date` \n\n**** \n**** Cluster Chef client bootstrap complete\n****\n"
|
145
|
+
EOF
|
@@ -0,0 +1,74 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Philip (flip) Kromer (<flip@infochimps.com>)
|
3
|
+
# Copyright:: Copyright (c) 2011 Infochimps, Inc
|
4
|
+
# License:: Apache License, Version 2.0
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
|
19
|
+
require File.expand_path(File.dirname(__FILE__)+"/generic_command.rb")
|
20
|
+
require 'chef/knife/bootstrap'
|
21
|
+
|
22
|
+
class Chef
|
23
|
+
class Knife
|
24
|
+
class ClusterBootstrap < Ironfan::Script
|
25
|
+
|
26
|
+
option :ssh_user,
|
27
|
+
:long => "--ssh-user USERNAME",
|
28
|
+
:short => "-x USERNAME",
|
29
|
+
:description => "The ssh username"
|
30
|
+
option :bootstrap_runs_chef_client,
|
31
|
+
:long => "--[no-]bootstrap-runs-chef-client",
|
32
|
+
:description => "If bootstrap is invoked, the bootstrap script causes an initial run of chef-client (default true).",
|
33
|
+
:boolean => true,
|
34
|
+
:default => true
|
35
|
+
option :distro,
|
36
|
+
:long => "--distro DISTRO",
|
37
|
+
:short => "-d DISTRO",
|
38
|
+
:description => "Bootstrap a distro using a template"
|
39
|
+
option :template_file,
|
40
|
+
:long => "--template-file TEMPLATE",
|
41
|
+
:description => "Full path to location of template to use"
|
42
|
+
option :use_sudo,
|
43
|
+
:long => "--sudo",
|
44
|
+
:description => "Execute the bootstrap via sudo",
|
45
|
+
:boolean => true
|
46
|
+
option :host_key_verify,
|
47
|
+
:long => "--[no-]host-key-verify",
|
48
|
+
:description => "Verify host key, enabled by default.",
|
49
|
+
:boolean => true,
|
50
|
+
:default => true
|
51
|
+
|
52
|
+
import_banner_and_options(Chef::Knife::Bootstrap,
|
53
|
+
:except => [:chef_node_name, :run_list, :ssh_user, :distro, :template_file, :no_host_key_verify, :host_key_verify])
|
54
|
+
import_banner_and_options(Ironfan::Script)
|
55
|
+
|
56
|
+
deps do
|
57
|
+
Chef::Knife::Bootstrap.load_deps
|
58
|
+
Ironfan::Script.load_deps
|
59
|
+
end
|
60
|
+
|
61
|
+
def perform_execution(target)
|
62
|
+
target.each do |svr|
|
63
|
+
run_bootstrap(svr, svr.fog_server.dns_name)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def confirm_execution(target)
|
68
|
+
ui.info "Bootstrapping the node redoes its initial setup -- only do this on an aborted launch."
|
69
|
+
confirm_or_exit("Are you absolutely certain that you want to perform this action? (Type 'Yes' to confirm) ", 'Yes')
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Ash Berlin (ash_github@firemirror.om) and Philip (flip) Kromer (flip@infochimps.com)
|
3
|
+
# Copyright:: Copyright (c) 2011 DigiResults Ltd. and Infochimps, Inc.
|
4
|
+
# License:: Apache License, Version 2.0
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
|
19
|
+
require File.expand_path(File.dirname(__FILE__)+"/knife_common.rb")
|
20
|
+
require File.expand_path(File.dirname(__FILE__)+"/cluster_ssh.rb")
|
21
|
+
|
22
|
+
class Chef
|
23
|
+
class Knife
|
24
|
+
#
|
25
|
+
# Based on https://gist.github.com/1325982 by Ash Berlin
|
26
|
+
#
|
27
|
+
# "Since chef v0.10 you can send USR1 to the chef-client process and it
|
28
|
+
# will wake up and do a run. But the usual case when I want to do a run
|
29
|
+
# is cos I'm either testing a cookbook change or I want to deploy now. I
|
30
|
+
# could just run sudo chef-client but then that will only log to std
|
31
|
+
# out. Just run this script, it will send chef-client a USR1 signal and
|
32
|
+
# then tail the log file (but nicely so that you'll get your terminal
|
33
|
+
# back when the run completes)."
|
34
|
+
#
|
35
|
+
class ClusterKick < Chef::Knife::ClusterSsh
|
36
|
+
|
37
|
+
import_banner_and_options(Chef::Knife::ClusterSsh)
|
38
|
+
banner 'knife cluster kick "CLUSTER [FACET [INDEXES]]" (options) - start a run of chef-client on each server, tailing the logs and exiting when the run completes.'
|
39
|
+
|
40
|
+
option :pid_file,
|
41
|
+
:long => "--pid_file",
|
42
|
+
:description => "Where to find the pid file. Typically /var/run/chef/client.pid (init.d) or /etc/sv/chef-client/supervise/pid (runit)",
|
43
|
+
:default => "/etc/sv/chef-client/supervise/pid"
|
44
|
+
|
45
|
+
unless defined?(KICKSTART_SCRIPT)
|
46
|
+
KICKSTART_SCRIPT = <<EOF
|
47
|
+
#!/bin/bash
|
48
|
+
set -e
|
49
|
+
<%= ((config[:verbosity].to_i > 1) ? "set -v" : "") %>
|
50
|
+
|
51
|
+
if sudo service chef-client status ; then
|
52
|
+
|
53
|
+
# running
|
54
|
+
pid_file="<%= config[:pid_file] %>"
|
55
|
+
log_file=/var/log/chef/client.log
|
56
|
+
|
57
|
+
declare tail_pid
|
58
|
+
|
59
|
+
on_exit() {
|
60
|
+
rm -f $pipe
|
61
|
+
[ -n "$tail_pid" ] && kill $tail_pid
|
62
|
+
}
|
63
|
+
|
64
|
+
trap "on_exit" EXIT ERR
|
65
|
+
|
66
|
+
pipe=/tmp/pipe-$$
|
67
|
+
mkfifo $pipe
|
68
|
+
|
69
|
+
tail -fn0 "$log_file" > $pipe &
|
70
|
+
|
71
|
+
tail_pid=$!
|
72
|
+
|
73
|
+
sudo true
|
74
|
+
pid="$(sudo cat $pid_file)"
|
75
|
+
sudo kill -USR1 "$pid"
|
76
|
+
sed -r "/(ERROR: Sleeping for [0-9]+ seconds before trying again|INFO: Report handlers complete)\$/{q}" $pipe
|
77
|
+
|
78
|
+
else
|
79
|
+
echo -e "****\n\nchef-client daemon not running, invoking chef-client directly\n\n****\n"
|
80
|
+
sudo chef-client
|
81
|
+
fi
|
82
|
+
EOF
|
83
|
+
end
|
84
|
+
|
85
|
+
def run
|
86
|
+
@name_args = [ @name_args.join(' ') ]
|
87
|
+
script = Erubis::Eruby.new(KICKSTART_SCRIPT).result(:config => config)
|
88
|
+
@name_args[1] = script
|
89
|
+
super
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Chris Howe (<howech@infochimps.com>)
|
3
|
+
# Copyright:: Copyright (c) 2011 Infochimps, Inc
|
4
|
+
# License:: Apache License, Version 2.0
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
|
19
|
+
require File.expand_path(File.dirname(__FILE__)+"/generic_command.rb")
|
20
|
+
|
21
|
+
class Chef
|
22
|
+
class Knife
|
23
|
+
class ClusterKill < Ironfan::Script
|
24
|
+
import_banner_and_options(Ironfan::Script)
|
25
|
+
|
26
|
+
option :kill_bogus,
|
27
|
+
:long => "--kill-bogus",
|
28
|
+
:description => "Kill bogus servers (ones that exist, but are not defined in the clusters file)",
|
29
|
+
:boolean => true,
|
30
|
+
:default => false
|
31
|
+
option :cloud,
|
32
|
+
:long => '--[no-]cloud',
|
33
|
+
:description => "Kill machines from cloud (default is yes, terminate machines; use --no-cloud to skip)",
|
34
|
+
:boolean => true,
|
35
|
+
:default => true
|
36
|
+
option :chef,
|
37
|
+
:long => "--[no-]chef",
|
38
|
+
:description => "Delete the chef node and client (default is yes, delete chef objects; use --no-chef to skip)",
|
39
|
+
:boolean => true,
|
40
|
+
:default => true
|
41
|
+
|
42
|
+
def relevant?(server)
|
43
|
+
server.killable?
|
44
|
+
end
|
45
|
+
|
46
|
+
# Execute every last mf'ing one of em
|
47
|
+
def perform_execution(target)
|
48
|
+
if config[:cloud]
|
49
|
+
section("Killing Cloud Machines")
|
50
|
+
target.select(&:in_cloud?).destroy
|
51
|
+
end
|
52
|
+
|
53
|
+
if config[:chef]
|
54
|
+
section("Killing Chef")
|
55
|
+
target.select(&:in_chef? ).delete_chef
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def display(target, *args, &block)
|
60
|
+
super
|
61
|
+
ui.info Formatador.display_line("[red]Bogus servers detected[reset]: [blue]#{target.bogus_servers.map(&:fullname).inspect}[reset]") unless target.bogus_servers.empty?
|
62
|
+
end
|
63
|
+
|
64
|
+
def confirm_execution(target)
|
65
|
+
delete_message = [
|
66
|
+
(((!config[:chef]) || target.chef_nodes.empty?) ? nil : "#{target.chef_nodes.length} chef nodes"),
|
67
|
+
(((!config[:cloud]) || target.fog_servers.empty?) ? nil : "#{target.fog_servers.length} fog servers") ].compact.join(" and ")
|
68
|
+
confirm_or_exit("Are you absolutely certain that you want to delete #{delete_message}? (Type 'Yes' to confirm) ", 'Yes')
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,164 @@
|
|
1
|
+
#
|
2
|
+
# Author:: Philip (flip) Kromer (<flip@infochimps.com>)
|
3
|
+
# Copyright:: Copyright (c) 2011 Infochimps, Inc
|
4
|
+
# License:: Apache License, Version 2.0
|
5
|
+
#
|
6
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
7
|
+
# you may not use this file except in compliance with the License.
|
8
|
+
# You may obtain a copy of the License at
|
9
|
+
#
|
10
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
11
|
+
#
|
12
|
+
# Unless required by applicable law or agreed to in writing, software
|
13
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
14
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
15
|
+
# See the License for the specific language governing permissions and
|
16
|
+
# limitations under the License.
|
17
|
+
#
|
18
|
+
|
19
|
+
require File.expand_path(File.dirname(__FILE__)+"/knife_common.rb")
|
20
|
+
require File.expand_path(File.dirname(__FILE__)+"/cluster_bootstrap.rb")
|
21
|
+
|
22
|
+
class Chef
|
23
|
+
class Knife
|
24
|
+
class ClusterLaunch < Knife
|
25
|
+
include Ironfan::KnifeCommon
|
26
|
+
|
27
|
+
deps do
|
28
|
+
require 'time'
|
29
|
+
require 'socket'
|
30
|
+
Chef::Knife::ClusterBootstrap.load_deps
|
31
|
+
end
|
32
|
+
|
33
|
+
banner "knife cluster launch CLUSTER_NAME [FACET_NAME [INDEXES]] (options)"
|
34
|
+
[ :ssh_port, :ssh_password, :identity_file, :use_sudo,
|
35
|
+
:prerelease, :bootstrap_version, :template_file, :distro,
|
36
|
+
:bootstrap_runs_chef_client, :host_key_verify
|
37
|
+
].each do |name|
|
38
|
+
option name, Chef::Knife::ClusterBootstrap.options[name]
|
39
|
+
end
|
40
|
+
|
41
|
+
option :dry_run,
|
42
|
+
:long => "--dry-run",
|
43
|
+
:description => "Don't really run, just use mock calls",
|
44
|
+
:boolean => true,
|
45
|
+
:default => false
|
46
|
+
option :force,
|
47
|
+
:long => "--force",
|
48
|
+
:description => "Perform launch operations even if it may not be safe to do so. Default false",
|
49
|
+
:boolean => true,
|
50
|
+
:default => false
|
51
|
+
|
52
|
+
option :bootstrap,
|
53
|
+
:long => "--[no-]bootstrap",
|
54
|
+
:description => "Also bootstrap the launched node (default is NOT to bootstrap)",
|
55
|
+
:boolean => true,
|
56
|
+
:default => false
|
57
|
+
|
58
|
+
def run
|
59
|
+
load_ironfan
|
60
|
+
die(banner) if @name_args.empty?
|
61
|
+
configure_dry_run
|
62
|
+
|
63
|
+
#
|
64
|
+
# Load the facet
|
65
|
+
#
|
66
|
+
full_target = get_slice(*@name_args)
|
67
|
+
display(full_target)
|
68
|
+
target = full_target.select(&:launchable?)
|
69
|
+
|
70
|
+
warn_or_die_on_bogus_servers(full_target) unless full_target.bogus_servers.empty?
|
71
|
+
|
72
|
+
die("", "#{ui.color("All servers are running -- not launching any.",:blue)}", "", 1) if target.empty?
|
73
|
+
|
74
|
+
# Pre-populate information in chef
|
75
|
+
section("Sync'ing to chef and cloud")
|
76
|
+
target.sync_to_cloud
|
77
|
+
target.sync_to_chef
|
78
|
+
|
79
|
+
# Launch servers
|
80
|
+
section("Launching machines", :green)
|
81
|
+
target.create_servers
|
82
|
+
|
83
|
+
ui.info("")
|
84
|
+
display(target)
|
85
|
+
|
86
|
+
# As each server finishes, configure it
|
87
|
+
watcher_threads = target.parallelize do |svr|
|
88
|
+
perform_after_launch_tasks(svr)
|
89
|
+
end
|
90
|
+
|
91
|
+
progressbar_for_threads(watcher_threads)
|
92
|
+
|
93
|
+
display(target)
|
94
|
+
end
|
95
|
+
|
96
|
+
def display(target)
|
97
|
+
super(target, ["Name", "InstanceID", "State", "Flavor", "Image", "AZ", "Public IP", "Private IP", "Created At", 'Volumes', 'Elastic IP']) do |svr|
|
98
|
+
{ 'launchable?' => (svr.launchable? ? "[blue]#{svr.launchable?}[reset]" : '-' ), }
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def perform_after_launch_tasks(server)
|
103
|
+
# Wait for node creation on amazon side
|
104
|
+
server.fog_server.wait_for{ ready? }
|
105
|
+
|
106
|
+
# Try SSH
|
107
|
+
unless config[:dry_run]
|
108
|
+
nil until tcp_test_ssh(server.fog_server.dns_name){ sleep @initial_sleep_delay ||= 10 }
|
109
|
+
end
|
110
|
+
|
111
|
+
# Make sure our list of volumes is accurate
|
112
|
+
Ironfan.fetch_fog_volumes
|
113
|
+
server.discover_volumes!
|
114
|
+
|
115
|
+
# Attach volumes, etc
|
116
|
+
server.sync_to_cloud
|
117
|
+
|
118
|
+
# Run Bootstrap
|
119
|
+
if config[:bootstrap]
|
120
|
+
run_bootstrap(server, server.fog_server.dns_name)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
def tcp_test_ssh(hostname)
|
125
|
+
tcp_socket = TCPSocket.new(hostname, 22)
|
126
|
+
readable = IO.select([tcp_socket], nil, nil, 5)
|
127
|
+
if readable
|
128
|
+
Chef::Log.debug("sshd accepting connections on #{hostname}, banner is #{tcp_socket.gets}")
|
129
|
+
yield
|
130
|
+
true
|
131
|
+
else
|
132
|
+
false
|
133
|
+
end
|
134
|
+
rescue Errno::ETIMEDOUT
|
135
|
+
false
|
136
|
+
rescue Errno::ECONNREFUSED
|
137
|
+
sleep 2
|
138
|
+
false
|
139
|
+
ensure
|
140
|
+
tcp_socket && tcp_socket.close
|
141
|
+
end
|
142
|
+
|
143
|
+
def warn_or_die_on_bogus_servers(target)
|
144
|
+
ui.info("")
|
145
|
+
ui.info "Cluster has servers in a transitional or undefined state (shown as 'bogus'):"
|
146
|
+
ui.info("")
|
147
|
+
display(target)
|
148
|
+
ui.info("")
|
149
|
+
unless config[:force]
|
150
|
+
die(
|
151
|
+
"Launch operations may be unpredictable under these circumstances.",
|
152
|
+
"You should wait for the cluster to stabilize, fix the undefined server problems",
|
153
|
+
"(run \"knife cluster show CLUSTER\" to see what the problems are), or launch",
|
154
|
+
"the cluster anyway using the --force option.", "", -2)
|
155
|
+
end
|
156
|
+
ui.info("")
|
157
|
+
ui.info "--force specified"
|
158
|
+
ui.info "Proceeding to launch anyway. This may produce undesired results."
|
159
|
+
ui.info("")
|
160
|
+
end
|
161
|
+
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|