From mboxrd@z Thu Jan 1 00:00:00 1970 From: rmccabe@sourceware.org Date: 18 Oct 2006 21:59:48 -0000 Subject: [Cluster-devel] conga/luci/site/luci/Extensions LuciSyslog.py ... Message-ID: <20061018215948.28341.qmail@sourceware.org> List-Id: To: cluster-devel.redhat.com MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit CVSROOT: /cvs/cluster Module name: conga Changes by: rmccabe at sourceware.org 2006-10-18 21:59:47 Modified files: luci/site/luci/Extensions: LuciSyslog.py ricci_communicator.py Log message: improved error handling and debug logging Patches: http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/site/luci/Extensions/LuciSyslog.py.diff?cvsroot=cluster&r1=1.2&r2=1.3 http://sourceware.org/cgi-bin/cvsweb.cgi/conga/luci/site/luci/Extensions/ricci_communicator.py.diff?cvsroot=cluster&r1=1.9&r2=1.10 --- conga/luci/site/luci/Extensions/LuciSyslog.py 2006/10/16 04:59:52 1.2 +++ conga/luci/site/luci/Extensions/LuciSyslog.py 2006/10/18 21:59:47 1.3 @@ -12,34 +12,47 @@ """ class LuciSyslog: def __init__(self): + self.__init = 0 try: openlog('luci', LOG_DAEMON, LOG_PID | LOG_NDELAY) + self.__init = 1 except: raise LuciSyslogError, 'unable to setup syslog functionality.' def info(self, msg): + if not self.__init: + return try: syslog(LOG_INFO, msg) except: raise LuciSyslogError, 'syslog info call failed' def warn(self, msg): + if not self.__init: + return try: syslog(LOG_WARNING, msg) except: raise LuciSyslogError, 'syslog warn call failed' def private(self, msg): + if not self.__init: + return try: syslog(LOG_AUTH, msg) except: raise LuciSyslogError, 'syslog private call failed' def debug(self, msg): + if not self.__init: + return try: syslog(LOG_DEBUG, msg) except: raise LuciSyslogError, 'syslog debug calle failed' def close(self): - closelog() + try: + closelog() + except: + pass --- conga/luci/site/luci/Extensions/ricci_communicator.py 2006/10/16 07:39:27 1.9 +++ conga/luci/site/luci/Extensions/ricci_communicator.py 2006/10/18 21:59:47 1.10 @@ -1,17 +1,24 @@ - - from time import * from socket import * import xml import xml.dom from xml.dom import minidom - +from LuciSyslog import LuciSyslog from HelperFunctions import access_to_host_allowed CERTS_DIR_PATH = '/var/lib/luci/var/certs/' +try: + luci_log = LuciSyslog() +except: + pass + +class RicciError(Exception): + def __init__(self, e): + pass + class RicciCommunicator: def __init__(self, hostname, port=11111): self.__hostname = hostname @@ -21,13 +28,21 @@ self.__cert_file = CERTS_DIR_PATH + 'cacert.pem' # socket - sock = socket(AF_INET, SOCK_STREAM) - sock.settimeout(2.0) - sock.connect((self.__hostname, self.__port)) - self.ss = ssl(sock, self.__privkey_file, self.__cert_file) - sock.settimeout(600.0) # 10 minutes - # TODO: data transfer timeout should be much less, - # leave until all calls are async ricci calls + try: + sock = socket(AF_INET, SOCK_STREAM) + sock.settimeout(2.0) + sock.connect((self.__hostname, self.__port)) + except Exception, e: + raise RicciError, 'Error connecting to %s:%d: %s' \ + % (self.__hostname, self.__port, str(e)) + try: + self.ss = ssl(sock, self.__privkey_file, self.__cert_file) + # TODO: data transfer timeout should be much less, + # leave until all calls are async ricci calls + sock.settimeout(600.0) # 10 minutes + except Exception, e: + raise RicciError, 'Error setting up SSL for connection to %s: %s' \ + % (self.__hostname, str(e)) # receive ricci header hello = self.__receive() @@ -83,15 +98,22 @@ doc.appendChild(ricci) self.__send(doc) resp = self.__receive() - ret = resp.firstChild.getAttribute('success') - if ret != '0': - raise Exception(str(ret)) + + try: + ret = resp.firstChild.getAttribute('success') + if ret != '0': + raise Exception, 'Invalid response' + except: + errstr = 'Error authenticating to host %s: %s' \ + % (self.__hostname, str(ret)) + luci_log.debug(errstr) + raise RicciError, errstr return True def process_batch(self, batch_xml, async=False): if not self.authed(): - raise 'not authenticated' + raise RicciError, 'not authenticated to host %s', self.__hostname # construct request doc = minidom.Document() @@ -108,13 +130,19 @@ ricci.appendChild(batch_xml.cloneNode(True)) # send request - self.__send(doc) - + try: + self.__send(doc) + except Exception, e: + luci_log.debug('Error sending XML \"%s\" to host %s' \ + % (doc.toxml(), self.__hostname)) + raise RicciError, 'Error sending XML to host %s: %s' \ + % (self.__hostname, str(e)) # receive response doc = self.__receive() if doc.firstChild.getAttribute('success') != '0': - raise 'ricci reported error' + raise RicciError, 'The last ricci command to host %s failed' \ + % self.__hostname batch_node = None for node in doc.firstChild.childNodes: @@ -122,7 +150,8 @@ if node.nodeName == 'batch': batch_node = node.cloneNode(True) if batch_node == None: - raise 'missing in ricci\'s response' + raise RicciError, 'missing in ricci\'s response from %s' \ + % self.__hostname return batch_node @@ -130,18 +159,22 @@ try: batch_xml_str = '' + batch_str + '' batch_xml = minidom.parseString(batch_xml_str).firstChild - except: - return None + except Exception, e: + luci_log.debug('received invalid batch XML for %s: \"%s\"' \ + % (self.__hostname, batch_xml_str)) + raise RicciError, 'batch XML is malformed' try: ricci_xml = self.process_batch(batch_xml, async) except: + luci_log.debug('An error occurred while trying to process the batch job: %s' % batch_xml_str) return None + return ricci_xml def batch_report(self, batch_id): if not self.authed(): - raise 'not authenticated' + raise RicciError, 'Not authenticated to host %s' % self.__hostname # construct request doc = minidom.Document() @@ -153,22 +186,21 @@ # send request self.__send(doc) - - + + # receive response doc = self.__receive() if doc.firstChild.getAttribute('success') == '12': return None if doc.firstChild.getAttribute('success') != '0': - raise 'ricci reported error' - + raise RicciError, 'Error while retrieving batch report for batch #%s from host %s' % (batch_id, self.__hostname) batch_node = None for node in doc.firstChild.childNodes: if node.nodeType == xml.dom.Node.ELEMENT_NODE: if node.nodeName == 'batch': batch_node = node.cloneNode(True) if batch_node == None: - raise 'missing in ricci\'s response' + raise RicciError, 'Missing in ricci\'s response from host %s' % self.__hostname return batch_node @@ -177,13 +209,17 @@ def __send(self, xml_doc): buff = xml_doc.toxml() + '\n' - #print buff while len(buff) != 0: - pos = self.ss.write(buff) + try: + pos = self.ss.write(buff) + except Exception, e: + luci_log.debug('Error sending XML \"%s\" to %s' \ + % (buff, self.__hostname)) + raise RicciError, 'write error while sending XML to host %s' \ + % self.__hostname buff = buff[pos:] return - def __receive(self): doc = None xml_in = '' @@ -197,18 +233,36 @@ doc = minidom.parseString(xml_in) break except: - pass - except: - pass + # we haven't received all of the XML data yet. + continue + except Exception, e: + luci_log.debug('Error reading data from %s: %s' \ + % (self.__hostname, str(e))) + raise RicciError, 'Error reading data from host %s' \ + % self.__hostname + try: if doc == None: doc = minidom.parseString(xml_in) - if doc.firstChild.nodeName != 'ricci': - raise '' - except: - raise 'invalid ricci response' + except Exception, e: + luci_log.debug('Error parsing XML \"%s" from %s' \ + % (xml_in, str(e))) + raise RicciError, 'Error parsing XML from host %s: %s' \ + % (self.__hostname, str(e)) + + if not doc or not doc.firstChild: + raise RicciError, \ + 'Error an empty response was received from host %s' \ + % self.__hostname - #print doc.toxml() + try: + if doc.firstChild.nodeName != 'ricci': + luci_log.debug('Expecting \"ricci\" got XML \"%s\" from %s' % + (xml_in, self.__hostname)) + raise Exception, 'Expecting first XML child node to be \"ricci\"' + except Exception, e: + raise RicciError, 'Invalid XML ricci response from host %s' \ + % self.__hostname return doc @@ -220,7 +274,9 @@ try: return RicciCommunicator(hostname) - except: + except Exception, e: + luci_log.debug('Error creating a ricci connection to %s: %s' \ + % (hostname, str(e))) return None pass @@ -307,7 +363,9 @@ # * error_msg: error message def extract_module_status(batch_xml, module_num=1): if batch_xml.nodeName != 'batch': - raise 'not a batch' + luci_log.debug('Expecting \"batch\" got \"%s\"' % batch_xml.toxml()) + raise RicciError, 'Invalid XML node; expecting a batch node' + c = 0 for node in batch_xml.childNodes: if node.nodeType == xml.dom.Node.ELEMENT_NODE: @@ -349,5 +407,5 @@ elif status == '5': return -103, 'module removed from schedule' - raise Exception, str('no ' + str(module_num) + 'th module in the batch, or malformed response') + raise RicciError, str('no ' + str(module_num) + 'th module in the batch, or malformed response')