Module: NexusSW::LXD::Driver::Mixins::CLI

Includes:
Helpers::WaitMixin
Included in:
CLI
Defined in:
lib/nexussw/lxd/driver/mixins/cli.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Helpers::WaitMixin

#check_for_ip, #wait_for

Instance Attribute Details

#driver_optionsObject (readonly)

Returns the value of attribute driver_options.



17
18
19
# File 'lib/nexussw/lxd/driver/mixins/cli.rb', line 17

def driver_options
  @driver_options
end

#inner_transportObject (readonly)

Returns the value of attribute inner_transport.



17
18
19
# File 'lib/nexussw/lxd/driver/mixins/cli.rb', line 17

def inner_transport
  @inner_transport
end

Instance Method Details

#container(container_id) ⇒ Object



102
103
104
105
106
107
108
109
# File 'lib/nexussw/lxd/driver/mixins/cli.rb', line 102

def container(container_id)
  res = inner_transport.execute("lxc list #{container_id} --format=json")
  res.error!
  JSON.parse(res.stdout).each do |c|
    return convert_keys(c.except('state')) if c['name'] == container_id
  end
  nil
end

#container_exists?(container_id) ⇒ Boolean

Returns:

  • (Boolean)


111
112
113
114
115
116
# File 'lib/nexussw/lxd/driver/mixins/cli.rb', line 111

def container_exists?(container_id)
  return true if container_status(container_id)
  return false
rescue
  false
end

#container_state(container_id) ⇒ Object

YAML is not supported until somewhere in the feature branch

the YAML return has :state and :container at the root level

the JSON return has no :container (:container is root)

and has :state underneath that

(CLI Only) and :state is only available if the container is running



93
94
95
96
97
98
99
100
# File 'lib/nexussw/lxd/driver/mixins/cli.rb', line 93

def container_state(container_id)
  res = inner_transport.execute("lxc list #{container_id} --format=json")
  res.error!
  JSON.parse(res.stdout).each do |c|
    return convert_keys(c['state']) if c['name'] == container_id
  end
  nil
end

#container_status(container_id) ⇒ Object



70
71
72
# File 'lib/nexussw/lxd/driver/mixins/cli.rb', line 70

def container_status(container_id)
  STATUS_CODES[container(container_id)[:status_code].to_i]
end

#convert_keys(oldhash) ⇒ Object



74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/nexussw/lxd/driver/mixins/cli.rb', line 74

def convert_keys(oldhash)
  return oldhash unless oldhash.is_a?(Hash) || oldhash.is_a?(Array)
  retval = {}
  if oldhash.is_a? Array
    retval = []
    oldhash.each { |v| retval << convert_keys(v) }
  else
    oldhash.each do |k, v|
      retval[k.to_sym] = convert_keys(v)
    end
  end
  retval
end

#create_container(container_name, container_options = {}) ⇒ Object



23
24
25
26
27
28
29
30
31
32
33
34
35
36
# File 'lib/nexussw/lxd/driver/mixins/cli.rb', line 23

def create_container(container_name, container_options = {})
  if container_exists? container_name
    start_container container_name # Start for Parity with the below logic (`lxc launch` auto starts)
    return container_name
  end
  cline = "lxc launch #{image_alias(container_options)} #{container_name}"
  profiles = container_options[:profiles] || []
  profiles.each { |p| cline += " -p #{p}" }
  configs = container_options[:config] || {}
  configs.each { |k, v| cline += " -c #{k}=#{v}" }
  inner_transport.execute(cline).error!
  wait_for_status container_name, 'running'
  container_name
end

#delete_container(container_id) ⇒ Object



65
66
67
68
# File 'lib/nexussw/lxd/driver/mixins/cli.rb', line 65

def delete_container(container_id)
  return unless container_exists? container_id
  inner_transport.execute("lxc delete #{container_id} --force", capture: false).error!
end

#initialize(inner_transport, driver_options = {}) ⇒ Object



12
13
14
15
# File 'lib/nexussw/lxd/driver/mixins/cli.rb', line 12

def initialize(inner_transport, driver_options = {})
  @inner_transport = inner_transport
  @driver_options = driver_options || {}
end

#start_container(container_id) ⇒ Object



38
39
40
41
42
# File 'lib/nexussw/lxd/driver/mixins/cli.rb', line 38

def start_container(container_id)
  return if container_status(container_id) == 'running'
  inner_transport.execute("lxc start #{container_id}").error!
  wait_for_status container_id, 'running'
end

#stop_container(container_id, options = {}) ⇒ Object



44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/nexussw/lxd/driver/mixins/cli.rb', line 44

def stop_container(container_id, options = {})
  options ||= {} # default behavior: no timeout or retries.  These functions are up to the consumer's context and not really 'sane' defaults
  return if container_status(container_id) == 'stopped'
  return inner_transport.execute("lxc stop #{container_id} --force", capture: false).error! if options[:force]
  LXD.with_timeout_and_retries(options) do
    return if container_status(container_id) == 'stopped'
    timeout = " --timeout=#{options[:retry_interval]}" if options[:retry_interval]
    retval = inner_transport.execute("lxc stop #{container_id}#{timeout || ''}", capture: false)
    begin
      retval.error!
    rescue => e
      return if container_status(container_id) == 'stopped'
      # can't distinguish between timeout, or other error.
      # but if the status call is not popping a 404, and we're not stopped, then a retry is worth it
      raise Timeout::Retry.new(e) if timeout # rubocop:disable Style/RaiseArgs
      raise
    end
  end
  wait_for_status container_id, 'stopped'
end

#transport_for(container_name) ⇒ Object



19
20
21
# File 'lib/nexussw/lxd/driver/mixins/cli.rb', line 19

def transport_for(container_name)
  Transport::CLI.new inner_transport, container_name, info: YAML.load(inner_transport.execute('lxc info').error!.stdout)
end