~rlane/nova/lp773690

« back to all changes in this revision

Viewing changes to nova/image/s3.py

  • Committer: rlane at wikimedia
  • Date: 2011-04-29 22:30:40 UTC
  • mfrom: (382.1.655 nova)
  • Revision ID: rlane@wikimedia.org-20110429223040-i0x3ds9eqwrabyru
MergeĀ fromĀ trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
16
16
#    License for the specific language governing permissions and limitations
17
17
#    under the License.
18
18
 
19
 
"""
20
 
Proxy AMI-related calls from the cloud controller, to the running
21
 
objectstore service.
22
 
"""
 
19
"""Proxy AMI-related calls from cloud controller to objectstore service."""
23
20
 
24
21
import binascii
25
 
import eventlet
26
22
import os
27
23
import shutil
28
24
import tarfile
30
26
from xml.etree import ElementTree
31
27
 
32
28
import boto.s3.connection
 
29
import eventlet
33
30
 
34
31
from nova import crypto
35
32
from nova import exception
46
43
 
47
44
 
48
45
class S3ImageService(service.BaseImageService):
49
 
    """Wraps an existing image service to support s3 based register"""
 
46
    """Wraps an existing image service to support s3 based register."""
 
47
 
50
48
    def __init__(self, service=None, *args, **kwargs):
51
 
        if service == None:
 
49
        if service is None:
52
50
            service = utils.import_object(FLAGS.image_service)
53
51
        self.service = service
54
52
        self.service.__init__(*args, **kwargs)
55
53
 
56
54
    def create(self, context, metadata, data=None):
57
 
        """metadata['properties'] should contain image_location"""
 
55
        """Create an image.
 
56
 
 
57
        metadata['properties'] should contain image_location.
 
58
 
 
59
        """
58
60
        image = self._s3_create(context, metadata)
59
61
        return image
60
62
 
100
102
        return local_filename
101
103
 
102
104
    def _s3_create(self, context, metadata):
103
 
        """Gets a manifext from s3 and makes an image"""
 
105
        """Gets a manifext from s3 and makes an image."""
104
106
 
105
107
        image_path = tempfile.mkdtemp(dir=FLAGS.image_decryption_dir)
106
108
 
107
109
        image_location = metadata['properties']['image_location']
108
 
        bucket_name = image_location.split("/")[0]
 
110
        bucket_name = image_location.split('/')[0]
109
111
        manifest_path = image_location[len(bucket_name) + 1:]
110
112
        bucket = self._conn(context).get_bucket(bucket_name)
111
113
        key = bucket.get_key(manifest_path)
116
118
        image_type = 'machine'
117
119
 
118
120
        try:
119
 
            kernel_id = manifest.find("machine_configuration/kernel_id").text
 
121
            kernel_id = manifest.find('machine_configuration/kernel_id').text
120
122
            if kernel_id == 'true':
121
123
                image_format = 'aki'
122
124
                image_type = 'kernel'
125
127
            kernel_id = None
126
128
 
127
129
        try:
128
 
            ramdisk_id = manifest.find("machine_configuration/ramdisk_id").text
 
130
            ramdisk_id = manifest.find('machine_configuration/ramdisk_id').text
129
131
            if ramdisk_id == 'true':
130
132
                image_format = 'ari'
131
133
                image_type = 'ramdisk'
134
136
            ramdisk_id = None
135
137
 
136
138
        try:
137
 
            arch = manifest.find("machine_configuration/architecture").text
 
139
            arch = manifest.find('machine_configuration/architecture').text
138
140
        except Exception:
139
141
            arch = 'x86_64'
140
142
 
160
162
        def delayed_create():
161
163
            """This handles the fetching and decrypting of the part files."""
162
164
            parts = []
163
 
            for fn_element in manifest.find("image").getiterator("filename"):
 
165
            for fn_element in manifest.find('image').getiterator('filename'):
164
166
                part = self._download_file(bucket, fn_element.text, image_path)
165
167
                parts.append(part)
166
168
 
174
176
            metadata['properties']['image_state'] = 'decrypting'
175
177
            self.service.update(context, image_id, metadata)
176
178
 
177
 
            hex_key = manifest.find("image/ec2_encrypted_key").text
 
179
            hex_key = manifest.find('image/ec2_encrypted_key').text
178
180
            encrypted_key = binascii.a2b_hex(hex_key)
179
 
            hex_iv = manifest.find("image/ec2_encrypted_iv").text
 
181
            hex_iv = manifest.find('image/ec2_encrypted_iv').text
180
182
            encrypted_iv = binascii.a2b_hex(hex_iv)
181
183
 
182
184
            # FIXME(vish): grab key from common service so this can run on
214
216
                                 process_input=encrypted_key,
215
217
                                 check_exit_code=False)
216
218
        if err:
217
 
            raise exception.Error(_("Failed to decrypt private key: %s")
 
219
            raise exception.Error(_('Failed to decrypt private key: %s')
218
220
                                  % err)
219
221
        iv, err = utils.execute('openssl',
220
222
                                'rsautl',
223
225
                                process_input=encrypted_iv,
224
226
                                check_exit_code=False)
225
227
        if err:
226
 
            raise exception.Error(_("Failed to decrypt initialization "
227
 
                                    "vector: %s") % err)
 
228
            raise exception.Error(_('Failed to decrypt initialization '
 
229
                                    'vector: %s') % err)
228
230
 
229
231
        _out, err = utils.execute('openssl', 'enc',
230
232
                                  '-d', '-aes-128-cbc',
234
236
                                  '-out', '%s' % (decrypted_filename,),
235
237
                                  check_exit_code=False)
236
238
        if err:
237
 
            raise exception.Error(_("Failed to decrypt image file "
238
 
                                    "%(image_file)s: %(err)s") %
 
239
            raise exception.Error(_('Failed to decrypt image file '
 
240
                                    '%(image_file)s: %(err)s') %
239
241
                                    {'image_file': encrypted_filename,
240
242
                                     'err': err})
241
243
 
242
244
    @staticmethod
243
245
    def _untarzip_image(path, filename):
244
 
        tar_file = tarfile.open(filename, "r|gz")
 
246
        tar_file = tarfile.open(filename, 'r|gz')
245
247
        tar_file.extractall(path)
246
248
        image_file = tar_file.getnames()[0]
247
249
        tar_file.close()