Martin Peřina has uploaded a new change for review.

Change subject: tools: Adds support to notify systemd using sd_notify
......................................................................

tools: Adds support to notify systemd using sd_notify

Adds support to notifier service to notify systemd about service startup
success/error using sd_notify daemon.

Change-Id: Ie62a4ba5a837bcaf216ace9870e212a7151aa8bc
Bug-Url: https://bugzilla.redhat.com/989382
Signed-off-by: Martin Perina <mper...@redhat.com>
---
A packaging/pythonlib/ovirt_engine/sdnotify.py
M packaging/pythonlib/ovirt_engine/service.py
M packaging/services/ovirt-engine-notifier/ovirt-engine-notifier.py
M packaging/services/ovirt-engine-notifier/ovirt-engine-notifier.systemd.in
4 files changed, 140 insertions(+), 9 deletions(-)


  git pull ssh://gerrit.ovirt.org:29418/ovirt-engine refs/changes/30/22630/1

diff --git a/packaging/pythonlib/ovirt_engine/sdnotify.py 
b/packaging/pythonlib/ovirt_engine/sdnotify.py
new file mode 100644
index 0000000..3ba1f35
--- /dev/null
+++ b/packaging/pythonlib/ovirt_engine/sdnotify.py
@@ -0,0 +1,81 @@
+#
+# Copyright 2013 Red Hat
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+import os
+import socket
+
+
+from . import base
+from . import util
+
+
+@util.export
+class Notifier(base.Base):
+    """Sends messages to systemd about service startup success or error"""
+
+    def __init__(self, socket=None):
+        super(Notifier, self).__init__()
+        self._socket = socket
+        if not self._socket:
+            self._socket = os.environ.get('NOTIFY_SOCKET')
+
+    def sendDict(self, state):
+        """Converts state defined as dict to string and sends it to systemd"""
+        return self.sendStr(
+            '\n'.join(['{0}={1}'.format(k, v) for (k, v) in state.iteritems()])
+        )
+
+    def sendStr(self, state):
+        """Sends state defined as string to systemd. Return True if state was
+        sent successfully, otherwise False"""
+
+        if self._socket[0] not in ('@', '/') or len(self._socket) == 1:
+            raise RuntimeError(
+                "Invalid sd_notify socket '%s'" % self._socket
+            )
+
+        if self._socket[0] == '@':
+            self._socket = '\0' + self._socket[1:]
+
+        self.logger.debug(
+            "Using socket '%s' to notify systemd",
+            self._socket,
+        )
+
+        result = True
+        s = None
+        try:
+            self.logger.debug(
+                "Sending '%s' to systemd",
+                state,
+            )
+
+            s = socket.socket(socket.AF_UNIX, socket.SOCK_DGRAM)
+            if s.sendto(state, self._socket) < 1:
+                result = False
+        except socket.error as e:
+            self.logger.error(
+                "Cannot send '%s' to systemd, error '%s'",
+                state,
+                e,
+            )
+        finally:
+            if s is not None:
+                s.close()
+        return result
+
+
+# vim: expandtab tabstop=4 shiftwidth=4
diff --git a/packaging/pythonlib/ovirt_engine/service.py 
b/packaging/pythonlib/ovirt_engine/service.py
index b25d58b..a91917c 100644
--- a/packaging/pythonlib/ovirt_engine/service.py
+++ b/packaging/pythonlib/ovirt_engine/service.py
@@ -292,6 +292,8 @@
                 close_fds=True,
             )
 
+            self.postDaemonExec(proc=p)
+
             self.logger.debug(
                 'waiting for termination of pid=%s',
                 p.pid,
@@ -414,12 +416,8 @@
 
         self.logger.debug('daemon return')
 
-    def run(self):
-        self.logger.debug('startup args=%s', sys.argv)
-
-        parser = optparse.OptionParser(
-            usage=_('usage: %prog [options] start'),
-        )
+    def addArgs(self, parser):
+        """Registers valid command line arguments"""
         parser.add_option(
             '-d', '--debug',
             dest='debug',
@@ -448,6 +446,14 @@
             default=False,
             help=_('Redirect output of daemon'),
         )
+
+    def run(self):
+        self.logger.debug('startup args=%s', sys.argv)
+
+        parser = optparse.OptionParser(
+            usage=_('usage: %prog [options] start'),
+        )
+        self.addArgs(parser)
         (self._options, args) = parser.parse_args()
 
         if self._options.debug:
@@ -488,6 +494,7 @@
                 )
             )
             self.logger.debug('exception', exc_info=True)
+            self.onDaemonException(e)
             sys.exit(1)
         else:
             sys.exit(0)
@@ -506,6 +513,15 @@
         """Called prior to daemon execution"""
         pass
 
+    def postDaemonExec(self, proc):
+        """Called after daemon subprocess execution, proc identifies daemon
+        subprocess."""
+        pass
+
+    def onDaemonException(self, exception):
+        """Called if exception is raised during daemon execution"""
+        pass
+
     def daemonContext(self):
         """Daemon logic
         Called within daemon context
diff --git a/packaging/services/ovirt-engine-notifier/ovirt-engine-notifier.py 
b/packaging/services/ovirt-engine-notifier/ovirt-engine-notifier.py
index cd7089b..9f521c1 100755
--- a/packaging/services/ovirt-engine-notifier/ovirt-engine-notifier.py
+++ b/packaging/services/ovirt-engine-notifier/ovirt-engine-notifier.py
@@ -26,6 +26,7 @@
 
 
 from ovirt_engine import configfile
+from ovirt_engine import sdnotify
 from ovirt_engine import service
 from ovirt_engine import java
 
@@ -88,8 +89,18 @@
                 mustExist=False,
             )
 
-    def daemonSetup(self):
+    def addArgs(self, parser):
+        """Adds argument to enable sd_notify functionality"""
+        super(Daemon, self).addArgs(parser)
+        parser.add_option(
+            '--notify',
+            dest='notify',
+            action='store_true',
+            default=False,
+            help=_('Enables notification of daemon startup success/error'),
+        )
 
+    def daemonSetup(self):
         if os.geteuid() == 0:
             raise RuntimeError(
                 _('This service cannot be executed as root')
@@ -203,6 +214,28 @@
         if proc.returncode != 0:
             raise RuntimeError('Error validating notifier configuration')
 
+    def postDaemonExec(self, proc):
+        """Notifies systemd about daemon startup"""
+        if self._options.notify:
+            exitCode = proc.poll()
+            if exitCode is None:
+                sdnotify.Notifier().sendDict(
+                    state={
+                        'READY': '1',
+                        'STATUS': 'Notifier daemon executed',
+                    }
+                )
+
+    def onDaemonException(self, exception):
+        """Called if exception is raised during daemon execution"""
+        if self._options.notify:
+            sdnotify.Notifier().sendDict(
+                state={
+                    'ERRNO': '1',
+                    'STATUS': 'Failed to start notifier',
+                }
+            )
+
 
 if __name__ == '__main__':
     service.setupLogger()
diff --git 
a/packaging/services/ovirt-engine-notifier/ovirt-engine-notifier.systemd.in 
b/packaging/services/ovirt-engine-notifier/ovirt-engine-notifier.systemd.in
index 9d53b2f..158132f 100644
--- a/packaging/services/ovirt-engine-notifier/ovirt-engine-notifier.systemd.in
+++ b/packaging/services/ovirt-engine-notifier/ovirt-engine-notifier.systemd.in
@@ -3,10 +3,11 @@
 After=network.service postgresql.service
 
 [Service]
-Type=simple
+Type=notify
+NotifyAccess=main
 User=@ENGINE_USER@
 Group=@ENGINE_GROUP@
-ExecStart=@ENGINE_USR@/services/ovirt-engine-notifier/ovirt-engine-notifier.py 
--redirect-output $EXTRA_ARGS start
+ExecStart=@ENGINE_USR@/services/ovirt-engine-notifier/ovirt-engine-notifier.py 
--redirect-output --notify $EXTRA_ARGS start
 EnvironmentFile=-/etc/sysconfig/ovirt-engine-notifier
 
 [Install]


-- 
To view, visit http://gerrit.ovirt.org/22630
To unsubscribe, visit http://gerrit.ovirt.org/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Ie62a4ba5a837bcaf216ace9870e212a7151aa8bc
Gerrit-PatchSet: 1
Gerrit-Project: ovirt-engine
Gerrit-Branch: master
Gerrit-Owner: Martin Peřina <mper...@redhat.com>
_______________________________________________
Engine-patches mailing list
Engine-patches@ovirt.org
http://lists.ovirt.org/mailman/listinfo/engine-patches

Reply via email to