diff --git a/neutron/agent/metadata/agent.py b/neutron/agent/metadata/agent.py index 30e5bc68f17..27205f7c7ff 100644 --- a/neutron/agent/metadata/agent.py +++ b/neutron/agent/metadata/agent.py @@ -15,7 +15,6 @@ import hashlib import hmac -import httplib2 from neutron_lib.agent import topics from neutron_lib import constants from neutron_lib import context @@ -24,6 +23,7 @@ from oslo_log import log as logging import oslo_messaging from oslo_service import loopingcall from oslo_utils import encodeutils +import requests import six import six.moves.urllib.parse as urlparse import webob @@ -186,35 +186,41 @@ class MetadataProxyHandler(object): req.query_string, '')) - h = httplib2.Http( - ca_certs=self.conf.auth_ca_cert, - disable_ssl_certificate_validation=self.conf.nova_metadata_insecure - ) - if self.conf.nova_client_cert and self.conf.nova_client_priv_key: - h.add_certificate(self.conf.nova_client_priv_key, - self.conf.nova_client_cert, - nova_host_port) - resp, content = h.request(url, method=req.method, headers=headers, - body=req.body) + disable_ssl_certificate_validation = self.conf.nova_metadata_insecure + if self.conf.auth_ca_cert and not disable_ssl_certificate_validation: + verify_cert = self.conf.auth_ca_cert + else: + verify_cert = not disable_ssl_certificate_validation - if resp.status == 200: - req.response.content_type = resp['content-type'] - req.response.body = content + client_cert = None + if self.conf.nova_client_cert and self.conf.nova_client_priv_key: + client_cert = (self.conf.nova_client_cert, + self.conf.nova_client_priv_key) + + resp = requests.request(method=req.method, url=url, + headers=headers, + data=req.body, + cert=client_cert, + verify=verify_cert) + + if resp.status_code == 200: + req.response.content_type = resp.headers['content-type'] + req.response.body = resp.content LOG.debug(str(resp)) return req.response - elif resp.status == 403: + elif resp.status_code == 403: LOG.warning( 'The remote metadata server responded with Forbidden. This ' 'response usually occurs when shared secrets do not match.' ) return webob.exc.HTTPForbidden() - elif resp.status == 400: + elif resp.status_code == 400: return webob.exc.HTTPBadRequest() - elif resp.status == 404: + elif resp.status_code == 404: return webob.exc.HTTPNotFound() - elif resp.status == 409: + elif resp.status_code == 409: return webob.exc.HTTPConflict() - elif resp.status == 500: + elif resp.status_code == 500: msg = _( 'Remote metadata server experienced an internal server error.' ) diff --git a/neutron/tests/unit/agent/metadata/test_agent.py b/neutron/tests/unit/agent/metadata/test_agent.py index 8d9cd49938a..09c6c7fa2c1 100644 --- a/neutron/tests/unit/agent/metadata/test_agent.py +++ b/neutron/tests/unit/agent/metadata/test_agent.py @@ -339,37 +339,28 @@ class _TestMetadataProxyHandlerCacheMixin(object): req = mock.Mock(path_info='/the_path', query_string='', headers=hdrs, method=method, body=body) - resp = mock.MagicMock(status=response_code) + resp = mock.MagicMock(status_code=response_code) + resp.content = 'content' req.response = resp with mock.patch.object(self.handler, '_sign_instance_id') as sign: sign.return_value = 'signed' - with mock.patch('httplib2.Http') as mock_http: - resp.__getitem__.return_value = "text/plain" - mock_http.return_value.request.return_value = (resp, 'content') - + with mock.patch('requests.request') as mock_request: + resp.headers = {'content-type': 'text/plain'} + mock_request.return_value = resp retval = self.handler._proxy_request('the_id', 'tenant_id', req) - mock_http.assert_called_once_with( - ca_certs=None, disable_ssl_certificate_validation=True) - mock_http.assert_has_calls([ - mock.call().add_certificate( - self.fake_conf.nova_client_priv_key, - self.fake_conf.nova_client_cert, - "%s:%s" % (self.fake_conf.nova_metadata_host, - self.fake_conf.nova_metadata_port) - ), - 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', - 'X-Tenant-ID': 'tenant_id' - }, - body=body - )] - ) + mock_request.assert_called_once_with( + method=method, url='http://9.9.9.9:8775/the_path', + headers={ + 'X-Forwarded-For': '8.8.8.8', + 'X-Instance-ID-Signature': 'signed', + 'X-Instance-ID': 'the_id', + 'X-Tenant-ID': 'tenant_id' + }, + data=body, + cert=(self.fake_conf.nova_client_cert, + self.fake_conf.nova_client_priv_key), + verify=False) return retval diff --git a/requirements.txt b/requirements.txt index 2961e8a509b..08257997caf 100644 --- a/requirements.txt +++ b/requirements.txt @@ -10,6 +10,7 @@ debtcollector>=1.2.0 # Apache-2.0 eventlet!=0.18.3,!=0.20.1,>=0.18.2 # MIT pecan!=1.0.2,!=1.0.3,!=1.0.4,!=1.2,>=1.1.1 # BSD httplib2>=0.9.1 # MIT +requests>=2.14.2 # Apache-2.0 Jinja2>=2.10 # BSD License (3 clause) keystonemiddleware>=4.17.0 # Apache-2.0 netaddr>=0.7.18 # BSD