lxc_ssh 0.0.1

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: b1299d54895480465b61dca5ec7b400375465399
4
+ data.tar.gz: 4694ed8006155c5d7d9bc7aa5d6f360c5847a8a1
5
+ SHA512:
6
+ metadata.gz: db2af76937ab694f8352c0a46f9ec049d0fd6490f4b856e3087f33a118a8d48615cf70d750a1bd1331f291db7984e419487dbf7bed1d7cf2ed255612ebafbc38
7
+ data.tar.gz: 22c78717be1114db31aef462339dcf3f709d5d09030a51cd95ba7945d304a7448dcd246f81decc52856fcc327840d38593d1268054b454f8feb5308a971b9bbf
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in lxc_ssh.gemspec
4
+ gemspec
@@ -0,0 +1,127 @@
1
+ # lxc_ssh
2
+
3
+ lxc_ssh is a ruby gem for managing lxc host systems over an ssh connection.
4
+ Supports LXC version 1.0 and higher. Depends on net-ssh (https://github.com/net-ssh/net-ssh).
5
+
6
+
7
+ ## Installation
8
+
9
+ !! NOT AT RUBYGEMS.ORG YET !!
10
+
11
+ Add this line to your application's Gemfile:
12
+
13
+ ```ruby
14
+ gem 'lxc_ssh'
15
+ ```
16
+
17
+ And then execute:
18
+
19
+ $ bundle
20
+
21
+ Or install it yourself as:
22
+
23
+ $ gem install lxc_ssh
24
+
25
+ ## Usage
26
+
27
+ First create a connection to your system over ssh (currently only the ssh default port is supported)
28
+ and authenticate as a privileged user (lxc is installed to /usr in this case):
29
+
30
+ ```ruby
31
+ con = LxcSsh::Connection.new
32
+ con.connect('my.cool.host', 'root', nil, '/usr')
33
+ ```
34
+
35
+ If no exception occured, you're ready to go.
36
+
37
+ #### Get containers
38
+
39
+ ```ruby
40
+ containers = con.manager.containers
41
+ ```
42
+
43
+
44
+ #### Get specific container information
45
+
46
+ ```ruby
47
+ container = con.manager.container 'my-fancy-container-name'
48
+ ```
49
+
50
+ Result:
51
+
52
+ ```ruby
53
+ #<LxcSsh::Container:0x00000000c7ea48 @name="my-fancy-container-name",
54
+ @pid="1234",
55
+ @state="RUNNING",
56
+ @memory_usage=0,
57
+ @memory_limit=0,
58
+ @cpu_shares=1024,
59
+ @cpu_usage="23994168167209",
60
+ @ip="192.168.0.2">
61
+ ```
62
+
63
+ #### Get container config
64
+
65
+ ```ruby
66
+ config = con.manager.container_config 'my-fancy-container-name'
67
+ puts config['lxc.network.veth.pair']
68
+ ```
69
+
70
+
71
+ #### Update config items
72
+
73
+ ```ruby
74
+ config = con.manager.container_config 'my-fancy-container-name'
75
+ config['lxc.network.veth.pair'] = 'none'
76
+ con.manager.write_config 'my-fancy-container-name', config
77
+ ```
78
+
79
+ ### Create container
80
+
81
+ ```ruby
82
+ con.manager.create_container 'testcontainer', 'gentoo'
83
+ ```
84
+
85
+ #### Start container
86
+
87
+ ```ruby
88
+ con.manager.start_container 'testcontainer'
89
+ ```
90
+
91
+ #### Stop container
92
+
93
+ ```ruby
94
+ con.manager.stop_container 'testcontainer'
95
+ ```
96
+
97
+ #### Destroy container
98
+
99
+ ```ruby
100
+ con.manager.destroy_container 'testcontainer'
101
+ ```
102
+
103
+ #### Create container
104
+
105
+ ```ruby
106
+ con.manager.create_container 'testcontainer', 'gentoo'
107
+ ```
108
+
109
+ #### Get templates
110
+
111
+ ```ruby
112
+ con.manager.template_names
113
+ ```
114
+
115
+ #### Get template help text
116
+
117
+ ```ruby
118
+ puts con.manager.template_help 'archlinux'
119
+ ```
120
+
121
+ ## Contributing
122
+
123
+ 1. Fork it ( https://github.com/dprandzioch/lxc_ssh/fork )
124
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
125
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
126
+ 4. Push to the branch (`git push origin my-new-feature`)
127
+ 5. Create a new Pull Request
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
@@ -0,0 +1,12 @@
1
+ require 'lxc_ssh/version.rb'
2
+ require "lxc_ssh/connection.rb"
3
+ require "lxc_ssh/container.rb"
4
+ require "lxc_ssh/container_info.rb"
5
+ require "lxc_ssh/container_config.rb"
6
+ require "lxc_ssh/manager.rb"
7
+ require "lxc_ssh/manager/specific_manager10.rb"
8
+
9
+ module LxcSsh
10
+ LIBNAME = 'lxc_ssh'
11
+ LIBDIR = File.expand_path("../#{LIBNAME}", __FILE__)
12
+ end
@@ -0,0 +1,54 @@
1
+ require 'net/ssh'
2
+
3
+ module LxcSsh
4
+ class Connection
5
+
6
+ attr_reader :manager
7
+
8
+ # Initializes the connection
9
+ def initialize
10
+ @session = nil
11
+ @manager = nil
12
+ @lxc_version = nil
13
+ @lxc_path = nil
14
+ end
15
+
16
+ # Connects to the host system via ssh and authenticates by
17
+ # either public key or password authentication
18
+ #
19
+ # @param hostname [String] SSH Hostname
20
+ # @param username [String] SSH Username
21
+ # @param password [String] SSH Password
22
+ # @param lxc_path [String] LXC installation path (default: /usr)
23
+ def connect(hostname, username, password, lxc_path = '/usr')
24
+ if @password.nil?
25
+ # pubkey
26
+ @session = Net::SSH.start(hostname, username)
27
+ else
28
+ @session = Net::SSH.start(hostname, username, password)
29
+ end
30
+
31
+ @lxc_path = lxc_path
32
+ @lxc_version = obtain_version
33
+ @manager = self.init_manager
34
+ end
35
+
36
+ # Obtains the version number of the lxc installation
37
+ #
38
+ # @return string
39
+ def obtain_version
40
+ output = @session.exec! @lxc_path + "/bin/lxc-start --version"
41
+
42
+ output.strip
43
+ end
44
+
45
+ # Initializes the lxc manager object
46
+ def init_manager
47
+ if @lxc_version.nil?
48
+ raise 'no lxc version set, please detect and set the lxc version using detect_lxc_version'
49
+ end
50
+
51
+ @manager = LxcSsh::Manager.new(@session, @lxc_version, @lxc_path)
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,35 @@
1
+ module LxcSsh
2
+ class Container
3
+
4
+ attr_accessor :name,
5
+ :state,
6
+ :pid,
7
+ :ip,
8
+ :memory_usage,
9
+ :memory_limit,
10
+ :cpu_shares,
11
+ :cpu_usage
12
+
13
+ # Checks if the container is running
14
+ #
15
+ # @return [Boolean]
16
+ def running?
17
+ @state == 'RUNNING'
18
+ end
19
+
20
+ # Checks if the container is frozen
21
+ #
22
+ # @return [Boolean]
23
+ def frozen?
24
+ @state == 'FROZEN'
25
+ end
26
+
27
+ # Checks if the container is stopped
28
+ #
29
+ # @return [Boolean]
30
+ def stopped?
31
+ !running? && !frozen?
32
+ end
33
+
34
+ end
35
+ end
@@ -0,0 +1,85 @@
1
+ module LxcSsh
2
+ class ContainerConfig
3
+
4
+ # Loads the configuration object with the config files' content
5
+ #
6
+ # @param data [String] config file contents
7
+ def initialize(data)
8
+ @content = parse(data)
9
+ end
10
+
11
+ # Loads the configuration object with the config files' content
12
+ #
13
+ # @param data [String] config file contents
14
+ # @return [Hash]
15
+ def parse(data)
16
+ items = {}
17
+
18
+ # only lines starting with 'lxc.'
19
+ lines = data.lines.map(&:strip).select do |line|
20
+ line.start_with?('lxc.')
21
+ end
22
+
23
+ # process lines
24
+ lines.each do |line|
25
+ key, value = line.split('=').map(&:strip)
26
+
27
+ if items.key?(key) == false
28
+ items[key] = []
29
+ end
30
+
31
+ items[key] << value
32
+ end
33
+
34
+ items.each_pair do |key, val|
35
+ if val.length == 1
36
+ items[key] = val.first
37
+ end
38
+ end
39
+
40
+ items
41
+ end
42
+
43
+ # Array-style accessor (getter)
44
+ #
45
+ # @param key [String] key of the hash
46
+ # @return [Object]
47
+ def [](key)
48
+ if key.kind_of?(String) == false
49
+ raise ArgumentError, 'key must be a string'
50
+ end
51
+
52
+ @content[key]
53
+ end
54
+
55
+ # Array-style accessor (setter)
56
+ #
57
+ # @param key [String] key of the hash
58
+ # @param val [Object] value to set
59
+ def []=(key, val)
60
+ @content[key] = val
61
+ end
62
+
63
+ # Generates a config string from the current object context
64
+ #
65
+ # @return [Hash]
66
+ def config_contents
67
+ lines = []
68
+
69
+ @content.each_pair do |key, value|
70
+ if value.class == Array
71
+ # multiple values assigned for a single key, order is important!
72
+ lines << value.map do |val|
73
+ key + ' = ' + val
74
+ end
75
+ else
76
+ line = key + ' = ' + value
77
+ lines << line
78
+ end
79
+ end
80
+
81
+ lines.join('\n')
82
+ end
83
+
84
+ end
85
+ end
@@ -0,0 +1,7 @@
1
+ module LxcSsh
2
+ class ContainerInfo
3
+
4
+ attr_accessor :pid, :state
5
+
6
+ end
7
+ end
@@ -0,0 +1,114 @@
1
+ module LxcSsh
2
+ class Manager
3
+
4
+ # Initializes the lxc manager by creating an instance of the version-specific
5
+ # lxc manager for the detected version
6
+ #
7
+ # @param session [SSH::Connection::Session] ssh session
8
+ # @param lxc_version [String] lxc version string
9
+ # @param lxc_path [String] lxc installation path
10
+ def initialize(session, lxc_version, lxc_path)
11
+ @lxc_path = lxc_path
12
+ @specific_manager = nil
13
+
14
+ # LXC APIs mac change in the future, therefore a version specific adapter
15
+ # must be used
16
+ if Gem::Version.new(lxc_version) >= Gem::Version.new('1.0')
17
+ @specific_manager = LxcSsh::SpecificManager10.new(session, lxc_path)
18
+ # other version checks go here
19
+ else
20
+ raise 'lxc versions < 1.0 are not supported'
21
+ end
22
+ end
23
+
24
+ # Returns an array of lxc containers
25
+ #
26
+ # @return [Array]
27
+ def container_names
28
+ @specific_manager.container_names
29
+ end
30
+
31
+ # Returns an array containing objects with container metadata
32
+ #
33
+ # @return [Array]
34
+ def containers
35
+ @specific_manager.containers
36
+ end
37
+
38
+ # Returns a LxcSsh::ContainerConfig object for the container name
39
+ #
40
+ # @return [LxcSsh::ContainerConfig]
41
+ def container_config(name)
42
+ @specific_manager.container_config name
43
+ end
44
+
45
+ # Returns an LxcSsh::Container object for the given container name
46
+ #
47
+ # @return [LxcSsh::Container]
48
+ def container(name)
49
+ @specific_manager.get_container_obj name
50
+ end
51
+
52
+ # Writes the config file contents back to the container config
53
+ #
54
+ # @param container_name [String] the container to use
55
+ # @param config [String] configuration string to save
56
+ def write_config(name, config)
57
+ @specific_manager.write_config name, config
58
+ end
59
+
60
+ # Returns an array containing all templates
61
+ #
62
+ # @todo check path
63
+ #
64
+ # @return [Array]
65
+ def template_names
66
+ @specific_manager.template_names
67
+ end
68
+
69
+ # Returns the template help text for a given template name
70
+ #
71
+ # @param template_name [String] template to use (without 'lxc-'-prefix)
72
+ # @return [String]
73
+ def template_help(name)
74
+ @specific_manager.template_help name
75
+ end
76
+
77
+ # Creates a container with the default configuration and additional template options
78
+ # and returns the output as a string
79
+ #
80
+ # @param name [String] container name
81
+ # @param template [String] template name (without 'lxc-'-prefix)
82
+ # @param template_options [String] additional template options
83
+ #
84
+ # @return [String]
85
+ def create_container(name, template, template_options = nil)
86
+ @specific_manager.create_container name, template, template_options
87
+ end
88
+
89
+ # Starts a container with the given name
90
+ #
91
+ # @param name [String] container name
92
+ # @return [Boolean]
93
+ def start_container(name)
94
+ @specific_manager.start_container name
95
+ end
96
+
97
+ # Stops a container
98
+ #
99
+ # @param name [String] container name
100
+ # @return [Boolean]
101
+ def stop_container(name)
102
+ @specific_manager.stop_container name
103
+ end
104
+
105
+ # Destroys a container with the given name
106
+ #
107
+ # @param name [String] container name
108
+ # @return [Boolean]
109
+ def destroy_container(name)
110
+ @specific_manager.destroy_container name
111
+ end
112
+
113
+ end
114
+ end
@@ -0,0 +1,244 @@
1
+ module LxcSsh
2
+ class SpecificManager10
3
+
4
+ # Initializes the manager
5
+ #
6
+ # @param session [SSH::Connection::Session] ssh session
7
+ # @param lxc_path [String] lxc installation path
8
+ def initialize(session, lxc_path)
9
+ @session = session
10
+ @lxc_path = lxc_path
11
+ end
12
+
13
+ # Returns an array of lxc containers
14
+ #
15
+ # @return [Array]
16
+ def container_names
17
+ result = @session.exec! @lxc_path + '/bin/lxc-ls'
18
+
19
+ result.lines.map(&:strip).uniq
20
+ end
21
+
22
+ # Returns an array containing objects with container metadata
23
+ #
24
+ # @return [Array]
25
+ def containers
26
+ containers = []
27
+
28
+ container_names.each do |name|
29
+ containers << get_container_obj(name)
30
+ end
31
+
32
+ containers
33
+ end
34
+
35
+ # Returns an LxcSsh::Container object for the given container name
36
+ #
37
+ # @return [LxcSsh::Container]
38
+ def get_container_obj(name)
39
+ container = Container.new
40
+ container.name = name
41
+
42
+ info = info(name)
43
+ container.pid = info.pid
44
+ container.state = info.state
45
+
46
+ container.memory_usage = run_cmd("lxc-cgroup", name, "memory.usage_in_bytes").strip.to_i
47
+ container.memory_limit = run_cmd("lxc-cgroup", name, "memory.limit_in_bytes").strip.to_i
48
+ container.cpu_shares = run_cmd("lxc-cgroup", name, "cpu.shares").strip.to_i
49
+ container.cpu_usage = cpu_usage name
50
+ container.ip = ip_addr name
51
+
52
+ container
53
+ end
54
+
55
+ # Returns a LxcSsh::ContainerConfig object for the container name
56
+ #
57
+ # @return [LxcSsh::ContainerConfig]
58
+ def container_config(name)
59
+ contents = config_contents name
60
+
61
+ ContainerConfig.new contents
62
+ end
63
+
64
+ # Writes the config file contents back to the container config
65
+ #
66
+ # @todo verify function
67
+ # @todo escape contents variable
68
+ #
69
+ # @param container_name [String] the container to use
70
+ # @param config [String] configuration string to save
71
+ def write_config(container_name, config)
72
+ if !config.kind_of?(ContainerConfig)
73
+ raise ArgumentError, "config must be a instance of ContainerConfig"
74
+ end
75
+
76
+ contents = config.config_contents
77
+
78
+ @session.exec! "echo -e '" + contents + "' > " + config_path(container_name)
79
+ end
80
+
81
+ # Returns an array containing all templates
82
+ #
83
+ # @todo check path
84
+ #
85
+ # @return [Array]
86
+ def template_names
87
+ output = @session.exec! "ls -1 " + @lxc_path + "/share/lxc/templates/"
88
+ output.gsub! 'lxc-', ''
89
+
90
+ result = output.lines.map(&:strip).uniq
91
+
92
+ result
93
+ end
94
+
95
+ # Returns the template help text for a given template name
96
+ #
97
+ # @param template_name [String] template to use (without 'lxc-'-prefix)
98
+ # @return [String]
99
+ def template_help(template_name)
100
+ output = run_cmd("lxc-create", nil, "-t lxc-#{template_name} -h")
101
+
102
+ output
103
+ end
104
+
105
+ # Creates a container with the default configuration and additional template options
106
+ # and returns the output as a string
107
+ #
108
+ # @param name [String] container name
109
+ # @param template [String] template name (without 'lxc-'-prefix)
110
+ # @param template_options [String] additional template options
111
+ #
112
+ # @return [String]
113
+ def create_container(name, template, template_options = nil)
114
+ args = "-t #{template}"
115
+
116
+ if template_options.nil? == false
117
+ args += " -- #{template_options}"
118
+ end
119
+
120
+ output = run_cmd("lxc-create", name, args)
121
+
122
+ output
123
+ end
124
+
125
+ # Starts a container with the given name
126
+ #
127
+ # @param name [String] container name
128
+ # @return [Boolean]
129
+ def start_container(name)
130
+ output = run_cmd("lxc-start", name, '-d')
131
+
132
+ output.nil?
133
+ end
134
+
135
+ # Stops a container
136
+ #
137
+ # @param name [String] container name
138
+ # @return [Boolean]
139
+ def stop_container(name)
140
+ output = run_cmd("lxc-stop", name)
141
+
142
+ output.nil?
143
+ end
144
+
145
+ # Destroys a container with the given name
146
+ #
147
+ # @param name [String] container name
148
+ # @return [Boolean]
149
+ def destroy_container(name)
150
+ output = run_cmd("lxc-destroy", name)
151
+
152
+ output.nil?
153
+ end
154
+
155
+ protected
156
+ # Executes a lxc command
157
+ #
158
+ # @param lxc_binary [String] lxc binary name
159
+ # @param container_name [String] container name (if needed, otherwise nil)
160
+ # @param params [String] additional parameter string to append
161
+ # @return [String]
162
+ def run_cmd(xlc_binary, container_name = nil, params = nil)
163
+ cmd = @lxc_path + '/bin/' + xlc_binary
164
+
165
+ if container_name.nil? == false
166
+ cmd += ' -n ' + container_name
167
+ end
168
+
169
+ cmd += ' '
170
+
171
+ if params.nil? == false
172
+ cmd += params
173
+ end
174
+
175
+ @session.exec!(cmd)
176
+ end
177
+
178
+ # Loads the lxc container path using lxc-config
179
+ #
180
+ # @return [String]
181
+ def container_path(name)
182
+ output = run_cmd("lxc-config", nil, "lxc.lxcpath").strip
183
+
184
+ "#{output}/#{name}"
185
+ end
186
+
187
+ # Returns the config file path for a given container
188
+ #
189
+ # @return [String]
190
+ def config_path(name)
191
+ container_path(name) + '/config'
192
+ end
193
+
194
+ # Obtains the contents of a container config file
195
+ #
196
+ # @return [String]
197
+ def config_contents(name)
198
+ @session.exec! 'cat ' + config_path(name)
199
+ end
200
+
201
+ # Returns the containers current cpu usage
202
+ #
203
+ # @return [String]
204
+ def cpu_usage(name)
205
+ result = run_cmd("lxc-cgroup", name, "cpuacct.usage").strip
206
+
207
+ result
208
+ end
209
+
210
+ # Returns the containers ip address
211
+ #
212
+ # @todo what happens if multiple ip addresses are configured
213
+ #
214
+ # @param name [String] container name
215
+ # @return [String]
216
+ def ip_addr(name)
217
+ output = run_cmd("lxc-info", name, "-i")
218
+
219
+ if output.nil?
220
+ return nil
221
+ end
222
+
223
+ result = output.scan(/^IP:\s+([0-9.]+)$/).flatten
224
+
225
+ result.first.nil? || result.first.empty? ? nil : result.first
226
+ end
227
+
228
+ # Returns a LxcSsh::ContainerInfo object containing the most essential information.
229
+ #
230
+ # @param name [String] container name
231
+ # @return [LxcSsh::ContainerInfo]
232
+ def info(name)
233
+ output = run_cmd("lxc-info", name)
234
+ result = output.scan(/^State:\s+([\w]+)|PID:\s+(-?[\d]+)$/).flatten
235
+
236
+ ci = ContainerInfo.new
237
+ ci.state = result.first
238
+ ci.pid = result.last
239
+
240
+ ci
241
+ end
242
+
243
+ end
244
+ end
@@ -0,0 +1,3 @@
1
+ module LxcSsh
2
+ VERSION = "0.0.1"
3
+ end
metadata ADDED
@@ -0,0 +1,98 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: lxc_ssh
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - David Prandzioch
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-08-26 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.6'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.6'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: net-ssh
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '2.9'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '2.9'
55
+ description: lxc_ssh is a ruby gem for managing lxc host systems over an ssh connection.
56
+ Supports LXC version 1.0 and higher. Depends on net-ssh.
57
+ email:
58
+ - david@backport.net
59
+ executables: []
60
+ extensions: []
61
+ extra_rdoc_files: []
62
+ files:
63
+ - Gemfile
64
+ - README.md
65
+ - Rakefile
66
+ - lib/lxc_ssh.rb
67
+ - lib/lxc_ssh/connection.rb
68
+ - lib/lxc_ssh/container.rb
69
+ - lib/lxc_ssh/container_config.rb
70
+ - lib/lxc_ssh/container_info.rb
71
+ - lib/lxc_ssh/manager.rb
72
+ - lib/lxc_ssh/manager/specific_manager10.rb
73
+ - lib/lxc_ssh/version.rb
74
+ homepage: https://github.com/dprandzioch/lxc_ssh
75
+ licenses:
76
+ - GPL-2.0
77
+ metadata: {}
78
+ post_install_message:
79
+ rdoc_options: []
80
+ require_paths:
81
+ - lib
82
+ required_ruby_version: !ruby/object:Gem::Requirement
83
+ requirements:
84
+ - - ">="
85
+ - !ruby/object:Gem::Version
86
+ version: '0'
87
+ required_rubygems_version: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - ">="
90
+ - !ruby/object:Gem::Version
91
+ version: '0'
92
+ requirements: []
93
+ rubyforge_project:
94
+ rubygems_version: 2.2.2
95
+ signing_key:
96
+ specification_version: 4
97
+ summary: LXC CLI wrapper using SSH
98
+ test_files: []