ironfan 5.0.11 → 6.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -0
- data/.gitmodules +3 -0
- data/Gemfile +8 -26
- data/Gemfile.lock +38 -41
- data/NOTES-REALM.md +172 -0
- data/Rakefile +19 -77
- data/config/ubuntu12.04-ironfan.erb +7 -0
- data/ironfan.gemspec +28 -225
- data/lib/chef/cluster_knife.rb +26 -0
- data/lib/chef/knife/bootstrap/ubuntu12.04-ironfan.erb +7 -0
- data/lib/chef/knife/cluster_bootstrap.rb +1 -3
- data/lib/chef/knife/cluster_diff.rb +2 -8
- data/lib/chef/knife/cluster_kick.rb +1 -3
- data/lib/chef/knife/cluster_kill.rb +1 -2
- data/lib/chef/knife/cluster_launch.rb +17 -34
- data/lib/chef/knife/cluster_list.rb +6 -5
- data/lib/chef/knife/cluster_proxy.rb +1 -3
- data/lib/chef/knife/cluster_pry.rb +1 -2
- data/lib/chef/knife/cluster_show.rb +6 -7
- data/lib/chef/knife/cluster_ssh.rb +10 -8
- data/lib/chef/knife/cluster_start.rb +1 -2
- data/lib/chef/knife/cluster_stop.rb +1 -2
- data/lib/chef/knife/cluster_sync.rb +2 -3
- data/lib/chef/knife/ironfan_knife_common.rb +58 -18
- data/lib/chef/knife/ironfan_script.rb +0 -3
- data/lib/ironfan/broker/computer.rb +14 -11
- data/lib/ironfan/broker.rb +17 -12
- data/lib/ironfan/cookbook_requirements.rb +155 -0
- data/lib/ironfan/dsl/cloud.rb +2 -0
- data/lib/ironfan/dsl/cluster.rb +25 -15
- data/lib/ironfan/dsl/component.rb +12 -15
- data/lib/ironfan/dsl/compute.rb +10 -8
- data/lib/ironfan/dsl/ec2.rb +2 -26
- data/lib/ironfan/dsl/facet.rb +16 -14
- data/lib/ironfan/dsl/openstack.rb +147 -0
- data/lib/ironfan/dsl/realm.rb +23 -16
- data/lib/ironfan/dsl/security_group.rb +29 -0
- data/lib/ironfan/dsl/server.rb +14 -5
- data/lib/ironfan/dsl/static.rb +63 -0
- data/lib/ironfan/dsl/vsphere.rb +1 -0
- data/lib/ironfan/dsl.rb +1 -134
- data/lib/ironfan/headers.rb +19 -0
- data/lib/ironfan/provider/chef/node.rb +3 -2
- data/lib/ironfan/provider/ec2/machine.rb +10 -14
- data/lib/ironfan/provider/ec2/security_group.rb +58 -43
- data/lib/ironfan/provider/openstack/elastic_ip.rb +96 -0
- data/lib/ironfan/provider/openstack/keypair.rb +78 -0
- data/lib/ironfan/provider/openstack/machine.rb +371 -0
- data/lib/ironfan/provider/openstack/security_group.rb +224 -0
- data/lib/ironfan/provider/openstack.rb +69 -0
- data/lib/ironfan/provider/static/machine.rb +192 -0
- data/lib/ironfan/provider/static.rb +23 -0
- data/lib/ironfan/provider.rb +58 -1
- data/lib/ironfan/requirements.rb +17 -1
- data/lib/ironfan/version.rb +3 -0
- data/lib/ironfan.rb +107 -172
- data/spec/chef/cluster_bootstrap_spec.rb +2 -7
- data/spec/chef/cluster_launch_spec.rb +1 -2
- data/spec/fixtures/realms/samurai.rb +26 -0
- data/spec/integration/minimal-chef-repo/clusters/.gitkeep +0 -0
- data/spec/integration/minimal-chef-repo/config/.gitkeep +0 -0
- data/spec/integration/minimal-chef-repo/knife/credentials/.gitignore +1 -0
- data/spec/integration/minimal-chef-repo/knife/credentials/certificates/.gitkeep +0 -0
- data/spec/integration/minimal-chef-repo/knife/credentials/client_keys/.gitkeep +0 -0
- data/spec/integration/minimal-chef-repo/knife/credentials/data_bag_keys/.gitkeep +0 -0
- data/spec/integration/minimal-chef-repo/knife/credentials/ec2_certs/.gitkeep +0 -0
- data/spec/integration/minimal-chef-repo/knife/credentials/ec2_keys/.gitkeep +0 -0
- data/spec/integration/minimal-chef-repo/knife/credentials/ironfantest-validator.pem +27 -0
- data/spec/integration/minimal-chef-repo/knife/credentials/ironfantester.pem +27 -0
- data/spec/integration/minimal-chef-repo/tasks/.gitkeep +0 -0
- data/spec/ironfan/cluster_spec.rb +1 -2
- data/spec/ironfan/diff_spec.rb +0 -2
- data/spec/ironfan/dsl_spec.rb +6 -3
- data/spec/ironfan/ec2/cloud_provider_spec.rb +17 -18
- data/spec/ironfan/ec2/elb_spec.rb +44 -41
- data/spec/ironfan/ec2/security_group_spec.rb +45 -47
- data/spec/ironfan/manifest_spec.rb +0 -1
- data/spec/ironfan/plugin_spec.rb +55 -40
- data/spec/ironfan/realm_spec.rb +42 -30
- data/spec/spec_helper.rb +17 -31
- data/spec/{spec_helper → support}/dummy_chef.rb +0 -0
- data/spec/{spec_helper → support}/dummy_diff_drawer.rb +0 -0
- metadata +78 -155
- data/.rspec +0 -2
- data/.yardopts +0 -19
- data/VERSION +0 -2
- data/chefignore +0 -41
- data/notes/Future-development-proposals.md +0 -266
- data/notes/Home.md +0 -55
- data/notes/INSTALL-cloud_setup.md +0 -103
- data/notes/INSTALL.md +0 -134
- data/notes/Ironfan-Roadmap.md +0 -70
- data/notes/Upgrading-to-v4.md +0 -66
- data/notes/advanced-superpowers.md +0 -16
- data/notes/aws_servers.jpg +0 -0
- data/notes/aws_user_key.png +0 -0
- data/notes/cookbook-versioning.md +0 -11
- data/notes/core_concepts.md +0 -200
- data/notes/declaring_volumes.md +0 -3
- data/notes/design_notes-aspect_oriented_devops.md +0 -36
- data/notes/design_notes-ci_testing.md +0 -169
- data/notes/design_notes-cookbook_event_ordering.md +0 -249
- data/notes/design_notes-meta_discovery.md +0 -59
- data/notes/ec2-pricing_and_capacity.md +0 -75
- data/notes/ec2-pricing_and_capacity.numbers +0 -0
- data/notes/homebase-layout.txt +0 -102
- data/notes/knife-cluster-commands.md +0 -21
- data/notes/named-cloud-objects.md +0 -11
- data/notes/opscode_org_key.png +0 -0
- data/notes/opscode_user_key.png +0 -0
- data/notes/philosophy.md +0 -13
- data/notes/rake_tasks.md +0 -24
- data/notes/renamed-recipes.txt +0 -142
- data/notes/silverware.md +0 -85
- data/notes/style_guide.md +0 -300
- data/notes/tips_and_troubleshooting.md +0 -92
- data/notes/walkthrough-hadoop.md +0 -168
- data/notes/walkthrough-web.md +0 -166
- data/spec/fixtures/gunbai.rb +0 -24
- data/spec/test_config.rb +0 -20
- data/tasks/chef_config.rake +0 -38
@@ -0,0 +1,224 @@
|
|
1
|
+
module Ironfan
|
2
|
+
class Provider
|
3
|
+
class OpenStack
|
4
|
+
|
5
|
+
class SecurityGroup < Ironfan::Provider::Resource
|
6
|
+
|
7
|
+
WIDE_OPEN = Range.new(1,65535)
|
8
|
+
|
9
|
+
delegate :_dump, :authorize_group_and_owner, :authorize_port_range,
|
10
|
+
:collection, :collection=, :connection, :connection=, :description,
|
11
|
+
:description=, :destroy, :group_id, :group_id=, :identity,
|
12
|
+
:identity=, :ip_permissions=, :name, :name=,
|
13
|
+
:new_record?, :owner_id, :owner_id=, :reload, :requires,
|
14
|
+
:requires_one, :revoke_group_and_owner, :revoke_port_range, :save,
|
15
|
+
:symbolize_keys, :wait_for, :name,
|
16
|
+
:create_security_group_rule,
|
17
|
+
:rules,
|
18
|
+
:to => :adaptee
|
19
|
+
|
20
|
+
def self.shared?() true; end
|
21
|
+
def self.multiple?() true; end
|
22
|
+
def self.resource_type() :security_group; end
|
23
|
+
|
24
|
+
def self.expected_ids(computer)
|
25
|
+
return unless computer.server
|
26
|
+
openstack = computer.server.cloud(:openstack)
|
27
|
+
server_groups = computer.server.security_groups
|
28
|
+
cloud_groups = openstack.security_groups
|
29
|
+
|
30
|
+
result = []
|
31
|
+
[server_groups, cloud_groups].each do |container|
|
32
|
+
container.each { |g| result.push(g.name) }
|
33
|
+
end
|
34
|
+
return result.uniq
|
35
|
+
end
|
36
|
+
|
37
|
+
def ip_permissions
|
38
|
+
end
|
39
|
+
|
40
|
+
def group_id
|
41
|
+
@adaptee.id
|
42
|
+
end
|
43
|
+
|
44
|
+
#
|
45
|
+
# Discovery
|
46
|
+
#
|
47
|
+
def self.load!(cluster=nil)
|
48
|
+
OpenStack.connection.security_groups.reject { |raw| raw.blank? }.each do |raw|
|
49
|
+
remember SecurityGroup.new(:adaptee => raw)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def receive_adaptee(obj)
|
54
|
+
obj = OpenStack.connection.security_groups.new(obj) if obj.is_a?(Hash)
|
55
|
+
super
|
56
|
+
end
|
57
|
+
|
58
|
+
def to_s
|
59
|
+
if ip_permissions.present?
|
60
|
+
perm_str = ip_permissions.map{|perm|
|
61
|
+
"%s:%s-%s (%s | %s)" % [
|
62
|
+
perm['ipProtocol'], perm['fromPort'], perm['toPort'],
|
63
|
+
perm['groups' ].map{|el| el['groupName'] }.join(','),
|
64
|
+
perm['ipRanges'].map{|el| el['cidrIp'] }.join(','),
|
65
|
+
]
|
66
|
+
}
|
67
|
+
return "<%-15s %-12s %-25s %s>" % [ self.class.handle, group_id, name, perm_str]
|
68
|
+
else
|
69
|
+
return "<%-15s %-12s %s>" % [ self.class.handle, group_id, name ]
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
#
|
74
|
+
# Manipulation
|
75
|
+
#
|
76
|
+
def self.prepare!(computers)
|
77
|
+
# Create any groups that don't yet exist, and ensure any authorizations
|
78
|
+
# that are required for those groups
|
79
|
+
cluster_name = nil
|
80
|
+
groups_to_create = [ ]
|
81
|
+
authorizations_to_ensure = [ ]
|
82
|
+
|
83
|
+
computers.each{|comp| ensure_groups(comp) if OpenStack.applicable(comp) } # Add facet and cluster security groups for the computer
|
84
|
+
|
85
|
+
# First, deduce the list of all groups to which at least one instance belongs
|
86
|
+
# We'll use this later to decide whether to create groups, or authorize access,
|
87
|
+
# using a VPC security group or an Openstack security group.
|
88
|
+
groups_that_should_exist = [] #computers.map{|comp| expected_ids(comp) }.flatten.compact.sort.uniq
|
89
|
+
groups_to_create << groups_that_should_exist
|
90
|
+
|
91
|
+
computers.select { |computer| OpenStack.applicable computer }.each do |computer|
|
92
|
+
cloud = computer.server.cloud(:openstack)
|
93
|
+
cluster_name = computer.server.cluster_name
|
94
|
+
|
95
|
+
# Iterate over all of the security group information, keeping track of
|
96
|
+
# any groups that must exist and any authorizations that must be ensured
|
97
|
+
[computer.server.security_groups, cloud.security_groups].each do |container|
|
98
|
+
|
99
|
+
container.values.each do |dsl_group|
|
100
|
+
|
101
|
+
groups_to_create << dsl_group.name
|
102
|
+
|
103
|
+
groups_to_create << dsl_group.group_authorized
|
104
|
+
|
105
|
+
groups_to_create << dsl_group.group_authorized_by
|
106
|
+
|
107
|
+
authorizations_to_ensure << dsl_group.group_authorized.map do |other_group|
|
108
|
+
{
|
109
|
+
:grantor => dsl_group.name,
|
110
|
+
:grantee => other_group,
|
111
|
+
:grantee_type => :group,
|
112
|
+
:range => WIDE_OPEN,
|
113
|
+
}
|
114
|
+
end
|
115
|
+
|
116
|
+
authorizations_to_ensure << dsl_group.group_authorized_by.map do |other_group|
|
117
|
+
{
|
118
|
+
:grantor => other_group,
|
119
|
+
:grantee => dsl_group.name,
|
120
|
+
:grantee_type => :group,
|
121
|
+
:range => WIDE_OPEN,
|
122
|
+
}
|
123
|
+
end
|
124
|
+
|
125
|
+
authorizations_to_ensure << dsl_group.range_authorizations.map do |range_auth|
|
126
|
+
range, cidr, protocol = range_auth
|
127
|
+
{
|
128
|
+
:grantor => dsl_group.name,
|
129
|
+
:grantee => { :cidr_ip => cidr, :ip_protocol => protocol },
|
130
|
+
:grantee_type => :cidr,
|
131
|
+
:range => range,
|
132
|
+
}
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
groups_to_create = groups_to_create.flatten.uniq.reject { |group| recall? group.to_s }.sort
|
138
|
+
authorizations_to_ensure = authorizations_to_ensure.flatten.uniq.sort { |a,b| a[:grantor] <=> b[:grantor] }
|
139
|
+
|
140
|
+
Ironfan.step(cluster_name, "creating security groups", :blue) unless groups_to_create.empty?
|
141
|
+
groups_to_create.each do |group|
|
142
|
+
if group =~ /\//
|
143
|
+
Ironfan.step(group, " assuming that owner/group pair #{group} already exists", :blue)
|
144
|
+
else
|
145
|
+
Ironfan.step(group, " creating #{group} security group", :blue)
|
146
|
+
begin
|
147
|
+
tokens = group.to_s.split(':')
|
148
|
+
group_id = tokens.pop
|
149
|
+
OpenStack.connection.create_security_group(group_id,"Ironfan created group #{group_id}")
|
150
|
+
rescue Fog::Compute::OpenStack::Error => e # InvalidPermission.Duplicate
|
151
|
+
Chef::Log.info("ignoring security group error: #{e}")
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
# Re-load everything so that we have a @@known list of security groups to manipulate
|
157
|
+
load! unless groups_to_create.empty?
|
158
|
+
|
159
|
+
# Now make sure that all required authorizations are present
|
160
|
+
Ironfan.step(cluster_name, "ensuring security group permissions", :blue) unless authorizations_to_ensure.empty?
|
161
|
+
authorizations_to_ensure.each do |auth|
|
162
|
+
grantor_fog = recall(auth[:grantor])
|
163
|
+
if :group == auth[:grantee_type]
|
164
|
+
if fog_grantee = recall(auth[:grantee])
|
165
|
+
options = { :group => fog_grantee.group_id }
|
166
|
+
elsif auth[:grantee] =~ /\//
|
167
|
+
options = { :group_alias => auth[:grantee] }
|
168
|
+
else
|
169
|
+
raise "Don't know what to do with authorization grantee #{auth[:grantee]}"
|
170
|
+
end
|
171
|
+
message = " ensuring access from #{auth[:grantee]} to #{auth[:grantor]}"
|
172
|
+
else
|
173
|
+
options = auth[:grantee]
|
174
|
+
message = " ensuring #{auth[:grantee][:ip_protocol]} access from #{auth[:grantee][:cidr_ip]} to #{auth[:range]}"
|
175
|
+
end
|
176
|
+
Ironfan.step(auth[:grantor], message, :blue)
|
177
|
+
safely_authorize(grantor_fog, auth[:range], options)
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
#
|
182
|
+
# Utility
|
183
|
+
#
|
184
|
+
def self.ensure_groups(computer)
|
185
|
+
return unless OpenStack.applicable computer
|
186
|
+
# Ensure the security_groups include those for cluster & facet
|
187
|
+
# FIXME: This violates the DSL's immutability; it should be
|
188
|
+
# something calculated from within the DSL construction
|
189
|
+
Ironfan.todo("CODE SMELL: violation of DSL immutability: #{caller}")
|
190
|
+
server = computer.server
|
191
|
+
c_group = server.security_group(computer.server.cluster_name)
|
192
|
+
c_group.authorized_by_group(c_group.name)
|
193
|
+
facet_name = "#{computer.server.cluster_name}-#{computer.server.facet_name}"
|
194
|
+
server.security_group(facet_name)
|
195
|
+
end
|
196
|
+
|
197
|
+
|
198
|
+
# Try an authorization, ignoring duplicates (this is easier than correlating).
|
199
|
+
# Do so for both TCP and UDP, unless only one is specified
|
200
|
+
def self.safely_authorize(fog_group,range,options)
|
201
|
+
if options[:group_alias]
|
202
|
+
owner, group = options[:group_alias].split(/\//)
|
203
|
+
self.patiently(fog_group.name, Fog::Compute::OpenStack::Error, :ignore => Proc.new { |e| e.message =~ /This rule already exists in group/ }) do
|
204
|
+
OpenStack.connection.authorize_security_group_ingress(
|
205
|
+
'GroupName' => fog_group.name,
|
206
|
+
'SourceSecurityGroupName' => group,
|
207
|
+
'SourceSecurityGroupOwnerId' => owner
|
208
|
+
)
|
209
|
+
end
|
210
|
+
elsif options[:ip_protocol]
|
211
|
+
self.patiently(fog_group.name, Excon::Errors::HTTPStatusError, :ignore => Proc.new { |e| e.message =~ /This rule already exists in group/ }) do
|
212
|
+
fog_group.create_security_group_rule(range.min, range.max, options[:ip_protocol], options[:cidr_ip], options[:group])
|
213
|
+
end
|
214
|
+
else
|
215
|
+
safely_authorize(fog_group,range,options.merge(:ip_protocol => 'tcp'))
|
216
|
+
safely_authorize(fog_group,range,options.merge(:ip_protocol => 'udp'))
|
217
|
+
safely_authorize(fog_group,Range.new(-1,-1),options.merge(:ip_protocol => 'icmp')) if(range == WIDE_OPEN)
|
218
|
+
return
|
219
|
+
end
|
220
|
+
end
|
221
|
+
end
|
222
|
+
end
|
223
|
+
end
|
224
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module Ironfan
|
2
|
+
class Provider
|
3
|
+
|
4
|
+
class OpenStack < Ironfan::IaasProvider
|
5
|
+
self.handle = :openstack
|
6
|
+
|
7
|
+
def self.resources
|
8
|
+
[ Machine, Keypair, SecurityGroup, ElasticIp ]
|
9
|
+
end
|
10
|
+
|
11
|
+
#
|
12
|
+
# Utility functions
|
13
|
+
#
|
14
|
+
def self.connection
|
15
|
+
@@connection ||= Fog::Compute.new(self.openstack_credentials.merge({ :provider => 'openstack' }))
|
16
|
+
end
|
17
|
+
|
18
|
+
|
19
|
+
#
|
20
|
+
# Returns a hash that maps flavor names to flavors
|
21
|
+
#
|
22
|
+
def self.flavor_hash
|
23
|
+
@@flavors ||= self.connection.flavors.inject({}){|h,f| h[f.name]=f; h }
|
24
|
+
end
|
25
|
+
|
26
|
+
#
|
27
|
+
# Returns a hash that maps flavor ids to flavors
|
28
|
+
#
|
29
|
+
def self.flavor_id_hash
|
30
|
+
@@flavor_ids ||= self.connection.flavors.inject({}){|h,f| h[f.id]=f; h }
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
# Ensure that a fog object (machine, volume, etc.) has the proper tags on it
|
35
|
+
def self.ensure_tags(tags,fog)
|
36
|
+
# openstack does not have tags.
|
37
|
+
|
38
|
+
#tags.delete_if {|k, v| fog.tags[k] == v.to_s rescue false }
|
39
|
+
#return if tags.empty?
|
40
|
+
|
41
|
+
#Ironfan.step(fog.name,"tagging with #{tags.inspect}", :green)
|
42
|
+
#tags.each do |k, v|
|
43
|
+
# Chef::Log.debug( "tagging #{fog.name} with #{k} = #{v}" )
|
44
|
+
# Ironfan.safely do
|
45
|
+
# config = {:key => k, :value => v.to_s, :resource_id => fog.id }
|
46
|
+
# connection.tags.create(config)
|
47
|
+
# end
|
48
|
+
#end
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.applicable(computer)
|
52
|
+
computer.server and computer.server.clouds.include?(:openstack)
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def self.openstack_credentials
|
58
|
+
return {
|
59
|
+
:openstack_api_key => Chef::Config[:knife][:openstack_api_key],
|
60
|
+
:openstack_username => Chef::Config[:knife][:openstack_username],
|
61
|
+
:openstack_auth_url => Chef::Config[:knife][:openstack_auth_url],
|
62
|
+
:openstack_tenant => Chef::Config[:knife][:openstack_tenant],
|
63
|
+
:openstack_region => Chef::Config[:knife][:openstack_region],
|
64
|
+
}
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,192 @@
|
|
1
|
+
module Ironfan
|
2
|
+
class Provider
|
3
|
+
class Static
|
4
|
+
class Machine < Ironfan::IaasProvider::Machine
|
5
|
+
|
6
|
+
def self.shared?() false; end
|
7
|
+
def self.multiple?() false; end
|
8
|
+
def self.resource_type() :machine; end
|
9
|
+
def self.expected_ids(computer) [computer.server.full_name]; end
|
10
|
+
|
11
|
+
def name() adaptee.full_name; end
|
12
|
+
def tags
|
13
|
+
t = {"Name" => @adaptee.name}
|
14
|
+
return t.keys.inject({}) {|h,k| h[k]=t[k]; h[k.to_sym]=t[k]; h}
|
15
|
+
end
|
16
|
+
|
17
|
+
def vpc_id
|
18
|
+
return nil
|
19
|
+
end
|
20
|
+
|
21
|
+
def created_at
|
22
|
+
nil
|
23
|
+
end
|
24
|
+
|
25
|
+
def flavor_id
|
26
|
+
return nil
|
27
|
+
end
|
28
|
+
|
29
|
+
def flavor_name
|
30
|
+
"nil"
|
31
|
+
end
|
32
|
+
|
33
|
+
def image_id
|
34
|
+
"none"
|
35
|
+
end
|
36
|
+
|
37
|
+
def groups ; [] ; end
|
38
|
+
|
39
|
+
def public_hostname ; adaptee.cloud(:static).public_hostname || public_ip_address ; end
|
40
|
+
def public_ip_address ; adaptee.cloud(:static).public_ip || private_ip_address ; end
|
41
|
+
def dns_name ; public_ip_address ; end
|
42
|
+
|
43
|
+
def keypair ; adaptee.cloud(:static).keypair ; end
|
44
|
+
|
45
|
+
def created?
|
46
|
+
false
|
47
|
+
end
|
48
|
+
def pending?
|
49
|
+
false
|
50
|
+
end
|
51
|
+
def running?
|
52
|
+
true
|
53
|
+
end
|
54
|
+
def stopping?
|
55
|
+
false
|
56
|
+
end
|
57
|
+
|
58
|
+
def stopped?
|
59
|
+
false
|
60
|
+
end
|
61
|
+
|
62
|
+
def error?
|
63
|
+
false
|
64
|
+
end
|
65
|
+
|
66
|
+
def start
|
67
|
+
end
|
68
|
+
|
69
|
+
def stop
|
70
|
+
end
|
71
|
+
|
72
|
+
def perform_after_launch_tasks?
|
73
|
+
true
|
74
|
+
end
|
75
|
+
|
76
|
+
def to_display(style,values={})
|
77
|
+
# style == :minimal
|
78
|
+
values["State"] = "???"
|
79
|
+
values["MachineID"] = private_ip_address
|
80
|
+
values["Public IP"] = private_ip_address
|
81
|
+
values["Private IP"] = public_ip_address
|
82
|
+
values["Created On"] = "???"
|
83
|
+
return values if style == :minimal
|
84
|
+
|
85
|
+
# style == :default
|
86
|
+
values["Flavor"] = nil
|
87
|
+
values["AZ"] = nil
|
88
|
+
return values if style == :default
|
89
|
+
|
90
|
+
# style == :expanded
|
91
|
+
values["Image"] = "none"
|
92
|
+
#values["Volumes"] = volumes.map(&:id).join(', ')
|
93
|
+
values["SSH Key"] = "none"
|
94
|
+
values
|
95
|
+
end
|
96
|
+
|
97
|
+
def ssh_key
|
98
|
+
keypair = cloud.keypair || computer.server.cluster_name
|
99
|
+
end
|
100
|
+
|
101
|
+
def key_name
|
102
|
+
keypair
|
103
|
+
end
|
104
|
+
|
105
|
+
def private_ip_address
|
106
|
+
adaptee.cloud(:static).private_ip
|
107
|
+
end
|
108
|
+
|
109
|
+
def availability_zone
|
110
|
+
'none'
|
111
|
+
end
|
112
|
+
|
113
|
+
def destroy
|
114
|
+
end
|
115
|
+
|
116
|
+
def to_s
|
117
|
+
"<%-15s %-12s %-25s %-25s %-15s %-15s %-12s %-12s %s:%s>" % [
|
118
|
+
self.class.handle, "", created_at, name, private_ip_address, public_ip_address, flavor_name, availability_zone, key_name, groups.join(',') ]
|
119
|
+
end
|
120
|
+
|
121
|
+
#
|
122
|
+
# Discovery
|
123
|
+
#
|
124
|
+
def self.load!(cluster=nil)
|
125
|
+
cluster.facets.each do |facet|
|
126
|
+
facet.servers.each do |server|
|
127
|
+
machine = new(:adaptee => server)
|
128
|
+
remember machine
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
# Find active machines that haven't matched, but should have,
|
134
|
+
# make sure all bogus machines have a computer to attach to
|
135
|
+
# for display purposes
|
136
|
+
def self.validate_resources!(computers)
|
137
|
+
recall.each_value do |machine|
|
138
|
+
next unless machine.users.empty? and machine.name
|
139
|
+
if machine.name.match("^#{computers.cluster.name}-")
|
140
|
+
machine.bogus << :unexpected_machine
|
141
|
+
end
|
142
|
+
next unless machine.bogus?
|
143
|
+
fake = Ironfan::Broker::Computer.new
|
144
|
+
fake[:machine] = machine
|
145
|
+
fake.name = machine.name
|
146
|
+
machine.users << fake
|
147
|
+
computers << fake
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
#
|
152
|
+
# Manipulation
|
153
|
+
#
|
154
|
+
def self.create!(computer)
|
155
|
+
nil
|
156
|
+
end
|
157
|
+
|
158
|
+
# @returns [Hash{String, Array}] of 'what you did wrong' => [relevant, info]
|
159
|
+
def self.lint(computer)
|
160
|
+
cloud = computer.server.cloud(:static)
|
161
|
+
info = [computer.name, cloud.inspect]
|
162
|
+
errors = {}
|
163
|
+
server_errors = computer.server.lint
|
164
|
+
errors["No Private IP"] = info if cloud.private_ip.blank?
|
165
|
+
errors
|
166
|
+
end
|
167
|
+
|
168
|
+
def self.launch_description(computer)
|
169
|
+
nil
|
170
|
+
end
|
171
|
+
|
172
|
+
# An array of hashes with dorky-looking keys, just like Fog wants it.
|
173
|
+
def self.block_device_mapping(computer)
|
174
|
+
[]
|
175
|
+
end
|
176
|
+
|
177
|
+
def self.destroy!(computer)
|
178
|
+
return unless computer.machine?
|
179
|
+
forget computer.machine.name
|
180
|
+
computer.machine.destroy
|
181
|
+
computer.machine.reload # show the node as shutting down
|
182
|
+
end
|
183
|
+
|
184
|
+
def self.save!(computer)
|
185
|
+
return unless computer.machine?
|
186
|
+
return unless computer.created?
|
187
|
+
nil
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
192
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Ironfan
|
2
|
+
class Provider
|
3
|
+
class Static < Ironfan::IaasProvider
|
4
|
+
self.handle = :static
|
5
|
+
|
6
|
+
def self.resources
|
7
|
+
[ Machine ]
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.ensure_tags(tags,fog)
|
11
|
+
# Ironfan.safely do
|
12
|
+
# config = {:key => k, :value => v.to_s, :resource_id => fog.id }
|
13
|
+
# connection.tags.create(config)
|
14
|
+
# end
|
15
|
+
#end
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.applicable(computer)
|
19
|
+
computer.server and computer.server.clouds.include?(:static)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/lib/ironfan/provider.rb
CHANGED
@@ -13,6 +13,8 @@ module Ironfan
|
|
13
13
|
case obj[:name]
|
14
14
|
when :chef then Chef
|
15
15
|
when :ec2 then Ec2
|
16
|
+
when :openstack then OpenStack
|
17
|
+
when :static then Static
|
16
18
|
when :vsphere then Vsphere
|
17
19
|
when :virtualbox then VirtualBox
|
18
20
|
when :rds then Rds
|
@@ -204,7 +206,62 @@ module Ironfan
|
|
204
206
|
class Machine < Resource
|
205
207
|
# A Machine lives and dies with its Computer
|
206
208
|
def self.shared?() false; end
|
209
|
+
|
210
|
+
def self.cloud_init_user_data(computer)
|
211
|
+
return <<EOF
|
212
|
+
#cloud-config
|
213
|
+
# The line above is critical - without it cloud-init will not interpret the machine
|
214
|
+
# user data as a cloud-init script.
|
215
|
+
|
216
|
+
# The following logs everything cloud init does to /var/log
|
217
|
+
output: {all: '| tee -a /var/log/cloud-init-output.log'}
|
218
|
+
|
219
|
+
# Set our hostname
|
220
|
+
manage_etc_hosts: True
|
221
|
+
|
222
|
+
cloud_init_modules:
|
223
|
+
- bootcmd
|
224
|
+
- resizefs
|
225
|
+
- set_hostname
|
226
|
+
- update_hostname
|
227
|
+
- update_etc_hosts
|
228
|
+
- write-files
|
229
|
+
- ca-certs
|
230
|
+
- rsyslog
|
231
|
+
- ssh
|
232
|
+
|
233
|
+
fqdn: #{computer.server.fqdn}
|
234
|
+
|
235
|
+
bootcmd:
|
236
|
+
# note that writefiles is not supported on precise...
|
237
|
+
- |
|
238
|
+
mkdir -p /etc/chef
|
239
|
+
touch /etc/chef/client.pem
|
240
|
+
chmod 600 /etc/chef/client.pem
|
241
|
+
chown root:root /etc/chef/client.pem
|
242
|
+
cat > /etc/chef/client.pem << EOF
|
243
|
+
#{computer.private_key.split("\n").map {|l| " "+l}.join("\n")}
|
244
|
+
EOF
|
245
|
+
domainname #{computer.server.fqdn}
|
246
|
+
|
247
|
+
chef:
|
248
|
+
install_type: "packages"
|
249
|
+
force_install: false
|
250
|
+
server_url: #{Chef::Config[:chef_server_url]}
|
251
|
+
node_name: #{computer.name}
|
252
|
+
initial_attributes:
|
253
|
+
chef_server: #{Chef::Config[:chef_server_url]}
|
254
|
+
node_name: #{computer.name}
|
255
|
+
organization: #{Chef::Config[:organization]}
|
256
|
+
realm_name: #{computer.server.realm_name}
|
257
|
+
cluster_name: #{computer.server.cluster_name}
|
258
|
+
facet_name: #{computer.server.facet_name}
|
259
|
+
facet_index: #{computer.server.index}
|
260
|
+
validation_name: "no-validator"
|
261
|
+
validation_key: |
|
262
|
+
We don't need no stinking validators.
|
263
|
+
EOF
|
264
|
+
end
|
207
265
|
end
|
208
266
|
end
|
209
|
-
|
210
267
|
end
|
data/lib/ironfan/requirements.rb
CHANGED
@@ -1,7 +1,10 @@
|
|
1
|
+
# Built on top of chef
|
2
|
+
require 'chef'
|
3
|
+
|
1
4
|
# Gorillib core classes
|
2
5
|
require 'gorillib/builder'
|
6
|
+
require 'gorillib/diff'
|
3
7
|
require 'gorillib/resolution'
|
4
|
-
|
5
8
|
require 'gorillib/nil_check_delegate'
|
6
9
|
|
7
10
|
# Pre-declaration of class hierarchy
|
@@ -11,10 +14,12 @@ require 'ironfan/headers'
|
|
11
14
|
require 'ironfan/plugin/base'
|
12
15
|
|
13
16
|
# DSL for cluster descriptions
|
17
|
+
require 'ironfan/cookbook_requirements'
|
14
18
|
require 'ironfan/dsl'
|
15
19
|
require 'ironfan/builder'
|
16
20
|
|
17
21
|
require 'ironfan/dsl/component'
|
22
|
+
require 'ironfan/dsl/security_group'
|
18
23
|
require 'ironfan/dsl/compute'
|
19
24
|
require 'ironfan/dsl/server'
|
20
25
|
require 'ironfan/dsl/facet'
|
@@ -26,6 +31,8 @@ require 'ironfan/dsl/volume'
|
|
26
31
|
|
27
32
|
require 'ironfan/dsl/cloud'
|
28
33
|
require 'ironfan/dsl/ec2'
|
34
|
+
require 'ironfan/dsl/openstack'
|
35
|
+
require 'ironfan/dsl/static'
|
29
36
|
require 'ironfan/dsl/vsphere'
|
30
37
|
require 'ironfan/dsl/rds'
|
31
38
|
|
@@ -48,6 +55,15 @@ require 'ironfan/provider/ec2/elastic_ip'
|
|
48
55
|
require 'ironfan/provider/ec2/elastic_load_balancer'
|
49
56
|
require 'ironfan/provider/ec2/iam_server_certificate'
|
50
57
|
|
58
|
+
require 'ironfan/provider/openstack'
|
59
|
+
require 'ironfan/provider/openstack/machine'
|
60
|
+
require 'ironfan/provider/openstack/keypair'
|
61
|
+
require 'ironfan/provider/openstack/security_group'
|
62
|
+
require 'ironfan/provider/openstack/elastic_ip'
|
63
|
+
|
64
|
+
require 'ironfan/provider/static'
|
65
|
+
require 'ironfan/provider/static/machine'
|
66
|
+
|
51
67
|
require 'ironfan/provider/virtualbox'
|
52
68
|
require 'ironfan/provider/virtualbox/machine'
|
53
69
|
|