Revision f2080d16

b/snf-cyclades-app/synnefo/api/servers.py
31 31
# interpreted as representing official policies, either expressed
32 32
# or implied, of GRNET S.A.
33 33

  
34
import datetime
34 35
from django import dispatch
35 36
from django.conf import settings
36 37
from django.conf.urls.defaults import patterns
......
45 46
from synnefo.api.actions import server_actions
46 47
from synnefo.db.models import (VirtualMachine, VirtualMachineMetadata,
47 48
                               NetworkInterface)
48
from synnefo.logic.backend import create_instance, delete_instance
49
from synnefo.logic.backend import (create_instance, delete_instance,
50
                                   process_op_status)
49 51
from synnefo.logic.utils import get_rsapi_state
50 52
from synnefo.logic.backend_allocator import BackendAllocator
51 53
from synnefo import quotas
......
404 406
                 userid, vm, nic, backend, str(jobID))
405 407
    except:
406 408
        # If an exception is raised, then the user will never get the VM id.
407
        # So, the VM must be marked as 'deleted'. We do not delete the VM row
408
        # from DB, because the job may have been enqueued to Ganeti. We must
409
        # also release the VM resources.
410
        if not vm.deleted:  # just an extra check for reconciliation...
411
            vm.deleted = True
412
            vm.operstate = "ERROR"
413
            vm.backendlogmsg = "Error while enqueuing job to Ganeti."
414
            vm.save()
415
            # The following call performs commit.
416
            quotas.issue_and_accept_commission(vm, delete=True)
409
        # In order to delete it from DB and release it's resources, we
410
        # mock a successful OP_INSTANCE_REMOVE job.
411
        process_op_status(vm=vm,
412
                          etime=datetime.datetime.now(),
413
                          jobid=-0,
414
                          opcode="OP_INSTANCE_REMOVE",
415
                          status="success",
416
                          logmsg="Reconciled eventd: VM creation failed.")
417 417
        raise
418 418

  
419 419
    return vm
b/snf-cyclades-app/synnefo/api/test/servers.py
40 40
from synnefo.cyclades_settings import cyclades_services
41 41
from synnefo.lib.services import get_service_path
42 42
from synnefo.lib import join_urls
43
from synnefo.logic.rapi import GanetiApiError
43 44

  
44 45
from mock import patch
45 46

  
......
303 304
                               json.dumps(request), 'json')
304 305
        self.assertItemNotFound(response)
305 306

  
307
    def test_create_server_error(self, mrapi, mimage):
308
        """Test if the create server call returns the expected response
309
           if a valid request has been speficied."""
310
        mimage.return_value = {'location': 'pithos://foo',
311
                               'checksum': '1234',
312
                               "id": 1,
313
                               "name": "test_image",
314
                               'disk_format': 'diskdump'}
315
        mrapi().CreateInstance.side_effect = GanetiApiError("..ganeti is down")
316
        flavor = mfactory.FlavorFactory()
317
        # Create public network and backend
318
        network = mfactory.NetworkFactory(public=True)
319
        backend = mfactory.BackendFactory()
320
        mfactory.BackendNetworkFactory(network=network, backend=backend)
321

  
322
        request = {
323
                    "server": {
324
                        "name": "new-server-test",
325
                        "userid": "test_user",
326
                        "imageRef": 1,
327
                        "flavorRef": flavor.id,
328
                        "metadata": {
329
                            "My Server Name": "Apache1"
330
                        },
331
                        "personality": []
332
                    }
333
        }
334
        with mocked_quotaholder():
335
            response = self.mypost('servers', 'test_user',
336
                                   json.dumps(request), 'json')
337
        self.assertEqual(response.status_code, 500)
338
        mrapi().CreateInstance.assert_called_once()
339
        vm = VirtualMachine.objects.get()
340
        # The VM has been deleted
341
        self.assertTrue(vm.deleted)
342
        # and it has no nics
343
        self.assertEqual(len(vm.nics.all()), 0)
344
        self.assertEqual(vm.backendjobid, 0)
345

  
306 346

  
307 347
@patch('synnefo.logic.rapi_pool.GanetiRapiClient')
308 348
class ServerDestroyAPITest(ComputeAPITest):
b/snf-django-lib/snf_django/utils/testing.py
140 140
def mocked_quotaholder(success=True):
141 141
    with patch("synnefo.quotas.Quotaholder.get") as astakos:
142 142
        global serial
143
        serial += 1
144
        astakos.return_value.issue_one_commission.return_value = serial
143
        serial += 10
144

  
145
        def foo(*args, **kwargs):
146
            return (len(astakos.return_value.issue_one_commission.mock_calls) +
147
                    serial)
148
        astakos.return_value.issue_one_commission.side_effect = foo
145 149
        astakos.return_value.resolve_commissions.return_value = {"failed": []}
146 150
        yield
147 151

  

Also available in: Unified diff