diff --git a/openstack/network/v2/router.py b/openstack/network/v2/router.py index 6abcac108..87edb27fc 100644 --- a/openstack/network/v2/router.py +++ b/openstack/network/v2/router.py @@ -75,6 +75,16 @@ class Router(resource.Resource, resource.TagMixin): #: Timestamp when the router was created. updated_at = resource.Body('updated_at') + def _put(self, session, url, body): + resp = session.put(url, json=body) + if not resp.ok: + resp_body = resp.json() + message = None + if 'NeutronError' in resp_body: + message = resp_body['NeutronError']['message'] + raise SDKException(message=message) + return resp + def add_interface(self, session, **body): """Add an internal interface to a logical router. @@ -83,9 +93,11 @@ class Router(resource.Resource, resource.TagMixin): :param dict body: The body requested to be updated on the router :returns: The body of the response as a dictionary. + + :raises: :class:`~openstack.exceptions.SDKException` on error. """ url = utils.urljoin(self.base_path, self.id, 'add_router_interface') - resp = session.put(url, json=body) + resp = self._put(session, url, body) return resp.json() def remove_interface(self, session, **body): @@ -96,21 +108,13 @@ class Router(resource.Resource, resource.TagMixin): :param dict body: The body requested to be updated on the router :returns: The body of the response as a dictionary. + + :raises: :class:`~openstack.exceptions.SDKException` on error. """ url = utils.urljoin(self.base_path, self.id, 'remove_router_interface') - resp = session.put(url, json=body) + resp = self._put(session, url, body) return resp.json() - def _put(self, session, url, body): - resp = session.put(url, json=body) - if not resp.ok: - resp_body = resp.json() - message = None - if 'NeutronError' in resp_body: - message = resp_body['NeutronError']['message'] - raise SDKException(message=message) - return resp - def add_extra_routes(self, session, body): """Add extra routes to a logical router. diff --git a/openstack/tests/unit/network/v2/test_router.py b/openstack/tests/unit/network/v2/test_router.py index 560d0ea42..a5cd05326 100644 --- a/openstack/tests/unit/network/v2/test_router.py +++ b/openstack/tests/unit/network/v2/test_router.py @@ -11,6 +11,9 @@ # under the License. import mock +import testtools + +from openstack.exceptions import SDKException from openstack.tests.unit import base from openstack.network.v2 import router @@ -173,6 +176,37 @@ class TestRouter(base.TestCase): sess.put.assert_called_with(url, json=body) + def test_add_interface_4xx(self): + # Neutron may return 4xx, we have to raise if that happens + sot = router.Router(**EXAMPLE) + response = mock.Mock() + msg = 'borked' + response.body = {'NeutronError': {'message': msg}} + response.json = mock.Mock(return_value=response.body) + response.ok = False + response.status_code = 409 + sess = mock.Mock() + sess.put = mock.Mock(return_value=response) + body = {'subnet_id': '3'} + with testtools.ExpectedException(SDKException, msg): + sot.add_interface(sess, **body) + + def test_remove_interface_4xx(self): + # Neutron may return 4xx for example if a router interface has + # extra routes referring to it as a nexthop + sot = router.Router(**EXAMPLE) + response = mock.Mock() + msg = 'borked' + response.body = {'NeutronError': {'message': msg}} + response.json = mock.Mock(return_value=response.body) + response.ok = False + response.status_code = 409 + sess = mock.Mock() + sess.put = mock.Mock(return_value=response) + body = {'subnet_id': '3'} + with testtools.ExpectedException(SDKException, msg): + sot.remove_interface(sess, **body) + def test_add_extra_routes(self): r = router.Router(**EXAMPLE) response = mock.Mock()