blob: b8eedbe1eecb7e9cd7860ea9dd0cf4122aa253b3 [file] [log] [blame]
Oleksiy Petrenko2652ac12018-04-16 17:40:13 +03001try:
2 from urllib.parse import urlencode
3except ImportError:
4 from urllib import urlencode
5import hashlib
6
7from glancev2.common import send, get_raw_client, get_by_name_or_uuid
8
9RESOURCE_LIST_KEY = 'images'
10
11
12@send('get')
13def image_list(**kwargs):
14 url = '/v2/images?{}'.format(urlencode(kwargs))
15 return url, {}
16
17
18@send('post')
19def image_create(**kwargs):
20 url = '/v2/images'
21 return url, {'json': kwargs}
22
23
24@get_by_name_or_uuid(image_list, RESOURCE_LIST_KEY)
25@send('get')
26def image_get_details(image_id, **kwargs):
27 url = '/v2/images/{}'.format(image_id)
28 return url, {}
29
30
31@get_by_name_or_uuid(image_list, RESOURCE_LIST_KEY)
32@send('patch')
33def image_update(image_id, properties, **kwargs):
34 url = '/v2/images/{}'.format(image_id)
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')
43def image_delete(image_id, **kwargs):
44 url = '/v2/images/{}'.format(image_id)
45 return url, {}
46
47
48@get_by_name_or_uuid(image_list, RESOURCE_LIST_KEY)
49@send('post')
50def image_deactivate(image_id, **kwargs):
51 url = '/v2/images/{}/actions/deactivate'.format(image_id)
52 return url, {}
53
54
55@get_by_name_or_uuid(image_list, RESOURCE_LIST_KEY)
56@send('post')
57def image_reactivate(image_id, **kwargs):
58 url = '/v2/images/{}/actions/reactivate'.format(image_id)
59 return url, {}
60
61
62class StreamingDownloader(object):
63
64 def __init__(self, adapter, image_id, chunksize):
65 self.hasher = hashlib.new('md5')
66 self.chunksize = chunksize
67
68 resp = adapter.get('/v2/images/{}/file'.format(image_id),
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)
85def 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')
97def image_data_upload(image_id, file_name, **kwargs):
98 url = '/v2/images/{}/file'.format(image_id)
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}