blob: 9c382e57caefb8fb85b8756507f817d8367c014c [file] [log] [blame]
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements. See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import os
import mimetypes
import warnings
from httplib import HTTPResponse
SHOW_DEPRECATION_WARNING = True
SHOW_IN_DEVELOPMENT_WARNING = True
OLD_API_REMOVE_VERSION = '0.7.0'
CHUNK_SIZE = 8096
def read_in_chunks(iterator, chunk_size=None, fill_size=False):
"""
Return a generator which yields data in chunks.
@type iterator: C{Iterator}
@param response: An object which implements an iterator interface
or a File like object with read method.
@type chunk_size: C{int}
@param chunk_size: Optional chunk size (defaults to CHUNK_SIZE)
@type fill_size: C{bool}
@param fill_size: If True, make sure chunks are chunk_size in length
(except for last chunk).
"""
chunk_size = chunk_size or CHUNK_SIZE
if isinstance(iterator, (file, HTTPResponse)):
get_data = iterator.read
args = (chunk_size, )
else:
get_data = iterator.next
args = ()
data = ''
empty = False
while not empty or len(data) > 0:
if not empty:
try:
chunk = str(get_data(*args))
if len(chunk) > 0:
data += chunk
else:
empty = True
except StopIteration:
empty = True
if len(data) == 0:
raise StopIteration
if fill_size:
if empty or len(data) >= chunk_size:
yield data[:chunk_size]
data = data[chunk_size:]
else:
yield data
data = ''
def exhaust_iterator(iterator):
"""
Exhaust an iterator and return all data returned by it.
@type iterator: C{Iterator}
@param response: An object which implements an iterator interface
or a File like object with read method.
@rtype C{str}
@return Data returned by the iterator.
"""
data = ''
try:
chunk = str(iterator.next())
except StopIteration:
chunk = ''
while len(chunk) > 0:
data += chunk
try:
chunk = str(iterator.next())
except StopIteration:
chunk = ''
return data
def guess_file_mime_type(file_path):
filename = os.path.basename(file_path)
(mimetype, encoding) = mimetypes.guess_type(filename)
return mimetype, encoding
def deprecated_warning(module):
if SHOW_DEPRECATION_WARNING:
warnings.warn('This path has been deprecated and the module'
' is now available at "libcloud.compute.%s".'
' This path will be fully removed in libcloud %s.' %
(module, OLD_API_REMOVE_VERSION),
category=DeprecationWarning)
def in_development_warning(module):
if SHOW_IN_DEVELOPMENT_WARNING:
warnings.warn('The module %s is in development and your are advised '
'against using it in production.' % (module),
category=FutureWarning)
def str2dicts(data):
"""
Create a list of dictionaries from a whitespace and newline delimited text.
For example, this:
cpu 1100
ram 640
cpu 2200
ram 1024
becomes:
[{'cpu': '1100', 'ram': '640'}, {'cpu': '2200', 'ram': '1024'}]
"""
list_data = []
list_data.append({})
d = list_data[-1]
lines = data.split('\n')
for line in lines:
line = line.strip()
if not line:
d = {}
list_data.append(d)
d = list_data[-1]
continue
whitespace = line.find(' ')
if not whitespace:
continue
key = line[0:whitespace]
value = line[whitespace + 1:]
d.update({key: value})
list_data = [value for value in list_data if value != {}]
return list_data
def str2list(data):
"""
Create a list of values from a whitespace and newline delimited text
(keys are ignored).
For example, this:
ip 1.2.3.4
ip 1.2.3.5
ip 1.2.3.6
becomes:
['1.2.3.4', '1.2.3.5', '1.2.3.6']
"""
list_data = []
for line in data.split('\n'):
line = line.strip()
if not line:
continue
try:
splitted = line.split(' ')
# key = splitted[0]
value = splitted[1]
except Exception:
continue
list_data.append(value)
return list_data
def dict2str(data):
"""
Create a string with a whitespace and newline delimited text from a
dictionary.
For example, this:
{'cpu': '1100', 'ram': '640', 'smp': 'auto'}
becomes:
cpu 1100
ram 640
smp auto
cpu 2200
ram 1024
"""
result = ''
for k in data:
if data[k] != None:
result += '%s %s\n' % (str(k), str(data[k]))
else:
result += '%s\n' % str(k)
return result
def fixxpath(xpath, namespace=None):
# ElementTree wants namespaces in its xpaths, so here we add them.
if not namespace:
return xpath
return '/'.join(['{%s}%s' % (namespace, e) for e in xpath.split('/')])
def findtext(element, xpath, namespace=None):
return element.findtext(fixxpath(xpath=xpath, namespace=namespace))
def findattr(element, xpath, namespace=None):
return element.findtext(fixxpath(xpath=xpath, namespace=namespace))
def findall(element, xpath, namespace=None):
return element.findall(fixxpath(xpath=xpath, namespace=namespace))
def reverse_dict(dictionary):
return dict([(value, key) for key, value in dictionary.iteritems()])
def get_driver(drivers, provider):
"""
Get a driver.
@param drivers: Dictionary containing valid providers.
@param provider: Id of provider to get driver
@type provider: L{libcloud.types.Provider}
"""
if provider in drivers:
mod_name, driver_name = drivers[provider]
_mod = __import__(mod_name, globals(), locals(), [driver_name])
return getattr(_mod, driver_name)
raise AttributeError('Provider %s does not exist' % (provider))
def merge_valid_keys(params, valid_keys, extra):
"""
Merge valid keys from extra into params dictionary and return
dictionary with keys which have been merged.
Note: params is modified in place.
"""
merged = {}
if not extra:
return merged
for key in valid_keys:
if key in extra:
params[key] = extra[key]
merged[key] = extra[key]
return merged
def get_new_obj(obj, klass, attributes):
"""
Pass attributes from the existing object 'obj' and attributes
dictionary to a 'klass' constructor.
Attributes from 'attributes' dictionary are only passed to the
constructor if they are not None.
"""
kwargs = {}
for key, value in obj.__dict__.items():
if isinstance(value, dict):
kwargs[key] = value.copy()
elif isinstance(value, (tuple, list)):
kwargs[key] = value[:]
else:
kwargs[key] = value
for key, value in attributes.items():
if value is None:
continue
if isinstance(value, dict):
kwargs_value = kwargs.get(key, {})
for key1, value2 in value.items():
if value2 is None:
continue
kwargs_value[key1] = value2
kwargs[key] = kwargs_value
else:
kwargs[key] = value
return klass(**kwargs)