ceph-ruby-livelink 1.5.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,65 @@
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
+ # Ruby librbd bindings
8
+ module Rbd
9
+ extend FFI::Library
10
+
11
+ ffi_lib ['rbd', 'librbd.so.1']
12
+
13
+ attach_function 'rbd_version', [:pointer, :pointer, :pointer], :void
14
+
15
+ attach_function 'rbd_create2', [:pointer, :string, :size_t, :uint64,
16
+ :pointer], :int
17
+
18
+ attach_function 'rbd_remove', [:pointer, :string], :int
19
+
20
+ attach_function 'rbd_open', [:pointer, :string, :pointer, :string], :int
21
+
22
+ attach_function 'rbd_close', [:pointer], :void
23
+
24
+ attach_function 'rbd_write', [:pointer, :off_t, :size_t, :buffer_in], :int
25
+
26
+ attach_function 'rbd_read', [:pointer, :off_t, :size_t, :buffer_out], :int
27
+
28
+ attach_function 'rbd_stat', [:pointer, :pointer, :size_t], :int
29
+
30
+ attach_function 'rbd_resize', [:pointer, :size_t], :int
31
+
32
+ attach_function 'rbd_copy', [:pointer, :pointer, :string], :int
33
+
34
+ attach_function 'rbd_copy_with_progress', [:pointer, :pointer, :string,
35
+ :pointer, :pointer], :int
36
+
37
+ # Datatype to store rbd status information
38
+ class StatStruct < FFI::Struct #:nodoc:
39
+ layout :size, :uint64,
40
+ :obj_size, :uint64,
41
+ :num_objs, :uint64,
42
+ :order, :int,
43
+ :block_name_prefix, [:char, 24],
44
+ :parent_pool, :int, # deprecated
45
+ :parent_name, [:char, 96] # deprecated
46
+ end
47
+
48
+ def self.version
49
+ major = FFI::MemoryPointer.new(:int)
50
+ minor = FFI::MemoryPointer.new(:int)
51
+ extra = FFI::MemoryPointer.new(:int)
52
+ rbd_version(major, minor, extra)
53
+ {
54
+ major: major.get_int(0),
55
+ minor: minor.get_int(0),
56
+ extra: extra.get_int(0)
57
+ }
58
+ end
59
+
60
+ def self.version_string
61
+ "#{version[:major]}.#{version[:minor]}.#{version[:extra]}"
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,117 @@
1
+ module CephRuby
2
+ # Represents a Ceph pool
3
+ # = usage
4
+ # pool = cluster.pool('name')
5
+ class Pool
6
+ extend CephRuby::PoolHelper
7
+ include CephRuby::PoolHelper
8
+ include ::Comparable
9
+ attr_accessor :cluster, :name, :handle
10
+
11
+ def initialize(cluster, name)
12
+ self.cluster = cluster
13
+ self.name = name
14
+ begin
15
+ yield(self)
16
+ ensure
17
+ close
18
+ end if block_given?
19
+ end
20
+
21
+ def exists?
22
+ log('exists?')
23
+ ret = Lib::Rados.rados_pool_lookup(cluster.handle, name)
24
+ return true if ret >= 0
25
+ return false if ret == -Errno::ENOENT::Errno
26
+ raise SystemCallError.new("lookup of '#{name}' failed", -ret) if ret < 0
27
+ end
28
+
29
+ alias exist? exists?
30
+
31
+ def id
32
+ ensure_open
33
+ Lib::Rados.rados_ioctx_get_id(handle)
34
+ end
35
+
36
+ def auid=(dst_auid)
37
+ log("auid=#{dst_auid}")
38
+ ensure_open
39
+ ret = Lib::Rados.rados_ioctx_pool_set_auid(handle, dst_auid)
40
+ raise SystemCallError.new('set of auid for'\
41
+ " '#{name}' failed", -ret) if ret < 0
42
+ end
43
+
44
+ def auid
45
+ log('auid')
46
+ ensure_open
47
+ auid_p = FFI::MemoryPointer.new(:uint64)
48
+ ret = Lib::Rados.rados_ioctx_pool_get_auid(handle, auid_p)
49
+ raise SystemCallError.new('get of auid for'\
50
+ " '#{name}' failed", -ret) if ret < 0
51
+ auid_p.get_uint64(0)
52
+ end
53
+
54
+ def open
55
+ return if open?
56
+ log('open')
57
+ handle_p = FFI::MemoryPointer.new(:pointer)
58
+ ret = Lib::Rados.rados_ioctx_create(cluster.handle, name, handle_p)
59
+ raise SystemCallError.new('creation of io context for'\
60
+ " '#{name}' failed", -ret) if ret < 0
61
+ self.handle = handle_p.get_pointer(0)
62
+ end
63
+
64
+ def close
65
+ return unless open?
66
+ log('close')
67
+ Lib::Rados.rados_ioctx_destroy(handle)
68
+ self.handle = nil
69
+ end
70
+
71
+ def rados_object(name, &block)
72
+ ensure_open
73
+ RadosObject.new(self, name, &block)
74
+ end
75
+
76
+ def rados_object_enumerator(&block)
77
+ ensure_open
78
+ RadosObjectEnumerator.new(self, &block)
79
+ end
80
+
81
+ def rados_block_device(name, &block)
82
+ ensure_open
83
+ RadosBlockDevice.new(self, name, &block)
84
+ end
85
+
86
+ def create(auid: nil, rule_id: nil)
87
+ log("create auid: #{auid}, rule: #{rule_id}")
88
+ rule_id ||= 0
89
+ return create_with_all(auid, rule_id) if auid
90
+ create_with_rule(rule_id)
91
+ close
92
+ end
93
+
94
+ def destroy
95
+ ret = Lib::Rados.rados_pool_delete(cluster.handle, name)
96
+ raise SystemCallError.new('delete pool failed',
97
+ -ret) if ret < 0
98
+ end
99
+
100
+ def stat
101
+ log('stat')
102
+ stat_s = Lib::Rados::PoolStatStruct.new
103
+ ensure_open
104
+ ret = Lib::Rados.rados_ioctx_pool_stat(handle, stat_s)
105
+ raise SystemCallError.new('stat failed',
106
+ -ret) if ret < 0
107
+ stat_s.to_hash
108
+ end
109
+
110
+ def flush_aio
111
+ ensure_open
112
+ ret = Lib::Rados.rados_aio_flush(handle)
113
+ raise SystemCallError.new('aio flush faield',
114
+ -ret) if ret < 0
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,32 @@
1
+ module CephRuby
2
+ # Enumerator of Ceph pools
3
+ class PoolEnumerator
4
+ include Enumerable
5
+ attr_accessor :cluster, :members
6
+ def initialize(cluster)
7
+ self.cluster = cluster
8
+ yield self if block_given?
9
+ end
10
+
11
+ def each
12
+ return enum_for(:each) unless block_given?
13
+
14
+ pools.each do |pool|
15
+ yield Pool.new(cluster, pool)
16
+ end
17
+ end
18
+
19
+ def size
20
+ pools.size
21
+ end
22
+
23
+ private
24
+
25
+ def pools(size = 512)
26
+ data_p = FFI::MemoryPointer.new(:char, size)
27
+ ret = Lib::Rados.rados_pool_list(cluster.handle, data_p, size)
28
+ return pools(ret) if ret > size
29
+ data_p.get_bytes(0, ret).split("\0")
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,46 @@
1
+ module CephRuby
2
+ # Pool Helper MEthods
3
+ module PoolHelper
4
+ def by_id(cluster, id, &block)
5
+ Pool.new(cluster, cluster.pool_name_by_id(id), &block)
6
+ end
7
+
8
+ def create_with_all(auid, rule_id)
9
+ ret = Lib::Rados.rados_pool_create_with_all(cluster.handle, name,
10
+ auid, rule_id)
11
+ raise SystemCallError.new("create pool with auid: #{auid}, "\
12
+ "rule_id: #{rule_id} failed", -ret) if ret < 0
13
+ end
14
+
15
+ def create_with_rule(rule_id)
16
+ ret = Lib::Rados.rados_pool_create_with_crush_rule(cluster.handle, name,
17
+ rule_id)
18
+ raise SystemCallError.new("create pool with rule_id: #{rule_id}"\
19
+ ' failed', -ret) if ret < 0
20
+ end
21
+
22
+ def open?
23
+ !handle.nil?
24
+ end
25
+
26
+ def ensure_open
27
+ return if open?
28
+ open
29
+ end
30
+
31
+ def log(message)
32
+ CephRuby.log("pool #{name} #{message}")
33
+ end
34
+
35
+ def <=>(other)
36
+ cluster_check = other.cluster <=> cluster
37
+ return cluster_check unless cluster_check == 0
38
+ other.name <=> name
39
+ end
40
+
41
+ def eql?(other)
42
+ return false unless other.class == self.class
43
+ self == other
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,42 @@
1
+ module CephRuby
2
+ # A Completion for callbacks for asynchronous IO
3
+ class RadosCompletion
4
+ attr_accessor :completion_t
5
+
6
+ def initialize(args: nil, complete_callback: nil, safe_callback: nil)
7
+ self.completion_t = Lib::Rados.rados_completion(args,
8
+ complete_callback,
9
+ safe_callback)
10
+ end
11
+
12
+ def wait_for_complete
13
+ end
14
+
15
+ def wait_for_safe
16
+ end
17
+
18
+ def complete?
19
+ end
20
+
21
+ def safe?
22
+ end
23
+
24
+ def wait_for_complete_and_cb
25
+ end
26
+
27
+ def wait_for_safe_and_cb
28
+ end
29
+
30
+ def complete_and_cb?
31
+ end
32
+
33
+ def safe_and_cb?
34
+ end
35
+
36
+ def return_value
37
+ end
38
+
39
+ def destroy
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,37 @@
1
+ module CephRuby
2
+ # Asynchronous object operations on Rados Object
3
+ class RadosAIOObject < RadosObject
4
+ attr_accessor :completions
5
+
6
+ def initialize(pool, name)
7
+ super(pool, name)
8
+ self.completions = []
9
+ end
10
+
11
+ def read(completion, _offset, _size)
12
+ completions << completion
13
+ end
14
+
15
+ def write(completion, _offset, data)
16
+ completions << completion
17
+ size = data.size
18
+ p size
19
+ end
20
+
21
+ def destroy(completion)
22
+ completions << completion
23
+ end
24
+
25
+ def append(completion, _data)
26
+ completions << completion
27
+ end
28
+
29
+ def stat(completion)
30
+ completions << completion
31
+ end
32
+
33
+ def cancel(completion)
34
+ completions << completion
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,118 @@
1
+ module CephRuby
2
+ # Rados Block Device
3
+ class RadosBlockDevice
4
+ extend CephRuby::RadosBlockDeviceHelper
5
+ attr_accessor :pool, :name, :handle
6
+
7
+ delegate :cluster, to: :pool
8
+
9
+ def initialize(pool, name)
10
+ self.pool = pool
11
+ self.name = name
12
+ if block_given?
13
+ begin
14
+ yield(self)
15
+ ensure
16
+ close
17
+ end
18
+ end
19
+ end
20
+
21
+ def exists?
22
+ log('exists?')
23
+ RadosBlockDevice.close_handle(open_handle)
24
+ rescue SystemCallError => e
25
+ return false if e.errno == -Errno::ENOENT::Errno
26
+ raise
27
+ end
28
+
29
+ def create(size, features = 0, order = 26)
30
+ log("create size #{size}, features #{features}, order #{order}")
31
+ order_p = FFI::MemoryPointer.new(:int)
32
+ order_p.put_int(0, order)
33
+ ret = Lib::Rbd.rbd_create2(pool.handle, name, size, features, order_p)
34
+ raise SystemCallError.new("creation of '#{name}' failed", -ret) if ret < 0
35
+ end
36
+
37
+ def open
38
+ return if open?
39
+ log('open')
40
+ self.handle = open_handle
41
+ end
42
+
43
+ def open_handle
44
+ handle_p = FFI::MemoryPointer.new(:pointer)
45
+ ret = Lib::Rbd.rbd_open(pool.handle, name, handle_p, nil)
46
+ raise SystemCallError.new("open of '#{name}' failed", -ret) if ret < 0
47
+ handle_p.get_pointer(0)
48
+ end
49
+
50
+ def close
51
+ return unless open?
52
+ log('close')
53
+ RadosBlockDevice.close_handle(handle)
54
+ self.handle = nil
55
+ end
56
+
57
+ def destroy
58
+ close if open?
59
+ log('destroy')
60
+ ret = Lib::Rbd.rbd_remove(pool.handle, name)
61
+ raise SystemCallError.new("destroy of '#{name}' failed", -ret) if ret < 0
62
+ end
63
+
64
+ def write(offset, data)
65
+ ensure_open
66
+ size = data.bytesize
67
+ log("write offset #{offset}, size #{size}")
68
+ ret = Lib::Rbd.rbd_write(handle, offset, size, data)
69
+ raise SystemCallError.new("write of #{size} bytes to '#{name}' "\
70
+ "at #{offset} failed", -ret) if ret < 0
71
+ raise Errno::EIO, "wrote only #{ret} of #{size} bytes to "\
72
+ "'#{name}' at #{offset}" if ret < size
73
+ end
74
+
75
+ def read(offset, size)
76
+ ensure_open
77
+ log("read offset #{offset}, size #{size}")
78
+ data_p = FFI::MemoryPointer.new(:char, size)
79
+ ret = Lib::Rbd.rbd_read(handle, offset, size, data_p)
80
+ raise SystemCallError.new("read of #{size} bytes from "\
81
+ "'#{name}' at #{offset} failed",
82
+ -ret) if ret < 0
83
+ data_p.get_bytes(0, ret)
84
+ end
85
+
86
+ def stat
87
+ ensure_open
88
+ log('stat')
89
+ stat = Lib::Rbd::StatStruct.new
90
+ ret = Lib::Rbd.rbd_stat(handle, stat, stat.size)
91
+ raise SystemCallError.new("stat of '#{name}' failed", -ret) if ret < 0
92
+ RadosBlockDevice.parse_stat(stat)
93
+ end
94
+
95
+ def resize(size)
96
+ ensure_open
97
+ log("resize size #{size}")
98
+ ret = Lib::Rbd.rbd_resize(handle, size)
99
+ raise SystemCallError.new("resize of '#{name}' to #{size} failed",
100
+ -ret) if ret < 0
101
+ end
102
+
103
+ def size
104
+ stat[:size]
105
+ end
106
+
107
+ def copy_to(dst_name, dst_pool = nil)
108
+ ensure_open
109
+ dst_pool = parse_dst(dst, pool)
110
+ dst_pool_name = dst_pool.name
111
+ log("copy_to #{dst_pool_name}/#{dst_name}")
112
+ ret = Lib::Rbd.rbd_copy(handle, dst_pool.handle, dst_name)
113
+ raise SystemCallError.new("copy of '#{name}' to "\
114
+ "'#{dst_pool_name}/#{dst_name}' failed",
115
+ -ret) if ret < 0
116
+ end
117
+ end
118
+ end