Revision 7ab30015 snf-cyclades-app/synnefo/logic/reconciliation.py

b/snf-cyclades-app/synnefo/logic/reconciliation.py
70 70

  
71 71

  
72 72
from datetime import datetime, timedelta
73
from collections import namedtuple
73 74

  
74
from synnefo.db.models import (VirtualMachine, pooled_rapi_client)
75
from synnefo.db.models import (VirtualMachine, NetworkInterface,
76
                               pooled_rapi_client)
75 77
from synnefo.logic.rapi import GanetiApiError
76 78
from synnefo.logic.backend import get_instances
77 79
from synnefo.logic import utils
......
90 92
    return (now > vm.updated + timedelta(seconds=CHECK_INTERVAL)) or\
91 93
           (now > vm.backendtime + timedelta(seconds=2*CHECK_INTERVAL))
92 94

  
95
VMState = namedtuple("VMState", ["state", "nics"])
96

  
93 97

  
94 98
def stale_servers_in_db(D, G):
95 99
    idD = set(D.keys())
......
131 135
    idG = set(G.keys())
132 136

  
133 137
    for i in idD & idG:
134
        vm_unsynced = (G[i] and D[i] != "STARTED") or\
135
                      (not G[i] and D[i] not in ('BUILD', 'ERROR', 'STOPPED'))
138
        dbstate = D[i].state
139
        gntstate = G[i].state
140
        vm_unsynced = (gntstate and dbstate != "STARTED") or\
141
            (not gntstate and dbstate not in ('BUILD', 'ERROR', 'STOPPED'))
136 142
        if vm_unsynced:
137
            unsynced.add((i, D[i], G[i]))
138
        if not G[i] and D[i] == 'BUILD':
143
            unsynced.add((i, dbstate, gntstate))
144
        if not gntstate and dbstate == 'BUILD':
139 145
            vm = VirtualMachine.objects.get(id=i)
140 146
            if needs_reconciliation(vm):
141 147
                with pooled_rapi_client(vm) as c:
142 148
                    try:
143 149
                        job_info = c.GetJobStatus(job_id=vm.backendjobid)
144 150
                        if job_info['status'] == 'success':
145
                            unsynced.add((i, D[i], G[i]))
151
                            unsynced.add((i, dbstate, gntstate))
146 152
                    except GanetiApiError:
147 153
                        pass
148 154

  
......
175 181
    return failed
176 182

  
177 183

  
178
def get_servers_from_db(backends):
184
def get_servers_from_db(backends, with_nics=True):
179 185
    vms = VirtualMachine.objects.filter(deleted=False, backend__in=backends)
180
    return dict(map(lambda x: (x.id, x.operstate), vms))
186
    vm_info = vms.values_list("id", "operstate")
187
    if with_nics:
188
        nics = NetworkInterface.objects.filter(machine__in=vms)\
189
                               .order_by("machine")\
190
                               .values_list("machine", "index", "mac", "ipv4",
191
                                            "network")
192
        vm_nics = {}
193
        for machine, machine_nics in itertools.groupby(nics,
194
                                                       lambda nic: nic[0]):
195
            vm_nics[machine] = {}
196
            for machine, index, mac, ipv4, network in machine_nics:
197
                nic = {'mac':      mac,
198
                       'network':  utils.id_to_network_name(network),
199
                       'ipv4':     ipv4 if ipv4 != '' else None
200
                       }
201
                vm_nics[machine][index] = nic
202
    servers = dict([(vm_id, VMState(state=state, nics=vm_nics.get(vm_id, [])))
203
                    for vm_id, state in vm_info])
204
    return servers
181 205

  
182 206

  
183 207
def get_instances_from_ganeti(backends):
......
186 210
        instances.append(get_instances(backend))
187 211
    ganeti_instances = reduce(list.__add__, instances, [])
188 212
    snf_instances = {}
189
    snf_nics = {}
190 213

  
191 214
    prefix = settings.BACKEND_PREFIX_ID
192 215
    for i in ganeti_instances:
......
203 226
                          i['name'])
204 227
                continue
205 228

  
206
            snf_instances[id] = i['oper_state']
207
            snf_nics[id] = get_nics_from_instance(i)
229
            nics = get_nics_from_instance(i)
230
            snf_instances[id] = VMState(state=i["oper_state"],
231
                                        nics=nics)
208 232

  
209
    return snf_instances, snf_nics
233
    return snf_instances
210 234

  
211 235

  
212 236
#
......
254 278
    return nics
255 279

  
256 280

  
257
def get_nics_from_db(backends):
258
    """Get network interfaces for each vm in DB.
259

  
260
    """
261
    instances = VirtualMachine.objects.filter(deleted=False,
262
                                              backend__in=backends)
263
    instances_nics = {}
264
    for instance in instances:
265
        nics = {}
266
        for n in instance.nics.all():
267
            ipv4 = n.ipv4
268
            nic = {'mac':      n.mac,
269
                   'network':  n.network.backend_id,
270
                   'ipv4':     ipv4 if ipv4 != '' else None
271
                   }
272
            nics[n.index] = nic
273
        instances_nics[instance.id] = nics
274
    return instances_nics
275

  
276

  
277
def unsynced_nics(DBNics, GNics):
281
def unsynced_nics(DBVMs, GanetiVMs):
278 282
    """Find unsynced network interfaces between DB and Ganeti.
279 283

  
280 284
    @ rtype: dict; {instance_id: ganeti_nics}
......
282 286
    interfaces between DB and Ganeti and the network interfaces in Ganeti.
283 287

  
284 288
    """
285
    idD = set(DBNics.keys())
286
    idG = set(GNics.keys())
289
    idD = set(DBVMs.keys())
290
    idG = set(GanetiVMs.keys())
287 291

  
288 292
    unsynced = {}
289 293
    for i in idD & idG:
290
        nicsD = DBNics[i]
291
        nicsG = GNics[i]
294
        nicsD = DBVMs[i].nics
295
        nicsG = GanetiVMs[i].nics
292 296
        if len(nicsD) != len(nicsG):
293 297
            unsynced[i] = (nicsD, nicsG)
294 298
            continue

Also available in: Unified diff