def test_assert_task_lock(self):
        mock_repo = mock.MagicMock()
        mock_repo.get.return_value.extra_properties = {
            'os_glance_import_task': TASK_ID1
        }
        wrapper = import_flow.ImportActionWrapper(mock_repo, IMAGE_ID1,
                                                  TASK_ID1)
        wrapper.assert_task_lock()

        # Try again with a different task ID and it should fail
        wrapper = import_flow.ImportActionWrapper(mock_repo, IMAGE_ID1, 'foo')
        self.assertRaises(exception.TaskAbortedError, wrapper.assert_task_lock)
    def test_revert_updates_status_keys(self):
        img_repo = mock.MagicMock()
        task_repo = mock.MagicMock()
        wrapper = import_flow.ImportActionWrapper(img_repo, IMAGE_ID1,
                                                  TASK_ID1)
        image_import = import_flow._ImportToStore(TASK_ID1, TASK_TYPE,
                                                  task_repo, wrapper,
                                                  "http://url", "store1", True,
                                                  True)
        extra_properties = {
            "os_glance_importing_to_stores": "store1,store2",
            "os_glance_import_task": TASK_ID1
        }
        image = self.img_factory.new_image(image_id=UUID1,
                                           extra_properties=extra_properties)
        img_repo.get.return_value = image

        fail_key = 'os_glance_failed_import'
        pend_key = 'os_glance_importing_to_stores'

        image_import.revert(None)
        self.assertEqual('store2', image.extra_properties[pend_key])

        try:
            raise Exception('foo')
        except Exception:
            fake_exc_info = sys.exc_info()

        extra_properties = {"os_glance_importing_to_stores": "store1,store2"}
        image_import.revert(taskflow.types.failure.Failure(fake_exc_info))
        self.assertEqual('store2', image.extra_properties[pend_key])
        self.assertEqual('store1', image.extra_properties[fail_key])
Beispiel #3
0
    def setUp(self):
        super(TestWebDownloadTask, self).setUp()

        self.config(node_staging_uri='/tmp/staging')
        self.image_repo = mock.MagicMock()
        self.image_id = mock.MagicMock()
        self.uri = mock.MagicMock()
        self.task_factory = domain.TaskFactory()

        task_input = {
            "import_req": {
                'method': {
                    'name': 'web_download',
                    'uri': 'http://cloud.foo/image.qcow2'
                }
            }
        }
        task_ttl = CONF.task.task_time_to_live

        self.task_type = 'import'
        request_id = 'fake_request_id'
        user_id = 'fake_user'
        self.task = self.task_factory.new_task(self.task_type,
                                               TENANT1,
                                               self.image_id,
                                               user_id,
                                               request_id,
                                               task_time_to_live=task_ttl,
                                               task_input=task_input)

        self.task_id = self.task.task_id
        self.action_wrapper = api_image_import.ImportActionWrapper(
            self.image_repo, self.image_id, self.task_id)
        self.image_repo.get.return_value = mock.MagicMock(
            extra_properties={'os_glance_import_task': self.task_id})
 def test_drop_lock_for_task(self):
     mock_repo = mock.MagicMock()
     mock_repo.get.return_value.extra_properties = {
         'os_glance_import_task': TASK_ID1}
     wrapper = import_flow.ImportActionWrapper(mock_repo, IMAGE_ID1,
                                               TASK_ID1)
     wrapper.drop_lock_for_task()
     mock_repo.delete_property_atomic.assert_called_once_with(
         mock_repo.get.return_value, 'os_glance_import_task', TASK_ID1)
 def test_image_size(self):
     mock_repo = mock.MagicMock()
     mock_image = mock_repo.get.return_value
     mock_image.image_id = IMAGE_ID1
     mock_image.extra_properties = {'os_glance_import_task': TASK_ID1}
     mock_image.size = 123
     wrapper = import_flow.ImportActionWrapper(mock_repo, IMAGE_ID1,
                                               TASK_ID1)
     with wrapper as action:
         self.assertEqual(123, action.image_size)
 def test_set_image_attribute_disallowed(self):
     mock_repo = mock.MagicMock()
     mock_image = mock_repo.get.return_value
     mock_image.extra_properties = {'os_glance_import_task': TASK_ID1}
     mock_image.status = 'bar'
     wrapper = import_flow.ImportActionWrapper(mock_repo, IMAGE_ID1,
                                               TASK_ID1)
     with wrapper as action:
         self.assertRaises(AttributeError,
                           action.set_image_attribute, id='foo')
Beispiel #7
0
    def setUp(self):
        super(TestConvertImageTask, self).setUp()

        glance_store.register_opts(CONF)
        self.config(default_store='file',
                    stores=['file', 'http'],
                    filesystem_store_datadir=self.test_dir,
                    group="glance_store")
        self.config(output_format='qcow2', group='image_conversion')
        glance_store.create_stores(CONF)

        self.work_dir = os.path.join(self.test_dir, 'work_dir')
        utils.safe_mkdirs(self.work_dir)
        self.config(work_dir=self.work_dir, group='task')

        self.context = mock.MagicMock()
        self.img_repo = mock.MagicMock()
        self.task_repo = mock.MagicMock()
        self.image_id = UUID1

        self.gateway = gateway.Gateway()
        self.task_factory = domain.TaskFactory()
        self.img_factory = self.gateway.get_image_factory(self.context)
        self.image = self.img_factory.new_image(image_id=self.image_id,
                                                disk_format='raw',
                                                container_format='bare')

        task_input = {
            "import_from": "http://cloud.foo/image.raw",
            "import_from_format": "raw",
            "image_properties": {
                'disk_format': 'raw',
                'container_format': 'bare'
            }
        }

        task_ttl = CONF.task.task_time_to_live

        self.task_type = 'import'
        request_id = 'fake_request_id'
        user_id = 'fake_user'
        self.task = self.task_factory.new_task(self.task_type,
                                               TENANT1,
                                               self.image_id,
                                               user_id,
                                               request_id,
                                               task_time_to_live=task_ttl,
                                               task_input=task_input)

        self.image.extra_properties = {
            'os_glance_import_task': self.task.task_id
        }
        self.wrapper = import_flow.ImportActionWrapper(self.img_repo,
                                                       self.image_id,
                                                       self.task.task_id)
    def test_status_callback_limits_rate(self, mock_now, mock_log):
        img_repo = mock.MagicMock()
        task_repo = mock.MagicMock()
        task_repo.get.return_value.status = 'processing'
        wrapper = import_flow.ImportActionWrapper(img_repo, IMAGE_ID1,
                                                  TASK_ID1)
        image_import = import_flow._ImportToStore(TASK_ID1, TASK_TYPE,
                                                  task_repo, wrapper,
                                                  "http://url", None, False,
                                                  True)

        expected_calls = []
        log_call = mock.call('Image import %(image_id)s copied %(copied)i MiB',
                             {
                                 'image_id': IMAGE_ID1,
                                 'copied': 0
                             })
        action = mock.MagicMock(image_id=IMAGE_ID1)

        mock_now.return_value = 1000
        image_import._status_callback(action, 32, 32)
        # First call will emit immediately because we only ran __init__
        # which sets the last status to zero
        expected_calls.append(log_call)
        mock_log.assert_has_calls(expected_calls)

        image_import._status_callback(action, 32, 64)
        # Second call will not emit any other logs because no time
        # has passed
        mock_log.assert_has_calls(expected_calls)

        mock_now.return_value += 190
        image_import._status_callback(action, 32, 96)
        # Third call will not emit any other logs because not enough
        # time has passed
        mock_log.assert_has_calls(expected_calls)

        mock_now.return_value += 300
        image_import._status_callback(action, 32, 128)
        # Fourth call will emit because we crossed five minutes
        expected_calls.append(log_call)
        mock_log.assert_has_calls(expected_calls)

        mock_now.return_value += 150
        image_import._status_callback(action, 32, 128)
        # Fifth call will not emit any other logs because not enough
        # time has passed
        mock_log.assert_has_calls(expected_calls)

        mock_now.return_value += 3600
        image_import._status_callback(action, 32, 128)
        # Sixth call will emit because we crossed five minutes
        expected_calls.append(log_call)
        mock_log.assert_has_calls(expected_calls)
 def test_execute_confirms_lock(self, mock_log):
     self.img_repo.get.return_value.extra_properties = {
         'os_glance_import_task': TASK_ID1}
     wrapper = import_flow.ImportActionWrapper(self.img_repo, IMAGE_ID1,
                                               TASK_ID1)
     imagelock = import_flow._ImageLock(TASK_ID1, TASK_TYPE, wrapper)
     imagelock.execute()
     mock_log.debug.assert_called_once_with('Image %(image)s import task '
                                            '%(task)s lock confirmed',
                                            {'image': IMAGE_ID1,
                                             'task': TASK_ID1})
 def test_revert_drops_lock(self, mock_log):
     wrapper = import_flow.ImportActionWrapper(self.img_repo, IMAGE_ID1,
                                               TASK_ID1)
     imagelock = import_flow._ImageLock(TASK_ID1, TASK_TYPE, wrapper)
     with mock.patch.object(wrapper, 'drop_lock_for_task') as mock_drop:
         imagelock.revert(None)
         mock_drop.assert_called_once_with()
     mock_log.debug.assert_called_once_with('Image %(image)s import task '
                                            '%(task)s dropped its lock '
                                            'after failure',
                                            {'image': IMAGE_ID1,
                                             'task': TASK_ID1})
 def test_revert_drops_lock_missing(self, mock_log):
     wrapper = import_flow.ImportActionWrapper(self.img_repo, IMAGE_ID1,
                                               TASK_ID1)
     imagelock = import_flow._ImageLock(TASK_ID1, TASK_TYPE, wrapper)
     with mock.patch.object(wrapper, 'drop_lock_for_task') as mock_drop:
         mock_drop.side_effect = exception.NotFound()
         imagelock.revert(None)
     mock_log.warning.assert_called_once_with('Image %(image)s import task '
                                              '%(task)s lost its lock '
                                              'during execution!',
                                              {'image': IMAGE_ID1,
                                               'task': TASK_ID1})
 def test_set_image_attribute(self):
     mock_repo = mock.MagicMock()
     mock_image = mock_repo.get.return_value
     mock_image.extra_properties = {'os_glance_import_task': TASK_ID1}
     mock_image.status = 'bar'
     wrapper = import_flow.ImportActionWrapper(mock_repo, IMAGE_ID1,
                                               TASK_ID1)
     with wrapper as action:
         action.set_image_attribute(status='foo', virtual_size=123)
     mock_repo.save.assert_called_once_with(mock_image, 'bar')
     self.assertEqual('foo', mock_image.status)
     self.assertEqual(123, mock_image.virtual_size)
 def test_raises_when_image_deleted(self):
     img_repo = mock.MagicMock()
     task_repo = mock.MagicMock()
     wrapper = import_flow.ImportActionWrapper(img_repo, IMAGE_ID1,
                                               TASK_ID1)
     image_import = import_flow._ImportToStore(TASK_ID1, TASK_TYPE,
                                               task_repo, wrapper,
                                               "http://url", "store1",
                                               False, True)
     image = self.img_factory.new_image(image_id=UUID1)
     image.status = "deleted"
     img_repo.get.return_value = image
     self.assertRaises(exception.ImportTaskError, image_import.execute)
 def test_wrapper_success(self):
     mock_repo = mock.MagicMock()
     mock_repo.get.return_value.extra_properties = {
         'os_glance_import_task': TASK_ID1
     }
     wrapper = import_flow.ImportActionWrapper(mock_repo, IMAGE_ID1,
                                               TASK_ID1)
     with wrapper as action:
         self.assertIsInstance(action, import_flow._ImportActions)
     mock_repo.get.assert_has_calls(
         [mock.call(IMAGE_ID1), mock.call(IMAGE_ID1)])
     mock_repo.save.assert_called_once_with(
         mock_repo.get.return_value, mock_repo.get.return_value.status)
    def test_verify_active_status(self):
        fake_img = mock.MagicMock(
            status='active',
            extra_properties={'os_glance_import_task': TASK_ID1})
        mock_repo = mock.MagicMock()
        mock_repo.get.return_value = fake_img
        wrapper = import_flow.ImportActionWrapper(mock_repo, IMAGE_ID1,
                                                  TASK_ID1)

        task = import_flow._VerifyImageState(TASK_ID1, TASK_TYPE, wrapper,
                                             'anything!')

        task.execute()

        fake_img.status = 'importing'
        self.assertRaises(import_flow._NoStoresSucceeded, task.execute)
    def test_image_locations(self):
        mock_repo = mock.MagicMock()
        mock_image = mock_repo.get.return_value
        mock_image.image_id = IMAGE_ID1
        mock_image.extra_properties = {'os_glance_import_task': TASK_ID1}
        mock_image.locations = {'some': {'complex': ['structure']}}
        wrapper = import_flow.ImportActionWrapper(mock_repo, IMAGE_ID1,
                                                  TASK_ID1)
        with wrapper as action:
            self.assertEqual({'some': {'complex': ['structure']}},
                             action.image_locations)
            # Mutate our copy
            action.image_locations['foo'] = 'bar'

        # Make sure we did not mutate the image itself
        self.assertEqual({'some': {'complex': ['structure']}},
                         mock_image.locations)
    def test_wrapper_logs_status(self, mock_log):
        mock_repo = mock.MagicMock()
        mock_image = mock_repo.get.return_value
        mock_image.extra_properties = {'os_glance_import_task': TASK_ID1}
        wrapper = import_flow.ImportActionWrapper(mock_repo, IMAGE_ID1,
                                                  TASK_ID1)

        mock_image.status = 'foo'
        with wrapper as action:
            action.set_image_attribute(status='bar')

        mock_log.debug.assert_called_once_with(
            'Image %(image_id)s status changing from '
            '%(old_status)s to %(new_status)s',
            {'image_id': IMAGE_ID1,
             'old_status': 'foo',
             'new_status': 'bar'})
        self.assertEqual('bar', mock_image.status)
 def test_raises_when_all_stores_must_succeed(self, mock_import):
     img_repo = mock.MagicMock()
     task_repo = mock.MagicMock()
     wrapper = import_flow.ImportActionWrapper(img_repo, IMAGE_ID1,
                                               TASK_ID1)
     image_import = import_flow._ImportToStore(TASK_ID1, TASK_TYPE,
                                               task_repo, wrapper,
                                               "http://url", "store1", True,
                                               True)
     extra_properties = {'os_glance_import_task': TASK_ID1}
     image = self.img_factory.new_image(image_id=UUID1,
                                        extra_properties=extra_properties)
     img_repo.get.return_value = image
     mock_import.set_image_data.side_effect = \
         cursive_exception.SignatureVerificationError(
             "Signature verification failed")
     self.assertRaises(cursive_exception.SignatureVerificationError,
                       image_import.execute)
 def test_remove_store_from_property(self, mock_import):
     img_repo = mock.MagicMock()
     task_repo = mock.MagicMock()
     wrapper = import_flow.ImportActionWrapper(img_repo, IMAGE_ID1,
                                               TASK_ID1)
     image_import = import_flow._ImportToStore(TASK_ID1, TASK_TYPE,
                                               task_repo, wrapper,
                                               "http://url",
                                               "store1", True,
                                               True)
     extra_properties = {"os_glance_importing_to_stores": "store1,store2",
                         "os_glance_import_task": TASK_ID1}
     image = self.img_factory.new_image(image_id=UUID1,
                                        extra_properties=extra_properties)
     img_repo.get.return_value = image
     image_import.execute()
     self.assertEqual(
         image.extra_properties['os_glance_importing_to_stores'], "store2")
    def test_check_task_lock(self, mock_log):
        mock_repo = mock.MagicMock()
        wrapper = import_flow.ImportActionWrapper(mock_repo, IMAGE_ID1,
                                                  TASK_ID1)
        image = mock.MagicMock(image_id=IMAGE_ID1)
        image.extra_properties = {'os_glance_import_task': TASK_ID1}
        mock_repo.get.return_value = image
        self._grab_image(wrapper)
        mock_log.error.assert_not_called()

        image.extra_properties['os_glance_import_task'] = 'somethingelse'
        self.assertRaises(exception.TaskAbortedError,
                          self._grab_image, wrapper)
        mock_log.error.assert_called_once_with(
            'Image %(image)s import task %(task)s attempted to take action on '
            'image, but other task %(other)s holds the lock; Aborting.',
            {'image': image.image_id,
             'task': TASK_ID1,
             'other': 'somethingelse'})
Beispiel #21
0
    def setUp(self):
        super(TestCopyImageTask, self).setUp()

        self.db = unit_test_utils.FakeDB(initialize=False)
        self._create_images()
        self.image_repo = mock.MagicMock()
        self.task_repo = mock.MagicMock()
        self.image_id = UUID1
        self.staging_store = mock.MagicMock()
        self.task_factory = domain.TaskFactory()

        task_input = {
            "import_req": {
                'method': {
                    'name': 'copy-image',
                },
                'stores': ['fast']
            }
        }
        task_ttl = CONF.task.task_time_to_live

        self.task_type = 'import'
        request_id = 'fake_request_id'
        user_id = 'fake_user'
        self.task = self.task_factory.new_task(self.task_type,
                                               TENANT1,
                                               self.image_id,
                                               user_id,
                                               request_id,
                                               task_time_to_live=task_ttl,
                                               task_input=task_input)
        self.task_id = self.task.task_id
        self.action_wrapper = api_image_import.ImportActionWrapper(
            self.image_repo, self.image_id, self.task_id)
        self.image_repo.get.return_value = mock.MagicMock(
            extra_properties={'os_glance_import_task': self.task_id})

        stores = {'cheap': 'file', 'fast': 'file'}
        self.config(enabled_backends=stores)
        store_api.register_store_opts(CONF, reserved_stores=RESERVED_STORES)
        self.config(default_backend='fast', group='glance_store')
        store_api.create_multi_stores(CONF, reserved_stores=RESERVED_STORES)
    def test_wrapper_failure(self):
        mock_repo = mock.MagicMock()
        mock_repo.get.return_value.extra_properties = {
            'os_glance_import_task': TASK_ID1}
        wrapper = import_flow.ImportActionWrapper(mock_repo, IMAGE_ID1,
                                                  TASK_ID1)

        class SpecificError(Exception):
            pass

        try:
            with wrapper:
                raise SpecificError('some failure')
        except SpecificError:
            # NOTE(danms): Make sure we only caught the test exception
            # and aren't hiding anything else
            pass

        mock_repo.get.assert_called_once_with(IMAGE_ID1)
        mock_repo.save.assert_not_called()
 def test_execute_body_without_store(self):
     image = mock.MagicMock()
     img_repo = mock.MagicMock()
     img_repo.get.return_value = image
     task_repo = mock.MagicMock()
     wrapper = import_flow.ImportActionWrapper(img_repo, IMAGE_ID1,
                                               TASK_ID1)
     image_import = import_flow._ImportToStore(TASK_ID1, TASK_TYPE,
                                               task_repo, wrapper,
                                               "http://url", None, False,
                                               True)
     action = mock.MagicMock()
     image_import._execute(action, mock.sentinel.path)
     action.set_image_data.assert_called_once_with(
         mock.sentinel.path,
         TASK_ID1,
         backend=None,
         set_active=True,
         callback=image_import._status_callback)
     action.remove_importing_stores.assert_not_called()
 def test_execute_body_with_store_no_path(self):
     image = mock.MagicMock()
     img_repo = mock.MagicMock()
     img_repo.get.return_value = image
     task_repo = mock.MagicMock()
     wrapper = import_flow.ImportActionWrapper(img_repo, IMAGE_ID1,
                                               TASK_ID1)
     image_import = import_flow._ImportToStore(TASK_ID1, TASK_TYPE,
                                               task_repo, wrapper,
                                               "http://url", "store1",
                                               False, True)
     action = mock.MagicMock()
     image_import._execute(action, None)
     action.set_image_data.assert_called_once_with(
         'http://url',
         TASK_ID1,
         backend='store1',
         set_active=True,
         callback=image_import._status_callback)
     action.remove_importing_stores(['store1'])
    def test_set_image_extra_properties(self, mock_log):
        mock_repo = mock.MagicMock()
        mock_image = mock_repo.get.return_value
        mock_image.image_id = IMAGE_ID1
        mock_image.extra_properties = {'os_glance_import_task': TASK_ID1}
        mock_image.status = 'bar'
        wrapper = import_flow.ImportActionWrapper(mock_repo, IMAGE_ID1,
                                                  TASK_ID1)
        # One banned property
        with wrapper as action:
            action.set_image_extra_properties({'os_glance_foo': 'bar'})
        self.assertEqual({'os_glance_import_task': TASK_ID1},
                         mock_image.extra_properties)

        mock_log.warning.assert_called()
        mock_log.warning.reset_mock()

        # Two banned properties
        with wrapper as action:
            action.set_image_extra_properties({'os_glance_foo': 'bar',
                                               'os_glance_baz': 'bat'})
        self.assertEqual({'os_glance_import_task': TASK_ID1},
                         mock_image.extra_properties)

        mock_log.warning.assert_called()
        mock_log.warning.reset_mock()

        # One banned and one allowed property
        with wrapper as action:
            action.set_image_extra_properties({'foo': 'bar',
                                               'os_glance_foo': 'baz'})
        self.assertEqual({'foo': 'bar',
                          'os_glance_import_task': TASK_ID1},
                         mock_image.extra_properties)

        mock_log.warning.assert_called_once_with(
            'Dropping %(key)s=%(val)s during metadata injection for %(image)s',
            {'key': 'os_glance_foo', 'val': 'baz',
             'image': IMAGE_ID1})
 def test_image_id_property(self):
     mock_repo = mock.MagicMock()
     wrapper = import_flow.ImportActionWrapper(mock_repo, IMAGE_ID1,
                                               TASK_ID1)
     self.assertEqual(IMAGE_ID1, wrapper.image_id)
 def test_execute_confirms_lock_not_held(self, mock_log):
     wrapper = import_flow.ImportActionWrapper(self.img_repo, IMAGE_ID1,
                                               TASK_ID1)
     imagelock = import_flow._ImageLock(TASK_ID1, TASK_TYPE, wrapper)
     self.assertRaises(exception.TaskAbortedError, imagelock.execute)