oreno_lxdapi 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 5b4a5211c7f6785c3c5dbb8ceaacf325fd5d8e7a
4
+ data.tar.gz: 05b9288e9946d99d70ec98f1dd250357bf2f72da
5
+ SHA512:
6
+ metadata.gz: 26fc8f5e94be979e32f7b295902ed2ed2b942eaeca80673983bfdff2836292eb45eeeb561a758ecb98800adbd6609354edda4a954230f0cde64927e6d49f8916
7
+ data.tar.gz: c20cc18f7b1b5ebfd8842dfa300a3c8673765280e1f4a351f6a980b146f3de1f4f2adf564910ed62f138adfa1c4ad9f8d0c063c7cf23e17bdac9665570354cf8
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/.travis.yml ADDED
@@ -0,0 +1,4 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.1.2
4
+ before_install: gem install bundler -v 1.10.6
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in oreno_lxdapi.gemspec
4
+ gemspec
data/README.md ADDED
@@ -0,0 +1,116 @@
1
+ # Oreno LXD API Client for Ruby
2
+ [![Build Status](https://travis-ci.org/inokappa/oreno_lxdapi.svg)](https://travis-ci.org/inokappa/oreno_lxdapi)
3
+
4
+ ## Reference
5
+
6
+ - [LXD REST API](https://github.com/lxc/lxd/blob/master/specs/rest-api.md)
7
+
8
+ ## Installation
9
+
10
+ Add this line to your application's Gemfile:
11
+
12
+ ```ruby
13
+ gem 'oreno_lxdapi'
14
+ ```
15
+
16
+ And then execute:
17
+
18
+ $ bundle
19
+
20
+ Or install it yourself as:
21
+
22
+ $ gem install oreno_lxdapi
23
+
24
+ ## Usage
25
+
26
+ ### sample script and output
27
+
28
+ - sample
29
+
30
+ ```ruby
31
+ #!/usr/bin/env ruby
32
+
33
+ require 'oreno_lxdapi'
34
+
35
+ c = OrenoLxdapi::Client.new(
36
+ "unix:///var/lib/lxd/unix.socket",
37
+ "oreno-ubuntu-image",
38
+ "test01"
39
+ )
40
+ p c.class
41
+
42
+ puts "=== create_container"
43
+ p c.create_container(
44
+ {
45
+ :architecture => "2",
46
+ :limits_cpu => "1",
47
+ :ephemeral => false
48
+ }
49
+ )
50
+ sleep 5
51
+
52
+ puts "=== run_container"
53
+ p c.state_container("start", :timeout => 50)
54
+
55
+ puts "=== file_upload"
56
+ p c.file_upload("sample.txt", "/tmp/sample.txt")
57
+
58
+ puts "=== run_lxc_exec"
59
+ c.run_lxc_exec("pwd")
60
+ c.run_lxc_exec("ls -l /tmp/sample.txt")
61
+
62
+ puts "== describe_container"
63
+ metadata = c.describe_container
64
+ data = []
65
+ data << metadata['status']['status']
66
+ data << metadata['ephemeral']
67
+ data << metadata['status']['ips'].each { |ip| p ip['address'] if ip['interface'] == "eth0"}
68
+ p data
69
+
70
+ puts "=== stop_container"
71
+ p c.state_container("stop", :timeout => 50)
72
+ sleep 5
73
+ p c.delete_container
74
+ ```
75
+
76
+ - output
77
+
78
+ ```sh
79
+ OrenoLxdapi::Client
80
+
81
+ === create_container
82
+ "{\"type\":\"async\",\"status\":\"OK\",\"status_code\":100,\"metadata\":{\"id\":\"e01bac0f-30f4-4dae-91b5-f7fd7e7ea926\",\"class\":\"task\",\"created_at\":\"2016-01-02T19:51:40.161118734+09:00\",\"updated_at\":\"2016-01-02T19:51:40.161118734+09:00\",\"status\":\"Running\",\"status_code\":103,\"resources\":{\"containers\":[\"/1.0/containers/test01\"]},\"metadata\":null,\"may_cancel\":false,\"err\":\"\"},\"operation\":\"/1.0/operations/e01bac0f-30f4-4dae-91b5-f7fd7e7ea926\"}\n"
83
+
84
+ === run_container
85
+ I, [2016-01-02T19:51:45.177958 #22904] INFO -- : Starting Container...
86
+ I, [2016-01-02T19:51:48.242125 #22904] INFO -- : Starting Container...
87
+ "{\"type\":\"async\",\"status\":\"OK\",\"status_code\":100,\"metadata\":{\"id\":\"03e75986-9732-41c1-8ef3-71ad2dcc1112\",\"class\":\"task\",\"created_at\":\"2016-01-02T19:51:45.172238776+09:00\",\"updated_at\":\"2016-01-02T19:51:45.172238776+09:00\",\"status\":\"Running\",\"status_code\":103,\"resources\":{\"containers\":[\"/1.0/containers/test01\"]},\"metadata\":null,\"may_cancel\":false,\"err\":\"\"},\"operation\":\"/1.0/operations/03e75986-9732-41c1-8ef3-71ad2dcc1112\"}\n"
88
+
89
+ === file_upload
90
+ "{\"type\":\"sync\",\"status\":\"Success\",\"status_code\":200,\"metadata\":{},\"operation\":\"\"}\n"
91
+
92
+ === run_lxc_exec
93
+ /root
94
+ --w-r-xr-- 1 root root 0 Jan 2 10:51 /tmp/sample.txt
95
+
96
+ == describe_container
97
+ "xx.x.x.205"
98
+ ["Running", false, [{"interface"=>"eth0", "protocol"=>"IPV4", "address"=>"xx.x.x.205", "host_veth"=>"vethVIDOBX"}, {"interface"=>"lo", "protocol"=>"IPV4", "address"=>"127.0.0.1", "host_veth"=>""}, {"interface"=>"lo", "protocol"=>"IPV6", "address"=>"::1", "host_veth"=>""}]]
99
+
100
+ === stop_container
101
+ I, [2016-01-02T19:51:48.563168 #22904] INFO -- : Stopping Container...
102
+ "{\"type\":\"async\",\"status\":\"OK\",\"status_code\":100,\"metadata\":{\"id\":\"b244aead-bf3f-4e2a-9ad4-0168fa64d45b\",\"class\":\"task\",\"created_at\":\"2016-01-02T19:51:48.559000682+09:00\",\"updated_at\":\"2016-01-02T19:51:48.559000682+09:00\",\"status\":\"Running\",\"status_code\":103,\"resources\":{\"containers\":[\"/1.0/containers/test01\"]},\"metadata\":null,\"may_cancel\":false,\"err\":\"\"},\"operation\":\"/1.0/operations/b244aead-bf3f-4e2a-9ad4-0168fa64d45b\"}\n"
103
+ I, [2016-01-02T19:51:53.563774 #22904] INFO -- : Deleting Container...
104
+ "{\"type\":\"async\",\"status\":\"OK\",\"status_code\":100,\"metadata\":{\"id\":\"a423baec-656e-49d3-8ab5-270cf7f11492\",\"class\":\"task\",\"created_at\":\"2016-01-02T19:51:53.577319191+09:00\",\"updated_at\":\"2016-01-02T19:51:53.577319191+09:00\",\"status\":\"Running\",\"status_code\":103,\"resources\":{\"containers\":[\"/1.0/containers/test01\"]},\"metadata\":null,\"may_cancel\":false,\"err\":\"\"},\"operation\":\"/1.0/operations/a423baec-656e-49d3-8ab5-270cf7f11492\"}\n"
105
+ ```
106
+
107
+ ## Development
108
+
109
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
110
+
111
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
112
+
113
+ ## Contributing
114
+
115
+ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/oreno_lxdapi.
116
+
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
@@ -0,0 +1,206 @@
1
+ require "oreno_lxdapi/version"
2
+ require "net_http_unix"
3
+ require "json"
4
+ require "logger"
5
+
6
+ module OrenoLxdapi
7
+ class Client
8
+
9
+ def initialize(uri, image_name, container_name)
10
+ @log = Logger.new(STDOUT)
11
+ @uri = uri
12
+ @image_name = image_name
13
+ @container_name = container_name
14
+ end
15
+
16
+ def client
17
+ NetX::HTTPUnix.new(@uri)
18
+ end
19
+
20
+ def list_containers
21
+ req = Net::HTTP::Get.new("/1.0/containers")
22
+ resp = client.request(req)
23
+ return resp.body
24
+ end
25
+
26
+ def config_container(opts={})
27
+ end
28
+
29
+ def create_container(opts={})
30
+ options = {
31
+ :architecture => 2,
32
+ :profiles => ["default"],
33
+ :ephemeral => true,
34
+ :limits_cpu => "1",
35
+ }
36
+
37
+ options.merge!(opts)
38
+
39
+ req = Net::HTTP::Post.new("/1.0/containers")
40
+ req["Content-Type"] = "application/json"
41
+ payload = {
42
+ "name" => @container_name,
43
+ "architecture" => options[:architecture].to_i,
44
+ "profiles" => options[:profiles],
45
+ "ephemeral" => options[:ephemeral],
46
+ "config" => {
47
+ "limits.cpu" => options[:limits_cpu]
48
+ },
49
+ "source" => {
50
+ "type" => "image",
51
+ "alias" => @image_name
52
+ }
53
+ }
54
+ req.body = payload.to_json
55
+
56
+ resp = client.request(req)
57
+ return resp.body
58
+ end
59
+
60
+ def delete_container
61
+ @log.info("Deleting Container...")
62
+ req = Net::HTTP::Delete.new("/1.0/containers/#{@container_name}")
63
+ resp = client.request(req)
64
+ return resp.body
65
+ end
66
+
67
+ def describe_container
68
+ req = Net::HTTP::Get.new("/1.0/containers/#{@container_name}")
69
+ resp = client.request(req)
70
+ json = JSON.parse(resp.body)
71
+
72
+ if json['metadata']
73
+ return json['metadata']
74
+ else
75
+ @log.warn("Failed to get metadata.")
76
+ end
77
+
78
+ end
79
+
80
+ def check_container_status
81
+ req = Net::HTTP::Get.new("/1.0/containers/#{@container_name}/state")
82
+ resp = client.request(req)
83
+ json = JSON.parse(resp.body)
84
+
85
+ status = ""
86
+ ipv4 = ""
87
+ if json['metadata']
88
+ status = json['metadata']['status']
89
+ unless json['metadata']['ips'] == nil
90
+ json['metadata']['ips'].each { |ip| ipv4 = ip['address'] if ip['interface'] == "eth0"}
91
+ return status, ipv4
92
+ else
93
+ return status
94
+ end
95
+ end
96
+
97
+ end
98
+
99
+ def state_container(action, opts={})
100
+ options = {
101
+ :timeout => 30,
102
+ :force => true
103
+ }
104
+
105
+ options.merge!(opts)
106
+
107
+ req = Net::HTTP::Put.new("/1.0/containers/#{@container_name}/state")
108
+ req["Content-Type"] = "application/json"
109
+ payload = {
110
+ "action" => action,
111
+ "timeout" => options[:timeout],
112
+ "force" => options[:force]
113
+ }
114
+ req.body = payload.to_json
115
+ resp = client.request(req)
116
+
117
+ if action == "start"
118
+ loop do
119
+ @log.info("Starting Container...")
120
+ status = check_container_status
121
+ if status.length == 2 && status[1] != ""
122
+ break
123
+ end
124
+
125
+ sleep 3
126
+ end
127
+ return resp.body
128
+ elsif action == "stop"
129
+ @log.info("Stopping Container...")
130
+ return resp.body
131
+ else
132
+ @log.warn("Invalid argument.")
133
+ end
134
+
135
+ end
136
+
137
+ def file_upload(src, dst)
138
+ req = Net::HTTP::Post.new("/1.0/containers/#{@container_name}/files?path=#{dst}")
139
+ req["X-LXD-uid"] = "0"
140
+ req["X-LXD-gid"] = "0"
141
+ req["X-LXD-mode"] = "700"
142
+ req["Content-Type"] = "multipart/form-data"
143
+
144
+ resp = ""
145
+ File.open(src, 'rb') do |f|
146
+ req.body_stream = f
147
+ req["Content-Length"] = f.size
148
+ resp = client.request(req)
149
+ end
150
+
151
+ return resp.body
152
+ end
153
+
154
+ def create_exec(command)
155
+ # commands = command.split(" ")
156
+ # req = Net::HTTP::Post.new("/1.0/containers/#{@container_name}/exec")
157
+ # req["Content-Type"] = "application/json"
158
+ # payload = {
159
+ # "command" => commands,
160
+ # "environment" => {
161
+ # "HOME" => "/root",
162
+ # "TERM" => "screen",
163
+ # "USER" => "root",
164
+ # },
165
+ # "wait-for-websocket" => true,
166
+ # "interactive" => true,
167
+ # }
168
+ # req.body = payload.to_json
169
+ #
170
+ # resp = client.request(req)
171
+ # json = JSON.parse(resp.body)
172
+
173
+ # operation_id = ""
174
+ # secret = ""
175
+
176
+ # if json['metadata']
177
+ # operation_id = json['metadata']['id']
178
+ # unless json['metadata']['metadata'] == nil
179
+ # secret = json['metadata']['metadata']['fds']['0']
180
+ # return operation_id, secret
181
+ # else
182
+ # return operation_id
183
+ # end
184
+ # end
185
+
186
+ end
187
+
188
+ def run_exec(operation_id, secret)
189
+ # run_lxc_exec
190
+ end
191
+
192
+ def run_lxc_exec(command)
193
+ lxc_exec = "lxc exec #{@container_name} -- "
194
+ run_command = lxc_exec + command
195
+ status = system(run_command)
196
+ return status
197
+ end
198
+
199
+ #def wait_operation(operation_id)
200
+ # req = Net::HTTP::Get.new("/1.0/operations/#{operation_id}/wait")
201
+ # resp = client.request(req)
202
+ # return resp.body
203
+ #end
204
+
205
+ end
206
+ end
@@ -0,0 +1,3 @@
1
+ module OrenoLxdapi
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,28 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'oreno_lxdapi/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "oreno_lxdapi"
8
+ spec.version = OrenoLxdapi::VERSION
9
+ spec.authors = ["inokappa"]
10
+ spec.email = ["inokara at gmail.com"]
11
+
12
+ spec.summary = %q{oreno}
13
+ spec.description = %q{lxdapi}
14
+ spec.homepage = ""
15
+
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
18
+ spec.bindir = "exe"
19
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
+ spec.require_paths = ["lib"]
21
+
22
+ spec.add_dependency "net_http_unix"
23
+
24
+ spec.add_development_dependency "bundler", "~> 1.10"
25
+ spec.add_development_dependency "rake", "~> 10.0"
26
+ spec.add_development_dependency "rspec"
27
+ spec.add_development_dependency "pry"
28
+ end
metadata ADDED
@@ -0,0 +1,122 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: oreno_lxdapi
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - inokappa
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2016-01-02 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: net_http_unix
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.10'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.10'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '10.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '10.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: pry
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: lxdapi
84
+ email:
85
+ - inokara at gmail.com
86
+ executables: []
87
+ extensions: []
88
+ extra_rdoc_files: []
89
+ files:
90
+ - ".gitignore"
91
+ - ".rspec"
92
+ - ".travis.yml"
93
+ - Gemfile
94
+ - README.md
95
+ - Rakefile
96
+ - lib/oreno_lxdapi.rb
97
+ - lib/oreno_lxdapi/version.rb
98
+ - oreno_lxdapi.gemspec
99
+ homepage: ''
100
+ licenses: []
101
+ metadata: {}
102
+ post_install_message:
103
+ rdoc_options: []
104
+ require_paths:
105
+ - lib
106
+ required_ruby_version: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ required_rubygems_version: !ruby/object:Gem::Requirement
112
+ requirements:
113
+ - - ">="
114
+ - !ruby/object:Gem::Version
115
+ version: '0'
116
+ requirements: []
117
+ rubyforge_project:
118
+ rubygems_version: 2.2.2
119
+ signing_key:
120
+ specification_version: 4
121
+ summary: oreno
122
+ test_files: []