Mini Shell
import argparse
import sys
from os import devnull, cpu_count
import logging
import rads
from rads.color import red, green, magenta, yellow, blue
from guds_modules.base import ModuleBase
DELETE = f"""{green('disk_cleanup.py delete [options]:')}
Data is deleted and customer notices are sent depending on the chosen modules.
show all delete modules: {magenta('disk_cleanup.py delete -h')}
Examples:
run all delete modules and pipe to stdout: {magenta('disk_cleanup.py -v delete -a')}
run updraft/core delete modules: {magenta('disk_cleanup.py delete --updraft --core')}
"""
NOTE = f"""{yellow('disk_cleanup.py note [options]:')}
Nothing is deleted and customer notices are sent regarding storage of data.
show all note modules: {magenta('disk_cleanup.py note -h')}
Examples:
run all note modules and pipe to stdout: {magenta('disk_cleanup.py -v note -a')}
"""
REPORT = f"""{blue('disk_cleanup.py aux and disk_cleanup.py change [options]:')}
These options do not require an argument list.
Just run the command and use info as needed.
Examples:
show aux info: {magenta('disk_cleanup.py aux')}
show change info: {magenta('disk_cleanup.py change')}
show change info compared against 2 days ago: {magenta('disk_cleanup.py change -d 2')}
"""
MAIN = f"""{red('Disk Cleaner v1.0')}
disk_cleanup.py with --help will display this message and exit.
Program actions are logged to /var/log/diskcleaner.log, but using `-v` as the
first disk_cleanup.py argument forces logging to stdout.
Usage of a screen is recommended with delete and note, but not required.
{DELETE}
{NOTE}
{REPORT}
"""
def get_args(
deleter_mods: dict[str, type[ModuleBase]],
notifier_mods: dict[str, type[ModuleBase]],
) -> tuple[dict, list[str]]:
"""Parse arguments"""
parser = argparse.ArgumentParser(description=__doc__, usage=MAIN)
argument = parser.add_argument
argument(
'-l',
'--loglevel',
dest='loglevel',
default='info',
type=str,
choices=['critical', 'error', 'warning', 'info', 'debug'],
help='level of verbosity in logging',
)
argument(
'-o',
'--output',
dest='log_file',
default="/var/log/diskcleaner.log",
type=str,
help='file to send logs to',
)
argument(
'-v',
'--verbose',
dest='verbose',
default=False,
action='store_true',
help='output logs to command line',
)
argument(
'-n',
'--dry-run',
default=False,
action='store_true',
help='only display actions; do not delete or notify',
)
subparser = parser.add_subparsers(help='Subcommands', dest="command")
# Make sub scripts: deleter and notifier
deleter_group = subparser.add_parser(
'delete',
usage=DELETE,
description='GRUDS Deleter Modules',
help='Options in this group delete, notifying as needed',
)
notifier_group = subparser.add_parser(
'note',
usage=NOTE,
description='GRUDS Notifier Modules',
help='Options in this group require user notification',
)
subparser.add_parser(
'aux',
usage=REPORT,
description='GRUDS AUX Info',
help='Auxiliary, list large dirs such as mlocate size',
)
disk_change = subparser.add_parser(
'change',
usage=REPORT,
description='GRUDS Change Info',
help='Shows change in disk usage on per-user basis',
)
# Deleter Group Arguments
for mod in deleter_mods:
long_option = "--%s" % mod
help_text = deleter_mods[mod].__doc__
deleter_group.add_argument(
long_option, action='store_true', help=help_text
)
# Notifier Group Arguments
for mod in notifier_mods:
short_option = f'-{mod[0]}'
long_option = f"--{mod}"
help_text = notifier_mods[mod].__doc__
notifier_group.add_argument(
short_option, long_option, action='store_true', help=help_text
)
cores = cpu_count()
assert isinstance(cores, int)
default_threads = min(max(int(cores / 4), 4), 12)
for grp in (deleter_group, notifier_group):
grp.add_argument(
'-a', '--all', action='store_true', help="Do all of the above"
)
grp.add_argument(
'--threads',
type=int,
default=default_threads,
help=f'parallel tasks (default: {default_threads})',
)
disk_change.add_argument(
'-d',
'--days',
help="days back to compare data against (default=1)",
default=1,
)
args = parser.parse_args() # Parse arguments
if args.verbose: # Set CLI output to std if verbose
args.output = sys.stderr
else: # Set CLI output to devnull if not verbose
# pylint: disable=consider-using-with
args.output = open(devnull, 'w', encoding='utf-8')
# Set logging value from optional argment
if args.loglevel == 'critical':
args.loglevel = logging.CRITICAL
elif args.loglevel == 'error':
args.loglevel = logging.ERROR
elif args.loglevel == 'warning':
args.loglevel = logging.WARNING
elif args.loglevel == 'info':
args.loglevel = logging.INFO
elif args.loglevel == 'debug':
args.loglevel = logging.DEBUG
else: # Logging set to INFO by default.
args.loglevel = logging.INFO
args = vars(args)
# Enumerate user-selected cleaner modules
modules = [
arg
for arg, value in args.items()
if arg != 'verbose' and arg != 'dry_run' and value is True
]
if rads.IMH_CLASS == 'reseller':
modules = override_selected_modules(modules)
# Sanity check on argument input
if len(modules) > 1 and "all" in modules:
print(red("--all is not compatible with selected options"))
sys.exit(1)
return args, modules
def override_selected_modules(modules: list[str]) -> list[str]:
"""If this is a reseller, or nginx server, then do not run updraft, or
backup cleaner modules
:param modules: the selected cleaner, or note modules
:return: modules"""
if 'all' in modules:
print(
'Only core, zip, and temp modules should run on Reseller servers;',
'Removing updraft and backup.',
)
return ['core', 'zip', 'temp']
if 'updraft' in modules:
print(
'Only core, zip, and temp modules should run on Reseller servers;',
'Removing updraft.',
)
modules.remove('updraft')
if 'backup' in modules:
print(
'Only core, zip, and temp modules should run on Reseller servers;',
'Removing backup.',
)
modules.remove('backup')
if 'boldgrid' in modules:
print(
'Only core, zip, and temp modules should run on Reseller servers;',
'Removing boldgrid.',
)
modules.remove('boldgrid')
return modules
Zerion Mini Shell 1.0