| try: |
| from urllib.parse import urlencode |
| except ImportError: |
| from urllib import urlencode |
| import hashlib |
| |
| from glancev2.common import send, get_raw_client, get_by_name_or_uuid |
| |
| RESOURCE_LIST_KEY = 'images' |
| |
| |
| @send('get') |
| def image_list(**kwargs): |
| url = '/images?{}'.format(urlencode(kwargs)) |
| return url, {} |
| |
| |
| @send('post') |
| def image_create(**kwargs): |
| url = '/images' |
| return url, {'json': kwargs} |
| |
| |
| @get_by_name_or_uuid(image_list, RESOURCE_LIST_KEY) |
| @send('get') |
| def image_get_details(image_id, **kwargs): |
| url = '/images/{}'.format(image_id) |
| return url, {} |
| |
| |
| @get_by_name_or_uuid(image_list, RESOURCE_LIST_KEY) |
| @send('patch') |
| def image_update(image_id, properties, **kwargs): |
| url = '/images/{}'.format(image_id) |
| headers = { |
| 'Content-Type': 'application/openstack-images-v2.1-json-patch', |
| } |
| return url, {'json': properties, 'headers': headers} |
| |
| |
| @get_by_name_or_uuid(image_list, RESOURCE_LIST_KEY) |
| @send('delete') |
| def image_delete(image_id, **kwargs): |
| url = '/images/{}'.format(image_id) |
| return url, {} |
| |
| |
| @get_by_name_or_uuid(image_list, RESOURCE_LIST_KEY) |
| @send('post') |
| def image_deactivate(image_id, **kwargs): |
| url = '/images/{}/actions/deactivate'.format(image_id) |
| return url, {} |
| |
| |
| @get_by_name_or_uuid(image_list, RESOURCE_LIST_KEY) |
| @send('post') |
| def image_reactivate(image_id, **kwargs): |
| url = '/images/{}/actions/reactivate'.format(image_id) |
| return url, {} |
| |
| |
| class StreamingDownloader(object): |
| |
| def __init__(self, adapter, image_id, chunksize): |
| self.hasher = hashlib.new('md5') |
| self.chunksize = chunksize |
| |
| resp = adapter.get('/images/{}/file'.format(image_id), |
| stream=True) |
| if resp.status_code != 200: |
| raise Exception('Invalid response code: %s' % resp.status_code) |
| |
| self._request = resp |
| |
| def __iter__(self): |
| for chunk in self._request.iter_content(chunk_size=self.chunksize): |
| self.hasher.update(chunk) |
| yield chunk |
| |
| def validate(self): |
| return self.hasher.hexdigest() == self._request.headers['Content-Md5'] |
| |
| |
| @get_by_name_or_uuid(image_list, RESOURCE_LIST_KEY) |
| def image_data_download(image_id, file_name, **kwargs): |
| cloud_name = kwargs.pop('cloud_name') |
| adapter = get_raw_client(cloud_name) |
| downloader = StreamingDownloader(adapter, image_id, 1024 * 1024) |
| with open(file_name, 'wb') as f: |
| for chunk in downloader: |
| f.write(chunk) |
| return downloader.validate() |
| |
| |
| @get_by_name_or_uuid(image_list, RESOURCE_LIST_KEY) |
| @send('put') |
| def image_data_upload(image_id, file_name, **kwargs): |
| url = '/images/{}/file'.format(image_id) |
| headers = {'Content-Type': 'application/octet-stream '} |
| with open(file_name, 'rb') as f: |
| data = f.readlines() |
| return url, {'json': data, 'headers': headers} |