dev-lxc 3.2.0 → 3.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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