elecksee 1.0.22 → 1.1.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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +10 -0
- data/CONTRIBUTING.md +25 -0
- data/README.md +43 -6
- data/elecksee.gemspec +3 -3
- data/lib/elecksee/clone.rb +47 -16
- data/lib/elecksee/ephemeral.rb +65 -15
- data/lib/elecksee/helpers/copies.rb +36 -5
- data/lib/elecksee/helpers/options.rb +29 -3
- data/lib/elecksee/{helpers/base.rb → helpers.rb} +115 -56
- data/lib/elecksee/lxc.rb +204 -82
- data/lib/elecksee/lxc_file_config.rb +26 -0
- data/lib/elecksee/storage/overlay_directory.rb +68 -37
- data/lib/elecksee/storage/overlay_mount.rb +80 -45
- data/lib/elecksee/storage/virtual_device.rb +104 -60
- data/lib/elecksee/storage.rb +13 -0
- data/lib/elecksee/version.rb +2 -1
- data/lib/elecksee.rb +13 -0
- metadata +26 -33
- data/Gemfile +0 -5
- data/Gemfile.lock +0 -22
- data/lib/elecksee/knife/config.rb +0 -37
data/lib/elecksee/lxc.rb
CHANGED
@@ -1,8 +1,9 @@
|
|
1
|
-
require 'elecksee
|
1
|
+
require 'elecksee'
|
2
2
|
require 'securerandom'
|
3
3
|
require 'shellwords'
|
4
4
|
require 'pathname'
|
5
5
|
require 'tmpdir'
|
6
|
+
require 'rye'
|
6
7
|
|
7
8
|
class Lxc
|
8
9
|
|
@@ -10,6 +11,10 @@ class Lxc
|
|
10
11
|
# begin with '/', and that's dumb. So we'll make our own Pathname,
|
11
12
|
# with a #join that uses File
|
12
13
|
class Pathname < ::Pathname
|
14
|
+
# Join arguments using ::File.join
|
15
|
+
#
|
16
|
+
# @param args [String] argument list
|
17
|
+
# @return [String]
|
13
18
|
def join(*args)
|
14
19
|
self.class.new(::File.join(self.to_path, *args))
|
15
20
|
end
|
@@ -17,16 +22,39 @@ class Lxc
|
|
17
22
|
|
18
23
|
include Helpers
|
19
24
|
|
20
|
-
|
25
|
+
# @return [String] name of container
|
26
|
+
attr_reader :name
|
27
|
+
# @return [String] base path of container
|
28
|
+
attr_reader :base_path
|
29
|
+
# @return [String] path to dnsmasq lease file
|
30
|
+
attr_reader :lease_file
|
31
|
+
# @return [String] network device to use for ssh connection
|
32
|
+
attr_reader :preferred_device
|
33
|
+
# @return [String, NilClass] path to default ssh key
|
34
|
+
attr_accessor :ssh_key
|
35
|
+
# @return [String, NilClass] ssh password
|
36
|
+
attr_accessor :ssh_password
|
37
|
+
# @return [String, NilClass] ssh user
|
38
|
+
attr_accessor :ssh_user
|
21
39
|
|
22
40
|
class << self
|
23
41
|
|
24
42
|
include Helpers
|
25
43
|
|
44
|
+
# @return [Truthy, String] use sudo when required (set to string for custom sudo command)
|
26
45
|
attr_accessor :use_sudo
|
46
|
+
# @return [String] base path for containers
|
27
47
|
attr_accessor :base_path
|
48
|
+
# @return [Symbol] :mixlib_shellout or :childprocess
|
28
49
|
attr_accessor :shellout_helper
|
29
|
-
|
50
|
+
# @return [String, NilClass] path to default ssh key
|
51
|
+
attr_accessor :default_ssh_key
|
52
|
+
# @return [String, NilClass] default ssh password
|
53
|
+
attr_accessor :default_ssh_password
|
54
|
+
# @return [String, NilClass] default ssh user
|
55
|
+
attr_accessor :default_ssh_user
|
56
|
+
|
57
|
+
# @return [String] sudo command
|
30
58
|
def sudo
|
31
59
|
case use_sudo
|
32
60
|
when TrueClass
|
@@ -36,44 +64,56 @@ class Lxc
|
|
36
64
|
end
|
37
65
|
end
|
38
66
|
|
67
|
+
# @return [String] base path for containers
|
39
68
|
def base_path
|
40
69
|
@base_path || '/var/lib/lxc'
|
41
70
|
end
|
42
71
|
|
43
|
-
#
|
72
|
+
# Currently running container names
|
73
|
+
#
|
74
|
+
# @return [Array<String>]
|
44
75
|
def running
|
45
76
|
full_list[:running]
|
46
77
|
end
|
47
78
|
|
48
|
-
#
|
79
|
+
# Currently stopped container names
|
80
|
+
#
|
81
|
+
# @return [Array<String>]
|
49
82
|
def stopped
|
50
83
|
full_list[:stopped]
|
51
84
|
end
|
52
85
|
|
53
|
-
#
|
86
|
+
# Currently frozen container names
|
87
|
+
#
|
88
|
+
# @return [Array<String>]
|
54
89
|
def frozen
|
55
90
|
full_list[:frozen]
|
56
91
|
end
|
57
92
|
|
58
|
-
#
|
59
|
-
#
|
93
|
+
# Container currently exists
|
94
|
+
#
|
95
|
+
# @param name [String] name of container
|
96
|
+
# @return [TrueClass, FalseClass]
|
60
97
|
def exists?(name)
|
61
98
|
list.include?(name)
|
62
99
|
end
|
63
100
|
|
64
|
-
# List of containers
|
101
|
+
# List of all containers
|
102
|
+
#
|
103
|
+
# @return [Array<String>] container names
|
65
104
|
def list
|
66
|
-
|
67
|
-
|
68
|
-
File.basename(item)
|
69
|
-
end
|
70
|
-
end.compact
|
105
|
+
run_command('lxc-ls', :sudo => true).
|
106
|
+
stdout.split(/\s/).map(&:strip).compact
|
71
107
|
end
|
72
108
|
|
73
|
-
#
|
74
|
-
#
|
109
|
+
# Information available for given container
|
110
|
+
#
|
111
|
+
# @param name [String] name of container
|
112
|
+
# @return [Hash]
|
75
113
|
def info(name)
|
76
|
-
|
114
|
+
if(exists?(name))
|
115
|
+
info = run_command("#{sudo}lxc-info -n #{name}", :allow_failure_retry => 3, :allow_failure => true)
|
116
|
+
end
|
77
117
|
if(info)
|
78
118
|
Hash[
|
79
119
|
info.stdout.split("\n").map do |string|
|
@@ -93,7 +133,9 @@ class Lxc
|
|
93
133
|
end
|
94
134
|
end
|
95
135
|
|
96
|
-
#
|
136
|
+
# Full list of containers grouped by state
|
137
|
+
#
|
138
|
+
# @return [Hash]
|
97
139
|
def full_list
|
98
140
|
res = {}
|
99
141
|
list.each do |item|
|
@@ -104,51 +146,69 @@ class Lxc
|
|
104
146
|
res
|
105
147
|
end
|
106
148
|
|
107
|
-
#
|
108
|
-
#
|
149
|
+
# IP address is currently active
|
150
|
+
#
|
151
|
+
# @param ip [String]
|
152
|
+
# @return [TrueClass, FalseClass]
|
109
153
|
def connection_alive?(ip)
|
110
154
|
%x{ping -c 1 -W 1 #{ip}}
|
111
155
|
$?.exitstatus == 0
|
112
156
|
end
|
113
157
|
end
|
114
158
|
|
115
|
-
#
|
116
|
-
#
|
117
|
-
#
|
118
|
-
#
|
119
|
-
#
|
159
|
+
# Create new instance
|
160
|
+
#
|
161
|
+
# @param name [String] container name
|
162
|
+
# @param args [Hash]
|
163
|
+
# @option args [String] :base_path path to container
|
164
|
+
# @option args [String] :dnsmasq_lease_file path to lease file
|
165
|
+
# @option args [String] :net_device network device within container for ssh connection
|
166
|
+
# @option args [String] :ssh_key path to ssh key
|
167
|
+
# @option args [String] :ssh_password ssh password
|
168
|
+
# @option args [String] :ssh_user ssh user
|
120
169
|
def initialize(name, args={})
|
121
170
|
@name = name
|
122
171
|
@base_path = args[:base_path] || self.class.base_path
|
123
172
|
@lease_file = args[:dnsmasq_lease_file] || '/var/lib/misc/dnsmasq.leases'
|
124
173
|
@preferred_device = args[:net_device]
|
174
|
+
@ssh_key = args.fetch(:ssh_key, self.class.default_ssh_key)
|
175
|
+
@ssh_password = args.fetch(:ssh_password, self.class.default_ssh_password)
|
176
|
+
@ssh_user = args.fetch(:ssh_user, self.class.default_ssh_user)
|
125
177
|
end
|
126
178
|
|
127
|
-
#
|
179
|
+
# @return [TrueClass, FalseClass] container exists
|
128
180
|
def exists?
|
129
181
|
self.class.exists?(name)
|
130
182
|
end
|
131
183
|
|
132
|
-
#
|
184
|
+
# @return [TrueClass, FalseClass] container is currently running
|
133
185
|
def running?
|
134
186
|
self.class.info(name)[:state] == :running
|
135
187
|
end
|
136
188
|
|
137
|
-
#
|
189
|
+
# @return [TrueClass, FalseClass] container is currently stopped
|
138
190
|
def stopped?
|
139
191
|
self.class.info(name)[:state] == :stopped
|
140
192
|
end
|
141
193
|
|
142
|
-
#
|
194
|
+
# @return [TrueClass, FalseClass] container is currently frozen
|
143
195
|
def frozen?
|
144
196
|
self.class.info(name)[:state] == :frozen
|
145
197
|
end
|
146
198
|
|
147
|
-
#
|
148
|
-
#
|
199
|
+
# Current IP address of container
|
200
|
+
#
|
201
|
+
# @param retries [Integer] number of times to retry discovery
|
202
|
+
# @param raise_on_fail [TrueClass, FalseClass] raise exception on failure
|
203
|
+
# @return [String, NilClass] IP address
|
204
|
+
# @note retries are executed on 3 second sleep intervals
|
149
205
|
def container_ip(retries=0, raise_on_fail=false)
|
150
206
|
(retries.to_i + 1).times do
|
151
|
-
ip =
|
207
|
+
ip = info_detected_address ||
|
208
|
+
proc_detected_address ||
|
209
|
+
hw_detected_address ||
|
210
|
+
leased_address ||
|
211
|
+
lxc_stored_address
|
152
212
|
if(ip.is_a?(Array))
|
153
213
|
# Filter any found loopbacks
|
154
214
|
ip.delete_if{|info| info[:device].start_with?('lo') }
|
@@ -168,7 +228,9 @@ class Lxc
|
|
168
228
|
raise "Failed to detect live IP address for container: #{name}" if raise_on_fail
|
169
229
|
end
|
170
230
|
|
171
|
-
# Container address
|
231
|
+
# Container address defined within the container's config file
|
232
|
+
#
|
233
|
+
# @return [String, NilClass] IP address
|
172
234
|
def lxc_stored_address
|
173
235
|
if(File.exists?(container_config))
|
174
236
|
ip = File.readlines(container_config).detect{|line|
|
@@ -183,7 +245,9 @@ class Lxc
|
|
183
245
|
end
|
184
246
|
end
|
185
247
|
|
186
|
-
# Container address via dnsmasq lease
|
248
|
+
# Container address discovered via dnsmasq lease
|
249
|
+
#
|
250
|
+
# @return [String, NilClass] IP address
|
187
251
|
def leased_address
|
188
252
|
ip = nil
|
189
253
|
if(File.exists?(@lease_file))
|
@@ -202,6 +266,16 @@ class Lxc
|
|
202
266
|
end
|
203
267
|
end
|
204
268
|
|
269
|
+
# Container address discovered via info
|
270
|
+
#
|
271
|
+
# @return [String, NilClass] IP address
|
272
|
+
def info_detected_address
|
273
|
+
self.class.info(name)[:ip]
|
274
|
+
end
|
275
|
+
|
276
|
+
# Container address discovered via device
|
277
|
+
#
|
278
|
+
# @return [String, NilClass] IP address
|
205
279
|
def hw_detected_address
|
206
280
|
if(container_config.readable?)
|
207
281
|
hw = File.readlines(container_config).detect{|line|
|
@@ -222,6 +296,10 @@ class Lxc
|
|
222
296
|
end
|
223
297
|
end
|
224
298
|
|
299
|
+
# Container address discovered via process
|
300
|
+
#
|
301
|
+
# @param base [String] path to netns
|
302
|
+
# @return [String, NilClass] IP address
|
225
303
|
def proc_detected_address(base='/run/netns')
|
226
304
|
if(pid != -1)
|
227
305
|
Dir.mktmpdir do |t_dir|
|
@@ -240,18 +318,19 @@ class Lxc
|
|
240
318
|
end
|
241
319
|
end
|
242
320
|
|
243
|
-
#
|
321
|
+
# @return [Pathname] path to container
|
244
322
|
def container_path
|
245
323
|
Pathname.new(@base_path).join(name)
|
246
324
|
end
|
247
325
|
alias_method :path, :container_path
|
248
326
|
|
249
|
-
#
|
327
|
+
# @return [Pathname] path to configuration file
|
250
328
|
def container_config
|
251
329
|
container_path.join('config')
|
252
330
|
end
|
253
331
|
alias_method :config, :container_config
|
254
332
|
|
333
|
+
# @return [Pathname] path to rootfs
|
255
334
|
def container_rootfs
|
256
335
|
if(File.exists?(config))
|
257
336
|
r_path = File.readlines(config).detect do |line|
|
@@ -262,19 +341,28 @@ class Lxc
|
|
262
341
|
end
|
263
342
|
alias_method :rootfs, :container_rootfs
|
264
343
|
|
344
|
+
# Expand path within containers rootfs
|
345
|
+
#
|
346
|
+
# @param path [String] relative path
|
347
|
+
# @return [Pathname] full path within container
|
265
348
|
def expand_path(path)
|
266
349
|
container_rootfs.join(path)
|
267
350
|
end
|
268
351
|
|
352
|
+
# @return [Symbol] current state
|
269
353
|
def state
|
270
354
|
self.class.info(name)[:state]
|
271
355
|
end
|
272
356
|
|
357
|
+
# @return [Integer, Symbol] process ID or :unknown
|
273
358
|
def pid
|
274
359
|
self.class.info(name)[:pid]
|
275
360
|
end
|
276
361
|
|
277
362
|
# Start the container
|
363
|
+
#
|
364
|
+
# @param args [Symbol] argument list (:no_daemon to foreground)
|
365
|
+
# @return [self]
|
278
366
|
def start(*args)
|
279
367
|
if(args.include?(:no_daemon))
|
280
368
|
run_command("lxc-start -n #{name}", :sudo => true)
|
@@ -282,52 +370,73 @@ class Lxc
|
|
282
370
|
run_command("lxc-start -n #{name} -d", :sudo => true)
|
283
371
|
wait_for_state(:running)
|
284
372
|
end
|
373
|
+
self
|
285
374
|
end
|
286
375
|
|
287
376
|
# Stop the container
|
377
|
+
#
|
378
|
+
# @return [self]
|
288
379
|
def stop
|
289
380
|
run_command("lxc-stop -n #{name}", :allow_failure_retry => 3, :sudo => true)
|
290
381
|
wait_for_state(:stopped)
|
382
|
+
self
|
291
383
|
end
|
292
384
|
|
293
385
|
# Freeze the container
|
386
|
+
#
|
387
|
+
# @return [self]
|
294
388
|
def freeze
|
295
389
|
run_command("lxc-freeze -n #{name}", :sudo => true)
|
296
390
|
wait_for_state(:frozen)
|
391
|
+
self
|
297
392
|
end
|
298
393
|
|
299
394
|
# Unfreeze the container
|
395
|
+
#
|
396
|
+
# @return [self]
|
300
397
|
def unfreeze
|
301
398
|
run_command("lxc-unfreeze -n #{name}", :sudo => true)
|
302
399
|
wait_for_state(:running)
|
400
|
+
self
|
303
401
|
end
|
304
402
|
|
305
403
|
# Shutdown the container
|
404
|
+
#
|
405
|
+
# @return [self]
|
306
406
|
def shutdown
|
307
|
-
run_command("lxc-shutdown -n #{name}", :sudo => true)
|
308
|
-
wait_for_state(:stopped, :timeout => 120)
|
309
407
|
# This block is for fedora/centos/anyone else that does not like lxc-shutdown
|
310
408
|
if(running?)
|
311
409
|
container_command('shutdown -h now')
|
312
410
|
wait_for_state(:stopped, :timeout => 120)
|
313
411
|
# If still running here, something is wrong
|
314
412
|
if(running?)
|
315
|
-
|
413
|
+
run_command("lxc-stop -n #{name}", :sudo => true)
|
414
|
+
wait_for_state(:stopped, :timeout => 120)
|
415
|
+
if(running?)
|
416
|
+
raise "Failed to shutdown container: #{name}"
|
417
|
+
end
|
316
418
|
end
|
317
419
|
end
|
420
|
+
self
|
318
421
|
end
|
319
422
|
|
320
423
|
# Destroy the container
|
424
|
+
#
|
425
|
+
# @return [self]
|
321
426
|
def destroy
|
322
427
|
unless stopped?
|
323
428
|
stop
|
324
429
|
end
|
325
430
|
run_command("lxc-destroy -n #{name}", :sudo => true)
|
431
|
+
self
|
326
432
|
end
|
327
433
|
|
328
|
-
#
|
329
|
-
#
|
330
|
-
#
|
434
|
+
# Execute command within the container
|
435
|
+
#
|
436
|
+
# @param command [String] command to execute
|
437
|
+
# @param opts [Hash] options passed to #tmp_execute_script
|
438
|
+
# @return [CommandResult]
|
439
|
+
# @note container must be stopped
|
331
440
|
def execute(command, opts={})
|
332
441
|
if(stopped?)
|
333
442
|
cmd = Shellwords.split(command)
|
@@ -347,22 +456,47 @@ class Lxc
|
|
347
456
|
end
|
348
457
|
end
|
349
458
|
|
459
|
+
# Execute command within running container
|
460
|
+
#
|
461
|
+
# @param command [String]
|
462
|
+
# @param args [Hash]
|
463
|
+
# @option args [Integer] :timeout
|
464
|
+
# @option args [TrueClass, FalseClass] :live_stream
|
465
|
+
# @option args [TrueClass, FalseClass] :raise_on_failure
|
466
|
+
# @return [CommandResult]
|
350
467
|
def direct_container_command(command, args={})
|
351
468
|
begin
|
352
|
-
|
353
|
-
|
354
|
-
:
|
355
|
-
:
|
356
|
-
:
|
469
|
+
box = Rye::Box.new(
|
470
|
+
args.fetch(:ip, container_ip(3)),
|
471
|
+
:user => ssh_user,
|
472
|
+
:password => ssh_password,
|
473
|
+
:password_prompt => false,
|
474
|
+
:keys => [ssh_key],
|
475
|
+
:safe => false,
|
476
|
+
:paranoid => false
|
357
477
|
)
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
478
|
+
result = box.execute command
|
479
|
+
CommandResult.new(result)
|
480
|
+
rescue Rye::Err => e
|
481
|
+
if(args[:raise_on_failure])
|
482
|
+
raise CommandFailed.new(
|
483
|
+
"Command failed: #{command}",
|
484
|
+
CommandResult.new(e)
|
485
|
+
)
|
486
|
+
else
|
487
|
+
false
|
488
|
+
end
|
362
489
|
end
|
363
490
|
end
|
364
491
|
alias_method :knife_container, :direct_container_command
|
365
492
|
|
493
|
+
# Wait for container to reach given state
|
494
|
+
#
|
495
|
+
# @param desired_state [Symbol]
|
496
|
+
# @param args [Hash]
|
497
|
+
# @option args [Integer] :timeout
|
498
|
+
# @option args [Numeric] :sleep_interval
|
499
|
+
# @return [self]
|
366
500
|
def wait_for_state(desired_state, args={})
|
367
501
|
args[:sleep_interval] ||= 1.0
|
368
502
|
wait_total = 0.0
|
@@ -370,10 +504,18 @@ class Lxc
|
|
370
504
|
sleep(args[:sleep_interval])
|
371
505
|
wait_total += args[:sleep_interval]
|
372
506
|
end
|
507
|
+
self
|
373
508
|
end
|
374
509
|
|
375
|
-
#
|
376
|
-
#
|
510
|
+
# Write command to temporary file with networking enablement wrapper
|
511
|
+
# and yield relative path
|
512
|
+
#
|
513
|
+
# @param command [String]
|
514
|
+
# @param opts [Hash]
|
515
|
+
# @options opts [TrueClass, FalseClass] enable networking
|
516
|
+
# @yield block to execute
|
517
|
+
# @yieldparam command_script [String] path to file
|
518
|
+
# @return [Object] result of block
|
377
519
|
def tmp_execute_script(command, opts)
|
378
520
|
script_path = "tmp/#{SecureRandom.uuid}"
|
379
521
|
File.open(rootfs.join(script_path), 'w') do |file|
|
@@ -400,23 +542,12 @@ EOS
|
|
400
542
|
end
|
401
543
|
end
|
402
544
|
|
403
|
-
#
|
404
|
-
#
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
home = File.directory?('/root') && File.writable?('/root') ? '/root' : '/tmp'
|
410
|
-
if(set_if_missing)
|
411
|
-
ENV['HOME'] = home
|
412
|
-
end
|
413
|
-
home
|
414
|
-
end
|
415
|
-
end
|
416
|
-
|
417
|
-
# cmd:: Shell command string
|
418
|
-
# retries:: Number of retry attempts (1 second sleep interval)
|
419
|
-
# Runs command in container via ssh
|
545
|
+
# Run command within container
|
546
|
+
#
|
547
|
+
# @param cmd [String] command to run
|
548
|
+
# @param retries [Integer] number of retry attempts
|
549
|
+
# @return [CommandResult]
|
550
|
+
# @note retries are over 1 second intervals
|
420
551
|
def container_command(cmd, retries=1)
|
421
552
|
begin
|
422
553
|
detect_home(true)
|
@@ -438,18 +569,9 @@ EOS
|
|
438
569
|
end
|
439
570
|
end
|
440
571
|
|
441
|
-
def log
|
442
|
-
if(defined?(Chef))
|
443
|
-
Chef::Log
|
444
|
-
else
|
445
|
-
unless(@logger)
|
446
|
-
require 'logger'
|
447
|
-
@logger = Logger.new('/dev/null')
|
448
|
-
end
|
449
|
-
@logger
|
450
|
-
end
|
451
|
-
end
|
452
|
-
|
453
572
|
end
|
454
573
|
|
574
|
+
# Make default settings
|
455
575
|
Lxc.shellout_helper = :mixlib_shellout
|
576
|
+
Lxc.default_ssh_key = '/opt/hw-lxc-config/id_rsa'
|
577
|
+
Lxc.default_ssh_user = 'root'
|
@@ -1,11 +1,21 @@
|
|
1
|
+
require 'elecksee'
|
2
|
+
|
1
3
|
class Lxc
|
4
|
+
# Configuration file interface
|
2
5
|
class FileConfig
|
3
6
|
|
7
|
+
# @return [Array]
|
4
8
|
attr_reader :network
|
9
|
+
# @return [String] path to configuration file
|
5
10
|
attr_reader :base
|
6
11
|
|
7
12
|
class << self
|
8
13
|
|
14
|
+
# Convert object to Hash if possible
|
15
|
+
#
|
16
|
+
# @param thing [Object]
|
17
|
+
# @return [Hash]
|
18
|
+
# @note used mostly for the lxc resource within chef
|
9
19
|
def convert_to_hash(thing)
|
10
20
|
if(defined?(Chef) && thing.is_a?(Chef::Resource))
|
11
21
|
result = Hash[*(
|
@@ -26,6 +36,10 @@ class Lxc
|
|
26
36
|
result || thing
|
27
37
|
end
|
28
38
|
|
39
|
+
# Symbolize keys within hash
|
40
|
+
#
|
41
|
+
# @param thing [Hashish]
|
42
|
+
# @return [Hash]
|
29
43
|
def symbolize_hash(thing)
|
30
44
|
if(defined?(Mash))
|
31
45
|
Mash.new(thing)
|
@@ -38,6 +52,10 @@ class Lxc
|
|
38
52
|
end
|
39
53
|
end
|
40
54
|
|
55
|
+
# Generate configuration file contents
|
56
|
+
#
|
57
|
+
# @param resource [Hashish]
|
58
|
+
# @return [String]
|
41
59
|
def generate_config(resource)
|
42
60
|
resource = symbolize_hash(convert_to_hash(resource))
|
43
61
|
config = []
|
@@ -79,6 +97,9 @@ class Lxc
|
|
79
97
|
|
80
98
|
end
|
81
99
|
|
100
|
+
# Create new instance
|
101
|
+
#
|
102
|
+
# @param path [String]
|
82
103
|
def initialize(path)
|
83
104
|
raise 'LXC config file not found' unless File.exists?(path)
|
84
105
|
@path = path
|
@@ -89,6 +110,9 @@ class Lxc
|
|
89
110
|
|
90
111
|
private
|
91
112
|
|
113
|
+
# Parse the configuration file
|
114
|
+
#
|
115
|
+
# @return [TrueClass]
|
92
116
|
def parse!
|
93
117
|
cur_net = nil
|
94
118
|
File.readlines(@path).each do |line|
|
@@ -115,6 +139,8 @@ class Lxc
|
|
115
139
|
end
|
116
140
|
end
|
117
141
|
@network << cur_net if cur_net
|
142
|
+
true
|
118
143
|
end
|
144
|
+
|
119
145
|
end
|
120
146
|
end
|