Bug 1:对不可迭代类进行迭代(libcloud.storage.driver.cloudfile line. 141-142)
使用libcloud连接自搭建swift服务,自己在服务器上搭建swift服务,利用keystone进行认证(swift自带认证服务swauth libcloud好像不支持),配置好keystone服务器(keystone服务器ip为192.168.137.201),先利用curl命令确认swift和keystone服务是正常运行。
执行如下几行代码进行openstack StorageDriver类的初始化:
1 CloudDriver = get_driver(Provider.CLOUDFILES_SWIFT) 2 driver = CloudDriver(user_id, passwd, secure=False, region='RegionOne', 3 ex_tenant_name=tenant_name, 4 ex_force_auth_url='http://192.168.137.201:35357', 5 ex_force_auth_version='2.0_passwd', 6 ex_force_service_type='object-store', 7 ex_force_service_name='Swift')
注意,其中auth_url要与自己认证服务器url一致,且auth_version/service_type/service_name等信息均要与keystone服务器中相应信息一致,否则将无法获取endpoint!
即便如此,仍旧无法获得endpoint,经过跟踪调试,最终将错误定位于libcloud.storage.driver中cloudfiles.py文件中line. 141-142:
1 if PUBLIC_ENDPOINT_KEY in endpoint: 2 return endpoint[PUBLIC_ENDPOINT_KEY]
此处endpoint为OpenStackServiceCatalogEntryEndpoint类对象,此类中并未定义迭代方法,无法对一个不可迭代类进行迭代!将上面两行代码修改为:
1 if endpoint.url: 2 return endpoint.url
代码即可正常运行。
Bug 2:死循环(libcloud.storage.driver.cloudfiles line. 728-751)
1 while True: 2 container_name_encoded = 3 self._encode_container_name(container.name) 4 response = self.connection.request('/%s' % 5 (container_name_encoded), 6 params=params) 7 8 if response.status == httplib.NO_CONTENT: 9 # Empty or non-existent container 10 break 11 elif response.status == httplib.OK: 12 objects = self._to_object_list(json.loads(response.body), 13 container) 14 15 if len(objects) == 0: 16 break 17 18 for obj in objects: 19 yield obj 20 params['marker'] = obj.name
此循环,是为了列出一个container中符合要求的所有object,但在依照此代码对百度云存储进行封装时输出结果陷入死循环,在最后一行添加break语句后代码正常运行。
在连接swift时尚未运行此段代码,不知其是否也会出现问题。
Bug 3:对上传文件进行二次迭代错误(libcloud.storage.base line. 622-637 734-782)
line 734:
1 generator = libcloud.utils.files.read_in_chunks(iterator, chunk_size) 2 3 bytes_transferred = 0 4 try: 5 chunk = next(generator) 6 except StopIteration: 7 # Special case when StopIteration is thrown on the first iteration 8 # create a 0-byte long object 9 chunk = ''
对文件的流式上传,每次均需要调用base.py中_upload_object()和_stream_data()函数。而我在对百度云存储封装流式上传函数时,每次上传文件均不成功,上面_stream_data()中代码每次都会进入StopIteration异常处理流程,上传一个空文件。
后来我发现是因为百度云不支持文件分块编码上传,故supports_chunked_encoding =False。在_upload_object()中会执行一次read_in_chunks(),而上面代码再次执行read_in_chunks()时,文件迭代器iterator已经指向文件末尾,故chunk = next(generator)总是异常。
仔细思考后,我在read_in_chunks()函数(libcloud.utils.file line. 36-94)开头添加如下两行代码:
1 if isinstance(iterator, file) and iterator.tell(): 2 iterator.seek(0,os.SEEK_SET)
即如果迭代器类型为文件且文件当前位置不为起始位置,将其位置置于起始位置。后代码正常运行。
开源代码也是人写的,也许在以后使用libcloud过程中,会发现更多bug。勿迷信他人代码,相信自己判断。