Revision 9068cd85

b/db/models.py
308 308
                                        null=True)
309 309
    backendlogmsg = models.TextField(null=True)
310 310

  
311
    buildpercentage = models.IntegerField(null=True)
312

  
311 313
    # Error classes
312 314
    class InvalidBackendIdError(Exception):
313 315
         def __init__(self, value):
......
334 336
    
335 337
    class BuildingError(Exception):
336 338
        pass
339

  
340
    class IllegalState(Exception):
341
        pass
337 342
    
338 343
    def __init__(self, *args, **kw):
339 344
        """Initialize state for just created VM instances."""
b/logic/backend.py
134 134
            firewall_profile=firewall_profile)
135 135
    vm.save()
136 136

  
137
@transaction.commit_on_success
138
def process_progress_update(vm, pr_percentage):
139

  
140
    if not type(pr_percentage) == int:
141
        raise TypeError("Percentage not an integer")
142

  
143
    if pr_percentage < 0 or pr_percentage > 100:
144
        raise Exception("Percentage not in range (0, 100)")
145

  
146
    last_update = vm.buildpercentage
147

  
148
    if last_update > pr_percentage:
149
        raise Exception("Build percentage should increase monotonically" \
150
                        " (old=%d, new=%d)"%(last_update, pr_percentage))
151

  
152
    if not vm.operstate == 'BUILD':
153
        raise VirtualMachine.IllegalState("VM is not in building state")
154

  
155
    vm.buildpercentage = pr_percentage
156
    vm.save()
137 157

  
138 158
def start_action(vm, action):
139 159
    """Update the state of a VM when a new action is initiated."""
b/logic/callbacks.py
134 134
    _logger.debug("Request to update credits")
135 135
    message.channel.basic_ack(message.delivery_tag)
136 136

  
137

  
138
def update_build_progress(message):
139
    """Process a progress update message"""
140
    try:
141
        msg = json.loads(message.body)
142

  
143
        if msg['type'] != "ganeti-create-progess":
144
            _logger.error("Message is of unknown type %s", msg["type"])
145
            return
146

  
147
        # XXX: The following assumes names like snf-12
148
        instid = msg['instance'].split('-')[1]
149

  
150
        vm = VirtualMachine.objects.get(id = instid)
151

  
152
        backend.process_net_status(vm, msg['percentage'])
153

  
154
        _logger.debug("Done processing ganeti-create-progess msg for vm %s.",
155
                      msg["instance"])
156
        message.channel.basic_ack(message.delivery_tag)
157

  
158
    except KeyError:
159
        _logger.error("Malformed incoming JSON, missing attributes: %s",
160
                      message.body)
161
    except VirtualMachine.IllegalState:
162
        _logger.error("Build progress message for non-building VM %s: %s"%
163
                      (instid, message.body))
164
    except Exception as e:
165
        _logger.exception("Unexpected error")
166
        raise
167

  
168

  
137 169
def trigger_status_update(message):
138 170
    """
139 171
        Triggers a status update job for a specific VM id.
b/logic/dispatcher.py
155 155

  
156 156
    QUEUE_GANETI_EVENTS_OP = "%s-events-op" % prefix
157 157
    QUEUE_GANETI_EVENTS_NET = "%s-events-net" % prefix
158
    QUEUE_GANETI_BUILD_PROGR = "%s-events-progress" % prefix
158 159
    QUEUE_CRON_CREDITS = "%s-credits" % prefix
159 160
    QUEUE_EMAIL = "%s-email" % prefix
160 161
    QUEUE_RECONC = "%s-reconciliation" % prefix
......
162 163
        QUEUE_DEBUG = "debug"       # Debug queue, retrieves all messages
163 164

  
164 165
    QUEUES = (QUEUE_GANETI_EVENTS_OP, QUEUE_GANETI_EVENTS_NET,
165
              QUEUE_CRON_CREDITS, QUEUE_EMAIL, QUEUE_RECONC)
166
              QUEUE_CRON_CREDITS, QUEUE_EMAIL, QUEUE_RECONC,
167
              QUEUE_GANETI_BUILD_PROGR)
166 168

  
167 169
    # notifications of type "ganeti-op-status"
168 170
    DB_HANDLER_KEY_OP ='ganeti.%s.event.op' % prefix
169 171
    # notifications of type "ganeti-net-status"
170 172
    DB_HANDLER_KEY_NET ='ganeti.%s.event.net' % prefix
173
    # Build process monitoring event
174
    BUILD_MONITOR_HANDLER = 'ganeti.%s.event.progress' %prefix
171 175

  
172 176
    BINDINGS = [
173
    # Queue                   # Exchange                # RouteKey          # Handler
174
    (QUEUE_GANETI_EVENTS_OP,  settings.EXCHANGE_GANETI, DB_HANDLER_KEY_OP,  'update_db'),
175
    (QUEUE_GANETI_EVENTS_NET, settings.EXCHANGE_GANETI, DB_HANDLER_KEY_NET, 'update_net'),
176
    (QUEUE_CRON_CREDITS,      settings.EXCHANGE_CRON,   '*.credits.*',      'update_credits'),
177
    (QUEUE_EMAIL,             settings.EXCHANGE_API,    '*.email.*',        'send_email'),
178
    (QUEUE_EMAIL,             settings.EXCHANGE_CRON,   '*.email.*',        'send_email'),
179
    (QUEUE_RECONC,            settings.EXCHANGE_CRON,   'reconciliation.*', 'trigger_status_update'),
177
    # Queue                   # Exchange                # RouteKey              # Handler
178
    (QUEUE_GANETI_EVENTS_OP,  settings.EXCHANGE_GANETI, DB_HANDLER_KEY_OP,      'update_db'),
179
    (QUEUE_GANETI_EVENTS_NET, settings.EXCHANGE_GANETI, DB_HANDLER_KEY_NET,     'update_net'),
180
    (QUEUE_GANETI_BUILD_PROGR,settings.EXCHANGE_GANETI, BUILD_MONITOR_HANDLER,  'update_build_progress'),
181
    (QUEUE_CRON_CREDITS,      settings.EXCHANGE_CRON,   '*.credits.*',          'update_credits'),
182
    (QUEUE_EMAIL,             settings.EXCHANGE_API,    '*.email.*',            'send_email'),
183
    (QUEUE_EMAIL,             settings.EXCHANGE_CRON,   '*.email.*',            'send_email'),
184
    (QUEUE_RECONC,            settings.EXCHANGE_CRON,   'reconciliation.*',     'trigger_status_update'),
180 185
    ]
181 186

  
182 187
    if settings.DEBUG is True:
b/logic/tests.py
317 317

  
318 318
        username = users.create_uname(u'Γεώργιος Παπαγεωργίου')
319 319
        self.assertEquals(username, u'παπαγεωγ')
320

  
321
class ProcessProgressUpdateTestCase(TestCase):
322
    fixtures = [ 'db_test_data' ]
323

  
324
    def test_progress_update(self):
325

  
326
        # A VM in status BUILDING
327
        vm = VirtualMachine.objects.get(pk=30002)
328

  
329
        backend.process_progress_update(vm, 12)
330
        self.assertEquals(vm.buildpercentage, 12)
331

  
332
        self.assertRaises(Exception, backend.process_progress_update, vm, 10)
333
        self.assertRaises(Exception, backend.process_progress_update, vm, -1)
334
        self.assertRaises(Exception, backend.process_progress_update, vm, 102)
335
        self.assertRaises(TypeError, backend.process_progress_update, vm, '1')
336

  
337
        # A VM in status RUNNING
338
        vm = VirtualMachine.objects.get(pk=30000)
339
        self.assertRaises(VirtualMachine.IllegalState,
340
                          backend.process_progress_update, vm, 1)

Also available in: Unified diff