19 from binascii
import unhexlify
22 from xml.dom
import minidom
24 from common.hardware
import disk_controllers, network_devices, video_devices
25 from common.states
import image_access, image_types, image_states, group_states
26 from ec2.base.action
import Action, CLMException
27 from ec2.error
import InvalidAMIID, MissingParameter, InternalError, \
28 UndefinedError, InvalidParameterValue, InvalidFilter, InvalidManifest, InvalidParameter
29 from ec2.helpers.entities
import Entity
30 from ec2.helpers.filters
import applyEc2Filters, validateEc2Filters
31 from ec2.helpers.parse
import parseFilters, parseID
32 from ec2.settings
import BUCKETS_PATH
33 from ec2.settings
import EC2_PRIVATE_KEY, EC2_CM_INTERFACE
34 from ec2.settings
import UPLOAD_IMAGES_PATH
37 """@package src.ec2.image
38 EC2 actions for images
40 @copyright Copyright (c) 2012 Institute of Nuclear Physics PAS <http://www.ifj.edu.pl/>
41 @author Rafał Grzymkowski
42 @author Oleksandr Gituliar <gituliar@gmail.com>
44 @author Łukasz Chrząszcz <l.chrzaszcz@gmail.com>
71 IMAGE_READ_BUFFER = 65536
76 image_id = parseID(self.parameters[
'ImageId'], Entity.image)
78 raise InvalidParameterValue
79 image_id = int(image_id)
81 raise MissingParameter(parameter=
'ImageId')
83 raise InvalidAMIID.Malformed
86 self.cluster_manager.user.system_image.delete({
'system_image_id':image_id})
87 except CLMException, error:
88 if error.status ==
'system_image_get' or error.status ==
'image_unavailable':
89 raise InvalidAMIID.NotFound(image_id=image_id)
90 if error.status ==
'image_delete':
94 return {
'result':
'true'}
99 available_filters = [
'description',
'image-id',
'name',
'state']
102 GROUP_ACCESS = image_access[
'group']
103 PRIVATE_ACCESS = image_access[
'private']
104 PUBLIC_ACCESS = image_access[
'public']
111 for param, value
in self.parameters.iteritems():
112 if param.startswith(
'ImageId'):
113 image_id = parseID(value, Entity.image)
115 raise InvalidParameterValue
116 image_ids.append( image_id )
119 for access
in (PRIVATE_ACCESS, PUBLIC_ACCESS):
121 access_images = self.cluster_manager.user.system_image.get_list({
126 for image
in access_images:
127 if image_ids
and str(image.get(
'image_id'))
not in image_ids:
130 'description': image.get(
'description').replace(
'<',
' '),
131 'image-id': image.get(
'image_id'),
132 'is_public':
'true' if access == PUBLIC_ACCESS
else 'false',
133 'name': image[
'name'],
134 'owner_id': image.get(
'user_id'),
135 'platform': PLATFORM.get(image.get(
'platform')),
136 'state': STATE.get(image.get(
'state')),
140 access_images = self.cluster_manager.user.system_image.get_list({
'access': GROUP_ACCESS})
143 for images_dict
in access_images:
144 for image
in images_dict[
'images']:
145 if image_ids
and str(image.get(
'image_id'))
not in image_ids:
148 'description': image.get(
'description').replace(
'<',
' '),
149 'image-id': image.get(
'image_id'),
150 'is_public':
'true' if access == PUBLIC_ACCESS
else 'false',
151 'name': image[
'name'],
152 'owner_id': image.get(
'user_id'),
153 'platform': PLATFORM.get(image.get(
'platform')),
154 'state': STATE.get(image.get(
'state')),
159 if filters.get(
'state'):
160 for state
in filters[
'state']:
161 state = [k
for k,v
in STATE.iteritems()
if v == STATE.get(state) ]
166 return {
'images': images}
171 user_name = self.parameters[
'AWSAccessKeyId']
172 manifest_url = self.parameters[
'ImageLocation']
174 raise MissingParameter(parameter=e.message)
176 if manifest_url.startswith(
'/'):
177 manifest_url = manifest_url[1:]
179 manifest_path = os.path.join(BUCKETS_PATH, user_name, manifest_url)
180 dom = minidom.parse(manifest_path)
181 manifest_elem = dom.getElementsByTagName(
'manifest')[0]
183 size = manifest_elem.getElementsByTagName(
'image')[0].getElementsByTagName(
'size')[0].childNodes[0].data
184 name = manifest_elem.getElementsByTagName(
'image')[0].getElementsByTagName(
'name')[0].childNodes[0].data
186 response = self.cluster_manager.user.system_image.create({
'description':
'Uploaded by EC2',
188 'disk_controller': disk_controllers[
'virtio'],
189 'network_device': network_devices[
'rtl8139'],
191 'video_device': video_devices[
'vga'],
194 thread.start_new_thread(merge_and_upload, (self.cluster_manager, self.parameters, response[
'system_image_id']))
200 manifest_url = parameters[
'ImageLocation']
202 raise MissingParameter(parameter=e.message)
205 if manifest_url.startswith(
'/'):
206 manifest_url = manifest_url[1:]
208 user_name = parameters.get(
'AWSAccessKeyId')
210 manifest_path = os.path.join(BUCKETS_PATH, user_name, manifest_url)
212 if os.path.abspath(manifest_path) != manifest_path:
213 raise InvalidParameter
215 parts_directory = os.path.dirname(manifest_path)
218 dom = minidom.parse(manifest_path)
219 manifest_elem = dom.getElementsByTagName(
'manifest')[0]
225 parts_list = manifest_elem.getElementsByTagName(
'filename')
226 for part_elem
in parts_list:
227 nodes = part_elem.childNodes
229 if node.nodeType == node.TEXT_NODE:
230 parts.append(node.data)
232 encrypted_key_elem = manifest_elem.getElementsByTagName(
'ec2_encrypted_key')[0]
233 encrypted_iv_elem = manifest_elem.getElementsByTagName(
'ec2_encrypted_iv')[0]
235 encrypted_key = encrypted_key_elem.firstChild.nodeValue
236 encrypted_iv = encrypted_iv_elem.firstChild.nodeValue
240 result_filename = manifest_path.replace(
'.manifest.xml',
'')
247 part_filename = os.path.join(parts_directory, part)
248 if not part_filename.startswith(parts_directory):
249 raise InvalidManifest
251 part_files.append(part_filename)
255 user_priv_key = RSA.load_key(EC2_PRIVATE_KEY)
256 key = user_priv_key.private_decrypt(unhexlify(encrypted_key),
258 iv = user_priv_key.private_decrypt(unhexlify(encrypted_iv),
263 cat_process = subprocess.Popen([
'cat'] + part_files, stdout=subprocess.PIPE)
264 openssl_process = subprocess.Popen([
'openssl',
'enc',
'-d',
'-aes-128-cbc',
'-K', key,
'-iv', iv],
265 stdin=cat_process.stdout, stdout=subprocess.PIPE)
266 uncompress_process = subprocess.Popen([
'gzip',
'-c',
'-d'], stdin=openssl_process.stdout,
267 stdout=subprocess.PIPE)
268 untar_process = subprocess.Popen([
'tar',
'-xvm',
'-C', parts_directory], stdin=uncompress_process.stdout, stdout=subprocess.PIPE)
278 link_name = user_name + str(uuid.uuid4())
279 link_path = os.path.join(UPLOAD_IMAGES_PATH, link_name)
281 os.symlink(result_filename, link_path)
284 image_url = EC2_CM_INTERFACE +
'?image_name=' + link_name
287 cluster_manager.user.system_image.download_ec2({
'system_image_id': system_image_id,