diff --git a/novaclient/__init__.py b/novaclient/__init__.py
index 7980a7b3f..727328f47 100644
--- a/novaclient/__init__.py
+++ b/novaclient/__init__.py
@@ -25,4 +25,4 @@ API_MIN_VERSION = api_versions.APIVersion("2.1")
 # when client supported the max version, and bumped sequentially, otherwise
 # the client may break due to server side new version may include some
 # backward incompatible change.
-API_MAX_VERSION = api_versions.APIVersion("2.28")
+API_MAX_VERSION = api_versions.APIVersion("2.29")
diff --git a/novaclient/tests/unit/v2/fakes.py b/novaclient/tests/unit/v2/fakes.py
index bc4c6e638..13681e02a 100644
--- a/novaclient/tests/unit/v2/fakes.py
+++ b/novaclient/tests/unit/v2/fakes.py
@@ -753,7 +753,11 @@ class FakeHTTPClient(base_client.HTTPClient):
                 keys.remove('adminPass')
             if 'host' in keys:
                 keys.remove('host')
-            assert set(keys) == set(['onSharedStorage'])
+            if 'onSharedStorage' in keys:
+                keys.remove('onSharedStorage')
+            if 'force' in keys:
+                keys.remove('force')
+            assert set(keys) == set()
         else:
             raise AssertionError("Unexpected server action: %s" % action)
         _headers.update(FAKE_RESPONSE_HEADERS)
diff --git a/novaclient/tests/unit/v2/test_servers.py b/novaclient/tests/unit/v2/test_servers.py
index 8d451af25..70b06f220 100644
--- a/novaclient/tests/unit/v2/test_servers.py
+++ b/novaclient/tests/unit/v2/test_servers.py
@@ -1179,3 +1179,19 @@ class ServersV226Test(ServersV225Test):
         ret = s.set_tags(['tag1', 'tag2'])
         self.assert_request_id(ret, fakes.FAKE_REQUEST_ID_LIST)
         self.assert_called('PUT', '/servers/1234/tags')
+
+
+class ServersV229Test(ServersV226Test):
+    def setUp(self):
+        super(ServersV229Test, self).setUp()
+        self.cs.api_version = api_versions.APIVersion("2.29")
+
+    def test_evacuate(self):
+        s = self.cs.servers.get(1234)
+        s.evacuate('fake_target_host')
+        self.assert_called('POST', '/servers/1234/action',
+                           {'evacuate': {'host': 'fake_target_host'}})
+        self.cs.servers.evacuate(s, 'fake_target_host', force=True)
+        self.assert_called('POST', '/servers/1234/action',
+                           {'evacuate': {'host': 'fake_target_host',
+                                         'force': True}})
diff --git a/novaclient/tests/unit/v2/test_shell.py b/novaclient/tests/unit/v2/test_shell.py
index a36ab82fe..d4a552698 100644
--- a/novaclient/tests/unit/v2/test_shell.py
+++ b/novaclient/tests/unit/v2/test_shell.py
@@ -2009,6 +2009,23 @@ class ShellTest(utils.TestCase):
                            {'evacuate': {'host': 'target_hyper',
                                          'onSharedStorage': False}}, pos=4)
 
+    def test_host_evacuate_v2_29(self):
+        self.run_command('host-evacuate hyper --target target_hyper --force',
+                         api_version='2.29')
+        self.assert_called('GET', '/os-hypervisors/hyper/servers', pos=0)
+        self.assert_called('POST', '/servers/uuid1/action',
+                           {'evacuate': {'host': 'target_hyper', 'force': True}
+                            }, pos=1)
+        self.assert_called('POST', '/servers/uuid2/action',
+                           {'evacuate': {'host': 'target_hyper', 'force': True}
+                            }, pos=2)
+        self.assert_called('POST', '/servers/uuid3/action',
+                           {'evacuate': {'host': 'target_hyper', 'force': True}
+                            }, pos=3)
+        self.assert_called('POST', '/servers/uuid4/action',
+                           {'evacuate': {'host': 'target_hyper', 'force': True}
+                            }, pos=4)
+
     def test_host_evacuate_with_shared_storage(self):
         self.run_command(
             'host-evacuate --on-shared-storage hyper --target target_hyper')
@@ -2410,6 +2427,21 @@ class ShellTest(utils.TestCase):
                            {'evacuate': {'host': 'new_host',
                                          'onSharedStorage': True}})
 
+    def test_evacuate_v2_29(self):
+        self.run_command('evacuate sample-server new_host', api_version="2.29")
+        self.assert_called('POST', '/servers/1234/action',
+                           {'evacuate': {'host': 'new_host'}})
+        self.run_command('evacuate sample-server new_host '
+                         '--password NewAdminPass', api_version="2.29")
+        self.assert_called('POST', '/servers/1234/action',
+                           {'evacuate': {'host': 'new_host',
+                                         'adminPass': 'NewAdminPass'}})
+        self.run_command('evacuate --force sample-server new_host',
+                         api_version="2.29")
+        self.assert_called('POST', '/servers/1234/action',
+                           {'evacuate': {'host': 'new_host',
+                                         'force': True}})
+
     def test_evacuate_with_no_target_host(self):
         self.run_command('evacuate sample-server')
         self.assert_called('POST', '/servers/1234/action',
diff --git a/novaclient/v2/contrib/host_evacuate.py b/novaclient/v2/contrib/host_evacuate.py
index 2a0335d30..22055656b 100644
--- a/novaclient/v2/contrib/host_evacuate.py
+++ b/novaclient/v2/contrib/host_evacuate.py
@@ -27,12 +27,17 @@ def _server_evacuate(cs, server, args):
     success = True
     error_message = ""
     try:
-        on_shared_storage = getattr(args, 'on_shared_storage', None)
-        if api_versions.APIVersion("2.14") <= cs.api_version:
-            # if microversion >= 2.14
+        if api_versions.APIVersion("2.29") <= cs.api_version:
+            # if microversion >= 2.29
+            force = getattr(args, 'force', None)
+            cs.servers.evacuate(server=server['uuid'], host=args.target_host,
+                                force=force)
+        elif api_versions.APIVersion("2.14") <= cs.api_version:
+            # if microversion 2.14 - 2.28
             cs.servers.evacuate(server=server['uuid'], host=args.target_host)
         else:
             # else microversion 2.0 - 2.13
+            on_shared_storage = getattr(args, 'on_shared_storage', None)
             cs.servers.evacuate(server=server['uuid'],
                                 host=args.target_host,
                                 on_shared_storage=on_shared_storage)
@@ -60,6 +65,13 @@ def _server_evacuate(cs, server, args):
     help=_('Specifies whether all instances files are on shared storage'),
     start_version='2.0',
     end_version='2.13')
+@utils.arg(
+    '--force',
+    dest='force',
+    action='store_true',
+    default=False,
+    help=_('Force to not verify the scheduler if a host is provided.'),
+    start_version='2.29')
 def do_host_evacuate(cs, args):
     """Evacuate all instances from failed host."""
     hypervisors = cs.hypervisors.search(args.host, servers=True)
diff --git a/novaclient/v2/servers.py b/novaclient/v2/servers.py
index 39adeaba4..fd672af20 100644
--- a/novaclient/v2/servers.py
+++ b/novaclient/v2/servers.py
@@ -499,7 +499,7 @@ class Server(base.Resource):
         """
         return self.manager.evacuate(self, host, on_shared_storage, password)
 
-    @api_versions.wraps("2.14")
+    @api_versions.wraps("2.14", "2.28")
     def evacuate(self, host=None, password=None):
         """
         Evacuate an instance from failed host to specified host.
@@ -511,6 +511,19 @@ class Server(base.Resource):
         """
         return self.manager.evacuate(self, host, password)
 
+    @api_versions.wraps("2.29")
+    def evacuate(self, host=None, password=None, force=None):
+        """
+        Evacuate an instance from failed host to specified host.
+
+        :param host: Name of the target host
+        :param password: string to set as admin password on the evacuated
+                         server.
+        :param force: forces to bypass the scheduler if host is provided.
+        :returns: An instance of novaclient.base.TupleWithMeta
+        """
+        return self.manager.evacuate(self, host, password, force)
+
     def interface_list(self):
         """
         List interfaces attached to an instance.
@@ -1658,7 +1671,7 @@ class ServerManager(base.BootingManagerWithFind):
                                                        body)
         return base.TupleWithMeta((resp, body), resp)
 
-    @api_versions.wraps("2.14")
+    @api_versions.wraps("2.14", "2.28")
     def evacuate(self, server, host=None, password=None):
         """
         Evacuate a server instance.
@@ -1680,6 +1693,32 @@ class ServerManager(base.BootingManagerWithFind):
                                                        body)
         return base.TupleWithMeta((resp, body), resp)
 
+    @api_versions.wraps("2.29")
+    def evacuate(self, server, host=None, password=None, force=None):
+        """
+        Evacuate a server instance.
+
+        :param server: The :class:`Server` (or its ID) to share onto.
+        :param host: Name of the target host.
+        :param password: string to set as password on the evacuated server.
+        :param force: forces to bypass the scheduler if host is provided.
+        :returns: An instance of novaclient.base.TupleWithMeta
+        """
+
+        body = {}
+        if host is not None:
+            body['host'] = host
+
+        if password is not None:
+            body['adminPass'] = password
+
+        if force:
+            body['force'] = force
+
+        resp, body = self._action_return_resp_and_body('evacuate', server,
+                                                       body)
+        return base.TupleWithMeta((resp, body), resp)
+
     def interface_list(self, server):
         """
         List attached network interfaces
diff --git a/novaclient/v2/shell.py b/novaclient/v2/shell.py
index 042b35435..7e1241640 100644
--- a/novaclient/v2/shell.py
+++ b/novaclient/v2/shell.py
@@ -4688,12 +4688,26 @@ def do_quota_class_update(cs, args):
     help=_('Specifies whether server files are located on shared storage.'),
     start_version='2.0',
     end_version='2.13')
+@utils.arg(
+    '--force',
+    dest='force',
+    action='store_true',
+    default=False,
+    help=_('Force to not verify the scheduler if a host is provided.'),
+    start_version='2.29')
 def do_evacuate(cs, args):
     """Evacuate server from failed host."""
 
     server = _find_server(cs, args.server)
     on_shared_storage = getattr(args, 'on_shared_storage', None)
-    res = server.evacuate(args.host, on_shared_storage, args.password)[1]
+    force = getattr(args, 'force', None)
+    update_kwargs = {}
+    if on_shared_storage is not None:
+        update_kwargs['on_shared_storage'] = on_shared_storage
+    if force:
+        update_kwargs['force'] = force
+    res = server.evacuate(host=args.host, password=args.password,
+                          **update_kwargs)[1]
     if isinstance(res, dict):
         utils.print_dict(res)