'Test image upload conflict.
If an image is uploaded before an existing upload to the same image
completes, the original upload should succeed and the conflicting
one should fail and any data be deleted.'

def test_upload_to_image_status_saving(self):

    fixture_headers = {'x-image-meta-store': 'file', 'x-image-meta-disk-format': 'vhd', 'x-image-meta-container-format': 'ovf', 'x-image-meta-name': 'some-foo-image'}
    req = webob.Request.blank('/images')
    req.method = 'POST'
    for (k, v) in six.iteritems(fixture_headers):
        req.headers[k] = v
    res = req.get_response(self.api)
    self.assertEqual(http_client.CREATED, res.status_int)
    res_body = jsonutils.loads(res.body)['image']
    image_id = res_body['id']
    self.assertIn(('/images/%s' % image_id), res.headers['location'])
    self.assertEqual('queued', res_body['status'])
    orig_get_image_metadata = registry.get_image_metadata
    orig_image_get = db_api._image_get
    orig_image_update = db_api._image_update
    orig_initiate_deletion = upload_utils.initiate_deletion
    call_sequence = []
    test_status = {'activate_session_started': False, 'queued_guard_passed': False}
    state_changes = []
    def mock_image_update(context, values, image_id, purge_props=False, from_state=None):
        status = values.get('status')
        if status:
            state_changes.append(status)
            if (status == 'active'):
                if test_status['activate_session_started']:
                    raise Exception('target    session    already    started')
                test_status['activate_session_started'] = True
                call_sequence.append('update_active')
            else:
                call_sequence.append('update')
        return orig_image_update(context, values, image_id, purge_props=purge_props, from_state=from_state)
    def mock_image_get(*args, **kwargs):
        "Force    status    to    'saving'    if    not    within    activate    db    session.\n\n                                                If    we    are    in    the    activate    db    session    we    return    'active'    which    we\n                                                then    expect    to    cause    exception.Conflict    to    be    raised    since    this\n                                                indicates    that    another    upload    has    succeeded.\n                                                "
        image = orig_image_get(*args, **kwargs)
        if test_status['activate_session_started']:
            call_sequence.append('image_get_active')
            setattr(image, 'status', 'active')
        else:
            setattr(image, 'status', 'saving')
        return image
    def mock_get_image_metadata(*args, **kwargs):
        'Force    image    status    sequence.\n                                                '
        call_sequence.append('get_image_meta')
        meta = orig_get_image_metadata(*args, **kwargs)
        if (not test_status['queued_guard_passed']):
            meta['status'] = 'queued'
            test_status['queued_guard_passed'] = True
        return meta
    def mock_initiate_deletion(*args, **kwargs):
        call_sequence.append('init_del')
        orig_initiate_deletion(*args, **kwargs)
    req = webob.Request.blank(('/images/%s' % image_id))
    req.method = 'PUT'
    req.headers['Content-Type'] = 'application/octet-stream'
    req.body = 'chunk00000remainder'
    with mock.patch.object(upload_utils, 'initiate_deletion') as mock_init_del:
        mock_init_del.side_effect = mock_initiate_deletion
        with mock.patch.object(registry, 'get_image_metadata') as mock_get_meta:
            mock_get_meta.side_effect = mock_get_image_metadata
            with mock.patch.object(db_api, '_image_get') as mock_db_get:
                mock_db_get.side_effect = mock_image_get
                with mock.patch.object(db_api, '_image_update') as mock_db_update:
                    mock_db_update.side_effect = mock_image_update
                    res = req.get_response(self.api)
                    self.assertEqual(http_client.CONFLICT, res.status_int)
                    self.assertEqual(['get_image_meta', 'get_image_meta', 'update', 'update_active', 'image_get_active', 'init_del'], call_sequence)
                    self.assertTrue(mock_get_meta.called)
                    self.assertTrue(mock_db_get.called)
                    self.assertTrue(mock_db_update.called)
                    self.assertEqual(1, mock_init_del.call_count)
                    self.assertEqual(['saving', 'active'], state_changes)
