ceph-ruby-ffi19 1.2

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 75ba7f7ee122ea4ec987fcc523f523d6564a2acc
4
+ data.tar.gz: 9ac2d1b1d3f05ae2f74b6f44ee1b7dfc8f8cea7b
5
+ SHA512:
6
+ metadata.gz: 761e5fa9f0e98077ec731a9f4e369aea8c8e70349e9e273a46138cfa4d864509da773e57c4129e4f7666d57d06053d6afb2d7f9ac1601891ccbbb9afb4b6c2bb
7
+ data.tar.gz: 6c04f18a1b4f489c6b0f7158829b678c6b53d4a53c84a77ce69d160308db83e4edeabbd8865203acf13026626ba8014d20408665558070b548c7e001a8ee349f
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in ceph-ruby.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 - 2013 Netskin GmbH
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,70 @@
1
+ # Ceph::Ruby
2
+
3
+ Easy management of Ceph Distributed Storage System (rbd, images, rados objects) using ruby.
4
+
5
+
6
+ ## Installation
7
+
8
+ Add this line to your application's Gemfile:
9
+
10
+ gem 'ceph-ruby'
11
+
12
+ And then execute:
13
+
14
+ $ bundle
15
+
16
+ Or install it yourself as:
17
+
18
+ $ gem install ceph-ruby
19
+
20
+
21
+ ## Usage
22
+
23
+ require "ceph-ruby"
24
+
25
+ # version information
26
+ puts CephRuby::Lib::Rados.version_string
27
+ puts CephRuby::Lib::Rbd.version_string
28
+
29
+ # connect to cluster and open a pool
30
+ cluster = CephRuby::Cluster.new
31
+ pool = cluster.pool("my-pool-xyz")
32
+ pool.open
33
+
34
+ # simple example for using rados objects
35
+ object = pool.rados_object("my-object-xyz")
36
+ object.write(0, "This is a Test!")
37
+ puts object.size
38
+
39
+ # simple example for using rbd images
40
+ image = pool.rados_block_device("my-image-xyz")
41
+ puts image.exists?
42
+ image.create(10.gigabytes)
43
+ puts image.exists?
44
+ puts image.size
45
+ image.write(0, "This is a Test!")
46
+ pp image.stat
47
+ image.close
48
+
49
+ # clean up
50
+ pool.close
51
+ cluster.shutdown
52
+
53
+
54
+ ## Known bugs
55
+
56
+ * Many features provided by ceph are not implemented yet. Please contribute!
57
+
58
+
59
+ ## Contributing
60
+
61
+ 1. Fork it
62
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
63
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
64
+ 4. Push to the branch (`git push origin my-new-feature`)
65
+ 5. Create new Pull Request
66
+
67
+
68
+ ## Copyright
69
+
70
+ Copyright (c) 2012 - 2013 [Netskin GmbH](http://www.netskin.com). Released unter the MIT license.
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/ceph-ruby.gemspec ADDED
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'ceph-ruby/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "ceph-ruby-ffi19"
8
+ gem.version = CephRuby::VERSION
9
+ gem.authors = ["Netskin GmbH", "Corin Langosch"]
10
+ gem.email = ["info@netskin.com", "info@corinlangosch.com"]
11
+ gem.description = %q{Easy management of Ceph}
12
+ gem.summary = %q{Easy management of Ceph Distributed Storage System using ruby}
13
+ gem.homepage = "https://github.com/ceph/ceph-ruby"
14
+ gem.license = "MIT"
15
+
16
+ gem.files = `git ls-files`.split($/)
17
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
18
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
19
+ gem.require_paths = ["lib"]
20
+
21
+ gem.add_dependency('ffi', '~> 1.9.10')
22
+ gem.add_dependency('activesupport', '>= 3.0.0')
23
+ end
@@ -0,0 +1,55 @@
1
+ module CephRuby
2
+ class Cluster
3
+ attr_accessor :handle
4
+
5
+ def initialize(config_path = "/etc/ceph/ceph.conf")
6
+ log("init lib rados #{Lib::Rados.version_string}, lib rbd #{Lib::Rbd.version_string}")
7
+
8
+ handle_p = FFI::MemoryPointer.new(:pointer)
9
+ ret = Lib::Rados.rados_create(handle_p, nil)
10
+ raise SystemCallError.new("open of cluster failed", -ret) if ret < 0
11
+ self.handle = handle_p.get_pointer(0)
12
+
13
+ setup_using_file(config_path)
14
+
15
+ connect
16
+
17
+ if block_given?
18
+ begin
19
+ yield(self)
20
+ ensure
21
+ close
22
+ end
23
+ end
24
+ end
25
+
26
+ def close
27
+ return unless handle
28
+ log("close")
29
+ Lib::Rados.rados_shutdown(handle)
30
+ self.handle = nil
31
+ end
32
+
33
+ def pool(name, &block)
34
+ Pool.new(self, name, &block)
35
+ end
36
+
37
+ # helper methods below
38
+
39
+ def connect
40
+ log("connect")
41
+ ret = Lib::Rados.rados_connect(handle)
42
+ raise SystemCallError.new("connect to cluster failed", -ret) if ret < 0
43
+ end
44
+
45
+ def setup_using_file(path)
46
+ log("setup_using_file #{path}")
47
+ ret = Lib::Rados.rados_conf_read_file(handle, path)
48
+ raise SystemCallError.new("setup of cluster from config file '#{path}' failed", -ret) if ret < 0
49
+ end
50
+
51
+ def log(message)
52
+ CephRuby.log("cluster #{message}")
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,47 @@
1
+ require "ffi"
2
+
3
+ # see https://github.com/ceph/ceph/blob/v0.48.2argonaut/src/pybind/rados.py
4
+
5
+ module CephRuby
6
+ module Lib
7
+ module Rados
8
+ extend FFI::Library
9
+
10
+ ffi_lib ['rados', 'librados.so.2']
11
+
12
+ attach_function 'rados_version', [:pointer, :pointer, :pointer], :void
13
+
14
+ attach_function 'rados_create', [:pointer, :string], :int
15
+ attach_function 'rados_connect', [:pointer], :int
16
+ attach_function 'rados_conf_read_file', [:pointer, :string], :int
17
+ attach_function 'rados_shutdown', [:pointer], :void
18
+
19
+ attach_function 'rados_pool_lookup', [:pointer, :string], :int
20
+
21
+ attach_function 'rados_ioctx_create', [:pointer, :string, :pointer], :int
22
+ attach_function 'rados_ioctx_destroy', [:pointer], :void
23
+
24
+ attach_function 'rados_write', [:pointer, :string, :buffer_in, :size_t, :off_t], :int
25
+ attach_function 'rados_read', [:pointer, :string, :buffer_out, :size_t, :off_t], :int
26
+ attach_function 'rados_remove', [:pointer, :string], :int
27
+ attach_function 'rados_trunc', [:pointer, :string, :size_t], :int
28
+ attach_function 'rados_stat', [:pointer, :string, :pointer, :pointer], :int
29
+
30
+ def self.version
31
+ major = FFI::MemoryPointer.new(:int)
32
+ minor= FFI::MemoryPointer.new(:int)
33
+ extra = FFI::MemoryPointer.new(:int)
34
+ rados_version(major, minor, extra)
35
+ {
36
+ :major => major.get_int(0),
37
+ :minor => minor.get_int(0),
38
+ :extra => extra.get_int(0),
39
+ }
40
+ end
41
+
42
+ def self.version_string
43
+ "#{version[:major]}.#{version[:minor]}.#{version[:extra]}"
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,66 @@
1
+ require "ffi"
2
+
3
+ # see https://github.com/ceph/ceph/blob/v0.48.2argonaut/src/pybind/rbd.py
4
+
5
+ module CephRuby
6
+ module Lib
7
+ module Rbd
8
+ extend FFI::Library
9
+
10
+ ffi_lib ['rbd', 'librbd.so.1']
11
+
12
+ attach_function 'rbd_version', [:pointer, :pointer, :pointer], :void
13
+
14
+ attach_function 'rbd_create2', [:pointer, :string, :size_t, :uint64, :pointer], :int
15
+ attach_function 'rbd_remove', [:pointer, :string], :int
16
+
17
+ attach_function 'rbd_open', [:pointer, :string, :pointer, :string], :int
18
+ attach_function 'rbd_close', [:pointer], :void
19
+
20
+ attach_function 'rbd_write', [:pointer, :off_t, :size_t, :buffer_in], :int
21
+ attach_function 'rbd_read', [:pointer, :off_t, :size_t, :buffer_out], :int
22
+ attach_function 'rbd_stat', [:pointer, :pointer, :size_t], :int
23
+ attach_function 'rbd_resize', [:pointer, :size_t], :int
24
+ attach_function 'rbd_get_size', [:pointer, :pointer], :int
25
+ attach_function 'rbd_get_features', [:pointer, :pointer], :int
26
+
27
+ attach_function 'rbd_copy', [:pointer, :pointer, :string], :int
28
+ attach_function 'rbd_copy_with_progress', [:pointer, :pointer, :string, :pointer, :pointer], :int
29
+
30
+ attach_function 'rbd_snap_create', [:pointer, :string], :int
31
+ attach_function 'rbd_snap_remove', [:pointer, :string], :int
32
+ attach_function 'rbd_snap_protect', [:pointer, :string], :int
33
+ attach_function 'rbd_snap_unprotect', [:pointer, :string], :int
34
+ attach_function 'rbd_snap_set', [:pointer, :string], :int
35
+
36
+ attach_function 'rbd_clone', [:pointer, :string, :string, :pointer, :string, :uint64, :pointer], :int
37
+ attach_function 'rbd_flatten', [:pointer], :int
38
+
39
+ class StatStruct < FFI::Struct
40
+ layout :size, :uint64,
41
+ :obj_size, :uint64,
42
+ :num_objs, :uint64,
43
+ :order, :int,
44
+ :block_name_prefix, [:char, 24],
45
+ :parent_pool, :int, # deprecated
46
+ :parent_name, [:char, 96] # deprecated
47
+ end
48
+
49
+ def self.version
50
+ major = FFI::MemoryPointer.new(:int)
51
+ minor= FFI::MemoryPointer.new(:int)
52
+ extra = FFI::MemoryPointer.new(:int)
53
+ rbd_version(major, minor, extra)
54
+ {
55
+ :major => major.get_int(0),
56
+ :minor => minor.get_int(0),
57
+ :extra => extra.get_int(0),
58
+ }
59
+ end
60
+
61
+ def self.version_string
62
+ "#{version[:major]}.#{version[:minor]}.#{version[:extra]}"
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,66 @@
1
+ module CephRuby
2
+ class Pool
3
+ attr_accessor :cluster, :name, :handle
4
+
5
+ def initialize(cluster, name)
6
+ self.cluster = cluster
7
+ self.name = name
8
+ if block_given?
9
+ begin
10
+ yield(self)
11
+ ensure
12
+ close
13
+ end
14
+ end
15
+ end
16
+
17
+ def exists?
18
+ log("exists?")
19
+ ret = Lib::Rados.rados_pool_lookup(cluster.handle, name)
20
+ return true if ret >= 0
21
+ return false if ret == -Errno::ENOENT::Errno
22
+ raise SystemCallError.new("lookup of '#{name}' failed", -ret) if ret < 0
23
+ end
24
+
25
+ def open
26
+ return if open?
27
+ log("open")
28
+ handle_p = FFI::MemoryPointer.new(:pointer)
29
+ ret = Lib::Rados.rados_ioctx_create(cluster.handle, name, handle_p)
30
+ raise SystemCallError.new("creation of io context for '#{name}' failed", -ret) if ret < 0
31
+ self.handle = handle_p.get_pointer(0)
32
+ end
33
+
34
+ def close
35
+ return unless open?
36
+ log("close")
37
+ Lib::Rados.rados_ioctx_destroy(handle)
38
+ self.handle = nil
39
+ end
40
+
41
+ def rados_object(name, &block)
42
+ ensure_open
43
+ RadosObject.new(self, name, &block)
44
+ end
45
+
46
+ def rados_block_device(name, &block)
47
+ ensure_open
48
+ RadosBlockDevice.new(self, name, &block)
49
+ end
50
+
51
+ # helper methods below
52
+
53
+ def open?
54
+ !!handle
55
+ end
56
+
57
+ def ensure_open
58
+ return if open?
59
+ open
60
+ end
61
+
62
+ def log(message)
63
+ CephRuby.log("pool #{name} #{message}")
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,212 @@
1
+ module CephRuby
2
+ class RadosBlockDevice
3
+ FEATURE_LAYERING = 1
4
+ FEATURE_STRIPING_V2 = 2
5
+ FEATURE_EXCLUSIVE_LOCK = 4
6
+ FEATURE_OBJECT_MAP = 8
7
+
8
+ attr_accessor :pool, :name, :handle
9
+
10
+ delegate :cluster, :to => :pool
11
+
12
+ def initialize(pool, name)
13
+ self.pool = pool
14
+ self.name = name
15
+ if block_given?
16
+ begin
17
+ yield(self)
18
+ ensure
19
+ close
20
+ end
21
+ end
22
+ end
23
+
24
+ def exists?
25
+ log("exists?")
26
+ handle_p = FFI::MemoryPointer.new(:pointer)
27
+ ret = Lib::Rbd.rbd_open(pool.handle, name, handle_p, nil)
28
+ case ret
29
+ when 0
30
+ handle = handle_p.get_pointer(0)
31
+ Lib::Rbd.rbd_close(handle)
32
+ true
33
+ when -Errno::ENOENT::Errno
34
+ false
35
+ else
36
+ raise SystemCallError.new("open of '#{name}' failed", -ret) if ret < 0
37
+ end
38
+ end
39
+
40
+ def create(size, features = 0, order = 0)
41
+ log("create size #{size}, features #{features}, order #{order}")
42
+ order_p = FFI::MemoryPointer.new(:int)
43
+ order_p.put_int(0, order)
44
+ ret = Lib::Rbd.rbd_create2(pool.handle, name, size, features, order_p)
45
+ raise SystemCallError.new("creation of '#{name}' failed", -ret) if ret < 0
46
+ end
47
+
48
+ def open
49
+ return if open?
50
+ log("open")
51
+ handle_p = FFI::MemoryPointer.new(:pointer)
52
+ ret = Lib::Rbd.rbd_open(pool.handle, name, handle_p, nil)
53
+ raise SystemCallError.new("open of '#{name}' failed", -ret) if ret < 0
54
+ self.handle = handle_p.get_pointer(0)
55
+ end
56
+
57
+ def close
58
+ return unless open?
59
+ log("close")
60
+ Lib::Rbd.rbd_close(handle)
61
+ self.handle = nil
62
+ end
63
+
64
+ def destroy
65
+ close if open?
66
+ log("destroy")
67
+ ret = Lib::Rbd.rbd_remove(pool.handle, name)
68
+ raise SystemCallError.new("destroy of '#{name}' failed", -ret) if ret < 0
69
+ end
70
+
71
+ def write(offset, data)
72
+ ensure_open
73
+ size = data.bytesize
74
+ log("write offset #{offset}, size #{size}")
75
+ ret = Lib::Rbd.rbd_write(handle, offset, size, data)
76
+ raise SystemCallError.new("write of #{size} bytes to '#{name}' at #{offset} failed", -ret) if ret < 0
77
+ raise Errno::EIO.new("wrote only #{ret} of #{size} bytes to '#{name}' at #{offset}") if ret < size
78
+ end
79
+
80
+ def read(offset, size)
81
+ ensure_open
82
+ log("read offset #{offset}, size #{size}")
83
+ data_p = FFI::MemoryPointer.new(:char, size)
84
+ ret = Lib::Rbd.rbd_read(handle, offset, size, data_p)
85
+ raise SystemCallError.new("read of #{size} bytes from '#{name}' at #{offset} failed", -ret) if ret < 0
86
+ data_p.get_bytes(0, ret)
87
+ end
88
+
89
+ def stat
90
+ ensure_open
91
+ log("stat")
92
+ stat = Lib::Rbd::StatStruct.new
93
+ ret = Lib::Rbd.rbd_stat(handle, stat, stat.size)
94
+ raise SystemCallError.new("stat of '#{name}' failed", -ret) if ret < 0
95
+ Hash[[:size, :obj_size, :num_objs, :order].map{ |k| [k, stat[k]] }].tap do |hash|
96
+ hash[:block_name_prefix] = stat[:block_name_prefix].to_ptr.read_string
97
+ end
98
+ end
99
+
100
+ def size
101
+ ensure_open
102
+ log("size")
103
+ size_p = FFI::MemoryPointer.new(:uint64)
104
+ ret = Lib::Rbd.rbd_get_size(handle, size_p)
105
+ raise SystemCallError.new("size of '#{name}' failed", -ret) if ret < 0
106
+ size_p.read_uint64
107
+ end
108
+
109
+ def features
110
+ ensure_open
111
+ log("features")
112
+ features_p = FFI::MemoryPointer.new(:uint64)
113
+ ret = Lib::Rbd.rbd_get_features(handle, features_p)
114
+ raise SystemCallError.new("features of '#{name}' failed", -ret) if ret < 0
115
+ features_p.read_uint64
116
+ end
117
+
118
+ def resize(size)
119
+ ensure_open
120
+ log("resize size #{size}")
121
+ ret = Lib::Rbd.rbd_resize(handle, size)
122
+ raise SystemCallError.new("resize of '#{name}' to #{size} failed", -ret) if ret < 0
123
+ end
124
+
125
+ def copy_to(dst_name, dst_pool = nil)
126
+ ensure_open
127
+ case dst_pool
128
+ when String
129
+ dst_pool = cluster.pool(dst_pool)
130
+ when nil
131
+ dst_pool = pool
132
+ end
133
+ dst_pool.ensure_open
134
+ log("copy_to #{dst_pool.name}/#{dst_name}")
135
+ ret = Lib::Rbd.rbd_copy(handle, dst_pool.handle, dst_name)
136
+ raise SystemCallError.new("copy of '#{name}' to '#{dst_pool.name}/#{dst_name}' failed", -ret) if ret < 0
137
+ end
138
+
139
+ def snapshot_create(name)
140
+ log("snapshot_create #{name}")
141
+ ensure_open
142
+ ret = Lib::Rbd.rbd_snap_create(handle, name)
143
+ raise SystemCallError.new("snapshot create '#{name}' of '#{self.name}' failed", -ret) if ret < 0
144
+ end
145
+
146
+ def snapshot_destroy(name)
147
+ log("snapshot_destroy #{name}")
148
+ ensure_open
149
+ ret = Lib::Rbd.rbd_snap_remove(handle, name)
150
+ raise SystemCallError.new("snapshot destroy '#{name}' of '#{self.name}' failed", -ret) if ret < 0
151
+ end
152
+
153
+ def snapshot_protect(name)
154
+ log("snapshot_protect #{name}")
155
+ ensure_open
156
+ ret = Lib::Rbd.rbd_snap_protect(handle, name)
157
+ raise SystemCallError.new("snapshot protect '#{name}' of '#{self.name}' failed", -ret) if ret < 0
158
+ end
159
+
160
+ def snapshot_unprotect(name)
161
+ log("snapshot_unprotect #{name}")
162
+ ensure_open
163
+ ret = Lib::Rbd.rbd_snap_unprotect(handle, name)
164
+ raise SystemCallError.new("snapshot unprotect '#{name}' of '#{self.name}' failed", -ret) if ret < 0
165
+ end
166
+
167
+ def snapshot_activate(name)
168
+ log("snapshot_activate #{name}")
169
+ ensure_open
170
+ ret = Lib::Rbd.rbd_snap_set(handle, name)
171
+ raise SystemCallError.new("activate snapshot '#{name}' of '#{self.name}' failed", -ret) if ret < 0
172
+ end
173
+
174
+ def clone(snapshot, dst_name, dst_pool = nil, features = 0, order = 0)
175
+ ensure_open
176
+ case dst_pool
177
+ when String
178
+ dst_pool = cluster.pool(dst_pool)
179
+ when nil
180
+ dst_pool = pool
181
+ end
182
+ dst_pool.ensure_open
183
+ log("clone snapshot #{snapshot} to #{dst_pool.name}/#{dst_name} features #{features} order #{order}")
184
+ order_p = FFI::MemoryPointer.new(:int)
185
+ order_p.put_int(0, order)
186
+ ret = Lib::Rbd.rbd_clone(pool.handle, name, snapshot, dst_pool.handle, dst_name, features, order_p)
187
+ raise SystemCallError.new("clone of '#{name}@#{snapshot}' to '#{dst_pool.name}/#{dst_name}' failed", -ret) if ret < 0
188
+ end
189
+
190
+ def flatten
191
+ log("flatten")
192
+ ensure_open
193
+ ret = Lib::Rbd.rbd_flatten(handle)
194
+ raise SystemCallError.new("flatten of '#{name}' failed", -ret) if ret < 0
195
+ end
196
+
197
+ # helper methods below
198
+
199
+ def open?
200
+ !!handle
201
+ end
202
+
203
+ def ensure_open
204
+ return if open?
205
+ open
206
+ end
207
+
208
+ def log(message)
209
+ CephRuby.log("rbd image #{pool.name}/#{name} #{message}")
210
+ end
211
+ end
212
+ end
@@ -0,0 +1,71 @@
1
+ module CephRuby
2
+ class RadosObject
3
+ attr_accessor :pool, :name
4
+
5
+ def initialize(pool, name)
6
+ self.pool = pool
7
+ self.name = name
8
+ if block_given?
9
+ yield(self)
10
+ end
11
+ end
12
+
13
+ def exists?
14
+ log("exists?")
15
+ !!stat
16
+ rescue SystemCallError => e
17
+ return false if e.errno == Errno::ENOENT::Errno
18
+ raise e
19
+ end
20
+
21
+ def write(offset, data)
22
+ size = data.bytesize
23
+ log("write offset #{offset}, size #{size}")
24
+ ret = Lib::Rados.rados_write(pool.handle, name, data, size, offset)
25
+ raise SystemCallError.new("write of #{size} bytes to '#{name}' at #{offset} failed", -ret) if ret < 0
26
+ raise Errno::EIO.new("wrote only #{ret} of #{size} bytes to '#{name}' at #{offset}") if ret < size
27
+ end
28
+
29
+ def read(offset, size)
30
+ log("read offset #{offset}, size #{size}")
31
+ data_p = FFI::MemoryPointer.new(:char, size)
32
+ ret = Lib::Rados.rados_read(pool.handle, name, data_p, size, offset)
33
+ raise SystemCallError.new("read of #{size} bytes from '#{name}' at #{offset} failed", -ret) if ret < 0
34
+ data_p.get_bytes(0, ret)
35
+ end
36
+
37
+ def destroy
38
+ log("destroy")
39
+ ret = Lib::Rados.rados_remove(pool.handle, name)
40
+ raise SystemCallError.new("destroy of '#{name}' failed", -ret) if ret < 0
41
+ end
42
+
43
+ def resize(size)
44
+ log("resize size #{size}")
45
+ ret = Lib::Rados.rados_trunc(pool.handle, name, size)
46
+ raise SystemCallError.new("resize of '#{name}' to #{size} failed", -ret) if ret < 0
47
+ end
48
+
49
+ def stat
50
+ log("stat")
51
+ size_p = FFI::MemoryPointer.new(:uint64)
52
+ mtime_p = FFI::MemoryPointer.new(:uint64)
53
+ ret = Lib::Rados.rados_stat(pool.handle, name, size_p, mtime_p)
54
+ raise SystemCallError.new("stat of '#{name}' failed", -ret) if ret < 0
55
+ {
56
+ :size => size_p.get_uint64(0),
57
+ :mtime => Time.at(mtime_p.get_uint64(0)),
58
+ }
59
+ end
60
+
61
+ def size
62
+ stat[:size]
63
+ end
64
+
65
+ # helper methods below
66
+
67
+ def log(message)
68
+ CephRuby.log("rados object #{pool.name}/#{name} #{message}")
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,3 @@
1
+ module CephRuby
2
+ VERSION = "1.2"
3
+ end
data/lib/ceph-ruby.rb ADDED
@@ -0,0 +1,22 @@
1
+ require "active_support/core_ext/module/delegation"
2
+ require "active_support/core_ext/module/attribute_accessors"
3
+
4
+ require "ffi"
5
+
6
+ require "ceph-ruby/lib/rados"
7
+ require "ceph-ruby/lib/rbd"
8
+
9
+ require "ceph-ruby/version"
10
+ require "ceph-ruby/cluster"
11
+ require "ceph-ruby/pool"
12
+ require "ceph-ruby/rados_block_device"
13
+ require "ceph-ruby/rados_object"
14
+
15
+ module CephRuby
16
+ mattr_accessor :logger
17
+
18
+ def self.log(message)
19
+ return unless logger
20
+ logger.info("CephRuby: #{message}")
21
+ end
22
+ end
metadata ADDED
@@ -0,0 +1,88 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ceph-ruby-ffi19
3
+ version: !ruby/object:Gem::Version
4
+ version: '1.2'
5
+ platform: ruby
6
+ authors:
7
+ - Netskin GmbH
8
+ - Corin Langosch
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2016-01-29 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: 1.9.10
20
+ name: ffi
21
+ prerelease: false
22
+ type: :runtime
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ~>
26
+ - !ruby/object:Gem::Version
27
+ version: 1.9.10
28
+ - !ruby/object:Gem::Dependency
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: 3.0.0
34
+ name: activesupport
35
+ prerelease: false
36
+ type: :runtime
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - '>='
40
+ - !ruby/object:Gem::Version
41
+ version: 3.0.0
42
+ description: Easy management of Ceph
43
+ email:
44
+ - info@netskin.com
45
+ - info@corinlangosch.com
46
+ executables: []
47
+ extensions: []
48
+ extra_rdoc_files: []
49
+ files:
50
+ - .gitignore
51
+ - Gemfile
52
+ - LICENSE.txt
53
+ - README.md
54
+ - Rakefile
55
+ - ceph-ruby.gemspec
56
+ - lib/ceph-ruby.rb
57
+ - lib/ceph-ruby/cluster.rb
58
+ - lib/ceph-ruby/lib/rados.rb
59
+ - lib/ceph-ruby/lib/rbd.rb
60
+ - lib/ceph-ruby/pool.rb
61
+ - lib/ceph-ruby/rados_block_device.rb
62
+ - lib/ceph-ruby/rados_object.rb
63
+ - lib/ceph-ruby/version.rb
64
+ homepage: https://github.com/ceph/ceph-ruby
65
+ licenses:
66
+ - MIT
67
+ metadata: {}
68
+ post_install_message:
69
+ rdoc_options: []
70
+ require_paths:
71
+ - lib
72
+ required_ruby_version: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ required_rubygems_version: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - '>='
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ requirements: []
83
+ rubyforge_project:
84
+ rubygems_version: 2.4.5
85
+ signing_key:
86
+ specification_version: 4
87
+ summary: Easy management of Ceph Distributed Storage System using ruby
88
+ test_files: []