GCE: improved Images coverage Signed-off-by: Sebastien Goasguen <[email protected]>
This closes #395 Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/43cec4eb Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/43cec4eb Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/43cec4eb Branch: refs/heads/trunk Commit: 43cec4eb312ec07c62f116ad9b0aa7ab894e7b15 Parents: 2aa6f34 Author: Eric Johnson <[email protected]> Authored: Thu Nov 20 18:04:05 2014 +0000 Committer: Sebastien Goasguen <[email protected]> Committed: Sat Nov 22 16:30:34 2014 -0500 ---------------------------------------------------------------------- CHANGES.rst | 4 + libcloud/compute/drivers/gce.py | 117 +++++++++++++------ .../projects_debian-cloud_global_images.json | 8 +- ...s-central1-a_machineTypes_n1-standard-1.json | 25 ++-- libcloud/test/compute/test_gce.py | 24 +++- 5 files changed, 123 insertions(+), 55 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/libcloud/blob/43cec4eb/CHANGES.rst ---------------------------------------------------------------------- diff --git a/CHANGES.rst b/CHANGES.rst index 5c23dc6..943f714 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -49,6 +49,10 @@ Compute (GITHUB-396) [Eric Johnson] +- GCE: Improved Images coverage + (GITHUB-395) + [Eric Johnson] + Changes with Apache Libcloud 0.16.0 ----------------------------------- http://git-wip-us.apache.org/repos/asf/libcloud/blob/43cec4eb/libcloud/compute/drivers/gce.py ---------------------------------------------------------------------- diff --git a/libcloud/compute/drivers/gce.py b/libcloud/compute/drivers/gce.py index 6b42ce6..065075a 100644 --- a/libcloud/compute/drivers/gce.py +++ b/libcloud/compute/drivers/gce.py @@ -243,7 +243,8 @@ class GCENodeImage(NodeImage): """ return self.driver.ex_delete_image(image=self) - def deprecate(self, replacement, state): + def deprecate(self, replacement, state, deprecated=None, obsolete=None, + deleted=None): """ Deprecate this image @@ -254,10 +255,20 @@ class GCENodeImage(NodeImage): \'DELETED\', \'DEPRECATED\' or \'OBSOLETE\'. :type state: ``str`` + :param deprecated: RFC3339 timestamp to mark DEPRECATED + :type deprecated: ``str`` or ``None`` + + :param obsolete: RFC3339 timestamp to mark OBSOLETE + :type obsolete: ``str`` or ``None`` + + :param deleted: RFC3339 timestamp to mark DELETED + :type deleted: ``str`` or ``None`` + :return: True if successful :rtype: ``bool`` """ - return self.driver.ex_deprecate_image(self, replacement, state) + return self.driver.ex_deprecate_image(self, replacement, state, + deprecated, obsolete, deleted) class GCENetwork(UuidMixin): @@ -722,7 +733,7 @@ class GCENodeDriver(NodeDriver): Return a list of image objects for a project. :keyword ex_project: Optional alternate project name. - :type ex_project: ``str`` or ``None`` + :type ex_project: ``str``, ``list`` of ``str``, or ``None`` :return: List of GCENodeImage objects :rtype: ``list`` of :class:`GCENodeImage` @@ -730,18 +741,25 @@ class GCENodeDriver(NodeDriver): request = '/global/images' if ex_project is None: response = self.connection.request(request, method='GET').object + list_images = [self._to_node_image(i) for i in + response.get('items', [])] else: + list_images = [] # Save the connection request_path save_request_path = self.connection.request_path - # Override the connection request path - new_request_path = save_request_path.replace(self.project, - ex_project) - self.connection.request_path = new_request_path - response = self.connection.request(request, method='GET').object + if isinstance(ex_project, str): + ex_project = [ex_project] + for proj in ex_project: + # Override the connection request path + new_request_path = save_request_path.replace(self.project, + proj) + self.connection.request_path = new_request_path + response = self.connection.request(request, + method='GET').object + list_images.extend([self._to_node_image(i) for i in + response.get('items', [])]) # Restore the connection request_path self.connection.request_path = save_request_path - list_images = [self._to_node_image(i) for i in - response.get('items', [])] return list_images def list_locations(self): @@ -2186,7 +2204,8 @@ class GCENodeDriver(NodeDriver): self.connection.async_request(request, method='DELETE') return True - def ex_deprecate_image(self, image, replacement, state=None): + def ex_deprecate_image(self, image, replacement, state=None, + deprecated=None, obsolete=None, deleted=None): """ Deprecate a specific image resource. @@ -2199,6 +2218,15 @@ class GCENodeDriver(NodeDriver): :param state: State of the image :type state: ``str`` + :param deprecated: RFC3339 timestamp to mark DEPRECATED + :type deprecated: ``str`` or ``None`` + + :param obsolete: RFC3339 timestamp to mark OBSOLETE + :type obsolete: ``str`` or ``None`` + + :param deleted: RFC3339 timestamp to mark DELETED + :type deleted: ``str`` or ``None`` + :return: True if successful :rtype: ``bool`` """ @@ -2222,6 +2250,27 @@ class GCENodeDriver(NodeDriver): 'replacement': replacement.extra['selfLink'], } + if deprecated is not None: + try: + _ = timestamp_to_datetime(deprecated) # NOQA + except: + raise ValueError('deprecated must be an RFC3339 timestamp') + image_data['deprecated'] = deprecated + + if obsolete is not None: + try: + _ = timestamp_to_datetime(obsolete) # NOQA + except: + raise ValueError('obsolete must be an RFC3339 timestamp') + image_data['obsolete'] = obsolete + + if deleted is not None: + try: + _ = timestamp_to_datetime(deleted) # NOQA + except: + raise ValueError('deleted must be an RFC3339 timestamp') + image_data['deleted'] = deleted + request = '/global/images/%s/deprecate' % (image.name) self.connection.request( @@ -2527,7 +2576,7 @@ class GCENodeDriver(NodeDriver): response = self.connection.request(request, method='GET').object return self._to_forwarding_rule(response) - def ex_get_image(self, partial_name): + def ex_get_image(self, partial_name, ex_project_list=None): """ Return an GCENodeImage object based on the name or link provided. @@ -2542,10 +2591,11 @@ class GCENodeDriver(NodeDriver): if partial_name.startswith('https://'): response = self.connection.request(partial_name, method='GET') return self._to_node_image(response.object) - image = self._match_images(None, partial_name) + image = self._match_images(ex_project_list, partial_name) if not image: if (partial_name.startswith('debian') or - partial_name.startswith('backports')): + partial_name.startswith('backports') or + partial_name.startswith('nvme-backports')): image = self._match_images('debian-cloud', partial_name) elif partial_name.startswith('centos'): image = self._match_images('centos-cloud', partial_name) @@ -3420,11 +3470,24 @@ class GCENodeDriver(NodeDriver): :rtype: :class:`GCENodeImage` """ extra = {} - extra['preferredKernel'] = image.get('preferredKernel', None) + if 'preferredKernel' in image: + extra['preferredKernel'] = image.get('preferredKernel', None) extra['description'] = image.get('description', None) extra['creationTimestamp'] = image.get('creationTimestamp') extra['selfLink'] = image.get('selfLink') - extra['deprecated'] = image.get('deprecated', None) + if 'deprecated' in image: + extra['deprecated'] = image.get('deprecated', None) + extra['sourceType'] = image.get('sourceType', None) + extra['rawDisk'] = image.get('rawDisk', None) + extra['status'] = image.get('status', None) + extra['archiveSizeBytes'] = image.get('archiveSizeBytes', None) + extra['diskSizeGb'] = image.get('diskSizeGb', None) + if 'sourceDisk' in image: + extra['sourceDisk'] = image.get('sourceDisk', None) + if 'sourceDiskId' in image: + extra['sourceDiskId'] = image.get('sourceDiskId', None) + if 'licenses' in image: + extra['licenses'] = image.get('licenses', None) return GCENodeImage(id=image['id'], name=image['name'], driver=self, extra=extra) @@ -3512,27 +3575,11 @@ class GCENodeDriver(NodeDriver): :rtype: :class:`GCENodeSize` """ extra = {} - disk_size = 10 extra['selfLink'] = machine_type.get('selfLink') - extra['creationTimestamp'] = machine_type.get('creationTimestamp') extra['zone'] = self.ex_get_zone(machine_type['zone']) extra['description'] = machine_type.get('description') extra['guestCpus'] = machine_type.get('guestCpus') - extra['memoryMb'] = machine_type.get('memoryMb') - extra['maximumPersistentDisks'] = \ - machine_type.get('maximumPersistentDisks') - if 'imageSpaceGb' in machine_type: - extra['imageSpaceGb'] = machine_type.get('imageSpaceGb') - disk_size = extra['imageSpaceGb'] - if 'maximumPersistentDisksSizeGb' in machine_type: - extra['maximumPersistentDisksSizeGb'] = \ - int(machine_type.get('maximumPersistentDisksSizeGb')) - disk_size = extra['maximumPersistentDisksSizeGb'] - if 'deprecated' in machine_type: - extra['deprecated'] = machine_type.get('deprecated') - if 'scratchDisks' in machine_type: - extra['scratchDisks'] = machine_type.get('scratchDisks') - + extra['creationTimestamp'] = machine_type.get('creationTimestamp') try: price = self._get_size_price(size_id=machine_type['name']) except KeyError: @@ -3540,8 +3587,8 @@ class GCENodeDriver(NodeDriver): return GCENodeSize(id=machine_type['id'], name=machine_type['name'], ram=machine_type.get('memoryMb'), - disk=disk_size, bandwidth=0, price=price, - driver=self, extra=extra) + disk=machine_type.get('imageSpaceGb'), + bandwidth=0, price=price, driver=self, extra=extra) def _to_project(self, project): """ http://git-wip-us.apache.org/repos/asf/libcloud/blob/43cec4eb/libcloud/test/compute/fixtures/gce/projects_debian-cloud_global_images.json ---------------------------------------------------------------------- diff --git a/libcloud/test/compute/fixtures/gce/projects_debian-cloud_global_images.json b/libcloud/test/compute/fixtures/gce/projects_debian-cloud_global_images.json index 32de60d..19bdc29 100644 --- a/libcloud/test/compute/fixtures/gce/projects_debian-cloud_global_images.json +++ b/libcloud/test/compute/fixtures/gce/projects_debian-cloud_global_images.json @@ -42,7 +42,9 @@ "archiveSizeBytes": "255972840", "creationTimestamp": "2013-05-09T12:56:21.720-07:00", "deprecated": { - "deprecated": "2013-11-12T21:00:00Z", + "deprecated": "2064-03-11T20:18:36.194-07:00", + "obsolete": "2074-03-11T20:18:36.194-07:00", + "deleted": "2084-03-11T20:18:36.194-07:00", "replacement": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131014", "state": "DEPRECATED" }, @@ -162,7 +164,9 @@ "archiveSizeBytes": "300710522", "creationTimestamp": "2013-10-11T09:26:47.736-07:00", "deprecated": { - "deprecated": "2013-11-14T00:00:00Z", + "deprecated": "2064-03-11T20:18:36.194-07:00", + "obsolete": "2074-03-11T20:18:36.194-07:00", + "deleted": "2084-03-11T20:18:36.194-07:00", "replacement": "https://www.googleapis.com/compute/v1/projects/debian-cloud/global/images/debian-7-wheezy-v20131014", "state": "DEPRECATED" }, http://git-wip-us.apache.org/repos/asf/libcloud/blob/43cec4eb/libcloud/test/compute/fixtures/gce/zones_us-central1-a_machineTypes_n1-standard-1.json ---------------------------------------------------------------------- diff --git a/libcloud/test/compute/fixtures/gce/zones_us-central1-a_machineTypes_n1-standard-1.json b/libcloud/test/compute/fixtures/gce/zones_us-central1-a_machineTypes_n1-standard-1.json index 98608d5..d1b3d74 100644 --- a/libcloud/test/compute/fixtures/gce/zones_us-central1-a_machineTypes_n1-standard-1.json +++ b/libcloud/test/compute/fixtures/gce/zones_us-central1-a_machineTypes_n1-standard-1.json @@ -1,13 +1,14 @@ { - "kind": "compute#machineType", - "id": "12907738072351752276", - "creationTimestamp": "2012-06-07T13:48:14.670-07:00", - "name": "n1-standard-1", - "description": "1 vCPU, 3.75 GB RAM", - "guestCpus": 1, - "memoryMb": 3840, - "maximumPersistentDisks": 16, - "maximumPersistentDisksSizeGb": "10240", - "zone": "us-central1-a", - "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-standard-1" -} + "creationTimestamp": "2012-06-07T13:48:14.670-07:00", + "description": "1 vCPU, 3.75 GB RAM", + "guestCpus": 1, + "id": "11077240422128681563", + "imageSpaceGb": 10, + "kind": "compute#machineType", + "maximumPersistentDisks": 16, + "maximumPersistentDisksSizeGb": "10240", + "memoryMb": 3840, + "name": "n1-standard-1", + "selfLink": "https://www.googleapis.com/compute/v1/projects/project_name/zones/us-central1-a/machineTypes/n1-standard-1", + "zone": "us-central1-a" +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/libcloud/blob/43cec4eb/libcloud/test/compute/test_gce.py ---------------------------------------------------------------------- diff --git a/libcloud/test/compute/test_gce.py b/libcloud/test/compute/test_gce.py index 2e3d6a6..05ab6fc 100644 --- a/libcloud/test/compute/test_gce.py +++ b/libcloud/test/compute/test_gce.py @@ -142,8 +142,10 @@ class GCENodeDriverTest(LibcloudTestCase, TestCaseMixin): def test_list_images(self): local_images = self.driver.list_images() debian_images = self.driver.list_images(ex_project='debian-cloud') + local_plus_deb = self.driver.list_images(['debian-cloud', 'project_name']) self.assertEqual(len(local_images), 3) self.assertEqual(len(debian_images), 19) + self.assertEqual(len(local_plus_deb), 22) self.assertEqual(local_images[0].name, 'debian-7-wheezy-v20130617') self.assertEqual(local_images[1].name, 'centos-6-v20131118') @@ -531,9 +533,18 @@ class GCENodeDriverTest(LibcloudTestCase, TestCaseMixin): self.assertTrue(deleted) def test_ex_deprecate_image(self): - image = self.driver.ex_get_image('debian-6') - deprecated = image.deprecate('debian-7', 'DEPRECATED') + dep_ts = '2064-03-11T20:18:36.194-07:00' + obs_ts = '2074-03-11T20:18:36.194-07:00' + del_ts = '2084-03-11T20:18:36.194-07:00' + image = self.driver.ex_get_image('debian-6-squeeze-v20130926') + deprecated = image.deprecate('debian-7', 'DEPRECATED', + deprecated=dep_ts, + obsolete=obs_ts, + deleted=del_ts) self.assertTrue(deprecated) + self.assertTrue(image.extra['deprecated']['deprecated'], dep_ts) + self.assertTrue(image.extra['deprecated']['obsolete'], obs_ts) + self.assertTrue(image.extra['deprecated']['deleted'], del_ts) def test_ex_destroy_firewall(self): firewall = self.driver.ex_get_firewall('lcfirewall') @@ -627,6 +638,10 @@ class GCENodeDriverTest(LibcloudTestCase, TestCaseMixin): self.assertEqual(image.name, 'debian-6-squeeze-v20130926') self.assertTrue(image.extra['description'].startswith('Debian')) + partial_name = 'debian-7' + image = self.driver.ex_get_image(partial_name, ['debian-cloud']) + self.assertEqual(image.name, 'debian-7-wheezy-v20131120') + def test_ex_copy_image(self): name = 'coreos' url = 'gs://storage.core-os.net/coreos/amd64-generic/247.0.0/coreos_production_gce.tar.gz' @@ -676,12 +691,9 @@ class GCENodeDriverTest(LibcloudTestCase, TestCaseMixin): size = self.driver.ex_get_size(size_name) self.assertEqual(size.name, size_name) self.assertEqual(size.extra['zone'].name, 'us-central1-a') - self.assertEqual(size.disk, 10240) + self.assertEqual(size.disk, 10) self.assertEqual(size.ram, 3840) self.assertEqual(size.extra['guestCpus'], 1) - self.assertEqual(size.extra['memoryMb'], 3840) - self.assertEqual(size.extra['maximumPersistentDisks'], 16) - self.assertEqual(size.extra['maximumPersistentDisksSizeGb'], 10240) def test_ex_get_targetpool(self): targetpool_name = 'lctargetpool'
