diff --git a/ironic_python_agent/backoff.py b/ironic_python_agent/backoff.py
deleted file mode 100644
index 80105b2e7..000000000
--- a/ironic_python_agent/backoff.py
+++ /dev/null
@@ -1,113 +0,0 @@
-# Copyright 2014 Rackspace, Inc.
-#
-# 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 random
-
-from oslo_service import loopingcall
-
-
-# TODO(JoshNang) move to oslo, i18n
-class LoopingCallTimeOut(Exception):
-    """Exception for a timed out LoopingCall.
-
-    The LoopingCall will raise this exception when a timeout is provided
-    and it is exceeded.
-    """
-    pass
-
-
-class BackOffLoopingCall(loopingcall.LoopingCallBase):
-    """Run a method in a loop with backoff on error.
-
-    The passed in function should return True (no error, return to
-    initial_interval),
-    False (error, start backing off), or raise LoopingCallDone(retvalue=None)
-    (quit looping, return retvalue if set).
-
-    When there is an error, the call will backoff on each failure. The
-    backoff will be equal to double the previous base interval times some
-    jitter. If a backoff would put it over the timeout, it halts immediately,
-    so the call will never take more than timeout, but may and likely will
-    take less time.
-
-    When the function return value is True or False, the interval will be
-    multiplied by a random jitter. If min_jitter or max_jitter is None,
-    there will be no jitter (jitter=1). If min_jitter is below 0.5, the code
-    may not backoff and may increase its retry rate.
-
-    If func constantly returns True, this function will not return.
-
-    To run a func and wait for a call to finish (by raising a LoopingCallDone):
-
-        timer = BackOffLoopingCall(func)
-        response = timer.start().wait()
-
-    :param initial_delay: delay before first running of function
-    :param starting_interval: initial interval in seconds between calls to
-                              function. When an error occurs and then a
-                              success, the interval is returned to
-                              starting_interval
-    :param timeout: time in seconds before a LoopingCallTimeout is raised.
-                    The call will never take longer than timeout, but may quit
-                    before timeout.
-    :param max_interval: The maximum interval between calls during errors
-    :param jitter: Used to vary when calls are actually run to avoid group of
-                   calls all coming at the exact same time. Uses
-                   random.gauss(jitter, 0.1), with jitter as the mean for the
-                   distribution. If set below .5, it can cause the calls to
-                   come more rapidly after each failure.
-    :raises: LoopingCallTimeout if time spent doing error retries would exceed
-             timeout.
-    """
-
-    _RNG = random.SystemRandom()
-    _KIND = 'Dynamic backoff interval looping call'
-    _RUN_ONLY_ONE_MESSAGE = ("A dynamic backoff interval looping call can"
-                             " only run one function at a time")
-
-    def __init__(self, f=None, *args, **kw):
-        super(BackOffLoopingCall, self).__init__(f=f, *args, **kw)
-        self._error_time = 0
-        self._interval = 1
-
-    def start(self, initial_delay=None, starting_interval=1, timeout=300,
-              max_interval=300, jitter=0.75):
-        if self._thread is not None:
-            raise RuntimeError(self._RUN_ONLY_ONE_MESSAGE)
-
-        # Reset any prior state.
-        self._error_time = 0
-        self._interval = starting_interval
-
-        def _idle_for(success, _elapsed):
-            random_jitter = self._RNG.gauss(jitter, 0.1)
-            if success:
-                # Reset error state now that it didn't error...
-                self._interval = starting_interval
-                self._error_time = 0
-                return self._interval * random_jitter
-            else:
-                # Perform backoff
-                self._interval = idle = min(
-                    self._interval * 2 * random_jitter, max_interval)
-                # Don't go over timeout, end early if necessary. If
-                # timeout is 0, keep going.
-                if timeout > 0 and self._error_time + idle > timeout:
-                    raise LoopingCallTimeOut(
-                        'Looping call timed out after %.02f seconds'
-                        % self._error_time)
-                self._error_time += idle
-                return idle
-
-        return self._start(_idle_for, initial_delay=initial_delay)
diff --git a/ironic_python_agent/ironic_api_client.py b/ironic_python_agent/ironic_api_client.py
index 5816b95af..4be6849ec 100644
--- a/ironic_python_agent/ironic_api_client.py
+++ b/ironic_python_agent/ironic_api_client.py
@@ -18,7 +18,6 @@ from oslo_log import log
 from oslo_service import loopingcall
 import requests
 
-from ironic_python_agent import backoff
 from ironic_python_agent import encoding
 from ironic_python_agent import errors
 
@@ -80,14 +79,14 @@ class APIClient(object):
 
     def lookup_node(self, hardware_info, timeout, starting_interval,
                     node_uuid=None):
-        timer = backoff.BackOffLoopingCall(
+        timer = loopingcall.BackOffLoopingCall(
             self._do_lookup,
             hardware_info=hardware_info,
             node_uuid=node_uuid)
         try:
             node_content = timer.start(starting_interval=starting_interval,
                                        timeout=timeout).wait()
-        except backoff.LoopingCallTimeOut:
+        except loopingcall.LoopingCallTimeOut:
             raise errors.LookupNodeError('Could not look up node info. Check '
                                          'logs for details.')
         return node_content
diff --git a/ironic_python_agent/tests/unit/test_backoff.py b/ironic_python_agent/tests/unit/test_backoff.py
deleted file mode 100644
index bed034ca8..000000000
--- a/ironic_python_agent/tests/unit/test_backoff.py
+++ /dev/null
@@ -1,100 +0,0 @@
-# Copyright 2014 Rackspace, Inc.
-#
-# 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 unittest
-
-import mock
-from oslo_service import loopingcall
-
-from ironic_python_agent import backoff
-
-
-class TestBackOffLoopingCall(unittest.TestCase):
-    @mock.patch('random.SystemRandom.gauss')
-    @mock.patch('eventlet.greenthread.sleep')
-    def test_exponential_backoff(self, sleep_mock, random_mock):
-        def false():
-            return False
-
-        random_mock.return_value = .8
-
-        self.assertRaises(backoff.LoopingCallTimeOut,
-                          backoff.BackOffLoopingCall(false).start()
-                          .wait)
-
-        expected_times = [mock.call(1.6000000000000001),
-                          mock.call(2.5600000000000005),
-                          mock.call(4.096000000000001),
-                          mock.call(6.5536000000000021),
-                          mock.call(10.485760000000004),
-                          mock.call(16.777216000000006),
-                          mock.call(26.843545600000013),
-                          mock.call(42.949672960000022),
-                          mock.call(68.719476736000033),
-                          mock.call(109.95116277760006)]
-        self.assertEqual(expected_times, sleep_mock.call_args_list)
-
-    @mock.patch('random.SystemRandom.gauss')
-    @mock.patch('eventlet.greenthread.sleep')
-    def test_no_backoff(self, sleep_mock, random_mock):
-        random_mock.return_value = 1
-        func = mock.Mock()
-        # func.side_effect
-        func.side_effect = [True, True, True, loopingcall.LoopingCallDone(
-            retvalue='return value')]
-
-        retvalue = backoff.BackOffLoopingCall(func).start().wait()
-
-        expected_times = [mock.call(1), mock.call(1), mock.call(1)]
-        self.assertEqual(expected_times, sleep_mock.call_args_list)
-        self.assertTrue(retvalue, 'return value')
-
-    @mock.patch('random.SystemRandom.gauss')
-    @mock.patch('eventlet.greenthread.sleep')
-    def test_no_sleep(self, sleep_mock, random_mock):
-        # Any call that executes properly the first time shouldn't sleep
-        random_mock.return_value = 1
-        func = mock.Mock()
-        # func.side_effect
-        func.side_effect = loopingcall.LoopingCallDone(retvalue='return value')
-
-        retvalue = backoff.BackOffLoopingCall(func).start().wait()
-        self.assertFalse(sleep_mock.called)
-        self.assertTrue(retvalue, 'return value')
-
-    @mock.patch('random.SystemRandom.gauss')
-    @mock.patch('eventlet.greenthread.sleep')
-    def test_max_interval(self, sleep_mock, random_mock):
-        def false():
-            return False
-
-        random_mock.return_value = .8
-
-        self.assertRaises(backoff.LoopingCallTimeOut,
-                          backoff.BackOffLoopingCall(false).start(
-                              max_interval=60)
-                          .wait)
-
-        expected_times = [mock.call(1.6000000000000001),
-                          mock.call(2.5600000000000005),
-                          mock.call(4.096000000000001),
-                          mock.call(6.5536000000000021),
-                          mock.call(10.485760000000004),
-                          mock.call(16.777216000000006),
-                          mock.call(26.843545600000013),
-                          mock.call(42.949672960000022),
-                          mock.call(60),
-                          mock.call(60),
-                          mock.call(60)]
-        self.assertEqual(expected_times, sleep_mock.call_args_list)
diff --git a/ironic_python_agent/tests/unit/test_ironic_api_client.py b/ironic_python_agent/tests/unit/test_ironic_api_client.py
index f860c95fb..bad882d69 100644
--- a/ironic_python_agent/tests/unit/test_ironic_api_client.py
+++ b/ironic_python_agent/tests/unit/test_ironic_api_client.py
@@ -18,7 +18,6 @@ import mock
 from oslo_service import loopingcall
 from oslotest import base as test_base
 
-from ironic_python_agent import backoff
 from ironic_python_agent import errors
 from ironic_python_agent import hardware
 from ironic_python_agent import ironic_api_client
@@ -111,7 +110,7 @@ class TestBaseIronicPythonAgent(test_base.BaseTestCase):
     @mock.patch('eventlet.greenthread.sleep')
     @mock.patch('ironic_python_agent.ironic_api_client.APIClient._do_lookup')
     def test_lookup_timeout(self, lookup_mock, sleep_mock):
-        lookup_mock.side_effect = backoff.LoopingCallTimeOut()
+        lookup_mock.side_effect = loopingcall.LoopingCallTimeOut()
         self.assertRaises(errors.LookupNodeError,
                           self.api_client.lookup_node,
                           hardware_info=self.hardware_info,