ironfan 3.2.2 → 4.0.0

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.
Files changed (66) hide show
  1. data/CHANGELOG.md +5 -0
  2. data/VERSION +1 -1
  3. data/ironfan.gemspec +33 -20
  4. data/lib/chef/knife/cluster_kick.rb +17 -17
  5. data/lib/chef/knife/cluster_kill.rb +13 -7
  6. data/lib/chef/knife/cluster_launch.rb +60 -66
  7. data/lib/chef/knife/cluster_pry.rb +2 -2
  8. data/lib/chef/knife/cluster_show.rb +3 -6
  9. data/lib/chef/knife/cluster_ssh.rb +5 -11
  10. data/lib/chef/knife/cluster_start.rb +2 -4
  11. data/lib/chef/knife/cluster_stop.rb +1 -3
  12. data/lib/chef/knife/cluster_sync.rb +13 -21
  13. data/lib/chef/knife/ironfan_knife_common.rb +11 -9
  14. data/lib/chef/knife/ironfan_script.rb +2 -1
  15. data/lib/gorillib/resolution.rb +119 -0
  16. data/lib/ironfan/broker/computer.rb +316 -0
  17. data/lib/ironfan/broker/drive.rb +21 -0
  18. data/lib/ironfan/broker.rb +37 -0
  19. data/lib/ironfan/builder.rb +14 -0
  20. data/lib/ironfan/deprecated.rb +16 -58
  21. data/lib/ironfan/dsl/cloud.rb +21 -0
  22. data/lib/ironfan/dsl/cluster.rb +27 -0
  23. data/lib/ironfan/dsl/compute.rb +84 -0
  24. data/lib/ironfan/dsl/ec2.rb +260 -0
  25. data/lib/ironfan/dsl/facet.rb +25 -0
  26. data/lib/ironfan/dsl/role.rb +19 -0
  27. data/lib/ironfan/dsl/server.rb +31 -0
  28. data/lib/ironfan/dsl/virtualbox.rb +8 -0
  29. data/lib/ironfan/dsl/volume.rb +45 -0
  30. data/lib/ironfan/dsl.rb +7 -0
  31. data/lib/ironfan/headers.rb +58 -0
  32. data/lib/ironfan/provider/chef/client.rb +77 -0
  33. data/lib/ironfan/provider/chef/node.rb +133 -0
  34. data/lib/ironfan/provider/chef/role.rb +69 -0
  35. data/lib/ironfan/provider/chef.rb +28 -0
  36. data/lib/ironfan/provider/ec2/ebs_volume.rb +137 -0
  37. data/lib/ironfan/provider/ec2/elastic_ip.rb +10 -0
  38. data/lib/ironfan/provider/ec2/key_pair.rb +65 -0
  39. data/lib/ironfan/provider/ec2/machine.rb +258 -0
  40. data/lib/ironfan/provider/ec2/placement_group.rb +24 -0
  41. data/lib/ironfan/provider/ec2/security_group.rb +118 -0
  42. data/lib/ironfan/provider/ec2.rb +47 -0
  43. data/lib/ironfan/provider/virtualbox/machine.rb +10 -0
  44. data/lib/ironfan/provider/virtualbox.rb +8 -0
  45. data/lib/ironfan/provider.rb +139 -0
  46. data/lib/ironfan/requirements.rb +52 -0
  47. data/lib/ironfan.rb +44 -33
  48. metadata +34 -21
  49. data/lib/chef/knife/cluster_vagrant.rb +0 -144
  50. data/lib/chef/knife/vagrant/ironfan_environment.rb +0 -18
  51. data/lib/chef/knife/vagrant/ironfan_provisioners.rb +0 -27
  52. data/lib/chef/knife/vagrant/skeleton_vagrantfile.rb +0 -119
  53. data/lib/ironfan/chef_layer.rb +0 -300
  54. data/lib/ironfan/cloud.rb +0 -323
  55. data/lib/ironfan/cluster.rb +0 -118
  56. data/lib/ironfan/compute.rb +0 -139
  57. data/lib/ironfan/discovery.rb +0 -190
  58. data/lib/ironfan/dsl_builder.rb +0 -99
  59. data/lib/ironfan/facet.rb +0 -143
  60. data/lib/ironfan/fog_layer.rb +0 -196
  61. data/lib/ironfan/private_key.rb +0 -130
  62. data/lib/ironfan/role_implications.rb +0 -58
  63. data/lib/ironfan/security_group.rb +0 -133
  64. data/lib/ironfan/server.rb +0 -291
  65. data/lib/ironfan/server_slice.rb +0 -265
  66. 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,10 @@
1
+ module Ironfan
2
+ class Provider
3
+ class Ec2
4
+
5
+ class ElasticIp < Ironfan::Provider::Resource
6
+
7
+ end
8
+ end
9
+ end
10
+ 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