provider.py 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. """
  2. Provider implementation based on google-api-python-client library
  3. for GCE.
  4. """
  5. from cloudbridge.cloud.base import BaseCloudProvider
  6. import httplib2
  7. import json
  8. import os
  9. import time
  10. from googleapiclient import discovery
  11. import googleapiclient.http
  12. from oauth2client.client import GoogleCredentials
  13. from oauth2client.service_account import ServiceAccountCredentials
  14. from .services import GCEComputeService
  15. from .services import GCESecurityService
  16. class GCECloudProvider(BaseCloudProvider):
  17. PROVIDER_ID = 'gce'
  18. def __init__(self, config):
  19. super(GCECloudProvider, self).__init__(config)
  20. # Initialize cloud connection fields
  21. self.client_email = self._get_config_value(
  22. 'gce_client_email', os.environ.get('GCE_CLIENT_EMAIL'))
  23. self.project_name = self._get_config_value(
  24. 'gce_project_name', os.environ.get('GCE_PROJECT_NAME'))
  25. self.credentials_file = self._get_config_value(
  26. 'gce_service_creds_file', os.environ.get('GCE_SERVICE_CREDS_FILE'))
  27. self.credentials_dict = self._get_config_value(
  28. 'gce_service_creds_dict', {})
  29. # If 'gce_service_creds_dict' is not passed in from config and
  30. # self.credentials_file is available, read and parse the json file to
  31. # self.credentials_dict.
  32. if self.credentials_file and not self.credentials_dict:
  33. with open(self.credentials_file) as creds_file:
  34. self.credentials_dict = json.load(creds_file)
  35. self.default_zone = self._get_config_value(
  36. 'gce_default_zone', os.environ.get('GCE_DEFAULT_ZONE'))
  37. self.region_name = self._get_config_value(
  38. 'gce_region_name', 'us-central1')
  39. # oauth2client.Credentials to be used for authentication
  40. self._credentials = None
  41. # service connections, lazily initialized
  42. self._gce_compute = None
  43. # Initialize provider services
  44. self._compute = GCEComputeService(self)
  45. self._security = GCESecurityService(self)
  46. @property
  47. def compute(self):
  48. return self._compute
  49. @property
  50. def network(self):
  51. raise NotImplementedError(
  52. "GCECloudProvider does not implement this service")
  53. @property
  54. def security(self):
  55. return self._security
  56. @property
  57. def block_store(self):
  58. raise NotImplementedError(
  59. "GCECloudProvider does not implement this service")
  60. @property
  61. def object_store(self):
  62. raise NotImplementedError(
  63. "GCECloudProvider does not implement this service")
  64. @property
  65. def gce_compute(self):
  66. if not self._gce_compute:
  67. self._gce_compute = self._connect_gce_compute()
  68. return self._gce_compute
  69. def _connect_gce_compute(self):
  70. if self.credentials_dict:
  71. credentials = ServiceAccountCredentials.from_json_keyfile_dict(
  72. self.credentials_dict)
  73. else:
  74. credentials = GoogleCredentials.get_application_default()
  75. self._credentials = credentials
  76. return discovery.build('compute', 'v1', credentials=credentials)
  77. def get_gce_resource_data(self, uri):
  78. """
  79. Retrieves GCE resoure data given its resource URI.
  80. """
  81. http = httplib2.Http()
  82. http = self._credentials.authorize(http)
  83. def _postproc(*kwargs):
  84. if len(kwargs) >= 2:
  85. # The first argument is request, and the second is response.
  86. resource_dict = json.loads(kwargs[1])
  87. return resource_dict
  88. request = googleapiclient.http.HttpRequest(http=http,
  89. postproc=_postproc,
  90. uri=uri)
  91. # The response is a dict representing the GCE resource data.
  92. response = request.execute()
  93. return response
  94. def wait_for_global_operation(self, operation):
  95. while True:
  96. result = self.gce_compute.globalOperations().get(
  97. project=self.project_name,
  98. operation=operation['name']).execute()
  99. if result['status'] == 'DONE':
  100. if 'error' in result:
  101. raise Exception(result['error'])
  102. return result
  103. time.sleep(0.5)