Add SSD support to GCE Compute driver

Closes #339

Signed-off-by: Tomaz Muraus <[email protected]>


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/e3edf278
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/e3edf278
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/e3edf278

Branch: refs/heads/trunk
Commit: e3edf278c3310bd93f5d4e463bcc0373a38d5401
Parents: a26da95
Author: Eric Johnson <[email protected]>
Authored: Wed Jul 16 15:40:12 2014 +0000
Committer: Tomaz Muraus <[email protected]>
Committed: Mon Jul 21 10:09:13 2014 +0200

----------------------------------------------------------------------
 CHANGES.rst                                     |    3 +
 demos/gce_demo.py                               |    6 +-
 libcloud/compute/drivers/gce.py                 |   71 +-
 libcloud/compute/drivers/gce.py.orig            | 3353 ++++++++++++++++++
 .../gce/global_snapshots_lcsnapshot.json        |    4 +-
 .../fixtures/gce/zones_us-central1-a_disks.json |    8 +-
 .../gce/zones_us-central1-a_disks_lcdisk.json   |    6 +-
 libcloud/test/compute/test_gce.py               |   17 +-
 8 files changed, 3445 insertions(+), 23 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/e3edf278/CHANGES.rst
----------------------------------------------------------------------
diff --git a/CHANGES.rst b/CHANGES.rst
index 17999cc..bef4c9d 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -16,6 +16,9 @@ Compute
   (LIBCLOUD-594, GITHUB-337)
   [Atsushi Sasaki]
 
+- Add support for SSD disks to Google Compute driver.
+  (GITHUB-339)
+  [Eric Johnson]
 
 Loadbalancer
 ~~~~~~~~~~~~

http://git-wip-us.apache.org/repos/asf/libcloud/blob/e3edf278/demos/gce_demo.py
----------------------------------------------------------------------
diff --git a/demos/gce_demo.py b/demos/gce_demo.py
index 5f45c68..3535689 100755
--- a/demos/gce_demo.py
+++ b/demos/gce_demo.py
@@ -190,16 +190,16 @@ def main():
 
     # == Create Node with disk auto-created ==
     if MAX_NODES > 1:
-        print('Creating Node with auto-created disk:')
+        print('Creating Node with auto-created SSD:')
         name = '%s-np-node' % DEMO_BASE_NAME
         node_1 = gce.create_node(name, 'n1-standard-1', 'debian-7',
-                                 ex_tags=['libcloud'])
+                                 ex_tags=['libcloud'], ex_disk_type='pd-ssd')
         print('   Node %s created' % name)
 
         # == Create, and attach a disk ==
         print('Creating a new disk:')
         disk_name = '%s-attach-disk' % DEMO_BASE_NAME
-        volume = gce.create_volume(1, disk_name)
+        volume = gce.create_volume(10, disk_name)
         if volume.attach(node_1):
             print ('   Attached %s to %s' % (volume.name, node_1.name))
 

http://git-wip-us.apache.org/repos/asf/libcloud/blob/e3edf278/libcloud/compute/drivers/gce.py
----------------------------------------------------------------------
diff --git a/libcloud/compute/drivers/gce.py b/libcloud/compute/drivers/gce.py
index 62164fd..a6f3c9f 100644
--- a/libcloud/compute/drivers/gce.py
+++ b/libcloud/compute/drivers/gce.py
@@ -1140,7 +1140,8 @@ class GCENodeDriver(NodeDriver):
     def create_node(self, name, size, image, location=None,
                     ex_network='default', ex_tags=None, ex_metadata=None,
                     ex_boot_disk=None, use_existing_disk=True,
-                    external_ip='ephemeral'):
+                    external_ip='ephemeral', ex_disk_type='pd-standard',
+                    ex_disk_auto_delete=True):
         """
         Create a new node and return a node object for the node.
 
@@ -1182,6 +1183,15 @@ class GCENodeDriver(NodeDriver):
                                a GCEAddress object should be passed in.
         :type     external_ip: :class:`GCEAddress` or ``str`` or None
 
+        :keyword  ex_disk_type: Specify a pd-standard (default) disk or pd-ssd
+                                for an SSD disk.
+        :type     ex_disk_type: ``str``
+
+        :keyword  ex_disk_auto_delete: Indicate that the boot disk should be
+                                       deleted when the Node is deleted. Set to
+                                       True by default.
+        :type     ex_disk_auto_delete: ``bool``
+
         :return:  A Node object for the new node.
         :rtype:   :class:`Node`
         """
@@ -1198,7 +1208,8 @@ class GCENodeDriver(NodeDriver):
         if not ex_boot_disk:
             ex_boot_disk = self.create_volume(None, name, location=location,
                                               image=image,
-                                              use_existing=use_existing_disk)
+                                              use_existing=use_existing_disk,
+                                              ex_disk_type=ex_disk_type)
 
         if ex_metadata is not None:
             ex_metadata = {"items": [{"key": k, "value": v}
@@ -1207,7 +1218,9 @@ class GCENodeDriver(NodeDriver):
         request, node_data = self._create_node_req(name, size, image,
                                                    location, ex_network,
                                                    ex_tags, ex_metadata,
-                                                   ex_boot_disk, external_ip)
+                                                   ex_boot_disk, external_ip,
+                                                   ex_disk_type,
+                                                   ex_disk_auto_delete)
         self.connection.async_request(request, method='POST', data=node_data)
 
         return self.ex_get_node(name, location.name)
@@ -1217,6 +1230,8 @@ class GCENodeDriver(NodeDriver):
                                  ex_tags=None, ex_metadata=None,
                                  ignore_errors=True, use_existing_disk=True,
                                  poll_interval=2, external_ip='ephemeral',
+                                 ex_disk_type='pd-standard',
+                                 ex_auto_disk_delete=True,
                                  timeout=DEFAULT_TASK_COMPLETION_TIMEOUT):
         """
         Create multiple nodes and return a list of Node objects.
@@ -1273,6 +1288,15 @@ class GCENodeDriver(NodeDriver):
                                multiple node creation.)
         :type     external_ip: ``str`` or None
 
+        :keyword  ex_disk_type: Specify a pd-standard (default) disk or pd-ssd
+                                for an SSD disk.
+        :type     ex_disk_type: ``str``
+
+        :keyword  ex_disk_auto_delete: Indicate that the boot disk should be
+                                       deleted when the Node is deleted. Set to
+                                       True by default.
+        :type     ex_disk_auto_delete: ``bool``
+
         :keyword  timeout: The number of seconds to wait for all nodes to be
                            created before timing out.
         :type     timeout: ``int``
@@ -1298,7 +1322,8 @@ class GCENodeDriver(NodeDriver):
                       'metadata': ex_metadata,
                       'ignore_errors': ignore_errors,
                       'use_existing_disk': use_existing_disk,
-                      'external_ip': external_ip}
+                      'external_ip': external_ip,
+                      'ex_disk_type': ex_disk_type}
 
         # List for holding the status information for disk/node creation.
         status_list = []
@@ -1406,7 +1431,8 @@ class GCENodeDriver(NodeDriver):
         return self.ex_get_targetpool(name, region)
 
     def create_volume(self, size, name, location=None, snapshot=None,
-                      image=None, use_existing=True):
+                      image=None, use_existing=True,
+                      ex_disk_type='pd-standard'):
         """
         Create a volume (disk).
 
@@ -1432,11 +1458,15 @@ class GCENodeDriver(NodeDriver):
                                 of attempting to create a new disk.
         :type     use_existing: ``bool``
 
+        :keyword  ex_disk_type: Specify a pd-standard (default) disk or pd-ssd
+                                for an SSD disk.
+        :type     ex_disk_type: ``str``
+
         :return:  Storage Volume object
         :rtype:   :class:`StorageVolume`
         """
         request, volume_data, params = self._create_vol_req(
-            size, name, location, snapshot, image)
+            size, name, location, snapshot, image, ex_disk_type)
         try:
             self.connection.async_request(request, method='POST',
                                           data=volume_data, params=params)
@@ -2716,7 +2746,8 @@ class GCENodeDriver(NodeDriver):
 
     def _create_node_req(self, name, size, image, location, network,
                          tags=None, metadata=None, boot_disk=None,
-                         external_ip='ephemeral'):
+                         external_ip='ephemeral', ex_disk_type='pd-standard',
+                         ex_disk_auto_delete=True):
         """
         Returns a request and body to create a new node.  This is a helper
         method to support both :class:`create_node` and
@@ -2754,6 +2785,15 @@ class GCENodeDriver(NodeDriver):
                                a GCEAddress object should be passed in.
         :type     external_ip: :class:`GCEAddress` or ``str`` or None
 
+        :keyword  ex_disk_type: Specify a pd-standard (default) disk or pd-ssd
+                                for an SSD disk.
+        :type     ex_disk_type: ``str``
+
+        :keyword  ex_disk_auto_delete: Indicate that the boot disk should be
+                                       deleted when the Node is deleted. Set to
+                                       True by default.
+        :type     ex_disk_auto_delete: ``bool``
+
         :return:  A tuple containing a request string and a node_data dict.
         :rtype:   ``tuple`` of ``str`` and ``dict``
         """
@@ -2799,7 +2839,7 @@ class GCENodeDriver(NodeDriver):
         :type   status: ``dict``
 
         :param  node_attrs: Dictionary for holding node attribute information.
-                            (size, image, location, etc.)
+                            (size, image, location, ex_disk_type, etc.)
         :type   node_attrs: ``dict``
         """
         disk = None
@@ -2818,7 +2858,8 @@ class GCENodeDriver(NodeDriver):
             # Or, if there is an error, mark as failed.
             disk_req, disk_data, disk_params = self._create_vol_req(
                 None, status['name'], location=node_attrs['location'],
-                image=node_attrs['image'])
+                image=node_attrs['image'],
+                ex_disk_type=node_attrs['ex_disk_type'])
             try:
                 disk_res = self.connection.request(
                     disk_req, method='POST', data=disk_data,
@@ -2926,7 +2967,7 @@ class GCENodeDriver(NodeDriver):
                                               node_attrs['location'])
 
     def _create_vol_req(self, size, name, location=None, snapshot=None,
-                        image=None):
+                        image=None, ex_disk_type='pd-standard'):
         """
         Assemble the request/data for creating a volume.
 
@@ -2949,6 +2990,9 @@ class GCENodeDriver(NodeDriver):
         :keyword  image: Image to create disk from.
         :type     image: :class:`GCENodeImage` or ``str`` or ``None``
 
+        :keyword  ex_disk_type: Specify pd-standard (default) or pd-ssd
+        :type     ex_disk_type: ``str``
+
         :return:  Tuple containing the request string, the data dictionary and
                   the URL parameters
         :rtype:   ``tuple``
@@ -2976,6 +3020,12 @@ class GCENodeDriver(NodeDriver):
         location = location or self.zone
         if not hasattr(location, 'name'):
             location = self.ex_get_zone(location)
+        if ex_disk_type.startswith('https'):
+            volume_data['type'] = ex_disk_type
+        else:
+            volume_data['type'] = 'https://www.googleapis.com/compute/'
+            volume_data['type'] += '%s/projects/%s/zones/%s/diskTypes/%s' % (
+                API_VERSION, self.project, location.name, ex_disk_type)
         request = '/zones/%s/disks' % (location.name)
 
         return request, volume_data, params
@@ -3305,6 +3355,7 @@ class GCENodeDriver(NodeDriver):
         extra['status'] = volume.get('status')
         extra['creationTimestamp'] = volume.get('creationTimestamp')
         extra['description'] = volume.get('description')
+        extra['type'] = volume.get('type', 'pd-standard').split('/')[-1]
 
         return StorageVolume(id=volume['id'], name=volume['name'],
                              size=volume['sizeGb'], driver=self, extra=extra)

Reply via email to