~ubuntu-branches/ubuntu/natty/euca2ools/natty-201106142030

« back to all changes in this revision

Viewing changes to .pc/bundle-vol-exclude-persistent-udev-net-rules.patch/bin/euca-bundle-vol

  • Committer: Scott Moser
  • Date: 2010-11-17 21:23:16 UTC
  • Revision ID: smoser@ubuntu.com-20101117212316-is94e55u3jv46y9l
move to quilt 3.0 source format, re-apply all relevant delta

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/python
 
2
# -*- coding: utf-8 -*-
 
3
 
 
4
# Software License Agreement (BSD License)
 
5
#
 
6
# Copyright (c) 2009, Eucalyptus Systems, Inc.
 
7
# All rights reserved.
 
8
#
 
9
# Redistribution and use of this software in source and binary forms, with or
 
10
# without modification, are permitted provided that the following conditions
 
11
# are met:
 
12
#
 
13
#   Redistributions of source code must retain the above
 
14
#   copyright notice, this list of conditions and the
 
15
#   following disclaimer.
 
16
#
 
17
#   Redistributions in binary form must reproduce the above
 
18
#   copyright notice, this list of conditions and the
 
19
#   following disclaimer in the documentation and/or other
 
20
#   materials provided with the distribution.
 
21
#
 
22
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 
23
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 
24
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 
25
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 
26
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 
27
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 
28
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 
29
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 
30
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 
31
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 
32
# POSSIBILITY OF SUCH DAMAGE.
 
33
#
 
34
# Author: Neil Soman neil@eucalyptus.com
 
35
 
 
36
import getopt
 
37
import sys
 
38
import os
 
39
from euca2ools import Euca2ool, FileValidationError, \
 
40
    DirValidationError, CopyError, MetadataReadError, Util, \
 
41
    NotFoundError, CommandFailed, UnsupportedException
 
42
from subprocess import *
 
43
import platform
 
44
 
 
45
usage_string = \
 
46
    """
 
47
Bundle the local filesystem of a running instance as a bundled image.
 
48
 
 
49
euca-bundle-vol -u, --user user -s, --size size_in_MB
 
50
[-c, --cert cert_path] [-k, --privatekey private_key_path] 
 
51
[-a, --all] [-e, --exclude dir1, dir2,...dirN] [-p, --prefix prefix] [--[no-]inherit] [-v, --volume volume_path] [--fstab fstab_path] [--generate-fstab] [--kernel kernel_id] [--ramdisk ramdisk_id] [-B, --block-device-mapping mapping] 
 
52
[-d, --destination destination_path] [--ec2cert ec2cert_path] [-r, --arch target_architecture] [--batch] [--version]
 
53
 
 
54
REQUIRED PARAMETERS
 
55
 
 
56
-u, --user                      User ID (12-digit) of the user who is bundling the image.
 
57
 
 
58
-s, --size                      Size for the image in MB (default: 10GB or 10240MB).
 
59
 
 
60
OPTIONAL PARAMETERS
 
61
 
 
62
-c, --cert                      Path to the user's PEM encoded certificate.
 
63
 
 
64
-k, --privatekey                Path to the user's PEM encoded private key.
 
65
 
 
66
-a, --all                       Bundle all directories (including mounted filesystems).
 
67
 
 
68
-p, --prefix                    The prefix for the bundle image files. (default: image name).
 
69
 
 
70
--[no-]inherit                  Add (or do not add) instance metadata to the bundled image. Inherit is set by default.
 
71
 
 
72
-e, --exclude                   comma-separated list of directories to exclude.
 
73
 
 
74
--kernel                        The kernel to be associated with the bundled image.
 
75
 
 
76
--ramdisk                       The ramdisk to be associated with the bundled image.
 
77
 
 
78
-B, --block-device-mapping      Default block device mapping for the image (comma-separated list of key=value pairs).
 
79
 
 
80
-d, --destination               Directory to store the bundled image in (default: "/tmp"). Recommended. 
 
81
 
 
82
--ec2cert                       The path to the Cloud's X509 public key certificate.
 
83
 
 
84
-r, --arch                      Target architecture for the image ('x86_64' or 'i386' default: 'x86_64').
 
85
 
 
86
-v, --volume                    Path to mounted volume to create the bundle from (default: "/").
 
87
 
 
88
--fstab                         Path to the fstab to be bundled into the image.
 
89
        
 
90
--generate-fstab                Generate fstab to bundle into the image.
 
91
 
 
92
--batch                         Run in batch mode (compatibility only. has no effect).
 
93
"""
 
94
 
 
95
MAX_IMAGE_SIZE = 1024 * 10
 
96
 
 
97
 
 
98
def usage(status=1):
 
99
    print usage_string
 
100
    sys.exit(status)
 
101
 
 
102
 
 
103
def version():
 
104
    print Util().version()
 
105
    sys.exit()
 
106
 
 
107
 
 
108
def check_root():
 
109
    if os.geteuid() == 0:
 
110
        return
 
111
    else:
 
112
        print 'Must be superuser to execute this command.'
 
113
        sys.exit()
 
114
 
 
115
 
 
116
def check_image_size(size):
 
117
    if size > MAX_IMAGE_SIZE:
 
118
        print 'Image Size is too large (Max = %d MB)' % MAX_IMAGE_SIZE
 
119
        sys.exit()
 
120
 
 
121
 
 
122
def parse_excludes(excludes_string):
 
123
    excludes = []
 
124
    if excludes_string:
 
125
        excludes_string = excludes_string.replace(' ', '')
 
126
        excludes = excludes_string.split(',')
 
127
    return excludes
 
128
 
 
129
 
 
130
def get_instance_metadata(
 
131
    euca,
 
132
    ramdisk,
 
133
    kernel,
 
134
    mapping,
 
135
    ):
 
136
    product_codes = None
 
137
    ramdisk_id = ramdisk
 
138
    kernel_id = kernel
 
139
    block_dev_mapping = mapping
 
140
    ancestor_ami_ids = None
 
141
    try:
 
142
        euca.can_read_instance_metadata()
 
143
        if not ramdisk_id:
 
144
            try:
 
145
                ramdisk_id = euca.get_instance_ramdisk()
 
146
            except MetadataReadError:
 
147
                print 'Unable to read ramdisk id'
 
148
 
 
149
        if not kernel_id:
 
150
            try:
 
151
                kernel_id = euca.get_instance_kernel()
 
152
            except MetadataReadError:
 
153
                print 'Unable to read kernel id'
 
154
 
 
155
        if not block_dev_mapping:
 
156
            try:
 
157
                block_dev_mapping = \
 
158
                    euca.get_instance_block_device_mappings()
 
159
            except MetadataReadError:
 
160
                print 'Unable to read block device mapping'
 
161
 
 
162
        try:
 
163
            product_codes = euca.get_instance_product_codes().split('\n'
 
164
                    )
 
165
        except MetadataReadError:
 
166
            print 'Unable to read product codes'
 
167
 
 
168
        try:
 
169
            ancestor_ami_ids = euca.get_ancestor_ami_ids().split('\n')
 
170
        except MetadataReadError:
 
171
            print 'Unable to read product codes'
 
172
    except IOError:
 
173
 
 
174
        print 'Unable to read instance metadata. Pass the --no-inherit option if you wish to exclude instance metadata.'
 
175
        sys.exit()
 
176
 
 
177
    return (ramdisk_id, kernel_id, block_dev_mapping, product_codes,
 
178
            ancestor_ami_ids)
 
179
 
 
180
 
 
181
def add_product_codes(product_code_string, product_codes):
 
182
    if not product_codes:
 
183
        product_codes = []
 
184
    product_code_values = product_code_string.split(',')
 
185
 
 
186
    for p in product_code_values:
 
187
        product_codes.append(p)
 
188
 
 
189
    return product_codes
 
190
 
 
191
 
 
192
def cleanup(path):
 
193
    if os.path.exists(path):
 
194
        os.remove(path)
 
195
 
 
196
 
 
197
def main():
 
198
    euca = None
 
199
    try:
 
200
        euca = Euca2ool('a:c:k:u:B:d:br:p:s:v:e:', [
 
201
            'cert=',
 
202
            'privatekey=',
 
203
            'user=',
 
204
            'prefix=',
 
205
            'volume=',
 
206
            'all',
 
207
            'kernel=',
 
208
            'ramdisk=',
 
209
            'block-device-mapping=',
 
210
            'destination=',
 
211
            'ec2cert=',
 
212
            'arch=',
 
213
            'size=',
 
214
            'exclude=',
 
215
            'inherit=',
 
216
            'no-inherit',
 
217
            'batch',
 
218
            'fstab=',
 
219
            'generate-fstab',
 
220
            'productcodes=',
 
221
            ])
 
222
    except Exception, e:
 
223
        print e
 
224
        usage()
 
225
 
 
226
    kernel = None
 
227
    user = None
 
228
    ramdisk = None
 
229
    try:
 
230
        cert_path = euca.get_environ('EC2_CERT')
 
231
        private_key_path = euca.get_environ('EC2_PRIVATE_KEY')
 
232
        ec2cert_path = euca.get_environ('EUCALYPTUS_CERT')
 
233
        user_string = euca.get_environ('EC2_USER_ID')
 
234
    except NotFoundError:
 
235
        sys.exit(1)
 
236
 
 
237
    prefix = 'image'
 
238
    size_in_MB = 10 * 1024
 
239
    destination_path = '/disk1'
 
240
    target_arch = 'x86_64'
 
241
    mapping = None
 
242
    excludes_string = None
 
243
    excludes = None
 
244
    all = False
 
245
    volume_path = '/'
 
246
    inherit = True
 
247
    product_codes = None
 
248
    ancestor_ami_ids = None
 
249
    fstab_path = None
 
250
    generate_fstab = False
 
251
    product_code_string = None
 
252
    if user_string:
 
253
        try:
 
254
            user = int(user_string)
 
255
        except ValueError:
 
256
            print 'Invalid user', user_string
 
257
            sys.exit()
 
258
    user = user_string
 
259
 
 
260
    for (name, value) in euca.opts:
 
261
        if name in ('-h', '--help'):
 
262
            usage(0)
 
263
        elif name in ('-c', '--cert'):
 
264
            cert_path = value
 
265
        elif name in ('-k', '--privatekey'):
 
266
            private_key_path = value
 
267
        elif name in ('-u', '--user'):
 
268
            try:
 
269
                value = value.replace('-', '')
 
270
                user = int(value)
 
271
            except ValueError:
 
272
                print 'Invalid user', value
 
273
                sys.exit()
 
274
            user = value
 
275
        elif name == '--kernel':
 
276
            kernel = value
 
277
        elif name == '--ramdisk':
 
278
            ramdisk = value
 
279
        elif name in ('-p', '--prefix'):
 
280
            prefix = value
 
281
        elif name in ('-s', '--size'):
 
282
            size_in_MB = int(value)
 
283
        elif name in ('-v', '--volume'):
 
284
            volume_path = value
 
285
        elif name in ('-e', '--exclude'):
 
286
            excludes_string = value
 
287
        elif name in ('-d', '--destination'):
 
288
            destination_path = value
 
289
        elif name == '--ec2cert':
 
290
            ec2cert_path = value
 
291
        elif name in ('-a', '--all'):
 
292
            all = True
 
293
        elif name in ('-r', '--arch'):
 
294
            target_arch = value
 
295
            if target_arch != 'i386' and target_arch != 'x86_64':
 
296
                print 'target architecture must be i386 or x86_64'
 
297
                usage()
 
298
        elif name in ('-B', '--block-device-mapping'):
 
299
            mapping = value
 
300
        elif name == '--no-inherit':
 
301
            inherit = False
 
302
        elif name == '--generate-fstab':
 
303
            generate_fstab = True
 
304
        elif name == '--fstab':
 
305
            fstab_path = value
 
306
        elif name == '--productcodes':
 
307
            product_code_string = value
 
308
        elif name == '--version':
 
309
            version()
 
310
 
 
311
    if size_in_MB and cert_path and private_key_path and user \
 
312
        and ec2cert_path:
 
313
        try:
 
314
            euca.validate_file(cert_path)
 
315
        except FileValidationError:
 
316
            print 'Invalid cert'
 
317
            sys.exit(1)
 
318
        try:
 
319
            euca.validate_file(private_key_path)
 
320
        except FileValidationError:
 
321
            print 'Invalid private key'
 
322
            sys.exit(1)
 
323
        try:
 
324
            euca.validate_file(ec2cert_path)
 
325
        except FileValidationError:
 
326
            print 'Invalid ec2cert'
 
327
            sys.exit(1)
 
328
        try:
 
329
            euca.validate_dir(volume_path)
 
330
        except DirValidationError:
 
331
            print 'Invalid directory', volume_path
 
332
            sys.exit(1)
 
333
            if generate_fstab and fstab_path:
 
334
                print '--generate-fstab and --fstab path cannot both be set.'
 
335
                sys.exit(1)
 
336
            if fstab_path:
 
337
                try:
 
338
                    euca.validate_file(fstab_path)
 
339
                except FileValidationError:
 
340
                    print 'Invalid fstab path'
 
341
                    sys.exit(1)
 
342
        if not fstab_path:
 
343
            if platform.machine() == 'i386':
 
344
                fstab_path = 'old'
 
345
            else:
 
346
                fstab_path = 'new'
 
347
 
 
348
        check_root()
 
349
        check_image_size(size_in_MB)
 
350
        volume_path = os.path.normpath(volume_path)
 
351
        if not all:
 
352
            excludes = parse_excludes(excludes_string)
 
353
            euca.add_excludes(volume_path, excludes)
 
354
        if inherit:
 
355
            (ramdisk, kernel, mapping, product_codes,
 
356
             ancestor_ami_ids) = get_instance_metadata(euca, ramdisk,
 
357
                    kernel, mapping)
 
358
        if product_code_string:
 
359
            product_codes = add_product_codes(product_code_string,
 
360
                    product_codes)
 
361
        try:
 
362
            image_path = euca.make_image(size_in_MB, excludes, prefix,
 
363
                    destination_path)
 
364
        except NotFoundError:
 
365
            sys.exit(1)
 
366
        except UnsupportedException:
 
367
            sys.exit(1)
 
368
        image_path = os.path.normpath(image_path)
 
369
        if image_path.find(volume_path) == 0:
 
370
            exclude_image = image_path.replace(volume_path, '', 1)
 
371
            image_path_parts = exclude_image.split('/')
 
372
            if len(image_path_parts) > 1:
 
373
                exclude_image = \
 
374
                    exclude_image.replace(image_path_parts[0] + '/', ''
 
375
                        , 1)
 
376
            excludes.append(exclude_image)
 
377
        try:
 
378
            euca.copy_volume(image_path, volume_path, excludes,
 
379
                             generate_fstab, fstab_path)
 
380
        except CopyError:
 
381
            print 'Unable to copy files'
 
382
            cleanup(image_path)
 
383
            sys.exit(1)
 
384
        except NotFoundError:
 
385
            cleanup(image_path)
 
386
            sys.exit(1)
 
387
        except CommandFailed:
 
388
            cleanup(image_path)
 
389
            sys.exit(1)
 
390
        except UnsupportedException:
 
391
            cleanup(image_path)
 
392
            sys.exit(1)
 
393
 
 
394
        (image_size, sha_image_digest) = euca.check_image(image_path,
 
395
                destination_path)
 
396
        if not prefix:
 
397
            prefix = euca.get_relative_filename(image_path)
 
398
        try:
 
399
            tgz_file = euca.tarzip_image(prefix, image_path,
 
400
                    destination_path)
 
401
        except NotFoundError:
 
402
            sys.exit(1)
 
403
        except CommandFailed:
 
404
            sys.exit(1)
 
405
 
 
406
        (encrypted_file, key, iv, bundled_size) = \
 
407
            euca.encrypt_image(tgz_file)
 
408
        os.remove(tgz_file)
 
409
        (parts, parts_digest) = euca.split_image(encrypted_file)
 
410
        euca.generate_manifest(
 
411
            destination_path,
 
412
            prefix,
 
413
            parts,
 
414
            parts_digest,
 
415
            image_path,
 
416
            key,
 
417
            iv,
 
418
            cert_path,
 
419
            ec2cert_path,
 
420
            private_key_path,
 
421
            target_arch,
 
422
            image_size,
 
423
            bundled_size,
 
424
            sha_image_digest,
 
425
            user,
 
426
            kernel,
 
427
            ramdisk,
 
428
            mapping,
 
429
            product_codes,
 
430
            ancestor_ami_ids,
 
431
            )
 
432
        os.remove(encrypted_file)
 
433
    else:
 
434
 
 
435
# ....cleanup(image_path)
 
436
 
 
437
        if not size_in_MB:
 
438
            print 'size must be specified.'
 
439
        if not cert_path:
 
440
            print 'cert must be specified.'
 
441
        if not private_key_path:
 
442
            print 'privatekey must be specified.'
 
443
        if not user:
 
444
            print 'user must be specified.'
 
445
        if not ec2cert_path:
 
446
            defcert = "/usr/share/euca2ools/cert-ec2.pem"
 
447
            if os.path.exists(defcert):
 
448
                ec2cert_path = defcert
 
449
            else:
 
450
                print 'ec2cert must be specified or exist in %s.' % defcert
 
451
        usage()
 
452
 
 
453
 
 
454
if __name__ == '__main__':
 
455
    main()
 
456