diff --git a/kuryr/controllers.py b/kuryr/controllers.py index c7b5c92e..26b05ff0 100644 --- a/kuryr/controllers.py +++ b/kuryr/controllers.py @@ -623,4 +623,19 @@ def network_driver_join(): @app.route('/NetworkDriver.Leave', methods=['POST']) def network_driver_leave(): + """Unbinds a Neutron Port to a network interface attached to a container. + + This function takes the following JSON data and delete the veth pair + corresponding to the given info. :: + + { + "NetworkID": string, + "EndpointID": string + } + """ + json_data = flask.request.get_json(force=True) + app.logger.debug("Received JSON data {0} for /NetworkDriver.DeleteEndpoint" + .format(json_data)) + jsonschema.validate(json_data, schemata.LEAVE_SCHEMA) + return flask.jsonify(constants.SCHEMA['SUCCESS']) diff --git a/kuryr/schemata/__init__.py b/kuryr/schemata/__init__.py index 52851af9..d687a586 100644 --- a/kuryr/schemata/__init__.py +++ b/kuryr/schemata/__init__.py @@ -13,6 +13,7 @@ from kuryr.schemata import endpoint_create from kuryr.schemata import endpoint_delete from kuryr.schemata import join +from kuryr.schemata import leave from kuryr.schemata import network_create from kuryr.schemata import network_delete @@ -21,5 +22,6 @@ from kuryr.schemata import network_delete ENDPOINT_CREATE_SCHEMA = endpoint_create.ENDPOINT_CREATE_SCHEMA ENDPOINT_DELETE_SCHEMA = endpoint_delete.ENDPOINT_DELETE_SCHEMA JOIN_SCHEMA = join.JOIN_SCHEMA +LEAVE_SCHEMA = leave.LEAVE_SCHEMA NETWORK_CREATE_SCHEMA = network_create.NETWORK_CREATE_SCHEMA NETWORK_DELETE_SCHEMA = network_delete.NETWORK_DELETE_SCHEMA diff --git a/kuryr/schemata/leave.py b/kuryr/schemata/leave.py new file mode 100644 index 00000000..c5978aa8 --- /dev/null +++ b/kuryr/schemata/leave.py @@ -0,0 +1,24 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +from kuryr.schemata import endpoint_delete + + +LEAVE_SCHEMA = endpoint_delete.ENDPOINT_DELETE_SCHEMA +LEAVE_SCHEMA[u'title'] = u'Leave endpoint' +LEAVE_SCHEMA[u'links'] = [{ + u'method': u'POST', + u'href': u'/NetworkDriver.Leave', + u'description': u'Unbinds the endpoint from the container.', + u'rel': u'self', + u'title': u'Leave' +}] diff --git a/kuryr/tests/test_kuryr.py b/kuryr/tests/test_kuryr.py index 864126fa..4f7a4957 100644 --- a/kuryr/tests/test_kuryr.py +++ b/kuryr/tests/test_kuryr.py @@ -43,9 +43,8 @@ class TestKuryr(base.TestKuryrBase): - POST /NetworkDriver.Leave """ @ddt.data(('/Plugin.Activate', constants.SCHEMA['PLUGIN_ACTIVATE']), - ('/NetworkDriver.EndpointOperInfo', - constants.SCHEMA['ENDPOINT_OPER_INFO']), - ('/NetworkDriver.Leave', constants.SCHEMA['SUCCESS'])) + ('/NetworkDriver.EndpointOperInfo', + constants.SCHEMA['ENDPOINT_OPER_INFO'])) @ddt.unpack def test_remote_driver_endpoint(self, endpoint, expected): response = self.app.post(endpoint) diff --git a/kuryr/tests/test_leave.py b/kuryr/tests/test_leave.py new file mode 100644 index 00000000..582c9fb8 --- /dev/null +++ b/kuryr/tests/test_leave.py @@ -0,0 +1,50 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +import hashlib +import random + +from oslo_serialization import jsonutils +from werkzeug import exceptions as w_exceptions + +from kuryr.tests import base + + +class TestKuryrLeaveFailures(base.TestKuryrFailures): + """Unit tests for the failures for unbinding a Neutron port. + """ + def _invoke_leave_request(self, docker_network_id, + docker_endpoint_id): + data = { + 'NetworkID': docker_network_id, + 'EndpointID': docker_endpoint_id, + } + response = self.app.post('/NetworkDriver.Leave', + content_type='application/json', + data=jsonutils.dumps(data)) + + return response + + def test_leave_bad_request(self): + fake_docker_network_id = hashlib.sha256( + str(random.getrandbits(256))).hexdigest() + invalid_docker_endpoint_id = 'id-should-be-hexdigits' + + response = self._invoke_leave_request( + fake_docker_network_id, invalid_docker_endpoint_id) + + self.assertEqual(w_exceptions.BadRequest.code, response.status_code) + decoded_json = jsonutils.loads(response.data) + self.assertTrue('Err' in decoded_json) + # TODO(tfukushima): Add the better error message validation. + self.assertTrue(invalid_docker_endpoint_id in decoded_json['Err']) + self.assertTrue('EndpointID' in decoded_json['Err'])