Source code for flexget.plugins.operate.free_space

import shutil
from pathlib import Path

from loguru import logger

from flexget import plugin
from flexget.config_schema import parse_size
from flexget.event import event

logger = logger.bind(name='free_space')

ABORT_BELOW = 'below'
ABORT_ABOVE = 'above'


[docs] def get_free_space(config, task): """Return folder/drive free space (in megabytes).""" if 'host' in config: import paramiko ssh = paramiko.SSHClient() ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) try: ssh.connect( config.get('host'), config.get('port', 22), config.get('user'), config.get('password', None), config.get('pkey', None), config.get('ssh_key_filepath'), timeout=5000, ) except Exception as e: logger.error('Issue connecting to remote host. {}', e) task.abort('Error with remote host.') if config['allotment'] != -1: _stdin, stdout, _stderr = ssh.exec_command(f'du -s {config["path"]} | cut -f 1') else: _stdin, stdout, _stderr = ssh.exec_command( f"df -k {config['path']} | tail -1 | tr -s ' ' | cut -d' ' -f4" ) outlines = stdout.readlines() resp = ''.join(outlines) ssh.close() try: if config['allotment'] != -1: free = int(config['allotment']) - ((int(resp.strip()) * 1024) / 1000000) else: free = int(resp.strip()) / 1000 except ValueError: logger.error('Non-integer was returned when calculating disk usage.') task.abort('Error with remote host.') return free path = Path(config['path']).expanduser().absolute() usage = shutil.disk_usage(path) return usage.free / 1024 / 1024
[docs] class PluginFreeSpace: """Aborts a task if an entry is accepted and there is less than a certain amount of space free on a drive.""" schema = { 'oneOf': [ {'type': 'number'}, { 'type': 'object', 'properties': { 'space': {'oneOf': [{'type': 'number'}, {'type': 'string', 'format': 'size'}]}, 'abort_if': { 'type': 'string', 'enum': [ABORT_BELOW, ABORT_ABOVE], 'default': ABORT_BELOW, }, 'path': {'type': 'string'}, 'port': {'type': 'integer', 'default': 22}, 'host': {'type': 'string'}, 'user': {'type': 'string'}, 'ssh_key_filepath': {'type': 'string'}, 'allotment': {'type': 'number', 'default': -1}, }, 'required': ['space'], 'dependentRequired': {'host': ['user', 'ssh_key_filepath', 'path']}, 'additionalProperties': False, }, ] }
[docs] @staticmethod def prepare_config(config, task): if isinstance(config, (float, int)): config = {'space': config} if isinstance(config['space'], str): config['space'] = parse_size(config['space']) / 1024 / 1024 # Use config path if none is specified if not config.get('path'): config['path'] = task.manager.config_base return config
[docs] @plugin.priority(plugin.PRIORITY_FIRST) def on_task_download(self, task, config): config = self.prepare_config(config, task) free_space = get_free_space(config, task) space = config['space'] path = config['path'] abort_if = config['abort_if'] if free_space < space and abort_if == ABORT_BELOW: logger.error('Less than {} MB of free space in {} aborting task.', space, path) # backlog plugin will save and restore the task content, if available task.abort(f'Less than {space} MB of free space in {path}') elif free_space > space and abort_if == ABORT_ABOVE: logger.error('Over than {} MB of free space in {} aborting task.', space, path) # backlog plugin will save and restore the task content, if available task.abort(f'Over than {space} MB of free space in {path}')
[docs] @event('plugin.register') def register_plugin(): plugin.register(PluginFreeSpace, 'free_space', api_ver=2)