summaryrefslogtreecommitdiffstats
path: root/tests/functional/disperse/test_ec_eager_lock_functional_validation.py
blob: b4fb4c9d9b33c295431855a2a0d13853f073bcaa (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
#  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.

"""
Test Description:
    Verify Eager lock reduces the number of locks
    being taken when writing to the file continuosly
"""
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.volume_ops import set_volume_options
from glustolibs.gluster.volume_libs import get_subvols
from glustolibs.gluster.profile_ops import (profile_start, profile_stop)
from glustolibs.gluster.dht_test_utils import find_hashed_subvol
from glustolibs.gluster.lib_utils import get_extended_attributes_info


@runs_on([['dispersed', 'distributed-dispersed'], ['glusterfs']])
class EagerlockFunctionalValidationTest(GlusterBaseClass):
    # Method to setup the environment for test case

    def setUp(self):
        self.get_super_method(self, 'setUp')()
        ret = self.setup_volume_and_mount_volume(mounts=self.mounts,
                                                 volume_create_force=True)
        if not ret:
            raise ExecutionError("Failed to setup and mount volume")

    def _check_dirty_xattr(self, filename):
        """Get trusted.ec.dirty xattr value to validate eagerlock behavior"""
        # Find the hashed subvol of the file created
        # for distributed disperse case
        subvols_info = get_subvols(self.mnode, self.volname)
        subvols_info = subvols_info['volume_subvols']
        if len(subvols_info) > 1:
            _, hashed_subvol = find_hashed_subvol(subvols_info,
                                                  '', filename)
            if hashed_subvol is None:
                g.log.error("Error in finding hash value of %s", filename)
                return None
        else:
            hashed_subvol = 0

        # Collect ec.dirty xattr value from each brick
        result = []
        for subvol in subvols_info[hashed_subvol]:
            host, brickpath = subvol.split(':')
            brickpath = brickpath + '/' + filename
            ret = get_extended_attributes_info(host, [brickpath],
                                               encoding='hex',
                                               attr_name='trusted.ec.dirty')
            ret = ret[brickpath]['trusted.ec.dirty']
            result.append(ret)

        # Check if xattr values are same across all bricks
        if result.count(result[0]) == len(result):
            return ret
        g.log.error("trusted.ec.dirty value is not consistent across the "
                    "disperse set %s", result)
        return None

    def _file_create_and_profile_info(self, status):
        """Create a file and check the volume profile for inode lock count."""
        # Creating file
        mountpoint = self.mounts[0].mountpoint
        client = self.mounts[0].client_system

        filename = 'f1_EagerLock_' + status
        cmd = ("dd if=/dev/urandom of=%s/%s bs=100M count=10"
               % (mountpoint, filename))

        ret, _, _ = g.run(client, cmd)
        self.assertEqual(ret, 0, "Failed to create file on mountpoint")
        g.log.info("Successfully created files on mountpoint")

        # Getting and checking output of profile info.
        cmd = "gluster volume profile %s info | grep -i INODELK" % self.volname
        ret, rout, _ = g.run(self.mnode, cmd)
        self.assertEqual(ret, 0, "Failed to grep INODELK count from profile "
                         "info")
        g.log.info("The lock counts on all bricks with eager-lock %s: %s",
                   status, rout)

        return filename

    def test_validate_profile_for_inodelk(self):
        """
        Test Steps:
        1) Create an ecvolume and mount it
        2) Set the eagerlock option
        3) Create a 1GB file
        4) View the profile of the volume for INODELK count must be about
           2-10 locks for each brick.
        5) check backend bricks for trusted.ec.dirty xattr must be non-zero
        6) Disable the eagerlock option
        7) Repeat steps 3-5 and now dirty xattr must be zero and
           INODELK count in range of 100-5k.
        """

        # Enable EagerLock
        ret = set_volume_options(self.mnode, self.volname,
                                 {'disperse.eager-lock': 'on',
                                  'disperse.eager-lock-timeout': '10'})
        self.assertTrue(ret, "Failed to turn on eagerlock"
                             "on %s" % self.volname)

        # Start profile on volume.
        ret, _, _ = profile_start(self.mnode, self.volname)
        self.assertEqual(ret, 0, "Failed to start profile on volume: %s"
                         % self.volname)

        # Test behavior with EagerLock on
        filename = self._file_create_and_profile_info("on")
        self.assertIsNotNone(filename, "Failed to get filename")

        # Test dirty bit with EagerLock on
        ret = self._check_dirty_xattr(filename)
        self.assertEqual(ret, '0x00000000000000010000000000000001',
                         "Unexpected dirty xattr value is %s on %s"
                         % (ret, filename))

        # Disable EagerLock
        ret = set_volume_options(self.mnode, self.volname,
                                 {'disperse.eager-lock': 'off'})
        self.assertTrue(ret, "Failed to turn off eagerlock "
                             "on %s" % self.volname)

        # Test behavior with EagerLock off
        filename = self._file_create_and_profile_info("off")
        self.assertIsNotNone(filename, "Failed to get filename")

        # Test dirty bit with EagerLock off
        ret = self._check_dirty_xattr(filename)
        self.assertEqual(ret, '0x00000000000000000000000000000000',
                         "Unexpected dirty xattr value is %s on %s"
                         % (ret, filename))

        # Stop profile on volume.
        ret, _, _ = profile_stop(self.mnode, self.volname)
        self.assertEqual(ret, 0, "Failed to stop profile on volume: %s"
                         % self.volname)

    def tearDown(self):
        ret = self.unmount_volume_and_cleanup_volume(mounts=self.mounts)
        if not ret:
            raise ExecutionError("Failed to Unmount Volume and Cleanup Volume")