Revision 8e67ea28

b/snf-cyclades-app/synnefo/api/tests/servers.py
506 506
                                   json.dumps(request), 'json')
507 507
        self.assertItemNotFound(response)
508 508

  
509
    def test_create_server_error(self, mrapi, mimage):
509
    def test_create_server_error(self, mrapi):
510 510
        """Test if the create server call returns the expected response
511 511
           if a valid request has been speficied."""
512
        mimage.return_value = {'location': 'pithos://foo',
513
                               'checksum': '1234',
514
                               "id": 1,
515
                               "name": "test_image",
516
                               'disk_format': 'diskdump'}
517 512
        mrapi().CreateInstance.side_effect = GanetiApiError("..ganeti is down")
518
        flavor = mfactory.FlavorFactory()
519 513
        # Create public network and backend
520 514
        network = mfactory.NetworkFactory(public=True)
521 515
        backend = mfactory.BackendFactory()
522 516
        mfactory.BackendNetworkFactory(network=network, backend=backend)
523 517

  
524
        request = {
525
                    "server": {
526
                        "name": "new-server-test",
527
                        "userid": "test_user",
528
                        "imageRef": 1,
529
                        "flavorRef": flavor.id,
530
                        "metadata": {
531
                            "My Server Name": "Apache1"
532
                        },
533
                        "personality": []
534
                    }
535
        }
518
        request = self.request
536 519
        with mocked_quotaholder():
537 520
            response = self.mypost('servers', 'test_user',
538 521
                                   json.dumps(request), 'json')
b/snf-cyclades-app/synnefo/logic/servers.py
1 1
import logging
2
import datetime
2 3

  
3 4
from socket import getfqdn
4 5
from functools import wraps
......
12 13
from synnefo.api import util
13 14
from synnefo.logic import backend
14 15
from synnefo.logic.backend_allocator import BackendAllocator
15
from synnefo.logic.rapi import GanetiApiError
16 16
from synnefo.db.models import (NetworkInterface, VirtualMachine, Network,
17 17
                               VirtualMachineMetadata, FloatingIP)
18 18

  
......
177 177

  
178 178
        log.info("Created entry in DB for VM '%s'", vm)
179 179

  
180
        # dispatch server created signal
181
        server_created.send(sender=vm, created_vm_params={
182
            'img_id': image['backend_id'],
183
            'img_passwd': password,
184
            'img_format': str(image['format']),
185
            'img_personality': json.dumps(personality),
186
            'img_properties': json.dumps(image['metadata']),
187
        })
188

  
189 180
        nics = create_instance_nics(vm, userid, private_networks, floating_ips)
190 181

  
191 182
        # Also we must create the VM metadata in the same transaction.
......
204 195
    else:
205 196
        transaction.commit()
206 197

  
198
    jobID = None
207 199
    try:
200
        vm = VirtualMachine.objects.select_for_update().get(id=vm.id)
201
        # dispatch server created signal needed to trigger the 'vmapi', which
202
        # enriches the vm object with the 'config_url' attribute which must be
203
        # passed to the Ganeti job.
204
        server_created.send(sender=vm, created_vm_params={
205
            'img_id': image['backend_id'],
206
            'img_passwd': password,
207
            'img_format': str(image['format']),
208
            'img_personality': json.dumps(personality),
209
            'img_properties': json.dumps(image['metadata']),
210
        })
211

  
208 212
        jobID = backend.create_instance(vm, nics, flavor, image)
209 213
        # At this point the job is enqueued in the Ganeti backend
210 214
        vm.backendjobid = jobID
......
214 218
        transaction.commit()
215 219
        log.info("User %s created VM %s, NICs %s, Backend %s, JobID %s",
216 220
                 userid, vm, nics, backend, str(jobID))
217
    except GanetiApiError as e:
218
        log.exception("Can not communicate to backend %s: %s.",
219
                      backend, e)
220
        # Failed while enqueuing OP_INSTANCE_CREATE to backend. Restore
221
        # already reserved quotas by issuing a negative commission
222
        vm.operstate = "ERROR"
223
        vm.backendlogmsg = "Can not communicate to backend."
224
        vm.deleted = True
225
        vm.save()
226
        quotas.issue_and_accept_commission(vm, delete=True)
227
        raise
228 221
    except:
229
        transaction.rollback()
222
        # If an exception is raised, then the user will never get the VM id.
223
        # In order to delete it from DB and release it's resources, we
224
        # mock a successful OP_INSTANCE_REMOVE job.
225
        backend.process_op_status(vm=vm, etime=datetime.datetime.now(),
226
                                  jobid=-0,
227
                                  opcode="OP_INSTANCE_REMOVE",
228
                                  status="success",
229
                                  logmsg="Reconciled eventd: VM creation"
230
                                         " failed.")
230 231
        raise
231 232

  
232 233
    return vm

Also available in: Unified diff