Revision 727fb2f9

b/snf-cyclades-app/conf/20-snf-cyclades-app-backend.conf
33 33
## a network. This requires qemu-kvm=1.0.
34 34
#GANETI_USE_HOTPLUG = False
35 35
#
36
## If True, Ganeti will try to allocate new instances only on nodes that are
37
## not already locked. This might result in slightly unbalanced clusters.
38
#GANETI_USE_OPPORTUNISTIC_LOCKING = True
39
#
36 40
## This module implements the strategy for allocating a vm to a backend
37 41
#BACKEND_ALLOCATOR_MODULE = "synnefo.logic.allocators.default_allocator"
38 42
## Refresh backend statistics timeout, in minutes, used in backend allocation
b/snf-cyclades-app/synnefo/app_settings/default/backend.py
33 33
# a network. This requires qemu-kvm=1.0.
34 34
GANETI_USE_HOTPLUG = False
35 35

  
36
# If True, Ganeti will try to allocate new instances only on nodes that are
37
# not already locked. This might result in slightly unbalanced clusters.
38
GANETI_USE_OPPORTUNISTIC_LOCKING = True
39

  
36 40
# This module implements the strategy for allocating a vm to a backend
37 41
BACKEND_ALLOCATOR_MODULE = "synnefo.logic.allocators.default_allocator"
38 42
# Refresh backend statistics timeout, in minutes, used in backend allocation
b/snf-cyclades-app/synnefo/logic/backend.py
434 434
        'img_format': image['format']}
435 435

  
436 436
    # Use opportunistic locking
437
    kw['opportunistic_locking'] = True
437
    kw['opportunistic_locking'] = settings.GANETI_USE_OPPORTUNISTIC_LOCKING
438 438

  
439 439
    # Defined in settings.GANETI_CREATEINSTANCE_KWARGS
440 440
    # kw['hvparams'] = dict(serial_console=False)
b/snf-cyclades-app/synnefo/logic/callbacks.py
34 34
import json
35 35
from functools import wraps
36 36

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

  
40 41
from synnefo.lib.utils import merge_time
......
170 171
        log.error("Message is of unknown type %s.", msg['type'])
171 172
        return
172 173

  
174
    operation = msg["operation"]
175
    status = msg["status"]
176
    jobID = msg["jobId"]
177
    logmsg = msg["logmsg"]
173 178
    nics = msg.get("nics", None)
174
    backend.process_op_status(vm, event_time, msg['jobId'], msg['operation'],
175
                              msg['status'], msg['logmsg'], nics)
179
    job_fields = msg.get("job_fields", {})
180

  
181
    # Special case: OP_INSTANCE_CREATE with opportunistic locking may fail
182
    # if all Ganeti nodes are already locked. Retry the job without
183
    # opportunistic locking..
184
    if (operation == "OP_INSTANCE_CREATE" and status == "error" and
185
       job_fields.get("opportunistic_locking", False)):
186
        if vm.backendjobid != jobID:  # The job has already been retried!
187
            return
188
        # Remove extra fields
189
        [job_fields.pop(f) for f in ("OP_ID", "reason")]
190
        name = job_fields.pop("name", job_fields.pop("instance_name"))
191
        # Turn off opportunistic locking before retrying the job
192
        job_fields["opportunistic_locking"] = False
193
        with pooled_rapi_client(vm) as c:
194
            jobID = c.CreateInstance(name=name, **job_fields)
195
        # Update the VM fields
196
        vm.backendjobid = jobID
197
        vm.backendjobstatus = None
198
        vm.save()
199
        log.info("Retrying failed creation of instance '%s' without"
200
                 " opportunistic locking. New job ID: '%s'", name, jobID)
201
        return
202

  
203
    backend.process_op_status(vm, event_time, jobID, operation,
204
                              status, logmsg, nics)
176 205

  
177 206
    log.debug("Done processing ganeti-op-status msg for vm %s.",
178 207
              msg['instance'])
b/snf-cyclades-gtools/synnefo/ganeti/eventd.py
247 247
                    nics = get_instance_nics(msg["instance"], self.logger)
248 248
                    msg["nics"] = nics
249 249

  
250
            if op_id == "OP_INSTANCE_CREATE" and op.status == "error":
251
                # In case an instance creation fails send the job input
252
                # so that the job can be retried if needed.
253
                msg["job_fields"] = op.Serialize()["input"]
254

  
250 255
            msg = json.dumps(msg)
256

  
251 257
            self.logger.debug("Delivering msg: %s (key=%s)", msg, routekey)
252 258

  
253 259
            # Send the message to RabbitMQ

Also available in: Unified diff