commit e649b5d8db85bcea23d04ba380c8f04cec5589d4
Author: Radek Novacek <rnovacek(a)redhat.com>
Date: Mon Jul 16 15:50:26 2012 +0200
Add ability to restart itself on SIGHUP signal
It will reload configuration and reconnect to libvirt and rhsm.
Can be used by external programs to force virt-who to reload.
It's also send When virt-who is disconnected from libvirt (xen only).
event.py | 14 ++++++++++++--
subscriptionmanager.py | 20 ++++++++++++--------
virt-who.py | 26 ++++++++++++++++++++++++++
virt.py | 2 ++
4 files changed, 52 insertions(+), 10 deletions(-)
---
diff --git a/event.py b/event.py
index 0f035e6..9d3a557 100644
--- a/event.py
+++ b/event.py
@@ -14,7 +14,10 @@ import libvirt
import select
import time
import threading
+import signal
+# Type of virtualization
+virtType = None
# This general purpose event loop will support waiting for file handle
# I/O and errors events, as well as scheduling repeatable timers with
@@ -264,6 +267,12 @@ class virEventLoopPure:
self.handles = handles
self.interrupt()
+ # !!! This is NOT present in original example from libvirt
+ # Remove handle happens when libvirtd dies, so we'll restart ourself
+ # Only for XEN, works fine for other virt types
+ if virtType is not None and virtType == "Xen":
+ os.kill(os.getpid(), signal.SIGHUP)
+
# Stop firing the periodic timer
def remove_timer(self, timerID):
timers = []
@@ -308,13 +317,12 @@ class virEventLoopPure:
# This single global instance of the event loop wil be used for
# monitoring libvirt events
-eventLoop = virEventLoopPure()
+eventLoop = None
# This keeps track of what thread is running the event loop,
# (if it is run in a background thread)
eventLoopThread = None
-
# These next set of 6 methods are the glue between the official
# libvirt events API, and our particular impl of the event loop
#
@@ -365,6 +373,8 @@ def virEventLoopPureRun():
# Spawn a background thread to run the event loop
def virEventLoopPureStart():
global eventLoopThread
+ global eventLoop
+ eventLoop = virEventLoopPure()
virEventLoopPureRegister()
eventLoopThread = threading.Thread(target=virEventLoopPureRun,
name="libvirtEventLoop")
eventLoopThread.setDaemon(True)
diff --git a/subscriptionmanager.py b/subscriptionmanager.py
index 1b82ec4..4050655 100644
--- a/subscriptionmanager.py
+++ b/subscriptionmanager.py
@@ -49,7 +49,7 @@ class SubscriptionManager:
self.logger = logger
self.cert_uuid = None
- self.config = rhsm_config.initConfig()
+ self.config = rhsm_config.initConfig(rhsm_config.DEFAULT_CONFIG_PATH)
self.readConfig()
# Consumer ID obtained from consumer certificate
@@ -68,13 +68,17 @@ class SubscriptionManager:
def connect(self, Connection=rhsm_connection.UEPConnection):
""" Connect to the subscription-manager. """
- self.connection = Connection(cert_file=self.cert_file, key_file=self.key_file)
- try:
- if not self.connection.ping()['result']:
- raise SubscriptionManagerConnectionError("Unable to obtain status
from server, UEPConnection is likely not usable.")
- except Exception, e:
- self.logger.exception("Unable to obtain status from server,
UEPConnection is likely not usable:")
- raise SubscriptionManagerError()
+ self.connection = Connection(
+ host=self.config.get('server', 'hostname'),
+ ssl_port=int(self.config.get('server', 'port')),
+ handler=self.config.get('server', 'prefix'),
+ proxy_hostname=self.config.get('server',
'proxy_hostname'),
+ proxy_port=self.config.get('server', 'proxy_port'),
+ proxy_user=self.config.get('server', 'proxy_user'),
+ proxy_password=self.config.get('server',
'proxy_password'),
+ cert_file=self.cert_file, key_file=self.key_file)
+ if not self.connection.ping()['result']:
+ raise SubscriptionManagerError("Unable to obtain status from server,
UEPConnection is likely not usable.")
def sendVirtGuests(self, domains):
""" Update consumer facts with UUIDs of virtual guests.
"""
diff --git a/virt-who.py b/virt-who.py
index f154b14..3ae6e37 100644
--- a/virt-who.py
+++ b/virt-who.py
@@ -81,6 +81,9 @@ class VirtWho(object):
if not options.oneshot:
self.unableToRecoverStr += ", retry in %d seconds." %
RetryInterval
+ # True if reload is queued
+ self.doReload = False
+
def initVirt(self):
"""
@@ -219,6 +222,22 @@ class VirtWho(object):
return False
return self.virt.ping()
+ def queueReload(self, *p):
+ """
+ Reload virt-who configuration. Called on SIGHUP signal arrival.
+ """
+ self.doReload = True
+
+ def reloadConfig(self):
+ if self.virt and self.virt.virt:
+ self.virt.virt.close()
+ self.virt = None
+ self.subscriptionManager = None
+ self.checkConnections()
+ self.logger.debug("virt-who configution reloaded")
+ self.doReload = False
+
+
def daemonize(debugMode):
""" Perform double-fork and redirect std* to /dev/null
"""
@@ -397,6 +416,7 @@ if __name__ == '__main__':
RetryInterval = options.interval
virtWho = VirtWho(logger, options)
+ signal.signal(signal.SIGHUP, virtWho.queueReload)
try:
virtWho.checkConnections()
except Exception:
@@ -426,6 +446,12 @@ if __name__ == '__main__':
t = min(RetryInterval, options.interval - slept)
time.sleep(t)
slept += t
+
+ # Reload configuration if queued
+ if virtWho.doReload:
+ virtWho.reloadConfig()
+ break
+
# Check the connection
if not virtWho.ping():
# End the cycle
diff --git a/virt.py b/virt.py
index d439c30..75d8019 100644
--- a/virt.py
+++ b/virt.py
@@ -19,6 +19,7 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
"""
import libvirt
+import event
class VirtError(Exception):
pass
@@ -35,6 +36,7 @@ class Virt:
self.virt = libvirt.openReadOnly("")
# Register listener for domain changes
self.virt.domainEventRegister(self.changed, None)
+ event.virtType = self.virt.getType()
except libvirt.libvirtError, e:
raise VirtError(str(e))