Example #1
0
    def test_remove_base_file_original(self):
        with self._make_base_file() as fname:
            image_cache_manager = imagecache.ImageCacheManager()
            image_cache_manager.originals = [fname]
            image_cache_manager._remove_base_file(fname)
            info_fname = imagecache.get_info_filename(fname)

            # Files are initially too new to delete
            self.assertTrue(os.path.exists(fname))
            self.assertTrue(os.path.exists(info_fname))

            # This file should stay longer than a resized image
            os.utime(fname, (-1, time.time() - 3601))
            image_cache_manager._remove_base_file(fname)

            self.assertTrue(os.path.exists(fname))
            self.assertTrue(os.path.exists(info_fname))

            # Originals don't stay forever though
            os.utime(fname, (-1, time.time() - 3600 * 25))
            image_cache_manager._remove_base_file(fname)

            self.assertFalse(os.path.exists(fname))
            self.assertFalse(os.path.exists(info_fname))
Example #2
0
    def test_verify_checksum_invalid(self):
        img = {'container_format': 'ami', 'id': '42'}

        self.flags(checksum_base_images=True)

        with self._intercept_log_messages() as stream:
            with utils.tempdir() as tmpdir:
                self.flags(instances_path=tmpdir)
                self.flags(image_info_filename_pattern=('$instances_path/'
                                                        '%(image)s.info'))

                fname, info_fname, testdata = self._make_checksum(tmpdir)

                # Checksum is invalid, but is in valid json
                f = open(info_fname, 'w')
                f.write('{"sha1": "banana"}')
                f.close()

                image_cache_manager = imagecache.ImageCacheManager()
                res = image_cache_manager._verify_checksum(img, fname)
                self.assertFalse(res)
                log = stream.getvalue()

                self.assertNotEqual(log.find('image verification failed'), -1)
Example #3
0
    def test_find_base_file_all(self):
        fingerprint = '968dd6cc49e01aaa044ed11c0cce733e0fa44a6a'
        listing = ['00000001',
                   'ephemeral_0_20_None',
                   '968dd6cc49e01aaa044ed11c0cce733e0fa44a6a_sm',
                   '968dd6cc49e01aaa044ed11c0cce733e0fa44a6a_10737418240',
                   '00000004']

        self.stubs.Set(os, 'listdir', lambda x: listing)
        self.stubs.Set(os.path, 'exists', lambda x: True)
        self.stubs.Set(os.path, 'isfile', lambda x: True)

        base_dir = '/var/lib/nova/instances/_base'
        image_cache_manager = imagecache.ImageCacheManager()
        image_cache_manager._list_base_images(base_dir)
        res = list(image_cache_manager._find_base_file(base_dir, fingerprint))

        base_file1 = os.path.join(base_dir, fingerprint)
        base_file2 = os.path.join(base_dir, fingerprint + '_sm')
        base_file3 = os.path.join(base_dir, fingerprint + '_10737418240')
        print res
        self.assertTrue(res == [(base_file1, False, False),
                                (base_file2, True, False),
                                (base_file3, False, True)])
Example #4
0
 def test_get_age_of_file_not_exists(self, mock_exists):
     image_cache_manager = imagecache.ImageCacheManager()
     exists, age = image_cache_manager._get_age_of_file('/tmp')
     self.assertFalse(exists)
     self.assertEqual(0, age)
Example #5
0
 def test_get_age_of_file(self, mock_getmtime, mock_time, mock_exists):
     image_cache_manager = imagecache.ImageCacheManager()
     exists, age = image_cache_manager._get_age_of_file('/tmp')
     self.assertTrue(exists)
     self.assertEqual(1000000, age)
Example #6
0
 def test_verify_base_images_no_base(self):
     self.flags(instances_path='/tmp/no/such/dir/name/please')
     image_cache_manager = imagecache.ImageCacheManager()
     image_cache_manager.update(None, [])
Example #7
0
    def test_verify_base_images(self, mock_lock, mock_utime):
        hashed_1 = '356a192b7913b04c54574d18c28d46e6395428ab'
        hashed_21 = '472b07b9fcf2c2451e8781e944bf5f77cd8457c8'
        hashed_22 = '12c6fc06c99a462375eeb3f43dfd832b08ca9e17'
        hashed_42 = '92cfceb39d57d914ed8b14d0e37643de0797ae56'

        self.flags(instances_path='/instance_path',
                   image_cache_subdirectory_name='_base')

        base_file_list = [
            '00000001', 'ephemeral_0_20_None',
            'e97222e91fc4241f49a7f520d1dcf446751129b3_sm',
            'e09c675c2d1cfac32dae3c2d83689c8c94bc693b_sm', hashed_42, hashed_1,
            hashed_21, hashed_22,
            '%s_5368709120' % hashed_1,
            '%s_10737418240' % hashed_1, '00000004'
        ]

        def fq_path(path):
            return os.path.join('/instance_path/_base/', path)

        # Fake base directory existence
        orig_exists = os.path.exists

        def exists(path):
            # The python coverage tool got angry with my overly broad mocks
            if not path.startswith('/instance_path'):
                return orig_exists(path)

            if path in [
                    '/instance_path', '/instance_path/_base',
                    '/instance_path/instance-1/disk',
                    '/instance_path/instance-2/disk',
                    '/instance_path/instance-3/disk',
                    '/instance_path/_base/%s.info' % hashed_42
            ]:
                return True

            for p in base_file_list:
                if path == fq_path(p):
                    return True
                if path == fq_path(p) + '.info':
                    return False

            if path in [
                    '/instance_path/_base/%s_sm' % i
                    for i in [hashed_1, hashed_21, hashed_22, hashed_42]
            ]:
                return False

            self.fail('Unexpected path existence check: %s' % path)

        self.stub_out('os.path.exists', lambda x: exists(x))

        # Fake up some instances in the instances directory
        orig_listdir = os.listdir

        def listdir(path):
            # The python coverage tool got angry with my overly broad mocks
            if not path.startswith('/instance_path'):
                return orig_listdir(path)

            if path == '/instance_path':
                return ['instance-1', 'instance-2', 'instance-3', '_base']

            if path == '/instance_path/_base':
                return base_file_list

            self.fail('Unexpected directory listed: %s' % path)

        self.stub_out('os.listdir', lambda x: listdir(x))

        # Fake isfile for these faked images in _base
        orig_isfile = os.path.isfile

        def isfile(path):
            # The python coverage tool got angry with my overly broad mocks
            if not path.startswith('/instance_path'):
                return orig_isfile(path)

            for p in base_file_list:
                if path == fq_path(p):
                    return True

            self.fail('Unexpected isfile call: %s' % path)

        self.stub_out('os.path.isfile', lambda x: isfile(x))

        # Fake the database call which lists running instances
        instances = [{
            'image_ref': '1',
            'host': CONF.host,
            'name': 'instance-1',
            'uuid': uuids.instance_1,
            'vm_state': '',
            'task_state': ''
        }, {
            'image_ref': '1',
            'kernel_id': '21',
            'ramdisk_id': '22',
            'host': CONF.host,
            'name': 'instance-2',
            'uuid': uuids.instance_2,
            'vm_state': '',
            'task_state': ''
        }]
        all_instances = [
            fake_instance.fake_instance_obj(None, **instance)
            for instance in instances
        ]
        image_cache_manager = imagecache.ImageCacheManager()

        # Fake the utils call which finds the backing image
        def get_disk_backing_file(path):
            if path in [
                    '/instance_path/instance-1/disk',
                    '/instance_path/instance-2/disk'
            ]:
                return fq_path('%s_5368709120' % hashed_1)
            self.fail('Unexpected backing file lookup: %s' % path)

        self.stub_out('nova.virt.libvirt.utils.get_disk_backing_file',
                      lambda x: get_disk_backing_file(x))

        # Fake getmtime as well
        orig_getmtime = os.path.getmtime

        def getmtime(path):
            if not path.startswith('/instance_path'):
                return orig_getmtime(path)

            return 1000000

        self.stub_out('os.path.getmtime', lambda x: getmtime(x))

        # Make sure we don't accidentally remove a real file
        orig_remove = os.remove

        def remove(path):
            if not path.startswith('/instance_path'):
                return orig_remove(path)

            # Don't try to remove fake files
            return

        self.stub_out('os.remove', lambda x: remove(x))

        with mock.patch.object(objects.block_device.BlockDeviceMappingList,
                               'bdms_by_instance_uuid',
                               return_value={}) as mock_bdms:
            ctxt = context.get_admin_context()
            # And finally we can make the call we're actually testing...
            # The argument here should be a context, but it is mocked out
            image_cache_manager.update(ctxt, all_instances)

            # Verify
            active = [
                fq_path(hashed_1),
                fq_path('%s_5368709120' % hashed_1),
                fq_path(hashed_21),
                fq_path(hashed_22)
            ]
            for act in active:
                self.assertIn(act, image_cache_manager.active_base_files)
            self.assertEqual(len(image_cache_manager.active_base_files),
                             len(active))

            for rem in [
                    fq_path('e97222e91fc4241f49a7f520d1dcf446751129b3_sm'),
                    fq_path('e09c675c2d1cfac32dae3c2d83689c8c94bc693b_sm'),
                    fq_path(hashed_42),
                    fq_path('%s_10737418240' % hashed_1)
            ]:
                self.assertIn(rem, image_cache_manager.removable_base_files)

            mock_bdms.assert_called_once_with(
                ctxt, [uuids.instance_1, uuids.instance_2])
Example #8
0
    def test_verify_base_images(self):
        hashed_1 = '356a192b7913b04c54574d18c28d46e6395428ab'
        hashed_42 = '92cfceb39d57d914ed8b14d0e37643de0797ae56'

        self.flags(instances_path='/instance_path')
        self.flags(remove_unused_base_images=True)

        base_file_list = [
            '00000001', 'ephemeral_0_20_None',
            'e97222e91fc4241f49a7f520d1dcf446751129b3_sm',
            'e09c675c2d1cfac32dae3c2d83689c8c94bc693b_sm', hashed_42, hashed_1,
            '%s_5368709120' % hashed_1,
            '%s_10737418240' % hashed_1, '00000004'
        ]

        def fq_path(path):
            return os.path.join('/instance_path/_base/', path)

        # Fake base directory existance
        orig_exists = os.path.exists

        def exists(path):
            # The python coverage tool got angry with my overly broad mocks
            if not path.startswith('/instance_path'):
                return orig_exists(path)

            if path in [
                    '/instance_path', '/instance_path/_base',
                    '/instance_path/instance-1/disk',
                    '/instance_path/instance-2/disk',
                    '/instance_path/instance-3/disk',
                    '/instance_path/_base/%s.sha1' % hashed_42
            ]:
                return True

            for p in base_file_list:
                if path == fq_path(p):
                    return True
                if path == fq_path(p) + '.sha1':
                    return False

            if path in [
                    '/instance_path/_base/%s_sm' % hashed_1,
                    '/instance_path/_base/%s_sm' % hashed_42
            ]:
                return False

            self.fail('Unexpected path existance check: %s' % path)

        self.stubs.Set(os.path, 'exists', lambda x: exists(x))

        self.stubs.Set(virtutils, 'chown', lambda x, y: None)

        # We need to stub utime as well
        orig_utime = os.utime
        self.stubs.Set(os, 'utime', lambda x, y: None)

        # Fake up some instances in the instances directory
        orig_listdir = os.listdir

        def listdir(path):
            # The python coverage tool got angry with my overly broad mocks
            if not path.startswith('/instance_path'):
                return orig_list(path)

            if path == '/instance_path':
                return ['instance-1', 'instance-2', 'instance-3', '_base']

            if path == '/instance_path/_base':
                return base_file_list

            self.fail('Unexpected directory listed: %s' % path)

        self.stubs.Set(os, 'listdir', lambda x: listdir(x))

        # Fake isfile for these faked images in _base
        orig_isfile = os.path.isfile

        def isfile(path):
            # The python coverage tool got angry with my overly broad mocks
            if not path.startswith('/instance_path'):
                return orig_isfile(path)

            for p in base_file_list:
                if path == fq_path(p):
                    return True

            self.fail('Unexpected isfile call: %s' % path)

        self.stubs.Set(os.path, 'isfile', lambda x: isfile(x))

        # Fake the database call which lists running instances
        self.stubs.Set(
            db, 'instance_get_all', lambda x: [{
                'image_ref': '1',
                'host': FLAGS.host,
                'name': 'instance-1',
                'uuid': '123'
            }, {
                'image_ref': '1',
                'host': FLAGS.host,
                'name': 'instance-2',
                'uuid': '456'
            }])

        image_cache_manager = imagecache.ImageCacheManager()

        # Fake the utils call which finds the backing image
        def get_disk_backing_file(path):
            if path in [
                    '/instance_path/instance-1/disk',
                    '/instance_path/instance-2/disk'
            ]:
                return fq_path('%s_5368709120' % hashed_1)
            self.fail('Unexpected backing file lookup: %s' % path)

        self.stubs.Set(virtutils, 'get_disk_backing_file',
                       lambda x: get_disk_backing_file(x))

        # Fake out verifying checksums, as that is tested elsewhere
        self.stubs.Set(image_cache_manager, '_verify_checksum',
                       lambda x, y: y == hashed_42)

        # Fake getmtime as well
        orig_getmtime = os.path.getmtime

        def getmtime(path):
            if not path.startswith('/instance_path'):
                return orig_getmtime(path)

            return 1000000

        self.stubs.Set(os.path, 'getmtime', lambda x: getmtime(x))

        # Make sure we don't accidentally remove a real file
        orig_remove = os.remove

        def remove(path):
            if not path.startswith('/instance_path'):
                return orig_remove(path)

            # Don't try to remove fake files
            return

        self.stubs.Set(os, 'remove', lambda x: remove(x))

        # And finally we can make the call we're actually testing...
        # The argument here should be a context, but it is mocked out
        image_cache_manager.verify_base_images(None)

        # Verify
        active = [fq_path(hashed_1), fq_path('%s_5368709120' % hashed_1)]
        self.assertEquals(image_cache_manager.active_base_files, active)

        for rem in [
                fq_path('e97222e91fc4241f49a7f520d1dcf446751129b3_sm'),
                fq_path('e09c675c2d1cfac32dae3c2d83689c8c94bc693b_sm'),
                fq_path(hashed_42),
                fq_path('%s_10737418240' % hashed_1)
        ]:
            self.assertTrue(rem in image_cache_manager.removable_base_files)

        # Ensure there are no "corrupt" images as well
        self.assertTrue(len(image_cache_manager.corrupt_base_files), 0)
    def test_configured_checksum_path(self):
        with utils.tempdir() as tmpdir:
            self.flags(instances_path=tmpdir)
            self.flags(image_info_filename_pattern=('$instances_path/'
                                                    '%(image)s.info'),
                       group='libvirt')

            # Ensure there is a base directory
            os.mkdir(os.path.join(tmpdir, '_base'))

            # Fake the database call which lists running instances
            instances = [{
                'image_ref': '1',
                'host': CONF.host,
                'name': 'instance-1',
                'uuid': '123',
                'vm_state': '',
                'task_state': ''
            }, {
                'image_ref': '1',
                'host': CONF.host,
                'name': 'instance-2',
                'uuid': '456',
                'vm_state': '',
                'task_state': ''
            }]

            all_instances = []
            for instance in instances:
                all_instances.append(
                    fake_instance.fake_instance_obj(None, **instance))

            def touch(filename):
                f = open(filename, 'w')
                f.write('Touched')
                f.close()

            old = time.time() - (25 * 3600)
            hashed = 'e97222e91fc4241f49a7f520d1dcf446751129b3'
            base_filename = os.path.join(tmpdir, hashed)
            touch(base_filename)
            touch(base_filename + '.info')
            os.utime(base_filename + '.info', (old, old))
            touch(base_filename + '.info')
            os.utime(base_filename + '.info', (old, old))

            self.mox.StubOutWithMock(
                objects.block_device.BlockDeviceMappingList,
                'bdms_by_instance_uuid')

            ctxt = context.get_admin_context()
            objects.block_device.BlockDeviceMappingList.bdms_by_instance_uuid(
                ctxt, ['123', '456']).AndReturn({})

            self.mox.ReplayAll()

            image_cache_manager = imagecache.ImageCacheManager()
            image_cache_manager.update(ctxt, all_instances)

            self.assertTrue(os.path.exists(base_filename))
            self.assertTrue(os.path.exists(base_filename + '.info'))