dev-lxc 3.2.0 → 3.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,1215 +1,1310 @@
1
- require "dev-lxc/server"
2
- require "mixlib/install"
3
- require "open-uri"
4
-
5
- module DevLXC
6
- class Cluster
7
- attr_reader :config
8
-
9
- def initialize(cluster_config)
10
- FileUtils.mkdir_p('/var/dev-lxc') unless Dir.exist?('/var/dev-lxc')
11
-
12
- @config = Hash.new { |hash, key| hash[key] = {} }
13
- @server_configs = Hash.new
14
-
15
- %w(adhoc analytics automate build-nodes chef-backend chef-server compliance nodes runners supermarket).each do |server_type|
16
- if cluster_config[server_type]
17
- if cluster_config[server_type]["servers"]
18
- cluster_config[server_type]["servers"].each do |server_name, server_config|
19
- server_config ||= Hash.new
20
-
21
- products = server_config['products']
22
- products ||= Hash.new
23
-
24
- enable_build_snapshots = cluster_config[server_type]["enable_build_snapshots"]
25
- enable_build_snapshots = cluster_config["enable_build_snapshots"] if enable_build_snapshots.nil?
26
- enable_build_snapshots = server_config["enable_build_snapshots"] if server_config.key?("enable_build_snapshots")
27
- enable_build_snapshots = true if enable_build_snapshots.nil?
28
-
29
- memory_per_server = cluster_config[server_type]["memory_per_server"]
30
- memory_per_server ||= cluster_config["memory_per_server"]
31
- memory_per_server = server_config["memory_per_server"] if server_config["memory_per_server"]
32
-
33
- mounts = ["/var/dev-lxc var/dev-lxc"]
34
- if cluster_config[server_type]["mounts"]
35
- mounts.concat(cluster_config[server_type]["mounts"])
36
- elsif cluster_config["mounts"]
37
- mounts.concat(cluster_config["mounts"])
38
- end
39
- mounts = ["/var/dev-lxc var/dev-lxc"] + server_config["mounts"] if server_config["mounts"]
40
-
41
- ssh_keys = cluster_config[server_type]["ssh-keys"]
42
- ssh_keys ||= cluster_config["ssh-keys"]
43
- ssh_keys = server_config["ssh-keys"] if server_config["ssh-keys"]
44
-
45
- base_container_name = cluster_config[server_type]["base_container"]
46
- base_container_name ||= cluster_config["base_container"]
47
- base_container_name = server_config["base_container"] if server_config["base_container"]
48
-
49
- @server_configs[server_name] = {
50
- server_type: server_type,
51
- products: products,
52
- ipaddress: server_config['ipaddress'],
53
- additional_fqdn: nil,
54
- enable_build_snapshots: enable_build_snapshots,
55
- first_run: false,
56
- memory_per_server: memory_per_server,
57
- mounts: mounts,
58
- ssh_keys: ssh_keys,
59
- base_container_name: base_container_name
60
- }
61
- # gather configuration from only the first "automate", "compliance" or "supermarket" server
62
- break if %w(automate compliance supermarket).include?(server_type)
63
- end
64
- end
65
-
66
- case server_type
67
- when "analytics"
68
- @config[server_type][:topology] = cluster_config[server_type]["topology"]
69
- @config[server_type][:topology] ||= 'standalone'
70
- @config[server_type][:fqdn] = cluster_config[server_type]["analytics_fqdn"]
71
- @config[server_type][:frontends] = Array.new
72
-
73
- if cluster_config[server_type]["servers"]
74
- cluster_config[server_type]["servers"].each do |server_name, server_config|
75
- server_config ||= Hash.new
76
- additional_fqdn = nil
77
- case @config[server_type][:topology]
78
- when 'standalone'
79
- @config[server_type][:bootstrap_backend] = server_name if server_config["role"].nil?
80
- @config[server_type][:fqdn] ||= @config[server_type][:bootstrap_backend]
81
- when 'tier'
82
- @config[server_type][:bootstrap_backend] = server_name if server_config["role"] == "backend" && server_config["bootstrap"] == true
83
- if server_config["role"] == "frontend"
84
- additional_fqdn = @config[server_type][:fqdn]
85
- @config[server_type][:frontends] << server_name
86
- end
87
- end
88
- @server_configs[server_name].merge!({
89
- additional_fqdn: additional_fqdn
90
- })
91
- end
92
- end
93
- when "chef-backend"
94
- @config[server_type][:fqdn] = cluster_config[server_type]["api_fqdn"]
95
- @config[server_type][:users] = cluster_config[server_type]["users"]
96
- @config[server_type][:users] ||= Array.new
97
- @config[server_type][:orgs] = cluster_config[server_type]["orgs"]
98
- @config[server_type][:orgs] ||= Hash.new
99
- @config[server_type][:backends] = Array.new
100
- @config[server_type][:frontends] = Array.new
101
-
102
- servers = cluster_config[server_type]["servers"]
103
- if servers
104
- @config[server_type][:leader_backend] = servers.select { |s,sc| sc['role'] == 'backend' && sc['leader'] == true }.keys.first
105
- @config[server_type][:bootstrap_frontend] = servers.select { |s,sc| sc['role'] == 'frontend' && sc['bootstrap'] == true }.keys.first
106
- @config[server_type][:backends] << @config[server_type][:leader_backend]
107
- @config[server_type][:frontends] << @config[server_type][:bootstrap_frontend]
108
- servers.each do |server_name, server_config|
109
- server_config ||= Hash.new
110
- additional_fqdn = nil
111
- case server_config["role"]
112
- when "backend"
113
- @config[server_type][:backends] << server_name unless server_name == @config[server_type][:leader_backend]
114
- when "frontend"
115
- additional_fqdn = @config[server_type][:fqdn]
116
- @config[server_type][:frontends] << server_name unless server_name == @config[server_type][:bootstrap_frontend]
117
- end
118
- @server_configs[server_name].merge!({
119
- additional_fqdn: additional_fqdn,
120
- chef_server_type: 'chef-server'
121
- })
122
- end
123
- end
124
- when "chef-server"
125
- @config[server_type][:topology] = cluster_config[server_type]["topology"]
126
- @config[server_type][:topology] ||= 'standalone'
127
- @config[server_type][:fqdn] = cluster_config[server_type]["api_fqdn"]
128
- @config[server_type][:users] = cluster_config[server_type]["users"]
129
- @config[server_type][:users] ||= Array.new
130
- @config[server_type][:orgs] = cluster_config[server_type]["orgs"]
131
- @config[server_type][:orgs] ||= Hash.new
132
- @config[server_type][:frontends] = Array.new
133
-
134
- if cluster_config[server_type]["servers"]
135
- cluster_config[server_type]["servers"].each do |server_name, server_config|
136
- server_config ||= Hash.new
137
- additional_fqdn = nil
138
- chef_server_type = 'private-chef' if @server_configs[server_name][:products].has_key?('private-chef')
139
- chef_server_type = 'chef-server' if @server_configs[server_name][:products].has_key?('chef-server')
140
- case @config[server_type][:topology]
141
- when 'standalone'
142
- @config[server_type][:bootstrap_backend] = server_name if server_config["role"].nil?
143
- @config[server_type][:fqdn] ||= @config[server_type][:bootstrap_backend]
144
- when 'tier'
145
- @config[server_type][:bootstrap_backend] = server_name if server_config["role"] == "backend" && server_config["bootstrap"] == true
146
- if server_config["role"] == "frontend"
147
- additional_fqdn = @config[server_type][:fqdn]
148
- @config[server_type][:frontends] << server_name
149
- end
150
- end
151
- @server_configs[server_name].merge!({
152
- additional_fqdn: additional_fqdn,
153
- chef_server_type: chef_server_type
154
- })
155
- end
156
- end
157
- when "supermarket"
158
- unless cluster_config[server_type]["servers"].first.nil?
159
- (server_name, server_config) = cluster_config[server_type]["servers"].first
160
- @config[server_type][:fqdn] = server_name
161
- end
162
- when "compliance"
163
- unless cluster_config[server_type]["servers"].first.nil?
164
- (server_name, server_config) = cluster_config[server_type]["servers"].first
165
- @server_configs[server_name][:admin_user] = cluster_config[server_type]["admin_user"]
166
- end
167
- when "automate"
168
- unless cluster_config[server_type]["servers"].first.nil?
169
- (server_name, server_config) = cluster_config[server_type]["servers"].first
170
- server_config ||= Hash.new
171
- @server_configs[server_name].merge!({
172
- license_path: server_config['license_path'],
173
- chef_org: server_config['chef_org'],
174
- enterprise_name: server_config['enterprise_name']
175
- })
176
- end
177
- when "nodes"
178
- chef_server_url = cluster_config[server_type]['chef_server_url']
179
- validation_client_name = cluster_config[server_type]['validation_client_name']
180
- validation_key = cluster_config[server_type]['validation_key']
181
- if cluster_config[server_type]["servers"]
182
- cluster_config[server_type]["servers"].each do |server_name, server_config|
183
- server_config ||= Hash.new
184
- chef_server_url = server_config['chef_server_url'] if server_config['chef_server_url']
185
- validation_client_name = server_config['validation_client_name'] if server_config['validation_client_name']
186
- validation_key = server_config['validation_key'] if server_config['validation_key']
187
- @server_configs[server_name].merge!({
188
- chef_server_url: chef_server_url,
189
- validation_client_name: validation_client_name,
190
- validation_key: validation_key
191
- })
192
- end
193
- end
194
- end
195
- end
196
- end
197
- validate_cluster_config
198
- end
199
-
200
- def validate_cluster_config
201
- base_container_names = Array.new
202
- mounts = Array.new
203
- ssh_keys = Array.new
204
- hostnames = Array.new
205
-
206
- @config.map { |server_type, config| hostnames.push(config[:fqdn]) }
207
-
208
- @server_configs.each do |server_name, server_config|
209
- base_container_names.push(server_config[:base_container_name]).uniq! if server_config[:base_container_name]
210
- mounts.concat(server_config[:mounts]).uniq! if server_config[:mounts]
211
- ssh_keys.concat(server_config[:ssh_keys]).uniq! if server_config[:ssh_keys]
212
- hostnames.push(server_name)
213
- case server_config[:server_type]
214
- when "automate"
215
- if server_config[:license_path] && !File.file?(server_config[:license_path])
216
- puts "ERROR: Automate license #{server_config[:license_path]} does not exist or is not a file."
217
- exit 1
218
- end
219
- when "nodes"
220
- if server_config[:validation_key] && !File.file?(server_config[:validation_key])
221
- puts "ERROR: Validation key #{server_config[:validation_key]} does not exist or is not a file."
222
- exit 1
223
- end
224
- end
225
- end
226
-
227
- unless base_container_names.empty?
228
- base_container_names.each do |base_container_name|
229
- unless ::DevLXC::Container.new(base_container_name).defined?
230
- puts "ERROR: Base container #{base_container_name} does not exist."
231
- exit 1
232
- end
233
- end
234
- end
235
- unless hostnames.empty?
236
- hostnames.each do |hostname|
237
- unless hostname.end_with?(".lxc")
238
- puts "ERROR: Hostname #{hostname} does not end with '.lxc'."
239
- exit 1
240
- end
241
- end
242
- end
243
- unless mounts.empty?
244
- mounts.each do |mount|
245
- unless File.exists?(mount.split.first)
246
- puts "ERROR: Mount source #{mount.split.first} does not exist."
247
- exit 1
248
- end
249
- end
250
- end
251
- unless ssh_keys.empty?
252
- ssh_keys.each do |ssh_key|
253
- unless File.exists?(ssh_key)
254
- puts "ERROR: SSH key #{ssh_key} does not exist."
255
- exit 1
256
- end
257
- end
258
- end
259
- end
260
-
261
- def show_config(include_products=false)
262
- require 'pp'
263
- calculate_required_products(get_sorted_servers, true) if include_products
264
- puts "Cluster config:"
265
- pp @config
266
- puts
267
- puts "Server configs:"
268
- pp @server_configs
269
- end
270
-
271
- def get_server(server_name)
272
- ipaddress = @server_configs[server_name][:ipaddress]
273
- additional_fqdn = @server_configs[server_name][:additional_fqdn]
274
- memory_per_server = @server_configs[server_name][:memory_per_server]
275
- mounts = @server_configs[server_name][:mounts]
276
- ssh_keys = @server_configs[server_name][:ssh_keys]
277
- Server.new(server_name, ipaddress, additional_fqdn, memory_per_server, mounts, ssh_keys)
278
- end
279
-
280
- def get_sorted_servers(server_name_regex=nil)
281
- servers = Array.new
282
-
283
- # the order of this list of server_types matters
284
- # it determines the order in which actions are applied to each server_type
285
- %w(chef-backend chef-server analytics compliance supermarket automate build-nodes runners nodes adhoc).each do |server_type|
286
- unless @config[server_type].empty?
287
- case server_type
288
- when "chef-backend"
289
- @config[server_type][:backends].each do |backend_name|
290
- servers << get_server(backend_name)
291
- end
292
- @config[server_type][:frontends].each do |frontend_name|
293
- servers << get_server(frontend_name)
294
- end
295
- when "analytics", "chef-server"
296
- if @config[server_type][:bootstrap_backend]
297
- server_name = @config[server_type][:bootstrap_backend]
298
- servers << get_server(server_name)
299
- end
300
- @config[server_type][:frontends].each do |frontend_name|
301
- servers << get_server(frontend_name)
302
- end
303
- end
304
- end
305
- if %w(adhoc automate build-nodes compliance nodes runners supermarket).include?(server_type)
306
- server_configs = @server_configs.select { |server_name, server_config| server_config[:server_type] == server_type }
307
- server_configs.each_key { |server_name| servers << get_server(server_name) }
308
- end
309
- end
310
- servers.select { |s| s.name =~ /#{server_name_regex}/ }
311
- end
312
-
313
- def destroy(server_name_regex=nil)
314
- servers = get_sorted_servers(server_name_regex)
315
- servers.reverse_each { |s| s.destroy; puts }
316
- delete_dns_records unless get_sorted_servers.any? { |s| s.container.state != :stopped }
317
- end
318
-
319
- def halt(server_name_regex=nil)
320
- servers = get_sorted_servers(server_name_regex)
321
- servers.reverse_each { |s| s.shutdown; puts }
322
- delete_dns_records unless get_sorted_servers.any? { |s| s.container.state != :stopped }
323
- end
324
-
325
- def delete_dns_records
326
- @server_configs.keys.each { |server_name| DevLXC::search_file_delete_line("/etc/lxc/addn-hosts.conf", /\s#{server_name}/) }
327
- DevLXC::reload_dnsmasq
328
- end
329
-
330
- def up(server_name_regex=nil)
331
- configured_servers = Array.new
332
- servers = get_sorted_servers(server_name_regex)
333
- exit 1 if abort_up(servers)
334
- servers.each do |server|
335
- unless server.container.defined?
336
- clone_from_base_container(server)
337
- @server_configs[server.name][:first_run] = true
338
- end
339
- end
340
- prep_product_cache(servers)
341
- # get_sorted_servers is called again in order to ensure the container objects are initialized properly in case they were just cloned from the base container
342
- servers = get_sorted_servers(server_name_regex)
343
- create_dns_records unless servers.empty?
344
- servers.each do |server|
345
- next if ! @server_configs[server.name][:enable_build_snapshots] && ! @server_configs[server.name][:first_run]
346
- if %w(build-nodes runners).include?(@server_configs[server.name][:server_type])
347
- next if @server_configs[server.name][:required_products]["chefdk"] && @server_configs[server.name][:required_products].length == 1
348
- end
349
- install_products(server) unless @server_configs[server.name][:required_products].empty?
350
- end
351
- servers.each do |server|
352
- if server.snapshot_list.select { |sn| sn[2].to_s.start_with?("dev-lxc build: completed") }.empty?
353
- if server.name == @config["chef-backend"][:bootstrap_frontend]
354
- running_backends = Array.new
355
- @config["chef-backend"][:backends].reverse_each do |server_name|
356
- next unless @server_configs[server_name][:enable_build_snapshots]
357
- backend = get_server(server_name)
358
- if backend.container.defined? && backend.snapshot_list.select { |sn| sn[2].to_s.start_with?("dev-lxc build: backend cluster configured but frontend not bootstrapped") }.empty?
359
- if backend.container.running?
360
- running_backends << backend.name
361
- backend.shutdown
362
- end
363
- backend.snapshot("dev-lxc build: backend cluster configured but frontend not bootstrapped")
364
- snapshot = backend.snapshot_list.select { |sn| sn[2].to_s.start_with?("dev-lxc build: completed") }.first
365
- backend.snapshot_destroy(snapshot.first) if snapshot
366
- end
367
- end
368
- @config["chef-backend"][:backends].each do |server_name|
369
- next unless @server_configs[server_name][:enable_build_snapshots]
370
- if running_backends.include?(server_name)
371
- get_server(server_name).start
372
- configured_servers << server_name unless configured_servers.include?(server_name)
373
- end
374
- end
375
- end
376
- if @server_configs[server.name][:enable_build_snapshots] || @server_configs[server.name][:first_run]
377
- configure_products(server)
378
- configured_servers << server.name
379
- end
380
- end
381
- if server.container.running?
382
- puts "Container '#{server.name}' is already running"
383
- puts
384
- else
385
- server.start
386
- end
387
- end
388
- configured_servers.reverse_each do |server_name|
389
- next unless @server_configs[server_name][:enable_build_snapshots]
390
- server = get_server(server_name)
391
- server.shutdown if server.container.running?
392
- server.snapshot("dev-lxc build: completed")
393
- end
394
- configured_servers.each do |server_name|
395
- next unless @server_configs[server_name][:enable_build_snapshots]
396
- server = get_server(server_name)
397
- server.start if server.container.defined?
398
- end
399
- end
400
-
401
- def abort_up(servers)
402
- abort_up = false
403
- servers.each do |server|
404
- next if server.container.defined? && !server.snapshot_list.select { |sn| sn[2].to_s.start_with?("dev-lxc build: completed") }.empty?
405
- next if ! @server_configs[server.name][:enable_build_snapshots] && ! @server_configs[server.name][:first_run]
406
- if @server_configs[server.name][:server_type] == 'compliance' && @config["chef-server"][:topology] == "standalone"
407
- if @config['chef-server'][:bootstrap_backend].nil?
408
- puts "ERROR: '#{server.name}' requires a Chef Server bootstrap backend to be configured first."
409
- abort_up = true
410
- elsif !get_server(@config['chef-server'][:bootstrap_backend]).container.running? && servers.select { |s| s.name == @config['chef-server'][:bootstrap_backend] }.empty?
411
- puts "ERROR: '#{server.name}' requires '#{@config['chef-server'][:bootstrap_backend]}' to be running first."
412
- abort_up = true
413
- end
414
- end
415
- if (@config['chef-server'][:frontends] && @config['chef-server'][:frontends].include?(server.name)) || server.name == @config['analytics'][:bootstrap_backend]
416
- if @config['chef-server'][:bootstrap_backend].nil?
417
- puts "ERROR: '#{server.name}' requires a Chef Server bootstrap backend to be configured first."
418
- abort_up = true
419
- elsif !get_server(@config['chef-server'][:bootstrap_backend]).container.defined? && servers.select { |s| s.name == @config['chef-server'][:bootstrap_backend] }.empty?
420
- puts "ERROR: '#{server.name}' requires '#{@config['chef-server'][:bootstrap_backend]}' to be configured first."
421
- abort_up = true
422
- end
423
- end
424
- if @config['chef-server'][:bootstrap_backend] && @server_configs[server.name][:server_type] == 'supermarket'
425
- if !get_server(@config['chef-server'][:bootstrap_backend]).container.defined? && servers.select { |s| s.name == @config['chef-server'][:bootstrap_backend] }.empty?
426
- puts "ERROR: '#{server.name}' requires '#{@config['chef-server'][:bootstrap_backend]}' to be configured first."
427
- abort_up = true
428
- end
429
- end
430
- if @config['analytics'][:frontends] && @config['analytics'][:frontends].include?(server.name)
431
- if @config['analytics'][:bootstrap_backend].nil?
432
- puts "ERROR: '#{server.name}' requires an Analytics Server bootstrap backend to be configured first."
433
- abort_up = true
434
- elsif !get_server(@config['analytics'][:bootstrap_backend]).container.defined? && servers.select { |s| s.name == @config['analytics'][:bootstrap_backend] }.empty?
435
- puts "ERROR: '#{server.name}' requires '#{@config['analytics'][:bootstrap_backend]}' to be configured first."
436
- abort_up = true
437
- end
438
- end
439
- if @config['chef-backend'][:frontends] && @config['chef-backend'][:frontends].include?(server.name) && server.name != @config['chef-backend'][:bootstrap_frontend]
440
- if @config['chef-backend'][:bootstrap_frontend].nil?
441
- puts "ERROR: '#{server.name}' requires a Chef Server bootstrap frontend to be configured first."
442
- abort_up = true
443
- elsif !get_server(@config['chef-backend'][:bootstrap_frontend]).container.defined? && servers.select { |s| s.name == @config['chef-backend'][:bootstrap_frontend] }.empty?
444
- puts "ERROR: '#{server.name}' requires '#{@config['chef-backend'][:bootstrap_frontend]}' to be configured first."
445
- abort_up = true
446
- end
447
- end
448
- if server.name == @config['chef-backend'][:bootstrap_frontend]
449
- if (@config['chef-backend'][:backends].select { |s| get_server(s).container.running? }.length + servers.select { |s| @config['chef-backend'][:backends].include?(s.name) }.length) < 2
450
- puts "ERROR: '#{server.name}' requires at least two nodes in the backend cluster to be running first."
451
- abort_up = true
452
- end
453
- end
454
- if @config['chef-backend'][:backends] && @config['chef-backend'][:backends].include?(server.name) && server.name != @config['chef-backend'][:leader_backend]
455
- if !get_server(@config['chef-backend'][:leader_backend]).container.running? && servers.select { |s| s.name == @config['chef-backend'][:leader_backend] }.empty?
456
- puts "ERROR: '#{server.name}' requires '#{@config['chef-backend'][:leader_backend]}' to be running first."
457
- abort_up = true
458
- end
459
- end
460
- if @server_configs[server.name][:server_type] == 'nodes'
461
- if @server_configs[server.name][:chef_server_url] && @server_configs[server.name][:validation_client_name] && @server_configs[server.name][:validation_key].nil?
462
- if @config['chef-server'][:bootstrap_backend] && !get_server(@config['chef-server'][:bootstrap_backend]).container.defined? && servers.select { |s| s.name == @config['chef-server'][:bootstrap_backend] }.empty?
463
- puts "ERROR: '#{server.name}' requires '#{@config['chef-server'][:bootstrap_backend]}' to be configured first."
464
- abort_up = true
465
- elsif @config['chef-backend'][:bootstrap_frontend] && !get_server(@config['chef-backend'][:bootstrap_frontend]).container.defined? && servers.select { |s| s.name == @config['chef-backend'][:bootstrap_frontend] }.empty?
466
- puts "ERROR: '#{server.name}' requires '#{@config['chef-backend'][:bootstrap_frontend]}' to be configured first."
467
- abort_up = true
468
- end
469
- end
470
- end
471
- if @server_configs[server.name][:server_type] == 'automate'
472
- if @config['chef-server'][:bootstrap_backend].nil?
473
- puts "ERROR: '#{server.name}' requires a Chef Server bootstrap backend to be configured first."
474
- abort_up = true
475
- elsif !get_server(@config['chef-server'][:bootstrap_backend]).container.defined? && servers.select { |s| s.name == @config['chef-server'][:bootstrap_backend] }.empty?
476
- puts "ERROR: '#{server.name}' requires '#{@config['chef-server'][:bootstrap_backend]}' to be configured first."
477
- abort_up = true
478
- end
479
- end
480
- if %w(build-nodes runners).include?(@server_configs[server.name][:server_type])
481
- if @config['chef-server'][:bootstrap_backend].nil?
482
- puts "ERROR: '#{server.name}' requires a Chef Server bootstrap backend to be configured first."
483
- abort_up = true
484
- elsif !get_server(@config['chef-server'][:bootstrap_backend]).container.running? && servers.select { |s| s.name == @config['chef-server'][:bootstrap_backend] }.empty?
485
- puts "ERROR: '#{server.name}' requires '#{@config['chef-server'][:bootstrap_backend]}' to be running first."
486
- abort_up = true
487
- end
488
- if @config['chef-server'][:topology] == 'tier'
489
- if @config[server_type][:frontends].empty?
490
- puts "ERROR: '#{server.name}' requires at least one Chef Server frontend to be configured first."
491
- abort_up = true
492
- elsif (@config['chef-server'][:frontends].select { |s| get_server(s).container.running? }.length + servers.select { |s| @config['chef-server'][:frontends].include?(s.name) }.length) < 1
493
- puts "ERROR: '#{server.name}' requires at least one Chef Server frontend to be running first."
494
- abort_up = true
495
- end
496
- end
497
- automate_server_name = @server_configs.select {|name, config| config[:server_type] == 'automate'}.keys.first
498
- if automate_server_name
499
- if !get_server(automate_server_name).container.running? && servers.select { |s| s.name == automate_server_name }.empty?
500
- puts "ERROR: '#{server.name}' requires '#{automate_server_name}' to be running first."
501
- abort_up = true
502
- end
503
- else
504
- puts "ERROR: '#{server.name}' requires an Automate Server to be configured first."
505
- abort_up = true
506
- end
507
- end
508
- end
509
- return abort_up
510
- end
511
-
512
- def create_dns_records
513
- get_sorted_servers.each do |server|
514
- ipaddress = server.container.ip_addresses.first
515
- ipaddress ||= @server_configs[server.name][:ipaddress]
516
- next unless ipaddress
517
- additional_fqdn = @server_configs[server.name][:additional_fqdn]
518
- dns_record = "#{ipaddress} #{server.name}"
519
- dns_record += " #{additional_fqdn}\n" if additional_fqdn
520
- DevLXC::search_file_delete_line("/etc/lxc/addn-hosts.conf", /\s#{server.name}/)
521
- DevLXC::append_line_to_file("/etc/lxc/addn-hosts.conf", dns_record)
522
- end
523
- DevLXC::reload_dnsmasq
524
- end
525
-
526
- def clone_from_base_container(server)
527
- server_type = @server_configs[server.name][:server_type]
528
- base_container = DevLXC::Container.new(@server_configs[server.name][:base_container_name])
529
- puts "Cloning base container '#{base_container.name}' into container '#{server.name}'"
530
- base_container.clone(server.name, {:flags => LXC::LXC_CLONE_SNAPSHOT})
531
- server.container.load_config
532
- puts "Deleting SSH Server Host Keys"
533
- FileUtils.rm_f(Dir.glob("#{server.container.config_item('lxc.rootfs')}/etc/ssh/ssh_host*_key*"))
534
- end
535
-
536
- def get_product_download_info(server, product_name, product_options)
537
- server_type = @server_configs[server.name][:server_type]
538
- base_container = DevLXC::Container.new(@server_configs[server.name][:base_container_name])
539
- mixlib_install_platform_detection_path = "#{base_container.config_item('lxc.rootfs')}/mixlib-install-platform-detection"
540
- IO.write(mixlib_install_platform_detection_path, Mixlib::Install::Generator::Bourne.detect_platform_sh)
541
- platform_results = `chroot #{base_container.config_item('lxc.rootfs')} bash mixlib-install-platform-detection`
542
- File.unlink(mixlib_install_platform_detection_path)
543
- if platform_results.empty?
544
- puts "ERROR: Unable to detect the platform of container '#{base_container.name}'"
545
- exit 1
546
- end
547
- (platform, platform_version, architecture) = platform_results.split
548
- product_version = product_options['version'] if product_options
549
- product_version ||= 'latest'
550
- channel = product_options['channel'] if product_options
551
- channel ||= 'stable'
552
- channel = channel.to_sym
553
- options = {
554
- product_name: product_name,
555
- product_version: product_version,
556
- channel: channel,
557
- platform: platform,
558
- platform_version: platform_version,
559
- architecture: architecture
560
- }
561
- artifact = Mixlib::Install.new(options).artifact_info
562
- if artifact.class != Mixlib::Install::ArtifactInfo
563
- puts "ERROR: Unable to find download URL for the following product"
564
- puts JSON.pretty_generate(options)
565
- exit 1
566
- end
567
- [artifact.url, artifact.sha256]
568
- end
569
-
570
- def calculate_required_products(servers, force=false)
571
- all_required_products = Hash.new
572
- servers.each do |server|
573
- products = @server_configs[server.name][:products]
574
- @server_configs[server.name][:required_products] = Hash.new
575
- if !force && !server.snapshot_list.select { |sn| sn[2].to_s.start_with?("dev-lxc build: products installed") }.empty?
576
- # Skipping product cache preparation for container because it has a 'products installed' snapshot
577
- next
578
- elsif !force && !server.snapshot_list.select { |sn| sn[2].to_s.start_with?("dev-lxc build: completed") }.empty?
579
- # Skipping product cache preparation for container because it has a 'build: completed' snapshot
580
- next
581
- elsif ! @server_configs[server.name][:enable_build_snapshots] && ! @server_configs[server.name][:first_run]
582
- # Skipping product cache preparation for container because it build snapshots are disabled and this is not the container's first run
583
- next
584
- end
585
- products.each do |product_name, product_options|
586
- if product_options && product_options['package_source']
587
- package_source = product_options['package_source']
588
- all_required_products[package_source] = [product_name, nil]
589
- @server_configs[server.name][:required_products][product_name] = package_source
590
- else
591
- package_source, package_sha256 = get_product_download_info(server, product_name, product_options)
592
- all_required_products[package_source] = [product_name, package_sha256]
593
- product_cache_path = "/var/dev-lxc/cache/chef-products/#{product_name}/#{File.basename(package_source)}"
594
- @server_configs[server.name][:required_products][product_name] = product_cache_path
595
- end
596
- end
597
- end
598
- all_required_products
599
- end
600
-
601
- def prep_product_cache(servers, force=false)
602
- all_required_products = calculate_required_products(servers, force)
603
- all_required_products.each do |package_source, v|
604
- product_name, package_sha256 = v
605
- if package_source.start_with?('http')
606
- product_cache_path = "/var/dev-lxc/cache/chef-products/#{product_name}/#{File.basename(package_source)}"
607
- if !File.exist?(product_cache_path)
608
- FileUtils.mkdir_p(File.dirname(product_cache_path)) unless Dir.exist?(File.dirname(product_cache_path))
609
- puts "Downloading #{package_source} to #{product_cache_path}"
610
- open(package_source) { |url| File.open(product_cache_path, 'wb') { |f| f.write(url.read) } }
611
- end
612
- if package_sha256 != Digest::SHA256.file(product_cache_path).hexdigest
613
- puts "ERROR: Incorrect SHA256 for #{product_cache_path}"
614
- exit 1
615
- end
616
- elsif !File.exist?(package_source)
617
- puts "ERROR: Package source #{package_source} does not exist."
618
- exit 1
619
- end
620
- end
621
- end
622
-
623
- def install_products(server)
624
- if !server.snapshot_list.select { |sn| sn[2].to_s.start_with?("dev-lxc build: products installed") }.empty?
625
- puts "Skipping product installation for container '#{server.name}' because it already has a 'products installed' snapshot"
626
- return
627
- elsif !server.snapshot_list.select { |sn| sn[2].to_s.start_with?("dev-lxc build: completed") }.empty?
628
- puts "Skipping product installation for container '#{server.name}' because it already has a 'build: completed' snapshot"
629
- return
630
- end
631
- if server.container.running?
632
- server_was_running = true
633
- else
634
- server_was_running = false
635
- server.start
636
- end
637
- @server_configs[server.name][:required_products].each do |product_name, package_source|
638
- next if %w(build-nodes runners).include?(@server_configs[server.name][:server_type]) && product_name == "chefdk"
639
- server.install_package(package_source)
640
- end
641
- if @server_configs[server.name][:enable_build_snapshots]
642
- server.shutdown
643
- server.snapshot("dev-lxc build: products installed")
644
- server.start if server_was_running
645
- end
646
- end
647
-
648
- def configure_products(server)
649
- puts "Configuring container '#{server.name}'"
650
- server.start
651
- installed_products = @server_configs[server.name][:products].keys if @server_configs[server.name][:products]
652
- installed_products ||= Array.new
653
- server_type = @server_configs[server.name][:server_type]
654
- dot_chef_path = "/root/chef-repo/.chef"
655
- case server_type
656
- when 'adhoc'
657
- # Allow adhoc servers time to generate SSH Server Host Keys
658
- sleep 5
659
- when 'analytics'
660
- configure_analytics(server) if installed_products.include?('analytics')
661
- when 'build-nodes'
662
- sleep 5 # give time for DNS resolution to be available
663
- configure_build_node(server)
664
- when 'runners'
665
- sleep 5 # give time for DNS resolution to be available
666
- configure_runner(server)
667
- when 'chef-backend'
668
- configure_chef_backend(server) if installed_products.include?('chef-backend')
669
- if installed_products.include?('chef-server')
670
- configure_chef_frontend(server)
671
- if server.name == @config['chef-backend'][:bootstrap_frontend]
672
- create_users_orgs_knife_configs(server, dot_chef_path)
673
- end
674
- end
675
- configure_manage(server) if installed_products.include?('manage')
676
- when 'chef-server'
677
- if installed_products.include?('chef-server') || installed_products.include?('private-chef')
678
- configure_chef_server(server)
679
- if server.name == @config['chef-server'][:bootstrap_backend]
680
- create_users_orgs_knife_configs(server, dot_chef_path)
681
-
682
- automate_server_name = @server_configs.select {|name, config| config[:server_type] == 'automate'}.keys.first
683
- if automate_server_name
684
- automate_user = "delivery"
685
- automate_chef_org = @server_configs[automate_server_name][:chef_org]
686
- create_user(server, automate_user, dot_chef_path)
687
- create_org(server, automate_chef_org, dot_chef_path)
688
- org_add_user(server, automate_chef_org, automate_user, true, dot_chef_path)
689
- end
690
- end
691
- end
692
- configure_reporting(server) if installed_products.include?('reporting')
693
- configure_push_jobs_server(server) if installed_products.include?('push-jobs-server')
694
- configure_manage(server) if installed_products.include?('manage')
695
- when 'compliance'
696
- configure_compliance(server) if installed_products.include?('compliance')
697
- when 'automate'
698
- configure_automate(server) if installed_products.include?('automate') || installed_products.include?('delivery')
699
- when 'nodes'
700
- # Allow servers time to generate SSH Server Host Keys
701
- sleep 5
702
- configure_chef_client(server, dot_chef_path) if installed_products.include?('chef') || installed_products.include?('chefdk')
703
- when 'supermarket'
704
- configure_supermarket(server) if installed_products.include?('supermarket')
705
- end
706
- end
707
-
708
- def configure_automate(server)
709
- license_path = @server_configs[server.name][:license_path]
710
- chef_org = @server_configs[server.name][:chef_org]
711
- enterprise_name = @server_configs[server.name][:enterprise_name]
712
- chef_server_url = @config['chef-server'][:fqdn]
713
- supermarket_fqdn = @config['supermarket'][:fqdn]
714
-
715
- FileUtils.cp(license_path, "#{server.container.config_item('lxc.rootfs')}/root/automate.license")
716
-
717
- chef_server = get_server(@config['chef-server'][:bootstrap_backend])
718
- automate_chef_user_key = "#{chef_server.container.config_item('lxc.rootfs')}/root/chef-repo/.chef/delivery.pem"
719
- FileUtils.cp(automate_chef_user_key, "#{server.container.config_item('lxc.rootfs')}/root/automate_chef_user_key.pem")
720
-
721
- setup_cmd = "setup"
722
- setup_cmd += " --license /root/automate.license"
723
- setup_cmd += " --fqdn #{server.name}"
724
- setup_cmd += " --key /root/automate_chef_user_key.pem"
725
- setup_cmd += " --server-url https://#{chef_server_url}/organizations/#{chef_org}"
726
- setup_cmd += " --supermarket-fqdn #{supermarket_fqdn}" if supermarket_fqdn
727
- setup_cmd += " --enterprise #{enterprise_name}"
728
- setup_cmd += " --no-build-node"
729
- setup_cmd += " --no-configure"
730
- server.run_command("delivery-ctl #{setup_cmd}")
731
-
732
- # enable Compliance profiles asset store
733
- DevLXC::append_line_to_file("#{server.container.config_item('lxc.rootfs')}/etc/delivery/delivery.rb", "compliance_profiles['enable'] = true\n")
734
-
735
- server.run_command("delivery-ctl reconfigure")
736
-
737
- # give time for all services to come up completely
738
- sleep 10
739
-
740
- server.run_command("delivery-ctl create-enterprise #{enterprise_name} --ssh-pub-key-file /etc/delivery/builder_key.pub", "#{server.container.config_item('lxc.rootfs')}/etc/delivery/#{enterprise_name}-admin-credentials")
741
- end
742
-
743
- def print_automate_credentials
744
- automate_server_name = @server_configs.select {|name, config| config[:server_type] == 'automate'}.keys.first
745
- if automate_server_name
746
- automate_server = get_server(automate_server_name)
747
- automate_credentials_files = Dir.glob("#{automate_server.container.config_item('lxc.rootfs')}/etc/delivery/*-credentials")
748
- automate_credentials_files.each_with_index do |automate_credentials_file, index|
749
- puts IO.read(automate_credentials_file)
750
- puts if index + 1 < automate_credentials_files.length
751
- end
752
- else
753
- puts "WARNING: An Automate server is not defined."
754
- exit 1
755
- end
756
- end
757
-
758
- def configure_build_node(server)
759
- automate_server_name = @server_configs.select {|name, config| config[:server_type] == 'automate'}.keys.first
760
- if automate_server_name
761
- automate_server = get_server(automate_server_name)
762
- install_build_node_cmd = "install-build-node"
763
- install_build_node_cmd += " --fqdn #{server.name}"
764
- install_build_node_cmd += " --username dev-lxc"
765
- install_build_node_cmd += " --password dev-lxc"
766
- install_build_node_cmd += " --installer #{@server_configs[server.name][:required_products]["chefdk"]}"
767
- install_build_node_cmd += " --overwrite-registration"
768
- automate_server.run_command("delivery-ctl #{install_build_node_cmd}")
769
- end
770
- end
771
-
772
- def configure_runner(server)
773
- automate_server_name = @server_configs.select {|name, config| config[:server_type] == 'automate'}.keys.first
774
- if automate_server_name
775
- automate_server = get_server(automate_server_name)
776
- install_runner_cmd = "install-runner #{server.name} dev-lxc"
777
- install_runner_cmd += " --password dev-lxc"
778
- install_runner_cmd += " --installer #{@server_configs[server.name][:required_products]["chefdk"]}"
779
- install_runner_cmd += " --yes"
780
- automate_server.run_command("delivery-ctl #{install_runner_cmd}")
781
- end
782
- end
783
-
784
- def configure_chef_client(server, dot_chef_path)
785
- puts "Configuring Chef Client in container '#{server.name}'"
786
-
787
- FileUtils.mkdir_p("#{server.container.config_item('lxc.rootfs')}/etc/chef")
788
-
789
- chef_server_url = @server_configs[server.name][:chef_server_url]
790
- validation_client_name = @server_configs[server.name][:validation_client_name]
791
- validation_key = @server_configs[server.name][:validation_key]
792
- if validation_key.nil?
793
- chef_server_name = @config['chef-server'][:bootstrap_backend]
794
- chef_server_name ||= @config['chef-backend'][:bootstrap_frontend]
795
- if chef_server_name
796
- chef_server = get_server(chef_server_name)
797
- if chef_server.container.defined?
798
- validator_pem_files = Dir.glob("#{chef_server.container.config_item('lxc.rootfs')}#{dot_chef_path}/*-validator.pem")
799
- FileUtils.cp(validator_pem_files, "#{server.container.config_item('lxc.rootfs')}/etc/chef/") unless validator_pem_files.empty?
800
- end
801
- end
802
- else
803
- FileUtils.cp(validation_key, "#{server.container.config_item('lxc.rootfs')}/etc/chef/") if File.exists?(validation_key)
804
- end
805
-
806
- client_rb = %Q(# uncomment the following proxy lines to send traffic through mitmproxy
807
- #http_proxy 'http://10.0.3.1:8080'
808
- #https_proxy 'http://10.0.3.1:8080'
809
-
810
- chef_server_url '#{chef_server_url}'
811
- validation_client_name '#{validation_client_name}'
812
- validation_key '/etc/chef/#{validation_client_name}.pem'
813
- ssl_verify_mode :verify_none
814
- )
815
-
816
- automate_server_name = @server_configs.select {|name, config| config[:server_type] == 'automate'}.keys.first
817
- if automate_server_name
818
- client_rb += %Q(
819
- # data_collector.server_url "https://#{automate_server_name}/data-collector/v0/"
820
- # data_collector.token "93a49a4f2482c64126f7b6015e6b0f30284287ee4054ff8807fb63d9cbd1c506"
821
- )
822
- end
823
-
824
- IO.write("#{server.container.config_item('lxc.rootfs')}/etc/chef/client.rb", client_rb)
825
- end
826
-
827
- def configure_chef_backend(server)
828
- FileUtils.mkdir_p("#{server.container.config_item('lxc.rootfs')}/var/opt/chef-backend")
829
- FileUtils.touch("#{server.container.config_item('lxc.rootfs')}/var/opt/chef-backend/.license.accepted")
830
- if server.name == @config['chef-backend'][:leader_backend]
831
- puts "Creating /etc/chef-backend/chef-backend.rb"
832
- FileUtils.mkdir_p("#{server.container.config_item('lxc.rootfs')}/etc/chef-backend")
833
- chef_backend_config = "publish_address '#{@server_configs[server.name][:ipaddress]}'\n"
834
- IO.write("#{server.container.config_item('lxc.rootfs')}/etc/chef-backend/chef-backend.rb", chef_backend_config)
835
- server.run_command("chef-backend-ctl bootstrap --yes")
836
- else
837
- puts "Joining #{server.name} to the chef-backend cluster"
838
- leader_backend = get_server(@config['chef-backend'][:leader_backend])
839
- FileUtils.cp("#{leader_backend.container.config_item('lxc.rootfs')}/etc/chef-backend/chef-backend-secrets.json",
840
- "#{server.container.config_item('lxc.rootfs')}/root/")
841
- server.run_command("chef-backend-ctl join-cluster #{@server_configs[leader_backend.name][:ipaddress]} -p #{@server_configs[server.name][:ipaddress]} -s /root/chef-backend-secrets.json --yes")
842
- end
843
- end
844
-
845
- def configure_chef_frontend(server)
846
- puts "Creating /etc/opscode/chef-server.rb"
847
- FileUtils.mkdir_p("#{server.container.config_item('lxc.rootfs')}/etc/opscode")
848
- leader_backend = get_server(@config['chef-backend'][:leader_backend])
849
- leader_backend.run_command("chef-backend-ctl gen-server-config #{server.name} --filename /tmp/#{server.name}.rb")
850
- FileUtils.cp("#{leader_backend.container.config_item('lxc.rootfs')}/tmp/#{server.name}.rb",
851
- "#{server.container.config_item('lxc.rootfs')}/etc/opscode/chef-server.rb")
852
- unless server.name == @config['chef-backend'][:bootstrap_frontend]
853
- bootstrap_frontend = get_server(@config['chef-backend'][:bootstrap_frontend])
854
- puts "Copying /etc/opscode/private-chef-secrets.json from bootstrap frontend '#{bootstrap_frontend.name}'"
855
- FileUtils.cp("#{bootstrap_frontend.container.config_item('lxc.rootfs')}/etc/opscode/private-chef-secrets.json",
856
- "#{server.container.config_item('lxc.rootfs')}/etc/opscode/")
857
- puts "Copying /etc/opscode/pivotal.pem from bootstrap frontend '#{bootstrap_frontend.name}'"
858
- FileUtils.cp("#{bootstrap_frontend.container.config_item('lxc.rootfs')}/etc/opscode/pivotal.pem",
859
- "#{server.container.config_item('lxc.rootfs')}/etc/opscode/")
860
- end
861
- server.run_command("chef-server-ctl reconfigure")
862
- end
863
-
864
- def configure_chef_server(server)
865
- if @config['chef-server'][:topology] == "standalone" || @config['chef-server'][:bootstrap_backend] == server.name
866
- case @server_configs[server.name][:chef_server_type]
867
- when 'private-chef'
868
- puts "Creating /etc/opscode/private-chef.rb"
869
- FileUtils.mkdir_p("#{server.container.config_item('lxc.rootfs')}/etc/opscode")
870
- IO.write("#{server.container.config_item('lxc.rootfs')}/etc/opscode/private-chef.rb", chef_server_config)
871
- when 'chef-server'
872
- puts "Creating /etc/opscode/chef-server.rb"
873
- FileUtils.mkdir_p("#{server.container.config_item('lxc.rootfs')}/etc/opscode")
874
- IO.write("#{server.container.config_item('lxc.rootfs')}/etc/opscode/chef-server.rb", chef_server_config)
875
- end
876
- elsif @config['chef-server'][:frontends].include?(server.name)
877
- puts "Copying /etc/opscode from bootstrap backend '#{@config['chef-server'][:bootstrap_backend]}'"
878
- FileUtils.cp_r("#{get_server(@config['chef-server'][:bootstrap_backend]).container.config_item('lxc.rootfs')}/etc/opscode",
879
- "#{server.container.config_item('lxc.rootfs')}/etc", preserve: true)
880
- end
881
- server.run_command("#{@server_configs[server.name][:chef_server_type]}-ctl reconfigure")
882
- end
883
-
884
- def configure_reporting(server)
885
- FileUtils.mkdir_p("#{server.container.config_item('lxc.rootfs')}/var/opt/opscode-reporting")
886
- FileUtils.touch("#{server.container.config_item('lxc.rootfs')}/var/opt/opscode-reporting/.license.accepted")
887
- if @config['chef-server'][:frontends].include?(server.name)
888
- puts "Copying /etc/opscode-reporting from bootstrap backend '#{@config['chef-server'][:bootstrap_backend]}'"
889
- FileUtils.cp_r("#{get_server(@config['chef-server'][:bootstrap_backend]).container.config_item('lxc.rootfs')}/etc/opscode-reporting",
890
- "#{server.container.config_item('lxc.rootfs')}/etc", preserve: true)
891
- end
892
- server.run_command("#{@server_configs[server.name][:chef_server_type]}-ctl reconfigure")
893
- server.run_command("opscode-reporting-ctl reconfigure")
894
- end
895
-
896
- def configure_push_jobs_server(server)
897
- server.run_command("opscode-push-jobs-server-ctl reconfigure")
898
- server.run_command("#{@server_configs[server.name][:chef_server_type]}-ctl reconfigure")
899
- end
900
-
901
- def configure_manage(server)
902
- FileUtils.mkdir_p("#{server.container.config_item('lxc.rootfs')}/var/opt/chef-manage")
903
- FileUtils.touch("#{server.container.config_item('lxc.rootfs')}/var/opt/chef-manage/.license.accepted")
904
- if @server_configs[server.name][:chef_server_type] == 'private-chef'
905
- puts "Disabling old opscode-webui in /etc/opscode/private-chef.rb"
906
- DevLXC.search_file_delete_line("#{server.container.config_item('lxc.rootfs')}/etc/opscode/private-chef.rb", /opscode_webui[.enable.]/)
907
- DevLXC.append_line_to_file("#{server.container.config_item('lxc.rootfs')}/etc/opscode/private-chef.rb", "\nopscode_webui['enable'] = false\n")
908
- server.run_command("#{@server_configs[server.name][:chef_server_type]}-ctl reconfigure")
909
- end
910
- server.run_command("opscode-manage-ctl reconfigure")
911
- end
912
-
913
- def configure_analytics(server)
914
- FileUtils.mkdir_p("#{server.container.config_item('lxc.rootfs')}/var/opt/opscode-analytics")
915
- FileUtils.touch("#{server.container.config_item('lxc.rootfs')}/var/opt/opscode-analytics/.license.accepted")
916
- if @config['analytics'][:topology] == "standalone" || @config['analytics'][:bootstrap_backend] == server.name
917
- puts "Copying /etc/opscode-analytics from Chef Server bootstrap backend '#{@config['chef-server'][:bootstrap_backend]}'"
918
- FileUtils.cp_r("#{get_server(@config['chef-server'][:bootstrap_backend]).container.config_item('lxc.rootfs')}/etc/opscode-analytics",
919
- "#{server.container.config_item('lxc.rootfs')}/etc", preserve: true)
920
-
921
- IO.write("#{server.container.config_item('lxc.rootfs')}/etc/opscode-analytics/opscode-analytics.rb", analytics_config)
922
- elsif @config['analytics'][:frontends].include?(server.name)
923
- puts "Copying /etc/opscode-analytics from Analytics bootstrap backend '#{@config['analytics'][:bootstrap_backend]}'"
924
- FileUtils.cp_r("#{get_server(@config['analytics'][:bootstrap_backend]).container.config_item('lxc.rootfs')}/etc/opscode-analytics",
925
- "#{server.container.config_item('lxc.rootfs')}/etc", preserve: true)
926
- end
927
- server.run_command("opscode-analytics-ctl reconfigure")
928
- end
929
-
930
- def configure_compliance(server)
931
- FileUtils.mkdir_p("#{server.container.config_item('lxc.rootfs')}/var/opt/chef-compliance")
932
- FileUtils.touch("#{server.container.config_item('lxc.rootfs')}/var/opt/chef-compliance/.license.accepted")
933
- server.run_command("chef-compliance-ctl reconfigure")
934
- admin_user = @server_configs[server.name][:admin_user]
935
- if admin_user
936
- server.run_command("chef-compliance-ctl user-create #{admin_user} #{admin_user}")
937
- server.run_command("chef-compliance-ctl restart core")
938
- end
939
-
940
- if @config["chef-server"][:topology] == "standalone"
941
- chef_server = get_server(@config['chef-server'][:bootstrap_backend])
942
- FileUtils.mkdir_p("#{chef_server.container.config_item('lxc.rootfs')}/root/integrate-compliance-with-chef-server")
943
- FileUtils.mkdir_p("#{server.container.config_item('lxc.rootfs')}/root/integrate-compliance-with-chef-server")
944
- IO.write("#{server.container.config_item('lxc.rootfs')}/root/integrate-compliance-with-chef-server/prepare-chef-compliance",
945
- "chef-compliance-ctl connect chef-server --non-interactive true --chef-app-id 'compliance_server' --auth-id 'Chef Server' --insecure true --compliance-url 'https://#{server.name}'"
946
- )
947
- server.run_command("bash /root/integrate-compliance-with-chef-server/prepare-chef-compliance", "#{server.container.config_item('lxc.rootfs')}/root/integrate-compliance-with-chef-server/prepare-chef-compliance-output")
948
- server.run_command("chef-compliance-ctl reconfigure")
949
- server.run_command("chef-compliance-ctl restart core")
950
- prepare_chef_compliance_output = IO.read("#{server.container.config_item('lxc.rootfs')}/root/integrate-compliance-with-chef-server/prepare-chef-compliance-output")
951
- delimited_chef_server_command = prepare_chef_compliance_output.match(/\n---\n(.+)\n---/m)
952
- if delimited_chef_server_command
953
- IO.write("#{chef_server.container.config_item('lxc.rootfs')}/root/integrate-compliance-with-chef-server/configure-chef-server", delimited_chef_server_command[1])
954
- chef_server.run_command("bash /root/integrate-compliance-with-chef-server/configure-chef-server", "#{chef_server.container.config_item('lxc.rootfs')}/root/integrate-compliance-with-chef-server/configure-chef-server-output")
955
- end
956
- configure_chef_server_output = IO.read("#{chef_server.container.config_item('lxc.rootfs')}/root/integrate-compliance-with-chef-server/configure-chef-server-output")
957
- compliance_command = configure_chef_server_output.match(/^chef-compliance-ctl .+$/)
958
- if compliance_command
959
- IO.write("#{server.container.config_item('lxc.rootfs')}/root/integrate-compliance-with-chef-server/configure-chef-compliance", compliance_command)
960
- server.run_command("bash /root/integrate-compliance-with-chef-server/configure-chef-compliance")
961
- server.run_command("chef-compliance-ctl reconfigure")
962
- end
963
- end
964
- end
965
-
966
- def configure_supermarket(server)
967
- if @config['chef-server'][:bootstrap_backend] && get_server(@config['chef-server'][:bootstrap_backend]).container.defined?
968
- chef_server_supermarket_config = JSON.parse(IO.read("#{get_server(@config['chef-server'][:bootstrap_backend]).container.config_item('lxc.rootfs')}/etc/opscode/oc-id-applications/supermarket.json"))
969
- supermarket_config = {
970
- 'chef_server_url' => "https://#{@config['chef-server'][:fqdn]}/",
971
- 'chef_oauth2_app_id' => chef_server_supermarket_config['uid'],
972
- 'chef_oauth2_secret' => chef_server_supermarket_config['secret'],
973
- 'chef_oauth2_verify_ssl' => false
974
- }
975
- FileUtils.mkdir_p("#{server.container.config_item('lxc.rootfs')}/etc/supermarket")
976
- IO.write("#{server.container.config_item('lxc.rootfs')}/etc/supermarket/supermarket.json", JSON.pretty_generate(supermarket_config))
977
- end
978
- server.run_command("supermarket-ctl reconfigure")
979
- end
980
-
981
- def create_users_orgs_knife_configs(server, dot_chef_path)
982
- server_type = @server_configs[server.name][:server_type]
983
- # give time for all services to come up completely
984
- sleep 10
985
- if @server_configs[server.name][:chef_server_type] == 'private-chef'
986
- # give more time for all services to come up completely
987
- sleep 50
988
- server.run_command("/opt/opscode/embedded/bin/gem install knife-opc --no-ri --no-rdoc -v 0.3.1")
989
- end
990
- chef_server_dot_chef_path = "#{server.container.config_item('lxc.rootfs')}#{dot_chef_path}"
991
- FileUtils.mkdir_p(chef_server_dot_chef_path)
992
- FileUtils.cp( "#{server.container.config_item('lxc.rootfs')}/etc/opscode/pivotal.pem", chef_server_dot_chef_path )
993
- create_pivotal_knife_config('127.0.0.1', chef_server_dot_chef_path)
994
- create_knife_config('127.0.0.1', chef_server_dot_chef_path)
995
- @config[server_type][:users].each do |username|
996
- create_user(server, username, dot_chef_path)
997
- end
998
- @config[server_type][:orgs].each do |orgname, org_users|
999
- create_org(server, orgname, dot_chef_path)
1000
- if org_users
1001
- if org_users['admins']
1002
- org_users['admins'].each do |username|
1003
- org_add_user(server, orgname, username, true, dot_chef_path)
1004
- end
1005
- end
1006
- if org_users['non-admins']
1007
- org_users['non-admins'].each do |username|
1008
- org_add_user(server, orgname, username, false, dot_chef_path)
1009
- end
1010
- end
1011
- end
1012
- end
1013
- end
1014
-
1015
- def create_pivotal_knife_config(fqdn, dot_chef_path)
1016
- pivotal_rb = %Q(
1017
- current_dir = File.dirname(__FILE__)
1018
-
1019
- chef_server_root "https://#{fqdn}"
1020
- chef_server_url "https://#{fqdn}"
1021
-
1022
- node_name "pivotal"
1023
- client_key "\#{current_dir}/pivotal.pem"
1024
-
1025
- cookbook_path Dir.pwd + "/cookbooks"
1026
- knife[:chef_repo_path] = Dir.pwd
1027
-
1028
- ssl_verify_mode :verify_none
1029
- )
1030
- IO.write("#{dot_chef_path}/pivotal.rb", pivotal_rb)
1031
- end
1032
-
1033
- def create_knife_config(fqdn, dot_chef_path)
1034
- knife_rb = %Q(# uncomment the following proxy lines to send traffic through a proxy
1035
- # mitmproxy uses port 8080
1036
- # tinyproxy uses port 8888
1037
- #http_proxy 'http://127.0.0.1:8080'
1038
- #https_proxy 'http://127.0.0.1:8080'
1039
-
1040
- username = "CHANGEME"
1041
- orgname = "CHANGEME"
1042
-
1043
- if [username, orgname].include?("CHANGEME")
1044
- puts "ERROR: Please set 'username' and 'orgname' to proper values in knife.rb"
1045
- exit!
1046
- end
1047
-
1048
- current_dir = File.dirname(__FILE__)
1049
-
1050
- chef_server_url "https://#{fqdn}/organizations/\#{orgname}"
1051
-
1052
- node_name username
1053
- client_key "\#{current_dir}/\#{username}.pem"
1054
-
1055
- validation_client_name "\#{orgname}-validator"
1056
- validation_key "\#{current_dir}/\#{orgname}-validator.pem"
1057
-
1058
- cookbook_path Dir.pwd + "/cookbooks"
1059
- knife[:chef_repo_path] = Dir.pwd
1060
-
1061
- ssl_verify_mode :verify_none
1062
- )
1063
- IO.write("#{dot_chef_path}/knife.rb", knife_rb)
1064
- end
1065
-
1066
- def create_user(server, username, dot_chef_path)
1067
- create_user_string = "#{username} #{username} #{username} #{username}@noreply.com #{username} --filename #{dot_chef_path}/#{username}.pem"
1068
- case @server_configs[server.name][:chef_server_type]
1069
- when 'private-chef'
1070
- server.run_command("/opt/opscode/embedded/bin/knife opc user create #{create_user_string} -c #{dot_chef_path}/pivotal.rb")
1071
- when 'chef-server'
1072
- server.run_command("chef-server-ctl user-create #{create_user_string}")
1073
- end
1074
- end
1075
-
1076
- def create_org(server, orgname, dot_chef_path)
1077
- create_org_string = "#{orgname} #{orgname} --filename #{dot_chef_path}/#{orgname}-validator.pem"
1078
- case @server_configs[server.name][:chef_server_type]
1079
- when 'private-chef'
1080
- server.run_command("/opt/opscode/embedded/bin/knife opc org create #{create_org_string} -c #{dot_chef_path}/pivotal.rb")
1081
- when 'chef-server'
1082
- server.run_command("chef-server-ctl org-create #{create_org_string}")
1083
- end
1084
- end
1085
-
1086
- def org_add_user(server, orgname, username, admin, dot_chef_path)
1087
- org_add_user_string = "#{orgname} #{username}"
1088
- org_add_user_string += " --admin" if admin
1089
- case @server_configs[server.name][:chef_server_type]
1090
- when 'private-chef'
1091
- server.run_command("/opt/opscode/embedded/bin/knife opc org user add #{org_add_user_string} -c #{dot_chef_path}/pivotal.rb")
1092
- when 'chef-server'
1093
- server.run_command("chef-server-ctl org-user-add #{org_add_user_string}")
1094
- end
1095
- end
1096
-
1097
- def chef_repo(force=false, pivotal=false)
1098
- chef_server_dot_chef_path = "/root/chef-repo/.chef"
1099
- dot_chef_path = ".chef"
1100
-
1101
- if @config['chef-server'][:bootstrap_backend]
1102
- chef_server = get_server(@config['chef-server'][:bootstrap_backend])
1103
- chef_server_fqdn = @config['chef-server'][:fqdn]
1104
- elsif @config['chef-backend'][:bootstrap_frontend]
1105
- chef_server = get_server(@config['chef-backend'][:bootstrap_frontend])
1106
- chef_server_fqdn = @config['chef-backend'][:fqdn]
1107
- else
1108
- puts "ERROR: A Chef Server is not defined in the cluster's config. Please define it first."
1109
- exit 1
1110
- end
1111
- unless chef_server.container.defined?
1112
- puts "ERROR: The '#{chef_server.name}' Chef Server does not exist."
1113
- exit 1
1114
- end
1115
-
1116
- puts "Creating chef-repo with pem files and knife.rb in the current directory"
1117
- FileUtils.mkdir_p(dot_chef_path)
1118
-
1119
- pem_files = Dir.glob("#{chef_server.container.config_item('lxc.rootfs')}#{chef_server_dot_chef_path}/*.pem")
1120
- pem_files.delete_if { |pem_file| pem_file.end_with?("/pivotal.pem") } unless pivotal
1121
- FileUtils.cp(pem_files, dot_chef_path) unless pem_files.empty?
1122
-
1123
- if pivotal
1124
- if File.exists?("#{dot_chef_path}/pivotal.rb") && ! force
1125
- puts "Skipping pivotal.rb because it already exists in `#{dot_chef_path}`"
1126
- else
1127
- create_pivotal_knife_config(chef_server_fqdn, dot_chef_path)
1128
- end
1129
- end
1130
-
1131
- if File.exists?("#{dot_chef_path}/knife.rb") && ! force
1132
- puts "Skipping knife.rb because it already exists in `#{dot_chef_path}`"
1133
- else
1134
- create_knife_config(chef_server_fqdn, dot_chef_path)
1135
- end
1136
- end
1137
-
1138
- def chef_server_config
1139
- chef_server_config = %Q(api_fqdn "#{@config['chef-server'][:fqdn]}"\n)
1140
- if @config['chef-server'][:topology] == 'tier'
1141
- chef_server_config += %Q(
1142
- topology "#{@config['chef-server'][:topology]}"
1143
-
1144
- server "#{@config['chef-server'][:bootstrap_backend]}",
1145
- :ipaddress => "#{@server_configs[@config['chef-server'][:bootstrap_backend]][:ipaddress]}",
1146
- :role => "backend",
1147
- :bootstrap => true
1148
-
1149
- backend_vip "#{@config['chef-server'][:bootstrap_backend]}",
1150
- :ipaddress => "#{@server_configs[@config['chef-server'][:bootstrap_backend]][:ipaddress]}"
1151
- )
1152
- @config['chef-server'][:frontends].each do |frontend_name|
1153
- chef_server_config += %Q(
1154
- server "#{frontend_name}",
1155
- :ipaddress => "#{@server_configs[frontend_name][:ipaddress]}",
1156
- :role => "frontend"
1157
- )
1158
- end
1159
- end
1160
- if @config['analytics'][:fqdn]
1161
- chef_server_config += %Q(
1162
- oc_id['applications'] ||= {}
1163
- oc_id['applications']['analytics'] = {
1164
- 'redirect_uri' => 'https://#{@config['analytics'][:fqdn]}/'
1165
- }
1166
- rabbitmq['vip'] = '#{@config['chef-server'][:bootstrap_backend]}'
1167
- rabbitmq['node_ip_address'] = '0.0.0.0'
1168
- )
1169
- end
1170
- if @config['supermarket'][:fqdn]
1171
- chef_server_config += %Q(
1172
- oc_id['applications'] ||= {}
1173
- oc_id['applications']['supermarket'] = {
1174
- 'redirect_uri' => 'https://#{@config['supermarket'][:fqdn]}/auth/chef_oauth2/callback'
1175
- }
1176
- )
1177
- end
1178
- automate_server_name = @server_configs.select {|name, config| config[:server_type] == 'automate'}.keys.first
1179
- if automate_server_name
1180
- chef_server_config += %Q(
1181
- data_collector['root_url'] = "https://#{automate_server_name}/data-collector/v0/"
1182
- data_collector['token'] = "93a49a4f2482c64126f7b6015e6b0f30284287ee4054ff8807fb63d9cbd1c506"
1183
- profiles['root_url'] = "https://#{automate_server_name}"
1184
- )
1185
- end
1186
- return chef_server_config
1187
- end
1188
-
1189
- def analytics_config
1190
- analytics_config = %Q(analytics_fqdn "#{@config['analytics'][:fqdn]}"
1191
- topology "#{@config['analytics'][:topology]}"
1192
- )
1193
- if @config['analytics'][:topology] == 'tier'
1194
- analytics_config += %Q(
1195
- server "#{@config['analytics'][:bootstrap_backend]}",
1196
- :ipaddress => "#{@server_configs[@config['analytics'][:bootstrap_backend]][:ipaddress]}",
1197
- :role => "backend",
1198
- :bootstrap => true
1199
-
1200
- backend_vip "#{@config['analytics'][:bootstrap_backend]}",
1201
- :ipaddress => "#{@server_configs[@config['analytics'][:bootstrap_backend]][:ipaddress]}"
1202
- )
1203
- @config['analytics'][:frontends].each do |frontend_name|
1204
- analytics_config += %Q(
1205
- server "#{frontend_name}",
1206
- :ipaddress => "#{@server_configs[frontend_name][:ipaddress]}",
1207
- :role => "frontend"
1208
- )
1209
- end
1210
- end
1211
- return analytics_config
1212
- end
1213
-
1214
- end
1215
- end
1
+ require "dev-lxc/server"
2
+ require "mixlib/install"
3
+ require "open-uri"
4
+
5
+ module DevLXC
6
+ class Cluster
7
+ attr_reader :config
8
+
9
+ def initialize(cluster_config)
10
+ FileUtils.mkdir_p('/var/dev-lxc') unless Dir.exist?('/var/dev-lxc')
11
+
12
+ @config = Hash.new { |hash, key| hash[key] = {} }
13
+ @server_configs = Hash.new
14
+
15
+ %w(adhoc analytics automate build-nodes chef-backend chef-server compliance nodes runners supermarket).each do |server_type|
16
+ if cluster_config[server_type]
17
+ if cluster_config[server_type]["servers"]
18
+ cluster_config[server_type]["servers"].each do |server_name, server_config|
19
+ server_config ||= Hash.new
20
+
21
+ products = server_config['products']
22
+ products ||= Hash.new
23
+
24
+ enable_build_snapshots = cluster_config[server_type]["enable_build_snapshots"]
25
+ enable_build_snapshots = cluster_config["enable_build_snapshots"] if enable_build_snapshots.nil?
26
+ enable_build_snapshots = server_config["enable_build_snapshots"] if server_config.key?("enable_build_snapshots")
27
+ enable_build_snapshots = true if enable_build_snapshots.nil?
28
+
29
+ memory_per_server = cluster_config[server_type]["memory_per_server"]
30
+ memory_per_server ||= cluster_config["memory_per_server"]
31
+ memory_per_server = server_config["memory_per_server"] if server_config["memory_per_server"]
32
+
33
+ mounts = ["/var/dev-lxc var/dev-lxc"]
34
+ if cluster_config[server_type]["mounts"]
35
+ mounts.concat(cluster_config[server_type]["mounts"])
36
+ elsif cluster_config["mounts"]
37
+ mounts.concat(cluster_config["mounts"])
38
+ end
39
+ mounts = ["/var/dev-lxc var/dev-lxc"] + server_config["mounts"] if server_config["mounts"]
40
+
41
+ ssh_keys = cluster_config[server_type]["ssh-keys"]
42
+ ssh_keys ||= cluster_config["ssh-keys"]
43
+ ssh_keys = server_config["ssh-keys"] if server_config["ssh-keys"]
44
+
45
+ base_container_name = cluster_config[server_type]["base_container"]
46
+ base_container_name ||= cluster_config["base_container"]
47
+ base_container_name = server_config["base_container"] if server_config["base_container"]
48
+
49
+ @server_configs[server_name] = {
50
+ server_type: server_type,
51
+ products: products,
52
+ ipaddress: server_config['ipaddress'],
53
+ additional_fqdn: nil,
54
+ enable_build_snapshots: enable_build_snapshots,
55
+ first_run: false,
56
+ memory_per_server: memory_per_server,
57
+ mounts: mounts,
58
+ ssh_keys: ssh_keys,
59
+ base_container_name: base_container_name
60
+ }
61
+ # gather configuration from only the first "automate", "compliance" or "supermarket" server
62
+ break if %w(automate compliance supermarket).include?(server_type)
63
+ end
64
+ end
65
+
66
+ case server_type
67
+ when "analytics"
68
+ @config[server_type][:topology] = cluster_config[server_type]["topology"]
69
+ @config[server_type][:topology] ||= 'standalone'
70
+ @config[server_type][:fqdn] = cluster_config[server_type]["analytics_fqdn"]
71
+ @config[server_type][:frontends] = Array.new
72
+
73
+ if cluster_config[server_type]["servers"]
74
+ cluster_config[server_type]["servers"].each do |server_name, server_config|
75
+ server_config ||= Hash.new
76
+ additional_fqdn = nil
77
+ case @config[server_type][:topology]
78
+ when 'standalone'
79
+ @config[server_type][:bootstrap_backend] = server_name if server_config["role"].nil?
80
+ @config[server_type][:fqdn] ||= @config[server_type][:bootstrap_backend]
81
+ when 'tier'
82
+ @config[server_type][:bootstrap_backend] = server_name if server_config["role"] == "backend" && server_config["bootstrap"] == true
83
+ if server_config["role"] == "frontend"
84
+ additional_fqdn = @config[server_type][:fqdn]
85
+ @config[server_type][:frontends] << server_name
86
+ end
87
+ end
88
+ @server_configs[server_name].merge!({
89
+ additional_fqdn: additional_fqdn
90
+ })
91
+ end
92
+ end
93
+ when "chef-backend"
94
+ @config[server_type][:fqdn] = cluster_config[server_type]["api_fqdn"]
95
+ @config[server_type][:users] = cluster_config[server_type]["users"]
96
+ @config[server_type][:users] ||= Array.new
97
+ @config[server_type][:orgs] = cluster_config[server_type]["orgs"]
98
+ @config[server_type][:orgs] ||= Hash.new
99
+ @config[server_type][:backends] = Array.new
100
+ @config[server_type][:frontends] = Array.new
101
+
102
+ servers = cluster_config[server_type]["servers"]
103
+ if servers
104
+ @config[server_type][:leader_backend] = servers.select { |s,sc| sc['role'] == 'backend' && sc['leader'] == true }.keys.first
105
+ @config[server_type][:bootstrap_frontend] = servers.select { |s,sc| sc['role'] == 'frontend' && sc['bootstrap'] == true }.keys.first
106
+ @config[server_type][:backends] << @config[server_type][:leader_backend]
107
+ @config[server_type][:frontends] << @config[server_type][:bootstrap_frontend]
108
+ servers.each do |server_name, server_config|
109
+ server_config ||= Hash.new
110
+ additional_fqdn = nil
111
+ case server_config["role"]
112
+ when "backend"
113
+ @config[server_type][:backends] << server_name unless server_name == @config[server_type][:leader_backend]
114
+ when "frontend"
115
+ additional_fqdn = @config[server_type][:fqdn]
116
+ @config[server_type][:frontends] << server_name unless server_name == @config[server_type][:bootstrap_frontend]
117
+ @server_configs[server_name].merge!({
118
+ chef_server_rb: server_config['chef-server.rb'],
119
+ chef_server_rb_partials: server_config['chef-server.rb_partials']
120
+ })
121
+ end
122
+ @server_configs[server_name].merge!({
123
+ additional_fqdn: additional_fqdn,
124
+ chef_server_type: 'chef-server'
125
+ })
126
+ end
127
+ end
128
+ when "chef-server"
129
+ @config[server_type][:topology] = cluster_config[server_type]["topology"]
130
+ @config[server_type][:topology] ||= 'standalone'
131
+ @config[server_type][:fqdn] = cluster_config[server_type]["api_fqdn"]
132
+ @config[server_type][:users] = cluster_config[server_type]["users"]
133
+ @config[server_type][:users] ||= Array.new
134
+ @config[server_type][:orgs] = cluster_config[server_type]["orgs"]
135
+ @config[server_type][:orgs] ||= Hash.new
136
+ @config[server_type][:frontends] = Array.new
137
+
138
+ if cluster_config[server_type]["servers"]
139
+ cluster_config[server_type]["servers"].each do |server_name, server_config|
140
+ server_config ||= Hash.new
141
+ additional_fqdn = nil
142
+ chef_server_type = 'private-chef' if @server_configs[server_name][:products].has_key?('private-chef')
143
+ chef_server_type = 'chef-server' if @server_configs[server_name][:products].has_key?('chef-server')
144
+ case @config[server_type][:topology]
145
+ when 'standalone'
146
+ @config[server_type][:bootstrap_backend] = server_name if server_config["role"].nil?
147
+ @config[server_type][:fqdn] ||= @config[server_type][:bootstrap_backend]
148
+ when 'tier'
149
+ @config[server_type][:bootstrap_backend] = server_name if server_config["role"] == "backend" && server_config["bootstrap"] == true
150
+ if server_config["role"] == "frontend"
151
+ additional_fqdn = @config[server_type][:fqdn]
152
+ @config[server_type][:frontends] << server_name
153
+ end
154
+ end
155
+ @server_configs[server_name].merge!({
156
+ additional_fqdn: additional_fqdn,
157
+ chef_server_type: chef_server_type,
158
+ chef_server_rb: server_config['chef-server.rb'],
159
+ chef_server_rb_partials: server_config['chef-server.rb_partials']
160
+ })
161
+ end
162
+ end
163
+ when "supermarket"
164
+ unless cluster_config[server_type]["servers"].first.nil?
165
+ (server_name, server_config) = cluster_config[server_type]["servers"].first
166
+ @config[server_type][:fqdn] = server_name
167
+ end
168
+ when "compliance"
169
+ unless cluster_config[server_type]["servers"].first.nil?
170
+ (server_name, server_config) = cluster_config[server_type]["servers"].first
171
+ @server_configs[server_name][:admin_user] = cluster_config[server_type]["admin_user"]
172
+ end
173
+ when "automate"
174
+ unless cluster_config[server_type]["servers"].first.nil?
175
+ (server_name, server_config) = cluster_config[server_type]["servers"].first
176
+ server_config ||= Hash.new
177
+ @server_configs[server_name].merge!({
178
+ license_path: server_config['license_path'],
179
+ chef_org: server_config['chef_org'],
180
+ enterprise_name: server_config['enterprise_name'],
181
+ delivery_rb: server_config['delivery.rb'],
182
+ delivery_rb_partials: server_config['delivery.rb_partials']
183
+ })
184
+ end
185
+ when "nodes"
186
+ chef_server_url = cluster_config[server_type]['chef_server_url']
187
+ validation_client_name = cluster_config[server_type]['validation_client_name']
188
+ validation_key = cluster_config[server_type]['validation_key']
189
+ if cluster_config[server_type]["servers"]
190
+ cluster_config[server_type]["servers"].each do |server_name, server_config|
191
+ server_config ||= Hash.new
192
+ chef_server_url = server_config['chef_server_url'] if server_config['chef_server_url']
193
+ validation_client_name = server_config['validation_client_name'] if server_config['validation_client_name']
194
+ validation_key = server_config['validation_key'] if server_config['validation_key']
195
+ @server_configs[server_name].merge!({
196
+ chef_server_url: chef_server_url,
197
+ validation_client_name: validation_client_name,
198
+ validation_key: validation_key
199
+ })
200
+ end
201
+ end
202
+ end
203
+ end
204
+ end
205
+ validate_cluster_config
206
+ end
207
+
208
+ def validate_cluster_config
209
+ base_container_names = Array.new
210
+ mounts = Array.new
211
+ ssh_keys = Array.new
212
+ hostnames = Array.new
213
+
214
+ @config.map { |server_type, config| hostnames.push(config[:fqdn]) }
215
+
216
+ puts "WARNING: No servers are configured in dev-lxc.yml." if @server_configs.empty?
217
+
218
+ @server_configs.each do |server_name, server_config|
219
+ base_container_names.push(server_config[:base_container_name]).uniq! if server_config[:base_container_name]
220
+ mounts.concat(server_config[:mounts]).uniq! if server_config[:mounts]
221
+ ssh_keys.concat(server_config[:ssh_keys]).uniq! if server_config[:ssh_keys]
222
+ hostnames.push(server_name)
223
+ case server_config[:server_type]
224
+ when "automate"
225
+ if server_config[:license_path] && !File.file?(server_config[:license_path])
226
+ puts "ERROR: Automate license #{server_config[:license_path]} does not exist or is not a file."
227
+ exit 1
228
+ end
229
+ if server_config[:delivery_rb] && !File.file?(server_config[:delivery_rb])
230
+ puts "ERROR: Automate config #{server_config[:delivery_rb]} does not exist or is not a file."
231
+ exit 1
232
+ end
233
+ if server_config[:delivery_rb_partials]
234
+ server_config[:delivery_rb_partials].each do |partial|
235
+ unless File.file?(partial)
236
+ puts "ERROR: Automate config partial #{partial} does not exist or is not a file."
237
+ exit 1
238
+ end
239
+ end
240
+ end
241
+ when "chef-server", "chef-backend"
242
+ if server_config[:chef_server_rb] && !File.file?(server_config[:chef_server_rb])
243
+ puts "ERROR: Chef Server config #{server_config[:chef_server_rb]} does not exist or is not a file."
244
+ exit 1
245
+ end
246
+ if server_config[:chef_server_rb_partials]
247
+ server_config[:chef_server_rb_partials].each do |partial|
248
+ unless File.file?(partial)
249
+ puts "ERROR: Chef Server config partial #{partial} does not exist or is not a file."
250
+ exit 1
251
+ end
252
+ end
253
+ end
254
+ when "nodes"
255
+ if server_config[:validation_key] && !File.file?(server_config[:validation_key])
256
+ puts "ERROR: Validation key #{server_config[:validation_key]} does not exist or is not a file."
257
+ exit 1
258
+ end
259
+ end
260
+ end
261
+
262
+ unless base_container_names.empty?
263
+ base_container_names.each do |base_container_name|
264
+ unless ::DevLXC::Container.new(base_container_name).defined?
265
+ puts "ERROR: Base container #{base_container_name} does not exist."
266
+ exit 1
267
+ end
268
+ end
269
+ end
270
+ unless hostnames.empty?
271
+ hostnames.each do |hostname|
272
+ unless hostname.end_with?(".lxc")
273
+ puts "ERROR: Hostname #{hostname} does not end with '.lxc'."
274
+ exit 1
275
+ end
276
+ end
277
+ end
278
+ unless mounts.empty?
279
+ mounts.each do |mount|
280
+ unless File.exists?(mount.split.first)
281
+ puts "ERROR: Mount source #{mount.split.first} does not exist."
282
+ exit 1
283
+ end
284
+ end
285
+ end
286
+ unless ssh_keys.empty?
287
+ ssh_keys.each do |ssh_key|
288
+ unless File.exists?(ssh_key)
289
+ puts "ERROR: SSH key #{ssh_key} does not exist."
290
+ exit 1
291
+ end
292
+ end
293
+ end
294
+ end
295
+
296
+ def show_config(include_products=false)
297
+ require 'pp'
298
+ calculate_required_products(get_sorted_servers, true) if include_products
299
+ puts "Cluster config:"
300
+ pp @config
301
+ puts
302
+ puts "Server configs:"
303
+ pp @server_configs
304
+ end
305
+
306
+ def get_server(server_name)
307
+ ipaddress = @server_configs[server_name][:ipaddress]
308
+ additional_fqdn = @server_configs[server_name][:additional_fqdn]
309
+ memory_per_server = @server_configs[server_name][:memory_per_server]
310
+ mounts = @server_configs[server_name][:mounts]
311
+ ssh_keys = @server_configs[server_name][:ssh_keys]
312
+ Server.new(server_name, ipaddress, additional_fqdn, memory_per_server, mounts, ssh_keys)
313
+ end
314
+
315
+ def get_sorted_servers(server_name_regex=nil)
316
+ servers = Array.new
317
+
318
+ # the order of this list of server_types matters
319
+ # it determines the order in which actions are applied to each server_type
320
+ %w(chef-backend chef-server analytics compliance supermarket automate build-nodes runners nodes adhoc).each do |server_type|
321
+ unless @config[server_type].empty?
322
+ case server_type
323
+ when "chef-backend"
324
+ @config[server_type][:backends].each do |backend_name|
325
+ servers << get_server(backend_name)
326
+ end
327
+ @config[server_type][:frontends].each do |frontend_name|
328
+ servers << get_server(frontend_name)
329
+ end
330
+ when "analytics", "chef-server"
331
+ if @config[server_type][:bootstrap_backend]
332
+ server_name = @config[server_type][:bootstrap_backend]
333
+ servers << get_server(server_name)
334
+ end
335
+ @config[server_type][:frontends].each do |frontend_name|
336
+ servers << get_server(frontend_name)
337
+ end
338
+ end
339
+ end
340
+ if %w(adhoc automate build-nodes compliance nodes runners supermarket).include?(server_type)
341
+ server_configs = @server_configs.select { |server_name, server_config| server_config[:server_type] == server_type }
342
+ server_configs.each_key { |server_name| servers << get_server(server_name) }
343
+ end
344
+ end
345
+ servers.select { |s| s.name =~ /#{server_name_regex}/ }
346
+ end
347
+
348
+ def destroy(server_name_regex=nil)
349
+ servers = get_sorted_servers(server_name_regex)
350
+ servers.reverse_each { |s| s.destroy; puts }
351
+ delete_dns_records unless get_sorted_servers.any? { |s| s.container.state != :stopped }
352
+ end
353
+
354
+ def halt(server_name_regex=nil)
355
+ servers = get_sorted_servers(server_name_regex)
356
+ servers.reverse_each { |s| s.shutdown; puts }
357
+ delete_dns_records unless get_sorted_servers.any? { |s| s.container.state != :stopped }
358
+ end
359
+
360
+ def delete_dns_records
361
+ @server_configs.keys.each { |server_name| DevLXC::search_file_delete_line("/etc/lxc/addn-hosts.conf", /\s#{server_name}/) }
362
+ DevLXC::reload_dnsmasq
363
+ end
364
+
365
+ def up(server_name_regex=nil)
366
+ configured_servers = Array.new
367
+ servers = get_sorted_servers(server_name_regex)
368
+ exit 1 if abort_up(servers)
369
+ servers.each do |server|
370
+ unless server.container.defined?
371
+ clone_from_base_container(server)
372
+ @server_configs[server.name][:first_run] = true
373
+ end
374
+ end
375
+ prep_product_cache(servers)
376
+ # get_sorted_servers is called again in order to ensure the container objects are initialized properly in case they were just cloned from the base container
377
+ servers = get_sorted_servers(server_name_regex)
378
+ create_dns_records unless servers.empty?
379
+ servers.each do |server|
380
+ next if ! @server_configs[server.name][:enable_build_snapshots] && ! @server_configs[server.name][:first_run]
381
+ if %w(build-nodes runners).include?(@server_configs[server.name][:server_type])
382
+ next if @server_configs[server.name][:required_products]["chefdk"] && @server_configs[server.name][:required_products].length == 1
383
+ end
384
+ install_products(server) unless @server_configs[server.name][:required_products].empty?
385
+ end
386
+ servers.each do |server|
387
+ if server.snapshot_list.select { |sn| sn[2].to_s.start_with?("dev-lxc build: completed") }.empty?
388
+ if server.name == @config["chef-backend"][:bootstrap_frontend]
389
+ running_backends = Array.new
390
+ @config["chef-backend"][:backends].reverse_each do |server_name|
391
+ next unless @server_configs[server_name][:enable_build_snapshots]
392
+ backend = get_server(server_name)
393
+ if backend.container.defined? && backend.snapshot_list.select { |sn| sn[2].to_s.start_with?("dev-lxc build: backend cluster configured but frontend not bootstrapped") }.empty?
394
+ if backend.container.running?
395
+ running_backends << backend.name
396
+ backend.shutdown
397
+ end
398
+ backend.snapshot("dev-lxc build: backend cluster configured but frontend not bootstrapped")
399
+ snapshot = backend.snapshot_list.select { |sn| sn[2].to_s.start_with?("dev-lxc build: completed") }.first
400
+ backend.snapshot_destroy(snapshot.first) if snapshot
401
+ end
402
+ end
403
+ @config["chef-backend"][:backends].each do |server_name|
404
+ next unless @server_configs[server_name][:enable_build_snapshots]
405
+ if running_backends.include?(server_name)
406
+ get_server(server_name).start
407
+ configured_servers << server_name unless configured_servers.include?(server_name)
408
+ end
409
+ end
410
+ end
411
+ if @server_configs[server.name][:enable_build_snapshots] || @server_configs[server.name][:first_run]
412
+ configure_products(server)
413
+ configured_servers << server.name
414
+ end
415
+ end
416
+ if server.container.running?
417
+ puts "Container '#{server.name}' is already running"
418
+ puts
419
+ else
420
+ server.start
421
+ end
422
+ end
423
+ configured_servers.reverse_each do |server_name|
424
+ next unless @server_configs[server_name][:enable_build_snapshots]
425
+ server = get_server(server_name)
426
+ server.shutdown if server.container.running?
427
+ server.snapshot("dev-lxc build: completed")
428
+ end
429
+ configured_servers.each do |server_name|
430
+ next unless @server_configs[server_name][:enable_build_snapshots]
431
+ server = get_server(server_name)
432
+ server.start if server.container.defined?
433
+ end
434
+ end
435
+
436
+ def abort_up(servers)
437
+ abort_up = false
438
+ servers.each do |server|
439
+ next if server.container.defined? && !server.snapshot_list.select { |sn| sn[2].to_s.start_with?("dev-lxc build: completed") }.empty?
440
+ next if ! @server_configs[server.name][:enable_build_snapshots] && ! @server_configs[server.name][:first_run]
441
+ if @server_configs[server.name][:server_type] == 'compliance' && @config["chef-server"][:topology] == "standalone"
442
+ if @config['chef-server'][:bootstrap_backend].nil?
443
+ puts "ERROR: '#{server.name}' requires a Chef Server bootstrap backend to be configured first."
444
+ abort_up = true
445
+ elsif !get_server(@config['chef-server'][:bootstrap_backend]).container.running? && servers.select { |s| s.name == @config['chef-server'][:bootstrap_backend] }.empty?
446
+ puts "ERROR: '#{server.name}' requires '#{@config['chef-server'][:bootstrap_backend]}' to be running first."
447
+ abort_up = true
448
+ end
449
+ end
450
+ if (@config['chef-server'][:frontends] && @config['chef-server'][:frontends].include?(server.name)) || server.name == @config['analytics'][:bootstrap_backend]
451
+ if @config['chef-server'][:bootstrap_backend].nil?
452
+ puts "ERROR: '#{server.name}' requires a Chef Server bootstrap backend to be configured first."
453
+ abort_up = true
454
+ elsif !get_server(@config['chef-server'][:bootstrap_backend]).container.defined? && servers.select { |s| s.name == @config['chef-server'][:bootstrap_backend] }.empty?
455
+ puts "ERROR: '#{server.name}' requires '#{@config['chef-server'][:bootstrap_backend]}' to be configured first."
456
+ abort_up = true
457
+ end
458
+ end
459
+ if @config['chef-server'][:bootstrap_backend] && @server_configs[server.name][:server_type] == 'supermarket'
460
+ if !get_server(@config['chef-server'][:bootstrap_backend]).container.defined? && servers.select { |s| s.name == @config['chef-server'][:bootstrap_backend] }.empty?
461
+ puts "ERROR: '#{server.name}' requires '#{@config['chef-server'][:bootstrap_backend]}' to be configured first."
462
+ abort_up = true
463
+ end
464
+ end
465
+ if @config['analytics'][:frontends] && @config['analytics'][:frontends].include?(server.name)
466
+ if @config['analytics'][:bootstrap_backend].nil?
467
+ puts "ERROR: '#{server.name}' requires an Analytics Server bootstrap backend to be configured first."
468
+ abort_up = true
469
+ elsif !get_server(@config['analytics'][:bootstrap_backend]).container.defined? && servers.select { |s| s.name == @config['analytics'][:bootstrap_backend] }.empty?
470
+ puts "ERROR: '#{server.name}' requires '#{@config['analytics'][:bootstrap_backend]}' to be configured first."
471
+ abort_up = true
472
+ end
473
+ end
474
+ if @config['chef-backend'][:frontends] && @config['chef-backend'][:frontends].include?(server.name) && server.name != @config['chef-backend'][:bootstrap_frontend]
475
+ if @config['chef-backend'][:bootstrap_frontend].nil?
476
+ puts "ERROR: '#{server.name}' requires a Chef Server bootstrap frontend to be configured first."
477
+ abort_up = true
478
+ elsif !get_server(@config['chef-backend'][:bootstrap_frontend]).container.defined? && servers.select { |s| s.name == @config['chef-backend'][:bootstrap_frontend] }.empty?
479
+ puts "ERROR: '#{server.name}' requires '#{@config['chef-backend'][:bootstrap_frontend]}' to be configured first."
480
+ abort_up = true
481
+ end
482
+ end
483
+ if server.name == @config['chef-backend'][:bootstrap_frontend]
484
+ if (@config['chef-backend'][:backends].select { |s| get_server(s).container.running? }.length + servers.select { |s| @config['chef-backend'][:backends].include?(s.name) }.length) < 2
485
+ puts "ERROR: '#{server.name}' requires at least two nodes in the backend cluster to be running first."
486
+ abort_up = true
487
+ end
488
+ end
489
+ if @config['chef-backend'][:backends] && @config['chef-backend'][:backends].include?(server.name) && server.name != @config['chef-backend'][:leader_backend]
490
+ if !get_server(@config['chef-backend'][:leader_backend]).container.running? && servers.select { |s| s.name == @config['chef-backend'][:leader_backend] }.empty?
491
+ puts "ERROR: '#{server.name}' requires '#{@config['chef-backend'][:leader_backend]}' to be running first."
492
+ abort_up = true
493
+ end
494
+ end
495
+ if @server_configs[server.name][:server_type] == 'nodes'
496
+ if @server_configs[server.name][:chef_server_url] && @server_configs[server.name][:validation_client_name] && @server_configs[server.name][:validation_key].nil?
497
+ if @config['chef-server'][:bootstrap_backend] && !get_server(@config['chef-server'][:bootstrap_backend]).container.defined? && servers.select { |s| s.name == @config['chef-server'][:bootstrap_backend] }.empty?
498
+ puts "ERROR: '#{server.name}' requires '#{@config['chef-server'][:bootstrap_backend]}' to be configured first."
499
+ abort_up = true
500
+ elsif @config['chef-backend'][:bootstrap_frontend] && !get_server(@config['chef-backend'][:bootstrap_frontend]).container.defined? && servers.select { |s| s.name == @config['chef-backend'][:bootstrap_frontend] }.empty?
501
+ puts "ERROR: '#{server.name}' requires '#{@config['chef-backend'][:bootstrap_frontend]}' to be configured first."
502
+ abort_up = true
503
+ end
504
+ end
505
+ end
506
+ if @server_configs[server.name][:server_type] == 'automate'
507
+ if @config['chef-server'][:bootstrap_backend].nil?
508
+ puts "ERROR: '#{server.name}' requires a Chef Server bootstrap backend to be configured first."
509
+ abort_up = true
510
+ elsif !get_server(@config['chef-server'][:bootstrap_backend]).container.defined? && servers.select { |s| s.name == @config['chef-server'][:bootstrap_backend] }.empty?
511
+ puts "ERROR: '#{server.name}' requires '#{@config['chef-server'][:bootstrap_backend]}' to be configured first."
512
+ abort_up = true
513
+ end
514
+ end
515
+ if %w(build-nodes runners).include?(@server_configs[server.name][:server_type])
516
+ if @config['chef-server'][:bootstrap_backend].nil?
517
+ puts "ERROR: '#{server.name}' requires a Chef Server bootstrap backend to be configured first."
518
+ abort_up = true
519
+ elsif !get_server(@config['chef-server'][:bootstrap_backend]).container.running? && servers.select { |s| s.name == @config['chef-server'][:bootstrap_backend] }.empty?
520
+ puts "ERROR: '#{server.name}' requires '#{@config['chef-server'][:bootstrap_backend]}' to be running first."
521
+ abort_up = true
522
+ end
523
+ if @config['chef-server'][:topology] == 'tier'
524
+ if @config[server_type][:frontends].empty?
525
+ puts "ERROR: '#{server.name}' requires at least one Chef Server frontend to be configured first."
526
+ abort_up = true
527
+ elsif (@config['chef-server'][:frontends].select { |s| get_server(s).container.running? }.length + servers.select { |s| @config['chef-server'][:frontends].include?(s.name) }.length) < 1
528
+ puts "ERROR: '#{server.name}' requires at least one Chef Server frontend to be running first."
529
+ abort_up = true
530
+ end
531
+ end
532
+ automate_server_name = @server_configs.select {|name, config| config[:server_type] == 'automate'}.keys.first
533
+ if automate_server_name
534
+ if !get_server(automate_server_name).container.running? && servers.select { |s| s.name == automate_server_name }.empty?
535
+ puts "ERROR: '#{server.name}' requires '#{automate_server_name}' to be running first."
536
+ abort_up = true
537
+ end
538
+ else
539
+ puts "ERROR: '#{server.name}' requires an Automate Server to be configured first."
540
+ abort_up = true
541
+ end
542
+ end
543
+ end
544
+ return abort_up
545
+ end
546
+
547
+ def create_dns_records
548
+ get_sorted_servers.each do |server|
549
+ ipaddress = server.container.ip_addresses.first
550
+ ipaddress ||= @server_configs[server.name][:ipaddress]
551
+ next unless ipaddress
552
+ additional_fqdn = @server_configs[server.name][:additional_fqdn]
553
+ dns_record = "#{ipaddress} #{server.name}"
554
+ dns_record += " #{additional_fqdn}\n" if additional_fqdn
555
+ DevLXC::search_file_delete_line("/etc/lxc/addn-hosts.conf", /\s#{server.name}/)
556
+ DevLXC::append_line_to_file("/etc/lxc/addn-hosts.conf", dns_record)
557
+ end
558
+ DevLXC::reload_dnsmasq
559
+ end
560
+
561
+ def clone_from_base_container(server)
562
+ server_type = @server_configs[server.name][:server_type]
563
+ base_container = DevLXC::Container.new(@server_configs[server.name][:base_container_name])
564
+ puts "Cloning base container '#{base_container.name}' into container '#{server.name}'"
565
+ base_container.clone(server.name, {:flags => LXC::LXC_CLONE_SNAPSHOT})
566
+ server.container.load_config
567
+ puts "Deleting SSH Server Host Keys"
568
+ FileUtils.rm_f(Dir.glob("#{server.container.config_item('lxc.rootfs')}/etc/ssh/ssh_host*_key*"))
569
+ end
570
+
571
+ def get_product_download_info(server, product_name, product_options)
572
+ server_type = @server_configs[server.name][:server_type]
573
+ base_container = DevLXC::Container.new(@server_configs[server.name][:base_container_name])
574
+ mixlib_install_platform_detection_path = "#{base_container.config_item('lxc.rootfs')}/mixlib-install-platform-detection"
575
+ IO.write(mixlib_install_platform_detection_path, Mixlib::Install::Generator::Bourne.detect_platform_sh)
576
+ platform_results = `chroot #{base_container.config_item('lxc.rootfs')} bash mixlib-install-platform-detection`
577
+ File.unlink(mixlib_install_platform_detection_path)
578
+ if platform_results.empty?
579
+ puts "ERROR: Unable to detect the platform of container '#{base_container.name}'"
580
+ exit 1
581
+ end
582
+ (platform, platform_version, architecture) = platform_results.split
583
+ product_version = product_options['version'] if product_options
584
+ product_version ||= 'latest'
585
+ channel = product_options['channel'] if product_options
586
+ channel ||= 'stable'
587
+ channel = channel.to_sym
588
+ options = {
589
+ product_name: product_name,
590
+ product_version: product_version,
591
+ channel: channel,
592
+ platform: platform,
593
+ platform_version: platform_version,
594
+ architecture: architecture
595
+ }
596
+ artifact = Mixlib::Install.new(options).artifact_info
597
+ if artifact.class != Mixlib::Install::ArtifactInfo
598
+ puts "ERROR: Unable to find download URL for the following product"
599
+ puts JSON.pretty_generate(options)
600
+ exit 1
601
+ end
602
+ [artifact.url, artifact.sha256]
603
+ end
604
+
605
+ def calculate_required_products(servers, force=false)
606
+ all_required_products = Hash.new
607
+ servers.each do |server|
608
+ products = @server_configs[server.name][:products]
609
+ @server_configs[server.name][:required_products] = Hash.new
610
+ if !force && !server.snapshot_list.select { |sn| sn[2].to_s.start_with?("dev-lxc build: products installed") }.empty?
611
+ # Skipping product cache preparation for container because it has a 'products installed' snapshot
612
+ next
613
+ elsif !force && !server.snapshot_list.select { |sn| sn[2].to_s.start_with?("dev-lxc build: completed") }.empty?
614
+ # Skipping product cache preparation for container because it has a 'build: completed' snapshot
615
+ next
616
+ elsif ! @server_configs[server.name][:enable_build_snapshots] && ! @server_configs[server.name][:first_run]
617
+ # Skipping product cache preparation for container because it build snapshots are disabled and this is not the container's first run
618
+ next
619
+ end
620
+ products.each do |product_name, product_options|
621
+ if product_options && product_options['package_source']
622
+ package_source = product_options['package_source']
623
+ all_required_products[package_source] = [product_name, nil]
624
+ @server_configs[server.name][:required_products][product_name] = package_source
625
+ else
626
+ package_source, package_sha256 = get_product_download_info(server, product_name, product_options)
627
+ all_required_products[package_source] = [product_name, package_sha256]
628
+ product_cache_path = "/var/dev-lxc/cache/chef-products/#{product_name}/#{File.basename(package_source)}"
629
+ @server_configs[server.name][:required_products][product_name] = product_cache_path
630
+ end
631
+ end
632
+ end
633
+ all_required_products
634
+ end
635
+
636
+ def prep_product_cache(servers, force=false)
637
+ all_required_products = calculate_required_products(servers, force)
638
+ all_required_products.each do |package_source, v|
639
+ product_name, package_sha256 = v
640
+ if package_source.start_with?('http')
641
+ product_cache_path = "/var/dev-lxc/cache/chef-products/#{product_name}/#{File.basename(package_source)}"
642
+ if !File.exist?(product_cache_path)
643
+ FileUtils.mkdir_p(File.dirname(product_cache_path)) unless Dir.exist?(File.dirname(product_cache_path))
644
+ puts "Downloading #{package_source} to #{product_cache_path}"
645
+ open(package_source) { |url| File.open(product_cache_path, 'wb') { |f| f.write(url.read) } }
646
+ end
647
+ if package_sha256 != Digest::SHA256.file(product_cache_path).hexdigest
648
+ puts "ERROR: Incorrect SHA256 for #{product_cache_path}"
649
+ exit 1
650
+ end
651
+ elsif !File.exist?(package_source)
652
+ puts "ERROR: Package source #{package_source} does not exist."
653
+ exit 1
654
+ end
655
+ end
656
+ end
657
+
658
+ def install_products(server)
659
+ if !server.snapshot_list.select { |sn| sn[2].to_s.start_with?("dev-lxc build: products installed") }.empty?
660
+ puts "Skipping product installation for container '#{server.name}' because it already has a 'products installed' snapshot"
661
+ return
662
+ elsif !server.snapshot_list.select { |sn| sn[2].to_s.start_with?("dev-lxc build: completed") }.empty?
663
+ puts "Skipping product installation for container '#{server.name}' because it already has a 'build: completed' snapshot"
664
+ return
665
+ end
666
+ if server.container.running?
667
+ server_was_running = true
668
+ else
669
+ server_was_running = false
670
+ server.start
671
+ end
672
+ @server_configs[server.name][:required_products].each do |product_name, package_source|
673
+ next if %w(build-nodes runners).include?(@server_configs[server.name][:server_type]) && product_name == "chefdk"
674
+ server.install_package(package_source)
675
+ end
676
+ if @server_configs[server.name][:enable_build_snapshots]
677
+ server.shutdown
678
+ server.snapshot("dev-lxc build: products installed")
679
+ server.start if server_was_running
680
+ end
681
+ end
682
+
683
+ def configure_products(server)
684
+ puts "Configuring container '#{server.name}'"
685
+ server.start
686
+ installed_products = @server_configs[server.name][:products].keys if @server_configs[server.name][:products]
687
+ installed_products ||= Array.new
688
+ server_type = @server_configs[server.name][:server_type]
689
+ dot_chef_path = "/root/chef-repo/.chef"
690
+ case server_type
691
+ when 'adhoc'
692
+ # Allow adhoc servers time to generate SSH Server Host Keys
693
+ sleep 5
694
+ when 'analytics'
695
+ configure_analytics(server) if installed_products.include?('analytics')
696
+ when 'build-nodes'
697
+ sleep 5 # give time for DNS resolution to be available
698
+ configure_build_node(server)
699
+ when 'runners'
700
+ sleep 5 # give time for DNS resolution to be available
701
+ configure_runner(server)
702
+ when 'chef-backend'
703
+ configure_chef_backend(server) if installed_products.include?('chef-backend')
704
+ if installed_products.include?('chef-server')
705
+ configure_chef_frontend(server)
706
+ if server.name == @config['chef-backend'][:bootstrap_frontend]
707
+ create_users_orgs_knife_configs(server, dot_chef_path)
708
+ end
709
+ end
710
+ configure_manage(server) if installed_products.include?('manage')
711
+ when 'chef-server'
712
+ if installed_products.include?('chef-server') || installed_products.include?('private-chef')
713
+ configure_chef_server(server)
714
+ if server.name == @config['chef-server'][:bootstrap_backend]
715
+ create_users_orgs_knife_configs(server, dot_chef_path)
716
+
717
+ automate_server_name = @server_configs.select {|name, config| config[:server_type] == 'automate'}.keys.first
718
+ if automate_server_name
719
+ automate_user = "delivery"
720
+ automate_chef_org = @server_configs[automate_server_name][:chef_org]
721
+ create_user(server, automate_user, dot_chef_path)
722
+ create_org(server, automate_chef_org, dot_chef_path)
723
+ org_add_user(server, automate_chef_org, automate_user, true, dot_chef_path)
724
+ end
725
+ end
726
+ end
727
+ configure_reporting(server) if installed_products.include?('reporting')
728
+ configure_push_jobs_server(server) if installed_products.include?('push-jobs-server')
729
+ configure_manage(server) if installed_products.include?('manage')
730
+ when 'compliance'
731
+ configure_compliance(server) if installed_products.include?('compliance')
732
+ when 'automate'
733
+ configure_automate(server) if installed_products.include?('automate') || installed_products.include?('delivery')
734
+ when 'nodes'
735
+ # Allow servers time to generate SSH Server Host Keys
736
+ sleep 5
737
+ configure_chef_client(server, dot_chef_path) if installed_products.include?('chef') || installed_products.include?('chefdk')
738
+ when 'supermarket'
739
+ configure_supermarket(server) if installed_products.include?('supermarket')
740
+ end
741
+ end
742
+
743
+ def configure_automate(server)
744
+ license_path = @server_configs[server.name][:license_path]
745
+ chef_org = @server_configs[server.name][:chef_org]
746
+ enterprise_name = @server_configs[server.name][:enterprise_name]
747
+ chef_server_url = @config['chef-server'][:fqdn]
748
+ supermarket_fqdn = @config['supermarket'][:fqdn]
749
+
750
+ FileUtils.cp(license_path, "#{server.container.config_item('lxc.rootfs')}/root/automate.license")
751
+
752
+ chef_server = get_server(@config['chef-server'][:bootstrap_backend])
753
+ automate_chef_user_key = "#{chef_server.container.config_item('lxc.rootfs')}/root/chef-repo/.chef/delivery.pem"
754
+ FileUtils.cp(automate_chef_user_key, "#{server.container.config_item('lxc.rootfs')}/root/automate_chef_user_key.pem")
755
+
756
+ setup_cmd = "setup"
757
+ setup_cmd += " --license /root/automate.license"
758
+ setup_cmd += " --fqdn #{server.name}"
759
+ setup_cmd += " --key /root/automate_chef_user_key.pem"
760
+ setup_cmd += " --server-url https://#{chef_server_url}/organizations/#{chef_org}"
761
+ setup_cmd += " --supermarket-fqdn #{supermarket_fqdn}" if supermarket_fqdn
762
+ setup_cmd += " --enterprise #{enterprise_name}"
763
+ setup_cmd += " --no-build-node"
764
+ setup_cmd += " --no-configure"
765
+ server.run_command("delivery-ctl #{setup_cmd}")
766
+
767
+ if @server_configs[server.name][:delivery_rb]
768
+ puts "Copying #{@server_configs[server.name][:delivery_rb]} to /etc/delivery/delivery.rb"
769
+ FileUtils.cp(@server_configs[server.name][:delivery_rb], "#{server.container.config_item('lxc.rootfs')}/etc/delivery/delivery.rb")
770
+ else
771
+ # enable Compliance profiles asset store
772
+ DevLXC::append_line_to_file("#{server.container.config_item('lxc.rootfs')}/etc/delivery/delivery.rb", "compliance_profiles['enable'] = true\n")
773
+ end
774
+ if @server_configs[server.name][:delivery_rb_partials]
775
+ @server_configs[server.name][:delivery_rb_partials].each do |partial|
776
+ puts "Appending #{partial} to /etc/delivery/delivery.rb"
777
+ partial_content = IO.read(partial)
778
+ IO.write("#{server.container.config_item('lxc.rootfs')}/etc/delivery/delivery.rb", partial_content, mode: 'a')
779
+ end
780
+ end
781
+
782
+ server.run_command("delivery-ctl reconfigure")
783
+
784
+ # give time for all services to come up completely
785
+ sleep 10
786
+
787
+ server.run_command("delivery-ctl create-enterprise #{enterprise_name} --ssh-pub-key-file /etc/delivery/builder_key.pub", "#{server.container.config_item('lxc.rootfs')}/etc/delivery/#{enterprise_name}-admin-credentials")
788
+ end
789
+
790
+ def print_automate_credentials
791
+ automate_server_name = @server_configs.select {|name, config| config[:server_type] == 'automate'}.keys.first
792
+ if automate_server_name
793
+ automate_server = get_server(automate_server_name)
794
+ automate_credentials_files = Dir.glob("#{automate_server.container.config_item('lxc.rootfs')}/etc/delivery/*-credentials")
795
+ automate_credentials_files.each_with_index do |automate_credentials_file, index|
796
+ puts IO.read(automate_credentials_file)
797
+ puts if index + 1 < automate_credentials_files.length
798
+ end
799
+ else
800
+ puts "WARNING: An Automate server is not defined."
801
+ exit 1
802
+ end
803
+ end
804
+
805
+ def configure_build_node(server)
806
+ automate_server_name = @server_configs.select {|name, config| config[:server_type] == 'automate'}.keys.first
807
+ if automate_server_name
808
+ automate_server = get_server(automate_server_name)
809
+ install_build_node_cmd = "install-build-node"
810
+ install_build_node_cmd += " --fqdn #{server.name}"
811
+ install_build_node_cmd += " --username dev-lxc"
812
+ install_build_node_cmd += " --password dev-lxc"
813
+ install_build_node_cmd += " --installer #{@server_configs[server.name][:required_products]["chefdk"]}"
814
+ install_build_node_cmd += " --overwrite-registration"
815
+ automate_server.run_command("delivery-ctl #{install_build_node_cmd}")
816
+ end
817
+ end
818
+
819
+ def configure_runner(server)
820
+ automate_server_name = @server_configs.select {|name, config| config[:server_type] == 'automate'}.keys.first
821
+ if automate_server_name
822
+ automate_server = get_server(automate_server_name)
823
+ install_runner_cmd = "install-runner #{server.name} dev-lxc"
824
+ install_runner_cmd += " --password dev-lxc"
825
+ install_runner_cmd += " --installer #{@server_configs[server.name][:required_products]["chefdk"]}"
826
+ install_runner_cmd += " --yes"
827
+ automate_server.run_command("delivery-ctl #{install_runner_cmd}")
828
+ end
829
+ end
830
+
831
+ def configure_chef_client(server, dot_chef_path)
832
+ puts "Configuring Chef Client in container '#{server.name}'"
833
+
834
+ FileUtils.mkdir_p("#{server.container.config_item('lxc.rootfs')}/etc/chef")
835
+
836
+ chef_server_url = @server_configs[server.name][:chef_server_url]
837
+ validation_client_name = @server_configs[server.name][:validation_client_name]
838
+ validation_key = @server_configs[server.name][:validation_key]
839
+ if validation_key.nil?
840
+ chef_server_name = @config['chef-server'][:bootstrap_backend]
841
+ chef_server_name ||= @config['chef-backend'][:bootstrap_frontend]
842
+ if chef_server_name
843
+ chef_server = get_server(chef_server_name)
844
+ if chef_server.container.defined?
845
+ validator_pem_files = Dir.glob("#{chef_server.container.config_item('lxc.rootfs')}#{dot_chef_path}/*-validator.pem")
846
+ FileUtils.cp(validator_pem_files, "#{server.container.config_item('lxc.rootfs')}/etc/chef/") unless validator_pem_files.empty?
847
+ end
848
+ end
849
+ else
850
+ FileUtils.cp(validation_key, "#{server.container.config_item('lxc.rootfs')}/etc/chef/") if File.exists?(validation_key)
851
+ end
852
+
853
+ client_rb = %Q(# uncomment the following proxy lines to send traffic through mitmproxy
854
+ #http_proxy 'http://10.0.3.1:8080'
855
+ #https_proxy 'http://10.0.3.1:8080'
856
+
857
+ chef_server_url '#{chef_server_url}'
858
+ validation_client_name '#{validation_client_name}'
859
+ validation_key '/etc/chef/#{validation_client_name}.pem'
860
+ ssl_verify_mode :verify_none
861
+ )
862
+
863
+ automate_server_name = @server_configs.select {|name, config| config[:server_type] == 'automate'}.keys.first
864
+ if automate_server_name
865
+ client_rb += %Q(
866
+ # data_collector.server_url "https://#{automate_server_name}/data-collector/v0/"
867
+ # data_collector.token "93a49a4f2482c64126f7b6015e6b0f30284287ee4054ff8807fb63d9cbd1c506"
868
+ )
869
+ end
870
+
871
+ IO.write("#{server.container.config_item('lxc.rootfs')}/etc/chef/client.rb", client_rb)
872
+ end
873
+
874
+ def configure_chef_backend(server)
875
+ FileUtils.mkdir_p("#{server.container.config_item('lxc.rootfs')}/var/opt/chef-backend")
876
+ FileUtils.touch("#{server.container.config_item('lxc.rootfs')}/var/opt/chef-backend/.license.accepted")
877
+ if server.name == @config['chef-backend'][:leader_backend]
878
+ puts "Creating /etc/chef-backend/chef-backend.rb"
879
+ FileUtils.mkdir_p("#{server.container.config_item('lxc.rootfs')}/etc/chef-backend")
880
+ chef_backend_config = "publish_address '#{@server_configs[server.name][:ipaddress]}'\n"
881
+ IO.write("#{server.container.config_item('lxc.rootfs')}/etc/chef-backend/chef-backend.rb", chef_backend_config)
882
+ server.run_command("chef-backend-ctl bootstrap --yes")
883
+ else
884
+ puts "Joining #{server.name} to the chef-backend cluster"
885
+ leader_backend = get_server(@config['chef-backend'][:leader_backend])
886
+ FileUtils.cp("#{leader_backend.container.config_item('lxc.rootfs')}/etc/chef-backend/chef-backend-secrets.json",
887
+ "#{server.container.config_item('lxc.rootfs')}/root/")
888
+ server.run_command("chef-backend-ctl join-cluster #{@server_configs[leader_backend.name][:ipaddress]} -p #{@server_configs[server.name][:ipaddress]} -s /root/chef-backend-secrets.json --yes")
889
+ end
890
+ end
891
+
892
+ def configure_chef_frontend(server)
893
+ puts "Creating /etc/opscode/chef-server.rb"
894
+ FileUtils.mkdir_p("#{server.container.config_item('lxc.rootfs')}/etc/opscode")
895
+ leader_backend = get_server(@config['chef-backend'][:leader_backend])
896
+ if @server_configs[server.name][:chef_server_rb]
897
+ puts "Copying #{@server_configs[server.name][:chef_server_rb]} to /etc/opscode/chef-server.rb"
898
+ FileUtils.cp(@server_configs[server.name][:chef_server_rb], "#{server.container.config_item('lxc.rootfs')}/etc/opscode/chef-server.rb")
899
+ else
900
+ leader_backend.run_command("chef-backend-ctl gen-server-config #{server.name}", "#{server.container.config_item('lxc.rootfs')}/etc/opscode/chef-server.rb")
901
+ end
902
+ if @server_configs[server.name][:chef_server_rb_partials]
903
+ @server_configs[server.name][:chef_server_rb_partials].each do |partial|
904
+ puts "Appending #{partial} to /etc/opscode/chef-server.rb"
905
+ partial_content = IO.read(partial)
906
+ IO.write("#{server.container.config_item('lxc.rootfs')}/etc/opscode/chef-server.rb", partial_content, mode: 'a')
907
+ end
908
+ end
909
+ unless server.name == @config['chef-backend'][:bootstrap_frontend]
910
+ bootstrap_frontend = get_server(@config['chef-backend'][:bootstrap_frontend])
911
+ %w(pivotal.pem private-chef-secrets.json webui_priv.pem webui_pub.pem).each do |file|
912
+ puts "Copying /etc/opscode/#{file} from bootstrap frontend '#{bootstrap_frontend.name}'"
913
+ FileUtils.cp("#{bootstrap_frontend.container.config_item('lxc.rootfs')}/etc/opscode/#{file}", "#{server.container.config_item('lxc.rootfs')}/etc/opscode/")
914
+ end
915
+ FileUtils.mkdir_p("#{server.container.config_item('lxc.rootfs')}/var/opt/opscode/upgrades/")
916
+ puts "Copying /var/opt/opscode/upgrades/migration-level from bootstrap frontend '#{bootstrap_frontend.name}'"
917
+ FileUtils.cp("#{bootstrap_frontend.container.config_item('lxc.rootfs')}/var/opt/opscode/upgrades/migration-level", "#{server.container.config_item('lxc.rootfs')}/var/opt/opscode/upgrades/")
918
+ puts "Touching /var/opt/opscode/bootstrapped"
919
+ FileUtils.touch("#{server.container.config_item('lxc.rootfs')}/var/opt/opscode/bootstrapped")
920
+ end
921
+ server.run_command("chef-server-ctl reconfigure")
922
+ end
923
+
924
+ def configure_chef_server(server)
925
+ if @config['chef-server'][:topology] == "standalone" || @config['chef-server'][:bootstrap_backend] == server.name
926
+ case @server_configs[server.name][:chef_server_type]
927
+ when 'private-chef'
928
+ puts "Creating /etc/opscode/private-chef.rb"
929
+ FileUtils.mkdir_p("#{server.container.config_item('lxc.rootfs')}/etc/opscode")
930
+ if @server_configs[server.name][:chef_server_rb]
931
+ puts "Copying #{@server_configs[server.name][:chef_server_rb]} to /etc/opscode/private-chef.rb"
932
+ FileUtils.cp(@server_configs[server.name][:chef_server_rb], "#{server.container.config_item('lxc.rootfs')}/etc/opscode/private-chef.rb")
933
+ else
934
+ IO.write("#{server.container.config_item('lxc.rootfs')}/etc/opscode/private-chef.rb", chef_server_config)
935
+ end
936
+ if @server_configs[server.name][:chef_server_rb_partials]
937
+ @server_configs[server.name][:chef_server_rb_partials].each do |partial|
938
+ puts "Appending #{partial} to /etc/opscode/private-chef.rb"
939
+ partial_content = IO.read(partial)
940
+ IO.write("#{server.container.config_item('lxc.rootfs')}/etc/opscode/private-chef.rb", partial_content, mode: 'a')
941
+ end
942
+ end
943
+ when 'chef-server'
944
+ puts "Creating /etc/opscode/chef-server.rb"
945
+ FileUtils.mkdir_p("#{server.container.config_item('lxc.rootfs')}/etc/opscode")
946
+ if @server_configs[server.name][:chef_server_rb]
947
+ puts "Copying #{@server_configs[server.name][:chef_server_rb]} to /etc/opscode/chef-server.rb"
948
+ FileUtils.cp(@server_configs[server.name][:chef_server_rb], "#{server.container.config_item('lxc.rootfs')}/etc/opscode/chef-server.rb")
949
+ else
950
+ IO.write("#{server.container.config_item('lxc.rootfs')}/etc/opscode/chef-server.rb", chef_server_config)
951
+ end
952
+ if @server_configs[server.name][:chef_server_rb_partials]
953
+ @server_configs[server.name][:chef_server_rb_partials].each do |partial|
954
+ puts "Appending #{partial} to /etc/opscode/chef-server.rb"
955
+ partial_content = IO.read(partial)
956
+ IO.write("#{server.container.config_item('lxc.rootfs')}/etc/opscode/chef-server.rb", partial_content, mode: 'a')
957
+ end
958
+ end
959
+ end
960
+ elsif @config['chef-server'][:frontends].include?(server.name)
961
+ puts "Copying /etc/opscode from bootstrap backend '#{@config['chef-server'][:bootstrap_backend]}'"
962
+ FileUtils.cp_r("#{get_server(@config['chef-server'][:bootstrap_backend]).container.config_item('lxc.rootfs')}/etc/opscode",
963
+ "#{server.container.config_item('lxc.rootfs')}/etc", preserve: true)
964
+ if @server_configs[server.name][:chef_server_rb]
965
+ puts "Copying #{@server_configs[server.name][:chef_server_rb]} to /etc/opscode/#{@server_configs[server.name][:chef_server_type]}.rb"
966
+ FileUtils.cp(@server_configs[server.name][:chef_server_rb], "#{server.container.config_item('lxc.rootfs')}/etc/opscode/#{@server_configs[server.name][:chef_server_type]}.rb")
967
+ end
968
+ if @server_configs[server.name][:chef_server_rb_partials]
969
+ @server_configs[server.name][:chef_server_rb_partials].each do |partial|
970
+ puts "Appending #{partial} to /etc/opscode/#{@server_configs[server.name][:chef_server_type]}.rb"
971
+ partial_content = IO.read(partial)
972
+ IO.write("#{server.container.config_item('lxc.rootfs')}/etc/opscode/#{@server_configs[server.name][:chef_server_type]}.rb", partial_content, mode: 'a')
973
+ end
974
+ end
975
+ end
976
+ server.run_command("#{@server_configs[server.name][:chef_server_type]}-ctl reconfigure")
977
+ end
978
+
979
+ def configure_reporting(server)
980
+ FileUtils.mkdir_p("#{server.container.config_item('lxc.rootfs')}/var/opt/opscode-reporting")
981
+ FileUtils.touch("#{server.container.config_item('lxc.rootfs')}/var/opt/opscode-reporting/.license.accepted")
982
+ if @config['chef-server'][:frontends].include?(server.name)
983
+ puts "Copying /etc/opscode-reporting from bootstrap backend '#{@config['chef-server'][:bootstrap_backend]}'"
984
+ FileUtils.cp_r("#{get_server(@config['chef-server'][:bootstrap_backend]).container.config_item('lxc.rootfs')}/etc/opscode-reporting",
985
+ "#{server.container.config_item('lxc.rootfs')}/etc", preserve: true)
986
+ end
987
+ server.run_command("#{@server_configs[server.name][:chef_server_type]}-ctl reconfigure")
988
+ server.run_command("opscode-reporting-ctl reconfigure")
989
+ end
990
+
991
+ def configure_push_jobs_server(server)
992
+ server.run_command("opscode-push-jobs-server-ctl reconfigure")
993
+ server.run_command("#{@server_configs[server.name][:chef_server_type]}-ctl reconfigure")
994
+ end
995
+
996
+ def configure_manage(server)
997
+ FileUtils.mkdir_p("#{server.container.config_item('lxc.rootfs')}/var/opt/chef-manage")
998
+ FileUtils.touch("#{server.container.config_item('lxc.rootfs')}/var/opt/chef-manage/.license.accepted")
999
+ if @server_configs[server.name][:chef_server_type] == 'private-chef'
1000
+ puts "Disabling old opscode-webui in /etc/opscode/private-chef.rb"
1001
+ DevLXC.search_file_delete_line("#{server.container.config_item('lxc.rootfs')}/etc/opscode/private-chef.rb", /opscode_webui[.enable.]/)
1002
+ DevLXC.append_line_to_file("#{server.container.config_item('lxc.rootfs')}/etc/opscode/private-chef.rb", "\nopscode_webui['enable'] = false\n")
1003
+ server.run_command("#{@server_configs[server.name][:chef_server_type]}-ctl reconfigure")
1004
+ end
1005
+ server.run_command("opscode-manage-ctl reconfigure")
1006
+ end
1007
+
1008
+ def configure_analytics(server)
1009
+ FileUtils.mkdir_p("#{server.container.config_item('lxc.rootfs')}/var/opt/opscode-analytics")
1010
+ FileUtils.touch("#{server.container.config_item('lxc.rootfs')}/var/opt/opscode-analytics/.license.accepted")
1011
+ if @config['analytics'][:topology] == "standalone" || @config['analytics'][:bootstrap_backend] == server.name
1012
+ puts "Copying /etc/opscode-analytics from Chef Server bootstrap backend '#{@config['chef-server'][:bootstrap_backend]}'"
1013
+ FileUtils.cp_r("#{get_server(@config['chef-server'][:bootstrap_backend]).container.config_item('lxc.rootfs')}/etc/opscode-analytics",
1014
+ "#{server.container.config_item('lxc.rootfs')}/etc", preserve: true)
1015
+
1016
+ IO.write("#{server.container.config_item('lxc.rootfs')}/etc/opscode-analytics/opscode-analytics.rb", analytics_config)
1017
+ elsif @config['analytics'][:frontends].include?(server.name)
1018
+ puts "Copying /etc/opscode-analytics from Analytics bootstrap backend '#{@config['analytics'][:bootstrap_backend]}'"
1019
+ FileUtils.cp_r("#{get_server(@config['analytics'][:bootstrap_backend]).container.config_item('lxc.rootfs')}/etc/opscode-analytics",
1020
+ "#{server.container.config_item('lxc.rootfs')}/etc", preserve: true)
1021
+ end
1022
+ server.run_command("opscode-analytics-ctl reconfigure")
1023
+ end
1024
+
1025
+ def configure_compliance(server)
1026
+ FileUtils.mkdir_p("#{server.container.config_item('lxc.rootfs')}/var/opt/chef-compliance")
1027
+ FileUtils.touch("#{server.container.config_item('lxc.rootfs')}/var/opt/chef-compliance/.license.accepted")
1028
+ server.run_command("chef-compliance-ctl reconfigure")
1029
+ admin_user = @server_configs[server.name][:admin_user]
1030
+ if admin_user
1031
+ server.run_command("chef-compliance-ctl user-create #{admin_user} #{admin_user}")
1032
+ server.run_command("chef-compliance-ctl restart core")
1033
+ end
1034
+
1035
+ if @config["chef-server"][:topology] == "standalone"
1036
+ chef_server = get_server(@config['chef-server'][:bootstrap_backend])
1037
+ FileUtils.mkdir_p("#{chef_server.container.config_item('lxc.rootfs')}/root/integrate-compliance-with-chef-server")
1038
+ FileUtils.mkdir_p("#{server.container.config_item('lxc.rootfs')}/root/integrate-compliance-with-chef-server")
1039
+ IO.write("#{server.container.config_item('lxc.rootfs')}/root/integrate-compliance-with-chef-server/prepare-chef-compliance",
1040
+ "chef-compliance-ctl connect chef-server --non-interactive true --chef-app-id 'compliance_server' --auth-id 'Chef Server' --insecure true --compliance-url 'https://#{server.name}'"
1041
+ )
1042
+ server.run_command("bash /root/integrate-compliance-with-chef-server/prepare-chef-compliance", "#{server.container.config_item('lxc.rootfs')}/root/integrate-compliance-with-chef-server/prepare-chef-compliance-output")
1043
+ server.run_command("chef-compliance-ctl reconfigure")
1044
+ server.run_command("chef-compliance-ctl restart core")
1045
+ prepare_chef_compliance_output = IO.read("#{server.container.config_item('lxc.rootfs')}/root/integrate-compliance-with-chef-server/prepare-chef-compliance-output")
1046
+ delimited_chef_server_command = prepare_chef_compliance_output.match(/\n---\n(.+)\n---/m)
1047
+ if delimited_chef_server_command
1048
+ IO.write("#{chef_server.container.config_item('lxc.rootfs')}/root/integrate-compliance-with-chef-server/configure-chef-server", delimited_chef_server_command[1])
1049
+ chef_server.run_command("bash /root/integrate-compliance-with-chef-server/configure-chef-server", "#{chef_server.container.config_item('lxc.rootfs')}/root/integrate-compliance-with-chef-server/configure-chef-server-output")
1050
+ end
1051
+ configure_chef_server_output = IO.read("#{chef_server.container.config_item('lxc.rootfs')}/root/integrate-compliance-with-chef-server/configure-chef-server-output")
1052
+ compliance_command = configure_chef_server_output.match(/^chef-compliance-ctl .+$/)
1053
+ if compliance_command
1054
+ IO.write("#{server.container.config_item('lxc.rootfs')}/root/integrate-compliance-with-chef-server/configure-chef-compliance", compliance_command)
1055
+ server.run_command("bash /root/integrate-compliance-with-chef-server/configure-chef-compliance")
1056
+ server.run_command("chef-compliance-ctl reconfigure")
1057
+ end
1058
+ end
1059
+ end
1060
+
1061
+ def configure_supermarket(server)
1062
+ if @config['chef-server'][:bootstrap_backend] && get_server(@config['chef-server'][:bootstrap_backend]).container.defined?
1063
+ chef_server_supermarket_config = JSON.parse(IO.read("#{get_server(@config['chef-server'][:bootstrap_backend]).container.config_item('lxc.rootfs')}/etc/opscode/oc-id-applications/supermarket.json"))
1064
+ supermarket_config = {
1065
+ 'chef_server_url' => "https://#{@config['chef-server'][:fqdn]}/",
1066
+ 'chef_oauth2_app_id' => chef_server_supermarket_config['uid'],
1067
+ 'chef_oauth2_secret' => chef_server_supermarket_config['secret'],
1068
+ 'chef_oauth2_verify_ssl' => false
1069
+ }
1070
+ FileUtils.mkdir_p("#{server.container.config_item('lxc.rootfs')}/etc/supermarket")
1071
+ IO.write("#{server.container.config_item('lxc.rootfs')}/etc/supermarket/supermarket.json", JSON.pretty_generate(supermarket_config))
1072
+ end
1073
+ server.run_command("supermarket-ctl reconfigure")
1074
+ end
1075
+
1076
+ def create_users_orgs_knife_configs(server, dot_chef_path)
1077
+ server_type = @server_configs[server.name][:server_type]
1078
+ # give time for all services to come up completely
1079
+ sleep 10
1080
+ if @server_configs[server.name][:chef_server_type] == 'private-chef'
1081
+ # give more time for all services to come up completely
1082
+ sleep 50
1083
+ server.run_command("/opt/opscode/embedded/bin/gem install knife-opc --no-ri --no-rdoc -v 0.3.1")
1084
+ end
1085
+ chef_server_dot_chef_path = "#{server.container.config_item('lxc.rootfs')}#{dot_chef_path}"
1086
+ FileUtils.mkdir_p(chef_server_dot_chef_path)
1087
+ FileUtils.cp( "#{server.container.config_item('lxc.rootfs')}/etc/opscode/pivotal.pem", chef_server_dot_chef_path )
1088
+ create_pivotal_knife_config('127.0.0.1', chef_server_dot_chef_path)
1089
+ create_knife_config('127.0.0.1', chef_server_dot_chef_path)
1090
+ @config[server_type][:users].each do |username|
1091
+ create_user(server, username, dot_chef_path)
1092
+ end
1093
+ @config[server_type][:orgs].each do |orgname, org_users|
1094
+ create_org(server, orgname, dot_chef_path)
1095
+ if org_users
1096
+ if org_users['admins']
1097
+ org_users['admins'].each do |username|
1098
+ org_add_user(server, orgname, username, true, dot_chef_path)
1099
+ end
1100
+ end
1101
+ if org_users['non-admins']
1102
+ org_users['non-admins'].each do |username|
1103
+ org_add_user(server, orgname, username, false, dot_chef_path)
1104
+ end
1105
+ end
1106
+ end
1107
+ end
1108
+ end
1109
+
1110
+ def create_pivotal_knife_config(fqdn, dot_chef_path)
1111
+ pivotal_rb = %Q(
1112
+ current_dir = File.dirname(__FILE__)
1113
+
1114
+ chef_server_root "https://#{fqdn}"
1115
+ chef_server_url "https://#{fqdn}"
1116
+
1117
+ node_name "pivotal"
1118
+ client_key "\#{current_dir}/pivotal.pem"
1119
+
1120
+ cookbook_path Dir.pwd + "/cookbooks"
1121
+ knife[:chef_repo_path] = Dir.pwd
1122
+
1123
+ ssl_verify_mode :verify_none
1124
+ )
1125
+ IO.write("#{dot_chef_path}/pivotal.rb", pivotal_rb)
1126
+ end
1127
+
1128
+ def create_knife_config(fqdn, dot_chef_path)
1129
+ knife_rb = %Q(# uncomment the following proxy lines to send traffic through a proxy
1130
+ # mitmproxy uses port 8080
1131
+ # tinyproxy uses port 8888
1132
+ #http_proxy 'http://127.0.0.1:8080'
1133
+ #https_proxy 'http://127.0.0.1:8080'
1134
+
1135
+ username = "CHANGEME"
1136
+ orgname = "CHANGEME"
1137
+
1138
+ if [username, orgname].include?("CHANGEME")
1139
+ puts "ERROR: Please set 'username' and 'orgname' to proper values in knife.rb"
1140
+ exit!
1141
+ end
1142
+
1143
+ current_dir = File.dirname(__FILE__)
1144
+
1145
+ chef_server_url "https://#{fqdn}/organizations/\#{orgname}"
1146
+
1147
+ node_name username
1148
+ client_key "\#{current_dir}/\#{username}.pem"
1149
+
1150
+ validation_client_name "\#{orgname}-validator"
1151
+ validation_key "\#{current_dir}/\#{orgname}-validator.pem"
1152
+
1153
+ cookbook_path Dir.pwd + "/cookbooks"
1154
+ knife[:chef_repo_path] = Dir.pwd
1155
+
1156
+ ssl_verify_mode :verify_none
1157
+ )
1158
+ IO.write("#{dot_chef_path}/knife.rb", knife_rb)
1159
+ end
1160
+
1161
+ def create_user(server, username, dot_chef_path)
1162
+ create_user_string = "#{username} #{username} #{username} #{username}@noreply.com #{username} --filename #{dot_chef_path}/#{username}.pem"
1163
+ case @server_configs[server.name][:chef_server_type]
1164
+ when 'private-chef'
1165
+ server.run_command("/opt/opscode/embedded/bin/knife opc user create #{create_user_string} -c #{dot_chef_path}/pivotal.rb")
1166
+ when 'chef-server'
1167
+ server.run_command("chef-server-ctl user-create #{create_user_string}")
1168
+ end
1169
+ end
1170
+
1171
+ def create_org(server, orgname, dot_chef_path)
1172
+ create_org_string = "#{orgname} #{orgname} --filename #{dot_chef_path}/#{orgname}-validator.pem"
1173
+ case @server_configs[server.name][:chef_server_type]
1174
+ when 'private-chef'
1175
+ server.run_command("/opt/opscode/embedded/bin/knife opc org create #{create_org_string} -c #{dot_chef_path}/pivotal.rb")
1176
+ when 'chef-server'
1177
+ server.run_command("chef-server-ctl org-create #{create_org_string}")
1178
+ end
1179
+ end
1180
+
1181
+ def org_add_user(server, orgname, username, admin, dot_chef_path)
1182
+ org_add_user_string = "#{orgname} #{username}"
1183
+ org_add_user_string += " --admin" if admin
1184
+ case @server_configs[server.name][:chef_server_type]
1185
+ when 'private-chef'
1186
+ server.run_command("/opt/opscode/embedded/bin/knife opc org user add #{org_add_user_string} -c #{dot_chef_path}/pivotal.rb")
1187
+ when 'chef-server'
1188
+ server.run_command("chef-server-ctl org-user-add #{org_add_user_string}")
1189
+ end
1190
+ end
1191
+
1192
+ def chef_repo(force=false, pivotal=false)
1193
+ chef_server_dot_chef_path = "/root/chef-repo/.chef"
1194
+ dot_chef_path = ".chef"
1195
+
1196
+ if @config['chef-server'][:bootstrap_backend]
1197
+ chef_server = get_server(@config['chef-server'][:bootstrap_backend])
1198
+ chef_server_fqdn = @config['chef-server'][:fqdn]
1199
+ elsif @config['chef-backend'][:bootstrap_frontend]
1200
+ chef_server = get_server(@config['chef-backend'][:bootstrap_frontend])
1201
+ chef_server_fqdn = @config['chef-backend'][:fqdn]
1202
+ else
1203
+ puts "ERROR: A Chef Server is not defined in the cluster's config. Please define it first."
1204
+ exit 1
1205
+ end
1206
+ unless chef_server.container.defined?
1207
+ puts "ERROR: The '#{chef_server.name}' Chef Server does not exist."
1208
+ exit 1
1209
+ end
1210
+
1211
+ puts "Creating chef-repo with pem files and knife.rb in the current directory"
1212
+ FileUtils.mkdir_p(dot_chef_path)
1213
+
1214
+ pem_files = Dir.glob("#{chef_server.container.config_item('lxc.rootfs')}#{chef_server_dot_chef_path}/*.pem")
1215
+ pem_files.delete_if { |pem_file| pem_file.end_with?("/pivotal.pem") } unless pivotal
1216
+ FileUtils.cp(pem_files, dot_chef_path) unless pem_files.empty?
1217
+
1218
+ if pivotal
1219
+ if File.exists?("#{dot_chef_path}/pivotal.rb") && ! force
1220
+ puts "Skipping pivotal.rb because it already exists in `#{dot_chef_path}`"
1221
+ else
1222
+ create_pivotal_knife_config(chef_server_fqdn, dot_chef_path)
1223
+ end
1224
+ end
1225
+
1226
+ if File.exists?("#{dot_chef_path}/knife.rb") && ! force
1227
+ puts "Skipping knife.rb because it already exists in `#{dot_chef_path}`"
1228
+ else
1229
+ create_knife_config(chef_server_fqdn, dot_chef_path)
1230
+ end
1231
+ end
1232
+
1233
+ def chef_server_config
1234
+ chef_server_config = %Q(api_fqdn "#{@config['chef-server'][:fqdn]}"\n)
1235
+ if @config['chef-server'][:topology] == 'tier'
1236
+ chef_server_config += %Q(
1237
+ topology "#{@config['chef-server'][:topology]}"
1238
+
1239
+ server "#{@config['chef-server'][:bootstrap_backend]}",
1240
+ :ipaddress => "#{@server_configs[@config['chef-server'][:bootstrap_backend]][:ipaddress]}",
1241
+ :role => "backend",
1242
+ :bootstrap => true
1243
+
1244
+ backend_vip "#{@config['chef-server'][:bootstrap_backend]}",
1245
+ :ipaddress => "#{@server_configs[@config['chef-server'][:bootstrap_backend]][:ipaddress]}"
1246
+ )
1247
+ @config['chef-server'][:frontends].each do |frontend_name|
1248
+ chef_server_config += %Q(
1249
+ server "#{frontend_name}",
1250
+ :ipaddress => "#{@server_configs[frontend_name][:ipaddress]}",
1251
+ :role => "frontend"
1252
+ )
1253
+ end
1254
+ end
1255
+ if @config['analytics'][:fqdn]
1256
+ chef_server_config += %Q(
1257
+ oc_id['applications'] ||= {}
1258
+ oc_id['applications']['analytics'] = {
1259
+ 'redirect_uri' => 'https://#{@config['analytics'][:fqdn]}/'
1260
+ }
1261
+ rabbitmq['vip'] = '#{@config['chef-server'][:bootstrap_backend]}'
1262
+ rabbitmq['node_ip_address'] = '0.0.0.0'
1263
+ )
1264
+ end
1265
+ if @config['supermarket'][:fqdn]
1266
+ chef_server_config += %Q(
1267
+ oc_id['applications'] ||= {}
1268
+ oc_id['applications']['supermarket'] = {
1269
+ 'redirect_uri' => 'https://#{@config['supermarket'][:fqdn]}/auth/chef_oauth2/callback'
1270
+ }
1271
+ )
1272
+ end
1273
+ automate_server_name = @server_configs.select {|name, config| config[:server_type] == 'automate'}.keys.first
1274
+ if automate_server_name
1275
+ chef_server_config += %Q(
1276
+ data_collector['root_url'] = "https://#{automate_server_name}/data-collector/v0/"
1277
+ data_collector['token'] = "93a49a4f2482c64126f7b6015e6b0f30284287ee4054ff8807fb63d9cbd1c506"
1278
+ profiles['root_url'] = "https://#{automate_server_name}"
1279
+ )
1280
+ end
1281
+ return chef_server_config
1282
+ end
1283
+
1284
+ def analytics_config
1285
+ analytics_config = %Q(analytics_fqdn "#{@config['analytics'][:fqdn]}"
1286
+ topology "#{@config['analytics'][:topology]}"
1287
+ )
1288
+ if @config['analytics'][:topology] == 'tier'
1289
+ analytics_config += %Q(
1290
+ server "#{@config['analytics'][:bootstrap_backend]}",
1291
+ :ipaddress => "#{@server_configs[@config['analytics'][:bootstrap_backend]][:ipaddress]}",
1292
+ :role => "backend",
1293
+ :bootstrap => true
1294
+
1295
+ backend_vip "#{@config['analytics'][:bootstrap_backend]}",
1296
+ :ipaddress => "#{@server_configs[@config['analytics'][:bootstrap_backend]][:ipaddress]}"
1297
+ )
1298
+ @config['analytics'][:frontends].each do |frontend_name|
1299
+ analytics_config += %Q(
1300
+ server "#{frontend_name}",
1301
+ :ipaddress => "#{@server_configs[frontend_name][:ipaddress]}",
1302
+ :role => "frontend"
1303
+ )
1304
+ end
1305
+ end
1306
+ return analytics_config
1307
+ end
1308
+
1309
+ end
1310
+ end