Skip to content
Snippets Groups Projects
Commit d46a90f35a22 authored by jfp's avatar jfp
Browse files

Add optional password for supervisorctl, return a reply for each command

parent 8fe8267c9b59
Branches
No related tags found
No related merge requests found
import argparse
import cmd import cmd
import json import json
...@@ -1,7 +2,6 @@ ...@@ -1,7 +2,6 @@
import cmd import cmd
import json import json
import sys from typing import Tuple, Any
from typing import Tuple
from ovms import cmbdef, iodef, mbxqio, psldef, starlet from ovms import cmbdef, iodef, mbxqio, psldef, starlet
...@@ -5,6 +5,8 @@ ...@@ -5,6 +5,8 @@
from ovms import cmbdef, iodef, mbxqio, psldef, starlet from ovms import cmbdef, iodef, mbxqio, psldef, starlet
supervisorctl_pwd = ''
def pstat2str(s: int) -> str: def pstat2str(s: int) -> str:
dstate = { dstate = {
...@@ -36,6 +38,15 @@ ...@@ -36,6 +38,15 @@
self.mcmd_r = mcmd_r self.mcmd_r = mcmd_r
cmd.Cmd.__init__(self, completekey, stdin, stdout) cmd.Cmd.__init__(self, completekey, stdin, stdout)
def write_cmd(self, cmd: dict) -> Any:
global supervisorctl_pwd
cmd['pwd'] = supervisorctl_pwd
jscmd = json.dumps(cmd)
self.mcmd.write(jscmd.encode('ascii'), iodef.IO_M_READERCHECK)
return json.loads(
self.mcmd_r.read(4096, iodef.IO_M_WRITERCHECK) # type: ignore
)
def do_EOF(self, line): def do_EOF(self, line):
"""To quit, type ^D or use the quit command""" """To quit, type ^D or use the quit command"""
return True return True
...@@ -50,9 +61,9 @@ ...@@ -50,9 +61,9 @@
if len(lst) != 0: if len(lst) != 0:
print('*** invalid number of arguments') print('*** invalid number of arguments')
return return
jscmd = json.dumps({'cmd': 'shutdown'}) res = self.write_cmd({'cmd': 'shutdown'})
self.mcmd.write(jscmd.encode('ascii'), iodef.IO_M_READERCHECK) print(res)
def do_status(self, arg): def do_status(self, arg):
"""Display status of programs""" """Display status of programs"""
lst = arg.split() lst = arg.split()
...@@ -55,13 +66,12 @@ ...@@ -55,13 +66,12 @@
def do_status(self, arg): def do_status(self, arg):
"""Display status of programs""" """Display status of programs"""
lst = arg.split() lst = arg.split()
jscmd = json.dumps({'cmd': 'status', 'programs': lst}) jscmd = self.write_cmd({'cmd': 'status', 'programs': lst})
self.mcmd.write(jscmd.encode('ascii'), iodef.IO_M_READERCHECK) if 'error' in jscmd:
res: bytes print(jscmd['error'])
res = self.mcmd_r.read(4096, iodef.IO_M_WRITERCHECK) # type: ignore return
jscmd = json.loads(res) for pinfo in jscmd['result']:
for pinfo in jscmd['reply']:
pinfo[3] = pstat2str(pinfo[3]) pinfo[3] = pstat2str(pinfo[3])
print(pinfo) print(pinfo)
...@@ -65,6 +75,22 @@ ...@@ -65,6 +75,22 @@
pinfo[3] = pstat2str(pinfo[3]) pinfo[3] = pstat2str(pinfo[3])
print(pinfo) print(pinfo)
def do_start(self, arg):
lst = arg.split()
if len(lst) < 1:
print('*** invalid number of arguments')
return
res = self.write_cmd({'cmd': 'start', 'programs': lst})
print(res)
def do_stop(self, arg):
lst = arg.split()
if len(lst) < 1:
print('*** invalid number of arguments')
return
res = self.write_cmd({'cmd': 'stop', 'programs': lst})
print(res)
def help_status(self): def help_status(self):
print('status <name>\t\tGet status for a single process') print('status <name>\t\tGet status for a single process')
print('status <gname>:*\tGet status for all ' 'processes in a group') print('status <gname>:*\tGet status for all ' 'processes in a group')
...@@ -73,17 +99,9 @@ ...@@ -73,17 +99,9 @@
) )
print('status\t\t\tGet all process status info') print('status\t\t\tGet all process status info')
def do_start(self, arg):
lst = arg.split()
if len(lst) < 1:
print('*** invalid number of arguments')
return
jscmd = json.dumps({'cmd': 'start', 'programs': lst})
self.mcmd.write(jscmd.encode('ascii'), iodef.IO_M_READERCHECK)
def help_start(self): def help_start(self):
print('start <name>\t\tStart a process') print('start <name>\t\tStart a process')
print('start <gname>:*\t\tStart all processes in a group') print('start <gname>:*\t\tStart all processes in a group')
print('start <name> <name>\tStart multiple processes or groups') print('start <name> <name>\tStart multiple processes or groups')
print('start all\t\tStart all processes') print('start all\t\tStart all processes')
...@@ -84,17 +102,9 @@ ...@@ -84,17 +102,9 @@
def help_start(self): def help_start(self):
print('start <name>\t\tStart a process') print('start <name>\t\tStart a process')
print('start <gname>:*\t\tStart all processes in a group') print('start <gname>:*\t\tStart all processes in a group')
print('start <name> <name>\tStart multiple processes or groups') print('start <name> <name>\tStart multiple processes or groups')
print('start all\t\tStart all processes') print('start all\t\tStart all processes')
def do_stop(self, arg):
lst = arg.split()
if len(lst) < 1:
print('*** invalid number of arguments')
return
jscmd = json.dumps({'cmd': 'stop', 'programs': lst})
self.mcmd.write(jscmd.encode('ascii'), iodef.IO_M_READERCHECK)
def help_stop(self): def help_stop(self):
print('stop <name>\t\tStop a process') print('stop <name>\t\tStop a process')
print('stop <gname>:*\t\tStop all processes in a group') print('stop <gname>:*\t\tStop all processes in a group')
...@@ -126,9 +136,23 @@ ...@@ -126,9 +136,23 @@
def main(): def main():
global supervisorctl_pwd
parser = argparse.ArgumentParser(description='supervisorctl')
parser.add_argument(
'-p',
'--password',
required=False,
# type=str,
default='',
help='password for supervisord',
)
# args = parser.parse_args()
# print('-->', args)
args, unknownargs = parser.parse_known_args()
supervisorctl_pwd = args.password
chan, chan_r = mbx_init() chan, chan_r = mbx_init()
with ( with (
mbxqio.MBXQIO(channel=chan) as mcmd, mbxqio.MBXQIO(channel=chan) as mcmd,
mbxqio.MBXQIO(channel=chan_r) as mcmd_r, mbxqio.MBXQIO(channel=chan_r) as mcmd_r,
): ):
c = Controller(mcmd, mcmd_r) c = Controller(mcmd, mcmd_r)
...@@ -129,11 +153,11 @@ ...@@ -129,11 +153,11 @@
chan, chan_r = mbx_init() chan, chan_r = mbx_init()
with ( with (
mbxqio.MBXQIO(channel=chan) as mcmd, mbxqio.MBXQIO(channel=chan) as mcmd,
mbxqio.MBXQIO(channel=chan_r) as mcmd_r, mbxqio.MBXQIO(channel=chan_r) as mcmd_r,
): ):
c = Controller(mcmd, mcmd_r) c = Controller(mcmd, mcmd_r)
if len(sys.argv) > 1: if len(unknownargs) > 0:
c.onecmd(' '.join(sys.argv[1:])) c.onecmd(' '.join(unknownargs))
else: else:
c.cmdloop() c.cmdloop()
......
[openvms]
password=xxxxxx
[program:firstpgm] [program:firstpgm]
command=dev:[dir]PGM1.COM command=dev:[dir]PGM1.COM
process_name=PGM1D process_name=PGM1D
......
# #
# Required privileges: SYSNAM, PRMMBX, IMPERSONATE, WORLD # Required privileges: SYSNAM, PRMMBX, IMPERSONATE, WORLD
# #
import argparse
import configparser import configparser
import ctypes import ctypes
import datetime import datetime
...@@ -38,6 +39,7 @@ ...@@ -38,6 +39,7 @@
current_tick: int = 0 current_tick: int = 0
timer_queue: queue.PriorityQueue['PrioritizedItem'] = queue.PriorityQueue() timer_queue: queue.PriorityQueue['PrioritizedItem'] = queue.PriorityQueue()
supervisorctl_pwd = ''
class TimerItemType(IntEnum): class TimerItemType(IntEnum):
UNDEF = 0 UNDEF = 0
...@@ -420,4 +422,14 @@ ...@@ -420,4 +422,14 @@
return astctxt return astctxt
def send_cmd_reply(fcmd_r: mbxqio.MBXQIO, cmdreply: dict):
jscmd = json.dumps(cmdreply)
try:
fcmd_r.write(
jscmd.encode('ascii'),
iodef.IO_M_READERCHECK | iodef.IO_M_NOW,
)
except OSError:
pass
def dispatch_cmd(res: bytes, fcmd_r: mbxqio.MBXQIO): def dispatch_cmd(res: bytes, fcmd_r: mbxqio.MBXQIO):
...@@ -423,2 +435,3 @@ ...@@ -423,2 +435,3 @@
def dispatch_cmd(res: bytes, fcmd_r: mbxqio.MBXQIO): def dispatch_cmd(res: bytes, fcmd_r: mbxqio.MBXQIO):
global supervisorctl_pwd
jscmd = json.loads(res) jscmd = json.loads(res)
...@@ -424,4 +437,10 @@ ...@@ -424,4 +437,10 @@
jscmd = json.loads(res) jscmd = json.loads(res)
logging.info(f'Receive cmd: {jscmd}') pwd = jscmd['pwd']
jscmd['pwd'] = '*****'
if pwd != supervisorctl_pwd:
logging.info('Invalid password')
send_cmd_reply(fcmd_r, {'error': 'Invalid password'})
return
match jscmd['cmd'].lower(): match jscmd['cmd'].lower():
case 'shutdown': case 'shutdown':
...@@ -426,5 +445,6 @@ ...@@ -426,5 +445,6 @@
match jscmd['cmd'].lower(): match jscmd['cmd'].lower():
case 'shutdown': case 'shutdown':
send_cmd_reply(fcmd_r, {'result': None})
exit(1) exit(1)
case 'start': case 'start':
pgmnames = set([name.upper() for name in jscmd['programs']]) pgmnames = set([name.upper() for name in jscmd['programs']])
...@@ -441,6 +461,7 @@ ...@@ -441,6 +461,7 @@
pgm.process.state = ProcessStates.STOPPED pgm.process.state = ProcessStates.STOPPED
pgm.remain_startretries = pgm.startretries + 1 pgm.remain_startretries = pgm.startretries + 1
pgm.create_process(False) pgm.create_process(False)
send_cmd_reply(fcmd_r, {'result': None})
case 'stop': case 'stop':
pgmnames = set([name.upper() for name in jscmd['programs']]) pgmnames = set([name.upper() for name in jscmd['programs']])
if 'ALL' in pgmnames: if 'ALL' in pgmnames:
...@@ -450,6 +471,7 @@ ...@@ -450,6 +471,7 @@
for pgm in Program.programs.values(): for pgm in Program.programs.values():
if pgm.name in pgmnames: if pgm.name in pgmnames:
pgm.kill() pgm.kill()
send_cmd_reply(fcmd_r, {'result': None})
case 'status': case 'status':
pgmnames = set([name.upper() for name in jscmd['programs']]) pgmnames = set([name.upper() for name in jscmd['programs']])
lst = [] lst = []
...@@ -473,14 +495,7 @@ ...@@ -473,14 +495,7 @@
lst[-1].append(str(pgm.process.end_time)[:19]) lst[-1].append(str(pgm.process.end_time)[:19])
lst[-1].append(pgm.process.finalsts) lst[-1].append(pgm.process.finalsts)
jscmd = json.dumps({'reply': lst}) send_cmd_reply(fcmd_r, {'result': lst})
try:
fcmd_r.write(
jscmd.encode('ascii'),
iodef.IO_M_READERCHECK | iodef.IO_M_NOW,
)
except OSError:
pass
def dispatch_ast(astparam: AstParam, fcmd_r: mbxqio.MBXQIO): def dispatch_ast(astparam: AstParam, fcmd_r: mbxqio.MBXQIO):
...@@ -579,7 +594,7 @@ ...@@ -579,7 +594,7 @@
def main(): def main():
global logger global logger, supervisorctl_pwd
logging_format = '%(asctime)s - %(name)s - %(levelname)s - %(message)s' logging_format = '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
logging.basicConfig( logging.basicConfig(
...@@ -603,4 +618,14 @@ ...@@ -603,4 +618,14 @@
| prvdef.PRV_M_WORLD, | prvdef.PRV_M_WORLD,
) )
parser = argparse.ArgumentParser(description='supervisord')
parser.add_argument(
'-c',
'--configuration',
type=argparse.FileType('r', encoding='latin1'),
default='./supervisord.conf',
help='Configuration file path (default ./supervisord.conf)',
)
args = parser.parse_args()
config = configparser.ConfigParser() config = configparser.ConfigParser()
...@@ -606,5 +631,9 @@ ...@@ -606,5 +631,9 @@
config = configparser.ConfigParser() config = configparser.ConfigParser()
config.read('supervisord.conf') config.read_file(args.configuration)
args.configuration.close()
supervisorctl_pwd = config['openvms'].get('password', '')
for sn in config.sections(): for sn in config.sections():
if sn.startswith('program:'): if sn.startswith('program:'):
name = sn.split(':')[-1].upper() name = sn.split(':')[-1].upper()
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment