mirror of
https://gitlab.isc.org/isc-projects/kea
synced 2025-10-23 14:56:19 +00:00
1. Add unittests and help information for cmdctl and bindctl.
2. Add login idle timeout for cmdctl, default idle time is 1200 seconds. 3. Refactor some code for cmdctl. git-svn-id: svn://bind10.isc.org/svn/bind10/trunk@961 e5f2f494-b856-4b98-b285-d166d9295462
This commit is contained in:
@@ -61,47 +61,52 @@ class BindCmdInterpreter(Cmd):
|
||||
self.modules = OrderedDict()
|
||||
self.add_module_info(ModuleInfo("help", desc = "Get help for bindctl"))
|
||||
self.server_port = server_port
|
||||
self.connect_to_cmd_ctrld()
|
||||
self._connect_to_cmd_ctrld()
|
||||
self.session_id = self._get_session_id()
|
||||
|
||||
def connect_to_cmd_ctrld(self):
|
||||
def _connect_to_cmd_ctrld(self):
|
||||
'''Connect to cmdctl in SSL context. '''
|
||||
try:
|
||||
self.conn = http.client.HTTPSConnection(self.server_port, cert_file='bindctl.pem')
|
||||
except Exception as e:
|
||||
print(e)
|
||||
print("can't connect to %s, please make sure cmd-ctrld is running" % self.server_port)
|
||||
print(e, "can't connect to %s, please make sure cmd-ctrld is running" %
|
||||
self.server_port)
|
||||
|
||||
def _get_session_id(self):
|
||||
'''Generate one session id for the connection. '''
|
||||
rand = os.urandom(16)
|
||||
now = time.time()
|
||||
ip = socket.gethostbyname(socket.gethostname())
|
||||
session_id = sha1(("%s%s%s" %(rand, now, ip)).encode())
|
||||
session_id = session_id.hexdigest()
|
||||
return session_id
|
||||
digest = session_id.hexdigest()
|
||||
return digest
|
||||
|
||||
def run(self):
|
||||
'''Parse commands inputted from user and send them to cmdctl. '''
|
||||
try:
|
||||
ret = self.login()
|
||||
if not ret:
|
||||
if not self.login_to_cmdctl():
|
||||
return False
|
||||
|
||||
# Get all module information from cmd-ctrld
|
||||
self.config_data = isc.config.UIModuleCCSession(self)
|
||||
self.update_commands()
|
||||
self._update_commands()
|
||||
self.cmdloop()
|
||||
except KeyboardInterrupt:
|
||||
return True
|
||||
|
||||
def login(self):
|
||||
def login_to_cmdctl(self):
|
||||
'''Login to cmdctl with the username and password inputted
|
||||
from user. After login sucessfully, the username and password
|
||||
will be saved in 'default_user.csv', when login next time,
|
||||
username and password saved in 'default_user.csv' will be used
|
||||
first.
|
||||
'''
|
||||
csvfile = None
|
||||
bsuccess = False
|
||||
try:
|
||||
csvfile = open('default_user.csv')
|
||||
users = csv.reader(csvfile)
|
||||
for row in users:
|
||||
if (len(row) < 2):
|
||||
continue
|
||||
|
||||
param = {'username': row[0], 'password' : row[1]}
|
||||
response = self.send_POST('/login', param)
|
||||
data = response.read().decode()
|
||||
@@ -120,10 +125,13 @@ class BindCmdInterpreter(Cmd):
|
||||
return True
|
||||
|
||||
count = 0
|
||||
csvfile = None
|
||||
print("[TEMP MESSAGE]: username :root password :bind10")
|
||||
while count < 3:
|
||||
while True:
|
||||
count = count + 1
|
||||
if count > 3:
|
||||
print("Too many authentication failures")
|
||||
return False
|
||||
|
||||
username = input("Username:")
|
||||
passwd = getpass.getpass()
|
||||
param = {'username': username, 'password' : passwd}
|
||||
@@ -135,26 +143,23 @@ class BindCmdInterpreter(Cmd):
|
||||
csvfile = open('default_user.csv', 'w')
|
||||
writer = csv.writer(csvfile)
|
||||
writer.writerow([username, passwd])
|
||||
bsuccess = True
|
||||
break
|
||||
csvfile.close()
|
||||
return True
|
||||
|
||||
if count == 3:
|
||||
print("Too many authentication failures")
|
||||
break
|
||||
|
||||
if csvfile:
|
||||
csvfile.close()
|
||||
return bsuccess
|
||||
|
||||
def update_commands(self):
|
||||
def _update_commands(self):
|
||||
'''Get all commands of modules. '''
|
||||
cmd_spec = self.send_GET('/command_spec')
|
||||
if (len(cmd_spec) == 0):
|
||||
print('can\'t get any command specification')
|
||||
if not cmd_spec:
|
||||
return
|
||||
|
||||
for module_name in cmd_spec.keys():
|
||||
if cmd_spec[module_name]:
|
||||
self.prepare_module_commands(module_name, cmd_spec[module_name])
|
||||
self._prepare_module_commands(module_name, cmd_spec[module_name])
|
||||
|
||||
def send_GET(self, url, body = None):
|
||||
'''Send GET request to cmdctl, session id is send with the name
|
||||
'cookie' in header.
|
||||
'''
|
||||
headers = {"cookie" : self.session_id}
|
||||
self.conn.request('GET', url, body, headers)
|
||||
res = self.conn.getresponse()
|
||||
@@ -162,11 +167,12 @@ class BindCmdInterpreter(Cmd):
|
||||
if reply_msg:
|
||||
return json.loads(reply_msg.decode())
|
||||
else:
|
||||
return None
|
||||
return {}
|
||||
|
||||
|
||||
def send_POST(self, url, post_param = None):
|
||||
'''
|
||||
'''Send GET request to cmdctl, session id is send with the name
|
||||
'cookie' in header.
|
||||
Format: /module_name/command_name
|
||||
parameters of command is encoded as a map
|
||||
'''
|
||||
@@ -183,13 +189,12 @@ class BindCmdInterpreter(Cmd):
|
||||
self.prompt = self.location + self.prompt_end
|
||||
return stop
|
||||
|
||||
def prepare_module_commands(self, module_name, module_commands):
|
||||
def _prepare_module_commands(self, module_name, module_commands):
|
||||
module = ModuleInfo(name = module_name,
|
||||
desc = "same here")
|
||||
for command in module_commands:
|
||||
cmd = CommandInfo(name = command["command_name"],
|
||||
desc = command["command_description"],
|
||||
need_inst_param = False)
|
||||
desc = command["command_description"])
|
||||
for arg in command["command_args"]:
|
||||
param = ParamInfo(name = arg["item_name"],
|
||||
type = arg["item_type"],
|
||||
@@ -200,7 +205,7 @@ class BindCmdInterpreter(Cmd):
|
||||
module.add_command(cmd)
|
||||
self.add_module_info(module)
|
||||
|
||||
def validate_cmd(self, cmd):
|
||||
def _validate_cmd(self, cmd):
|
||||
if not cmd.module in self.modules:
|
||||
raise CmdUnknownModuleSyntaxError(cmd.module)
|
||||
|
||||
@@ -225,7 +230,6 @@ class BindCmdInterpreter(Cmd):
|
||||
list(params.keys())[0])
|
||||
elif params:
|
||||
param_name = None
|
||||
index = 0
|
||||
param_count = len(params)
|
||||
for name in params:
|
||||
# either the name of the parameter must be known, or
|
||||
@@ -250,18 +254,17 @@ class BindCmdInterpreter(Cmd):
|
||||
raise CmdUnknownParamSyntaxError(cmd.module, cmd.command, cmd.params[name])
|
||||
else:
|
||||
# replace the numbered items by named items
|
||||
param_name = command_info.get_param_name_by_position(name+1, index, param_count)
|
||||
param_name = command_info.get_param_name_by_position(name+1, param_count)
|
||||
cmd.params[param_name] = cmd.params[name]
|
||||
del cmd.params[name]
|
||||
|
||||
elif not name in all_params:
|
||||
raise CmdUnknownParamSyntaxError(cmd.module, cmd.command, name)
|
||||
|
||||
param_nr = 0
|
||||
for name in manda_params:
|
||||
if not name in params and not param_nr in params:
|
||||
raise CmdMissParamSyntaxError(cmd.module, cmd.command, name)
|
||||
|
||||
param_nr += 1
|
||||
param_nr += 1
|
||||
|
||||
def _handle_cmd(self, cmd):
|
||||
@@ -385,7 +388,7 @@ class BindCmdInterpreter(Cmd):
|
||||
def _parse_cmd(self, line):
|
||||
try:
|
||||
cmd = BindCmdParse(line)
|
||||
self.validate_cmd(cmd)
|
||||
self._validate_cmd(cmd)
|
||||
self._handle_cmd(cmd)
|
||||
except BindCtlException as e:
|
||||
print("Error! ", e)
|
||||
@@ -497,5 +500,3 @@ class BindCmdInterpreter(Cmd):
|
||||
print("received reply:", data)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user