Merge "Fix NetworkInUse when deleting RS Cloud::Network"

This commit is contained in:
Jenkins 2014-12-23 20:43:06 +00:00 committed by Gerrit Code Review
commit c16f539c53
2 changed files with 53 additions and 15 deletions

View File

@ -23,6 +23,7 @@ from heat.engine import resource
from heat.openstack.common import log as logging from heat.openstack.common import log as logging
try: try:
from pyrax.exceptions import NetworkInUse # noqa
from pyrax.exceptions import NotFound # noqa from pyrax.exceptions import NotFound # noqa
PYRAX_INSTALLED = True PYRAX_INSTALLED = True
except ImportError: except ImportError:
@ -31,13 +32,15 @@ except ImportError:
class NotFound(Exception): class NotFound(Exception):
"""Dummy pyrax exception - only used for testing.""" """Dummy pyrax exception - only used for testing."""
class NetworkInUse(Exception):
"""Dummy pyrax exception - only used for testing."""
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
class CloudNetwork(resource.Resource): class CloudNetwork(resource.Resource):
""" """A resource for creating Rackspace Cloud Networks.
A resource for creating Rackspace Cloud Networks.
See http://www.rackspace.com/cloud/networks/ for service See http://www.rackspace.com/cloud/networks/ for service
documentation. documentation.
@ -106,20 +109,40 @@ class CloudNetwork(resource.Resource):
self.cloud_networks().get(self.resource_id) self.cloud_networks().get(self.resource_id)
def handle_delete(self): def handle_delete(self):
net = self.network() '''Delete cloud network.
if net:
net.delete()
return net
def check_delete_complete(self, network): Cloud Network doesn't have a status attribute, and there is a non-zero
if network: window between the deletion of a server and the acknowledgement from
the cloud network that it's no longer in use, so it needs some way to
keep track of when the delete call was successfully issued.
'''
network_info = {
'delete_issued': False,
'network': self.network(),
}
return network_info
def check_delete_complete(self, network_info):
network = network_info['network']
if not network:
return True
if not network_info['delete_issued']:
try: try:
network.get() network.delete()
except NotFound: except NetworkInUse:
return True LOG.warn("Network '%s' still in use." % network.id)
else: else:
return False network_info['delete_issued'] = True
return True return False
try:
network.get()
except NotFound:
return True
return False
def validate(self): def validate(self):
super(CloudNetwork, self).validate() super(CloudNetwork, self).validate()

View File

@ -26,7 +26,7 @@ from heat.tests import utils
from ..resources import cloudnetworks # noqa from ..resources import cloudnetworks # noqa
try: try:
from pyrax.exceptions import NotFound from pyrax.exceptions import NotFound # noqa
except ImportError: except ImportError:
from ..resources.cloudnetworks import NotFound # noqa from ..resources.cloudnetworks import NotFound # noqa
@ -144,10 +144,25 @@ class CloudNetworkTest(common.HeatTestCase):
exc = self.assertRaises(NotFound, self.fake_cnw.get, res_id) exc = self.assertRaises(NotFound, self.fake_cnw.get, res_id)
self.assertIn(res_id, six.text_type(exc)) self.assertIn(res_id, six.text_type(exc))
def test_delete_in_use(self, mock_client):
self._setup_stack(mock_client)
res = self.stack['cnw']
fake_network = res.network()
fake_network.delete = mock.Mock()
fake_network.delete.side_effect = [cloudnetworks.NetworkInUse(), True]
fake_network.get = mock.Mock(side_effect=cloudnetworks.NotFound())
scheduler.TaskRunner(res.delete)()
self.assertEqual((res.DELETE, res.COMPLETE), res.state)
def test_delete_not_complete(self, mock_client): def test_delete_not_complete(self, mock_client):
self._setup_stack(mock_client) self._setup_stack(mock_client)
res = self.stack['cnw'] res = self.stack['cnw']
self.assertFalse(res.check_delete_complete(res.network())) fake_network = res.network()
fake_network.get = mock.Mock()
task = res.handle_delete()
self.assertFalse(res.check_delete_complete(task))
def test_delete_not_found(self, mock_client): def test_delete_not_found(self, mock_client):
self._setup_stack(mock_client) self._setup_stack(mock_client)