#!/usr/bin/env python3

"""
swapsize - Increases swapspace based on memory size
Copyright (c) 2023 - Bart Sjerps <bart@dirty-cache.com>
License: GPLv3+
"""

"""
Note:

Swapspace must be on <root vg>/swap
Minimal swapspace:
RAM <= 1GB  : Swap 1GB
RAM <= 2GB  : Swap 4GB
RAM >= 4GB  : Swap = RAM
RAM >= 16GB : Swap = 16GB
"""

import sys, re, subprocess, argparse

def getmeminfo():
    memtotal, swaptotal = None, None
    with open('/proc/meminfo') as f:
        data = f.read()
        r = re.search(r'^SwapTotal\:\s+(\d+)\s+.*\s', data, re.M)
        if r:
            swaptotal = int(r.group(1))/1024
        r = re.search(r'^MemTotal\:\s+(\d+)\s+.*\s', data, re.M)
        if r:
            memtotal = int(r.group(1))/1024 + 400
        return memtotal, swaptotal

def run(c, **kwargs):
    r = subprocess.run(c.split(), check=True, **kwargs)
    return r

def resize():
    memtotal, swaptotal = getmeminfo()
    mem_mb = round(memtotal)
    swap_mb = round(swaptotal)
    if memtotal >= 16384:
        minswap = 16384
    elif memtotal >= 4096:
        minswap = round(memtotal)
    else:
        minswap = 4096
    print(f'Memsize:\t{mem_mb}\nSwapsize:\t{swap_mb}\nMinswap:\t{minswap}\n')

    with open('/proc/swaps') as f:
        data = f.read()
        r = re.search(r'(/dev/\S+)', data) #, re.M)
        if not r:
            devname = None
        devname = r.group(1)
        r = run(f'lsblk -nponame {devname}', stdout=subprocess.PIPE)
        dev = r.stdout.decode().strip()

    if minswap > swap_mb:
        print("Increasing swapsize")
        try:
            run(f'lvdisplay {dev}', stdout=subprocess.PIPE)
        except subprocess.CalledProcessError:
            sys.exit(10)
        try:
            run('swapoff -a')
            run(f'lvresize -L {minswap+4} {dev}')
            run(f'mkswap -f {dev}')
        except subprocess.CalledProcessError:
            sys.exit(10)
        finally:
            run('swapon -a')

if __name__ == '__main__':
    parser = argparse.ArgumentParser(epilog=__doc__, formatter_class=argparse.RawTextHelpFormatter)
    args = parser.parse_args()
    resize()
