leofs_manager_client 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ *.swp
4
+ .bundle
5
+ .config
6
+ .yardoc
7
+ Gemfile.lock
8
+ InstalledFiles
9
+ _yardoc
10
+ coverage
11
+ doc/
12
+ lib/bundler/man
13
+ pkg
14
+ rdoc
15
+ spec/reports
16
+ test/tmp
17
+ test/version_tmp
18
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in leofs_manager.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,178 @@
1
+
2
+ Apache License
3
+ Version 2.0, January 2004
4
+ http://www.apache.org/licenses/
5
+
6
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7
+
8
+ 1. Definitions.
9
+
10
+ "License" shall mean the terms and conditions for use, reproduction,
11
+ and distribution as defined by Sections 1 through 9 of this document.
12
+
13
+ "Licensor" shall mean the copyright owner or entity authorized by
14
+ the copyright owner that is granting the License.
15
+
16
+ "Legal Entity" shall mean the union of the acting entity and all
17
+ other entities that control, are controlled by, or are under common
18
+ control with that entity. For the purposes of this definition,
19
+ "control" means (i) the power, direct or indirect, to cause the
20
+ direction or management of such entity, whether by contract or
21
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
22
+ outstanding shares, or (iii) beneficial ownership of such entity.
23
+
24
+ "You" (or "Your") shall mean an individual or Legal Entity
25
+ exercising permissions granted by this License.
26
+
27
+ "Source" form shall mean the preferred form for making modifications,
28
+ including but not limited to software source code, documentation
29
+ source, and configuration files.
30
+
31
+ "Object" form shall mean any form resulting from mechanical
32
+ transformation or translation of a Source form, including but
33
+ not limited to compiled object code, generated documentation,
34
+ and conversions to other media types.
35
+
36
+ "Work" shall mean the work of authorship, whether in Source or
37
+ Object form, made available under the License, as indicated by a
38
+ copyright notice that is included in or attached to the work
39
+ (an example is provided in the Appendix below).
40
+
41
+ "Derivative Works" shall mean any work, whether in Source or Object
42
+ form, that is based on (or derived from) the Work and for which the
43
+ editorial revisions, annotations, elaborations, or other modifications
44
+ represent, as a whole, an original work of authorship. For the purposes
45
+ of this License, Derivative Works shall not include works that remain
46
+ separable from, or merely link (or bind by name) to the interfaces of,
47
+ the Work and Derivative Works thereof.
48
+
49
+ "Contribution" shall mean any work of authorship, including
50
+ the original version of the Work and any modifications or additions
51
+ to that Work or Derivative Works thereof, that is intentionally
52
+ submitted to Licensor for inclusion in the Work by the copyright owner
53
+ or by an individual or Legal Entity authorized to submit on behalf of
54
+ the copyright owner. For the purposes of this definition, "submitted"
55
+ means any form of electronic, verbal, or written communication sent
56
+ to the Licensor or its representatives, including but not limited to
57
+ communication on electronic mailing lists, source code control systems,
58
+ and issue tracking systems that are managed by, or on behalf of, the
59
+ Licensor for the purpose of discussing and improving the Work, but
60
+ excluding communication that is conspicuously marked or otherwise
61
+ designated in writing by the copyright owner as "Not a Contribution."
62
+
63
+ "Contributor" shall mean Licensor and any individual or Legal Entity
64
+ on behalf of whom a Contribution has been received by Licensor and
65
+ subsequently incorporated within the Work.
66
+
67
+ 2. Grant of Copyright License. Subject to the terms and conditions of
68
+ this License, each Contributor hereby grants to You a perpetual,
69
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70
+ copyright license to reproduce, prepare Derivative Works of,
71
+ publicly display, publicly perform, sublicense, and distribute the
72
+ Work and such Derivative Works in Source or Object form.
73
+
74
+ 3. Grant of Patent License. Subject to the terms and conditions of
75
+ this License, each Contributor hereby grants to You a perpetual,
76
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77
+ (except as stated in this section) patent license to make, have made,
78
+ use, offer to sell, sell, import, and otherwise transfer the Work,
79
+ where such license applies only to those patent claims licensable
80
+ by such Contributor that are necessarily infringed by their
81
+ Contribution(s) alone or by combination of their Contribution(s)
82
+ with the Work to which such Contribution(s) was submitted. If You
83
+ institute patent litigation against any entity (including a
84
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
85
+ or a Contribution incorporated within the Work constitutes direct
86
+ or contributory patent infringement, then any patent licenses
87
+ granted to You under this License for that Work shall terminate
88
+ as of the date such litigation is filed.
89
+
90
+ 4. Redistribution. You may reproduce and distribute copies of the
91
+ Work or Derivative Works thereof in any medium, with or without
92
+ modifications, and in Source or Object form, provided that You
93
+ meet the following conditions:
94
+
95
+ (a) You must give any other recipients of the Work or
96
+ Derivative Works a copy of this License; and
97
+
98
+ (b) You must cause any modified files to carry prominent notices
99
+ stating that You changed the files; and
100
+
101
+ (c) You must retain, in the Source form of any Derivative Works
102
+ that You distribute, all copyright, patent, trademark, and
103
+ attribution notices from the Source form of the Work,
104
+ excluding those notices that do not pertain to any part of
105
+ the Derivative Works; and
106
+
107
+ (d) If the Work includes a "NOTICE" text file as part of its
108
+ distribution, then any Derivative Works that You distribute must
109
+ include a readable copy of the attribution notices contained
110
+ within such NOTICE file, excluding those notices that do not
111
+ pertain to any part of the Derivative Works, in at least one
112
+ of the following places: within a NOTICE text file distributed
113
+ as part of the Derivative Works; within the Source form or
114
+ documentation, if provided along with the Derivative Works; or,
115
+ within a display generated by the Derivative Works, if and
116
+ wherever such third-party notices normally appear. The contents
117
+ of the NOTICE file are for informational purposes only and
118
+ do not modify the License. You may add Your own attribution
119
+ notices within Derivative Works that You distribute, alongside
120
+ or as an addendum to the NOTICE text from the Work, provided
121
+ that such additional attribution notices cannot be construed
122
+ as modifying the License.
123
+
124
+ You may add Your own copyright statement to Your modifications and
125
+ may provide additional or different license terms and conditions
126
+ for use, reproduction, or distribution of Your modifications, or
127
+ for any such Derivative Works as a whole, provided Your use,
128
+ reproduction, and distribution of the Work otherwise complies with
129
+ the conditions stated in this License.
130
+
131
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
132
+ any Contribution intentionally submitted for inclusion in the Work
133
+ by You to the Licensor shall be under the terms and conditions of
134
+ this License, without any additional terms or conditions.
135
+ Notwithstanding the above, nothing herein shall supersede or modify
136
+ the terms of any separate license agreement you may have executed
137
+ with Licensor regarding such Contributions.
138
+
139
+ 6. Trademarks. This License does not grant permission to use the trade
140
+ names, trademarks, service marks, or product names of the Licensor,
141
+ except as required for reasonable and customary use in describing the
142
+ origin of the Work and reproducing the content of the NOTICE file.
143
+
144
+ 7. Disclaimer of Warranty. Unless required by applicable law or
145
+ agreed to in writing, Licensor provides the Work (and each
146
+ Contributor provides its Contributions) on an "AS IS" BASIS,
147
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148
+ implied, including, without limitation, any warranties or conditions
149
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150
+ PARTICULAR PURPOSE. You are solely responsible for determining the
151
+ appropriateness of using or redistributing the Work and assume any
152
+ risks associated with Your exercise of permissions under this License.
153
+
154
+ 8. Limitation of Liability. In no event and under no legal theory,
155
+ whether in tort (including negligence), contract, or otherwise,
156
+ unless required by applicable law (such as deliberate and grossly
157
+ negligent acts) or agreed to in writing, shall any Contributor be
158
+ liable to You for damages, including any direct, indirect, special,
159
+ incidental, or consequential damages of any character arising as a
160
+ result of this License or out of the use or inability to use the
161
+ Work (including but not limited to damages for loss of goodwill,
162
+ work stoppage, computer failure or malfunction, or any and all
163
+ other commercial damages or losses), even if such Contributor
164
+ has been advised of the possibility of such damages.
165
+
166
+ 9. Accepting Warranty or Additional Liability. While redistributing
167
+ the Work or Derivative Works thereof, You may choose to offer,
168
+ and charge a fee for, acceptance of support, warranty, indemnity,
169
+ or other liability obligations and/or rights consistent with this
170
+ License. However, in accepting such obligations, You may act only
171
+ on Your own behalf and on Your sole responsibility, not on behalf
172
+ of any other Contributor, and only if You agree to indemnify,
173
+ defend, and hold each Contributor harmless for any liability
174
+ incurred by, or claims asserted against, such Contributor by reason
175
+ of your accepting any such warranty or additional liability.
176
+
177
+ END OF TERMS AND CONDITIONS
178
+
data/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # leofs_manager_client
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'leofs_manager'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install leofs_manager
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,33 @@
1
+ # ======================================================================
2
+ #
3
+ # LeoFS Manager Client
4
+ #
5
+ # Copyright (c) 2012 Rakuten, Inc.
6
+ #
7
+ # This file is provided to you under the Apache License,
8
+ # Version 2.0 (the "License"); you may not use this file
9
+ # except in compliance with the License. You may obtain
10
+ # a copy of the License at
11
+ #
12
+ # http://www.apache.org/licenses/LICENSE-2.0
13
+ #
14
+ # Unless required by applicable law or agreed to in writing,
15
+ # software distributed under the License is distributed on an
16
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17
+ # KIND, either express or implied. See the License for the
18
+ # specific language governing permissions and limitations
19
+ # under the License.
20
+ #
21
+ # ======================================================================
22
+ require 'rubygems'
23
+ require 'rake'
24
+ require "bundler/gem_tasks"
25
+ require 'rspec/core'
26
+ require 'rspec/core/rake_task'
27
+
28
+ task :default => :spec
29
+
30
+ desc "Run all specs in spec directory"
31
+ RSpec::Core::RakeTask.new(:spec) do |t|
32
+ t.rspec_opts = "-c -f d --tty"
33
+ end
@@ -0,0 +1,18 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "leofs_manager_client"
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "leofs_manager_client"
8
+ gem.version = LeoFSManager::VERSION
9
+ gem.authors = ["Masaki Matsushita", "Yosuke Hara"]
10
+ gem.email = ["leofaststorage@gmail.com"]
11
+ gem.description = %q{Client for LeoFS Manager}
12
+ gem.summary = %q{Client for LeoFS Manager}
13
+ gem.homepage = ""
14
+
15
+ gem.files = `git ls-files`.split($/)
16
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
17
+ gem.require_paths = ["lib"]
18
+ end
@@ -0,0 +1,114 @@
1
+ module LeoFSManager
2
+ ## ======================================================================
3
+ ## CLASS
4
+ ## ======================================================================
5
+ ## @doc System Information Model
6
+ ##
7
+ class Status
8
+ class SystemInfo
9
+ def initialize(h)
10
+ @version = h[:version]
11
+ @n = h[:n]
12
+ @r = h[:r]
13
+ @w = h[:w]
14
+ @d = h[:d]
15
+ @ring_size = h[:ring_size]
16
+ @ring_cur = h[:ring_cur]
17
+ @ring_prev = h[:ring_prev]
18
+ end
19
+
20
+ attr_reader :version, :n, :r, :w, :d, :ring_size, :ring_cur, :ring_prev
21
+ end
22
+
23
+ ## @doc Node Info Model
24
+ ##
25
+ class NodeInfo
26
+ def initialize(h)
27
+ @type = h[:type]
28
+ @node = h[:node]
29
+ @state = h[:state]
30
+ @ring_cur = h[:ring_cur]
31
+ @ring_prev = h[:ring_prev]
32
+ @joined_at = h[:when]
33
+ end
34
+
35
+ attr_reader :type, :node, :state, :ring_cur, :ring_prev, :joined_at
36
+ end
37
+
38
+ ## @doc Node Status Model
39
+ ##
40
+ class NodeStat
41
+ def initialize(h)
42
+ @type = h[:version]
43
+ @log_dir = h[:log_dir]
44
+ @ring_cur = h[:ring_cur]
45
+ @ring_prev = h[:ring_prev]
46
+ @total_mem_usage = h[:total_mem_usage]
47
+ @system_mem_usage = h[:system_mem_usage]
48
+ @procs_mem_usage = h[:procs_mem_usage]
49
+ @ets_mem_usage = h[:ets_mem_usage]
50
+ @num_of_procs = h[:num_of_procs]
51
+ end
52
+
53
+ attr_reader :version, :log_dir, :ring_cur, :ring_prev, :tota_mem_usage,
54
+ :system_mem_usage, :procs_mem_usage, :ets_mem_usage, :num_of_procs
55
+ end
56
+
57
+ def initialize(h)
58
+ @node_stat = NodeStat.new(h[:node_stat]) if h.has_key?(:node_stat)
59
+ @system_info = SystemInfo.new(h[:system_info]) if h.has_key?(:system_info)
60
+ @node_list = h[:node_list].map {|node| NodeInfo.new(node) } if h.has_key?(:node_list)
61
+ end
62
+
63
+ attr_reader :node_stat, :system_info, :node_list
64
+ end
65
+
66
+ class WhereInfo
67
+ def initialize(h)
68
+ @node = h[:node]
69
+ @vnode_id = h[:vnode_id]
70
+ @size = h[:size]
71
+ @clock = h[:clock]
72
+ @checksum = h[:checksum]
73
+ @timestamp = h[:timestamp]
74
+ @delete = h[:delete]
75
+ end
76
+
77
+ attr_reader :node, :vnode_id, :size, :clock, :checksum, :timestamp, :delete
78
+ end
79
+
80
+ class DiskUsage
81
+ def initialize(h)
82
+ @file_size = h[:file_size]
83
+ @total_of_objects = h[:total_of_objects]
84
+ end
85
+
86
+ attr_reader :file_size, :total_of_objects
87
+ end
88
+
89
+ class Credential
90
+ def initialize(h)
91
+ @access_key_id = h[:access_key_id]
92
+ @secret_access_key = h[:secret_access_key]
93
+ end
94
+
95
+ attr_reader :access_key_id, :secret_access_key
96
+ end
97
+
98
+ class Endpoint
99
+ def initialize(h)
100
+ @endpoint = h[:endpoint]
101
+ @created_at = h[:created_at]
102
+ end
103
+
104
+ attr_reader :endpoint, :created_at
105
+ end
106
+
107
+ class Bucket
108
+ def initialize(h)
109
+ @name = h[:bucket]
110
+ @owner = h[:owner]
111
+ @created_at = Time.parse(h[:created_at])
112
+ end
113
+ end
114
+ end
@@ -0,0 +1,267 @@
1
+ # ======================================================================
2
+ #
3
+ # LeoFS Manager Client
4
+ #
5
+ # Copyright (c) 2012 Rakuten, Inc.
6
+ #
7
+ # This file is provided to you under the Apache License,
8
+ # Version 2.0 (the "License"); you may not use this file
9
+ # except in compliance with the License. You may obtain
10
+ # a copy of the License at
11
+ #
12
+ # http://www.apache.org/licenses/LICENSE-2.0
13
+ #
14
+ # Unless required by applicable law or agreed to in writing,
15
+ # software distributed under the License is distributed on an
16
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17
+ # KIND, either express or implied. See the License for the
18
+ # specific language governing permissions and limitations
19
+ # under the License.
20
+ #
21
+ # ======================================================================
22
+ require "socket"
23
+ require "json"
24
+ require "time"
25
+
26
+ require_relative "leofs_manager_client/leofs_manager_models"
27
+
28
+ module LeoFSManager
29
+ VERSION = "0.2.1"
30
+
31
+ class Remover
32
+ def initialize(data)
33
+ @data = data
34
+ end
35
+
36
+ def call(*args)
37
+ socket = @data[0]
38
+ socket.close if socket && !socket.closed?
39
+ warn "Closed socket: #{socket}" if $DEBUG
40
+ end
41
+ end
42
+
43
+ class Client
44
+ ## LeoFS-related commands:
45
+ CMD_VERSION = "version"
46
+ CMD_STATUS = "status %s"
47
+ CMD_START = "start"
48
+ CMD_DETACH = "detach %s"
49
+ CMD_SUSPEND = "suspend %s"
50
+ CMD_RESUME = "resume %s"
51
+ CMD_REBALANCE = "rebalance"
52
+ CMD_WHEREIS = "whereis %s"
53
+ CMD_DU = "du %s"
54
+ CMD_COMPACT = "compact %s"
55
+ CMD_PURGE = "purge %s"
56
+ CMD_S3_GEN_KEY = "s3-gen-key %s"
57
+ CMD_S3_SET_ENDPOINT = "s3-set-endpoint %s"
58
+ CMD_S3_DEL_ENDPOINT = "s3-delete-endpoint %s"
59
+ CMD_S3_GET_ENDPOINTS = "s3-get-endpoints"
60
+ CMD_S3_ADD_BUCKET = "s3-add-bucket %s %s"
61
+ CMD_S3_GET_BUCKETS = "s3-get-buckets"
62
+
63
+ ## ======================================================================
64
+ ## APIs
65
+ ## ======================================================================
66
+ ## @doc Constructor
67
+ ##
68
+ def initialize(*servers)
69
+ @servers = parse_servers(servers)
70
+ set_current_server
71
+ final = Remover.new(@data = [])
72
+ ObjectSpace.define_finalizer(self, final)
73
+ connect
74
+ end
75
+
76
+ attr_reader :servers, :current_server
77
+
78
+ ## @doc Retrieve LeoFS's version from LeoFS Manager
79
+ ## @return version
80
+ def version
81
+ h = sender(CMD_VERSION)
82
+ return h[:result]
83
+ end
84
+
85
+ ## @doc Retrieve LeoFS's system status from LeoFS Manager
86
+ ## @return
87
+ def status(node=nil)
88
+ Status.new(sender(CMD_STATUS % node))
89
+ end
90
+
91
+ ## @doc Launch LeoFS's storage cluster
92
+ ## @return nil
93
+ def start
94
+ sender(CMD_START)
95
+ nil
96
+ end
97
+
98
+ ## @doc Leave a node from the storage cluster
99
+ ##
100
+ def detach(node)
101
+ sender(CMD_DETACH % node)
102
+ nil
103
+ end
104
+
105
+ ## @doc Suspend a node in the storage cluster
106
+ ##
107
+ def suspend(node)
108
+ sender(CMD_SUSPEND % node)
109
+ nil
110
+ end
111
+
112
+ ## @doc Resume a node in the storage cluster
113
+ ##
114
+ def resume(node)
115
+ sender(CMD_RESUME % node)
116
+ nil
117
+ end
118
+
119
+ ## @doc Execute 'rebalance' in the storage cluster
120
+ ##
121
+ def rebalance
122
+ sender(CMD_REBALANCE)
123
+ nil
124
+ end
125
+
126
+ ## @doc Retrieve assigned file information
127
+ ##
128
+ def whereis(path)
129
+ whereis = sender(CMD_WHEREIS % path)[:buckets]
130
+ whereis.map {|h| WhereInfo.new(h)}
131
+ end
132
+
133
+ ## @doc Retrieve storage status from the storage
134
+ ##
135
+ def du(node)
136
+ DiskUsage.new(sender(CMD_DU % node))
137
+ end
138
+
139
+ ## @doc Execute 'compaction'
140
+ ##
141
+ def compact(node)
142
+ sender(CMD_COMPACT % node)
143
+ nil
144
+ end
145
+
146
+ ## @doc Purge a cache in gateways
147
+ ##
148
+ def purge(path)
149
+ sender(CMD_PURGE % path)
150
+ nil
151
+ end
152
+
153
+ ## @doc Generate credential for LeoFS
154
+ ##
155
+ def s3_gen_key(user_id)
156
+ Credential.new(sender(CMD_S3_GEN_KEY % user_id))
157
+ end
158
+
159
+ ## @doc Insert an endpoint in the system
160
+ ##
161
+ def s3_set_endpoint(endpoint)
162
+ sender(CMD_S3_SET_ENDPOINT % endpoint)
163
+ nil
164
+ end
165
+
166
+ ## @doc Remove an endpoint from the system
167
+ ##
168
+ def s3_del_endpoint(endpoint)
169
+ sender(CMD_S3_DEL_ENDPOINT % endpoint)
170
+ nil
171
+ end
172
+
173
+ ## @doc Retrieve an endpoint in the system
174
+ ##
175
+ def s3_get_endpoints
176
+ endpoints = sender(CMD_S3_GET_ENDPOINTS)[:endpoints]
177
+ endpoints.map {|endpoint| Endpoint.new(endpoint) }
178
+ end
179
+
180
+ def s3_add_bucket(bucket_name, access_key_id)
181
+ sender(CMD_S3_ADD_BUCKET % [bucket_name, access_key_id])
182
+ nil
183
+ end
184
+
185
+ ## @doc Retrieve all buckets from the system
186
+ ##
187
+ def s3_get_buckets
188
+ buckets = sender(CMD_S3_GET_BUCKETS)[:buckets]
189
+ buckets.map {|bucket| Bucket.new(bucket) }
190
+ end
191
+
192
+ ## ======================================================================
193
+ ## PRIVATE
194
+ ## ======================================================================
195
+ private
196
+
197
+ def parse_servers(servers)
198
+ servers.map do |server|
199
+ if server.is_a? String
200
+ m = server.match(/(?<host>.+):(?<port>[0-9]{1,5})/)
201
+ host = m[:host]
202
+ port = Integer(m[:port])
203
+
204
+ raise Error, "Invalid Port Number: #{port}" unless 0 <= port && port <= 65535
205
+ { :host => host, :port => port, :retry_count => 0 }
206
+ else
207
+ server
208
+ end
209
+ end
210
+ end
211
+
212
+ ## @doc
213
+ ##
214
+ def set_current_server
215
+ raise Error, "No servers to connect" if @servers.empty?
216
+ @current_server = @servers.first
217
+ end
218
+
219
+ ## @doc Connect to LeoFS Manager
220
+ ##
221
+ def connect
222
+ retry_count = 0
223
+ begin
224
+ @socket = TCPSocket.new(@current_server[:host], @current_server[:port])
225
+ @data[0] = @socket
226
+ rescue => ex
227
+ warn "Faild to connect: #{ex.class} (server: #{@current_server})"
228
+ warn ex.message
229
+ retry_count += 1
230
+ if retry_count > 3
231
+ warn "Connecting another server..."
232
+ @socket.close if @socket && !@socket.closed?
233
+ @servers.delete(@current_server)
234
+ set_current_server
235
+ retry_count = 0
236
+ end
237
+ retry
238
+ end
239
+ end
240
+
241
+ ## @doc Send a request to LeoFS Manager
242
+ ## @return Hash
243
+ def sender(command)
244
+ begin
245
+ @socket.puts command
246
+ response = JSON.parse(@socket.gets, symbolize_names: true)
247
+ rescue => ex
248
+ raise "An Error occured: #{ex.class} (server: #{@current_server})\n#{ex.message}"
249
+ end
250
+ raise response[:error] if response.has_key?(:error)
251
+ return response
252
+ end
253
+ end
254
+ end
255
+
256
+
257
+ if __FILE__ == $PROGRAM_NAME
258
+ require "pp"
259
+
260
+ $DEBUG = true
261
+ m = LeoFSManager::Client.new("localhost:10020", "localhost:10021")
262
+ p m.version
263
+ p m.status
264
+ p m.status("storage_0@127.0.0.1")
265
+ p m.s3_get_buckets()
266
+ p m.whereis("photo/hawaii-0.jpg")
267
+ end
@@ -0,0 +1,231 @@
1
+ # ======================================================================
2
+ #
3
+ # LeoFS Manager Client
4
+ #
5
+ # Copyright (c) 2012 Rakuten, Inc.
6
+ #
7
+ # This file is provided to you under the Apache License,
8
+ # Version 2.0 (the "License"); you may not use this file
9
+ # except in compliance with the License. You may obtain
10
+ # a copy of the License at
11
+ #
12
+ # http://www.apache.org/licenses/LICENSE-2.0
13
+ #
14
+ # Unless required by applicable law or agreed to in writing,
15
+ # software distributed under the License is distributed on an
16
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17
+ # KIND, either express or implied. See the License for the
18
+ # specific language governing permissions and limitations
19
+ # under the License.
20
+ #
21
+ # ======================================================================
22
+
23
+ require "socket"
24
+ require "json"
25
+ require_relative "../lib/leofs_manager_client"
26
+
27
+ Host = "localhost"
28
+ Port = 50000
29
+
30
+ $DEBUG = false
31
+ Thread.abort_on_exception = true
32
+
33
+ module Dummy
34
+ module Response
35
+ Status = {
36
+ :system_info => {
37
+ :version => "0.10.1",
38
+ :n => "1",
39
+ :r => "1",
40
+ :w => "1",
41
+ :d => "1",
42
+ :ring_size => "128",
43
+ :ring_hash_cur => "2688134336",
44
+ :ring_hash_prev => "2688134336"},
45
+ :node_list => [
46
+ {
47
+ :type => "S",
48
+ :node => "storage_0@127.0.0.1",
49
+ :state => "running",
50
+ :ring_cur => "a039acc0",
51
+ :ring_prev => "a039acc0",
52
+ :when => "2012-09-21 15:08:22 +0900"
53
+ }, {
54
+ :type => "G",
55
+ :node => "gateway_0@127.0.0.1",
56
+ :state => "running",
57
+ :ring_cur => "a039acc0",
58
+ :ring_prev => "a039acc0",
59
+ :when => "2012-09-21 15:08:25 +0900"
60
+ }
61
+ ]
62
+ }.to_json
63
+
64
+ Whereis = {
65
+ :buckets => [
66
+ {
67
+ :node => "storage_0@127.0.0.1",
68
+ :vnode_id => "",
69
+ :size => "",
70
+ :clock => "",
71
+ :checksum => "",
72
+ :timestamp => "",
73
+ :delete => 0
74
+ }
75
+ ]
76
+ }.to_json
77
+
78
+ S3GetEndpoints = {
79
+ :endpoints => [
80
+ {:endpoint => "s3.amazonaws.com", :created_at=>"2012-09-21 15:08:11 +0900"},
81
+ {:endpoint => "localhost", :created_at=>"2012-09-21 15:08:11 +0900"},
82
+ {:endpoint => "foo", :created_at=>"2012-09-21 18:51:08 +0900"},
83
+ {:endpoint => "leofs.org", :created_at=>"2012-09-21 15:08:11 +0900"}
84
+ ]
85
+ }.to_json
86
+
87
+ S3GetBuckets = {
88
+ :buckets => [
89
+ {
90
+ :bucket => "test",
91
+ :owner => "test",
92
+ :created_at => "2012-09-24 15:38:49 +0900"
93
+ }
94
+ ]
95
+ }.to_json
96
+ end
97
+
98
+ Argument = "hoge" # passed to command which requires some arguments.
99
+
100
+ # dummy Manager
101
+ class Manager
102
+ Thread.new do
103
+ TCPServer.open(Host, Port) do |server|
104
+ loop do
105
+ socket = server.accept
106
+ while line = socket.gets.split.first
107
+ line.rstrip!
108
+ begin
109
+ case line
110
+ when "status"
111
+ result = Response::Status
112
+ when "s3-get-buckets"
113
+ result = Response::S3GetBuckets
114
+ when "whereis"
115
+ result = Response::Whereis
116
+ when "s3-get-endpoints"
117
+ result = Response::S3GetEndpoints
118
+ when "s3-get-buckets"
119
+ result = Response::S3GetBuckets
120
+ else
121
+ result = { :result => line }.to_json
122
+ end
123
+ rescue => ex
124
+ result = { :error => ex.message }.to_json
125
+ ensure
126
+ socket.puts(result)
127
+ end
128
+ end
129
+ end
130
+ end
131
+ end
132
+ end
133
+ end
134
+
135
+ # key: api_name, value: num of args
136
+ NoResultAPIs = {
137
+ :start => 0,
138
+ :detach => 1,
139
+ :rebalance => 0,
140
+ :compact => 1,
141
+ :purge => 1,
142
+ :s3_set_endpoint => 1,
143
+ :s3_del_endpoint => 1,
144
+ :s3_add_bucket => 2
145
+ }
146
+
147
+ include LeoFSManager
148
+
149
+ describe LeoFSManager do
150
+ before(:all) do
151
+ Dummy::Manager.new
152
+ @manager = Client.new("#{Host}:#{Port}")
153
+ end
154
+
155
+ it "has version" do
156
+ defined?(VERSION).should eql "constant"
157
+ VERSION.should eql "0.2.1"
158
+ end
159
+
160
+ it "raises error when it is passed invalid params" do
161
+ lambda { Client.new }.should raise_error
162
+ end
163
+
164
+ describe "#status" do
165
+ it "returns Status" do
166
+ @manager.status.should be_a Status
167
+ end
168
+
169
+ it "returns SystemInfo" do
170
+ @manager.status.system_info.should be_a Status::SystemInfo
171
+ end
172
+
173
+ it "returns node list" do
174
+ node_list = @manager.status.node_list
175
+ node_list.should be_a Array
176
+ node_list.each do |node|
177
+ node.should be_a Status::NodeInfo
178
+ end
179
+ end
180
+ end
181
+
182
+ describe "#whereis" do
183
+ it "returns Array of WhereInfo" do
184
+ result = @manager.whereis("path")
185
+ result.should be_a Array
186
+ result.each do |where_info|
187
+ where_info.should be_a WhereInfo
188
+ end
189
+ end
190
+ end
191
+
192
+ describe "#du" do
193
+ it "returns DiskUsage" do
194
+ @manager.du("node").should be_a DiskUsage
195
+ end
196
+ end
197
+
198
+ describe "#s3_gen_key" do
199
+ it "returns Credential" do
200
+ @manager.s3_gen_key("user_id").should be_a Credential
201
+ end
202
+ end
203
+
204
+ describe "#s3_get_endpoints" do
205
+ it "returns Arrany of Endpoint" do
206
+ result = @manager.s3_get_endpoints
207
+ result.should be_a Array
208
+ result.each do |endpoint|
209
+ endpoint.should be_a Endpoint
210
+ end
211
+ end
212
+ end
213
+
214
+ describe "#s3_get_buckets" do
215
+ it "returns Array of Bucket" do
216
+ result = @manager.s3_get_buckets
217
+ result.should be_a Array
218
+ result.each do |buckets|
219
+ buckets.should be_a Bucket
220
+ end
221
+ end
222
+ end
223
+
224
+ NoResultAPIs.each do |api, num_of_args|
225
+ describe "##{api}" do
226
+ it "returns nil" do
227
+ @manager.send(api, *(["argument"] * num_of_args)).should be_nil
228
+ end
229
+ end
230
+ end
231
+ end
metadata ADDED
@@ -0,0 +1,56 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: leofs_manager_client
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Masaki Matsushita
9
+ - Yosuke Hara
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2012-09-24 00:00:00.000000000 Z
14
+ dependencies: []
15
+ description: Client for LeoFS Manager
16
+ email:
17
+ - leofaststorage@gmail.com
18
+ executables: []
19
+ extensions: []
20
+ extra_rdoc_files: []
21
+ files:
22
+ - .gitignore
23
+ - Gemfile
24
+ - LICENSE.txt
25
+ - README.md
26
+ - Rakefile
27
+ - leofs_manager_client.gemspec
28
+ - lib/leofs_manager_client.rb
29
+ - lib/leofs_manager_client/leofs_manager_models.rb
30
+ - spec/leofs_manager_client_spec.rb
31
+ homepage: ''
32
+ licenses: []
33
+ post_install_message:
34
+ rdoc_options: []
35
+ require_paths:
36
+ - lib
37
+ required_ruby_version: !ruby/object:Gem::Requirement
38
+ none: false
39
+ requirements:
40
+ - - ! '>='
41
+ - !ruby/object:Gem::Version
42
+ version: '0'
43
+ required_rubygems_version: !ruby/object:Gem::Requirement
44
+ none: false
45
+ requirements:
46
+ - - ! '>='
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ requirements: []
50
+ rubyforge_project:
51
+ rubygems_version: 1.8.23
52
+ signing_key:
53
+ specification_version: 3
54
+ summary: Client for LeoFS Manager
55
+ test_files:
56
+ - spec/leofs_manager_client_spec.rb