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