lxd-common 0.4.1 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 357a631e4d4f57d4da40fa8fd0be107475fe5884
4
- data.tar.gz: dbe4e06ab24215c9a33a05945d43b87b410e4d1b
3
+ metadata.gz: 3ca7ef26b1a5f3811c395b2c90ab29bf5f0e8127
4
+ data.tar.gz: 56e6fd7f480fd6278bb011ba1052bebcea703172
5
5
  SHA512:
6
- metadata.gz: 4ce7ae30122190b280fcbc337d6c0d822f55529e1a854132add4eb098a6d2808b87ed0534ad704710e928c31a9849d8b45323ac2037d1c11beb2f1c4190a937c
7
- data.tar.gz: 5c18e9da89372e41c6484a88f9118ba0d9f555a636361ad7c84c1ad720610135c25a592f51cdc0254e2e0e7f751a34e0d635497c4b207e58d1e1454e854687ac
6
+ metadata.gz: c2719010fc06f675be0ae6c8720ecb5144119f962a4be36392a4b8e9c404532f784c81a3a3ef237a761d5cb70ca2dea2b8cf3afd3c7f6a62dfce11724d56b311
7
+ data.tar.gz: ffccf9fa39e661c337be6e04145da71dda189612db57fb87e21aba68e185e97f476af06e0f5b84517b5a4547b3e89436f61d0afea5277d5e1b20e66170a938eb
@@ -1,3 +1,5 @@
1
+ require 'nexussw/lxd/driver/mixins/helpers/wait'
2
+ require 'nexussw/lxd/transport/cli'
1
3
  require 'tempfile'
2
4
  require 'yaml'
3
5
  require 'json'
@@ -14,6 +16,10 @@ module NexusSW
14
16
 
15
17
  attr_reader :inner_transport, :driver_options
16
18
 
19
+ def transport_for(container_name)
20
+ Transport::CLI.new inner_transport, container_name, info: YAML.load(inner_transport.execute('lxc info').error!.stdout)
21
+ end
22
+
17
23
  def create_container(container_name, container_options = {})
18
24
  if container_exists? container_name
19
25
  start_container container_name # Start for Parity with the below logic (`lxc launch` auto starts)
@@ -109,7 +115,7 @@ module NexusSW
109
115
  false
110
116
  end
111
117
 
112
- include WaitMixin
118
+ include Helpers::WaitMixin
113
119
 
114
120
  protected
115
121
 
@@ -0,0 +1,39 @@
1
+ module NexusSW
2
+ module LXD
3
+ class Driver
4
+ module Mixins
5
+ module Helpers
6
+ module WaitMixin
7
+ def check_for_ip(driver, container_name)
8
+ cc = driver.container(container_name)
9
+ state = driver.container_state(container_name)
10
+ cc[:expanded_devices].each do |nic, data|
11
+ next unless data[:type] == 'nic'
12
+ state[:network][nic][:addresses].each do |address|
13
+ return address[:address] if address[:family] == 'inet' && address[:address] && !address[:address].empty?
14
+ end
15
+ end
16
+ nil
17
+ end
18
+
19
+ def wait_for(container_name, what, timeout = 60)
20
+ Timeout.timeout timeout do
21
+ loop do
22
+ retval = nil
23
+ case what
24
+ when :ip
25
+ retval = check_for_ip(self, container_name)
26
+ else
27
+ raise 'unrecognized option'
28
+ end
29
+ return retval if retval
30
+ sleep 0.5
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -1,3 +1,5 @@
1
+ require 'nexussw/lxd/driver/mixins/helpers/wait'
2
+ require 'nexussw/lxd/transport/rest'
1
3
  require 'hyperkit'
2
4
 
3
5
  module NexusSW
@@ -17,19 +19,25 @@ module NexusSW
17
19
  auto_sync: true
18
20
  )
19
21
  @hk = inner_driver || Hyperkit::Client.new(hkoptions)
20
- # HACK: can't otherwise get at the request timeout because sawyer is in the way
21
- # Beware of unused function in hyperkit: reset_agent If that gets used it'll undo this timeout
22
- # unneeded while default valued: @hk.agent.instance_variable_get(:@conn).options[:timeout] = REQUEST_TIMEOUT
23
22
  end
24
23
 
25
24
  attr_reader :hk, :rest_endpoint, :driver_options
26
25
 
26
+ include Helpers::WaitMixin
27
+
28
+ def server_info
29
+ @server_info ||= hk.get('/1.0')[:metadata]
30
+ end
31
+
32
+ def transport_for(container_name)
33
+ Transport::Rest.new container_name, info: server_info, connection: hk, driver_options: driver_options, rest_endpoint: rest_endpoint
34
+ end
35
+
27
36
  def create_container(container_name, container_options = {})
28
37
  if container_exists?(container_name)
29
38
  start_container container_name # Start the container for Parity with the CLI
30
39
  return container_name
31
40
  end
32
- # we'll break this apart and time it out for those with slow net (and this was my 3 minute stress test case with good net)
33
41
  # parity note: CLI will run indefinitely rather than timeout hence the 0 timeout
34
42
  retry_forever do
35
43
  @hk.create_container(container_name, container_options.merge(sync: false))
@@ -48,25 +56,29 @@ module NexusSW
48
56
 
49
57
  def stop_container(container_id, options = {})
50
58
  return if container_status(container_id) == 'stopped'
51
- return @hk.stop_container(container_id, force: true) if options[:force]
52
- last_id = nil
53
- use_last = false
54
- LXD.with_timeout_and_retries({ timeout: 0 }.merge(options)) do # timeout: 0 to enable retry functionality
55
- return if container_status(container_id) == 'stopped'
56
- begin
57
- unless use_last
58
- # Keep resubmitting until the server complains (Stops will be ignored/hang if init is not yet listening for SIGPWR i.e. recently started)
59
- begin
60
- last_id = @hk.stop_container(container_id, sync: false)[:id] # TODO: this 'could' hang for 2 minutes? and then we'd never get a last_id if that's where the hang happens, and then it 'could' error on retry
61
- rescue Hyperkit::BadRequest # Happens if a stop command has previously been accepted as well as other reasons. handle that on next line
62
- raise unless last_id # if we have a last_id then a prior stop command has successfully initiated so we'll just wait on that one
63
- use_last = true
59
+ if options[:force]
60
+ @hk.stop_container(container_id, force: true)
61
+ else
62
+ last_id = nil
63
+ use_last = false
64
+ LXD.with_timeout_and_retries({ timeout: 0 }.merge(options)) do # timeout: 0 to enable retry functionality
65
+ return if container_status(container_id) == 'stopped'
66
+ begin
67
+ unless use_last
68
+ # Keep resubmitting until the server complains (Stops will be ignored/hang if init is not yet listening for SIGPWR i.e. recently started)
69
+ begin
70
+ last_id = @hk.stop_container(container_id, sync: false)[:id]
71
+ rescue Hyperkit::BadRequest # Happens if a stop command has previously been accepted as well as other reasons. handle that on next line
72
+ # if we have a last_id then a prior stop command has successfully initiated so we'll just wait on that one
73
+ raise unless last_id # rubocop:disable Metrics/BlockNesting
74
+ use_last = true
75
+ end
64
76
  end
77
+ @hk.wait_for_operation last_id # , options[:retry_interval]
78
+ rescue Faraday::TimeoutError => e
79
+ return if container_status(container_id) == 'stopped'
80
+ raise Timeout::Retry.new e # if options[:retry_interval] # rubocop:disable Style/RaiseArgs
65
81
  end
66
- @hk.wait_for_operation last_id # , options[:retry_interval]
67
- rescue Faraday::TimeoutError => e
68
- return if container_status(container_id) == 'stopped'
69
- raise Timeout::Retry.new e # if options[:retry_interval] # rubocop:disable Style/RaiseArgs
70
82
  end
71
83
  end
72
84
  wait_for_status container_id, 'stopped'
@@ -74,8 +86,14 @@ module NexusSW
74
86
 
75
87
  def delete_container(container_id)
76
88
  return unless container_exists? container_id
77
- stop_container container_id, force: true
78
- @hk.delete_container(container_id)
89
+ stop_container container_id, force: true
90
+
91
+ # overcome a race condition where the host is busy doing 'something' async causing the delete command to pop an error
92
+ # https://github.com/lxc/lxd/issues/4063
93
+ # sleep 1
94
+
95
+ id = @hk.delete_container(container_id, sync: false)[:id]
96
+ @hk.wait_for_operation id
79
97
  end
80
98
 
81
99
  def container_status(container_id)
@@ -98,8 +116,6 @@ module NexusSW
98
116
  false
99
117
  end
100
118
 
101
- include WaitMixin
102
-
103
119
  protected
104
120
 
105
121
  def wait_for_status(container_id, newstatus)
@@ -22,67 +22,39 @@ module NexusSW
22
22
  }.freeze
23
23
 
24
24
  def create_container(_container_name, _container_options)
25
- raise 'NexusSW::LXD::Driver.create_container not implemented'
25
+ raise "#{self.class}#create_container not implemented"
26
26
  end
27
27
 
28
28
  def start_container(_container_id)
29
- raise 'NexusSW::LXD::Driver.start_container not implemented'
29
+ raise "#{self.class}#start_container not implemented"
30
30
  end
31
31
 
32
32
  def stop_container(_container_id, _options = {})
33
- raise 'NexusSW::LXD::Driver.stop_container not implemented'
33
+ raise "#{self.class}#stop_container not implemented"
34
34
  end
35
35
 
36
36
  def delete_container(_container_id)
37
- raise 'NexusSW::LXD::Driver.delete_container not implemented'
37
+ raise "#{self.class}#delete_container not implemented"
38
38
  end
39
39
 
40
40
  def container_status(_container_id)
41
- raise 'NexusSW::LXD::Driver.container_status not implemented'
42
- end
43
-
44
- def ensure_profiles(_profiles)
45
- raise 'NexusSW::LXD::Driver.ensure_profiles not implemented'
41
+ raise "#{self.class}#container_status not implemented"
46
42
  end
47
43
 
48
44
  def container(_container_id)
49
- raise 'NexusSW::LXD::Driver.container not implemented'
45
+ raise "#{self.class}#container not implemented"
50
46
  end
51
47
 
52
48
  def container_state(_container_id)
53
- raise 'NexusSW::LXD::Driver.container_state not implemented'
49
+ raise "#{self.class}#container_state not implemented"
54
50
  end
55
51
 
56
52
  def wait_for(_what)
57
- raise 'NexusSW::LXD::Driver.wait_for not implemented'
53
+ raise "#{self.class}#wait_for not implemented"
58
54
  end
59
55
 
60
- module WaitMixin
61
- def check_for_ip(driver, container_name)
62
- cc = driver.container(container_name)
63
- state = driver.container_state(container_name)
64
- cc[:expanded_devices].each do |nic, data|
65
- next unless data[:type] == 'nic'
66
- state[:network][nic][:addresses].each do |address|
67
- return address[:address] if address[:family] == 'inet' && address[:address] && !address[:address].empty?
68
- end
69
- end
70
- nil
71
- end
72
-
73
- def wait_for(container_name, what, timeout = 60)
74
- Timeout.timeout timeout do
75
- loop do
76
- retval = nil
77
- case what
78
- when :ip
79
- retval = check_for_ip(self, container_name)
80
- end
81
- return retval if retval
82
- sleep 0.5
83
- end
84
- end
85
- end
56
+ def transport_for(_container_name)
57
+ raise "#{self.class}#transport_for not implemented"
86
58
  end
87
59
  end
88
60
  end
@@ -1,4 +1,5 @@
1
1
  require 'nexussw/lxd/transport/mixins/local'
2
+ require 'nexussw/lxd/transport/mixins/helpers/upload_folder'
2
3
  require 'tempfile'
3
4
  require 'pp'
4
5
 
@@ -13,8 +14,11 @@ module NexusSW
13
14
  @inner_transport = remote_transport
14
15
  @punt = !inner_transport.is_a?(::NexusSW::LXD::Transport::Mixins::Local)
15
16
  end
17
+
16
18
  attr_reader :inner_transport, :punt, :container_name, :config
17
19
 
20
+ include Helpers::UploadFolder
21
+
18
22
  def execute(command, options = {})
19
23
  mycommand = command.is_a?(Array) ? command.join(' ') : command
20
24
  subcommand = options[:subcommand] || "exec #{container_name} --"
@@ -62,6 +66,11 @@ module NexusSW
62
66
  inner_transport.execute("rm -rf #{tfile}", capture: false) if tfile
63
67
  end
64
68
 
69
+ def upload_folder(local_path, path)
70
+ return super unless config[:info] && config[:info][:api_extensions] && config[:info][:api_extensions].include?('directory_manipulation')
71
+ execute("-r #{localname} #{container_name}#{path}", subcommand: 'file push', capture: false).error!
72
+ end
73
+
65
74
  def add_remote(host_name)
66
75
  execute("add #{host_name} --accept-certificate", subcommand: 'remote').error! unless remote? host_name
67
76
  end
@@ -0,0 +1,53 @@
1
+ module NexusSW
2
+ module LXD
3
+ class Transport
4
+ module Mixins
5
+ module Helpers
6
+ module ExecuteMixin
7
+ class ExecuteResult
8
+ def initialize(command, options, exitstatus)
9
+ @command = command
10
+ @options = options || {}
11
+ @exitstatus = exitstatus
12
+ end
13
+
14
+ attr_reader :exitstatus, :options, :command
15
+
16
+ def stdout
17
+ options[:capture_options][:stdout] if options.key? :capture_options
18
+ end
19
+
20
+ def stderr
21
+ options[:capture_options][:stderr] if options.key? :capture_options
22
+ end
23
+
24
+ def error!
25
+ return self if exitstatus == 0
26
+ msg = "Error: '#{command}' failed with exit code #{exitstatus}.\n"
27
+ msg += "STDOUT: #{stdout}" if stdout && !stdout.empty?
28
+ msg += "STDERR: #{stderr}" if stderr && !stderr.empty?
29
+ raise msg
30
+ end
31
+ end
32
+
33
+ def execute(command, options = {}, &block)
34
+ options ||= {}
35
+ return execute_chunked(command, options) if options[:capture] == false && !block_given?
36
+
37
+ capture_options = { stdout: '', stderr: '' }
38
+ capture_options[:capture] = block if block_given?
39
+ capture_options[:capture] ||= options[:capture] if options[:capture].respond_to? :call
40
+ # capture_options[:capture] ||= options[:stream] if options[:stream].respond_to? :call
41
+ capture_options[:capture] ||= proc do |stdout_chunk, stderr_chunk|
42
+ capture_options[:stdout] += stdout_chunk if stdout_chunk
43
+ capture_options[:stderr] += stderr_chunk if stderr_chunk
44
+ end
45
+
46
+ execute_chunked(command, options.merge(capture_options: capture_options), &capture_options[:capture])
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,79 @@
1
+ module NexusSW
2
+ module LXD
3
+ class Transport
4
+ module Mixins
5
+ module Helpers
6
+ module UploadFolder
7
+ def upload_folder(local_path, path)
8
+ upload_using_tarball(local_path, path) || upload_files_individually(local_path, path)
9
+ end
10
+
11
+ def upload_files_individually(local_path, path)
12
+ Dir.entries(local_path).map { |f| (f == '.' || f == '..') ? nil : File.join(local_path, f) }.compact.each do |f|
13
+ dest = File.join(path, File.basename(local_path))
14
+ upload_files_individually f, dest if File.directory? f
15
+ upload_file f, File.join(dest, File.basename(f)) if File.file? f
16
+ end
17
+ end
18
+
19
+ def upload_using_tarball(local_path, path)
20
+ return false unless can_archive?
21
+ # TODO: should I return false upon error? i.e. retry with individual file uploads if this fails?
22
+ # lets see how this does in the wild before deciding
23
+ flag, ext = compression
24
+ begin
25
+ tfile = Tempfile.new(container_name)
26
+ tfile.close
27
+ `tar -c#{flag}f #{tfile.path} -C #{File.dirname local_path} ./#{File.basename local_path}`
28
+ # on that above note we'll do this at least
29
+ # raise "Unable to create archive #{tfile.path}" if File.zero? tfile.path
30
+ if File.zero? tfile.path
31
+ @can_archive = false
32
+ return false
33
+ end
34
+ fname = '/tmp/' + File.basename(tfile.path) + ".tar#{ext}"
35
+ upload_file tfile.path, fname
36
+ # TODO: serious: make sure the tar extract does an overwrite of existing files
37
+ # multiple converge support as well as CI cycle/dev updated files get updated instead of .1 suffixed (?)
38
+ # I think I need a flag (it's been a while)
39
+ execute("bash -c 'mkdir -p #{path} && cd #{path} && tar -xf #{fname} && rm -rf #{fname}'", capture: false).error!
40
+ ensure
41
+ tfile.unlink
42
+ end
43
+ end
44
+
45
+ private
46
+
47
+ def can_archive?
48
+ return false if @can_archive == false
49
+ @can_archive ||= begin
50
+ # I don't want to code tarball logic into the mock transport
51
+ return false if respond_to?(:hk) && hk.respond_to?(:mock)
52
+ return false if respond_to?(:inner_transport) && inner_transport.respond_to?(:mock)
53
+ return false if respond_to?(:inner_transport) && inner_transport.respond_to?(:inner_transport) && inner_transport.inner_transport.respond_to?(:mock)
54
+ return false if respond_to?(:inner_transport) && inner_transport.respond_to?(:hk) && inner_transport.hk.respond_to?(:mock)
55
+ `tar --version`
56
+ true
57
+ rescue
58
+ false
59
+ end
60
+ end
61
+
62
+ # gzip(-z) or bzip2(-j) (these are the only 2 on trusty atm)
63
+ def compression
64
+ @compression ||= begin
65
+ which = execute('bash -c "which gzip || which bzip2 || true"').stdout.strip
66
+ which = File.basename(which) if which
67
+ case which
68
+ when 'gzip' then ['z', '.gz']
69
+ when 'bzip2' then ['j', '.bzip2']
70
+ else ['', '']
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
@@ -1,3 +1,4 @@
1
+ require 'nexussw/lxd/transport/mixins/helpers/execute'
1
2
  require 'open3'
2
3
  require 'nio/websocket'
3
4
 
@@ -12,7 +13,7 @@ module NexusSW
12
13
 
13
14
  attr_reader :config
14
15
 
15
- include ExecuteMixin
16
+ include Helpers::ExecuteMixin
16
17
 
17
18
  def execute_chunked(command, options)
18
19
  NIO::WebSocket::Reactor.start
@@ -36,7 +37,7 @@ module NexusSW
36
37
  end
37
38
  th.join
38
39
  loop do
39
- return LXDExecuteResult.new(command, options, th.value.exitstatus) if th.value.exited? && mon_out && mon_err && mon_out.closed? && mon_err.closed?
40
+ return Helpers::ExecuteMixin::ExecuteResult.new(command, options, th.value.exitstatus) if th.value.exited? && mon_out && mon_err && mon_out.closed? && mon_err.closed?
40
41
  Thread.pass
41
42
  end
42
43
  end
@@ -1,22 +1,26 @@
1
+ require 'nexussw/lxd/transport/mixins/helpers/execute'
2
+ require 'nexussw/lxd/transport/mixins/helpers/upload_folder'
1
3
  require 'nio/websocket'
4
+ require 'tempfile'
2
5
 
3
6
  module NexusSW
4
7
  module LXD
5
8
  class Transport
6
9
  module Mixins
7
10
  module Rest
8
- def initialize(driver, container_name, config = {})
11
+ def initialize(container_name, config = {})
9
12
  @container_name = container_name
10
13
  @config = config
11
- raise "The rest transport requires the Rest Driver. You supplied #{driver}" unless driver.respond_to?(:hk) && driver.respond_to?(:rest_endpoint) # driver.is_a? NexusSW::LXD::Driver::Rest
12
- @rest_endpoint = driver.rest_endpoint
13
- @driver_options = driver.driver_options
14
- @hk = driver.hk
14
+ @rest_endpoint = config[:rest_endpoint]
15
+ @driver_options = config[:driver_options]
16
+ @hk = config[:connection]
17
+ raise 'The rest transport requires the following keys: { :connection, :driver_options, :rest_endpoint }' unless @rest_endpoint && @hk && @driver_options
15
18
  end
16
19
 
17
20
  attr_reader :hk, :rest_endpoint, :container_name, :config
18
21
 
19
- include ExecuteMixin
22
+ include Helpers::ExecuteMixin
23
+ include Helpers::UploadFolder
20
24
 
21
25
  def execute_chunked(command, options = {}, &block)
22
26
  opid = nil
@@ -32,7 +36,7 @@ module NexusSW
32
36
  begin
33
37
  retval = hk.wait_for_operation opid
34
38
  backchannel.exit if backchannel.respond_to? :exit
35
- return LXDExecuteResult.new command, options, retval[:metadata][:return].to_i
39
+ return Helpers::ExecuteMixin::ExecuteResult.new command, options, retval[:metadata][:return].to_i
36
40
  rescue Faraday::TimeoutError => e
37
41
  raise Timeout::Retry.new e # rubocop:disable Style/RaiseArgs
38
42
  end
@@ -54,7 +58,8 @@ module NexusSW
54
58
  end
55
59
 
56
60
  def upload_file(local_path, path)
57
- hk.push_file local_path, container_name, path
61
+ # return hk.push_file(local_path, container_name, path)
62
+ write_file(path, IO.binread(local_path))
58
63
  end
59
64
 
60
65
  protected
@@ -3,71 +3,29 @@ require 'nexussw/lxd'
3
3
  module NexusSW
4
4
  module LXD
5
5
  class Transport
6
- class LXDExecuteResult
7
- def initialize(command, options, exitstatus)
8
- @command = command
9
- @options = options || {}
10
- @exitstatus = exitstatus
11
- end
12
-
13
- attr_reader :exitstatus, :options, :command
14
-
15
- def stdout
16
- options[:capture_options][:stdout] if options.key? :capture_options
17
- end
18
-
19
- def stderr
20
- options[:capture_options][:stderr] if options.key? :capture_options
21
- end
22
-
23
- def error!
24
- return self if exitstatus == 0
25
- msg = "Error: '#{command}' failed with exit code #{exitstatus}.\n"
26
- msg += "STDOUT: #{stdout}" if stdout && !stdout.empty?
27
- msg += "STDERR: #{stderr}" if stderr && !stderr.empty?
28
- raise msg
29
- end
30
- end
31
-
32
- module ExecuteMixin
33
- def execute(command, options = {}, &block)
34
- options ||= {}
35
- return execute_chunked(command, options) if options[:capture] == false && !block_given?
36
-
37
- capture_options = { stdout: '', stderr: '' }
38
- capture_options[:capture] = block if block_given?
39
- capture_options[:capture] ||= options[:capture] if options[:capture].respond_to? :call
40
- # capture_options[:capture] ||= options[:stream] if options[:stream].respond_to? :call
41
- capture_options[:capture] ||= proc do |stdout_chunk, stderr_chunk|
42
- capture_options[:stdout] += stdout_chunk if stdout_chunk
43
- capture_options[:stderr] += stderr_chunk if stderr_chunk
44
- end
45
-
46
- execute_chunked(command, options.merge(capture_options: capture_options), &capture_options[:capture])
47
- end
48
- end
49
-
50
6
  def execute(_command, _options = {})
51
- raise 'NexusSW::LXD::Transport.execute not implemented'
7
+ raise "#{self.class}#execute not implemented"
52
8
  end
53
9
 
54
10
  def read_file(_path)
55
- raise 'NexusSW::LXD::Transport.read_file not implemented'
11
+ raise "#{self.class}#read_file not implemented"
56
12
  end
57
13
 
58
14
  def write_file(_path, _content)
59
- raise 'NexusSW::LXD::Transport.write_file not implemented'
15
+ raise "#{self.class}#write_file not implemented"
60
16
  end
61
17
 
62
18
  def download_file(_path, _local_path)
63
- raise 'NexusSW::LXD::Transport.download_file not implemented'
19
+ raise "#{self.class}#download_file not implemented"
64
20
  end
65
21
 
66
22
  def upload_file(_local_path, _path)
67
- raise 'NexusSW::LXD::Transport.upload_file not implemented'
23
+ raise "#{self.class}#upload_file not implemented"
24
+ end
25
+
26
+ def upload_folder(_local_path, _path)
27
+ raise "#{self.class}#upload_folder not implemented"
68
28
  end
69
- # protected
70
- # def execute_chunked(_command, _options = {})
71
29
  end
72
30
  end
73
31
  end
@@ -1,5 +1,5 @@
1
1
  module NexusSW
2
2
  module LXD
3
- VERSION = '0.4.1'.freeze
3
+ VERSION = '0.5.0'.freeze
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lxd-common
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sean Zachariasen
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-11-08 00:00:00.000000000 Z
11
+ date: 2017-12-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: hyperkit
@@ -115,12 +115,15 @@ files:
115
115
  - lib/nexussw/lxd/driver.rb
116
116
  - lib/nexussw/lxd/driver/cli.rb
117
117
  - lib/nexussw/lxd/driver/mixins/cli.rb
118
+ - lib/nexussw/lxd/driver/mixins/helpers/wait.rb
118
119
  - lib/nexussw/lxd/driver/mixins/rest.rb
119
120
  - lib/nexussw/lxd/driver/rest.rb
120
121
  - lib/nexussw/lxd/transport.rb
121
122
  - lib/nexussw/lxd/transport/cli.rb
122
123
  - lib/nexussw/lxd/transport/local.rb
123
124
  - lib/nexussw/lxd/transport/mixins/cli.rb
125
+ - lib/nexussw/lxd/transport/mixins/helpers/execute.rb
126
+ - lib/nexussw/lxd/transport/mixins/helpers/upload_folder.rb
124
127
  - lib/nexussw/lxd/transport/mixins/local.rb
125
128
  - lib/nexussw/lxd/transport/mixins/rest.rb
126
129
  - lib/nexussw/lxd/transport/rest.rb