Newer
Older
import argparse
jfp
committed
import configparser
from ovms import (
cmbdef,
crtl,
dvidef,
iodef,
lnmdef,
mbxqio,
prvdef,
psldef,
starlet,
)
supervisorctl_pwd = ''
supervisorctl_mbxreply = ''
supervisord_table_name = b'SUPERVISORD_TABLE'
jfp
committed
programs_name: Set[str] = set()
def pstat2str(s: int) -> str:
dstate = {
0: 'STOPPED',
10: 'STARTING',
20: 'RUNNING',
30: 'BACKOFF',
40: 'STOPPING',
100: 'EXITED',
200: 'FATAL',
1000: 'UNKNOWN',
}
return dstate[s]
class Controller(cmd.Cmd):
mcmd: mbxqio.MBXQIO
mcmd_r: mbxqio.MBXQIO
def __init__(
self,
mcmd: mbxqio.MBXQIO,
mcmd_r: mbxqio.MBXQIO,
completekey='tab',
stdin=None,
stdout=None,
):
self.mcmd = mcmd
self.mcmd_r = mcmd_r
cmd.Cmd.__init__(self, completekey, stdin, stdout)
def write_cmd(self, cmd: dict) -> Any:
global supervisorctl_pwd, supervisorctl_mbxreply
cmd['pwd'] = supervisorctl_pwd
cmd['mbxreply'] = supervisorctl_mbxreply
jscmd = json.dumps(cmd)
try:
self.mcmd.write(jscmd.encode('ascii'), iodef.IO_M_READERCHECK)
except OSError as e:
crtl.vms_exit(e.errno)
return json.loads(
# self.mcmd_r.read(4096, iodef.IO_M_WRITERCHECK) # type: ignore
self.mcmd_r.read(4096) # type: ignore
def do_EOF(self, line):
"""To quit, type ^D or use the quit command"""
return True
def do_quit(self, line):
"""To quit, type ^D or use the quit command"""
return True
def do_shutdown(self, arg):
"""Shutdown supervisord, don't stop programs"""
lst = arg.split()
if len(lst) != 0:
print('*** invalid number of arguments')
return
res = self.write_cmd({'cmd': 'shutdown'})
print(res)
jfp
committed
# return True
jfp
committed
global programs_name
jfp
committed
for name in lst:
name = name.upper()
if name not in programs_name:
print(f'Invalid program name {name}')
return
jscmd = self.write_cmd({'cmd': 'status', 'programs': lst})
if 'error' in jscmd:
print(jscmd['error'])
return
for pinfo in jscmd['result']:
def do_start(self, arg):
jfp
committed
global programs_name
lst = arg.split()
if len(lst) < 1:
print('*** invalid number of arguments')
return
jfp
committed
lst = [name.upper() for name in lst]
jfp
committed
for name in lst:
if name not in programs_name:
print(f'Invalid program name {name}')
return
res = self.write_cmd({'cmd': 'start', 'programs': lst})
print(res)
def do_stop(self, arg):
jfp
committed
global programs_name
lst = arg.split()
if len(lst) < 1:
print('*** invalid number of arguments')
return
jfp
committed
lst = [name.upper() for name in lst]
jfp
committed
for name in lst:
if name not in programs_name:
print(f'Invalid program name {name}')
return
res = self.write_cmd({'cmd': 'stop', 'programs': lst})
print(res)
def help_status(self):
print('status <name>\t\tGet status for a single process')
print('status <gname>:*\tGet status for all ' 'processes in a group')
print(
'status <name> <name>\tGet status for multiple named ' 'processes'
)
print('status\t\t\tGet all process status info')
def help_start(self):
print('start <name>\t\tStart a process')
print('start <gname>:*\t\tStart all processes in a group')
print('start <name> <name>\tStart multiple processes or groups')
print('start all\t\tStart all processes')
def help_stop(self):
print('stop <name>\t\tStop a process')
print('stop <gname>:*\t\tStop all processes in a group')
print('stop <name> <name>\tStop multiple processes or groups')
print('stop all\t\tStop all processes')
def logicals_init():
global supervisord_table_name
starlet.crelnt(
attr=lnmdef.LNM_M_CREATE_IF,
promsk=0xE000,
tabnam=supervisord_table_name,
partab=b'LNM$SYSTEM_DIRECTORY',
acmode=psldef.PSL_C_SUPER,
)
lib.set_logical(
b'LNM$PERMANENT_MAILBOX',
supervisord_table_name,
b'LNM$PROCESS_DIRECTORY',
)
def mbx_init() -> Tuple[int, int, str]:
s, chancmd = starlet.crembx(
prmflg=1,
lognam='SUPERVISORD_CMD',
maxmsg=2048,
bufquo=8192,
promsk=0x0000FF00,
acmode=psldef.PSL_C_USER,
flags=cmbdef.CMB_M_WRITEONLY,
)
s, chancmd_r = starlet.crembx(
prmflg=0,
# lognam='SUPERVISORD_CMD_REPLY',
maxmsg=32 * 1024,
bufquo=64 * 1024,
promsk=0x0000FF00,
acmode=psldef.PSL_C_USER,
flags=cmbdef.CMB_M_READONLY,
)
mbxunit = lib.getdvi(dvidef.DVI__UNIT, chancmd_r)[1]
return chancmd, chancmd_r, f'MBA{mbxunit}:'
global supervisorctl_pwd, supervisorctl_mbxreply, programs_name
parser = argparse.ArgumentParser(description='supervisorctl')
parser.add_argument(
'-p',
'--password',
required=False,
jfp
committed
type=str,
default='',
help='password for supervisord',
)
jfp
committed
parser.add_argument(
'-c',
'--configuration',
type=argparse.FileType('r', encoding='latin1'),
default='./supervisord.conf',
help='Configuration file path (default ./supervisord.conf)',
)
args, unknownargs = parser.parse_known_args()
supervisorctl_pwd = args.password
jfp
committed
config = configparser.ConfigParser()
config.read_file(args.configuration)
args.configuration.close()
for sn in config.sections():
if sn.startswith('program:'):
name = sn.split(':')[-1].upper()
programs_name.add(name)
starlet.setprv(1, prvdef.PRV_M_PRMMBX | prvdef.PRV_M_SYSNAM)
chan, chan_r, supervisorctl_mbxreply = mbx_init()
with (
mbxqio.MBXQIO(channel=chan) as mcmd,
mbxqio.MBXQIO(channel=chan_r) as mcmd_r,
):
c = Controller(mcmd, mcmd_r)
if len(unknownargs) > 0:
c.onecmd(' '.join(unknownargs))