dev-lxc 2.6.1 → 2.6.2

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.
data/lib/dev-lxc/cli.rb CHANGED
@@ -1,434 +1,434 @@
1
- require "yaml"
2
- require 'dev-lxc'
3
- require 'thor'
4
-
5
- module DevLXC::CLI
6
- class DevLXC < Thor
7
-
8
- no_commands{
9
- def get_cluster(config_file=nil)
10
- config_file ||= "dev-lxc.yml"
11
- if ! File.exists?(config_file)
12
- puts "ERROR: Cluster config file '#{config_file}' does not exist."
13
- puts " Create a `./dev-lxc.yml` file or specify the path using `--config`."
14
- exit 1
15
- end
16
- cluster_config = YAML.load(IO.read(config_file))
17
- ::DevLXC::Cluster.new(cluster_config)
18
- end
19
-
20
- def print_elapsed_time(elapsed_time)
21
- printf "dev-lxc is finished. (%im %.2fs)\n", elapsed_time / 60, elapsed_time % 60
22
- end
23
- }
24
-
25
- desc "show-config", "Show calculated configuration"
26
- option :config, :desc => "Specify a cluster's YAML config file. `./dev-lxc.yml` will be used by default"
27
- option :include_products, :type => :boolean, :desc => "Calculate required products"
28
- def show_config
29
- get_cluster(options[:config]).show_config(options[:include_products])
30
- end
31
-
32
- desc "create-base-container [BASE_CONTAINER_NAME]", "Create a base container"
33
- option :options, :aliases => "-o", :desc => "Specify additional options for the lxc create"
34
- def create_base_container(base_container_name=nil)
35
- start_time = Time.now
36
- base_container_names = %w(b-ubuntu-1204 b-ubuntu-1404 b-ubuntu-1604 b-centos-5 b-centos-6 b-centos-7)
37
- if base_container_name.nil? || ! base_container_names.include?(base_container_name)
38
- base_container_names_with_index = base_container_names.map.with_index{ |a, i| [i+1, *a]}
39
- print_table base_container_names_with_index
40
- selection = ask("Which base container do you want to create?", :limited_to => base_container_names_with_index.map{|c| c[0].to_s})
41
- base_container_name = base_container_names[selection.to_i - 1]
42
- end
43
- ::DevLXC.create_base_container(base_container_name, options[:options])
44
- puts
45
- print_elapsed_time(Time.now - start_time)
46
- end
47
-
48
- desc "init", "Provide a cluster config file"
49
- option :chef, :type => :boolean, :desc => "Standalone Chef Server"
50
- option :chef_tier, :type => :boolean, :desc => "Chef Server using Tier topology with one backend"
51
- option :chef_backend, :type => :boolean, :desc => "Chef Server using Chef Backend HA topology with three backends"
52
- option :nodes, :type => :boolean, :desc => "Node Servers"
53
- option :analytics, :type => :boolean, :desc => "Analytics Server"
54
- option :compliance, :type => :boolean, :desc => "Compliance Server"
55
- option :supermarket, :type => :boolean, :desc => "Supermarket Server"
56
- option :automate, :type => :boolean, :desc => "Automate Server"
57
- option :build_nodes, :type => :boolean, :desc => "Build Nodes"
58
- option :runners, :type => :boolean, :desc => "Runners"
59
- option :adhoc, :type => :boolean, :desc => "Adhoc Servers"
60
- option :append, :aliases => "-a", :type => :boolean, :desc => "Do not generate the global config header"
61
- option :filename, :aliases => "-f", :desc => "Write generated content to FILE rather than standard output."
62
- def init
63
- header = %Q(# enable_build_snapshots automatically makes container snapshots at key times during the build process
64
- # default value is `true`
65
- #enable_build_snapshots: true
66
-
67
- # base_container must be the name of an existing container
68
- base_container: b-ubuntu-1404
69
-
70
- # memory_per_server sets the maximum amount of user memory (including file cache) for each server.
71
- # dev-lxc will set the `memory.limit_in_bytes` cgroup for each server to apply this limit.
72
- # If no units are specified, the value is interpreted as bytes.
73
- # You can use suffixes to represent larger units k or K for kilobytes, m or M for megabytes, and g or G for gigabytes.
74
- # The default behavior is that no limit is set.
75
- #memory_per_server: 4G
76
-
77
- # list any host directories you want mounted into the servers
78
- #mounts:
79
- # - /root/work root/work
80
-
81
- # list any SSH public keys you want added to /home/dev-lxc/.ssh/authorized_keys
82
- #ssh-keys:
83
- # - /root/work/clusters/id_rsa.pub
84
-
85
- # DHCP reserved (static) IPs must be selected from the IP range 10.0.3.150 - 254
86
- )
87
- chef_tier_config = %Q(
88
- chef-server:
89
- topology: tier
90
- api_fqdn: chef-tier.lxc
91
- users: # a user's password will be the same as its username
92
- - mary-admin
93
- - joe-user
94
- orgs:
95
- demo:
96
- admins:
97
- - mary-admin
98
- non-admins:
99
- - joe-user
100
- servers:
101
- chef-be.lxc:
102
- ipaddress: 10.0.3.201
103
- role: backend
104
- bootstrap: true
105
- products:
106
- chef-server:
107
- push-jobs-server:
108
- reporting:
109
- chef-fe1.lxc:
110
- ipaddress: 10.0.3.202
111
- role: frontend
112
- products:
113
- chef-server:
114
- manage:
115
- push-jobs-server:
116
- reporting:
117
- )
118
- chef_config = %Q(
119
- chef-server:
120
- users: # a user's password will be the same as its username
121
- - mary-admin
122
- - joe-user
123
- orgs:
124
- demo:
125
- admins:
126
- - mary-admin
127
- non-admins:
128
- - joe-user
129
- servers:
130
- chef.lxc:
131
- ipaddress: 10.0.3.203
132
- products:
133
- chef-server:
134
- manage:
135
- push-jobs-server:
136
- reporting:
137
- )
138
- automate_config = %Q(
139
- automate:
140
- servers:
141
- automate.lxc:
142
- ipaddress: 10.0.3.200
143
- products:
144
- delivery:
145
- license_path: /path/for/automate.license
146
- chef_org: delivery
147
- enterprise_name: demo-ent
148
- )
149
- build_nodes_config = %Q(
150
- build-nodes:
151
- servers:
152
- build-node-1.lxc:
153
- products:
154
- chefdk: # downloaded only
155
- )
156
- runners_config = %Q(
157
- runners:
158
- servers:
159
- runner-1.lxc:
160
- products:
161
- chefdk: # downloaded only
162
- )
163
- analytics_config = %Q(
164
- analytics:
165
- servers:
166
- analytics.lxc:
167
- ipaddress: 10.0.3.204
168
- products:
169
- analytics:
170
- )
171
- compliance_config = %Q(
172
- compliance:
173
- admin_user: admin # the password will be the same as the username
174
- servers:
175
- compliance.lxc:
176
- ipaddress: 10.0.3.205
177
- products:
178
- compliance:
179
- )
180
- supermarket_config = %Q(
181
- supermarket:
182
- servers:
183
- supermarket.lxc:
184
- ipaddress: 10.0.3.206
185
- products:
186
- supermarket:
187
- )
188
- adhoc_config = %Q(
189
- adhoc:
190
- servers:
191
- adhoc.lxc:
192
- ipaddress: 10.0.3.207
193
- )
194
- chef_backend_config = %Q(
195
- chef-backend:
196
- api_fqdn: chef-ha.lxc
197
- users: # a user's password will be the same as its username
198
- - mary-admin
199
- - joe-user
200
- orgs:
201
- demo:
202
- admins:
203
- - mary-admin
204
- non-admins:
205
- - joe-user
206
- servers:
207
- chef-backend1.lxc:
208
- ipaddress: 10.0.3.208
209
- role: backend
210
- leader: true
211
- products:
212
- chef-backend:
213
- chef-backend2.lxc:
214
- ipaddress: 10.0.3.209
215
- role: backend
216
- products:
217
- chef-backend:
218
- chef-backend3.lxc:
219
- ipaddress: 10.0.3.210
220
- role: backend
221
- products:
222
- chef-backend:
223
- chef-frontend1.lxc:
224
- ipaddress: 10.0.3.211
225
- role: frontend
226
- bootstrap: true
227
- products:
228
- chef-server:
229
- manage:
230
- )
231
- nodes_config = %Q(
232
- nodes:
233
- chef_server_url: https://chef.lxc/organizations/demo
234
- validation_client_name: demo-validator
235
- # comment out or remove the validation_key path to use chef-server keys generated by dev-lxc
236
- validation_key: # /path/for/ORG-validator.pem
237
- servers:
238
- node-1.lxc:
239
- products:
240
- chef:
241
- )
242
- config = ""
243
- config += header unless options[:append]
244
- config += chef_config if options[:chef]
245
- config += chef_tier_config if options[:chef_tier]
246
- config += analytics_config if options[:analytics]
247
- config += compliance_config if options[:compliance]
248
- config += supermarket_config if options[:supermarket]
249
- config += automate_config if options[:automate]
250
- config += build_nodes_config if options[:build_nodes]
251
- config += runners_config if options[:runners]
252
- config += adhoc_config if options[:adhoc]
253
- config += chef_backend_config if options[:chef_backend]
254
- config += nodes_config if options[:nodes]
255
- if options[:filename]
256
- mode = options[:append] ? 'a' : 'w'
257
- IO.write(options[:filename], config, mode: mode)
258
- else
259
- puts config
260
- end
261
- end
262
-
263
- desc "status [SERVER_NAME_REGEX]", "Show status of servers"
264
- option :config, :desc => "Specify a cluster's YAML config file. `./dev-lxc.yml` will be used by default"
265
- def status(server_name_regex=nil)
266
- cluster = get_cluster(options[:config])
267
- if cluster.config['chef-server'][:topology] == "tier" && cluster.config['chef-server'][:fqdn]
268
- printf "Chef Server FQDN: %s\n\n", cluster.config['chef-server'][:fqdn]
269
- end
270
- if cluster.config['chef-backend'][:fqdn]
271
- printf "Chef Server FQDN: %s\n\n", cluster.config['chef-backend'][:fqdn]
272
- end
273
- if cluster.config['analytics'][:topology] == "tier" && cluster.config['analytics'][:fqdn]
274
- printf "Analytics FQDN: %s\n\n", cluster.config['analytics'][:fqdn]
275
- end
276
- servers = Array.new
277
- cluster.get_sorted_servers(server_name_regex).map { |s| servers << s.status }
278
- max_server_name_length = servers.max_by { |s| s['name'].length }['name'].length unless servers.empty?
279
- servers.each_with_index do |s, server_index|
280
- printf "%-#{max_server_name_length}s %-15s %s\n", s['name'], s['state'].upcase, s['ip_addresses']
281
- server = cluster.get_server(s['name'])
282
- server.snapshot_list.each do |snapname, snaptime, snap_comment|
283
- printf " |_ %s %s %s\n", snapname, snaptime, snap_comment
284
- end
285
- puts if server_index + 1 < servers.length
286
- end
287
- end
288
-
289
- desc "attach [SERVER_NAME_REGEX]", "Attach the terminal to a single server"
290
- option :config, :desc => "Specify a cluster's YAML config file. `./dev-lxc.yml` will be used by default"
291
- def attach(server_name_regex)
292
- servers = get_cluster(options[:config]).get_sorted_servers(server_name_regex)
293
- if servers.length > 1
294
- puts "ERROR: The following servers matched '#{server_name_regex}'"
295
- servers.map { |s| puts " #{s.name}" }
296
- puts " Please specify a single server to attach to"
297
- exit 1
298
- elsif servers.empty?
299
- puts "ERROR: No servers matched '#{server_name_regex}'"
300
- puts " Please specify a single server to attach to"
301
- exit 1
302
- end
303
- container = servers.first.container
304
- if !container.defined? || !container.running?
305
- puts "ERROR: Server '#{container.name}' is not running"
306
- exit 1
307
- end
308
- attach_opts = {
309
- wait: true,
310
- env_policy: LXC::LXC_ATTACH_CLEAR_ENV,
311
- extra_env_vars: ["LANG=en_US.UTF-8", "TERM=linux", "HOME=#{ENV['HOME']}"]
312
- }
313
- shell = ENV['SHELL']
314
- container.attach(attach_opts) { system(shell) }
315
- end
316
-
317
- desc "chef-repo", "Creates a chef-repo in the current directory using files from the cluster's backend /root/chef-repo"
318
- option :config, :desc => "Specify a cluster's YAML config file. `./dev-lxc.yml` will be used by default"
319
- option :force, :aliases => "-f", :type => :boolean, :desc => "Overwrite any existing knife.rb or pivotal.rb files"
320
- option :pivotal, :aliases => "-p", :type => :boolean, :desc => "Also copy pivotal.rb and pivotal.pem"
321
- def chef_repo
322
- get_cluster(options[:config]).chef_repo(options[:force], options[:pivotal])
323
- end
324
-
325
- desc "print-automate-credentials", "Print Automate credentials"
326
- option :config, :desc => "Specify a cluster's YAML config file. `./dev-lxc.yml` will be used by default"
327
- def print_automate_credentials
328
- get_cluster(options[:config]).print_automate_credentials
329
- end
330
-
331
- desc "run-command [SERVER_NAME_REGEX] [COMMAND]", "Runs a command in each server"
332
- option :config, :desc => "Specify a cluster's YAML config file. `./dev-lxc.yml` will be used by default"
333
- def run_command(server_name_regex=nil, command)
334
- start_time = Time.now
335
- get_cluster(options[:config]).get_sorted_servers(server_name_regex).each { |s| s.run_command(command); puts }
336
- print_elapsed_time(Time.now - start_time)
337
- end
338
-
339
- desc "prepare-product-cache [SERVER_NAME_REGEX]", "Download required product packages to cache"
340
- option :config, :desc => "Specify a cluster's YAML config file. `./dev-lxc.yml` will be used by default"
341
- def prepare_product_cache(server_name_regex=nil)
342
- start_time = Time.now
343
- cluster = get_cluster(options[:config])
344
- servers = cluster.get_sorted_servers(server_name_regex)
345
- cluster.prep_product_cache(servers, true)
346
- print_elapsed_time(Time.now - start_time)
347
- end
348
-
349
- desc "up [SERVER_NAME_REGEX]", "Start servers - This is the default if no subcommand is given"
350
- option :config, :desc => "Specify a cluster's YAML config file. `./dev-lxc.yml` will be used by default"
351
- def up(server_name_regex=nil)
352
- start_time = Time.now
353
- get_cluster(options[:config]).up(server_name_regex)
354
- print_elapsed_time(Time.now - start_time)
355
- end
356
-
357
- desc "halt [SERVER_NAME_REGEX]", "Shutdown servers"
358
- option :config, :desc => "Specify a cluster's YAML config file. `./dev-lxc.yml` will be used by default"
359
- def halt(server_name_regex=nil)
360
- start_time = Time.now
361
- get_cluster(options[:config]).halt(server_name_regex)
362
- print_elapsed_time(Time.now - start_time)
363
- end
364
-
365
- desc "snapshot [SERVER_NAME_REGEX]", "Manage a cluster's snapshots"
366
- option :comment, :aliases => "-c", :desc => "Add snapshot comment"
367
- option :config, :desc => "Specify a cluster's YAML config file. `./dev-lxc.yml` will be used by default"
368
- option :destroy, :aliases => "-d", :desc => "Destroy snapshot - use ALL to destroy all snapshots"
369
- option :list, :aliases => "-l", :type => :boolean, :desc => "List snapshots"
370
- option :restore, :aliases => "-r", :desc => "Restore snapshots"
371
- def snapshot(server_name_regex=nil)
372
- start_time = Time.now
373
- servers = get_cluster(options[:config]).get_sorted_servers(server_name_regex)
374
- if options[:list]
375
- servers.each_with_index do |s, server_index|
376
- puts s.name
377
- s.snapshot_list.each do |snapname, snaptime, snap_comment|
378
- printf " |_ %s %s %s\n", snapname, snaptime, snap_comment
379
- end
380
- puts if server_index + 1 < servers.length
381
- end
382
- return
383
- elsif options[:destroy]
384
- snapname = options[:destroy] == 'destroy' ? "LAST" : options[:destroy]
385
- servers.each { |s| s.snapshot_destroy(snapname); puts }
386
- elsif options[:restore]
387
- running_servers = Array.new
388
- servers.each do |s|
389
- running_servers << s.name if s.container.running?
390
- end
391
- unless running_servers.empty?
392
- puts "ERROR: Aborting snapshot restore because the following servers are running"
393
- puts running_servers
394
- exit 1
395
- end
396
- snapname = options[:restore] == 'restore' ? "LAST" : options[:restore]
397
- servers.each { |s| s.snapshot_restore(snapname); puts }
398
- else
399
- running_servers = Array.new
400
- servers.each do |s|
401
- running_servers << s.name if s.container.running?
402
- end
403
- unless running_servers.empty?
404
- puts "ERROR: Aborting snapshot because the following servers are running"
405
- puts running_servers
406
- exit 1
407
- end
408
- servers.each { |s| s.snapshot(options[:comment]); puts }
409
- end
410
- print_elapsed_time(Time.now - start_time)
411
- end
412
-
413
- desc "destroy [SERVER_NAME_REGEX]", "Destroy servers"
414
- option :config, :desc => "Specify a cluster's YAML config file. `./dev-lxc.yml` will be used by default"
415
- option :force, :aliases => "-f", :type => :boolean, :desc => "Destroy servers without confirmation"
416
- def destroy(server_name_regex=nil)
417
- servers = get_cluster(options[:config]).get_sorted_servers(server_name_regex)
418
- if servers.empty?
419
- puts "No matching server names were found"
420
- exit
421
- end
422
- unless options[:force]
423
- confirmation_string = String.new
424
- servers.reverse_each { |s| confirmation_string += "#{s.name}\n" }
425
- confirmation_string += "Are you sure you want to destroy these servers? (y/N)\n"
426
- return unless yes?(confirmation_string)
427
- end
428
- start_time = Time.now
429
- get_cluster(options[:config]).destroy(server_name_regex)
430
- print_elapsed_time(Time.now - start_time)
431
- end
432
-
433
- end
434
- end
1
+ require "yaml"
2
+ require 'dev-lxc'
3
+ require 'thor'
4
+
5
+ module DevLXC::CLI
6
+ class DevLXC < Thor
7
+
8
+ no_commands{
9
+ def get_cluster(config_file=nil)
10
+ config_file ||= "dev-lxc.yml"
11
+ if ! File.exists?(config_file)
12
+ puts "ERROR: Cluster config file '#{config_file}' does not exist."
13
+ puts " Create a `./dev-lxc.yml` file or specify the path using `--config`."
14
+ exit 1
15
+ end
16
+ cluster_config = YAML.load(IO.read(config_file))
17
+ ::DevLXC::Cluster.new(cluster_config)
18
+ end
19
+
20
+ def print_elapsed_time(elapsed_time)
21
+ printf "dev-lxc is finished. (%im %.2fs)\n", elapsed_time / 60, elapsed_time % 60
22
+ end
23
+ }
24
+
25
+ desc "show-config", "Show calculated configuration"
26
+ option :config, :desc => "Specify a cluster's YAML config file. `./dev-lxc.yml` will be used by default"
27
+ option :include_products, :type => :boolean, :desc => "Calculate required products"
28
+ def show_config
29
+ get_cluster(options[:config]).show_config(options[:include_products])
30
+ end
31
+
32
+ desc "create-base-container [BASE_CONTAINER_NAME]", "Create a base container"
33
+ option :options, :aliases => "-o", :desc => "Specify additional options for the lxc create"
34
+ def create_base_container(base_container_name=nil)
35
+ start_time = Time.now
36
+ base_container_names = %w(b-ubuntu-1204 b-ubuntu-1404 b-ubuntu-1604 b-centos-5 b-centos-6 b-centos-7)
37
+ if base_container_name.nil? || ! base_container_names.include?(base_container_name)
38
+ base_container_names_with_index = base_container_names.map.with_index{ |a, i| [i+1, *a]}
39
+ print_table base_container_names_with_index
40
+ selection = ask("Which base container do you want to create?", :limited_to => base_container_names_with_index.map{|c| c[0].to_s})
41
+ base_container_name = base_container_names[selection.to_i - 1]
42
+ end
43
+ ::DevLXC.create_base_container(base_container_name, options[:options])
44
+ puts
45
+ print_elapsed_time(Time.now - start_time)
46
+ end
47
+
48
+ desc "init", "Provide a cluster config file"
49
+ option :chef, :type => :boolean, :desc => "Standalone Chef Server"
50
+ option :chef_tier, :type => :boolean, :desc => "Chef Server using Tier topology with one backend"
51
+ option :chef_backend, :type => :boolean, :desc => "Chef Server using Chef Backend HA topology with three backends"
52
+ option :nodes, :type => :boolean, :desc => "Node Servers"
53
+ option :analytics, :type => :boolean, :desc => "Analytics Server"
54
+ option :compliance, :type => :boolean, :desc => "Compliance Server"
55
+ option :supermarket, :type => :boolean, :desc => "Supermarket Server"
56
+ option :automate, :type => :boolean, :desc => "Automate Server"
57
+ option :build_nodes, :type => :boolean, :desc => "Build Nodes"
58
+ option :runners, :type => :boolean, :desc => "Runners"
59
+ option :adhoc, :type => :boolean, :desc => "Adhoc Servers"
60
+ option :append, :aliases => "-a", :type => :boolean, :desc => "Do not generate the global config header"
61
+ option :filename, :aliases => "-f", :desc => "Write generated content to FILE rather than standard output."
62
+ def init
63
+ header = %Q(# enable_build_snapshots automatically makes container snapshots at key times during the build process
64
+ # default value is `true`
65
+ #enable_build_snapshots: true
66
+
67
+ # base_container must be the name of an existing container
68
+ base_container: b-ubuntu-1404
69
+
70
+ # memory_per_server sets the maximum amount of user memory (including file cache) for each server.
71
+ # dev-lxc will set the `memory.limit_in_bytes` cgroup for each server to apply this limit.
72
+ # If no units are specified, the value is interpreted as bytes.
73
+ # You can use suffixes to represent larger units - k or K for kilobytes, m or M for megabytes, and g or G for gigabytes.
74
+ # The default behavior is that no limit is set.
75
+ #memory_per_server: 4G
76
+
77
+ # list any host directories you want mounted into the servers
78
+ #mounts:
79
+ # - /root/work root/work
80
+
81
+ # list any SSH public keys you want added to /home/dev-lxc/.ssh/authorized_keys
82
+ #ssh-keys:
83
+ # - /root/work/clusters/id_rsa.pub
84
+
85
+ # DHCP reserved (static) IPs must be selected from the IP range 10.0.3.150 - 254
86
+ )
87
+ chef_tier_config = %Q(
88
+ chef-server:
89
+ topology: tier
90
+ api_fqdn: chef-tier.lxc
91
+ users: # a user's password will be the same as its username
92
+ - mary-admin
93
+ - joe-user
94
+ orgs:
95
+ demo:
96
+ admins:
97
+ - mary-admin
98
+ non-admins:
99
+ - joe-user
100
+ servers:
101
+ chef-be.lxc:
102
+ ipaddress: 10.0.3.201
103
+ role: backend
104
+ bootstrap: true
105
+ products:
106
+ chef-server:
107
+ push-jobs-server:
108
+ reporting:
109
+ chef-fe1.lxc:
110
+ ipaddress: 10.0.3.202
111
+ role: frontend
112
+ products:
113
+ chef-server:
114
+ manage:
115
+ push-jobs-server:
116
+ reporting:
117
+ )
118
+ chef_config = %Q(
119
+ chef-server:
120
+ users: # a user's password will be the same as its username
121
+ - mary-admin
122
+ - joe-user
123
+ orgs:
124
+ demo:
125
+ admins:
126
+ - mary-admin
127
+ non-admins:
128
+ - joe-user
129
+ servers:
130
+ chef.lxc:
131
+ ipaddress: 10.0.3.203
132
+ products:
133
+ chef-server:
134
+ manage:
135
+ push-jobs-server:
136
+ reporting:
137
+ )
138
+ automate_config = %Q(
139
+ automate:
140
+ servers:
141
+ automate.lxc:
142
+ ipaddress: 10.0.3.200
143
+ products:
144
+ delivery:
145
+ license_path: /path/for/automate.license
146
+ chef_org: delivery
147
+ enterprise_name: demo-ent
148
+ )
149
+ build_nodes_config = %Q(
150
+ build-nodes:
151
+ servers:
152
+ build-node-1.lxc:
153
+ products:
154
+ chefdk: # downloaded only
155
+ )
156
+ runners_config = %Q(
157
+ runners:
158
+ servers:
159
+ runner-1.lxc:
160
+ products:
161
+ chefdk: # downloaded only
162
+ )
163
+ analytics_config = %Q(
164
+ analytics:
165
+ servers:
166
+ analytics.lxc:
167
+ ipaddress: 10.0.3.204
168
+ products:
169
+ analytics:
170
+ )
171
+ compliance_config = %Q(
172
+ compliance:
173
+ admin_user: admin # the password will be the same as the username
174
+ servers:
175
+ compliance.lxc:
176
+ ipaddress: 10.0.3.205
177
+ products:
178
+ compliance:
179
+ )
180
+ supermarket_config = %Q(
181
+ supermarket:
182
+ servers:
183
+ supermarket.lxc:
184
+ ipaddress: 10.0.3.206
185
+ products:
186
+ supermarket:
187
+ )
188
+ adhoc_config = %Q(
189
+ adhoc:
190
+ servers:
191
+ adhoc.lxc:
192
+ ipaddress: 10.0.3.207
193
+ )
194
+ chef_backend_config = %Q(
195
+ chef-backend:
196
+ api_fqdn: chef-ha.lxc
197
+ users: # a user's password will be the same as its username
198
+ - mary-admin
199
+ - joe-user
200
+ orgs:
201
+ demo:
202
+ admins:
203
+ - mary-admin
204
+ non-admins:
205
+ - joe-user
206
+ servers:
207
+ chef-backend1.lxc:
208
+ ipaddress: 10.0.3.208
209
+ role: backend
210
+ leader: true
211
+ products:
212
+ chef-backend:
213
+ chef-backend2.lxc:
214
+ ipaddress: 10.0.3.209
215
+ role: backend
216
+ products:
217
+ chef-backend:
218
+ chef-backend3.lxc:
219
+ ipaddress: 10.0.3.210
220
+ role: backend
221
+ products:
222
+ chef-backend:
223
+ chef-frontend1.lxc:
224
+ ipaddress: 10.0.3.211
225
+ role: frontend
226
+ bootstrap: true
227
+ products:
228
+ chef-server:
229
+ manage:
230
+ )
231
+ nodes_config = %Q(
232
+ nodes:
233
+ chef_server_url: https://chef.lxc/organizations/demo
234
+ validation_client_name: demo-validator
235
+ # comment out or remove the validation_key path to use chef-server keys generated by dev-lxc
236
+ validation_key: # /path/for/ORG-validator.pem
237
+ servers:
238
+ node-1.lxc:
239
+ products:
240
+ chef:
241
+ )
242
+ config = ""
243
+ config += header unless options[:append]
244
+ config += chef_config if options[:chef]
245
+ config += chef_tier_config if options[:chef_tier]
246
+ config += analytics_config if options[:analytics]
247
+ config += compliance_config if options[:compliance]
248
+ config += supermarket_config if options[:supermarket]
249
+ config += automate_config if options[:automate]
250
+ config += build_nodes_config if options[:build_nodes]
251
+ config += runners_config if options[:runners]
252
+ config += adhoc_config if options[:adhoc]
253
+ config += chef_backend_config if options[:chef_backend]
254
+ config += nodes_config if options[:nodes]
255
+ if options[:filename]
256
+ mode = options[:append] ? 'a' : 'w'
257
+ IO.write(options[:filename], config, mode: mode)
258
+ else
259
+ puts config
260
+ end
261
+ end
262
+
263
+ desc "status [SERVER_NAME_REGEX]", "Show status of servers"
264
+ option :config, :desc => "Specify a cluster's YAML config file. `./dev-lxc.yml` will be used by default"
265
+ def status(server_name_regex=nil)
266
+ cluster = get_cluster(options[:config])
267
+ if cluster.config['chef-server'][:topology] == "tier" && cluster.config['chef-server'][:fqdn]
268
+ printf "Chef Server FQDN: %s\n\n", cluster.config['chef-server'][:fqdn]
269
+ end
270
+ if cluster.config['chef-backend'][:fqdn]
271
+ printf "Chef Server FQDN: %s\n\n", cluster.config['chef-backend'][:fqdn]
272
+ end
273
+ if cluster.config['analytics'][:topology] == "tier" && cluster.config['analytics'][:fqdn]
274
+ printf "Analytics FQDN: %s\n\n", cluster.config['analytics'][:fqdn]
275
+ end
276
+ servers = Array.new
277
+ cluster.get_sorted_servers(server_name_regex).map { |s| servers << s.status }
278
+ max_server_name_length = servers.max_by { |s| s['name'].length }['name'].length unless servers.empty?
279
+ servers.each_with_index do |s, server_index|
280
+ printf "%-#{max_server_name_length}s %-15s %s\n", s['name'], s['state'].upcase, s['ip_addresses']
281
+ server = cluster.get_server(s['name'])
282
+ server.snapshot_list.each do |snapname, snaptime, snap_comment|
283
+ printf " |_ %s %s %s\n", snapname, snaptime, snap_comment
284
+ end
285
+ puts if server_index + 1 < servers.length
286
+ end
287
+ end
288
+
289
+ desc "attach [SERVER_NAME_REGEX]", "Attach the terminal to a single server"
290
+ option :config, :desc => "Specify a cluster's YAML config file. `./dev-lxc.yml` will be used by default"
291
+ def attach(server_name_regex)
292
+ servers = get_cluster(options[:config]).get_sorted_servers(server_name_regex)
293
+ if servers.length > 1
294
+ puts "ERROR: The following servers matched '#{server_name_regex}'"
295
+ servers.map { |s| puts " #{s.name}" }
296
+ puts " Please specify a single server to attach to"
297
+ exit 1
298
+ elsif servers.empty?
299
+ puts "ERROR: No servers matched '#{server_name_regex}'"
300
+ puts " Please specify a single server to attach to"
301
+ exit 1
302
+ end
303
+ container = servers.first.container
304
+ if !container.defined? || !container.running?
305
+ puts "ERROR: Server '#{container.name}' is not running"
306
+ exit 1
307
+ end
308
+ attach_opts = {
309
+ wait: true,
310
+ env_policy: LXC::LXC_ATTACH_CLEAR_ENV,
311
+ extra_env_vars: ["LANG=en_US.UTF-8", "TERM=linux", "HOME=#{ENV['HOME']}"]
312
+ }
313
+ shell = ENV['SHELL']
314
+ container.attach(attach_opts) { system(shell) }
315
+ end
316
+
317
+ desc "chef-repo", "Creates a chef-repo in the current directory using files from the cluster's backend /root/chef-repo"
318
+ option :config, :desc => "Specify a cluster's YAML config file. `./dev-lxc.yml` will be used by default"
319
+ option :force, :aliases => "-f", :type => :boolean, :desc => "Overwrite any existing knife.rb or pivotal.rb files"
320
+ option :pivotal, :aliases => "-p", :type => :boolean, :desc => "Also copy pivotal.rb and pivotal.pem"
321
+ def chef_repo
322
+ get_cluster(options[:config]).chef_repo(options[:force], options[:pivotal])
323
+ end
324
+
325
+ desc "print-automate-credentials", "Print Automate credentials"
326
+ option :config, :desc => "Specify a cluster's YAML config file. `./dev-lxc.yml` will be used by default"
327
+ def print_automate_credentials
328
+ get_cluster(options[:config]).print_automate_credentials
329
+ end
330
+
331
+ desc "run-command [SERVER_NAME_REGEX] [COMMAND]", "Runs a command in each server"
332
+ option :config, :desc => "Specify a cluster's YAML config file. `./dev-lxc.yml` will be used by default"
333
+ def run_command(server_name_regex=nil, command)
334
+ start_time = Time.now
335
+ get_cluster(options[:config]).get_sorted_servers(server_name_regex).each { |s| s.run_command(command); puts }
336
+ print_elapsed_time(Time.now - start_time)
337
+ end
338
+
339
+ desc "prepare-product-cache [SERVER_NAME_REGEX]", "Download required product packages to cache"
340
+ option :config, :desc => "Specify a cluster's YAML config file. `./dev-lxc.yml` will be used by default"
341
+ def prepare_product_cache(server_name_regex=nil)
342
+ start_time = Time.now
343
+ cluster = get_cluster(options[:config])
344
+ servers = cluster.get_sorted_servers(server_name_regex)
345
+ cluster.prep_product_cache(servers, true)
346
+ print_elapsed_time(Time.now - start_time)
347
+ end
348
+
349
+ desc "up [SERVER_NAME_REGEX]", "Start servers - This is the default if no subcommand is given"
350
+ option :config, :desc => "Specify a cluster's YAML config file. `./dev-lxc.yml` will be used by default"
351
+ def up(server_name_regex=nil)
352
+ start_time = Time.now
353
+ get_cluster(options[:config]).up(server_name_regex)
354
+ print_elapsed_time(Time.now - start_time)
355
+ end
356
+
357
+ desc "halt [SERVER_NAME_REGEX]", "Shutdown servers"
358
+ option :config, :desc => "Specify a cluster's YAML config file. `./dev-lxc.yml` will be used by default"
359
+ def halt(server_name_regex=nil)
360
+ start_time = Time.now
361
+ get_cluster(options[:config]).halt(server_name_regex)
362
+ print_elapsed_time(Time.now - start_time)
363
+ end
364
+
365
+ desc "snapshot [SERVER_NAME_REGEX]", "Manage a cluster's snapshots"
366
+ option :comment, :aliases => "-c", :desc => "Add snapshot comment"
367
+ option :config, :desc => "Specify a cluster's YAML config file. `./dev-lxc.yml` will be used by default"
368
+ option :destroy, :aliases => "-d", :desc => "Destroy snapshot - use ALL to destroy all snapshots"
369
+ option :list, :aliases => "-l", :type => :boolean, :desc => "List snapshots"
370
+ option :restore, :aliases => "-r", :desc => "Restore snapshots"
371
+ def snapshot(server_name_regex=nil)
372
+ start_time = Time.now
373
+ servers = get_cluster(options[:config]).get_sorted_servers(server_name_regex)
374
+ if options[:list]
375
+ servers.each_with_index do |s, server_index|
376
+ puts s.name
377
+ s.snapshot_list.each do |snapname, snaptime, snap_comment|
378
+ printf " |_ %s %s %s\n", snapname, snaptime, snap_comment
379
+ end
380
+ puts if server_index + 1 < servers.length
381
+ end
382
+ return
383
+ elsif options[:destroy]
384
+ snapname = options[:destroy] == 'destroy' ? "LAST" : options[:destroy]
385
+ servers.each { |s| s.snapshot_destroy(snapname); puts }
386
+ elsif options[:restore]
387
+ running_servers = Array.new
388
+ servers.each do |s|
389
+ running_servers << s.name if s.container.running?
390
+ end
391
+ unless running_servers.empty?
392
+ puts "ERROR: Aborting snapshot restore because the following servers are running"
393
+ puts running_servers
394
+ exit 1
395
+ end
396
+ snapname = options[:restore] == 'restore' ? "LAST" : options[:restore]
397
+ servers.each { |s| s.snapshot_restore(snapname); puts }
398
+ else
399
+ running_servers = Array.new
400
+ servers.each do |s|
401
+ running_servers << s.name if s.container.running?
402
+ end
403
+ unless running_servers.empty?
404
+ puts "ERROR: Aborting snapshot because the following servers are running"
405
+ puts running_servers
406
+ exit 1
407
+ end
408
+ servers.each { |s| s.snapshot(options[:comment]); puts }
409
+ end
410
+ print_elapsed_time(Time.now - start_time)
411
+ end
412
+
413
+ desc "destroy [SERVER_NAME_REGEX]", "Destroy servers"
414
+ option :config, :desc => "Specify a cluster's YAML config file. `./dev-lxc.yml` will be used by default"
415
+ option :force, :aliases => "-f", :type => :boolean, :desc => "Destroy servers without confirmation"
416
+ def destroy(server_name_regex=nil)
417
+ servers = get_cluster(options[:config]).get_sorted_servers(server_name_regex)
418
+ if servers.empty?
419
+ puts "No matching server names were found"
420
+ exit
421
+ end
422
+ unless options[:force]
423
+ confirmation_string = String.new
424
+ servers.reverse_each { |s| confirmation_string += "#{s.name}\n" }
425
+ confirmation_string += "Are you sure you want to destroy these servers? (y/N)\n"
426
+ return unless yes?(confirmation_string)
427
+ end
428
+ start_time = Time.now
429
+ get_cluster(options[:config]).destroy(server_name_regex)
430
+ print_elapsed_time(Time.now - start_time)
431
+ end
432
+
433
+ end
434
+ end