Mini Shell
Direktori : /opt/sharedrads/ |
|
Current File : //opt/sharedrads/packandgo |
#!/opt/imh-python/bin/python3
"""Pack and Go"""
from os import cpu_count
import random
import string
from pathlib import Path
from cproc import Proc
import subprocess
import sys
import argparse
import arrow
import platform
import rads
MAX_GB = 20
def parse_args() -> str:
"""Get the one argument, the user"""
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('user', help='Username')
args = parser.parse_args()
if rads.is_cpuser(args.user):
return args.user
sys.exit('ERROR: Not a user.')
def check_size(username: str) -> None:
"""If over 20GB, not packaging. They will need to use FTP.
Gets user disk usage using the quotactl syscall"""
quotactl = rads.QuotaCtl()
try:
size_bytes = quotactl.getquota(username)
except rads.QuotasDisabled:
sys.exit("Filesystem quotas are disabled; Try /scripts/fixquotas")
except Exception as exc:
sys.exit(f"{type(exc).__name__}: {exc}")
if size_bytes < 2**30: # < 1 GiB
print(f"{username}'s size: {round(size_bytes / 2**20, 2)} MiB")
else:
print(f"{username}'s size: {round(size_bytes / 2**30, 2)} GiB")
if size_bytes > MAX_GB * 2**30:
sys.exit(f"Over {MAX_GB}GiB - user will need to collect data via FTP")
def pack_it_up(username: str) -> Path:
"""cpuwatched pkgacct"""
cmd = ['/usr/local/cpanel/scripts/pkgacct', username]
print(f"Packing up {username}. This may take a while...")
try:
ret = Proc.run(
cmd,
lim=cpu_count(),
stdout=Proc.PIPE,
stderr=Proc.STDOUT,
encoding='utf-8',
check=True,
)
except Proc.CalledProcessError as exc:
if exc.returncode < 0:
sys.exit(
'Failed to create package - pkgacct process was killed '
f'(signal {-exc.returncode})'
)
sys.exit(f'{exc.stdout}\n\nFailed to create package')
path = None
for line in ret.stdout.splitlines():
line: str
if 'pkgacctfile is:' in line:
path = Path(line.split(' ')[-1].strip('\n'))
if path is None:
sys.exit(
f"{ret.stdout}\n\nFailed to create package - "
'pkgacct returned a successful exit code, but it did not '
'print the expected output, "pkgacctfile is: <path>"'
)
if not path.is_file():
sys.exit(f"Backup file not found at: {path}")
return path
def file_precheck(username: str) -> None:
"""Checks if backup already exists"""
path = Path(f'/home/cpmove-{username}.tar.gz')
if path.exists():
sys.exit(
f"ERROR: {path} already exists. Please remove for fresh backup"
)
def sec_dir() -> Path:
if rads.SECURE_USER is None:
sys.exit("Could not identify secure user name.")
rand = ''.join(random.choices(string.ascii_letters + string.digits, k=48))
path = Path('/home', rads.SECURE_USER, 'public_html', rand)
path.mkdir(mode=0o755, parents=True, exist_ok=False)
return path
def move_it(pkgacct_file: Path, dest_dir: Path) -> Path:
"""Moves newly created backup to secure users dir"""
pkgacct_file.rename(dest_dir / pkgacct_file.name)
rcode = subprocess.call(
['/usr/bin/fixperms', rads.SECURE_USER],
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
)
if rcode:
print(f"Warning: fixperms exited {rcode}")
def send_recl_email(sec_dir_path: Path) -> None:
"""Sends e-mail to reclamations to delete in 3 days"""
time_now = arrow.now().shift(days=3)
recl_date = time_now.format('MM-DD-YYYY')
hostname = platform.node()
to_addy = "reclamations@imhadmin.net"
subject = f"{hostname} : Reclaim cpmove {recl_date}"
body = f"{hostname} : rm -rvf {sec_dir_path}"
if rads.send_email(to_addy, subject, body) is False:
print("Reclamation request for removal in 72 hours of backup, sent.")
else:
print("Sending of reclamation request failed. Please send manually.")
def main():
"""Main function to pack and go"""
user = parse_args()
file_precheck(user)
check_size(user)
sec_dir_path = sec_dir()
bak_homepath = pack_it_up(user)
move_it(bak_homepath, sec_dir_path)
print(
"Download Link:",
f"https://{rads.SECURE_FQDN}/{sec_dir_path.name}/{bak_homepath.name}",
)
send_recl_email(sec_dir_path)
if __name__ == '__main__':
main()
Zerion Mini Shell 1.0