Oleksiy Petrenko | 2652ac1 | 2018-04-16 17:40:13 +0300 | [diff] [blame] | 1 | try: |
| 2 | from urllib.parse import urlencode |
| 3 | except ImportError: |
| 4 | from urllib import urlencode |
| 5 | import hashlib |
| 6 | |
| 7 | from glancev2.common import send, get_raw_client, get_by_name_or_uuid |
| 8 | |
| 9 | RESOURCE_LIST_KEY = 'images' |
| 10 | |
| 11 | |
| 12 | @send('get') |
| 13 | def image_list(**kwargs): |
Oleh Hryhorov | 6de49c9 | 2018-05-21 12:53:59 +0000 | [diff] [blame] | 14 | url = '/images?{}'.format(urlencode(kwargs)) |
Oleksiy Petrenko | 2652ac1 | 2018-04-16 17:40:13 +0300 | [diff] [blame] | 15 | return url, {} |
| 16 | |
| 17 | |
| 18 | @send('post') |
| 19 | def image_create(**kwargs): |
Oleh Hryhorov | 6de49c9 | 2018-05-21 12:53:59 +0000 | [diff] [blame] | 20 | url = '/images' |
Oleksiy Petrenko | 2652ac1 | 2018-04-16 17:40:13 +0300 | [diff] [blame] | 21 | return url, {'json': kwargs} |
| 22 | |
| 23 | |
| 24 | @get_by_name_or_uuid(image_list, RESOURCE_LIST_KEY) |
| 25 | @send('get') |
| 26 | def image_get_details(image_id, **kwargs): |
Oleh Hryhorov | 6de49c9 | 2018-05-21 12:53:59 +0000 | [diff] [blame] | 27 | url = '/images/{}'.format(image_id) |
Oleksiy Petrenko | 2652ac1 | 2018-04-16 17:40:13 +0300 | [diff] [blame] | 28 | return url, {} |
| 29 | |
| 30 | |
| 31 | @get_by_name_or_uuid(image_list, RESOURCE_LIST_KEY) |
| 32 | @send('patch') |
| 33 | def image_update(image_id, properties, **kwargs): |
Oleh Hryhorov | 6de49c9 | 2018-05-21 12:53:59 +0000 | [diff] [blame] | 34 | url = '/images/{}'.format(image_id) |
Oleksiy Petrenko | 2652ac1 | 2018-04-16 17:40:13 +0300 | [diff] [blame] | 35 | headers = { |
| 36 | 'Content-Type': 'application/openstack-images-v2.1-json-patch', |
| 37 | } |
| 38 | return url, {'json': properties, 'headers': headers} |
| 39 | |
| 40 | |
| 41 | @get_by_name_or_uuid(image_list, RESOURCE_LIST_KEY) |
| 42 | @send('delete') |
| 43 | def image_delete(image_id, **kwargs): |
Oleh Hryhorov | 6de49c9 | 2018-05-21 12:53:59 +0000 | [diff] [blame] | 44 | url = '/images/{}'.format(image_id) |
Oleksiy Petrenko | 2652ac1 | 2018-04-16 17:40:13 +0300 | [diff] [blame] | 45 | return url, {} |
| 46 | |
| 47 | |
| 48 | @get_by_name_or_uuid(image_list, RESOURCE_LIST_KEY) |
| 49 | @send('post') |
| 50 | def image_deactivate(image_id, **kwargs): |
Oleh Hryhorov | 6de49c9 | 2018-05-21 12:53:59 +0000 | [diff] [blame] | 51 | url = '/images/{}/actions/deactivate'.format(image_id) |
Oleksiy Petrenko | 2652ac1 | 2018-04-16 17:40:13 +0300 | [diff] [blame] | 52 | return url, {} |
| 53 | |
| 54 | |
| 55 | @get_by_name_or_uuid(image_list, RESOURCE_LIST_KEY) |
| 56 | @send('post') |
| 57 | def image_reactivate(image_id, **kwargs): |
Oleh Hryhorov | 6de49c9 | 2018-05-21 12:53:59 +0000 | [diff] [blame] | 58 | url = '/images/{}/actions/reactivate'.format(image_id) |
Oleksiy Petrenko | 2652ac1 | 2018-04-16 17:40:13 +0300 | [diff] [blame] | 59 | return url, {} |
| 60 | |
| 61 | |
| 62 | class StreamingDownloader(object): |
| 63 | |
| 64 | def __init__(self, adapter, image_id, chunksize): |
| 65 | self.hasher = hashlib.new('md5') |
| 66 | self.chunksize = chunksize |
| 67 | |
Oleh Hryhorov | 6de49c9 | 2018-05-21 12:53:59 +0000 | [diff] [blame] | 68 | resp = adapter.get('/images/{}/file'.format(image_id), |
Oleksiy Petrenko | 2652ac1 | 2018-04-16 17:40:13 +0300 | [diff] [blame] | 69 | stream=True) |
| 70 | if resp.status_code != 200: |
| 71 | raise Exception('Invalid response code: %s' % resp.status_code) |
| 72 | |
| 73 | self._request = resp |
| 74 | |
| 75 | def __iter__(self): |
| 76 | for chunk in self._request.iter_content(chunk_size=self.chunksize): |
| 77 | self.hasher.update(chunk) |
| 78 | yield chunk |
| 79 | |
| 80 | def validate(self): |
| 81 | return self.hasher.hexdigest() == self._request.headers['Content-Md5'] |
| 82 | |
| 83 | |
| 84 | @get_by_name_or_uuid(image_list, RESOURCE_LIST_KEY) |
| 85 | def image_data_download(image_id, file_name, **kwargs): |
| 86 | cloud_name = kwargs.pop('cloud_name') |
| 87 | adapter = get_raw_client(cloud_name) |
| 88 | downloader = StreamingDownloader(adapter, image_id, 1024 * 1024) |
| 89 | with open(file_name, 'wb') as f: |
| 90 | for chunk in downloader: |
| 91 | f.write(chunk) |
| 92 | return downloader.validate() |
| 93 | |
| 94 | |
| 95 | @get_by_name_or_uuid(image_list, RESOURCE_LIST_KEY) |
| 96 | @send('put') |
| 97 | def image_data_upload(image_id, file_name, **kwargs): |
Oleh Hryhorov | 6de49c9 | 2018-05-21 12:53:59 +0000 | [diff] [blame] | 98 | url = '/images/{}/file'.format(image_id) |
Oleksiy Petrenko | 2652ac1 | 2018-04-16 17:40:13 +0300 | [diff] [blame] | 99 | headers = {'Content-Type': 'application/octet-stream '} |
| 100 | with open(file_name, 'rb') as f: |
| 101 | data = f.readlines() |
| 102 | return url, {'json': data, 'headers': headers} |