From 86cf8b53ee0f59fe213d18949c00cfb6c7287c86 Mon Sep 17 00:00:00 2001 From: Alessandro Pilotti Date: Wed, 1 May 2013 07:14:59 +0300 Subject: [PATCH] Adds POST method support in the metadata service Fixes bug: #1092311 The password generation feature introduced in Grizzly requires POST support in the metadata service. Support has been added to both the metadata agent and namespace proxy. Tests have been added and updated accordingly. Change-Id: If7ef6bede1775ad682822cb868518ec732b90805 --- quantum/agent/metadata/agent.py | 5 +- quantum/agent/metadata/namespace_proxy.py | 11 ++- quantum/tests/unit/test_metadata_agent.py | 19 +++++- .../unit/test_metadata_namespace_proxy.py | 68 +++++++++++++++++-- 4 files changed, 90 insertions(+), 13 deletions(-) diff --git a/quantum/agent/metadata/agent.py b/quantum/agent/metadata/agent.py index d04231b26..9e37251d1 100644 --- a/quantum/agent/metadata/agent.py +++ b/quantum/agent/metadata/agent.py @@ -139,7 +139,8 @@ class MetadataProxyHandler(object): '')) h = httplib2.Http() - resp, content = h.request(url, headers=headers) + resp, content = h.request(url, method=req.method, headers=headers, + body=req.body) if resp.status == 200: LOG.debug(str(resp)) @@ -153,6 +154,8 @@ class MetadataProxyHandler(object): return webob.exc.HTTPForbidden() elif resp.status == 404: return webob.exc.HTTPNotFound() + elif resp.status == 409: + return webob.exc.HTTPConflict() elif resp.status == 500: msg = _( 'Remote metadata server experienced an internal server error.' diff --git a/quantum/agent/metadata/namespace_proxy.py b/quantum/agent/metadata/namespace_proxy.py index 0a9a317be..f6282e8b4 100644 --- a/quantum/agent/metadata/namespace_proxy.py +++ b/quantum/agent/metadata/namespace_proxy.py @@ -75,15 +75,18 @@ class NetworkMetadataProxyHandler(object): LOG.debug(_("Request: %s"), req) try: return self._proxy_request(req.remote_addr, + req.method, req.path_info, - req.query_string) + req.query_string, + req.body) except Exception: LOG.exception(_("Unexpected error.")) msg = _('An unknown error has occurred. ' 'Please try your request again.') return webob.exc.HTTPInternalServerError(explanation=unicode(msg)) - def _proxy_request(self, remote_address, path_info, query_string): + def _proxy_request(self, remote_address, method, path_info, + query_string, body): headers = { 'X-Forwarded-For': remote_address, } @@ -103,7 +106,9 @@ class NetworkMetadataProxyHandler(object): h = httplib2.Http() resp, content = h.request( url, + method=method, headers=headers, + body=body, connection_type=UnixDomainHTTPConnection) if resp.status == 200: @@ -112,6 +117,8 @@ class NetworkMetadataProxyHandler(object): return content elif resp.status == 404: return webob.exc.HTTPNotFound() + elif resp.status == 409: + return webob.exc.HTTPConflict() elif resp.status == 500: msg = _( 'Remote metadata server experienced an internal server error.' diff --git a/quantum/tests/unit/test_metadata_agent.py b/quantum/tests/unit/test_metadata_agent.py index 1b0af7fc2..c50543ff8 100644 --- a/quantum/tests/unit/test_metadata_agent.py +++ b/quantum/tests/unit/test_metadata_agent.py @@ -180,9 +180,12 @@ class TestMetadataProxyHandler(base.BaseTestCase): self._get_instance_id_helper(headers, ports, networks=['the_id']) ) - def _proxy_request_test_helper(self, response_code): + def _proxy_request_test_helper(self, response_code=200, method='GET'): hdrs = {'X-Forwarded-For': '8.8.8.8'} - req = mock.Mock(path_info='/the_path', query_string='', headers=hdrs) + body = 'body' + + req = mock.Mock(path_info='/the_path', query_string='', headers=hdrs, + method=method, body=body) resp = mock.Mock(status=response_code) with mock.patch.object(self.handler, '_sign_instance_id') as sign: sign.return_value = 'signed' @@ -193,16 +196,22 @@ class TestMetadataProxyHandler(base.BaseTestCase): mock_http.assert_has_calls([ mock.call().request( 'http://9.9.9.9:8775/the_path', + method=method, headers={ 'X-Forwarded-For': '8.8.8.8', 'X-Instance-ID-Signature': 'signed', 'X-Instance-ID': 'the_id' - } + }, + body=body )] ) return retval + def test_proxy_request_post(self): + self.assertEqual('content', + self._proxy_request_test_helper(method='POST')) + def test_proxy_request_200(self): self.assertEqual('content', self._proxy_request_test_helper(200)) @@ -214,6 +223,10 @@ class TestMetadataProxyHandler(base.BaseTestCase): self.assertIsInstance(self._proxy_request_test_helper(404), webob.exc.HTTPNotFound) + def test_proxy_request_409(self): + self.assertIsInstance(self._proxy_request_test_helper(409), + webob.exc.HTTPConflict) + def test_proxy_request_500(self): self.assertIsInstance(self._proxy_request_test_helper(500), webob.exc.HTTPInternalServerError) diff --git a/quantum/tests/unit/test_metadata_namespace_proxy.py b/quantum/tests/unit/test_metadata_namespace_proxy.py index dc9e0ee54..ba1e72cb4 100644 --- a/quantum/tests/unit/test_metadata_namespace_proxy.py +++ b/quantum/tests/unit/test_metadata_namespace_proxy.py @@ -74,8 +74,10 @@ class TestNetworkMetadataProxyHandler(base.BaseTestCase): retval = self.handler(req) self.assertEqual(retval, 'value') proxy_req.assert_called_once_with(req.remote_addr, + req.method, req.path_info, - req.query_string) + req.query_string, + req.body) def test_no_argument_passed_to_init(self): with testtools.ExpectedException(ValueError): @@ -98,17 +100,21 @@ class TestNetworkMetadataProxyHandler(base.BaseTestCase): mock_http.return_value.request.return_value = (resp, 'content') retval = self.handler._proxy_request('192.168.1.1', + 'GET', '/latest/meta-data', + '', '') mock_http.assert_has_calls([ mock.call().request( 'http://169.254.169.254/latest/meta-data', + method='GET', headers={ 'X-Forwarded-For': '192.168.1.1', 'X-Quantum-Router-ID': 'router_id' }, - connection_type=ns_proxy.UnixDomainHTTPConnection + connection_type=ns_proxy.UnixDomainHTTPConnection, + body='' )] ) @@ -122,17 +128,21 @@ class TestNetworkMetadataProxyHandler(base.BaseTestCase): mock_http.return_value.request.return_value = (resp, 'content') retval = self.handler._proxy_request('192.168.1.1', + 'GET', '/latest/meta-data', + '', '') mock_http.assert_has_calls([ mock.call().request( 'http://169.254.169.254/latest/meta-data', + method='GET', headers={ 'X-Forwarded-For': '192.168.1.1', 'X-Quantum-Network-ID': 'network_id' }, - connection_type=ns_proxy.UnixDomainHTTPConnection + connection_type=ns_proxy.UnixDomainHTTPConnection, + body='' )] ) @@ -146,22 +156,54 @@ class TestNetworkMetadataProxyHandler(base.BaseTestCase): mock_http.return_value.request.return_value = (resp, '') retval = self.handler._proxy_request('192.168.1.1', + 'GET', '/latest/meta-data', + '', '') mock_http.assert_has_calls([ mock.call().request( 'http://169.254.169.254/latest/meta-data', + method='GET', headers={ 'X-Forwarded-For': '192.168.1.1', 'X-Quantum-Network-ID': 'network_id' }, - connection_type=ns_proxy.UnixDomainHTTPConnection + connection_type=ns_proxy.UnixDomainHTTPConnection, + body='' )] ) self.assertIsInstance(retval, webob.exc.HTTPNotFound) + def test_proxy_request_network_409(self): + self.handler.network_id = 'network_id' + + resp = mock.Mock(status=409) + with mock.patch('httplib2.Http') as mock_http: + mock_http.return_value.request.return_value = (resp, '') + + retval = self.handler._proxy_request('192.168.1.1', + 'POST', + '/latest/meta-data', + '', + '') + + mock_http.assert_has_calls([ + mock.call().request( + 'http://169.254.169.254/latest/meta-data', + method='POST', + headers={ + 'X-Forwarded-For': '192.168.1.1', + 'X-Quantum-Network-ID': 'network_id' + }, + connection_type=ns_proxy.UnixDomainHTTPConnection, + body='' + )] + ) + + self.assertIsInstance(retval, webob.exc.HTTPConflict) + def test_proxy_request_network_500(self): self.handler.network_id = 'network_id' @@ -170,17 +212,21 @@ class TestNetworkMetadataProxyHandler(base.BaseTestCase): mock_http.return_value.request.return_value = (resp, '') retval = self.handler._proxy_request('192.168.1.1', + 'GET', '/latest/meta-data', + '', '') mock_http.assert_has_calls([ mock.call().request( 'http://169.254.169.254/latest/meta-data', + method='GET', headers={ 'X-Forwarded-For': '192.168.1.1', 'X-Quantum-Network-ID': 'network_id' }, - connection_type=ns_proxy.UnixDomainHTTPConnection + connection_type=ns_proxy.UnixDomainHTTPConnection, + body='' )] ) @@ -195,17 +241,21 @@ class TestNetworkMetadataProxyHandler(base.BaseTestCase): with testtools.ExpectedException(Exception): self.handler._proxy_request('192.168.1.1', + 'GET', '/latest/meta-data', + '', '') mock_http.assert_has_calls([ mock.call().request( 'http://169.254.169.254/latest/meta-data', + method='GET', headers={ 'X-Forwarded-For': '192.168.1.1', 'X-Quantum-Network-ID': 'network_id' }, - connection_type=ns_proxy.UnixDomainHTTPConnection + connection_type=ns_proxy.UnixDomainHTTPConnection, + body='' )] ) @@ -218,17 +268,21 @@ class TestNetworkMetadataProxyHandler(base.BaseTestCase): with testtools.ExpectedException(Exception): self.handler._proxy_request('192.168.1.1', + 'GET', '/latest/meta-data', + '', '') mock_http.assert_has_calls([ mock.call().request( 'http://169.254.169.254/latest/meta-data', + method='GET', headers={ 'X-Forwarded-For': '192.168.1.1', 'X-Quantum-Network-ID': 'network_id' }, - connection_type=ns_proxy.UnixDomainHTTPConnection + connection_type=ns_proxy.UnixDomainHTTPConnection, + body='' )] ) -- 2.45.2