#!/usr/bin/env python3

import sys
sys.dont_write_bytecode = True
sys.path.append('/usr/lib/dcpython')

import argparse

"""
database - Perform actions on Oracle databases
Copyright (c) 2023 - Bart Sjerps <bart@dirty-cache.com>
License: GPLv3+
"""

try:
    from switchuser import switchuser
    from instance import oratab, Instance
except ImportError as e:
    print("Import failed:", e)
    sys.exit(20)

def dblist(args):
    for sid in oratab.sids:
        print(sid)

def status(args):
    instance = Instance(args.sid)
    status = instance.status()
    print(status)

def stop(args):
    instance = Instance(args.sid)
    instance.sqlplus('shutdown immediate')

def start(args):
    instance = Instance(args.sid)
    instance.sqlplus('startup')

def abort(args):
    instance = Instance(args.sid)
    instance.sqlplus('shutdown abort')

def dbclose(args):
    instance = Instance(args.sid)
    instance.sqlplus('alter database close;')

def dbopen(args):
    instance = Instance(args.sid)
    instance.sqlplus('alter database open read write;')

def dbmount(args):
    instance = Instance(args.sid)
    instance.sqlplus('alter database mount;')

def pfile(args):
    instance = Instance(args.sid)
    rc, out = instance.sqlplus("select value from v$parameter where name = 'spfile';")
    spfile = out.strip()
    instance.sqlplus(f"create pfile='/tmp/init{instance.sid}.ora' from SPFILE='{spfile}';")

def spfile(args):
    instance = Instance(args.sid)
    instance.sqlplus(f"create spfile='+TEMP/{instance.sid}/spfile{instance.sid}.ora' from pfile='/tmp/init{instance.sid}.ora';")

def trcfile(args):
    instance = Instance(args.sid)
    instance.sqlplus(f"alter database backup controlfile to trace as '/tmp/trace{instance.sid}.sql' reuse;")

if __name__ == '__main__':
    parser = argparse.ArgumentParser(description="Manage Oracle Databases (single instance)")

    parent = argparse.ArgumentParser(add_help=False)
    parent.add_argument("-a", "--all", help="all instances", action='store_true')
    parent.add_argument("sid", metavar="SID", default=oratab.sids[0], nargs='?')

    subparsers = parser.add_subparsers(title='commands')
    parser_list    = subparsers.add_parser('list',       help='List databases')
    parser_status  = subparsers.add_parser('status',     parents=[parent], help='Show database status')
    parser_stop    = subparsers.add_parser('stop',       parents=[parent], help='Stop database')
    parser_start   = subparsers.add_parser('start',      parents=[parent], help='Start database')
    parser_abort   = subparsers.add_parser('abort',      parents=[parent], help='Stop database (abort)')
    parser_mount   = subparsers.add_parser('mount',      parents=[parent], help='Mount database')
    parser_open    = subparsers.add_parser('open',       parents=[parent], help='Open database read/write')
    parser_close   = subparsers.add_parser('close',      parents=[parent], help='Close database')
    parser_pfile   = subparsers.add_parser('pfile',      parents=[parent], help='Make pfile (/tmp/init<sid>.ora)')
    parser_spfile  = subparsers.add_parser('spfile',     parents=[parent], help='Make spfile (+DATA/<sid>/spfile<sid>.ora)')
    parser_trcfile = subparsers.add_parser('trcfile',    parents=[parent], help='Make tracefile (/tmp/trace<sid>.sql)')

    parser_list.   set_defaults(func=dblist)
    parser_stop.   set_defaults(func=stop)
    parser_start.  set_defaults(func=start)
    parser_abort.  set_defaults(func=abort)
    parser_mount.  set_defaults(func=dbmount)
    parser_open.   set_defaults(func=dbopen)
    parser_close.  set_defaults(func=dbclose)
    parser_status. set_defaults(func=status)
    parser_pfile.  set_defaults(func=pfile)
    parser_spfile. set_defaults(func=spfile)
    parser_trcfile.set_defaults(func=trcfile)

    args = parser.parse_args()

    try:
        if not hasattr(args, 'func'):
            raise ValueError('Bad command')
        switchuser('oracle')
        if getattr(args, 'all', None):
            for sid in listsids():
                args.sid = sid
                args.func(args)
        else:
            args.func(args)
    except ValueError as e:
        print(e)
        sys.exit(10)
