def find_new_hashed(subvols, parent_path, oldname): ''' This is written for rename case so that the new name will hash to a different subvol than that of the the old name. Note: The new hash will be searched under the same parent Args: subvols = list of subvols parent_path = parent path (relative to mount) of "oldname" oldname = name of the source file for rename operation Return Values: For success returns an object of type NewHashed holding information pertaining to new name. For Failure returns None ''' # pylint: disable=protected-access # pylint: disable=pointless-string-statement # pylint: disable=too-many-locals # pylint: disable=too-many-statements # pylint: disable=too-many-branches # pylint: disable=too-many-return-statements brickobject = create_brickobjectlist(subvols, parent_path) if brickobject is None: g.log.error("could not form brickobject list") return None for bro in brickobject: bro._get_hashrange() low = bro._hashrange_low high = bro._hashrange_high g.log.debug("low hashrange %s high hashrange %s", str(low), str(high)) g.log.debug("absoulte path %s", bro._fqpath) hash_num = calculate_hash(brickobject[0]._host, oldname) oldhashed, _ = find_hashed_subvol(subvols, parent_path, oldname) if oldhashed is None: g.log.error("could not find old hashed subvol") return None g.log.debug("oldhashed: %s oldname: %s oldhash %s", oldhashed._host, oldname, hash_num) count = -1 for item in range(1, 5000, 1): newhash = calculate_hash(brickobject[0]._host, str(item)) for brickdir in brickobject: count += 1 ret = brickdir.hashrange_contains_hash(newhash) if ret == 1: if oldhashed._fqpath != brickdir._fqpath: g.log.debug("oldhashed %s new %s count %s", oldhashed, brickdir._host, str(count)) return NewHashed(item, brickdir, count) count = -1 return None
def find_specific_hashed(subvols, parent_path, subvol): """ Finds filename that hashes to a specific subvol. Args: subvols(list): list of subvols parent_path(str): parent path (relative to mount) of "oldname" subvol(str): The subvol to which the new name has to be hashed Returns: (Class Object): For success returns an object of type NewHashed holding information pertaining to new name. None, otherwise Note: The new hash will be searched under the same parent """ # pylint: disable=protected-access brickobject = create_brickobjectlist(subvols, parent_path) if brickobject is None: g.log.error("could not form brickobject list") return None count = -1 for item in range(1, 5000, 1): newhash = calculate_hash(brickobject[0]._host, str(item)) for brickdir in brickobject: count += 1 if subvol._fqpath == brickdir._fqpath: ret = brickdir.hashrange_contains_hash(newhash) if ret: g.log.debug("oldhashed %s new %s count %s", subvol, brickdir._host, str(count)) return NewHashed(item, brickdir, count) count = -1 return None
def find_nonhashed_subvol(subvols, parent_path, name): ''' Args: subvols: subvol list parent_path: Immediate parent path of "name" relative from mount point e.g. if your mount is "/mnt" and the path from mount is "/mnt/directory" then just pass "directory" as parent_path name: file or directory name Return Values: nonhashed_subvol object: An object of type BrickDir type representing the nonhashed subvolume subvol_count: The subvol index in the subvol list ''' # pylint: disable=protected-access if subvols is None or parent_path is None or name is None: g.log.error("empty arguments") return None, -1 brickobject = create_brickobjectlist(subvols, parent_path) hash_num = calculate_hash(brickobject[0]._host, name) count = -1 for brickdir in brickobject: count += 1 ret = brickdir.hashrange_contains_hash(hash_num) if ret == 1: g.log.debug('hash subvolume is %s', brickdir.path) continue nonhashed_subvol = brickdir g.log.info('nonhashed subvol %s', brickdir._host) break return nonhashed_subvol, count
def test_create_file(self): ''' Test file creation. ''' # pylint: disable=too-many-locals # pylint: disable=protected-access # pylint: disable=too-many-statements mount_obj = self.mounts[0] mountpoint = mount_obj.mountpoint # files that needs to be created file_one = mountpoint + '/file1' # hash for file_one filehash = calculate_hash(self.servers[0], 'file1') # collect subvol info subvols = (get_subvols(self.mnode, self.volname))['volume_subvols'] secondary_bricks = [] for subvol in subvols: secondary_bricks.append(subvol[0]) brickobject = [] for item in secondary_bricks: temp = BrickDir(item) brickobject.append(temp) # create a file ret, _, _ = g.run(self.clients[0], ("touch %s" % file_one)) self.assertEqual(ret, 0, ("File %s creation failed", file_one)) # get pathinfo xattr on the file ret, out, err = g.run(self.clients[0], ("getfattr -n trusted.glusterfs.pathinfo %s" % file_one)) g.log.info("pathinfo o/p %s", out) self.assertEqual(ret, 0, ("failed to get pathinfo on file %s err %s", file_one, err)) vol_type = self.volume_type if vol_type == "distributed": brickhost = (out.split(":"))[3] brickpath = (out.split(":"))[4].split(">")[0] else: brickhost = (out.split(":"))[4] brickpath = (out.split(":")[5]).split(">")[0] g.log.debug("brickhost %s brickpath %s", brickhost, brickpath) # make sure the file is present only on the hashed brick count = -1 for brickdir in brickobject: count += 1 ret = brickdir.hashrange_contains_hash(filehash) if ret: hash_subvol = subvols[count] ret, _, err = g.run(brickdir._host, ("stat %s/file1" % brickdir._fqpath)) g.log.info("Hashed subvol is %s", brickdir._host) self.assertEqual(ret, 0, "Expected stat to succeed for file1") continue ret, _, err = g.run(brickdir._host, ("stat %s/file1" % brickdir._fqpath)) self.assertEqual(ret, 1, "Expected stat to fail for file1") # checking if pathinfo xattr has the right value ret, _, _ = g.run(brickhost, ("stat %s" % brickpath)) self.assertEqual(ret, 0, ("Expected file1 to be present on %s", brickhost)) # get permission from mount ret, out, _ = g.run(self.clients[0], ("ls -l %s" % file_one)) mperm = (out.split(" "))[0] self.assertIsNotNone(mperm, "Expected stat to fail for file1") g.log.info("permission on mount %s", mperm) # get permission from brick ret, out, _ = g.run(brickhost, ("ls -l %s" % brickpath)) bperm = (out.split(" "))[0] self.assertIsNotNone(bperm, "Expected stat to fail for file1") g.log.info("permission on brick %s", bperm) # check if the permission matches self.assertEqual(mperm, bperm, "Expected permission to match") # check that gfid xattr is present on the brick ret, _, _ = g.run(brickhost, ("getfattr -n trusted.gfid %s" % brickpath)) self.assertEqual(ret, 0, "gfid is not present on file") # delete the file, bring down it's hash, create the file, ret, _, _ = g.run(self.clients[0], ("rm -f %s" % file_one)) self.assertEqual(ret, 0, "file deletion for file1 failed") ret = bring_bricks_offline(self.volname, hash_subvol) self.assertTrue(ret, ('Error in bringing down subvolume %s', hash_subvol)) # check file creation should fail ret, _, _ = g.run(self.clients[0], ("touch %s" % file_one)) self.assertTrue(ret, "Expected file creation to fail")
def test_directory_heal(self): ''' Test directory healing. ''' # pylint: disable=too-many-locals # pylint: disable=too-many-statements # pylint: disable=protected-access mount_obj = self.mounts[0] mountpoint = mount_obj.mountpoint # directory that needs to be created parent_dir = mountpoint + '/parent' target_dir = mountpoint + '/parent/child' # create parent dir ret, _, err = g.run(self.clients[0], ("mkdir %s" % parent_dir)) g.log.info("mkdir of parent directory %s successful", parent_dir) self.assertEqual(ret, 0, ('mkdir failed for %s err: %s', parent_dir, err)) g.log.info("mkdir of parent successful") # find non-hashed subvol for child hashed, non_hashed = [], [] hash_num = calculate_hash(self.mnode, "child") bricklist = get_all_bricks(self.mnode, self.volname) for brick in bricklist: ret = check_hashrange(brick + "/parent") hash_range_low = ret[0] hash_range_high = ret[1] if hash_range_low <= hash_num <= hash_range_high: hashed.append(brick) non_hashed = [brick for brick in bricklist if brick not in hashed] g.log.info("Non-hashed bricks are: %s", non_hashed) # bring non_hashed offline for brick in non_hashed: ret = bring_bricks_offline(self.volname, brick) self.assertTrue(ret, ('Error in bringing down brick %s', brick)) g.log.info('Non-hashed brick %s is offline', brick) # create child directory runc = ("mkdir %s" % target_dir) ret, _, _ = g.run(self.clients[0], runc) self.assertEqual(ret, 0, ('failed to create dir %s' % target_dir)) g.log.info('mkdir successful %s', target_dir) # Check that the dir is not created on the down brick for brick in non_hashed: non_hashed_host, dir_path = brick.split(":") brickpath = ("%s/parent/child" % dir_path) ret, _, _ = g.run(non_hashed_host, ("stat %s" % brickpath)) self.assertEqual(ret, 1, ("Expected %s to be not present on %s" % (brickpath, non_hashed_host))) g.log.info("Stat of %s failed as expected", brickpath) # bring up the subvol ret = bring_bricks_online( self.mnode, self.volname, non_hashed, bring_bricks_online_methods='volume_start_force') self.assertTrue(ret, "Error in bringing back subvol online") g.log.info("Subvol is back online") runc = ("ls %s" % target_dir) ret, _, _ = g.run(self.clients[0], runc) self.assertEqual(ret, 0, ("Lookup on %s failed", target_dir)) g.log.info("Lookup is successful on %s", target_dir) # check if the directory is created on non_hashed for brick in non_hashed: non_hashed_host, dir_path = brick.split(":") absolutedirpath = ("%s/parent/child" % dir_path) ret = get_file_stat(non_hashed_host, absolutedirpath) self.assertIsNotNone(ret, "Directory is not present on non_hashed") g.log.info("Directory is created on non_hashed subvol") # check if directory is healed => i.e. layout is zeroed out for brick in non_hashed: brick_path = ("%s/parent/child" % brick) ret = check_hashrange(brick_path) hash_range_low = ret[0] hash_range_high = ret[1] if not hash_range_low and not hash_range_high: g.log.info("Directory healing successful") else: g.log.error("Directory is not healed")