baizhang 9 лет назад
Родитель
Сommit
ae4e751407

+ 80 - 0
cloudbridge/cloud/providers/gce/resources.py

@@ -3,8 +3,12 @@ DataTypes used by this provider
 """
 from cloudbridge.cloud.base.resources import BaseInstanceType
 from cloudbridge.cloud.base.resources import BaseKeyPair
+from cloudbridge.cloud.base.resources import BaseMachineImage
 from cloudbridge.cloud.base.resources import BasePlacementZone
 from cloudbridge.cloud.base.resources import BaseRegion
+from cloudbridge.cloud.interfaces.resources import MachineImageState
+
+import googleapiclient
 
 
 class GCEKeyPair(BaseKeyPair):
@@ -162,3 +166,79 @@ class GCERegion(BaseRegion):
                  if zone['region'] == self._gce_region['selfLink']]
         return [GCEPlacementZone(self._provider, zone['name'], self.name)
                 for zone in zones]
+
+
+class GCEMachineImage(BaseMachineImage):
+
+    IMAGE_STATE_MAP = {
+        'PENDING': MachineImageState.PENDING,
+        'READY': MachineImageState.AVAILABLE,
+        'FAILED': MachineImageState.ERROR
+    }
+
+    def __init__(self, provider, image):
+        super(GCEMachineImage, self).__init__(provider)
+        if isinstance(image, GCEMachineImage):
+            # pylint:disable=protected-access
+            self._gce_image = image._gce_image
+        else:
+            self._gce_image = image
+
+    @property
+    def id(self):
+        """
+        Get the image identifier.
+        :rtype: ``str``
+        :return: ID for this instance as returned by the cloud middleware.
+        """
+        return self._gce_image['id']
+
+    @property
+    def name(self):
+        """
+        Get the image name.
+        :rtype: ``str``
+        :return: Name for this image as returned by the cloud middleware.
+        """
+        return self._gce_image['name']
+
+    @property
+    def description(self):
+        """
+        Get the image description.
+        :rtype: ``str``
+        :return: Description for this image as returned by the cloud middleware
+        """
+        return self._gce_image['description']
+
+    def delete(self):
+        """
+        Delete this image
+        """
+        request = self._provider.gce_compute.images().delete(
+            project=self._provider.project_name, image=self.name)
+        request.execute()
+
+    @property
+    def state(self):
+        return GCEMachineImage.IMAGE_STATE_MAP.get(
+            self._gce_image['status'], MachineImageState.UNKNOWN)
+
+    def refresh(self):
+        """
+        Refreshes the state of this instance by re-querying the cloud provider
+        for its latest state.
+        """
+        try:
+            response = self._provider.gce_compute \
+                                  .images() \
+                                  .get(project=self._provider.project_name,
+                                       image=self.name) \
+                                  .execute()
+            if response:
+                # pylint:disable=protected-access
+                self._gce_image = response
+        except googleapiclient.errors.HttpError as http_error:
+            # image no longer exists
+            print("googleapiclient.errors.HttpError: {0}".format(http_error))
+            self._gce_image['status'] = "unknown"

+ 71 - 1
cloudbridge/cloud/providers/gce/services.py

@@ -1,5 +1,6 @@
 from cloudbridge.cloud.base.resources import ClientPagedResultList
 from cloudbridge.cloud.base.services import BaseComputeService
+from cloudbridge.cloud.base.services import BaseImageService
 from cloudbridge.cloud.base.services import BaseInstanceTypesService
 from cloudbridge.cloud.base.services import BaseKeyPairService
 from cloudbridge.cloud.base.services import BaseRegionService
@@ -12,6 +13,7 @@ import googleapiclient
 
 from retrying import retry
 
+from .resources import GCEMachineImage
 from .resources import GCEInstanceType
 from .resources import GCEKeyPair
 from .resources import GCERegion
@@ -267,16 +269,84 @@ class GCERegionService(BaseRegionService):
         return self.get(self.provider.region_name)
 
 
+class GCEImageService(BaseImageService):
+
+    def __init__(self, provider):
+        super(GCEImageService, self).__init__(provider)
+
+    def get(self, image_name):
+        """
+        Returns an Image given its name
+        """
+        try:
+            image = self.provider.gce_compute \
+                                  .images() \
+                                  .get(project=self.provider.project_name,
+                                       image=image_name) \
+                                  .execute()
+            if image:
+                return GCEMachineImage(self.provider, image)
+        except TypeError as type_error:
+            # The API will throw an TypeError, if parameter `image` does not
+            # match the pattern "[a-z](?:[-a-z0-9]{0,61}[a-z0-9])?".
+            print("TypeError: {0}".format(type_error))
+            return None
+        except googleapiclient.errors.HttpError as http_error:
+            print("googleapiclient.errors.HttpError: {0}".format(http_error))
+            return None
+
+    def find(self, name, limit=None, marker=None):
+        """
+        Searches for an image by a given list of attributes
+        """
+        filters = {'name': name}
+        try:
+            response = self.provider.gce_compute \
+                                    .images() \
+                                  .list(project=self.provider.project_name) \
+                                  .execute()
+        except googleapiclient.errors.HttpError as http_error:
+            print("googleapiclient.errors.HttpError: {0}".format(http_error))
+            return []
+        if 'items' not in response:
+            return []
+        images = [GCEMachineImage(self.provider, image) for image
+                  in response['items']
+                  if 'name' in image and image['name'] == filters['name']]
+        return ClientPagedResultList(self.provider, images,
+                                     limit=limit, marker=marker)
+
+    def list(self, limit=None, marker=None):
+        """
+        List all images.
+        """
+        try:
+            response = self.provider.gce_compute \
+                                  .images() \
+                                  .list(project=self.provider.project_name) \
+                                  .execute()
+        except googleapiclient.errors.HttpError as http_error:
+            print("googleapiclient.errors.HttpError: {0}".format(http_error))
+            return []
+        if 'items' not in response:
+            return []
+        images = [GCEMachineImage(self.provider, image) for image
+                  in response['items']]
+        return ClientPagedResultList(self.provider, images,
+                                     limit=limit, marker=marker)
+
+
 class GCEComputeService(BaseComputeService):
     # TODO: implement GCEComputeService
     def __init__(self, provider):
         super(GCEComputeService, self).__init__(provider)
         self._instance_type_svc = GCEInstanceTypesService(self.provider)
         self._region_svc = GCERegionService(self.provider)
+        self._images_svc = GCEImageService(self.provider)
 
     @property
     def images(self):
-        raise NotImplementedError("To be implemented")
+        return self._images_svc
 
     @property
     def instance_types(self):