def extend_lv(self, lv_name, vg_name, size, cmd_extend, subproc_env, plugin_name): """ Extends an LVM logical volume """ status = False try: exec_args = [ cmd_extend, "-L", str(size) + "k", vg_name + "/" + lv_name ] utils.debug_log_exec_args(self.__class__.__name__, exec_args) proc_rc = subprocess.call(exec_args, 0, cmd_extend, env=subproc_env, close_fds=True) if proc_rc == 0: status = True except OSError as os_err: logging.error( plugin_name + ": LV extension failed, unable to run " "external program '%s', error message from the OS: %s" % (cmd_extend, str(os_err))) return status
def _create_vol(self, vol_name, size, thin=False): size, bs = self._final_size(size) zfs_vol_name = utils.build_path(self._conf[consts.KEY_VG_NAME], vol_name) try: exec_args = [self._cmd_create, self.ZFS_CREATE] if thin: exec_args.append('-s') exec_args += ['-b'+bs, '-V', str(size) + 'k', zfs_vol_name] utils.debug_log_exec_args(self.__class__.__name__, exec_args) zfs_proc = subprocess.Popen( exec_args, 0, self._cmd_create, env=self._subproc_env, close_fds=True ) zfs_rc = zfs_proc.wait() if zfs_rc == 0: path = os.path.join(self._conf[self.KEY_DEV_PATH], zfs_vol_name) if not self._wait_dev_to_settle(path): raise StoragePluginException except OSError as os_err: logging.error( "Zvol: LV creation failed, unable to run " "external program '%s', error message from the OS: %s" % (self._cmd_create, str(os_err)) ) raise StoragePluginException
def _check_vol_exists(self, vol_name): exists = False try: exec_args = [self._cmd_list, self.ZVOL_LIST] if '.' in vol_name: vol_name = self._vol_name_to_snapshot(vol_name) exec_args += ['-t', 'snapshot'] exec_args.append( utils.build_path(self._conf[consts.KEY_VG_NAME], vol_name)) utils.debug_log_exec_args(self.__class__.__name__, exec_args) zfs_proc = subprocess.Popen(exec_args, 0, self._cmd_list, env=self._subproc_env, close_fds=True) zfs_rc = zfs_proc.wait() if zfs_rc == 0: exists = True except OSError: logging.error( "Zvol2: Unable to retrieve the list of existing Zvols") raise StoragePluginCheckFailedException return exists
def update_pool(self, node): fn_rc = exc.DM_ESTORAGE pool_size = -1 pool_free = -1 zpool_proc = None try: exec_args = [ self._cmd_vgs, 'get', '-H', '-p', 'available,used', self._conf[consts.KEY_VG_NAME] ] utils.debug_log_exec_args(self.__class__.__name__, exec_args) zpool_proc = subprocess.Popen( exec_args, env=self._subproc_env, stdout=subprocess.PIPE, close_fds=True ) # output should be sorted, but just to be sure for i in range(2): pool_data = zpool_proc.stdout.readline() if len(pool_data) > 0: pool_data = pool_data.strip().split() if pool_data[1].strip() == 'available': pool_free = long(pool_data[2].strip()) elif pool_data[1].strip() == 'used': pool_used = long(pool_data[2].strip()) if pool_used == -1 or pool_free == -1: pool_size, pool_free = -1, -1 else: pool_size = pool_free + pool_used pool_size /= 1024 pool_free /= 1024 fn_rc = exc.DM_SUCCESS except Exception as unhandled_exc: logging.error( "Zvol: Retrieving storage pool information failed, " "unhandled exception: %s" % (str(unhandled_exc)) ) finally: if zpool_proc is not None: try: zpool_proc.stdout.close() except Exception: pass zpool_proc.wait() return (fn_rc, pool_size, pool_free)
def update_pool(self, node): fn_rc = exc.DM_ESTORAGE pool_size = -1 pool_free = -1 lvm_proc = None try: exec_args = [ self._cmd_vgs, "--noheadings", "--nosuffix", "--units", "k", "--separator", ",", "--options", "vg_size,vg_free", self._conf[consts.KEY_VG_NAME] ] utils.debug_log_exec_args(self.__class__.__name__, exec_args) lvm_proc = subprocess.Popen(exec_args, env=self._subproc_env, stdout=subprocess.PIPE, close_fds=True) pool_data = lvm_proc.stdout.readline() if len(pool_data) > 0: pool_data.strip() try: size_data, free_data = pool_data.split(",") size_data = self.discard_fraction(size_data) free_data = self.discard_fraction(free_data) # Parse values and assign them in two steps, so that # either both values or none of them will be assigned, # depending on whether parsing succeeds or not size_value = long(size_data) free_value = long(free_data) # Assign values after successful parsing pool_size = size_value pool_free = free_value fn_rc = exc.DM_SUCCESS except ValueError: pass except Exception as unhandled_exc: logging.error("Lvm: Retrieving storage pool information failed, " "unhandled exception: %s" % (str(unhandled_exc))) finally: if lvm_proc is not None: try: lvm_proc.stdout.close() except Exception: pass lvm_proc.wait() return (fn_rc, pool_size, pool_free)
def remove_lv(self, lv_name, vg_name, cmd_remove, subproc_env, plugin_name): try: exec_args = [cmd_remove, "--force", vg_name + "/" + lv_name] utils.debug_log_exec_args(self.__class__.__name__, exec_args) subprocess.call(exec_args, 0, cmd_remove, env=subproc_env, close_fds=True) except OSError as os_err: logging.error( plugin_name + ": LV removal failed, unable to run " "external program '%s', error message from the OS: %s" % (cmd_remove, str(os_err))) raise StoragePluginException
def _create_snapshot_impl(self, snaps_name, lv_name): try: zfs_snap_name = utils.build_path(self._conf[consts.KEY_VG_NAME], lv_name) + '@' + snaps_name exec_args = [ self._cmd_create, self.ZVOL_SNAP_CREATE, zfs_snap_name ] utils.debug_log_exec_args(self.__class__.__name__, exec_args) subprocess.call(exec_args, 0, self._cmd_create, env=self._subproc_env, close_fds=True) except OSError as os_err: logging.error( "Zvol2: Snapshot creation failed, unable to run " "external program '%s', error message from the OS: %s" % (self._cmd_create, str(os_err))) raise StoragePluginException
def _create_snapshot_impl(self, snaps_name, lv_name): try: exec_args = [ self._cmd_create, "-s", self._conf[consts.KEY_VG_NAME] + "/" + lv_name, "-n", snaps_name ] utils.debug_log_exec_args(self.__class__.__name__, exec_args) subprocess.call(exec_args, 0, self._cmd_create, env=self._subproc_env, close_fds=True) except OSError as os_err: logging.error( "LvmThinLv: Snapshot creation failed, unable to run " "external program '%s', error message from the OS: %s" % (self._cmd_create, str(os_err))) raise StoragePluginException
def _remove_vol(self, vol_name): if '.' in vol_name: vol_name = self._vol_name_to_snapshot(vol_name) try: exec_args = [ self._cmd_remove, self.ZVOL_REMOVE, utils.build_path(self._conf[consts.KEY_VG_NAME], vol_name) ] utils.debug_log_exec_args(self.__class__.__name__, exec_args) subprocess.call(exec_args, 0, self._cmd_remove, env=self._subproc_env, close_fds=True) except OSError as os_err: logging.error( "Zvol2: LV remove failed, unable to run " "external program '%s', error message from the OS: %s" % (self._cmd_remove, str(os_err))) raise StoragePluginException
def _create_vol(self, lv_name, size): try: exec_args = [ self._cmd_create, "-n", lv_name, "-L", str(size) + "k", self._conf[consts.KEY_VG_NAME] ] utils.debug_log_exec_args(self.__class__.__name__, exec_args) subprocess.call(exec_args, 0, self._cmd_create, env=self._subproc_env, close_fds=True) except OSError as os_err: logging.error( "Lvm: LV creation failed, unable to run " "external program '%s', error message from the OS: %s" % (self._cmd_create, str(os_err))) raise StoragePluginException devpath = "/dev/" + self._conf[consts.KEY_VG_NAME] + "/" + lv_name utils.wipefs(devpath)
def __create_pool(self, pool_name, size): """ Creates an LVM thin pool """ try: exec_args = [ self._cmd_create, "-L", str(size) + "k", "-T", self._conf[consts.KEY_VG_NAME] + "/" + pool_name ] utils.debug_log_exec_args(self.__class__.__name__, exec_args) subprocess.call( exec_args, 0, self._cmd_create, env=self._subproc_env, close_fds=True ) except OSError as os_err: logging.error( "LvmThinPool: LV creation failed, unable to run " "external program '%s', error message from the OS: %s" % (self._cmd_create, str(os_err)) ) raise StoragePluginException
def check_lv_exists(self, lv_name, vg_name, cmd_lvs, subproc_env, plugin_name): """ Check whether an LVM logical volume exists @returns: True if the LV exists, False if the LV does not exist Throws an StoragePluginCheckFailedException if the check itself fails """ exists = False try: exec_args = [ cmd_lvs, "--noheadings", "--options", "lv_name", vg_name + "/" + lv_name ] utils.debug_log_exec_args(self.__class__.__name__, exec_args) lvm_proc = subprocess.Popen(exec_args, 0, cmd_lvs, env=subproc_env, stdout=subprocess.PIPE, close_fds=True) lv_entry = lvm_proc.stdout.readline() if len(lv_entry) > 0: lv_entry = lv_entry[:-1].strip() if lv_entry == lv_name: exists = True lvm_rc = lvm_proc.wait() # LVM's "lvs" utility exits with exit code 5 if the # LV was not found if lvm_rc != 0 and lvm_rc != LvmCommon.LVM_LVS_ENOENT: raise StoragePluginCheckFailedException except OSError: logging.error(plugin_name + ": Unable to retrieve the list of existing LVs") raise StoragePluginCheckFailedException return exists
def _extend_vol(self, vol_name, size): status = False size, _ = self._final_size(size) try: exec_args = [ self._cmd_extend, self.ZFS_EXTEND, 'volsize=%sk' % str(size), utils.build_path(self._conf[consts.KEY_VG_NAME], vol_name) ] utils.debug_log_exec_args(self.__class__.__name__, exec_args) proc_rc = subprocess.call( exec_args, 0, self._cmd_extend, env=self._subproc_env, close_fds=True ) if proc_rc == 0: status = True except OSError as os_err: logging.error( self.NAME + ": vol extension failed, unable to run " "external program '%s', error message from the OS: %s" % (self._cmd_extend, str(os_err)) ) return status
def _create_snapshot_impl(self, snaps_name, lv_name): try: zfs_snap_name = utils.build_path(self._conf[consts.KEY_VG_NAME], lv_name) + '@' + snaps_name exec_args = [ self._cmd_create, self.ZVOL_SNAP_CREATE, zfs_snap_name ] utils.debug_log_exec_args(self.__class__.__name__, exec_args) subprocess.call( exec_args, 0, self._cmd_create, env=self._subproc_env, close_fds=True ) exec_args = [ self._cmd_create, self.ZVOL_SNAP_CLONE, zfs_snap_name, utils.build_path(self._conf[consts.KEY_VG_NAME], snaps_name) ] utils.debug_log_exec_args(self.__class__.__name__, exec_args) zfs_proc = subprocess.Popen( exec_args, 0, self._cmd_create, env=self._subproc_env, close_fds=True ) zfs_rc = zfs_proc.wait() if zfs_rc == 0: path = os.path.join(self._conf[self.KEY_DEV_PATH], utils.build_path(self._conf[consts.KEY_VG_NAME], snaps_name)) if not self._wait_dev_to_settle(path): raise StoragePluginException except OSError as os_err: logging.error( "Zvol: Snapshot creation failed, unable to run " "external program '%s', error message from the OS: %s" % (self._cmd_create, str(os_err)) ) raise StoragePluginException
def _restore_snapshot(self, vol_name, source_blockdev): try: snaps_name = source_blockdev.get_name() orig = source_blockdev.get_name() vol = orig[-3:] orig = orig.split('.')[0] orig = orig + vol zfs_snap_name = utils.build_path(self._conf[consts.KEY_VG_NAME], orig) + '@' + snaps_name new_vol = utils.build_path(self._conf[consts.KEY_VG_NAME], vol_name) exec_args = [ self._cmd_create, self.ZVOL_SNAP_CLONE, zfs_snap_name, new_vol ] utils.debug_log_exec_args(self.__class__.__name__, exec_args) zfs_proc = subprocess.Popen(exec_args, 0, self._cmd_create, env=self._subproc_env, close_fds=True) zfs_rc = zfs_proc.wait() if zfs_rc == 0: path = os.path.join(self._conf[self.KEY_DEV_PATH], new_vol) if not self._wait_dev_to_settle(path): raise StoragePluginException except OSError as os_err: logging.error( "Zvol: Snapshot creation failed, unable to run " "external program '%s', error message from the OS: %s" % (self._cmd_create, str(os_err))) raise StoragePluginException retblockdevice = storcore.BlockDevice(vol_name, 0, self._vg_path + vol_name) self._volumes[vol_name] = retblockdevice self.save_state(self._volumes) return retblockdevice
def _remove_vol(self, vol_name): origin_data = [] try: exec_args = [ self._cmd_vgs, 'get', '-H', '-p', 'origin', utils.build_path(self._conf[consts.KEY_VG_NAME], vol_name) ] utils.debug_log_exec_args(self.__class__.__name__, exec_args) zpool_proc = subprocess.Popen( exec_args, env=self._subproc_env, stdout=subprocess.PIPE, close_fds=True ) origin_data = zpool_proc.stdout.readline() origin_data = origin_data.strip().split() except: pass try: exec_args = [ self._cmd_remove, self.ZVOL_REMOVE, '-R', utils.build_path(self._conf[consts.KEY_VG_NAME], vol_name) ] utils.debug_log_exec_args(self.__class__.__name__, exec_args) subprocess.call( exec_args, 0, self._cmd_remove, env=self._subproc_env, close_fds=True ) except OSError as os_err: logging.error( "Zvol: LV remove failed, unable to run " "external program '%s', error message from the OS: %s" % (self._cmd_remove, str(os_err)) ) raise StoragePluginException try: if len(origin_data) == 4: # rm origin exec_args = [ self._cmd_remove, self.ZVOL_REMOVE, origin_data[2] ] utils.debug_log_exec_args(self.__class__.__name__, exec_args) subprocess.call( exec_args, 0, self._cmd_remove, env=self._subproc_env, close_fds=True ) except: pass
def up_blockdevice(self, blockdevice): fn_rc = exc.DM_ESTORAGE try: lv_name = blockdevice.get_name() pool_name = None try: pool_name = self._pool_lookup[lv_name] except KeyError: pass vg_activated = False pool_activated = False lv_activated = False try: exec_args = [ self._cmd_vgchange, "-ay", self._conf[consts.KEY_VG_NAME], ] utils.debug_log_exec_args(self.__class__.__name__, exec_args) lvm_rc = subprocess.call( exec_args, 0, self._cmd_vgchange, env=self._subproc_env, close_fds=True ) if lvm_rc == 0: vg_activated = True except OSError as os_err: logging.error( "LvmThinPool: Volume group activation failed, " "unable to run external program '%s', error message " "from the OS: %s" % (self._cmd_vgchange, str(os_err)) ) raise StoragePluginException if pool_name is not None: try: exec_args = [ self._cmd_lvchange, "-ay", "-K", self._conf[consts.KEY_VG_NAME] + "/" + pool_name ] utils.debug_log_exec_args(self.__class__.__name__, exec_args) lvm_rc = subprocess.call( exec_args, 0, self._cmd_lvchange, env=self._subproc_env, close_fds=True ) if lvm_rc == 0: pool_activated = True except OSError as os_err: logging.error( "LvmThinPool: Thin pool activation failed, " "unable to run external program '%s', error message " "from the OS: %s" % (self._cmd_lvchange, str(os_err)) ) raise StoragePluginException else: logging.error( "LvmThinPool: Incomplete activation of volume '%s', " "cannot find the associated thin pool" % (lv_name) ) try: exec_args = [ self._cmd_lvchange, "-ay", "-K", self._conf[consts.KEY_VG_NAME] + "/" + lv_name ] utils.debug_log_exec_args(self.__class__.__name__, exec_args) lvm_rc = subprocess.call( exec_args, 0, self._cmd_lvchange, env=self._subproc_env, close_fds=True ) if lvm_rc == 0: lv_activated = True except OSError as os_err: logging.error( "LvmThinPool: LV activation failed, unable to run " "external program '%s', error message from the OS: %s" % (self._cmd_lvchange, str(os_err)) ) raise StoragePluginException if vg_activated and pool_activated and lv_activated: fn_rc = exc.DM_SUCCESS except (StoragePluginCheckFailedException, StoragePluginException): # Unable to run one of the LVM commands # The error is reported by the corresponding function # # Abort pass except Exception as unhandled_exc: logging.error( "LvmThinPool: Block device creation failed, " "unhandled exception: %s" % (str(unhandled_exc)) ) return fn_rc
def update_pool(self, node): """ Updates the DrbdNode object with the current storage status Determines the current total and free space that is available for allocation on the host this instance of the drbdmanage server is running on and updates the DrbdNode object with that information. @param node: The node to update @type node: DrbdNode object @return: standard return code (see drbdmanage.exceptions) """ fn_rc = exc.DM_ESTORAGE pool_size = -1 pool_free = -1 lvm_proc = None try: exec_args = [ self._cmd_vgs, "--noheadings", "--nosuffix", "--units", "k", "--separator", ",", "--options", "vg_size,vg_free", self._conf[consts.KEY_VG_NAME] ] utils.debug_log_exec_args(self.__class__.__name__, exec_args) lvm_proc = subprocess.Popen( exec_args, env=self._subproc_env, stdout=subprocess.PIPE, close_fds=True ) pool_data = lvm_proc.stdout.readline() if len(pool_data) > 0: pool_data.strip() try: size_data, free_data = pool_data.split(",") size_data = self.discard_fraction(size_data) free_data = self.discard_fraction(free_data) # Parse values and assign them in two steps, so that # either both values or none of them will be assigned, # depending on whether parsing succeeds or not size_value = long(size_data) free_value = long(free_data) # Assign values after successful parsing pool_size = size_value pool_free = free_value fn_rc = exc.DM_SUCCESS except ValueError: pass except Exception as unhandled_exc: logging.error( "LvmThinPool: Retrieving storage pool information failed, " "unhandled exception: %s" % (str(unhandled_exc)) ) finally: if lvm_proc is not None: try: lvm_proc.stdout.close() except Exception: pass lvm_proc.wait() return (fn_rc, pool_size, pool_free)
def update_pool(self, node): fn_rc = exc.DM_ESTORAGE pool_size = -1 pool_free = -1 lvm_proc = None try: exec_args = [ self._cmd_lvs, "--noheadings", "--nosuffix", "--units", "k", "--separator", ",", "--options", "size,data_percent", self._conf[consts.KEY_VG_NAME] + "/" + self._conf[LvmThinLv.KEY_POOL_NAME] ] utils.debug_log_exec_args(self.__class__.__name__, exec_args) lvm_proc = subprocess.Popen(exec_args, env=self._subproc_env, stdout=subprocess.PIPE, close_fds=True) pool_data = lvm_proc.stdout.readline() if len(pool_data) > 0: pool_data.strip() try: size_data, data_part = (pool_data.split(",")) size_data = self.discard_fraction(size_data) space_size = long(size_data) # Data percentage data_perc = float(0) if len(data_part) > 0: try: data_perc = float(data_part) / 100 except ValueError: pass # Calculate the amount of occupied space space_used = data_perc * space_size space_free = int(space_size - space_used) if space_free < 0: space_free = 0 # Finally, assign the results to the variables # that will be returned, so that neither will be set # if any of the earlier parsers or calculations fail pool_size = space_size pool_free = space_free fn_rc = exc.DM_SUCCESS except ValueError: pass except Exception as unhandled_exc: logging.error( "LvmThinLv: Retrieving storage pool information failed, " "unhandled exception: %s" % (str(unhandled_exc))) finally: if lvm_proc is not None: try: lvm_proc.stdout.close() except Exception: pass lvm_proc.wait() return (fn_rc, pool_size, pool_free)
def up_blockdevice(self, blockdevice): fn_rc = exc.DM_ESTORAGE try: lv_name = blockdevice.get_name() vg_activated = False lv_activated = False try: exec_args = [ self._cmd_vgchange, "-ay", self._conf[consts.KEY_VG_NAME], ] utils.debug_log_exec_args(self.__class__.__name__, exec_args) lvm_rc = subprocess.call(exec_args, 0, self._cmd_vgchange, env=self._subproc_env, close_fds=True) if lvm_rc == 0: vg_activated = True except OSError as os_err: logging.error( "LvmThinLv: Volume group activation failed, " "unable to run external program '%s', error message " "from the OS: %s" % (self._cmd_vgchange, str(os_err))) raise StoragePluginException try: exec_args = [ self._cmd_lvchange, "-ay", "-K", self._conf[consts.KEY_VG_NAME] + "/" + lv_name ] utils.debug_log_exec_args(self.__class__.__name__, exec_args) lvm_rc = subprocess.call(exec_args, 0, self._cmd_lvchange, env=self._subproc_env, close_fds=True) if lvm_rc == 0: lv_activated = True except OSError as os_err: logging.error( "LvmThinLv: LV activation failed, unable to run " "external program '%s', error message from the OS: %s" % (self._cmd_lvchange, str(os_err))) raise StoragePluginException if vg_activated and lv_activated: fn_rc = exc.DM_SUCCESS except StoragePluginException: # Unable to run one of the LVM commands # The error is reported by the corresponding function # # Abort pass except Exception as unhandled_exc: logging.error("LvmThinLv: Block device creation failed, " "unhandled exception: %s" % (str(unhandled_exc))) return fn_rc