From 8e69447d7b9efc23a0695edbbb55bfbd845a99d8 Mon Sep 17 00:00:00 2001
From: Eric Harney <eharney@redhat.com>
Date: Mon, 21 Sep 2015 14:29:19 -0400
Subject: [PATCH] Allow c-vol backends to start when some backends fail to load

Currently, if a c-vol backend fails to load due to an error in
the module startup process (like a volume driver's __init__ or
dependency import failure), the c-vol process halts completely.

Instead, catch that backend failure, log it, and allow other
backends in enabled_backends to still start up and run.

Note that this is not applicable for failures that allow
drivers to load and remain "uninitialized" -- this is for
failures that occur prior to that point.

Closes-Bug: #1497413

Change-Id: If183b9e3d21777cddf713c2dc88dc80ae7cfe01d
---
 cinder/cmd/volume.py | 33 +++++++++++++++++++++++++--------
 1 file changed, 25 insertions(+), 8 deletions(-)

diff --git a/cinder/cmd/volume.py b/cinder/cmd/volume.py
index c07ea42fa..c9877aefe 100644
--- a/cinder/cmd/volume.py
+++ b/cinder/cmd/volume.py
@@ -42,6 +42,7 @@ i18n.enable_lazy()
 # Need to register global_opts
 from cinder.common import config  # noqa
 from cinder.db import api as session
+from cinder.i18n import _
 from cinder import service
 from cinder import utils
 from cinder import version
@@ -62,20 +63,36 @@ def main():
     utils.monkey_patch()
     gmr.TextGuruMeditation.setup_autorun(version)
     launcher = service.get_launcher()
+    LOG = logging.getLogger(__name__)
+    service_started = False
+
     if CONF.enabled_backends:
         for backend in CONF.enabled_backends:
             CONF.register_opt(host_opt, group=backend)
             backend_host = getattr(CONF, backend).backend_host
             host = "%s@%s" % (backend_host or CONF.host, backend)
-            server = service.Service.create(host=host,
-                                            service_name=backend,
-                                            binary='cinder-volume')
-            # Dispose of the whole DB connection pool here before
-            # starting another process.  Otherwise we run into cases where
-            # child processes share DB connections which results in errors.
-            session.dispose_engine()
-            launcher.launch_service(server)
+            try:
+                server = service.Service.create(host=host,
+                                                service_name=backend,
+                                                binary='cinder-volume')
+            except Exception:
+                msg = _('Volume service %s failed to start.') % host
+                LOG.exception(msg)
+            else:
+                # Dispose of the whole DB connection pool here before
+                # starting another process.  Otherwise we run into cases where
+                # child processes share DB connections which results in errors.
+                session.dispose_engine()
+                launcher.launch_service(server)
+                service_started = True
     else:
         server = service.Service.create(binary='cinder-volume')
         launcher.launch_service(server)
+        service_started = True
+
+    if not service_started:
+        msg = _('No volume service(s) started successfully, terminating.')
+        LOG.error(msg)
+        sys.exit(1)
+
     launcher.wait()
-- 
2.45.2