diff --git a/obmc/mapper/server.py b/obmc/mapper/server.py
new file mode 100644
index 0000000..b71ea6a
--- /dev/null
+++ b/obmc/mapper/server.py
@@ -0,0 +1,633 @@
+#!/usr/bin/env python
+
+# Contributors Listed Below - COPYRIGHT 2016
+# [+] International Business Machines Corp.
+#
+#
+# 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 dbus
+import dbus.service
+import dbus.exceptions
+import dbus.mainloop.glib
+import gobject
+import xml.etree.ElementTree as ET
+import obmc.utils.pathtree
+import obmc.utils.misc
+import obmc.mapper
+import obmc.dbuslib.bindings
+import obmc.dbuslib.enums
+
+
+class MapperNotFoundException(dbus.exceptions.DBusException):
+    _dbus_error_name = obmc.mapper.MAPPER_NOT_FOUND
+
+    def __init__(self, path):
+        super(MapperNotFoundException, self).__init__(
+            "path or object not found: %s" % path)
+
+
+def find_dbus_interfaces(conn, service, path, match):
+    class _FindInterfaces(object):
+        def __init__(self):
+            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):
+            return _FindInterfaces._invoke_method(
+                path,
+                dbus.INTROSPECTABLE_IFACE,
+                'Introspect')
+
+        @staticmethod
+        def _get_managed_objects(om):
+            return _FindInterfaces._invoke_method(
+                om,
+                dbus.BUS_DAEMON_IFACE + '.ObjectManager',
+                'GetManagedObjects')
+
+        @staticmethod
+        def _to_path(elements):
+            return '/' + '/'.join(elements)
+
+        @staticmethod
+        def _to_path_elements(path):
+            return filter(bool, path.split('/'))
+
+        def __call__(self, path):
+            self.results = {}
+            self._find_interfaces(path)
+            return self.results
+
+        @staticmethod
+        def _match(iface):
+            return iface == dbus.BUS_DAEMON_IFACE + '.ObjectManager' \
+                or match(iface)
+
+        def _find_interfaces(self, path):
+            path_elements = self._to_path_elements(path)
+            path = self._to_path(path_elements)
+            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')])
+            self.results[path] = ifaces
+
+            if dbus.BUS_DAEMON_IFACE + '.ObjectManager' in ifaces:
+                objs = self._get_managed_objects(path)
+                for k, v in objs.iteritems():
+                    self.results[k] = v
+            else:
+                children = filter(
+                    bool,
+                    [x.attrib.get('name') for x in root.findall('node')])
+                children = [
+                    self._to_path(
+                        path_elements + self._to_path_elements(x))
+                    for x in sorted(children)]
+                for child in children:
+                    if child not in self.results:
+                        self._find_interfaces(child)
+
+    return _FindInterfaces()(path)
+
+
+class Association(dbus.service.Object):
+    def __init__(self, bus, path, endpoints):
+        super(Association, self).__init__(bus, path)
+        self.endpoints = endpoints
+
+    def __getattr__(self, name):
+        if name == 'properties':
+            return {
+                obmc.dbuslib.enums.OBMC_ASSOC_IFACE: {
+                    'endpoints': self.endpoints}}
+        return super(Association, self).__getattr__(name)
+
+    def emit_signal(self, old):
+        if old != self.endpoints:
+            self.PropertiesChanged(
+                obmc.dbuslib.enums.OBMC_ASSOC_IFACE,
+                {'endpoints': self.endpoints}, ['endpoints'])
+
+    def append(self, endpoints):
+        old = self.endpoints
+        self.endpoints = list(set(endpoints).union(self.endpoints))
+        self.emit_signal(old)
+
+    def remove(self, endpoints):
+        old = self.endpoints
+        self.endpoints = list(set(self.endpoints).difference(endpoints))
+        self.emit_signal(old)
+
+    @dbus.service.method(dbus.PROPERTIES_IFACE, 'ss', 'as')
+    def Get(self, interface_name, property_name):
+        if property_name != 'endpoints':
+            raise dbus.exceptions.DBusException(name=DBUS_UNKNOWN_PROPERTY)
+        return self.GetAll(interface_name)[property_name]
+
+    @dbus.service.method(dbus.PROPERTIES_IFACE, 's', 'a{sas}')
+    def GetAll(self, interface_name):
+        if interface_name != obmc.dbuslib.enums.OBMC_ASSOC_IFACE:
+            raise dbus.exceptions.DBusException(DBUS_UNKNOWN_INTERFACE)
+        return {'endpoints': self.endpoints}
+
+    @dbus.service.signal(
+        dbus.PROPERTIES_IFACE, signature='sa{sas}as')
+    def PropertiesChanged(
+            self, interface_name, changed_properties, invalidated_properties):
+        pass
+
+
+class Manager(obmc.dbuslib.bindings.DbusObjectManager):
+    def __init__(self, bus, path):
+        obmc.dbuslib.bindings.DbusObjectManager.__init__(self)
+        dbus.service.Object.__init__(self, bus, path)
+
+
+class ObjectMapper(dbus.service.Object):
+    def __init__(self, bus, path,
+                 name_match=obmc.utils.misc.org_dot_openbmc_match,
+                 intf_match=obmc.utils.misc.org_dot_openbmc_match):
+        super(ObjectMapper, self).__init__(bus, path)
+        self.cache = obmc.utils.pathtree.PathTree()
+        self.bus = bus
+        self.name_match = name_match
+        self.intf_match = intf_match
+        self.tag_match = obmc.utils.misc.ListMatch(['children', 'interface'])
+        self.service = None
+        self.index = {}
+        self.manager = Manager(bus, obmc.dbuslib.bindings.OBJ_PREFIX)
+        self.unique = bus.get_unique_name()
+        self.bus_map = {}
+
+        gobject.idle_add(self.discover)
+        self.bus.add_signal_receiver(
+            self.bus_handler,
+            dbus_interface=dbus.BUS_DAEMON_IFACE,
+            signal_name='NameOwnerChanged')
+        self.bus.add_signal_receiver(
+            self.interfaces_added_handler,
+            dbus_interface=dbus.BUS_DAEMON_IFACE + '.ObjectManager',
+            signal_name='InterfacesAdded',
+            sender_keyword='sender',
+            path_keyword='sender_path')
+        self.bus.add_signal_receiver(
+            self.interfaces_removed_handler,
+            dbus_interface=dbus.BUS_DAEMON_IFACE + '.ObjectManager',
+            signal_name='InterfacesRemoved',
+            sender_keyword='sender',
+            path_keyword='sender_path')
+        self.bus.add_signal_receiver(
+            self.properties_changed_handler,
+            dbus_interface=dbus.PROPERTIES_IFACE,
+            signal_name='PropertiesChanged',
+            path_keyword='path',
+            sender_keyword='sender')
+
+    def bus_match(self, owner):
+        # Ignore my own signals
+        return owner != obmc.mapper.MAPPER_NAME and \
+            self.name_match(owner)
+
+    def discovery_pending(self):
+        return not bool(self.service)
+
+    def cache_get(self, path):
+        cache_entry = self.cache.get(path, {})
+        if cache_entry is None:
+            # hide path elements without any interfaces
+            cache_entry = {}
+        return cache_entry
+
+    def add_new_objmgr(self, path, owner):
+        # We don't get a signal for the ObjectManager
+        # interface itself, so if we see a signal from
+        # make sure its in our cache, and add it if not.
+        cache_entry = self.cache_get(path)
+        old = self.interfaces_get(cache_entry, owner)
+        new = list(set(old).union([dbus.BUS_DAEMON_IFACE + '.ObjectManager']))
+        self.update_interfaces(path, owner, old, new)
+
+    def interfaces_added_handler(self, path, iprops, **kw):
+        path = str(path)
+        owner = str(kw['sender'])
+        interfaces = self.get_signal_interfaces(owner, iprops.iterkeys())
+        if interfaces:
+            self.add_new_objmgr(str(kw['sender_path']), owner)
+            cache_entry = self.cache_get(path)
+            old = self.interfaces_get(cache_entry, owner)
+            new = list(set(interfaces).union(old))
+            self.update_interfaces(path, owner, old, new)
+
+    def interfaces_removed_handler(self, path, interfaces, **kw):
+        path = str(path)
+        owner = str(kw['sender'])
+        interfaces = self.get_signal_interfaces(owner, interfaces)
+        if interfaces:
+            self.add_new_objmgr(str(kw['sender_path']), owner)
+            cache_entry = self.cache_get(path)
+            old = self.interfaces_get(cache_entry, owner)
+            new = list(set(old).difference(interfaces))
+            self.update_interfaces(path, owner, old, new)
+
+    def properties_changed_handler(self, interface, new, old, **kw):
+        owner = str(kw['sender'])
+        path = str(kw['path'])
+        interfaces = self.get_signal_interfaces(owner, [interface])
+        if not self.is_association(interfaces):
+            return
+        associations = new.get('associations', None)
+        if associations is None:
+            return
+
+        associations = [
+            (str(x), str(y), str(z)) for x, y, z in associations]
+        self.update_associations(
+            path, owner,
+            self.index_get_associations(path, [owner]),
+            associations)
+
+    def process_new_owner(self, owned_name, owner):
+        # unique name
+        try:
+            return self.discover([(owned_name, owner)])
+        except dbus.exceptions.DBusException, e:
+            if obmc.dbuslib.enums.DBUS_UNKNOWN_SERVICE \
+                    not in e.get_dbus_name():
+                raise
+
+    def process_old_owner(self, owned_name, owner):
+        if owner in self.bus_map:
+            del self.bus_map[owner]
+
+        for path, item in self.cache.dataitems():
+            old = self.interfaces_get(item, owner)
+            # remove all interfaces for this service
+            self.update_interfaces(
+                path, owner, old=old, new=[])
+
+    def bus_handler(self, owned_name, old, new):
+        valid = False
+        if not obmc.dbuslib.bindings.is_unique(owned_name):
+            valid = self.valid_signal(owned_name)
+
+        if valid and new:
+            self.process_new_owner(owned_name, new)
+        if valid and old:
+            self.process_old_owner(owned_name, old)
+
+    def update_interfaces(self, path, owner, old, new):
+        # __xx -> intf list
+        # xx -> intf dict
+        if isinstance(old, dict):
+            __old = old.keys()
+        else:
+            __old = old
+            old = {x: {} for x in old}
+        if isinstance(new, dict):
+            __new = new.keys()
+        else:
+            __new = new
+            new = {x: {} for x in new}
+
+        cache_entry = self.cache.setdefault(path, {})
+        created = [] if self.has_interfaces(cache_entry) else [path]
+        added = list(set(__new).difference(__old))
+        removed = list(set(__old).difference(__new))
+        self.interfaces_append(cache_entry, owner, added)
+        self.interfaces_remove(cache_entry, owner, removed, path)
+        destroyed = [] if self.has_interfaces(cache_entry) else [path]
+
+        # react to anything that requires association updates
+        new_assoc = []
+        old_assoc = []
+        if self.is_association(added):
+            new_assoc = self.dbus_get_associations(path, owner, new)
+        if self.is_association(removed):
+            old_assoc = self.index_get_associations(path, [owner])
+        self.update_associations(
+            path, owner, old_assoc, new_assoc, created, destroyed)
+
+    def add_items(self, owner, bus_items):
+        for path, items in bus_items.iteritems():
+            self.update_interfaces(path, str(owner), old=[], new=items)
+
+    def discover(self, owners=[]):
+        def match(iface):
+            return iface == dbus.BUS_DAEMON_IFACE + '.ObjectManager' or \
+                self.intf_match(iface)
+        if not owners:
+            owned_names = [
+                x for x in self.bus.list_names() if self.bus_match(x)]
+            owners = [self.bus.get_name_owner(x) for x in owned_names]
+            owners = zip(owned_names, owners)
+        for owned_name, o in owners:
+            self.add_items(
+                o,
+                find_dbus_interfaces(self.bus, o, '/', self.intf_match))
+            self.bus_map[o] = owned_name
+
+        if self.discovery_pending():
+            # add my object mananger instance
+            self.bus_map[self.unique] = obmc.mapper.MAPPER_NAME
+            self.add_items(
+                self.unique,
+                {obmc.dbuslib.bindings.OBJ_PREFIX:
+                    {'interfaces':
+                        [dbus.BUS_DAEMON_IFACE + '.ObjectManager']}})
+
+            print "ObjectMapper discovery complete..."
+            self.service = dbus.service.BusName(
+                obmc.mapper.MAPPER_NAME, self.bus)
+
+    def valid_signal(self, name):
+        if self.discovery_pending():
+            return False
+
+        if obmc.dbuslib.bindings.is_unique(name):
+            name = self.bus_map.get(name)
+
+        return name is not None and \
+            self.bus_match(name)
+
+    def get_signal_interfaces(self, owner, interfaces):
+        filtered = []
+        if self.valid_signal(owner):
+            filtered = [str(x) for x in interfaces if self.intf_match(x)]
+
+        return filtered
+
+    @staticmethod
+    def interfaces_get(item, owner, default=[]):
+        return item.get(owner, default)
+
+    @staticmethod
+    def interfaces_append(item, owner, append):
+        interfaces = item.setdefault(owner, [])
+        item[owner] = list(set(append).union(interfaces))
+
+    def interfaces_remove(self, item, owner, remove, path):
+        interfaces = item.get(owner, [])
+        item[owner] = list(set(interfaces).difference(remove))
+
+        if not item[owner]:
+            # remove the owner if there aren't any interfaces left
+            del item[owner]
+
+        if item:
+            # other owners remain
+            return
+
+        if self.cache.get_children(path):
+            # there are still references to this path
+            # from objects further down the tree.
+            # mark it for removal if that changes
+            self.cache.demote(path)
+        else:
+            # delete the entire path if everything is gone
+            del self.cache[path]
+
+    @dbus.service.method(obmc.mapper.MAPPER_IFACE, 's', 'a{sas}')
+    def GetObject(self, path):
+        o = self.cache_get(path)
+        if not o:
+            raise MapperNotFoundException(path)
+        return o
+
+    @dbus.service.method(obmc.mapper.MAPPER_IFACE, 'si', 'as')
+    def GetSubTreePaths(self, path, depth):
+        try:
+            return self.cache.iterkeys(path, depth)
+        except KeyError:
+            raise MapperNotFoundException(path)
+
+    @dbus.service.method(obmc.mapper.MAPPER_IFACE, 'si', 'a{sa{sas}}')
+    def GetSubTree(self, path, depth):
+        try:
+            return {x: y for x, y in self.cache.dataitems(path, depth)}
+        except KeyError:
+            raise MapperNotFoundException(path)
+
+    @staticmethod
+    def has_interfaces(item):
+        for owner in item.iterkeys():
+            if ObjectMapper.interfaces_get(item, owner):
+                return True
+        return False
+
+    @staticmethod
+    def is_association(interfaces):
+        return obmc.dbuslib.enums.OBMC_ASSOCIATIONS_IFACE in interfaces
+
+    def index_get(self, index, path, owners):
+        items = []
+        item = self.index.get(index, {})
+        item = item.get(path, {})
+        for o in owners:
+            items.extend(item.get(o, []))
+        return items
+
+    def index_append(self, index, path, owner, assoc):
+        item = self.index.setdefault(index, {})
+        item = item.setdefault(path, {})
+        item = item.setdefault(owner, [])
+        item.append(assoc)
+
+    def index_remove(self, index, path, owner, assoc):
+        index = self.index.get(index, {})
+        owners = index.get(path, {})
+        items = owners.get(owner, [])
+        if assoc in items:
+            items.remove(assoc)
+        if not items:
+            del owners[owner]
+        if not owners:
+            del index[path]
+
+    def dbus_get_associations(self, path, owner, obj):
+        iface = obmc.dbuslib.enums.OBMC_ASSOCIATIONS_IFACE
+        if 'associations' in obj[iface]:
+            return obj[iface]['associations']
+
+        # fallback to dbus
+        obj = self.bus.get_object(owner, path, introspect=False)
+        iface = dbus.Interface(obj, dbus.PROPERTIES_IFACE)
+        return [(str(f), str(r), str(e)) for f, r, e in iface.Get(
+            obmc.dbuslib.enums.OBMC_ASSOCIATIONS_IFACE,
+            'associations')]
+
+    def index_get_associations(self, path, owners=[], direction='forward'):
+        forward = 'forward' if direction == 'forward' else 'reverse'
+        reverse = 'reverse' if direction == 'forward' else 'forward'
+
+        associations = []
+        if not owners:
+            index = self.index.get(forward, {})
+            owners = index.get(path, {}).keys()
+
+        # f: forward
+        # r: reverse
+        for rassoc in self.index_get(forward, path, owners):
+            elements = rassoc.split('/')
+            rtype = ''.join(elements[-1:])
+            fendpoint = '/'.join(elements[:-1])
+            for fassoc in self.index_get(reverse, fendpoint, owners):
+                elements = fassoc.split('/')
+                ftype = ''.join(elements[-1:])
+                rendpoint = '/'.join(elements[:-1])
+                if rendpoint != path:
+                    continue
+                associations.append((ftype, rtype, fendpoint))
+
+        return associations
+
+    def update_association(self, path, removed, added):
+        iface = obmc.dbuslib.enums.OBMC_ASSOC_IFACE
+        create = [] if self.manager.get(path, False) else [iface]
+
+        if added and create:
+            self.manager.add(
+                path, Association(self.bus, path, added))
+        elif added:
+            self.manager.get(path).append(added)
+
+        obj = self.manager.get(path, None)
+        if obj and removed:
+            obj.remove(removed)
+
+        if obj and not obj.endpoints:
+            self.manager.remove(path)
+
+        delete = [] if self.manager.get(path, False) else [iface]
+
+        if create != delete:
+            self.update_interfaces(
+                path, self.unique, delete, create)
+
+    def update_associations(
+            self, path, owner, old, new, created=[], destroyed=[]):
+        added = list(set(new).difference(old))
+        removed = list(set(old).difference(new))
+        for forward, reverse, endpoint in added:
+            # update the index
+            forward_path = str(path + '/' + forward)
+            reverse_path = str(endpoint + '/' + reverse)
+            self.index_append(
+                'forward', path, owner, reverse_path)
+            self.index_append(
+                'reverse', endpoint, owner, forward_path)
+
+            # create the association if the endpoint exists
+            if not self.cache_get(endpoint):
+                continue
+
+            self.update_association(forward_path, [], [endpoint])
+            self.update_association(reverse_path, [], [path])
+
+        for forward, reverse, endpoint in removed:
+            # update the index
+            forward_path = str(path + '/' + forward)
+            reverse_path = str(endpoint + '/' + reverse)
+            self.index_remove(
+                'forward', path, owner, reverse_path)
+            self.index_remove(
+                'reverse', endpoint, owner, forward_path)
+
+            # destroy the association if it exists
+            self.update_association(forward_path, [endpoint], [])
+            self.update_association(reverse_path, [path], [])
+
+        # If the associations interface endpoint comes
+        # or goes create or destroy the appropriate
+        # associations
+        for path in created:
+            for forward, reverse, endpoint in \
+                    self.index_get_associations(path, direction='reverse'):
+                forward_path = str(path + '/' + forward)
+                reverse_path = str(endpoint + '/' + reverse)
+                self.update_association(forward_path, [], [endpoint])
+                self.update_association(reverse_path, [], [path])
+
+        for path in destroyed:
+            for forward, reverse, endpoint in \
+                    self.index_get_associations(path, direction='reverse'):
+                forward_path = str(path + '/' + forward)
+                reverse_path = str(endpoint + '/' + reverse)
+                self.update_association(forward_path, [endpoint], [])
+                self.update_association(reverse_path, [path], [])
+
+    @dbus.service.method(obmc.mapper.MAPPER_IFACE, 's', 'a{sa{sas}}')
+    def GetAncestors(self, path):
+        elements = filter(bool, path.split('/'))
+        paths = []
+        objs = {}
+        while elements:
+            elements.pop()
+            paths.append('/' + '/'.join(elements))
+        if path != '/':
+            paths.append('/')
+
+        for path in paths:
+            obj = self.cache_get(path)
+            if not obj:
+                continue
+            objs[path] = obj
+
+        return objs
+
+
+def server_main():
+    dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
+    bus = dbus.SystemBus()
+    o = ObjectMapper(bus, obmc.mapper.MAPPER_PATH)
+    loop = gobject.MainLoop()
+
+    loop.run()
diff --git a/phosphor-mapper b/phosphor-mapper
index 1affe81..2f35daa 100644
--- a/phosphor-mapper
+++ b/phosphor-mapper
@@ -16,618 +16,8 @@
 # implied. See the License for the specific language governing
 # permissions and limitations under the License.
 
-import dbus
-import dbus.service
-import dbus.exceptions
-import dbus.mainloop.glib
-import gobject
-import xml.etree.ElementTree as ET
-import obmc.utils.pathtree
-import obmc.utils.misc
-import obmc.mapper
-import obmc.dbuslib.bindings
-import obmc.dbuslib.enums
-
-
-class MapperNotFoundException(dbus.exceptions.DBusException):
-    _dbus_error_name = obmc.mapper.MAPPER_NOT_FOUND
-
-    def __init__(self, path):
-        super(MapperNotFoundException, self).__init__(
-            "path or object not found: %s" % path)
-
-
-def find_dbus_interfaces(conn, service, path, match):
-    class _FindInterfaces(object):
-        def __init__(self):
-            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):
-            return _FindInterfaces._invoke_method(
-                path,
-                dbus.INTROSPECTABLE_IFACE,
-                'Introspect')
-
-        @staticmethod
-        def _get_managed_objects(om):
-            return _FindInterfaces._invoke_method(
-                om,
-                dbus.BUS_DAEMON_IFACE + '.ObjectManager',
-                'GetManagedObjects')
-
-        @staticmethod
-        def _to_path(elements):
-            return '/' + '/'.join(elements)
-
-        @staticmethod
-        def _to_path_elements(path):
-            return filter(bool, path.split('/'))
-
-        def __call__(self, path):
-            self.results = {}
-            self._find_interfaces(path)
-            return self.results
-
-        @staticmethod
-        def _match(iface):
-            return iface == dbus.BUS_DAEMON_IFACE + '.ObjectManager' \
-                or match(iface)
-
-        def _find_interfaces(self, path):
-            path_elements = self._to_path_elements(path)
-            path = self._to_path(path_elements)
-            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')])
-            self.results[path] = ifaces
-
-            if dbus.BUS_DAEMON_IFACE + '.ObjectManager' in ifaces:
-                objs = self._get_managed_objects(path)
-                for k, v in objs.iteritems():
-                    self.results[k] = v
-            else:
-                children = filter(
-                    bool,
-                    [x.attrib.get('name') for x in root.findall('node')])
-                children = [
-                    self._to_path(
-                        path_elements + self._to_path_elements(x))
-                    for x in sorted(children)]
-                for child in children:
-                    if child not in self.results:
-                        self._find_interfaces(child)
-
-    return _FindInterfaces()(path)
-
-
-class Association(dbus.service.Object):
-    def __init__(self, bus, path, endpoints):
-        super(Association, self).__init__(bus, path)
-        self.endpoints = endpoints
-
-    def __getattr__(self, name):
-        if name == 'properties':
-            return {
-                obmc.dbuslib.enums.OBMC_ASSOC_IFACE: {
-                    'endpoints': self.endpoints}}
-        return super(Association, self).__getattr__(name)
-
-    def emit_signal(self, old):
-        if old != self.endpoints:
-            self.PropertiesChanged(
-                obmc.dbuslib.enums.OBMC_ASSOC_IFACE,
-                {'endpoints': self.endpoints}, ['endpoints'])
-
-    def append(self, endpoints):
-        old = self.endpoints
-        self.endpoints = list(set(endpoints).union(self.endpoints))
-        self.emit_signal(old)
-
-    def remove(self, endpoints):
-        old = self.endpoints
-        self.endpoints = list(set(self.endpoints).difference(endpoints))
-        self.emit_signal(old)
-
-    @dbus.service.method(dbus.PROPERTIES_IFACE, 'ss', 'as')
-    def Get(self, interface_name, property_name):
-        if property_name != 'endpoints':
-            raise dbus.exceptions.DBusException(name=DBUS_UNKNOWN_PROPERTY)
-        return self.GetAll(interface_name)[property_name]
-
-    @dbus.service.method(dbus.PROPERTIES_IFACE, 's', 'a{sas}')
-    def GetAll(self, interface_name):
-        if interface_name != obmc.dbuslib.enums.OBMC_ASSOC_IFACE:
-            raise dbus.exceptions.DBusException(DBUS_UNKNOWN_INTERFACE)
-        return {'endpoints': self.endpoints}
-
-    @dbus.service.signal(
-        dbus.PROPERTIES_IFACE, signature='sa{sas}as')
-    def PropertiesChanged(
-            self, interface_name, changed_properties, invalidated_properties):
-        pass
-
-
-class Manager(obmc.dbuslib.bindings.DbusObjectManager):
-    def __init__(self, bus, path):
-        obmc.dbuslib.bindings.DbusObjectManager.__init__(self)
-        dbus.service.Object.__init__(self, bus, path)
-
-
-class ObjectMapper(dbus.service.Object):
-    def __init__(self, bus, path,
-                 name_match=obmc.utils.misc.org_dot_openbmc_match,
-                 intf_match=obmc.utils.misc.org_dot_openbmc_match):
-        super(ObjectMapper, self).__init__(bus, path)
-        self.cache = obmc.utils.pathtree.PathTree()
-        self.bus = bus
-        self.name_match = name_match
-        self.intf_match = intf_match
-        self.tag_match = obmc.utils.misc.ListMatch(['children', 'interface'])
-        self.service = None
-        self.index = {}
-        self.manager = Manager(bus, obmc.dbuslib.bindings.OBJ_PREFIX)
-        self.unique = bus.get_unique_name()
-        self.bus_map = {}
-
-        gobject.idle_add(self.discover)
-        self.bus.add_signal_receiver(
-            self.bus_handler,
-            dbus_interface=dbus.BUS_DAEMON_IFACE,
-            signal_name='NameOwnerChanged')
-        self.bus.add_signal_receiver(
-            self.interfaces_added_handler,
-            dbus_interface=dbus.BUS_DAEMON_IFACE + '.ObjectManager',
-            signal_name='InterfacesAdded',
-            sender_keyword='sender',
-            path_keyword='sender_path')
-        self.bus.add_signal_receiver(
-            self.interfaces_removed_handler,
-            dbus_interface=dbus.BUS_DAEMON_IFACE + '.ObjectManager',
-            signal_name='InterfacesRemoved',
-            sender_keyword='sender',
-            path_keyword='sender_path')
-        self.bus.add_signal_receiver(
-            self.properties_changed_handler,
-            dbus_interface=dbus.PROPERTIES_IFACE,
-            signal_name='PropertiesChanged',
-            path_keyword='path',
-            sender_keyword='sender')
-
-    def bus_match(self, owner):
-        # Ignore my own signals
-        return owner != obmc.mapper.MAPPER_NAME and \
-            self.name_match(owner)
-
-    def discovery_pending(self):
-        return not bool(self.service)
-
-    def cache_get(self, path):
-        cache_entry = self.cache.get(path, {})
-        if cache_entry is None:
-            # hide path elements without any interfaces
-            cache_entry = {}
-        return cache_entry
-
-    def add_new_objmgr(self, path, owner):
-        # We don't get a signal for the ObjectManager
-        # interface itself, so if we see a signal from
-        # make sure its in our cache, and add it if not.
-        cache_entry = self.cache_get(path)
-        old = self.interfaces_get(cache_entry, owner)
-        new = list(set(old).union([dbus.BUS_DAEMON_IFACE + '.ObjectManager']))
-        self.update_interfaces(path, owner, old, new)
-
-    def interfaces_added_handler(self, path, iprops, **kw):
-        path = str(path)
-        owner = str(kw['sender'])
-        interfaces = self.get_signal_interfaces(owner, iprops.iterkeys())
-        if interfaces:
-            self.add_new_objmgr(str(kw['sender_path']), owner)
-            cache_entry = self.cache_get(path)
-            old = self.interfaces_get(cache_entry, owner)
-            new = list(set(interfaces).union(old))
-            self.update_interfaces(path, owner, old, new)
-
-    def interfaces_removed_handler(self, path, interfaces, **kw):
-        path = str(path)
-        owner = str(kw['sender'])
-        interfaces = self.get_signal_interfaces(owner, interfaces)
-        if interfaces:
-            self.add_new_objmgr(str(kw['sender_path']), owner)
-            cache_entry = self.cache_get(path)
-            old = self.interfaces_get(cache_entry, owner)
-            new = list(set(old).difference(interfaces))
-            self.update_interfaces(path, owner, old, new)
-
-    def properties_changed_handler(self, interface, new, old, **kw):
-        owner = str(kw['sender'])
-        path = str(kw['path'])
-        interfaces = self.get_signal_interfaces(owner, [interface])
-        if not self.is_association(interfaces):
-            return
-        associations = new.get('associations', None)
-        if associations is None:
-            return
-
-        associations = [
-            (str(x), str(y), str(z)) for x, y, z in associations]
-        self.update_associations(
-            path, owner,
-            self.index_get_associations(path, [owner]),
-            associations)
-
-    def process_new_owner(self, owned_name, owner):
-        # unique name
-        try:
-            return self.discover([(owned_name, owner)])
-        except dbus.exceptions.DBusException, e:
-            if obmc.dbuslib.enums.DBUS_UNKNOWN_SERVICE \
-                    not in e.get_dbus_name():
-                raise
-
-    def process_old_owner(self, owned_name, owner):
-        if owner in self.bus_map:
-            del self.bus_map[owner]
-
-        for path, item in self.cache.dataitems():
-            old = self.interfaces_get(item, owner)
-            # remove all interfaces for this service
-            self.update_interfaces(
-                path, owner, old=old, new=[])
-
-    def bus_handler(self, owned_name, old, new):
-        valid = False
-        if not obmc.dbuslib.bindings.is_unique(owned_name):
-            valid = self.valid_signal(owned_name)
-
-        if valid and new:
-            self.process_new_owner(owned_name, new)
-        if valid and old:
-            self.process_old_owner(owned_name, old)
-
-    def update_interfaces(self, path, owner, old, new):
-        # __xx -> intf list
-        # xx -> intf dict
-        if isinstance(old, dict):
-            __old = old.keys()
-        else:
-            __old = old
-            old = {x: {} for x in old}
-        if isinstance(new, dict):
-            __new = new.keys()
-        else:
-            __new = new
-            new = {x: {} for x in new}
-
-        cache_entry = self.cache.setdefault(path, {})
-        created = [] if self.has_interfaces(cache_entry) else [path]
-        added = list(set(__new).difference(__old))
-        removed = list(set(__old).difference(__new))
-        self.interfaces_append(cache_entry, owner, added)
-        self.interfaces_remove(cache_entry, owner, removed, path)
-        destroyed = [] if self.has_interfaces(cache_entry) else [path]
-
-        # react to anything that requires association updates
-        new_assoc = []
-        old_assoc = []
-        if self.is_association(added):
-            new_assoc = self.dbus_get_associations(path, owner, new)
-        if self.is_association(removed):
-            old_assoc = self.index_get_associations(path, [owner])
-        self.update_associations(
-            path, owner, old_assoc, new_assoc, created, destroyed)
-
-    def add_items(self, owner, bus_items):
-        for path, items in bus_items.iteritems():
-            self.update_interfaces(path, str(owner), old=[], new=items)
-
-    def discover(self, owners=[]):
-        def match(iface):
-            return iface == dbus.BUS_DAEMON_IFACE + '.ObjectManager' or \
-                self.intf_match(iface)
-        if not owners:
-            owned_names = [
-                x for x in self.bus.list_names() if self.bus_match(x)]
-            owners = [self.bus.get_name_owner(x) for x in owned_names]
-            owners = zip(owned_names, owners)
-        for owned_name, o in owners:
-            self.add_items(
-                o,
-                find_dbus_interfaces(self.bus, o, '/', self.intf_match))
-            self.bus_map[o] = owned_name
-
-        if self.discovery_pending():
-            # add my object mananger instance
-            self.bus_map[self.unique] = obmc.mapper.MAPPER_NAME
-            self.add_items(
-                self.unique,
-                {obmc.dbuslib.bindings.OBJ_PREFIX:
-                    {'interfaces':
-                        [dbus.BUS_DAEMON_IFACE + '.ObjectManager']}})
-
-            print "ObjectMapper discovery complete..."
-            self.service = dbus.service.BusName(
-                obmc.mapper.MAPPER_NAME, self.bus)
-
-    def valid_signal(self, name):
-        if self.discovery_pending():
-            return False
-
-        if obmc.dbuslib.bindings.is_unique(name):
-            name = self.bus_map.get(name)
-
-        return name is not None and \
-            self.bus_match(name)
-
-    def get_signal_interfaces(self, owner, interfaces):
-        filtered = []
-        if self.valid_signal(owner):
-            filtered = [str(x) for x in interfaces if self.intf_match(x)]
-
-        return filtered
-
-    @staticmethod
-    def interfaces_get(item, owner, default=[]):
-        return item.get(owner, default)
-
-    @staticmethod
-    def interfaces_append(item, owner, append):
-        interfaces = item.setdefault(owner, [])
-        item[owner] = list(set(append).union(interfaces))
-
-    def interfaces_remove(self, item, owner, remove, path):
-        interfaces = item.get(owner, [])
-        item[owner] = list(set(interfaces).difference(remove))
-
-        if not item[owner]:
-            # remove the owner if there aren't any interfaces left
-            del item[owner]
-
-        if item:
-            # other owners remain
-            return
-
-        if self.cache.get_children(path):
-            # there are still references to this path
-            # from objects further down the tree.
-            # mark it for removal if that changes
-            self.cache.demote(path)
-        else:
-            # delete the entire path if everything is gone
-            del self.cache[path]
-
-    @dbus.service.method(obmc.mapper.MAPPER_IFACE, 's', 'a{sas}')
-    def GetObject(self, path):
-        o = self.cache_get(path)
-        if not o:
-            raise MapperNotFoundException(path)
-        return o
-
-    @dbus.service.method(obmc.mapper.MAPPER_IFACE, 'si', 'as')
-    def GetSubTreePaths(self, path, depth):
-        try:
-            return self.cache.iterkeys(path, depth)
-        except KeyError:
-            raise MapperNotFoundException(path)
-
-    @dbus.service.method(obmc.mapper.MAPPER_IFACE, 'si', 'a{sa{sas}}')
-    def GetSubTree(self, path, depth):
-        try:
-            return {x: y for x, y in self.cache.dataitems(path, depth)}
-        except KeyError:
-            raise MapperNotFoundException(path)
-
-    @staticmethod
-    def has_interfaces(item):
-        for owner in item.iterkeys():
-            if ObjectMapper.interfaces_get(item, owner):
-                return True
-        return False
-
-    @staticmethod
-    def is_association(interfaces):
-        return obmc.dbuslib.enums.OBMC_ASSOCIATIONS_IFACE in interfaces
-
-    def index_get(self, index, path, owners):
-        items = []
-        item = self.index.get(index, {})
-        item = item.get(path, {})
-        for o in owners:
-            items.extend(item.get(o, []))
-        return items
-
-    def index_append(self, index, path, owner, assoc):
-        item = self.index.setdefault(index, {})
-        item = item.setdefault(path, {})
-        item = item.setdefault(owner, [])
-        item.append(assoc)
-
-    def index_remove(self, index, path, owner, assoc):
-        index = self.index.get(index, {})
-        owners = index.get(path, {})
-        items = owners.get(owner, [])
-        if assoc in items:
-            items.remove(assoc)
-        if not items:
-            del owners[owner]
-        if not owners:
-            del index[path]
-
-    def dbus_get_associations(self, path, owner, obj):
-        iface = obmc.dbuslib.enums.OBMC_ASSOCIATIONS_IFACE
-        if 'associations' in obj[iface]:
-            return obj[iface]['associations']
-
-        # fallback to dbus
-        obj = self.bus.get_object(owner, path, introspect=False)
-        iface = dbus.Interface(obj, dbus.PROPERTIES_IFACE)
-        return [(str(f), str(r), str(e)) for f, r, e in iface.Get(
-            obmc.dbuslib.enums.OBMC_ASSOCIATIONS_IFACE,
-            'associations')]
-
-    def index_get_associations(self, path, owners=[], direction='forward'):
-        forward = 'forward' if direction == 'forward' else 'reverse'
-        reverse = 'reverse' if direction == 'forward' else 'forward'
-
-        associations = []
-        if not owners:
-            index = self.index.get(forward, {})
-            owners = index.get(path, {}).keys()
-
-        # f: forward
-        # r: reverse
-        for rassoc in self.index_get(forward, path, owners):
-            elements = rassoc.split('/')
-            rtype = ''.join(elements[-1:])
-            fendpoint = '/'.join(elements[:-1])
-            for fassoc in self.index_get(reverse, fendpoint, owners):
-                elements = fassoc.split('/')
-                ftype = ''.join(elements[-1:])
-                rendpoint = '/'.join(elements[:-1])
-                if rendpoint != path:
-                    continue
-                associations.append((ftype, rtype, fendpoint))
-
-        return associations
-
-    def update_association(self, path, removed, added):
-        iface = obmc.dbuslib.enums.OBMC_ASSOC_IFACE
-        create = [] if self.manager.get(path, False) else [iface]
-
-        if added and create:
-            self.manager.add(
-                path, Association(self.bus, path, added))
-        elif added:
-            self.manager.get(path).append(added)
-
-        obj = self.manager.get(path, None)
-        if obj and removed:
-            obj.remove(removed)
-
-        if obj and not obj.endpoints:
-            self.manager.remove(path)
-
-        delete = [] if self.manager.get(path, False) else [iface]
-
-        if create != delete:
-            self.update_interfaces(
-                path, self.unique, delete, create)
-
-    def update_associations(
-            self, path, owner, old, new, created=[], destroyed=[]):
-        added = list(set(new).difference(old))
-        removed = list(set(old).difference(new))
-        for forward, reverse, endpoint in added:
-            # update the index
-            forward_path = str(path + '/' + forward)
-            reverse_path = str(endpoint + '/' + reverse)
-            self.index_append(
-                'forward', path, owner, reverse_path)
-            self.index_append(
-                'reverse', endpoint, owner, forward_path)
-
-            # create the association if the endpoint exists
-            if not self.cache_get(endpoint):
-                continue
-
-            self.update_association(forward_path, [], [endpoint])
-            self.update_association(reverse_path, [], [path])
-
-        for forward, reverse, endpoint in removed:
-            # update the index
-            forward_path = str(path + '/' + forward)
-            reverse_path = str(endpoint + '/' + reverse)
-            self.index_remove(
-                'forward', path, owner, reverse_path)
-            self.index_remove(
-                'reverse', endpoint, owner, forward_path)
-
-            # destroy the association if it exists
-            self.update_association(forward_path, [endpoint], [])
-            self.update_association(reverse_path, [path], [])
-
-        # If the associations interface endpoint comes
-        # or goes create or destroy the appropriate
-        # associations
-        for path in created:
-            for forward, reverse, endpoint in \
-                    self.index_get_associations(path, direction='reverse'):
-                forward_path = str(path + '/' + forward)
-                reverse_path = str(endpoint + '/' + reverse)
-                self.update_association(forward_path, [], [endpoint])
-                self.update_association(reverse_path, [], [path])
-
-        for path in destroyed:
-            for forward, reverse, endpoint in \
-                    self.index_get_associations(path, direction='reverse'):
-                forward_path = str(path + '/' + forward)
-                reverse_path = str(endpoint + '/' + reverse)
-                self.update_association(forward_path, [endpoint], [])
-                self.update_association(reverse_path, [path], [])
-
-    @dbus.service.method(obmc.mapper.MAPPER_IFACE, 's', 'a{sa{sas}}')
-    def GetAncestors(self, path):
-        elements = filter(bool, path.split('/'))
-        paths = []
-        objs = {}
-        while elements:
-            elements.pop()
-            paths.append('/' + '/'.join(elements))
-        if path != '/':
-            paths.append('/')
-
-        for path in paths:
-            obj = self.cache_get(path)
-            if not obj:
-                continue
-            objs[path] = obj
-
-        return objs
-
+import sys
+import obmc.mapper.server
 
 if __name__ == '__main__':
-    dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
-    bus = dbus.SystemBus()
-    o = ObjectMapper(bus, obmc.mapper.MAPPER_PATH)
-    loop = gobject.MainLoop()
-
-    loop.run()
+    sys.exit(obmc.mapper.server.server_main())
