lxd-common 0.4.1 → 0.5.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 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