def search_volume(volname): """Search for a Volume by name in all Hosting Volumes""" volhash = get_volname_hash(volname) subdir_path = get_volume_path(PV_TYPE_SUBVOL, volhash, volname) virtblock_path = get_volume_path(PV_TYPE_VIRTBLOCK, volhash, volname) host_volumes = get_pv_hosting_volumes() for hvol in host_volumes: mntdir = os.path.join(HOSTVOL_MOUNTDIR, hvol) # Try to mount the Host Volume, handle failure if already mounted mount_glusterfs(hvol, mntdir) for info_path in [subdir_path, virtblock_path]: info_path_full = os.path.join(mntdir, "info", info_path + ".json") voltype = PV_TYPE_SUBVOL if "/%s/" % PV_TYPE_SUBVOL \ in info_path_full else PV_TYPE_VIRTBLOCK if os.path.exists(info_path_full): data = {} with open(info_path_full) as info_file: data = json.load(info_file) return Volume(volname=volname, voltype=voltype, volhash=volhash, hostvol=hvol, size=data["size"]) return None
def search_volume(volname): """Search for a Volume by name in all Hosting Volumes""" volhash = get_volname_hash(volname) subdir_path = get_volume_path(PV_TYPE_SUBVOL, volhash, volname) virtblock_path = get_volume_path(PV_TYPE_VIRTBLOCK, volhash, volname) host_volumes = get_pv_hosting_volumes() for volume in host_volumes: hvol = volume['name'] mntdir = os.path.join(HOSTVOL_MOUNTDIR, hvol) mount_glusterfs(volume, mntdir) # Check for mount availability before checking the info file retry_errors(os.statvfs, [mntdir], [ENOTCONN]) for info_path in [subdir_path, virtblock_path]: info_path_full = os.path.join(mntdir, "info", info_path + ".json") voltype = PV_TYPE_SUBVOL if "/%s/" % PV_TYPE_SUBVOL \ in info_path_full else PV_TYPE_VIRTBLOCK if os.path.exists(info_path_full): data = {} with open(info_path_full) as info_file: data = json.load(info_file) return Volume(volname=volname, voltype=voltype, volhash=volhash, hostvol=hvol, size=data["size"]) return None
def handle_quota(quota_report, brick_path, volname, pvtype): """Sets Quota if info file is available""" volhash = get_volname_hash(volname) volpath = get_volume_path(pvtype, volhash, volname) subdir_path = os.path.join(brick_path, volpath) projid = "#%d" % os.lstat(subdir_path).st_ino limit_hard = 0 for line in quota_report: if line.startswith(projid): limit_hard = int(line.split()[3]) break # Quota is already set, continue # TODO: Handle PV resize requests if limit_hard > 0: return pvinfo_file_path = os.path.join(brick_path, "info", volpath + ".json") if os.path.exists(pvinfo_file_path): data = {} with open(pvinfo_file_path) as pvinfo_file: data = json.loads(pvinfo_file.read().strip()) try: set_quota(os.path.dirname(brick_path), subdir_path, data["size"]) except CommandException as err: logging.error( logf("Failed to set Quota", err=err.err, path=subdir_path.replace(brick_path, ""), size=data["size"])) return
def create_virtblock_volume(hostvol_mnt, volname, size): """Create virtual block volume""" volhash = get_volname_hash(volname) volpath = get_volume_path(PV_TYPE_VIRTBLOCK, volhash, volname) volpath_full = os.path.join(hostvol_mnt, volpath) logging.debug(logf("Volume hash", volhash=volhash)) # Create a file with required size makedirs(os.path.dirname(volpath_full)) logging.debug( logf("Created virtblock directory", path=os.path.dirname(volpath))) volpath_fd = os.open(volpath_full, os.O_CREAT | os.O_RDWR) os.close(volpath_fd) os.truncate(volpath_full, size) logging.debug( logf("Truncated file to required size", path=volpath, size=size)) # TODO: Multiple FS support based on volume_capability mount option execute(MKFS_XFS_CMD, volpath_full) logging.debug( logf("Created Filesystem", path=volpath, command=MKFS_XFS_CMD)) save_pv_metadata(hostvol_mnt, volpath, size) return Volume( volname=volname, voltype=PV_TYPE_VIRTBLOCK, volhash=volhash, hostvol=os.path.basename(hostvol_mnt), size=size, volpath=volpath, )
def create_subdir_volume(hostvol_mnt, volname, size): """Create sub directory Volume""" volhash = get_volname_hash(volname) volpath = get_volume_path(PV_TYPE_SUBVOL, volhash, volname) logging.debug(logf("Volume hash", volhash=volhash)) # Check for mount availability before creating subdir volume retry_errors(os.statvfs, [hostvol_mnt], [ENOTCONN]) # Create a subdir makedirs(os.path.join(hostvol_mnt, volpath)) logging.debug(logf("Created PV directory", pvdir=volpath)) # Write info file so that Brick's quotad sidecar # container picks it up. save_pv_metadata(hostvol_mnt, volpath, size) # Wait for quota set # TODO: Handle Timeout pvsize_buffer = size * 0.05 # 5% pvsize_min = (size - pvsize_buffer) pvsize_max = (size + pvsize_buffer) logging.debug( logf( "Watching df of pv directory", pvdir=volpath, pvsize_buffer=pvsize_buffer, )) count = 0 while True: count += 1 pvstat = retry_errors(os.statvfs, [os.path.join(hostvol_mnt, volpath)], [ENOTCONN]) volsize = pvstat.f_blocks * pvstat.f_bsize if pvsize_min < volsize < pvsize_max: logging.debug( logf("Matching df output, Quota set successful", volsize=volsize, num_tries=count)) break if count >= 6: logging.warning( logf("Waited for some time, Quota set failed, continuing.", volsize=volsize, num_tries=count)) break time.sleep(1) return Volume( volname=volname, voltype=PV_TYPE_SUBVOL, volhash=volhash, hostvol=os.path.basename(hostvol_mnt), size=size, volpath=volpath, )
def setpath(self): """Set Volume path based on hash and volume name""" if self.volpath is None: self.volpath = get_volume_path( self.voltype, self.volhash, self.volname )
def create_virtblock_volume(hostvol_mnt, volname, size): """Create virtual block volume""" volhash = get_volname_hash(volname) volpath = get_volume_path(PV_TYPE_VIRTBLOCK, volhash, volname) volpath_full = os.path.join(hostvol_mnt, volpath) logging.debug(logf( "Volume hash", volhash=volhash )) # Check for mount availability before creating virtblock volume retry_errors(os.statvfs, [hostvol_mnt], [ENOTCONN]) # Create a file with required size makedirs(os.path.dirname(volpath_full)) logging.debug(logf( "Created virtblock directory", path=os.path.dirname(volpath) )) if os.path.exists(volpath_full): rand = time.time() logging.info(logf( "Getting 'Create request' on existing file, renaming.", path=volpath_full, random=rand )) os.rename(volpath_full, "%s.%s" % (volpath_full, rand)) volpath_fd = os.open(volpath_full, os.O_CREAT | os.O_RDWR) os.close(volpath_fd) os.truncate(volpath_full, size) logging.debug(logf( "Truncated file to required size", path=volpath, size=size )) # TODO: Multiple FS support based on volume_capability mount option execute(MKFS_XFS_CMD, volpath_full) logging.debug(logf( "Created Filesystem", path=volpath, command=MKFS_XFS_CMD )) save_pv_metadata(hostvol_mnt, volpath, size) return Volume( volname=volname, voltype=PV_TYPE_VIRTBLOCK, volhash=volhash, hostvol=os.path.basename(hostvol_mnt), size=size, volpath=volpath, )
def create_subdir_volume(hostvol_mnt, volname, size): """Create sub directory Volume""" volhash = get_volname_hash(volname) volpath = get_volume_path(PV_TYPE_SUBVOL, volhash, volname) logging.debug(logf("Volume hash", volhash=volhash)) # Create a subdir os.makedirs(os.path.join(hostvol_mnt, volpath), exist_ok=True) logging.debug(logf("Created PV directory", pvdir=volpath)) # Write info file so that Brick's quotad sidecar # container picks it up. save_pv_metadata(hostvol_mnt, volpath, size) # Wait for quota set # TODO: Handle Timeout pvsize_buffer = size * 0.05 # 5% pvsize_min = (size - pvsize_buffer) pvsize_max = (size + pvsize_buffer) logging.debug( logf( "Watching df of pv directory", pvdir=volpath, pvsize_buffer=pvsize_buffer, )) count = 0 while True: count += 1 pvstat = os.statvfs(os.path.join(hostvol_mnt, volpath)) volsize = pvstat.f_blocks * pvstat.f_bsize if pvsize_min < volsize < pvsize_max: logging.debug( logf("Matching df output, Quota set successful", volsize=volsize, num_tries=count)) break time.sleep(1) return Volume(volname=volname, voltype=PV_TYPE_SUBVOL, volhash=volhash, hostvol=os.path.basename(hostvol_mnt), size=size)
def handle_quota(brick_path, volname, pvtype): """Sets Quota if info file is available""" volhash = get_volname_hash(volname) volpath = get_volume_path(pvtype, volhash, volname) subdir_path = os.path.join(brick_path, volpath) pvinfo_file_path = os.path.join(brick_path, "info", volpath + ".json") if os.path.exists(pvinfo_file_path): data = {} with open(pvinfo_file_path) as pvinfo_file: data = json.loads(pvinfo_file.read().strip()) # global dictionary to avoid init to None global SIZE_LIMITS # Add every new entry of volnames if volname not in SIZE_LIMITS: SIZE_LIMITS[volname] = {} # Handle PV resize quota updates # Init existing_size to -1 to handle new quota requests # Update existing_size for every update requests if data["size"] > SIZE_LIMITS[volname].get('existing_size', -1): SIZE_LIMITS[volname]['existing_size'] = data["size"] # Quota already set for size, return else: return try: set_quota(os.path.dirname(brick_path), subdir_path, data["size"]) logging.info(logf("Quota set for size", size=data["size"])) except CommandException as err: logging.error( logf("Failed to set Quota", err=err.err, path=subdir_path.replace(brick_path, ""), size=data["size"])) return
def update_virtblock_volume(hostvol_mnt, volname, expansion_requested_pvsize): """Update virtual block volume""" volhash = get_volname_hash(volname) volpath = get_volume_path(PV_TYPE_VIRTBLOCK, volhash, volname) volpath_full = os.path.join(hostvol_mnt, volpath) logging.debug(logf("Volume hash", volhash=volhash)) # Check for mount availability before updating virtblock volume retry_errors(os.statvfs, [hostvol_mnt], [ENOTCONN]) # Update the file with required size makedirs(os.path.dirname(volpath_full)) logging.debug( logf("Updated virtblock directory", path=os.path.dirname(volpath))) volpath_fd = os.open(volpath_full, os.O_CREAT | os.O_RDWR) os.close(volpath_fd) execute("truncate", "-s", expansion_requested_pvsize, volpath_full) logging.debug( logf("Truncated file to required size", path=volpath, size=expansion_requested_pvsize)) # TODO: Multiple FS support based on volume_capability mount option execute(MKFS_XFS_CMD, volpath_full) logging.debug( logf("Created Filesystem", path=volpath, command=MKFS_XFS_CMD)) update_pv_metadata(hostvol_mnt, volpath, expansion_requested_pvsize) return Volume( volname=volname, voltype=PV_TYPE_VIRTBLOCK, volhash=volhash, hostvol=os.path.basename(hostvol_mnt), size=expansion_requested_pvsize, volpath=volpath, )
def create_subdir_volume(hostvol_mnt, volname, size): """Create sub directory Volume""" volhash = get_volname_hash(volname) volpath = get_volume_path(PV_TYPE_SUBVOL, volhash, volname) logging.debug(logf("Volume hash", volhash=volhash)) # Check for mount availability before creating subdir volume retry_errors(os.statvfs, [hostvol_mnt], [ENOTCONN]) # Create a subdir makedirs(os.path.join(hostvol_mnt, volpath)) logging.debug(logf("Created PV directory", pvdir=volpath)) # Write info file so that Brick's quotad sidecar # container picks it up. save_pv_metadata(hostvol_mnt, volpath, size) # Wait for quota set # TODO: Handle Timeout pvsize_buffer = size * 0.05 # 5% pvsize_min = (size - pvsize_buffer) pvsize_max = (size + pvsize_buffer) logging.debug( logf( "Watching df of pv directory", pvdir=volpath, pvsize_buffer=pvsize_buffer, )) #setfattr -n trusted.glusterfs.namespace -v true #setfattr -n trusted.gfs.squota.limit -v size try: retry_errors(os.setxattr, [ os.path.join(hostvol_mnt, volpath), "trusted.glusterfs.namespace", "true".encode() ], [ENOTCONN]) retry_errors(os.setxattr, [ os.path.join(hostvol_mnt, volpath), "trusted.gfs.squota.limit", str(size).encode() ], [ENOTCONN]) # noqa # pylint: disable=broad-except except Exception as err: logging.info( logf("Failed to set quota using simple-quota. Continuing", error=err)) count = 0 while True: count += 1 pvstat = retry_errors(os.statvfs, [os.path.join(hostvol_mnt, volpath)], [ENOTCONN]) volsize = pvstat.f_blocks * pvstat.f_bsize if pvsize_min < volsize < pvsize_max: logging.debug( logf("Matching df output, Quota set successful", volsize=volsize, num_tries=count)) break if count >= 6: logging.warning( logf("Waited for some time, Quota set failed, continuing.", volsize=volsize, num_tries=count)) break time.sleep(1) return Volume( volname=volname, voltype=PV_TYPE_SUBVOL, volhash=volhash, hostvol=os.path.basename(hostvol_mnt), size=size, volpath=volpath, )
def update_subdir_volume(hostvol_mnt, hostvoltype, volname, expansion_requested_pvsize): """Update sub directory Volume""" volhash = get_volname_hash(volname) volpath = get_volume_path(PV_TYPE_SUBVOL, volhash, volname) logging.debug(logf("Volume hash", volhash=volhash)) # Check for mount availability before updating subdir volume retry_errors(os.statvfs, [hostvol_mnt], [ENOTCONN]) # Create a subdir makedirs(os.path.join(hostvol_mnt, volpath)) logging.debug(logf("Updated PV directory", pvdir=volpath)) # Write info file so that Brick's quotad sidecar # container picks it up. update_pv_metadata(hostvol_mnt, volpath, expansion_requested_pvsize) # Wait for quota set # TODO: Handle Timeout pvsize_buffer = expansion_requested_pvsize * 0.05 # 5% pvsize_min = (expansion_requested_pvsize - pvsize_buffer) pvsize_max = (expansion_requested_pvsize + pvsize_buffer) logging.debug( logf( "Watching df of pv directory", pvdir=volpath, pvsize_buffer=pvsize_buffer, )) # Handle this case in calling function if hostvoltype == 'External': return None retry_errors(os.setxattr, [ os.path.join(hostvol_mnt, volpath), "trusted.gfs.squota.limit", str(expansion_requested_pvsize).encode() ], [ENOTCONN]) count = 0 while True: count += 1 pvstat = retry_errors(os.statvfs, [os.path.join(hostvol_mnt, volpath)], [ENOTCONN]) volsize = pvstat.f_blocks * pvstat.f_bsize if pvsize_min < volsize < pvsize_max: logging.debug( logf("Matching df output, Quota update set successful", volsize=volsize, pvsize=expansion_requested_pvsize, num_tries=count)) break if count >= 6: logging.warning( logf( "Waited for some time, Quota update set failed, continuing.", volsize=volsize, pvsize=expansion_requested_pvsize, num_tries=count)) break time.sleep(1) return Volume( volname=volname, voltype=PV_TYPE_SUBVOL, volhash=volhash, hostvol=os.path.basename(hostvol_mnt), size=expansion_requested_pvsize, volpath=volpath, )