From be552cc4462f8f0fe30d5ae1c41cf890b322a1f1 Mon Sep 17 00:00:00 2001 From: Jarrod Johnson Date: Fri, 4 Apr 2014 20:45:48 -0400 Subject: [PATCH] Fix the session reconfiguration automatic response Previously, it would register 2**x attribute watchers by mistake. Exponential growth of threads trying to talk to one BMC is evidently a bad thing. Fix this by correctly tracking and cancelling previous attribute watchers. Additionally, mask a harmless exception brought on by the death of orphaned pyghmi console objects by having them yell into the endless void rather than trip on an exception. --- confluent/consoleserver.py | 15 +++++++++++---- plugins/hardwaremanagement/ipmi.py | 8 +++++++- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/confluent/consoleserver.py b/confluent/consoleserver.py index fab16fab..7febd8cd 100644 --- a/confluent/consoleserver.py +++ b/confluent/consoleserver.py @@ -43,12 +43,19 @@ class _ConsoleHandler(object): self.connectstate = 'connecting' self._attribwatcher = None self._console = None + self.connectionthread = None eventlet.spawn(self._connect) def _attribschanged(self, **kwargs): eventlet.spawn(self._connect) def _connect(self): + if self.connectionthread: + self.connectionthread.kill() + self.connectionthread = None + self.connectionthread = eventlet.spawn(self._connect_backend) + + def _connect_backend(self): if self._console: self._console.close() self._console = None @@ -67,16 +74,16 @@ class _ConsoleHandler(object): attribstowatch = self._console.configattributes | _genwatchattribs else: attribstowatch = _genwatchattribs - self.cfgmgr.watch_attributes((self.node,), attribstowatch, - self._attribschanged) + self._attribwatcher = self.cfgmgr.watch_attributes( + (self.node,), attribstowatch, self._attribschanged) try: self._console.connect(self.get_console_output) except exc.TargetEndpointUnreachable: self.connectstate = 'unconnected' self._send_rcpts({'connectstate': self.connectstate}) retrytime = 30 + (30 * random.random()) - print "Console was unreachable, waiting %d seconds..." % retrytime - self.reconnect = eventlet.spawn_after(retrytime, self._connect) + if not self.reconnect: + self.reconnect = eventlet.spawn_after(retrytime, self._connect) return self._got_connected() diff --git a/plugins/hardwaremanagement/ipmi.py b/plugins/hardwaremanagement/ipmi.py index 44cb10fa..a50f0ad0 100644 --- a/plugins/hardwaremanagement/ipmi.py +++ b/plugins/hardwaremanagement/ipmi.py @@ -61,6 +61,12 @@ _configattributes = ('secret.hardwaremanagementuser', 'secret.hardwaremanagementpassphrase', 'secret.ipmikg', 'hardwaremanagement.manager') +def _donothing(data): + # a dummy function to avoid some awkward exceptions from + # zombie pyghmi console objects + pass + + class IpmiConsole(conapi.Console): configattributes = frozenset(_configattributes) @@ -122,7 +128,7 @@ class IpmiConsole(conapi.Console): def close(self): if hasattr(self, 'solconnection') and self.solconnection is not None: # break the circular reference here - self.solconnection.out_handler = None + self.solconnection.out_handler = _donothing self.solconnection = None self.broken = True self.error = "closed"