Forráskód Böngészése

Patch discovery.build calls in GCP provider to use google's improved
httplib2 that support multi-threading. Without using the GCP provider
in multithreaded results in exceptions and even segmentation faults.

See

https://github.com/googleapis/google-api-python-client/blob/master/docs/thread_safety.md

Sheer El Showk 5 éve
szülő
commit
6d909dd5a3
1 módosított fájl, 26 hozzáadás és 3 törlés
  1. 26 3
      cloudbridge/providers/gcp/provider.py

+ 26 - 3
cloudbridge/providers/gcp/provider.py

@@ -12,9 +12,15 @@ from string import Template
 import googleapiclient
 from googleapiclient import discovery
 
+import google_auth_httplib2
+import httplib2
+
 from oauth2client.client import GoogleCredentials
 from oauth2client.service_account import ServiceAccountCredentials
 
+from google.auth.credentials import with_scopes_if_required
+from google.oauth2.service_account import Credentials
+
 from cloudbridge.base import BaseCloudProvider
 from cloudbridge.interfaces.exceptions import ProviderConnectionException
 
@@ -26,6 +32,7 @@ from .services import GCPStorageService
 
 log = logging.getLogger(__name__)
 
+CLOUD_SCOPES = ['https://www.googleapis.com/auth/cloud-platform']
 
 class GCPResourceUrl(object):
 
@@ -336,17 +343,33 @@ class GCPCloudProvider(BaseCloudProvider):
     def client_id(self):
         return self._credentials.service_account_email
 
+    def _get_build_request(self):
+        credentials = Credentials.from_service_account_info(self.credentials_dict)
+        credentials=with_scopes_if_required(credentials, list(CLOUD_SCOPES))
+        # FROM: https://github.com/googleapis/google-api-python-client/blob/master/docs/thread_safety.md
+        # Create a new Http() object for every request
+        def build_request(http, *args, **kwargs):
+          new_http = google_auth_httplib2.AuthorizedHttp(credentials, http=httplib2.Http())
+          return googleapiclient.http.HttpRequest(new_http, *args, **kwargs)
+        return build_request
+
     def _connect_gcp_storage(self):
         return discovery.build('storage', 'v1', credentials=self._credentials,
-                               cache_discovery=False)
+                               cache_discovery=False,
+                               requestBuilder=self._get_build_request()
+                               )
 
     def _connect_gcp_compute(self):
         return discovery.build('compute', 'v1', credentials=self._credentials,
-                               cache_discovery=False)
+                               cache_discovery=False,
+                               requestBuilder=self._get_build_request()
+                               )
 
     def _connect_gcp_dns(self):
         return discovery.build('dns', 'v1', credentials=self._credentials,
-                               cache_discovery=False)
+                               cache_discovery=False,
+                               requestBuilder=self._get_build_request()
+                               )
 
     def wait_for_operation(self, operation, region=None, zone=None):
         args = {'project': self.project_name, 'operation': operation['name']}