~ubuntu-branches/ubuntu/saucy/nova/saucy-proposed

« back to all changes in this revision

Viewing changes to nova/virt/libvirt/utils.py

  • Committer: Package Import Robot
  • Author(s): Chuck Short
  • Date: 2012-05-24 13:12:53 UTC
  • mfrom: (1.1.55)
  • Revision ID: package-import@ubuntu.com-20120524131253-ommql08fg1en06ut
Tags: 2012.2~f1-0ubuntu1
* New upstream release.
* Prepare for quantal:
  - Dropped debian/patches/upstream/0006-Use-project_id-in-ec2.cloud._format_image.patch
  - Dropped debian/patches/upstream/0005-Populate-image-properties-with-project_id-again.patch
  - Dropped debian/patches/upstream/0004-Fixed-bug-962840-added-a-test-case.patch
  - Dropped debian/patches/upstream/0003-Allow-unprivileged-RADOS-users-to-access-rbd-volumes.patch
  - Dropped debian/patches/upstream/0002-Stop-libvirt-test-from-deleting-instances-dir.patch
  - Dropped debian/patches/upstream/0001-fix-bug-where-nova-ignores-glance-host-in-imageref.patch 
  - Dropped debian/patches/0001-fix-useexisting-deprecation-warnings.patch
* debian/control: Add python-keystone as a dependency. (LP: #907197)
* debian/patches/kombu_tests_timeout.patch: Refreshed.
* debian/nova.conf, debian/nova-common.postinst: Convert to new ini
  file configuration
* debian/patches/nova-manage_flagfile_location.patch: Refreshed

Show diffs side-by-side

added added

removed removed

Lines of Context:
19
19
#    License for the specific language governing permissions and limitations
20
20
#    under the License.
21
21
 
 
22
import hashlib
 
23
import json
22
24
import os
23
25
import random
 
26
import re
24
27
 
25
28
from nova import exception
26
29
from nova import flags
 
30
from nova import log as logging
 
31
from nova.openstack.common import cfg
27
32
from nova import utils
28
33
from nova.virt import images
29
34
 
30
35
 
 
36
LOG = logging.getLogger(__name__)
 
37
 
 
38
 
 
39
util_opts = [
 
40
    cfg.StrOpt('image_info_filename_pattern',
 
41
               default='$instances_path/$base_dir_name/%(image)s.info',
 
42
               help='Allows image information files to be stored in '
 
43
                    'non-standard locations')
 
44
    ]
 
45
 
 
46
flags.DECLARE('instances_path', 'nova.compute.manager')
 
47
flags.DECLARE('base_dir_name', 'nova.compute.manager')
31
48
FLAGS = flags.FLAGS
 
49
FLAGS.register_opts(util_opts)
32
50
 
33
51
 
34
52
def execute(*args, **kwargs):
69
87
    :param path: Desired location of the COW image
70
88
    """
71
89
    execute('qemu-img', 'create', '-f', 'qcow2', '-o',
72
 
             'cluster_size=2M,backing_file=%s' % backing_file, path)
 
90
             'backing_file=%s' % backing_file, path)
73
91
 
74
92
 
75
93
def get_disk_size(path):
92
110
    :returns: a path to the image's backing store
93
111
    """
94
112
    out, err = execute('qemu-img', 'info', path)
95
 
    backing_file = [i.split('actual path:')[1].strip()[:-1]
96
 
        for i in out.split('\n') if 0 <= i.find('backing file')]
 
113
    backing_file = None
 
114
 
 
115
    for line in out.split('\n'):
 
116
        if line.startswith('backing file: '):
 
117
            if 'actual path: ' in line:
 
118
                backing_file = line.split('actual path: ')[1][:-1]
 
119
            else:
 
120
                backing_file = line.split('backing file: ')[1]
 
121
            break
97
122
    if backing_file:
98
 
        backing_file = os.path.basename(backing_file[0])
 
123
        backing_file = os.path.basename(backing_file)
 
124
 
99
125
    return backing_file
100
126
 
101
127
 
286
312
def fetch_image(context, target, image_id, user_id, project_id):
287
313
    """Grab image"""
288
314
    images.fetch_to_raw(context, image_id, target, user_id, project_id)
 
315
 
 
316
 
 
317
def get_info_filename(base_path):
 
318
    """Construct a filename for storing addtional information about a base
 
319
    image.
 
320
 
 
321
    Returns a filename.
 
322
    """
 
323
 
 
324
    base_file = os.path.basename(base_path)
 
325
    return (FLAGS.image_info_filename_pattern
 
326
            % {'image': base_file})
 
327
 
 
328
 
 
329
def is_valid_info_file(path):
 
330
    """Test if a given path matches the pattern for info files."""
 
331
 
 
332
    digest_size = hashlib.sha1().digestsize * 2
 
333
    regexp = (FLAGS.image_info_filename_pattern
 
334
              % {'image': ('([0-9a-f]{%(digest_size)d}|'
 
335
                           '[0-9a-f]{%(digest_size)d}_sm|'
 
336
                           '[0-9a-f]{%(digest_size)d}_[0-9]+)'
 
337
                           % {'digest_size': digest_size})})
 
338
    m = re.match(regexp, path)
 
339
    if m:
 
340
        return True
 
341
    return False
 
342
 
 
343
 
 
344
def read_stored_info(base_path, field=None):
 
345
    """Read information about an image.
 
346
 
 
347
    Returns an empty dictionary if there is no info, just the field value if
 
348
    a field is requested, or the entire dictionary otherwise.
 
349
    """
 
350
 
 
351
    info_file = get_info_filename(base_path)
 
352
    if not os.path.exists(info_file):
 
353
        # Special case to handle essex checksums being converted
 
354
        old_filename = base_path + '.sha1'
 
355
        if field == 'sha1' and os.path.exists(old_filename):
 
356
            hash_file = open(old_filename)
 
357
            hash_value = hash_file.read()
 
358
            hash_file.close()
 
359
 
 
360
            write_stored_info(base_path, field=field, value=hash_value)
 
361
            os.remove(old_filename)
 
362
            d = {field: hash_value}
 
363
 
 
364
        else:
 
365
            d = {}
 
366
 
 
367
    else:
 
368
        LOG.info(_('Reading image info file: %s'), info_file)
 
369
        f = open(info_file, 'r')
 
370
        serialized = f.read().rstrip()
 
371
        f.close()
 
372
        LOG.info(_('Read: %s'), serialized)
 
373
 
 
374
        try:
 
375
            d = json.loads(serialized)
 
376
 
 
377
        except ValueError, e:
 
378
            LOG.error(_('Error reading image info file %(filename)s: '
 
379
                        '%(error)s'),
 
380
                      {'filename': info_file,
 
381
                       'error': e})
 
382
            d = {}
 
383
 
 
384
    if field:
 
385
        return d.get(field, None)
 
386
    return d
 
387
 
 
388
 
 
389
def write_stored_info(target, field=None, value=None):
 
390
    """Write information about an image."""
 
391
 
 
392
    if not field:
 
393
        return
 
394
 
 
395
    info_file = get_info_filename(target)
 
396
    ensure_tree(os.path.dirname(info_file))
 
397
 
 
398
    d = read_stored_info(info_file)
 
399
    d[field] = value
 
400
    serialized = json.dumps(d)
 
401
 
 
402
    LOG.info(_('Writing image info file: %s'), info_file)
 
403
    LOG.info(_('Wrote: %s'), serialized)
 
404
    f = open(info_file, 'w')
 
405
    f.write(serialized)
 
406
    f.close()