Improve short-lived object handling

Its expected that services will appear on the bus and may or may
not be around log enough for introspection to take place.  Catch
those exceptions and continue.

Change-Id: I77963d5af9d8267d1813bd2197ff287f06f7d2cd
Signed-off-by: Brad Bishop <bradleyb@fuzziesquirrel.com>
diff --git a/obmc/dbuslib/introspection.py b/obmc/dbuslib/introspection.py
index 9444d13..805197d 100644
--- a/obmc/dbuslib/introspection.py
+++ b/obmc/dbuslib/introspection.py
@@ -16,6 +16,7 @@
 
 import xml.etree.ElementTree as ET
 import dbus
+import obmc.dbuslib.enums
 
 
 class IntrospectionNodeParser:
@@ -142,17 +143,51 @@
             self.results = {}
 
         @staticmethod
+        def _get_object(path):
+            try:
+                return conn.get_object(service, path, introspect=False)
+            except dbus.exceptions.DBusException, e:
+                if e.get_dbus_name() in [
+                        obmc.dbuslib.enums.DBUS_UNKNOWN_SERVICE,
+                        obmc.dbuslib.enums.DBUS_NO_REPLY]:
+                    print "Warning: Introspection failure: " \
+                        "service `%s` is not running" % (service)
+                    return None
+                raise
+
+        @staticmethod
+        def _invoke_method(path, iface, method, *args):
+            obj = _FindInterfaces._get_object(path)
+            if not obj:
+                return None
+
+            iface = dbus.Interface(obj, iface)
+            try:
+                f = getattr(iface, method)
+                return f(*args)
+            except dbus.exceptions.DBusException, e:
+                if e.get_dbus_name() in [
+                        obmc.dbuslib.enums.DBUS_UNKNOWN_SERVICE,
+                        obmc.dbuslib.enums.DBUS_NO_REPLY]:
+                    print "Warning: Introspection failure: " \
+                        "service `%s` did not reply to "\
+                        "method call on %s" % (service, path)
+                    return None
+                raise
+
+        @staticmethod
         def _introspect(path):
-            obj = conn.get_object(service, path, introspect=False)
-            iface = dbus.Interface(obj, dbus.INTROSPECTABLE_IFACE)
-            return iface.Introspect()
+            return _FindInterfaces._invoke_method(
+                path,
+                dbus.INTROSPECTABLE_IFACE,
+                'Introspect')
 
         @staticmethod
         def _get_managed_objects(om):
-            obj = conn.get_object(service, om, introspect=False)
-            iface = dbus.Interface(
-                obj, dbus.BUS_DAEMON_IFACE + '.ObjectManager')
-            return iface.GetManagedObjects()
+            return _FindInterfaces._invoke_method(
+                om,
+                dbus.BUS_DAEMON_IFACE + '.ObjectManager',
+                'GetManagedObjects')
 
         @staticmethod
         def _to_path(elements):
@@ -175,8 +210,11 @@
         def _find_interfaces(self, path):
             path_elements = self._to_path_elements(path)
             path = self._to_path(path_elements)
-            root = ET.fromstring(self._introspect(path))
+            data = self._introspect(path)
+            if data is None:
+                return
 
+            root = ET.fromstring(data)
             ifaces = filter(
                 self._match,
                 [x.attrib.get('name') for x in root.findall('interface')])