ironfan 3.2.2 → 4.0.0

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