Revision aee560b0 snf-cyclades-app/synnefo/logic/callbacks.py

b/snf-cyclades-app/synnefo/logic/callbacks.py
36 36

  
37 37
from synnefo.db.models import (Backend, VirtualMachine, Network,
38 38
                               BackendNetwork, pooled_rapi_client)
39
from synnefo.logic import utils, backend
39
from synnefo.logic import utils, backend, rapi
40 40

  
41 41
from synnefo.lib.utils import merge_time
42 42

  
......
177 177
    logmsg = msg["logmsg"]
178 178
    nics = msg.get("nics", None)
179 179
    job_fields = msg.get("job_fields", {})
180
    result = msg.get("result", [])
180 181

  
181 182
    # Special case: OP_INSTANCE_CREATE with opportunistic locking may fail
182 183
    # if all Ganeti nodes are already locked. Retry the job without
183 184
    # opportunistic locking..
184 185
    if (operation == "OP_INSTANCE_CREATE" and status == "error" and
185 186
       job_fields.get("opportunistic_locking", False)):
186
        if vm.backendjobid != jobID:  # The job has already been retried!
187
        try:
188
            error_code = result[1][1]
189
        except IndexError:
190
            error_code = None
191
        if error_code == rapi.ECODE_TEMP_NORES:
192
            if vm.backendjobid != jobID:  # The job has already been retried!
193
                return
194
            # Remove extra fields
195
            [job_fields.pop(f) for f in ("OP_ID", "reason")]
196
            # Remove 'pnode' and 'snode' if they were set by Ganeti iallocator.
197
            # Ganeti will fail if both allocator and nodes are specified.
198
            allocator = job_fields.pop("iallocator")
199
            if allocator is not None:
200
                [job_fields.pop(f) for f in ("pnode", "snode")]
201
            name = job_fields.pop("name", job_fields.pop("instance_name"))
202
            # Turn off opportunistic locking before retrying the job
203
            job_fields["opportunistic_locking"] = False
204
            with pooled_rapi_client(vm) as c:
205
                jobID = c.CreateInstance(name=name, **job_fields)
206
            # Update the VM fields
207
            vm.backendjobid = jobID
208
            vm.backendjobstatus = None
209
            vm.save()
210
            log.info("Retrying failed creation of instance '%s' without"
211
                     " opportunistic locking. New job ID: '%s'", name, jobID)
187 212
            return
188
        # Remove extra fields
189
        [job_fields.pop(f) for f in ("OP_ID", "reason")]
190
        # Remove 'pnode' and 'snode' if they were set by Ganeti iallocator.
191
        # Ganeti will fail if both allocator and nodes are specified.
192
        allocator = job_fields.pop("iallocator")
193
        if allocator is not None:
194
            [job_fields.pop(f) for f in ("pnode", "snode")]
195
        name = job_fields.pop("name", job_fields.pop("instance_name"))
196
        # Turn off opportunistic locking before retrying the job
197
        job_fields["opportunistic_locking"] = False
198
        with pooled_rapi_client(vm) as c:
199
            jobID = c.CreateInstance(name=name, **job_fields)
200
        # Update the VM fields
201
        vm.backendjobid = jobID
202
        vm.backendjobstatus = None
203
        vm.save()
204
        log.info("Retrying failed creation of instance '%s' without"
205
                 " opportunistic locking. New job ID: '%s'", name, jobID)
206
        return
207 213

  
208 214
    backend.process_op_status(vm, event_time, jobID, operation,
209 215
                              status, logmsg, nics)

Also available in: Unified diff