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() Cloud Network doesn't have a status attribute, and there is a non-zero
return net 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:
network.delete()
except NetworkInUse:
LOG.warn("Network '%s' still in use." % network.id)
else:
network_info['delete_issued'] = True
return False
def check_delete_complete(self, network):
if network:
try: try:
network.get() network.get()
except NotFound: except NotFound:
return True return True
else:
return False return False
return True
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)