Repository: libcloud Updated Branches: refs/heads/trunk d8740d0af -> 0486f77e7
[google compute] Add License resource to GCE driver Closes #420 Signed-off-by: Eric Johnson <[email protected]> Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/0486f77e Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/0486f77e Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/0486f77e Branch: refs/heads/trunk Commit: 0486f77e7b3c6a70ce11fff45401b8d3767876bc Parents: d8740d0 Author: Eric Johnson <[email protected]> Authored: Fri Dec 19 20:46:38 2014 +0000 Committer: Eric Johnson <[email protected]> Committed: Sun Dec 21 17:09:58 2014 +0000 ---------------------------------------------------------------------- CHANGES.rst | 4 + libcloud/compute/drivers/gce.py | 82 +++++++++- .../gce/projects_suse-cloud_global_images.json | 160 +++++++++++++++++++ ...ects_suse-cloud_global_licenses_sles_11.json | 6 + ...ects_suse-cloud_global_licenses_sles_12.json | 6 + libcloud/test/compute/test_gce.py | 23 +++ 6 files changed, 279 insertions(+), 2 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/libcloud/blob/0486f77e/CHANGES.rst ---------------------------------------------------------------------- diff --git a/CHANGES.rst b/CHANGES.rst index 008d836..7ce653c 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -16,6 +16,10 @@ General Compute ~~~~~~~ +- GCE Licenses added to the GCE driver. + (GITHUB-420) + [Eric Johnson] + - GCE Projects support common instance metadata and usage export buckets (GITHUB-409) [Eric Johnson] http://git-wip-us.apache.org/repos/asf/libcloud/blob/0486f77e/libcloud/compute/drivers/gce.py ---------------------------------------------------------------------- diff --git a/libcloud/compute/drivers/gce.py b/libcloud/compute/drivers/gce.py index f44945e..a63c996 100644 --- a/libcloud/compute/drivers/gce.py +++ b/libcloud/compute/drivers/gce.py @@ -77,6 +77,21 @@ class GCEConnection(GoogleBaseConnection): project) +class GCELicense(UuidMixin): + """A GCE License used to track software usage in GCE nodes.""" + def __init__(self, id, name, driver, charges_use_fee, extra=None): + self.id = str(id) + self.name = name + self.driver = driver + self.charges_use_fee = charges_use_fee + self.extra = extra or {} + UuidMixin.__init__(self) + + def __repr__(self): + return '<GCELicense id="%s" name="%s" charges_use_fee="%s">' % ( + self.id, self.name, self.charges_use_fee) + + class GCEDiskType(UuidMixin): """A GCE DiskType resource.""" def __init__(self, id, name, zone, driver, extra=None): @@ -3059,6 +3074,29 @@ class GCENodeDriver(NodeDriver): self.connection.async_request(request, method='DELETE') return True + def ex_get_license(self, project, name): + """ + Return a License object for specified project and name. + + :param name: The project to reference when looking up the license. + :type name: ``str`` + + :param name: The name of the License + :type name: ``str`` + + :return: A DiskType object for the name + :rtype: :class:`GCEDiskType` + """ + saved_request_path = self.connection.request_path + new_request_path = saved_request_path.replace(self.project, project) + self.connection.request_path = new_request_path + + request = '/global/licenses/%s' % (name) + response = self.connection.request(request, method='GET').object + self.connection.request_path = saved_request_path + + return self._to_license(response) + def ex_get_disktype(self, name, zone=None): """ Return a DiskType object based on a name and optional zone. @@ -4158,7 +4196,8 @@ class GCENodeDriver(NodeDriver): if 'sourceDiskId' in image: extra['sourceDiskId'] = image.get('sourceDiskId', None) if 'licenses' in image: - extra['licenses'] = image.get('licenses', None) + lic_objs = self._licenses_from_urls(licenses=image['licenses']) + extra['licenses'] = lic_objs return GCENodeImage(id=image['id'], name=image['name'], driver=self, extra=extra) @@ -4336,7 +4375,8 @@ class GCENodeDriver(NodeDriver): if 'storageBytesStatus' in snapshot: extra['storageBytesStatus'] = snapshot['storageBytesStatus'] if 'licenses' in snapshot: - extra['licenses'] = snapshot['licenses'] + lic_objs = self._licenses_from_urls(licenses=snapshot['licenses']) + extra['licenses'] = lic_objs return GCESnapshot(id=snapshot['id'], name=snapshot['name'], size=snapshot['diskSizeGb'], @@ -4453,6 +4493,24 @@ class GCENodeDriver(NodeDriver): maintenance_windows=zone.get('maintenanceWindows'), deprecated=deprecated, driver=self, extra=extra) + def _to_license(self, license): + """ + Return a License object from the json-response dictionary. + + :param license: The dictionary describing the license. + :type license: ``dict`` + + :return: License object + :rtype: :class:`GCELicense` + """ + extra = {} + extra['selfLink'] = license.get('selfLink') + extra['kind'] = license.get('kind') + + return GCELicense(id=license['name'], name=license['name'], + charges_use_fee=license['chargesUseFee'], + driver=self, extra=extra) + def _set_project_metadata(self, metadata=None, force=False, current_keys=""): """ @@ -4497,3 +4555,23 @@ class GCENodeDriver(NodeDriver): new_md = updated_md new_md.append({'key': 'sshKeys', 'value': current_keys}) return new_md + + def _licenses_from_urls(self, licenses): + """ + Convert a list of license selfLinks into a list of :class:`GCELicense` + objects. + + :param licenses: A list of GCE license selfLink URLs. + :type licenses: ``list`` of ``str`` + + :return: List of :class:`GCELicense` objects. + :rtype: ``list`` + """ + return_list = [] + for license in licenses: + selfLink_parts = license.split('/') + lic_proj = selfLink_parts[6] + lic_name = selfLink_parts[-1] + return_list.append(self.ex_get_license(project=lic_proj, + name=lic_name)) + return return_list http://git-wip-us.apache.org/repos/asf/libcloud/blob/0486f77e/libcloud/test/compute/fixtures/gce/projects_suse-cloud_global_images.json ---------------------------------------------------------------------- diff --git a/libcloud/test/compute/fixtures/gce/projects_suse-cloud_global_images.json b/libcloud/test/compute/fixtures/gce/projects_suse-cloud_global_images.json new file mode 100644 index 0000000..820df9f --- /dev/null +++ b/libcloud/test/compute/fixtures/gce/projects_suse-cloud_global_images.json @@ -0,0 +1,160 @@ +{ + "kind": "compute#imageList", + "selfLink": "https://www.googleapis.com/compute/v1/projects/suse-cloud/global/images", + "id": "projects/suse-cloud/global/images", + "items": [ + { + "kind": "compute#image", + "selfLink": "https://www.googleapis.com/compute/v1/projects/suse-cloud/global/images/sles-11-sp3-v20140306", + "id": "3727805086509383287", + "creationTimestamp": "2014-03-06T13:13:29.791-08:00", + "name": "sles-11-sp3-v20140306", + "description": "", + "sourceType": "RAW", + "rawDisk": { + "source": "", + "containerType": "TAR" + }, + "deprecated": { + "state": "DEPRECATED", + "replacement": "https://content.googleapis.com/compute/v1/projects/suse-cloud/global/images/sles-11-sp3-v20140609", + "deprecated": "2014-06-09T00:00:00Z" + }, + "status": "READY", + "archiveSizeBytes": "354497936", + "diskSizeGb": "8", + "licenses": [ + "https://content.googleapis.com/compute/v1/projects/suse-cloud/global/licenses/sles-11" + ] + }, + { + "kind": "compute#image", + "selfLink": "https://www.googleapis.com/compute/v1/projects/suse-cloud/global/images/sles-11-sp3-v20140609", + "id": "10656986931280984622", + "creationTimestamp": "2014-06-09T10:29:06.385-07:00", + "name": "sles-11-sp3-v20140609", + "description": "", + "sourceType": "RAW", + "rawDisk": { + "source": "", + "containerType": "TAR" + }, + "deprecated": { + "state": "DEPRECATED", + "replacement": "https://content.googleapis.com/compute/v1/projects/suse-cloud/global/images/sles-11-sp3-v20140712", + "deprecated": "2014-07-12T00:00:00Z" + }, + "status": "READY", + "archiveSizeBytes": "1191603546", + "diskSizeGb": "8", + "licenses": [ + "https://content.googleapis.com/compute/v1/projects/suse-cloud/global/licenses/sles-11" + ] + }, + { + "kind": "compute#image", + "selfLink": "https://www.googleapis.com/compute/v1/projects/suse-cloud/global/images/sles-11-sp3-v20140712", + "id": "3415847542100990147", + "creationTimestamp": "2014-07-12T03:39:17.695-07:00", + "name": "sles-11-sp3-v20140712", + "description": "SUSE Linux Enterprise 11 SP3 built on 2014-07-12", + "sourceType": "RAW", + "rawDisk": { + "source": "", + "containerType": "TAR" + }, + "deprecated": { + "state": "DEPRECATED", + "replacement": "https://content.googleapis.com/compute/v1/projects/suse-cloud/global/images/sles-11-sp3-v20140826", + "deprecated": "2014-06-26T00:00:00Z" + }, + "status": "READY", + "archiveSizeBytes": "1071997074", + "diskSizeGb": "8", + "licenses": [ + "https://content.googleapis.com/compute/v1/projects/suse-cloud/global/licenses/sles-11" + ] + }, + { + "kind": "compute#image", + "selfLink": "https://www.googleapis.com/compute/v1/projects/suse-cloud/global/images/sles-11-sp3-v20140826", + "id": "588070221570840387", + "creationTimestamp": "2014-08-26T14:46:38.449-07:00", + "name": "sles-11-sp3-v20140826", + "description": "SUSE Linux Enterprise 11 SP3 released on 2014-06-26, built on 2014-08-20", + "sourceType": "RAW", + "rawDisk": { + "source": "", + "containerType": "TAR" + }, + "deprecated": { + "state": "DEPRECATED", + "replacement": "https://content.googleapis.com/compute/v1/projects/suse-cloud/global/images/sles-11-sp3-v20140930", + "deprecated": "2014-10-30T00:00:00Z" + }, + "status": "READY", + "archiveSizeBytes": "1072617138", + "diskSizeGb": "8", + "licenses": [ + "https://content.googleapis.com/compute/v1/projects/suse-cloud/global/licenses/sles-11" + ] + }, + { + "kind": "compute#image", + "selfLink": "https://www.googleapis.com/compute/v1/projects/suse-cloud/global/images/sles-11-sp3-v20140930", + "id": "3132872945991231828", + "creationTimestamp": "2014-09-30T08:27:46.201-07:00", + "name": "sles-11-sp3-v20140930", + "description": "SUSE Linux Enterprise Server 11 SP3", + "sourceType": "RAW", + "rawDisk": { + "source": "", + "containerType": "TAR" + }, + "status": "READY", + "archiveSizeBytes": "1102825953", + "diskSizeGb": "8", + "licenses": [ + "https://content.googleapis.com/compute/v1/projects/suse-cloud/global/licenses/sles-11" + ] + }, + { + "kind": "compute#image", + "selfLink": "https://www.googleapis.com/compute/v1/projects/suse-cloud/global/images/sles-11-sp3-v20141105", + "id": "14793554030256860036", + "creationTimestamp": "2014-11-05T16:11:49.996-08:00", + "name": "sles-11-sp3-v20141105", + "description": "SUSE Linux Enterprise Server 11 SP3 built on 2014-11-05", + "sourceType": "RAW", + "rawDisk": { + "source": "", + "containerType": "TAR" + }, + "status": "READY", + "archiveSizeBytes": "1075782309", + "diskSizeGb": "8", + "licenses": [ + "https://content.googleapis.com/compute/v1/projects/suse-cloud/global/licenses/sles-11" + ] + }, + { + "kind": "compute#image", + "selfLink": "https://www.googleapis.com/compute/v1/projects/suse-cloud/global/images/sles-12-v20141023", + "id": "15301906009182317384", + "creationTimestamp": "2014-10-26T08:14:59.932-07:00", + "name": "sles-12-v20141023", + "description": "SUSE Linux Enterprise Server 12 built on 2014-10-23", + "sourceType": "RAW", + "rawDisk": { + "source": "", + "containerType": "TAR" + }, + "status": "READY", + "archiveSizeBytes": "1525260684", + "diskSizeGb": "8", + "licenses": [ + "https://content.googleapis.com/compute/v1/projects/suse-cloud/global/licenses/sles-12" + ] + } + ] +} http://git-wip-us.apache.org/repos/asf/libcloud/blob/0486f77e/libcloud/test/compute/fixtures/gce/projects_suse-cloud_global_licenses_sles_11.json ---------------------------------------------------------------------- diff --git a/libcloud/test/compute/fixtures/gce/projects_suse-cloud_global_licenses_sles_11.json b/libcloud/test/compute/fixtures/gce/projects_suse-cloud_global_licenses_sles_11.json new file mode 100644 index 0000000..90fd2ad --- /dev/null +++ b/libcloud/test/compute/fixtures/gce/projects_suse-cloud_global_licenses_sles_11.json @@ -0,0 +1,6 @@ +{ + "kind": "compute#license", + "selfLink": "https://www.googleapis.com/compute/v1/projects/suse-cloud/global/licenses/sles-11", + "name": "sles-11", + "chargesUseFee": true +} http://git-wip-us.apache.org/repos/asf/libcloud/blob/0486f77e/libcloud/test/compute/fixtures/gce/projects_suse-cloud_global_licenses_sles_12.json ---------------------------------------------------------------------- diff --git a/libcloud/test/compute/fixtures/gce/projects_suse-cloud_global_licenses_sles_12.json b/libcloud/test/compute/fixtures/gce/projects_suse-cloud_global_licenses_sles_12.json new file mode 100644 index 0000000..bf1e32c --- /dev/null +++ b/libcloud/test/compute/fixtures/gce/projects_suse-cloud_global_licenses_sles_12.json @@ -0,0 +1,6 @@ +{ + "kind": "compute#license", + "selfLink": "https://www.googleapis.com/compute/v1/projects/suse-cloud/global/licenses/sles-12", + "name": "sles-12", + "chargesUseFee": true +} http://git-wip-us.apache.org/repos/asf/libcloud/blob/0486f77e/libcloud/test/compute/test_gce.py ---------------------------------------------------------------------- diff --git a/libcloud/test/compute/test_gce.py b/libcloud/test/compute/test_gce.py index 8efeaa1..567276e 100644 --- a/libcloud/test/compute/test_gce.py +++ b/libcloud/test/compute/test_gce.py @@ -224,6 +224,11 @@ class GCENodeDriverTest(LibcloudTestCase, TestCaseMixin): names = [s.name for s in sizes_all] self.assertEqual(names.count('n1-standard-1'), 5) + def test_ex_get_license(self): + license = self.driver.ex_get_license('suse-cloud', 'sles-12') + self.assertTrue(license.name, 'sles-12') + self.assertTrue(license.charges_use_fee) + def test_list_disktypes(self): disktypes = self.driver.ex_list_disktypes() disktypes_all = self.driver.ex_list_disktypes('all') @@ -733,6 +738,12 @@ class GCENodeDriverTest(LibcloudTestCase, TestCaseMixin): self.assertEqual(fwr.targetpool.name, 'lctargetpool') self.assertEqual(fwr.protocol, 'TCP') + def test_ex_get_image_license(self): + image = self.driver.ex_get_image('sles-12-v20141023') + self.assertTrue('licenses' in image.extra) + self.assertTrue(image.extra['licenses'][0].name, 'sles-12') + self.assertTrue(image.extra['licenses'][0].charges_use_fee) + def test_ex_get_image(self): partial_name = 'debian-7' image = self.driver.ex_get_image(partial_name) @@ -1402,6 +1413,18 @@ class GCEMockHttp(MockHttpTestCase): body = self.fixtures.load('project.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) + def _projects_suse_cloud_global_licenses_sles_11(self, method, url, body, headers): + body = self.fixtures.load('projects_suse-cloud_global_licenses_sles_11.json') + return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) + + def _projects_suse_cloud_global_licenses_sles_12(self, method, url, body, headers): + body = self.fixtures.load('projects_suse-cloud_global_licenses_sles_12.json') + return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) + + def _projects_suse_cloud_global_images(self, method, url, body, headers): + body = self.fixtures.load('projects_suse-cloud_global_images.json') + return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK]) + def _projects_debian_cloud_global_images(self, method, url, body, headers): body = self.fixtures.load('projects_debian-cloud_global_images.json') return (httplib.OK, body, self.json_hdr, httplib.responses[httplib.OK])
