Commit 98a3c1b5 authored by JINMEI Tatuya's avatar JINMEI Tatuya
Browse files

[2447] improved exception message on sockcreator failure to help admin.

it now includes textual representation of errno, and, if it's EACCES
("permission denied") the messsage suggesting restarting as a super user.
parent 1b828baa
......@@ -16,6 +16,7 @@
import socket
import struct
import os
import errno
import copy
import subprocess
import copy
......@@ -36,16 +37,16 @@ class CreatorError(Exception):
passed to the __init__ function.
"""
def __init__(self, message, fatal, errno=None):
def __init__(self, message, fatal, error_num=None):
"""
Creates the exception. The message argument is the usual string.
The fatal one tells if the error is fatal (eg. the creator crashed)
and errno is the errno value returned from socket creator, if
and error_num is the errno value returned from socket creator, if
applicable.
"""
Exception.__init__(self, message)
self.fatal = fatal
self.errno = errno
self.errno = error_num
class Parser:
"""
......@@ -94,6 +95,13 @@ class Parser:
self.__socket = None
raise CreatorError(str(se), True)
def __addrport_str(self, address, port):
'''Convert a pair of IP address and port to common form for logging.'''
if address.family == socket.AF_INET:
return str(address) + ':' + str(port)
else:
return '[' + str(address) + ']:' + str(port)
def get_socket(self, address, port, socktype):
"""
Asks the socket creator process to create a socket. Pass an address
......@@ -136,9 +144,9 @@ class Parser:
elif answer == b'E':
# There was an error, read the error as well
error = self.__socket.recv(1)
errno = struct.unpack('i',
self.__read_all(len(struct.pack('i',
0))))
rcv_errno = struct.unpack('i',
self.__read_all(len(struct.pack('i',
0))))
if error == b'S':
cause = 'socket'
elif error == b'B':
......@@ -147,10 +155,22 @@ class Parser:
self.__socket = None
logger.fatal(BIND10_SOCKCREATOR_BAD_CAUSE, error)
raise CreatorError('Unknown error cause' + str(answer), True)
logger.error(BIND10_SOCKET_ERROR, cause, errno[0],
os.strerror(errno[0]))
raise CreatorError('Error creating socket on ' + cause, False,
errno[0])
logger.error(BIND10_SOCKET_ERROR, cause, rcv_errno[0],
os.strerror(rcv_errno[0]))
# Provide as detailed information as possible on the error,
# as error related to socket creation is a common operation
# trouble. In particular, we are intentionally very verbose
# if it fails due to "permission denied" so the administrator
# can easily identify what is wrong and how to fix it.
addrport = self.__addrport_str(address, port)
error_text = 'Error creating socket on ' + cause + \
' to be bound to ' + addrport + ': ' + \
os.strerror(rcv_errno[0])
if rcv_errno[0] == errno.EACCES:
error_text += ' - probably need to restart BIND 10 ' + \
'as a super user'
raise CreatorError(error_text, False, rcv_errno[0])
else:
self.__socket = None
logger.fatal(BIND10_SOCKCREATOR_BAD_RESPONSE, answer)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment