ironfan 3.2.2 → 4.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +5 -0
- data/VERSION +1 -1
- data/ironfan.gemspec +33 -20
- data/lib/chef/knife/cluster_kick.rb +17 -17
- data/lib/chef/knife/cluster_kill.rb +13 -7
- data/lib/chef/knife/cluster_launch.rb +60 -66
- data/lib/chef/knife/cluster_pry.rb +2 -2
- data/lib/chef/knife/cluster_show.rb +3 -6
- data/lib/chef/knife/cluster_ssh.rb +5 -11
- data/lib/chef/knife/cluster_start.rb +2 -4
- data/lib/chef/knife/cluster_stop.rb +1 -3
- data/lib/chef/knife/cluster_sync.rb +13 -21
- data/lib/chef/knife/ironfan_knife_common.rb +11 -9
- data/lib/chef/knife/ironfan_script.rb +2 -1
- data/lib/gorillib/resolution.rb +119 -0
- data/lib/ironfan/broker/computer.rb +316 -0
- data/lib/ironfan/broker/drive.rb +21 -0
- data/lib/ironfan/broker.rb +37 -0
- data/lib/ironfan/builder.rb +14 -0
- data/lib/ironfan/deprecated.rb +16 -58
- data/lib/ironfan/dsl/cloud.rb +21 -0
- data/lib/ironfan/dsl/cluster.rb +27 -0
- data/lib/ironfan/dsl/compute.rb +84 -0
- data/lib/ironfan/dsl/ec2.rb +260 -0
- data/lib/ironfan/dsl/facet.rb +25 -0
- data/lib/ironfan/dsl/role.rb +19 -0
- data/lib/ironfan/dsl/server.rb +31 -0
- data/lib/ironfan/dsl/virtualbox.rb +8 -0
- data/lib/ironfan/dsl/volume.rb +45 -0
- data/lib/ironfan/dsl.rb +7 -0
- data/lib/ironfan/headers.rb +58 -0
- data/lib/ironfan/provider/chef/client.rb +77 -0
- data/lib/ironfan/provider/chef/node.rb +133 -0
- data/lib/ironfan/provider/chef/role.rb +69 -0
- data/lib/ironfan/provider/chef.rb +28 -0
- data/lib/ironfan/provider/ec2/ebs_volume.rb +137 -0
- data/lib/ironfan/provider/ec2/elastic_ip.rb +10 -0
- data/lib/ironfan/provider/ec2/key_pair.rb +65 -0
- data/lib/ironfan/provider/ec2/machine.rb +258 -0
- data/lib/ironfan/provider/ec2/placement_group.rb +24 -0
- data/lib/ironfan/provider/ec2/security_group.rb +118 -0
- data/lib/ironfan/provider/ec2.rb +47 -0
- data/lib/ironfan/provider/virtualbox/machine.rb +10 -0
- data/lib/ironfan/provider/virtualbox.rb +8 -0
- data/lib/ironfan/provider.rb +139 -0
- data/lib/ironfan/requirements.rb +52 -0
- data/lib/ironfan.rb +44 -33
- metadata +34 -21
- data/lib/chef/knife/cluster_vagrant.rb +0 -144
- data/lib/chef/knife/vagrant/ironfan_environment.rb +0 -18
- data/lib/chef/knife/vagrant/ironfan_provisioners.rb +0 -27
- data/lib/chef/knife/vagrant/skeleton_vagrantfile.rb +0 -119
- data/lib/ironfan/chef_layer.rb +0 -300
- data/lib/ironfan/cloud.rb +0 -323
- data/lib/ironfan/cluster.rb +0 -118
- data/lib/ironfan/compute.rb +0 -139
- data/lib/ironfan/discovery.rb +0 -190
- data/lib/ironfan/dsl_builder.rb +0 -99
- data/lib/ironfan/facet.rb +0 -143
- data/lib/ironfan/fog_layer.rb +0 -196
- data/lib/ironfan/private_key.rb +0 -130
- data/lib/ironfan/role_implications.rb +0 -58
- data/lib/ironfan/security_group.rb +0 -133
- data/lib/ironfan/server.rb +0 -291
- data/lib/ironfan/server_slice.rb +0 -265
- data/lib/ironfan/volume.rb +0 -146
@@ -0,0 +1,133 @@
|
|
1
|
+
module Ironfan
|
2
|
+
class Provider
|
3
|
+
class ChefServer
|
4
|
+
|
5
|
+
class Node < Ironfan::Provider::Resource
|
6
|
+
delegate :[], :[]=, :add_to_index, :apply_expansion_attributes,
|
7
|
+
:attribute, :attribute=, :attribute?, :automatic_attrs,
|
8
|
+
:automatic_attrs=, :cdb_destroy, :cdb_save, :chef_environment,
|
9
|
+
:chef_environment=, :chef_server_rest, :class_from_file,
|
10
|
+
:construct_attributes, :consume_attributes,
|
11
|
+
:consume_external_attrs, :consume_run_list, :cookbook_collection,
|
12
|
+
:cookbook_collection=, :couchdb, :couchdb=, :couchdb_id,
|
13
|
+
:couchdb_id=, :couchdb_rev, :couchdb_rev=, :create, :default,
|
14
|
+
:default_attrs, :default_attrs=, :default_unless,
|
15
|
+
:delete_from_index, :destroy, :display_hash, :each,
|
16
|
+
:each_attribute, :each_key, :each_value, :expand!, :find_file,
|
17
|
+
:from_file, :has_key?, :include_attribute, :index_id, :index_id=,
|
18
|
+
:index_object_type, :key?, :keys,
|
19
|
+
:load_attribute_by_short_filename, :load_attributes, :name, :node,
|
20
|
+
:normal, :normal_attrs, :normal_attrs=, :normal_unless, :override,
|
21
|
+
:override_attrs, :override_attrs=, :override_unless, :recipe?,
|
22
|
+
:recipe_list, :recipe_list=, :reset_defaults_and_overrides, :role?,
|
23
|
+
:run_list, :run_list=, :run_list?, :run_state, :run_state=, :save,
|
24
|
+
:set, :set_if_args, :set_or_return, :set_unless, :drive, :tags,
|
25
|
+
:to_hash, :update_from!, :validate, :with_indexer_metadata,
|
26
|
+
:to => :adaptee
|
27
|
+
|
28
|
+
def initialize(*args)
|
29
|
+
super
|
30
|
+
self.adaptee ||= Chef::Node.new
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.shared?() false; end
|
34
|
+
def self.multiple?() false; end
|
35
|
+
# def self.resource_type() self; end
|
36
|
+
def self.resource_type() :node; end
|
37
|
+
def self.expected_ids(computer) [computer.server.fullname]; end
|
38
|
+
|
39
|
+
def to_display(style,values={})
|
40
|
+
values["Chef?"] = adaptee.nil? ? "no" : "yes"
|
41
|
+
values
|
42
|
+
end
|
43
|
+
|
44
|
+
def save!(computer)
|
45
|
+
prepare_from computer
|
46
|
+
save
|
47
|
+
end
|
48
|
+
|
49
|
+
def create!(computer)
|
50
|
+
prepare_from computer
|
51
|
+
|
52
|
+
client = computer[:client]
|
53
|
+
unless File.exists?(client.key_filename)
|
54
|
+
raise("Cannot create chef node #{name} -- client #{@chef_client} exists but no client key found in #{client.key_filename}.")
|
55
|
+
end
|
56
|
+
ChefServer.post_rest("nodes", adaptee, :client => client)
|
57
|
+
end
|
58
|
+
|
59
|
+
def prepare_from(computer)
|
60
|
+
organization = Chef::Config.organization
|
61
|
+
normal[:organization] = organization unless organization.nil?
|
62
|
+
|
63
|
+
server = computer.server
|
64
|
+
chef_environment = server.environment
|
65
|
+
run_list.instance_eval { @run_list_items = server.run_list }
|
66
|
+
normal[:cluster_name] = server.cluster_name
|
67
|
+
normal[:facet_name] = server.facet_name
|
68
|
+
normal[:permanent] = computer.permanent?
|
69
|
+
normal[:volumes] = {}
|
70
|
+
computer.drives.each {|v| normal[:volumes][v.name] = v.node}
|
71
|
+
end
|
72
|
+
|
73
|
+
def announce_state state
|
74
|
+
set[:state] = state
|
75
|
+
save
|
76
|
+
end
|
77
|
+
|
78
|
+
def conterminous_with_machine?
|
79
|
+
true
|
80
|
+
end
|
81
|
+
|
82
|
+
#
|
83
|
+
# Discovery
|
84
|
+
#
|
85
|
+
def self.load!(cluster=nil)
|
86
|
+
ChefServer.search(:node,"name:#{cluster.name}-*") do |raw|
|
87
|
+
next if raw.blank?
|
88
|
+
node = Node.new
|
89
|
+
node.adaptee = raw
|
90
|
+
remember node
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def on_correlate(computer)
|
95
|
+
self['volumes'].each do |name,volume|
|
96
|
+
computer.drive(name).node.merge! volume
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def self.validate_computer!(computer)
|
101
|
+
return unless computer.node and not computer[:client]
|
102
|
+
computer.node.bogus << :node_without_client
|
103
|
+
end
|
104
|
+
|
105
|
+
#
|
106
|
+
# Manipulation
|
107
|
+
#
|
108
|
+
def self.create!(computer)
|
109
|
+
return if computer.node?
|
110
|
+
node = Node.new
|
111
|
+
node.name computer.server.fullname
|
112
|
+
node.create! computer
|
113
|
+
computer.node = node
|
114
|
+
remember node
|
115
|
+
end
|
116
|
+
|
117
|
+
def self.destroy!(computer)
|
118
|
+
return unless computer.node?
|
119
|
+
forget computer.node.name
|
120
|
+
computer.node.destroy
|
121
|
+
computer.delete(:node)
|
122
|
+
end
|
123
|
+
|
124
|
+
def self.save!(computer)
|
125
|
+
return unless computer.node?
|
126
|
+
computer.node.save! computer
|
127
|
+
end
|
128
|
+
|
129
|
+
end
|
130
|
+
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module Ironfan
|
2
|
+
class Provider
|
3
|
+
class ChefServer
|
4
|
+
|
5
|
+
class Role < Ironfan::Provider::Resource
|
6
|
+
delegate :active_run_list_for, :add_to_index, :cdb_destroy, :cdb_save,
|
7
|
+
:chef_server_rest, :class_from_file, :couchdb, :couchdb=,
|
8
|
+
:couchdb_id, :couchdb_id=, :couchdb_rev, :couchdb_rev=, :create,
|
9
|
+
:default_attributes, :delete_from_index, :description, :destroy,
|
10
|
+
:env_run_list, :env_run_lists, :environment, :environments,
|
11
|
+
:from_file, :index_id, :index_id=, :index_object_type, :name,
|
12
|
+
:override_attributes, :recipes, :run_list, :run_list_for, :save,
|
13
|
+
:set_or_return, :to_hash, :update_from!, :validate,
|
14
|
+
:with_indexer_metadata,
|
15
|
+
:to => :adaptee
|
16
|
+
|
17
|
+
def self.shared?() true; end
|
18
|
+
def self.multiple?() true; end
|
19
|
+
# def self.resource_type() self; end
|
20
|
+
def self.resource_type() :role; end
|
21
|
+
def self.expected_ids(computer)
|
22
|
+
[ computer.server.cluster_role.name.to_s,
|
23
|
+
computer.server.facet_role.name.to_s ]
|
24
|
+
end
|
25
|
+
|
26
|
+
def initialize(config={})
|
27
|
+
super
|
28
|
+
if self.adaptee.nil? and not config[:expected].nil?
|
29
|
+
expected = config[:expected]
|
30
|
+
desc = "Ironfan generated role for #{expected.name}"
|
31
|
+
self.adaptee = Chef::Role.new
|
32
|
+
self.name expected.name
|
33
|
+
self.override_attributes expected.override_attributes
|
34
|
+
self.default_attributes expected.default_attributes
|
35
|
+
self.description desc
|
36
|
+
end
|
37
|
+
raise "Missing adaptee" if self.adaptee.nil?
|
38
|
+
self
|
39
|
+
end
|
40
|
+
|
41
|
+
#
|
42
|
+
# Discovery
|
43
|
+
#
|
44
|
+
def self.load!(cluster)
|
45
|
+
ChefServer.search(:role,"name:#{cluster.name}_*") do |raw|
|
46
|
+
next if raw.blank?
|
47
|
+
remember Role.new(:adaptee => raw)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
#
|
52
|
+
# Manipulation
|
53
|
+
#
|
54
|
+
def self.save!(computer)
|
55
|
+
dsl_roles = []
|
56
|
+
dsl_roles << computer.server.cluster_role
|
57
|
+
dsl_roles << computer.server.facet_role
|
58
|
+
|
59
|
+
dsl_roles.each do |dsl_role|
|
60
|
+
next if recall? dsl_role.name # Handle each role only once
|
61
|
+
role = remember new(:expected => dsl_role)
|
62
|
+
role.save
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Ironfan
|
2
|
+
class Provider
|
3
|
+
|
4
|
+
class ChefServer < Ironfan::Provider
|
5
|
+
|
6
|
+
def self.resources
|
7
|
+
[ Client, Node, Role ]
|
8
|
+
end
|
9
|
+
|
10
|
+
#
|
11
|
+
# Utility functions
|
12
|
+
#
|
13
|
+
def self.post_rest(type, content, options={})
|
14
|
+
params = [ Chef::Config[:chef_server_url] ]
|
15
|
+
if options[:client]
|
16
|
+
params << options[:client].name
|
17
|
+
params << options[:client].key_filename
|
18
|
+
end
|
19
|
+
Chef::REST.new(*params).post_rest(type,content)
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.search(*params,&block)
|
23
|
+
Chef::Search::Query.new.search(*params,&block)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,137 @@
|
|
1
|
+
module Ironfan
|
2
|
+
class Provider
|
3
|
+
class Ec2
|
4
|
+
|
5
|
+
class EbsVolume < Ironfan::Provider::Resource
|
6
|
+
delegate :_dump, :attached_at, :attached_at=, :attributes,
|
7
|
+
:availability_zone, :availability_zone=, :collection, :collection=,
|
8
|
+
:connection, :connection=, :created_at, :created_at=,
|
9
|
+
:delete_on_termination, :delete_on_termination=, :destroy, :device,
|
10
|
+
:device=, :dup_attributes!, :force_detach, :id, :id=, :identity,
|
11
|
+
:identity=, :merge_attributes, :missing_attributes, :new_record?,
|
12
|
+
:ready?, :reload, :requires, :requires_one, :save, :server,
|
13
|
+
:server=, :server_id, :server_id=, :size, :size=, :snapshot,
|
14
|
+
:snapshot_id, :snapshot_id=, :snapshots, :state, :state=,
|
15
|
+
:symbolize_keys, :tags, :tags=, :wait_for,
|
16
|
+
:to => :adaptee
|
17
|
+
field :dsl_volume, Ironfan::Dsl::Volume
|
18
|
+
|
19
|
+
def self.shared?() false; end
|
20
|
+
def self.multiple?() true; end
|
21
|
+
def self.resource_type() :ebs_volume; end
|
22
|
+
def self.expected_ids(computer)
|
23
|
+
computer.server.volumes.values.map do |volume|
|
24
|
+
saved = computer.node[:volumes][volume.name][:volume_id] rescue nil
|
25
|
+
ebs_name = "#{computer.server.fullname}-#{volume.name}"
|
26
|
+
[ volume.volume_id, saved, ebs_name]
|
27
|
+
end.flatten.compact
|
28
|
+
end
|
29
|
+
|
30
|
+
def name
|
31
|
+
tags["Name"] || tags["name"] || id
|
32
|
+
end
|
33
|
+
|
34
|
+
def ephemeral_device?
|
35
|
+
false
|
36
|
+
end
|
37
|
+
|
38
|
+
#
|
39
|
+
# Discovery
|
40
|
+
#
|
41
|
+
def self.load!(cluster=nil)
|
42
|
+
Ec2.connection.volumes.each do |vol|
|
43
|
+
next if vol.blank?
|
44
|
+
ebs = EbsVolume.new(:adaptee => vol)
|
45
|
+
# Already have a volume by this name
|
46
|
+
if recall? ebs.name
|
47
|
+
ebs.bogus << :duplicate_volumes
|
48
|
+
recall(ebs.name).bogus << :duplicate_volumes
|
49
|
+
remember ebs, :append_id => "duplicate:#{ebs.id}"
|
50
|
+
else
|
51
|
+
remember ebs
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def on_correlate(computer)
|
57
|
+
Chef::Log.warn("ebs_volume::on_correlate is incomplete")
|
58
|
+
end
|
59
|
+
|
60
|
+
# def self.correlate!(computer)
|
61
|
+
# Chef::Log.warn("CODE SMELL: overly large method: #{caller}")
|
62
|
+
# return unless computer.server?
|
63
|
+
# computer.server.volumes.each do |volume|
|
64
|
+
# unless volume.attachable.to_s == 'ebs'
|
65
|
+
# Chef::Log.debug("Ignoring non-EBS volume = #{volume}")
|
66
|
+
# next
|
67
|
+
# end
|
68
|
+
#
|
69
|
+
# drive = computer.drive(volume.name)
|
70
|
+
# drive.node = computer.node[:volumes][volume.name].to_hash rescue {}
|
71
|
+
# if drive.node.has_key? :volume_id
|
72
|
+
# node_volume_id = drive.node[:volume_id]
|
73
|
+
# end
|
74
|
+
# ebs_name = "#{computer.server.fullname}-#{volume.name}"
|
75
|
+
#
|
76
|
+
# volume_id = volume.volume_id
|
77
|
+
# volume_id ||= node_volume_id
|
78
|
+
#
|
79
|
+
# # Volumes may match against name derived from the cluster definition,
|
80
|
+
# # or volume_id from the cluster definition or node
|
81
|
+
# case
|
82
|
+
# when (recall? ebs_name)
|
83
|
+
# ebs = recall ebs_name
|
84
|
+
# when (volume_id and recall? volume_id)
|
85
|
+
# ebs = recall volume_id
|
86
|
+
# else
|
87
|
+
# log_message = "Volume not found: name = #{ebs_name}"
|
88
|
+
# log_message += ", volume_id = #{volume_id}"
|
89
|
+
# Chef::Log.debug(log_message)
|
90
|
+
# next
|
91
|
+
# end
|
92
|
+
#
|
93
|
+
# # Make sure all the known volume_ids match
|
94
|
+
# [ ebs.id, volume.volume_id, node_volume_id ].compact.each do |id|
|
95
|
+
# id == volume_id or ebs.bogus << :volume_id_mismatch
|
96
|
+
# end if volume_id
|
97
|
+
#
|
98
|
+
# computer.bogus += ebs.bogus
|
99
|
+
# ebs.owner = computer.object_id
|
100
|
+
# drive.volume = volume
|
101
|
+
# drive.disk = ebs
|
102
|
+
# end
|
103
|
+
# end
|
104
|
+
def self.validate_computer!(computer)
|
105
|
+
Chef::Log.warn("ebs_volume::validate_computer! is incomplete")
|
106
|
+
# # Make sure all the known volume_ids match
|
107
|
+
# [ ebs.id, volume.volume_id, node_volume_id ].compact.each do |id|
|
108
|
+
# id == volume_id or ebs.bogus << :volume_id_mismatch
|
109
|
+
# end if volume_id
|
110
|
+
end
|
111
|
+
|
112
|
+
#
|
113
|
+
# Manipulation
|
114
|
+
#
|
115
|
+
|
116
|
+
def self.save!(computer)
|
117
|
+
Ironfan.step(computer.name,"syncing EBS volumes",:blue)
|
118
|
+
computer.drives.each do |drive|
|
119
|
+
# Only worry about computers with ebs volumes
|
120
|
+
ebs = drive.disk or next
|
121
|
+
# Only attach volumes if they aren't already attached
|
122
|
+
if ebs.server_id.nil?
|
123
|
+
Ironfan.step(computer.name, " - attaching #{ebs.name}", :blue)
|
124
|
+
Ironfan.safely do
|
125
|
+
ebs.device = drive.volume.device
|
126
|
+
ebs.server = computer.machine.adaptee
|
127
|
+
end
|
128
|
+
end
|
129
|
+
# Record the volume information in chef
|
130
|
+
drive.node['volume_id'] = ebs.id
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module Ironfan
|
2
|
+
class Provider
|
3
|
+
class Ec2
|
4
|
+
|
5
|
+
class KeyPair < Ironfan::Provider::Resource
|
6
|
+
delegate :_dump, :collection, :collection=, :connection,
|
7
|
+
:connection=, :destroy, :fingerprint, :fingerprint=, :identity,
|
8
|
+
:identity=, :name, :name=, :new_record?, :public_key,
|
9
|
+
:public_key=, :reload, :requires, :requires_one, :save,
|
10
|
+
:symbolize_keys, :wait_for, :writable?, :write,
|
11
|
+
:to => :adaptee
|
12
|
+
field :key_filename, String,
|
13
|
+
:default => ->{ "#{KeyPair.key_dir}/#{name}.pem" }
|
14
|
+
|
15
|
+
def self.shared?() true; end
|
16
|
+
def self.multiple?() false; end
|
17
|
+
def self.resource_type() :key_pair; end
|
18
|
+
def self.expected_ids(computer) [computer.server.cluster_name]; end
|
19
|
+
|
20
|
+
def private_key
|
21
|
+
File.open(key_filename, "rb").read
|
22
|
+
end
|
23
|
+
|
24
|
+
def private_key=(body=nil)
|
25
|
+
File.open(key_filename, "w", 0600){|f| f.print( body ) }
|
26
|
+
end
|
27
|
+
|
28
|
+
#
|
29
|
+
# Discovery
|
30
|
+
#
|
31
|
+
def self.load!(cluster=nil)
|
32
|
+
Ec2.connection.key_pairs.each do |keypair|
|
33
|
+
register keypair unless keypair.blank?
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
#
|
38
|
+
# Manipulation
|
39
|
+
#
|
40
|
+
|
41
|
+
def self.create!(computer)
|
42
|
+
name = computer.server.cluster_name
|
43
|
+
return if recall? name
|
44
|
+
Ironfan.step(name, "creating key pair for #{name}", :blue)
|
45
|
+
result = Ec2.connection.create_key_pair(name)
|
46
|
+
private_key = result.body["keyMaterial"]
|
47
|
+
load! # Reload to get the native object
|
48
|
+
recall(name).private_key = private_key
|
49
|
+
end
|
50
|
+
|
51
|
+
#
|
52
|
+
# Utility
|
53
|
+
#
|
54
|
+
|
55
|
+
def self.key_dir
|
56
|
+
return Chef::Config.ec2_key_dir if Chef::Config.ec2_key_dir
|
57
|
+
dir = "#{ENV['HOME']}/.chef/credentials/ec2_keys"
|
58
|
+
warn "Please set 'ec2_key_dir' in your knife.rb. Will use #{dir} as a default"
|
59
|
+
dir
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|