1 # Copyright 2013 GRNET S.A. All rights reserved.
3 # Redistribution and use in source and binary forms, with or
4 # without modification, are permitted provided that the following
7 # 1. Redistributions of source code must retain the above
8 # copyright notice, this list of conditions and the following
11 # 2. Redistributions in binary form must reproduce the above
12 # copyright notice, this list of conditions and the following
13 # disclaimer in the documentation and/or other materials
14 # provided with the distribution.
16 # THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20 # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 # USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 # POSSIBILITY OF SUCH DAMAGE.
29 # The views and conclusions contained in the software and
30 # documentation are those of the authors and should not be
31 # interpreted as representing official policies, either expressed
32 # or implied, of GRNET S.A.
34 from archipelago.common import loadrc, DEVICE_PREFIX, Error, construct_peers
35 import archipelago.vlmc as vlmc
36 import archipelago.archipelago as archipelago
40 from subprocess import check_call
42 def gettempname(prefix='myvolume-'):
43 t = tempfile.mktemp(prefix=prefix)
44 return os.path.basename(t)
46 def getrandomdata(size):
47 return os.urandom(size)
49 def getrandomfile(size):
50 randomfile = gettempname(prefix='random-')
51 randomdata = getrandomdata(size)
52 return (randomfile, randomdata)
54 def is_mounted(device):
55 lines = open("/proc/mounts").read().split("\n")
56 mounts = [l.split(" ")[0] for l in lines]
62 def mount(device, directory):
63 cmd = ['mount', device, directory]
65 check_call(cmd, shell=False)
67 raise Error("Cannot mount %s to %s" % (device, directory))
70 if not is_mounted(device):
72 cmd = ['umount', device]
74 check_call(cmd, shell=False)
76 raise Error("Cannot umount %s" % device)
79 def test_create(volume, volumesize=None, snap=None, cont_addr=False):
80 vlmc.create(name=volume, size=volumesize, snap=snap, cont_addr=cont_addr)
81 #should we catch Error here and do a vlmc.remove(name=volume)
82 # d_id = vlmc.map_volume(name=volume)
83 # device = DEVICE_PREFIX + str(d_id)
84 # vlmc.unmap_volume(name=device)
87 def write(volume, volumesize):
88 d_id=vlmc.map_volume(name=volume)
89 device = DEVICE_PREFIX + str(d_id)
91 fd = os.open(device, os.O_WRONLY)
92 os.lseek(fd, (volumesize*1024*1024)+1, os.SEEK_SET)
93 os.write(fd, "This should not succeed")
95 except OSError, (err, reason):
96 if err != errno.EINVAL:
97 raise Error("Cannot write to device %s : %s" % (device,reason))
101 vlmc.unmap_volume(name=device)
104 def mkfs_and_mount(volume, mountdir):
105 d_id=vlmc.map_volume(name=volume)
106 device = DEVICE_PREFIX + str(d_id)
108 cmd = ['mkfs.ext3', device]
109 check_call(cmd, shell=False)
111 mount(device, mountdir)
114 vlmc.unmap_volume(name=device)
117 def write_data(volume, mountdir, randomfiles):
118 d_id=vlmc.map_volume(name=volume)
119 device = DEVICE_PREFIX + str(d_id)
121 mount(device, mountdir)
122 for rf in randomfiles:
123 print "writing " + rf[0]
124 f = open(os.path.join(mountdir, rf[0]), 'w')
129 vlmc.unmap_volume(name=device)
131 def read_data(volume, mountdir, randomfiles):
132 d_id=vlmc.map_volume(name=volume)
133 device = DEVICE_PREFIX + str(d_id)
135 mount(device, mountdir)
136 for rf in randomfiles:
137 print "reading " + rf[0]
138 f = open(os.path.join(mountdir, rf[0]), 'r')
142 raise Error("Data mismatch %s" % rf[0])
145 vlmc.unmap_volume(name=device)
147 def snapshot(volume):
148 vlmc.snapshot(name=volume)
150 if __name__ == '__main__':
152 peers = construct_peers()
153 tmpvolume=gettempname()
154 mntdir = '/mnt/mountpoint'
155 RANDOMSIZE=20*1024*1024
157 test_create(tmpvolume, volumesize=10240)
159 write(tmpvolume, 10240)
160 mkfs_and_mount(tmpvolume, mntdir)
162 rf = [getrandomfile(RANDOMSIZE)]
163 write_data(tmpvolume, mntdir, rf)
164 archipelago.restart(user=True)
165 read_data(tmpvolume, mntdir, rf)
168 snapname=gettempname(prefix="snapshot")
169 print "Snapshot ", tmpvolume, "to", snapname
170 snap = vlmc.snapshot(name=tmpvolume, snap_name=snapname)
171 clonedvolume=gettempname()
172 print "Cloning ", snapname, "to", clonedvolume
173 test_create(clonedvolume, snap=snapname)
174 except Exception as e:
176 vlmc.remove(name=tmpvolume)
179 #create clone volume from snapshot
181 rf1 = [getrandomfile(RANDOMSIZE)]
182 #write new data to old volume
183 write_data(tmpvolume, mntdir, rf1)
184 #read new data from old volume
185 read_data(tmpvolume, mntdir, rf1)
186 #read old data from new volume
187 read_data(clonedvolume, mntdir, rf)
189 rf2 = [getrandomfile(RANDOMSIZE)]
190 #write new data2 to snapshot
191 write_data(clonedvolume, mntdir, rf2)
192 #read new data2 from clonedvolume
193 read_data(clonedvolume, mntdir, rf2)
194 #read new data from old volume
195 read_data(tmpvolume, mntdir, rf1)
196 except Exception as e:
199 vlmc.remove(name=tmpvolume)
200 vlmc.remove(name=clonedvolume)