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])
 def test_raises_when_image_deleted(self):
     img_repo = mock.MagicMock()
     image_import = import_flow._ImportToStore(TASK_ID1, TASK_TYPE,
                                               img_repo, "http://url",
                                               IMAGE_ID1, "store1", False,
                                               True)
     image = self.img_factory.new_image(image_id=UUID1)
     image.status = "deleted"
     img_repo.get.return_value = image
     self.assertRaises(ImportTaskError, image_import.execute)
    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_raises_when_all_stores_must_succeed(self, mock_import):
     img_repo = mock.MagicMock()
     image_import = import_flow._ImportToStore(TASK_ID1, TASK_TYPE,
                                               img_repo, "http://url",
                                               IMAGE_ID1, "store1", True,
                                               True)
     image = self.img_factory.new_image(image_id=UUID1)
     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()
     image_import = import_flow._ImportToStore(TASK_ID1, TASK_TYPE,
                                               img_repo, "http://url",
                                               IMAGE_ID1, "store1", True,
                                               True)
     extra_properties = {"os_glance_importing_to_stores": "store1,store2"}
     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_status_aborts_missing_task(self, mock_get):
     task_repo = mock.MagicMock()
     image_import = import_flow._ImportToStore(TASK_ID1, TASK_TYPE,
                                               task_repo, mock.MagicMock(),
                                               "http://url", "store1",
                                               False, True)
     mock_get.return_value = None
     action = mock.MagicMock()
     self.assertRaises(exception.TaskNotFound,
                       image_import._status_callback, action, 128,
                       256 * units.Mi)
     mock_get.assert_called_once_with(task_repo, TASK_ID1)
     task_repo.save.assert_not_called()
 def test_status_callback_updates_task_message(self, mock_get):
     task_repo = mock.MagicMock()
     image_import = import_flow._ImportToStore(TASK_ID1, TASK_TYPE,
                                               task_repo, mock.MagicMock(),
                                               "http://url", "store1",
                                               False, True)
     task = mock.MagicMock()
     task.status = 'processing'
     mock_get.return_value = task
     action = mock.MagicMock()
     image_import._status_callback(action, 128, 256 * units.Mi)
     mock_get.assert_called_once_with(task_repo, TASK_ID1)
     task_repo.save.assert_called_once_with(task)
     self.assertEqual(_('Copied %i MiB' % 256), task.message)
 def test_status_aborts_invalid_task_state(self, mock_get):
     task_repo = mock.MagicMock()
     image_import = import_flow._ImportToStore(TASK_ID1, TASK_TYPE,
                                               task_repo, mock.MagicMock(),
                                               "http://url", "store1",
                                               False, True)
     task = mock.MagicMock()
     task.status = 'failed'
     mock_get.return_value = task
     action = mock.MagicMock()
     self.assertRaises(exception.TaskAbortedError,
                       image_import._status_callback, action, 128,
                       256 * units.Mi)
     mock_get.assert_called_once_with(task_repo, TASK_ID1)
     task_repo.save.assert_not_called()
 def test_doesnt_raise_when_not_all_stores_must_succeed(self, mock_import):
     img_repo = mock.MagicMock()
     image_import = import_flow._ImportToStore(TASK_ID1, TASK_TYPE,
                                               img_repo, "http://url",
                                               IMAGE_ID1, "store1", False,
                                               True)
     image = self.img_factory.new_image(image_id=UUID1)
     img_repo.get.return_value = image
     mock_import.set_image_data.side_effect = \
         cursive_exception.SignatureVerificationError(
             "Signature verification failed")
     try:
         image_import.execute()
         self.assertEqual(image.extra_properties['os_glance_failed_import'],
                          "store1")
     except cursive_exception.SignatureVerificationError:
         self.fail("Exception shouldn't be raised")
 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_execute(self):
        wrapper = mock.MagicMock()
        action = mock.MagicMock()
        task_repo = mock.MagicMock()
        wrapper.__enter__.return_value = action
        image_import = import_flow._ImportToStore(TASK_ID1, TASK_TYPE,
                                                  task_repo, wrapper,
                                                  "http://url", "store1",
                                                  False, True)
        # Assert file_path is honored
        with mock.patch.object(image_import, '_execute') as mock_execute:
            image_import.execute(mock.sentinel.path)
            mock_execute.assert_called_once_with(action, mock.sentinel.path)

        # Assert file_path is optional
        with mock.patch.object(image_import, '_execute') as mock_execute:
            image_import.execute()
            mock_execute.assert_called_once_with(action, None)
 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'])