diff --git a/openstack/compute/v2/_proxy.py b/openstack/compute/v2/_proxy.py index 3d2d2fc6f..4996043aa 100644 --- a/openstack/compute/v2/_proxy.py +++ b/openstack/compute/v2/_proxy.py @@ -322,7 +322,7 @@ class Proxy(proxy2.BaseProxy): """ return self._create(_server.Server, **attrs) - def delete_server(self, server, ignore_missing=True): + def delete_server(self, server, ignore_missing=True, force=False): """Delete a server :param server: The value can be either the ID of a server or a @@ -331,11 +331,17 @@ class Proxy(proxy2.BaseProxy): :class:`~openstack.exceptions.ResourceNotFound` will be raised when the server does not exist. When set to ``True``, no exception will be set when - attempting to delete a nonexistent server. + attempting to delete a nonexistent server + :param bool force: When set to ``True``, the server deletion will be + forced immediatly. :returns: ``None`` """ - self._delete(_server.Server, server, ignore_missing=ignore_missing) + if force: + server = self._get_resource(_server.Server, server) + server.force_delete(self.session) + else: + self._delete(_server.Server, server, ignore_missing=ignore_missing) def find_server(self, name_or_id, ignore_missing=True): """Find a single server diff --git a/openstack/compute/v2/server.py b/openstack/compute/v2/server.py index 541034446..d6baba518 100644 --- a/openstack/compute/v2/server.py +++ b/openstack/compute/v2/server.py @@ -136,6 +136,11 @@ class Server(resource2.Resource, metadata.MetadataMixin): body = {'reboot': {'type': reboot_type}} self._action(session, body) + def force_delete(self, session): + """Force delete a server.""" + body = {'forceDelete': None} + self._action(session, body) + def rebuild(self, session, name, admin_password, preserve_ephemeral=False, image=None, access_ipv4=None, access_ipv6=None, diff --git a/openstack/tests/unit/compute/v2/test_proxy.py b/openstack/tests/unit/compute/v2/test_proxy.py index 177943321..16e1189fe 100644 --- a/openstack/tests/unit/compute/v2/test_proxy.py +++ b/openstack/tests/unit/compute/v2/test_proxy.py @@ -207,6 +207,11 @@ class TestComputeProxy(test_proxy_base2.TestProxyBase): def test_server_delete_ignore(self): self.verify_delete(self.proxy.delete_server, server.Server, True) + def test_server_force_delete(self): + self._verify("openstack.compute.v2.server.Server.force_delete", + self.proxy.delete_server, + method_args=["value", False, True]) + def test_server_find(self): self.verify_find(self.proxy.find_server, server.Server) diff --git a/openstack/tests/unit/compute/v2/test_server.py b/openstack/tests/unit/compute/v2/test_server.py index 7330d79b1..0273ed02f 100644 --- a/openstack/tests/unit/compute/v2/test_server.py +++ b/openstack/tests/unit/compute/v2/test_server.py @@ -153,6 +153,17 @@ class TestServer(testtools.TestCase): self.sess.post.assert_called_with( url, endpoint_filter=sot.service, json=body, headers=headers) + def test_force_delete(self): + sot = server.Server(**EXAMPLE) + + self.assertIsNone(sot.force_delete(self.sess)) + + url = 'servers/IDENTIFIER/action' + body = {'forceDelete': None} + headers = {'Accept': ''} + self.sess.post.assert_called_with( + url, endpoint_filter=sot.service, json=body, headers=headers) + def test_rebuild(self): sot = server.Server(**EXAMPLE) # Let the translate pass through, that portion is tested elsewhere