Browse Source

Merge "Replace httplib2 with requests in metadata agent" into stable/queens

changes/07/675607/1
Zuul 1 month ago
parent
commit
032baf8f45

+ 35
- 27
networking_ovn/agent/metadata/server.py View File

@@ -15,8 +15,8 @@
15 15
 import hashlib
16 16
 import hmac
17 17
 
18
-import httplib2
19 18
 from neutron.agent.linux import utils as agent_utils
19
+from neutron.common import ipv6_utils
20 20
 from neutron.conf.agent.metadata import config
21 21
 from neutron_lib.callbacks import events
22 22
 from neutron_lib.callbacks import registry
@@ -24,6 +24,7 @@ from neutron_lib.callbacks import resources
24 24
 from oslo_config import cfg
25 25
 from oslo_log import log as logging
26 26
 from oslo_utils import encodeutils
27
+import requests
27 28
 import six
28 29
 import six.moves.urllib.parse as urlparse
29 30
 import webob
@@ -91,15 +92,15 @@ class MetadataProxyHandler(object):
91 92
     def _proxy_request(self, instance_id, tenant_id, req):
92 93
         headers = {
93 94
             'X-Forwarded-For': req.headers.get('X-Forwarded-For'),
94
-            'X-Instance-ID': str(instance_id),
95
-            'X-Tenant-ID': str(tenant_id),
95
+            'X-Instance-ID': instance_id,
96
+            'X-Tenant-ID': tenant_id,
96 97
             'X-Instance-ID-Signature': self._sign_instance_id(instance_id)
97 98
         }
98 99
 
99
-        nova_host_port = '%s:%s' % (self.conf.nova_metadata_host,
100
-                                    self.conf.nova_metadata_port)
101
-        LOG.debug('Request to Nova at %s', nova_host_port)
102
-        LOG.debug(headers)
100
+        nova_host_port = ipv6_utils.valid_ipv6_url(
101
+            self.conf.nova_metadata_host,
102
+            self.conf.nova_metadata_port)
103
+
103 104
         url = urlparse.urlunsplit((
104 105
             self.conf.nova_metadata_protocol,
105 106
             nova_host_port,
@@ -107,43 +108,50 @@ class MetadataProxyHandler(object):
107 108
             req.query_string,
108 109
             ''))
109 110
 
110
-        h = httplib2.Http(
111
-            ca_certs=self.conf.auth_ca_cert,
112
-            disable_ssl_certificate_validation=self.conf.nova_metadata_insecure
113
-        )
111
+        disable_ssl_certificate_validation = self.conf.nova_metadata_insecure
112
+        if self.conf.auth_ca_cert and not disable_ssl_certificate_validation:
113
+            verify_cert = self.conf.auth_ca_cert
114
+        else:
115
+            verify_cert = not disable_ssl_certificate_validation
116
+
117
+        client_cert = None
114 118
         if self.conf.nova_client_cert and self.conf.nova_client_priv_key:
115
-            h.add_certificate(self.conf.nova_client_priv_key,
116
-                              self.conf.nova_client_cert,
117
-                              nova_host_port)
118
-        resp, content = h.request(url, method=req.method, headers=headers,
119
-                                  body=req.body)
120
-
121
-        if resp.status == 200:
122
-            req.response.content_type = resp['content-type']
123
-            req.response.body = content
119
+            client_cert = (self.conf.nova_client_cert,
120
+                           self.conf.nova_client_priv_key)
121
+
122
+        resp = requests.request(method=req.method, url=url,
123
+                                headers=headers,
124
+                                data=req.body,
125
+                                cert=client_cert,
126
+                                verify=verify_cert)
127
+
128
+        if resp.status_code == 200:
129
+            req.response.content_type = resp.headers['content-type']
130
+            req.response.body = resp.content
124 131
             LOG.debug(str(resp))
125 132
             return req.response
126
-        elif resp.status == 403:
133
+        elif resp.status_code == 403:
127 134
             LOG.warning(
128 135
                 'The remote metadata server responded with Forbidden. This '
129 136
                 'response usually occurs when shared secrets do not match.'
130 137
             )
131 138
             return webob.exc.HTTPForbidden()
132
-        elif resp.status == 400:
139
+        elif resp.status_code == 400:
133 140
             return webob.exc.HTTPBadRequest()
134
-        elif resp.status == 404:
141
+        elif resp.status_code == 404:
135 142
             return webob.exc.HTTPNotFound()
136
-        elif resp.status == 409:
143
+        elif resp.status_code == 409:
137 144
             return webob.exc.HTTPConflict()
138
-        elif resp.status == 500:
145
+        elif resp.status_code == 500:
139 146
             msg = _(
140 147
                 'Remote metadata server experienced an internal server error.'
141 148
             )
142
-            LOG.debug(msg)
149
+            LOG.warning(msg)
143 150
             explanation = six.text_type(msg)
144 151
             return webob.exc.HTTPInternalServerError(explanation=explanation)
145 152
         else:
146
-            raise Exception(_('Unexpected response code: %s') % resp.status)
153
+            raise Exception(_('Unexpected response code: %s') %
154
+                            resp.status_code)
147 155
 
148 156
     def _sign_instance_id(self, instance_id):
149 157
         secret = self.conf.metadata_proxy_shared_secret

+ 18
- 26
networking_ovn/tests/unit/agent/metadata/test_server.py View File

@@ -140,37 +140,29 @@ class TestMetadataProxyHandler(base.BaseTestCase):
140 140
 
141 141
         req = mock.Mock(path_info='/the_path', query_string='', headers=hdrs,
142 142
                         method=method, body=body)
143
-        resp = mock.MagicMock(status=response_code)
143
+        resp = mock.MagicMock(status_code=response_code)
144
+        resp.status.__str__.side_effect = AttributeError
145
+        resp.content = 'content'
144 146
         req.response = resp
145 147
         with mock.patch.object(self.handler, '_sign_instance_id') as sign:
146 148
             sign.return_value = 'signed'
147
-            with mock.patch('httplib2.Http') as mock_http:
148
-                resp.__getitem__.return_value = "text/plain"
149
-                mock_http.return_value.request.return_value = (resp, 'content')
150
-
149
+            with mock.patch('requests.request') as mock_request:
150
+                resp.headers = {'content-type': 'text/plain'}
151
+                mock_request.return_value = resp
151 152
                 retval = self.handler._proxy_request('the_id', 'tenant_id',
152 153
                                                      req)
153
-                mock_http.assert_called_once_with(
154
-                    ca_certs=None, disable_ssl_certificate_validation=True)
155
-                mock_http.assert_has_calls([
156
-                    mock.call().add_certificate(
157
-                        self.fake_conf.nova_client_priv_key,
158
-                        self.fake_conf.nova_client_cert,
159
-                        "%s:%s" % (self.fake_conf.nova_metadata_host,
160
-                                   self.fake_conf.nova_metadata_port)
161
-                    ),
162
-                    mock.call().request(
163
-                        'http://9.9.9.9:8775/the_path',
164
-                        method=method,
165
-                        headers={
166
-                            'X-Forwarded-For': '8.8.8.8',
167
-                            'X-Instance-ID-Signature': 'signed',
168
-                            'X-Instance-ID': 'the_id',
169
-                            'X-Tenant-ID': 'tenant_id'
170
-                        },
171
-                        body=body
172
-                    )]
173
-                )
154
+                mock_request.assert_called_once_with(
155
+                    method=method, url='http://9.9.9.9:8775/the_path',
156
+                    headers={
157
+                        'X-Forwarded-For': '8.8.8.8',
158
+                        'X-Instance-ID-Signature': 'signed',
159
+                        'X-Instance-ID': 'the_id',
160
+                        'X-Tenant-ID': 'tenant_id'
161
+                    },
162
+                    data=body,
163
+                    cert=(self.fake_conf.nova_client_cert,
164
+                          self.fake_conf.nova_client_priv_key),
165
+                    verify=False)
174 166
 
175 167
                 return retval
176 168
 

+ 1
- 0
requirements.txt View File

@@ -13,3 +13,4 @@ pyOpenSSL>=16.2.0 # Apache-2.0
13 13
 tenacity>=3.2.1 # Apache-2.0
14 14
 Babel!=2.4.0,>=2.3.4 # BSD
15 15
 six>=1.10.0 # MIT
16
+requests!=2.20.0,>=2.14.2 # Apache-2.0

Loading…
Cancel
Save