~ubuntu-branches/ubuntu/quantal/ceph/quantal

« back to all changes in this revision

Viewing changes to src/test/pybind/test_rbd.py

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2012-07-16 09:56:24 UTC
  • mfrom: (0.3.11)
  • mto: This revision was merged to the branch mainline in revision 17.
  • Revision ID: package-import@ubuntu.com-20120716095624-azr2w4hbhei1rxmx
Tags: upstream-0.48
ImportĀ upstreamĀ versionĀ 0.48

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
import random
 
2
import struct
 
3
import os
 
4
 
 
5
from nose import with_setup
 
6
from nose.tools import eq_ as eq, assert_raises
 
7
from rados import Rados
 
8
from rbd import (RBD, Image, ImageNotFound, InvalidArgument, ImageExists,
 
9
                 ImageBusy, ImageHasSnapshots)
 
10
 
 
11
 
 
12
rados = None
 
13
ioctx = None
 
14
IMG_NAME = 'foo'
 
15
IMG_SIZE = 8 << 20 # 8 MiB
 
16
IMG_ORDER = 22 # 4 MiB objects
 
17
 
 
18
def setUp():
 
19
    global rados
 
20
    rados = Rados(conffile='')
 
21
    rados.connect()
 
22
    assert rados.pool_exists('rbd')
 
23
    global ioctx
 
24
    ioctx = rados.open_ioctx('rbd')
 
25
 
 
26
def tearDown():
 
27
    global ioctx
 
28
    ioctx.__del__()
 
29
    global rados
 
30
    rados.shutdown()
 
31
 
 
32
def create_image():
 
33
    features = os.getenv("RBD_FEATURES")
 
34
    if features is not None:
 
35
        RBD().create(ioctx, IMG_NAME, IMG_SIZE, IMG_ORDER, old_format=False,
 
36
                     features=int(features))
 
37
    else:
 
38
        RBD().create(ioctx, IMG_NAME, IMG_SIZE, IMG_ORDER, old_format=True)
 
39
 
 
40
def remove_image():
 
41
    RBD().remove(ioctx, IMG_NAME)
 
42
    
 
43
def test_version():
 
44
    RBD().version()
 
45
 
 
46
def test_create():
 
47
    create_image()
 
48
    remove_image()
 
49
 
 
50
def test_context_manager():
 
51
    with Rados(conffile='') as cluster:
 
52
        with cluster.open_ioctx('rbd') as ioctx:
 
53
            RBD().create(ioctx, IMG_NAME, IMG_SIZE)
 
54
            with Image(ioctx, IMG_NAME) as image:
 
55
                data = rand_data(256)
 
56
                image.write(data, 0)
 
57
                read = image.read(0, 256)
 
58
            RBD().remove(ioctx, IMG_NAME)
 
59
            eq(data, read)
 
60
 
 
61
def test_remove_dne():
 
62
    assert_raises(ImageNotFound, remove_image)
 
63
 
 
64
def test_list_empty():
 
65
    eq([], RBD().list(ioctx))
 
66
 
 
67
@with_setup(create_image, remove_image)
 
68
def test_list():
 
69
    eq([IMG_NAME], RBD().list(ioctx))
 
70
 
 
71
@with_setup(create_image, remove_image)
 
72
def test_rename():
 
73
    rbd = RBD()
 
74
    rbd.rename(ioctx, IMG_NAME, IMG_NAME + '2')
 
75
    eq([IMG_NAME + '2'], rbd.list(ioctx))
 
76
    rbd.rename(ioctx, IMG_NAME + '2', IMG_NAME)
 
77
    eq([IMG_NAME], rbd.list(ioctx))
 
78
 
 
79
def rand_data(size):
 
80
    l = [random.Random().getrandbits(64) for _ in xrange(size/8)]
 
81
    return struct.pack((size/8)*'Q', *l)
 
82
 
 
83
def check_stat(info, size, order):
 
84
    assert 'block_name_prefix' in info
 
85
    eq(info['size'], size)
 
86
    eq(info['order'], order)
 
87
    eq(info['num_objs'], size / (1 << order))
 
88
    eq(info['obj_size'], 1 << order)
 
89
    eq(info['parent_pool'], -1)
 
90
    eq(info['parent_name'], '')
 
91
 
 
92
class TestImage(object):
 
93
 
 
94
    def setUp(self):
 
95
        self.rbd = RBD()
 
96
        create_image()
 
97
        self.image = Image(ioctx, IMG_NAME)
 
98
 
 
99
    def tearDown(self):
 
100
        self.image.close()
 
101
        remove_image()
 
102
 
 
103
    def test_stat(self):
 
104
        info = self.image.stat()
 
105
        check_stat(info, IMG_SIZE, IMG_ORDER)
 
106
 
 
107
    def test_write(self):
 
108
        data = rand_data(256)
 
109
        self.image.write(data, 0)
 
110
 
 
111
    def test_read(self):
 
112
        data = self.image.read(0, 20)
 
113
        eq(data, '\0' * 20)
 
114
 
 
115
    def test_large_write(self):
 
116
        data = rand_data(IMG_SIZE)
 
117
        self.image.write(data, 0)
 
118
 
 
119
    def test_large_read(self):
 
120
        data = self.image.read(0, IMG_SIZE)
 
121
        eq(data, '\0' * IMG_SIZE)
 
122
 
 
123
    def test_write_read(self):
 
124
        data = rand_data(256)
 
125
        offset = 50
 
126
        self.image.write(data, offset)
 
127
        read = self.image.read(offset, 256)
 
128
        eq(data, read)
 
129
 
 
130
    def test_read_bad_offset(self):
 
131
        assert_raises(InvalidArgument, self.image.read, IMG_SIZE + 1, IMG_SIZE)
 
132
 
 
133
    def test_resize(self):
 
134
        new_size = IMG_SIZE * 2
 
135
        self.image.resize(new_size)
 
136
        info = self.image.stat()
 
137
        check_stat(info, new_size, IMG_ORDER)
 
138
 
 
139
    def test_resize_down(self):
 
140
        new_size = IMG_SIZE / 2
 
141
        data = rand_data(256)
 
142
        self.image.write(data, IMG_SIZE / 2);
 
143
        self.image.resize(new_size)
 
144
        self.image.resize(IMG_SIZE)
 
145
        read = self.image.read(IMG_SIZE / 2, 256)
 
146
        eq('\0' * 256, read)
 
147
 
 
148
    def test_resize_bytes(self):
 
149
        new_size = IMG_SIZE / 2 - 5
 
150
        data = rand_data(256)
 
151
        self.image.write(data, IMG_SIZE / 2 - 10);
 
152
        self.image.resize(new_size)
 
153
        self.image.resize(IMG_SIZE)
 
154
        read = self.image.read(IMG_SIZE / 2 - 10, 5)
 
155
        eq(data[:5], read)
 
156
        read = self.image.read(IMG_SIZE / 2 - 5, 251)
 
157
        eq('\0' * 251, read)
 
158
 
 
159
    def test_copy(self):
 
160
        global ioctx
 
161
        data = rand_data(256)
 
162
        self.image.write(data, 256)
 
163
        self.image.copy(ioctx, IMG_NAME + '2')
 
164
        assert_raises(ImageExists, self.image.copy, ioctx, IMG_NAME + '2')
 
165
        copy = Image(ioctx, IMG_NAME + '2')
 
166
        copy_data = copy.read(256, 256)
 
167
        copy.close()
 
168
        self.rbd.remove(ioctx, IMG_NAME + '2')
 
169
        eq(data, copy_data)
 
170
 
 
171
    def test_create_snap(self):
 
172
        global ioctx
 
173
        self.image.create_snap('snap1')
 
174
        read = self.image.read(0, 256)
 
175
        eq(read, '\0' * 256)
 
176
        data = rand_data(256)
 
177
        self.image.write(data, 0)
 
178
        read = self.image.read(0, 256)
 
179
        eq(read, data)
 
180
        at_snapshot = Image(ioctx, IMG_NAME, 'snap1')
 
181
        snap_data = at_snapshot.read(0, 256)
 
182
        at_snapshot.close()
 
183
        eq(snap_data, '\0' * 256)
 
184
        self.image.remove_snap('snap1')
 
185
 
 
186
    def test_list_snaps(self):
 
187
        eq([], list(self.image.list_snaps()))
 
188
        self.image.create_snap('snap1')
 
189
        eq(['snap1'], map(lambda snap: snap['name'], self.image.list_snaps()))
 
190
        self.image.create_snap('snap2')
 
191
        eq(['snap1', 'snap2'], map(lambda snap: snap['name'], self.image.list_snaps()))
 
192
        self.image.remove_snap('snap1')
 
193
        self.image.remove_snap('snap2')
 
194
 
 
195
    def test_remove_snap(self):
 
196
        eq([], list(self.image.list_snaps()))
 
197
        self.image.create_snap('snap1')
 
198
        eq(['snap1'], map(lambda snap: snap['name'], self.image.list_snaps()))
 
199
        self.image.remove_snap('snap1')
 
200
        eq([], list(self.image.list_snaps()))
 
201
 
 
202
    def test_remove_with_snap(self):
 
203
        self.image.create_snap('snap1')
 
204
        assert_raises(ImageHasSnapshots, remove_image)
 
205
        self.image.remove_snap('snap1')
 
206
 
 
207
    def test_remove_with_watcher(self):
 
208
        assert_raises(ImageBusy, remove_image)
 
209
 
 
210
    def test_rollback_to_snap(self):
 
211
        self.image.write('\0' * 256, 0)
 
212
        self.image.create_snap('snap1')
 
213
        read = self.image.read(0, 256)
 
214
        eq(read, '\0' * 256)
 
215
        data = rand_data(256)
 
216
        self.image.write(data, 0)
 
217
        read = self.image.read(0, 256)
 
218
        eq(read, data)
 
219
        self.image.rollback_to_snap('snap1')
 
220
        read = self.image.read(0, 256)
 
221
        eq(read, '\0' * 256)
 
222
        self.image.remove_snap('snap1')
 
223
 
 
224
    def test_rollback_to_snap_sparse(self):
 
225
        self.image.create_snap('snap1')
 
226
        read = self.image.read(0, 256)
 
227
        eq(read, '\0' * 256)
 
228
        data = rand_data(256)
 
229
        self.image.write(data, 0)
 
230
        read = self.image.read(0, 256)
 
231
        eq(read, data)
 
232
        self.image.rollback_to_snap('snap1')
 
233
        read = self.image.read(0, 256)
 
234
        eq(read, '\0' * 256)
 
235
        self.image.remove_snap('snap1')
 
236
 
 
237
    def test_rollback_with_resize(self):
 
238
        read = self.image.read(0, 256)
 
239
        eq(read, '\0' * 256)
 
240
        data = rand_data(256)
 
241
        self.image.write(data, 0)
 
242
        self.image.create_snap('snap1')
 
243
        read = self.image.read(0, 256)
 
244
        eq(read, data)
 
245
        new_size = IMG_SIZE * 2
 
246
        self.image.resize(new_size)
 
247
        check_stat(self.image.stat(), new_size, IMG_ORDER)
 
248
        self.image.write(data, new_size - 256)
 
249
        self.image.create_snap('snap2')
 
250
        read = self.image.read(new_size - 256, 256)
 
251
        eq(read, data)
 
252
        self.image.rollback_to_snap('snap1')
 
253
        check_stat(self.image.stat(), IMG_SIZE, IMG_ORDER)
 
254
        assert_raises(InvalidArgument, self.image.read, new_size - 256, 256)
 
255
        self.image.rollback_to_snap('snap2')
 
256
        check_stat(self.image.stat(), new_size, IMG_ORDER)
 
257
        read = self.image.read(new_size - 256, 256)
 
258
        eq(read, data)
 
259
        self.image.remove_snap('snap1')
 
260
        self.image.remove_snap('snap2')
 
261
 
 
262
    def test_set_snap(self):
 
263
        self.image.write('\0' * 256, 0)
 
264
        self.image.create_snap('snap1')
 
265
        read = self.image.read(0, 256)
 
266
        eq(read, '\0' * 256)
 
267
        data = rand_data(256)
 
268
        self.image.write(data, 0)
 
269
        read = self.image.read(0, 256)
 
270
        eq(read, data)
 
271
        self.image.set_snap('snap1')
 
272
        read = self.image.read(0, 256)
 
273
        eq(read, '\0' * 256)
 
274
        self.image.remove_snap('snap1')
 
275
 
 
276
    def test_set_no_snap(self):
 
277
        self.image.write('\0' * 256, 0)
 
278
        self.image.create_snap('snap1')
 
279
        read = self.image.read(0, 256)
 
280
        eq(read, '\0' * 256)
 
281
        data = rand_data(256)
 
282
        self.image.write(data, 0)
 
283
        read = self.image.read(0, 256)
 
284
        eq(read, data)
 
285
        self.image.set_snap('snap1')
 
286
        read = self.image.read(0, 256)
 
287
        eq(read, '\0' * 256)
 
288
        self.image.set_snap(None)
 
289
        read = self.image.read(0, 256)
 
290
        eq(read, data)
 
291
        self.image.remove_snap('snap1')
 
292
 
 
293
    def test_set_snap_sparse(self):
 
294
        self.image.create_snap('snap1')
 
295
        read = self.image.read(0, 256)
 
296
        eq(read, '\0' * 256)
 
297
        data = rand_data(256)
 
298
        self.image.write(data, 0)
 
299
        read = self.image.read(0, 256)
 
300
        eq(read, data)
 
301
        self.image.set_snap('snap1')
 
302
        read = self.image.read(0, 256)
 
303
        eq(read, '\0' * 256)
 
304
        self.image.remove_snap('snap1')
 
305
 
 
306
    def test_many_snaps(self):
 
307
        num_snaps = 200
 
308
        for i in xrange(num_snaps):
 
309
            self.image.create_snap(str(i))
 
310
        snaps = sorted(self.image.list_snaps(),
 
311
                       key=lambda snap: int(snap['name']))
 
312
        eq(len(snaps), num_snaps)
 
313
        for i, snap in enumerate(snaps):
 
314
            eq(snap['size'], IMG_SIZE)
 
315
            eq(snap['name'], str(i))
 
316
        for i in xrange(num_snaps):
 
317
            self.image.remove_snap(str(i))
 
318
 
 
319
    def test_set_snap_deleted(self):
 
320
        self.image.write('\0' * 256, 0)
 
321
        self.image.create_snap('snap1')
 
322
        read = self.image.read(0, 256)
 
323
        eq(read, '\0' * 256)
 
324
        data = rand_data(256)
 
325
        self.image.write(data, 0)
 
326
        read = self.image.read(0, 256)
 
327
        eq(read, data)
 
328
        self.image.set_snap('snap1')
 
329
        self.image.remove_snap('snap1')
 
330
        assert_raises(ImageNotFound, self.image.read, 0, 256)
 
331
        self.image.set_snap(None)
 
332
        read = self.image.read(0, 256)
 
333
        eq(read, data)
 
334
 
 
335
    def test_set_snap_recreated(self):
 
336
        self.image.write('\0' * 256, 0)
 
337
        self.image.create_snap('snap1')
 
338
        read = self.image.read(0, 256)
 
339
        eq(read, '\0' * 256)
 
340
        data = rand_data(256)
 
341
        self.image.write(data, 0)
 
342
        read = self.image.read(0, 256)
 
343
        eq(read, data)
 
344
        self.image.set_snap('snap1')
 
345
        self.image.remove_snap('snap1')
 
346
        self.image.create_snap('snap1')
 
347
        assert_raises(ImageNotFound, self.image.read, 0, 256)
 
348
        self.image.set_snap(None)
 
349
        read = self.image.read(0, 256)
 
350
        eq(read, data)
 
351
        self.image.remove_snap('snap1')