charles walker created LIBCLOUD-459:
---------------------------------------
Summary: GCE issue when a region has no availability zone
Key: LIBCLOUD-459
URL: https://issues.apache.org/jira/browse/LIBCLOUD-459
Project: Libcloud
Issue Type: Bug
Components: Compute
Affects Versions: 0.14.0-beta3
Environment: AWS Ubuntu node with pull from last libcloud version
Reporter: charles walker
How to reproduce (on clean AWS Ubuntu instance) :
{noformat}
sudo apt-get install python-setuptools
sudo apt-get install git
curl -O https://pypi.python.org/packages/source/p/pip/pip-1.4.1.tar.gz
tar xvzf pip-1.4.1.tar.gz
cd pip-1.4.1
sudo python setup.py install
sudo pip install
git+https://git-wip-us.apache.org/repos/asf/libcloud.git@trunk#egg=apache-libcloud
{noformat}
(originaly done on 10DEC2013)
Then try the following python script (with vi Test.py) :
{noformat}
#!/usr/bin/python
from libcloud.compute.types import Provider
from libcloud.compute.providers import get_driver
#GCE general settings + instance settings
GCE_USER="XXXXXXXXXXXXXXXXXXXX.apps.googleusercontent.com"
GCE_PASS=" XXXXXXXXXXXXXXXXXXXX "
GCE_PROJECT=" XXXXXXXXXXXXXXXXXXXX "
GCE_INSTANCE_NAME="TEST_GCE"
GCE_Driver = get_driver(Provider.GCE)
GCE_Conex = GCE_Driver(GCE_USER, GCE_PASS,
project=GCE_PROJECT,auth_type="IA",datacenter="us-central1-a")
print ("images : " + str(GCE_Conex.list_images()))
print ("sizes : " + str(GCE_Conex.list_sizes()))
print ("locations : " + str(GCE_Conex.list_locations()))
{noformat}
(minimal code – change the GCE_ params for the script to be usable)
Then launch : python Test.py
The script will fails with the following stack :
{noformat}
Traceback (most recent call last):
File "Test.py", line 63, in <module>
listGce()
File "Test.py", line 55, in listGce
GCE_Conex = GCE_Driver(GCE_USER, GCE_PASS,
project=GCE_PROJECT,auth_type="IA",datacenter="us-central1-a")
File
"/usr/local/lib/python2.7/dist-packages/libcloud/compute/drivers/gce.py", line
529, in __init__
self.region_list = self.ex_list_regions()
File
"/usr/local/lib/python2.7/dist-packages/libcloud/compute/drivers/gce.py", line
912, in ex_list_regions
list_regions = [self._to_region(r) for r in response['items']]
File
"/usr/local/lib/python2.7/dist-packages/libcloud/compute/drivers/gce.py", line
2609, in _to_region
zones = [self.ex_get_zone(z) for z in region['zones']]
KeyError: 'zones'
{noformat}
So I debug by adding some logs in libcould with the following changes :
{noformat}
def _to_region(self, region):
"""
Return a Region object from the json-response dictionary.
:param region: The dictionary describing the region.
:type region: ``dict``
:return: Region object
:rtype: :class:`GCERegion`
"""
extra = {}
print("Working on region : " + str(region))
extra['selfLink'] = region['selfLink']
extra['creationTimestamp'] = region['creationTimestamp']
extra['description'] = region['description']
quotas = region.get('quotas')
zones = [self.ex_get_zone(z) for z in region['zones']]
# Work around a bug that will occasionally list missing zones in the
# region output
zones = [z for z in zones if z is not None]
deprecated = region.get('deprecated')
return GCERegion(id=region['id'], name=region['name'],
status=region['status'], zones=zones,
quotas=quotas, deprecated=deprecated,
driver=self, extra=extra)
{noformat}
which generate the following output :
{noformat}
Working on region : {u'status': u'UP', u'kind': u'compute#region',
u'description': u'europe-west1', u'quotas': [{u'usage': 0.0, u'metric':
u'CPUS', u'limit': 24.0}, {u'usage': 0.0, u'metric': u'DISKS_TOTAL_GB',
u'limit': 5120.0}, {u'usage': 0.0, u'metric': u'STATIC_ADDRESSES', u'limit':
7.0}, {u'usage': 0.0, u'metric': u'IN_USE_ADDRESSES', u'limit': 23.0}],
u'zones':
[u'https://www.googleapis.com/compute/v1beta16/projects/silicon-reason-334/zones/europe-west1-a',
u'https://www.googleapis.com/compute/v1beta16/projects/silicon-reason-334/zones/europe-west1-b'],
u'creationTimestamp': u'2013-11-15T07:46:07.251-08:00', u'id':
u'1385336798037303511', u'selfLink':
u'https://www.googleapis.com/compute/v1beta16/projects/silicon-reason-334/regions/europe-west1',
u'name': u'europe-west1'}
Working on region : {u'status': u'UP', u'kind': u'compute#region',
u'description': u'us-central1', u'quotas': [{u'usage': 0.0, u'metric': u'CPUS',
u'limit': 24.0}, {u'usage': 0.0, u'metric': u'DISKS_TOTAL_GB', u'limit':
5120.0}, {u'usage': 0.0, u'metric': u'STATIC_ADDRESSES', u'limit': 7.0},
{u'usage': 0.0, u'metric': u'IN_USE_ADDRESSES', u'limit': 23.0}], u'zones':
[u'https://www.googleapis.com/compute/v1beta16/projects/silicon-reason-334/zones/us-central1-a',
u'https://www.googleapis.com/compute/v1beta16/projects/silicon-reason-334/zones/us-central1-b'],
u'creationTimestamp': u'2013-11-15T07:46:07.260-08:00', u'id':
u'16772257450467573976', u'selfLink':
u'https://www.googleapis.com/compute/v1beta16/projects/silicon-reason-334/regions/us-central1',
u'name': u'us-central1'}
Working on region : {u'status': u'UP', u'kind': u'compute#region',
u'description': u'us-central2', u'quotas': [{u'usage': 0.0, u'metric': u'CPUS',
u'limit': 24.0}, {u'usage': 0.0, u'metric': u'DISKS_TOTAL_GB', u'limit':
5120.0}, {u'usage': 0.0, u'metric': u'STATIC_ADDRESSES', u'limit': 7.0},
{u'usage': 0.0, u'metric': u'IN_USE_ADDRESSES', u'limit': 23.0}],
u'creationTimestamp': u'2013-11-15T07:46:07.257-08:00', u'id':
u'11449717932546487924', u'selfLink':
u'https://www.googleapis.com/compute/v1beta16/projects/silicon-reason-334/regions/us-central2',
u'name': u'us-central2'}
{noformat}
The error seems due to the fact that the last region “us-central2” has no
“zones” defined. If you look on the function where I added the logs (just
below) you have the following comments :
{noformat}
# Work around a bug that will occasionally list missing zones in the
# region output
{noformat}
So I things I m not the first one which has such reponse without “zones”. It
seems (I m not a python expert) that the workaround will not works because
“zones” is not even present on the reponse for this “region”.
I modified the code to patch the function. Here is the new version :
{noformat}
def _to_region(self, region):
"""
Return a Region object from the json-response dictionary.
:param region: The dictionary describing the region.
:type region: ``dict``
:return: Region object
:rtype: :class:`GCERegion`
"""
extra = {}
print("Working on region : " + str(region))
extra['selfLink'] = region['selfLink']
extra['creationTimestamp'] = region['creationTimestamp']
extra['description'] = region['description']
quotas = region.get('quotas')
# Work around a bug that will occasionally list missing zones in the
# region output
zones=None
if ('zones' in region):
zones = [self.ex_get_zone(z) for z in region['zones']]
deprecated = region.get('deprecated')
return GCERegion(id=region['id'], name=region['name'],
status=region['status'], zones=zones,
quotas=quotas, deprecated=deprecated,
driver=self, extra=extra)
{noformat}
which works fine (I have a response and the python script works).
I check all open ticket and didn’t find anything related to this issue so here
I am.
--
This message was sent by Atlassian JIRA
(v6.1.4#6159)