summaryrefslogtreecommitdiffstats
path: root/tests/functional/dht/test_custom_xattr_healing_for_dir.py
blob: d5bca0fb322400699708330dfdaf88ccd668be86 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
#  Copyright (C) 2020 Red Hat, Inc. <http://www.redhat.com>
#
#  This program is free software; you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation; either version 2 of the License, or
#  any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License along
#  with this program; if not, write to the Free Software Foundation, Inc.,
#  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

# pylint: disable=protected-access
# pylint: disable=too-many-statements

from time import sleep
from glusto.core import Glusto as g
from glustolibs.gluster.exceptions import ExecutionError
from glustolibs.gluster.gluster_base_class import GlusterBaseClass, runs_on
from glustolibs.gluster.glusterfile import (get_fattr, set_fattr,
                                            delete_fattr)
from glustolibs.gluster.glusterdir import mkdir
from glustolibs.gluster.volume_libs import get_subvols
from glustolibs.gluster.dht_test_utils import (find_hashed_subvol,
                                               find_new_hashed)
from glustolibs.gluster.brick_libs import (get_online_bricks_list,
                                           bring_bricks_offline)
from glustolibs.gluster.volume_ops import volume_start


@runs_on([['distributed', 'distributed-dispersed',
           'distributed-arbiter', 'distribited-replicated'],
          ['glusterfs']])
class TestCustomXattrHealingForDir(GlusterBaseClass):
    def setUp(self):

        # Calling GlusterBaseClass setUp
        self.get_super_method(self, 'setUp')()

        # Setup Volume and Mount Volume
        ret = self.setup_volume_and_mount_volume([self.mounts[0]])
        if not ret:
            raise ExecutionError("Failed to Setup_Volume and Mount_Volume")
        g.log.info("Successful in Setup Volume and Mount Volume")

        self.client, self.m_point = (self.mounts[0].client_system,
                                     self.mounts[0].mountpoint)

    def tearDown(self):

        # Unmount and cleanup original volume
        ret = self.unmount_volume_and_cleanup_volume(mounts=[self.mounts[0]])
        if not ret:
            raise ExecutionError("Failed to umount the vol & cleanup Volume")
        g.log.info("Successful in umounting the volume and Cleanup")

        # Calling GlusterBaseClass tearDown
        self.get_super_method(self, 'tearDown')()

    def _set_xattr_value(self, fattr_value="bar2"):
        """Set the xattr 'user.foo' as per the value on dir1"""
        # Set the xattr on the dir1
        ret = set_fattr(self.client, '{}/dir1'.format(self.m_point),
                        'user.foo', fattr_value)
        self.assertTrue(ret, "Failed to set the xattr on dir1")
        g.log.info("Successfully set the xattr user.foo with value:"
                   " %s on dir1", fattr_value)

    def _check_xattr_value_on_mnt(self, expected_value=None):
        """Check if the expected value for 'user.foo'
        is present for dir1 on mountpoint"""
        ret = get_fattr(self.client, '{}/dir1'.format(self.m_point),
                        'user.foo', encode="text")
        self.assertEqual(ret, expected_value, "Failed to get the xattr"
                         " on:{}".format(self.client))
        g.log.info(
            "The xattr user.foo for dir1 is displayed on mointpoint"
            " and has value:%s", expected_value)

    def _check_xattr_value_on_bricks(self, online_bricks, expected_value=None):
        """Check if the expected value for 'user.foo'is present
        for dir1 on backend bricks"""
        for brick in online_bricks:
            host, brick_path = brick.split(':')
            ret = get_fattr(host, '{}/dir1'.format(brick_path),
                            'user.foo', encode="text")
            self.assertEqual(ret, expected_value, "Failed to get the xattr"
                                                  " on:{}".format(brick_path))
            g.log.info("The xattr user.foo is displayed for dir1 on "
                       "brick:%s and has value:%s",
                       brick_path, expected_value)

    def _create_dir(self, dir_name=None):
        """Create a directory on the mountpoint"""
        ret = mkdir(self.client, "{}/{}".format(self.m_point, dir_name))
        self.assertTrue(ret, "mkdir of {} failed".format(dir_name))

    def _perform_lookup(self):
        """Perform lookup on mountpoint"""
        cmd = ("ls -lR {}/dir1".format(self.m_point))
        ret, _, _ = g.run(self.client, cmd)
        self.assertEqual(ret, 0, "Failed to lookup")
        g.log.info("Lookup successful")
        sleep(5)

    def _create_xattr_check_self_heal(self):
        """Create custom xattr and check if its healed"""
        # Set the xattr on the dir1
        self._set_xattr_value(fattr_value="bar2")

        # Get online brick list
        online_bricks = get_online_bricks_list(self.mnode, self.volname)
        self.assertIsNotNone(online_bricks, "Failed to get online bricks")

        # Check if the custom xattr is being displayed on the
        # mount-point for dir1
        self._check_xattr_value_on_mnt(expected_value="bar2")

        # Check if the xattr is being displayed on the online-bricks
        # for dir1
        self._check_xattr_value_on_bricks(online_bricks, expected_value="bar2")

        # Modify custom xattr value on dir1
        self._set_xattr_value(fattr_value="ABC")

        # Lookup on moint-point to refresh the value of xattr
        self._perform_lookup()

        # Check if the modified custom xattr is being displayed
        # on the mount-point for dir1
        self._check_xattr_value_on_mnt(expected_value="ABC")

        # Check if the modified custom xattr is being
        # displayed on the bricks for dir1
        self._check_xattr_value_on_bricks(online_bricks, expected_value="ABC")

        # Remove the custom xattr from the mount point for dir1
        ret = delete_fattr(self.client,
                           '{}/dir1'.format(self.m_point), 'user.foo')
        self.assertTrue(ret, "Failed to delete the xattr for "
                             "dir1 on mountpoint")
        g.log.info(
            "Successfully deleted the xattr for dir1 from mountpoint")

        # Lookup on moint-point to refresh the value of xattr
        self._perform_lookup()

        # Check that the custom xattr is not displayed on the
        # for dir1 on mountpoint
        ret = get_fattr(self.client, '{}/dir1'.format(self.m_point),
                        'user.foo', encode="text")
        self.assertEqual(ret, None, "Xattr for dir1 is not removed"
                         " on:{}".format(self.client))
        g.log.info("Success: xattr is removed for dir1 on mointpoint")

        # Check that the custom xattr is not displayed on the
        # for dir1 on the backend bricks
        for brick in online_bricks:
            host, brick_path = brick.split(':')
            ret = get_fattr(host, '{}/dir1'.format(brick_path),
                            'user.foo', encode="text")
            self.assertEqual(ret, None, "Xattr for dir1 is not removed"
                                        " on:{}".format(brick_path))
            g.log.info("Xattr for dir1 is removed from "
                       "brick:%s", brick_path)

        # Check if the trusted.glusterfs.pathinfo is displayed
        # for dir1 on mointpoint
        ret = get_fattr(self.client, '{}/dir1'.format(self.m_point),
                        'trusted.glusterfs.pathinfo')
        self.assertIsNotNone(ret, "Failed to get the xattr"
                             " on:{}".format(self.client))
        g.log.info("The xattr trusted.glusterfs.pathinfo"
                   " is displayed on mointpoint for dir1")

        # Set the xattr on the dir1
        self._set_xattr_value(fattr_value="star1")

        # Bring back the bricks online
        ret, _, _ = volume_start(self.mnode, self.volname, force=True)
        self.assertFalse(ret, 'Failed to start volume %s with "force" option'
                         % self.volname)
        g.log.info('Successfully started volume %s with "force" option',
                   self.volname)

        # Execute lookup on the mointpoint
        self._perform_lookup()

        # Get online brick list
        online_bricks = get_online_bricks_list(self.mnode, self.volname)
        self.assertIsNotNone(online_bricks, "Failed to get online bricks")

        # Check if the custom xattr is being displayed
        # on the mount-point for dir1
        self._check_xattr_value_on_mnt(expected_value="star1")

        # Check if the custom xattr is displayed on all the bricks
        self._check_xattr_value_on_bricks(online_bricks,
                                          expected_value="star1")

    def test_custom_xattr_with_subvol_down_dir_exists(self):
        """
        Description:
        Steps:
        1) Create directories from mount point.
        2) Bring one or more(not all) dht sub-volume(s) down by killing
           processes on that server
        3) Create a custom xattr for dir hashed to down sub-volume and also for
           another dir not hashing to down sub-volumes
           # setfattr -n user.foo -v bar2 <dir>
        4) Verify that custom xattr for directory is displayed on mount point
           and bricks for both directories
           # getfattr -n user.foo <dir>
           # getfattr -n user.foo <brick_path>/<dir>
        5) Modify custom xattr value and verify that custom xattr for directory
           is displayed on mount point and all up bricks
           # setfattr -n user.foo -v ABC <dir>
        6) Verify that custom xattr is not displayed once you remove it on
           mount point and all up bricks
        7) Verify that mount point shows pathinfo xattr for dir hashed to down
           sub-volume and also for dir not hashed to down sub-volumes
           # getfattr -n trusted.glusterfs.pathinfo <dir>
        8) Again create a custom xattr for dir not hashing to down sub-volumes
           # setfattr -n user.foo -v star1 <dir>
        9) Bring up the sub-volumes
        10) Execute lookup on parent directory of both <dir> from mount point
        11) Verify Custom extended attributes for dir1 on all bricks
        """
        # pylint: disable=protected-access
        # Create dir1 on client0
        self._create_dir(dir_name="dir1")

        # Get subvol list
        subvols = (get_subvols(self.mnode, self.volname))['volume_subvols']
        self.assertIsNotNone(subvols, "Failed to get subvols")

        # Finding a dir name such that it hashes to a different subvol
        newhash = find_new_hashed(subvols, "/", "dir1")
        new_name = str(newhash.newname)
        new_subvol_count = newhash.subvol_count

        # Create a dir with the new name
        self._create_dir(dir_name=new_name)

        # Kill the brick/subvol to which the new dir hashes
        ret = bring_bricks_offline(
            self.volname, subvols[new_subvol_count])
        self.assertTrue(ret, ('Error in bringing down subvolume %s',
                              subvols[new_subvol_count]))
        g.log.info('DHT subvol %s is offline', subvols[new_subvol_count])

        # Set the xattr on dir hashing to down subvol
        ret = set_fattr(self.client, '{}/{}'.format(self.m_point, new_name),
                        'user.foo', 'bar2')
        self.assertFalse(ret, "Unexpected: custom xattr set successfully"
                              " for dir hashing to down subvol")
        g.log.info("Expected: Failed to set xattr on dir:%s"
                   " which hashes to down subvol due to error: Transport"
                   " endpoint not connected", new_name)

        # Check if the trusted.glusterfs.pathinfo is displayed
        # for dir hashing to down subvol on mointpoint
        ret = get_fattr(self.client, '{}/{}'.format(
            self.m_point, new_name), 'trusted.glusterfs.pathinfo')
        self.assertIsNotNone(ret, "Failed to get the xattr"
                             " on:{}".format(self.client))
        g.log.info("The xattr trusted.glusterfs.pathinfo"
                   " is displayed on mointpoint for %s", new_name)

        # Set the xattr on dir hashing to down subvol
        ret = set_fattr(self.client, '{}/{}'.format(self.m_point, new_name),
                        'user.foo', 'star1')
        self.assertFalse(ret, "Unexpected: custom xattr set successfully"
                              " for dir hashing to down subvol")
        g.log.info("Expected: Tansport endpoint not connected")

        # Calling the local function
        self._create_xattr_check_self_heal()

    def test_custom_xattr_with_subvol_down_dir_doesnt_exists(self):
        """
        Description:
        Steps:
        1) Bring one or more(not all) dht sub-volume(s) down by killing
           processes on that server
        2) Create a directory from mount point such that it
           hashes to up subvol.
        3) Create a custom xattr for dir
           # setfattr -n user.foo -v bar2 <dir>
        4) Verify that custom xattr for directory is displayed on mount point
           and bricks for directory
           # getfattr -n user.foo <dir>
           # getfattr -n user.foo <brick_path>/<dir>
        5) Modify custom xattr value and verify that custom xattr for directory
           is displayed on mount point and all up bricks
           # setfattr -n user.foo -v ABC <dir>
        6) Verify that custom xattr is not displayed once you remove it on
           mount point and all up bricks
        7) Verify that mount point shows pathinfo xattr for dir
        8) Again create a custom xattr for dir
           # setfattr -n user.foo -v star1 <dir>
        9) Bring up the sub-volumes
        10) Execute lookup on parent directory of both <dir> from mount point
        11) Verify Custom extended attributes for dir1 on all bricks
        """
        # Get subvol list
        subvols = (get_subvols(self.mnode, self.volname))['volume_subvols']
        self.assertIsNotNone(subvols, "Failed to get subvols")

        # Find out the hashed subvol for dir1
        hashed_subvol, subvol_count = find_hashed_subvol(subvols, "/", "dir1")
        self.assertIsNotNone(hashed_subvol, "Could not find srchashed")
        g.log.info("Hashed subvol for dir1 is %s", hashed_subvol._path)

        # Remove the hashed_subvol from subvol list
        subvols.remove(subvols[subvol_count])

        # Bring down a dht subvol
        ret = bring_bricks_offline(self.volname, subvols[0])
        self.assertTrue(ret, ('Error in bringing down subvolume %s',
                              subvols[0]))
        g.log.info('DHT subvol %s is offline', subvols[0])

        # Create the dir1
        self._create_dir(dir_name="dir1")

        # Calling the local function
        self._create_xattr_check_self_heal()