root / snf-cyclades-app / synnefo / logic / reconciliation.py @ 28662998
History | View | Annotate | Download (12.6 kB)
1 | 9fea53cc | Vangelis Koukis | #!/usr/bin/env python
|
---|---|---|---|
2 | 9fea53cc | Vangelis Koukis | # -*- coding: utf-8 -*-
|
3 | 9fea53cc | Vangelis Koukis | #
|
4 | 9fea53cc | Vangelis Koukis | # Copyright 2011 GRNET S.A. All rights reserved.
|
5 | 9fea53cc | Vangelis Koukis | #
|
6 | 9fea53cc | Vangelis Koukis | # Redistribution and use in source and binary forms, with or
|
7 | 9fea53cc | Vangelis Koukis | # without modification, are permitted provided that the following
|
8 | 9fea53cc | Vangelis Koukis | # conditions are met:
|
9 | 9fea53cc | Vangelis Koukis | #
|
10 | 9fea53cc | Vangelis Koukis | # 1. Redistributions of source code must retain the above
|
11 | 9fea53cc | Vangelis Koukis | # copyright notice, this list of conditions and the following
|
12 | 9fea53cc | Vangelis Koukis | # disclaimer.
|
13 | 9fea53cc | Vangelis Koukis | #
|
14 | 9fea53cc | Vangelis Koukis | # 2. Redistributions in binary form must reproduce the above
|
15 | 9fea53cc | Vangelis Koukis | # copyright notice, this list of conditions and the following
|
16 | 9fea53cc | Vangelis Koukis | # disclaimer in the documentation and/or other materials
|
17 | 9fea53cc | Vangelis Koukis | # provided with the distribution.
|
18 | 9fea53cc | Vangelis Koukis | #
|
19 | 9fea53cc | Vangelis Koukis | # THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
|
20 | 9fea53cc | Vangelis Koukis | # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
21 | 9fea53cc | Vangelis Koukis | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
22 | 9fea53cc | Vangelis Koukis | # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
|
23 | 9fea53cc | Vangelis Koukis | # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
24 | 9fea53cc | Vangelis Koukis | # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
25 | 9fea53cc | Vangelis Koukis | # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
26 | 9fea53cc | Vangelis Koukis | # USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
27 | 9fea53cc | Vangelis Koukis | # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
28 | 9fea53cc | Vangelis Koukis | # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
29 | 9fea53cc | Vangelis Koukis | # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
30 | 9fea53cc | Vangelis Koukis | # POSSIBILITY OF SUCH DAMAGE.
|
31 | 9fea53cc | Vangelis Koukis | #
|
32 | 9fea53cc | Vangelis Koukis | # The views and conclusions contained in the software and
|
33 | 9fea53cc | Vangelis Koukis | # documentation are those of the authors and should not be
|
34 | 9fea53cc | Vangelis Koukis | # interpreted as representing official policies, either expressed
|
35 | 9fea53cc | Vangelis Koukis | # or implied, of GRNET S.A.
|
36 | 9fea53cc | Vangelis Koukis | #
|
37 | 9fea53cc | Vangelis Koukis | """Business logic for reconciliation
|
38 | 9fea53cc | Vangelis Koukis |
|
39 | 9fea53cc | Vangelis Koukis | Reconcile the contents of the DB with the actual state of the
|
40 | 9fea53cc | Vangelis Koukis | Ganeti backend.
|
41 | 9fea53cc | Vangelis Koukis |
|
42 | 9fea53cc | Vangelis Koukis | Let D be the set of VMs in the DB, G the set of VMs in Ganeti.
|
43 | 9fea53cc | Vangelis Koukis | RULES:
|
44 | 9fea53cc | Vangelis Koukis | R1. Stale servers in DB:
|
45 | 9fea53cc | Vangelis Koukis | For any v in D but not in G:
|
46 | 9fea53cc | Vangelis Koukis | Set deleted=True.
|
47 | 9fea53cc | Vangelis Koukis | R2. Orphan instances in Ganet:
|
48 | 9fea53cc | Vangelis Koukis | For any v in G with deleted=True in D:
|
49 | 9fea53cc | Vangelis Koukis | Issue OP_INSTANCE_DESTROY.
|
50 | 9fea53cc | Vangelis Koukis | R3. Unsynced operstate:
|
51 | 9fea53cc | Vangelis Koukis | For any v whose operating state differs between G and V:
|
52 | 9fea53cc | Vangelis Koukis | Set the operating state in D based on the state in G.
|
53 | 9fea53cc | Vangelis Koukis | In the code, D, G are Python dicts mapping instance ids to operating state.
|
54 | 9fea53cc | Vangelis Koukis | For D, the operating state is chosen from VirtualMachine.OPER_STATES.
|
55 | 9fea53cc | Vangelis Koukis | For G, the operating state is True if the machine is up, False otherwise.
|
56 | 9fea53cc | Vangelis Koukis |
|
57 | 9fea53cc | Vangelis Koukis | """
|
58 | 9fea53cc | Vangelis Koukis | |
59 | 9e98ba3c | Giorgos Verigakis | import logging |
60 | 9fea53cc | Vangelis Koukis | import sys |
61 | 0e9a423f | Christos Stavrakakis | import itertools |
62 | 9fea53cc | Vangelis Koukis | |
63 | 9fea53cc | Vangelis Koukis | from django.core.management import setup_environ |
64 | 9fea53cc | Vangelis Koukis | try:
|
65 | 9fea53cc | Vangelis Koukis | from synnefo import settings |
66 | 9fea53cc | Vangelis Koukis | except ImportError: |
67 | 9fea53cc | Vangelis Koukis | raise Exception("Cannot import settings, make sure PYTHONPATH contains " |
68 | 9fea53cc | Vangelis Koukis | "the parent directory of the Synnefo Django project.")
|
69 | 9fea53cc | Vangelis Koukis | setup_environ(settings) |
70 | 9fea53cc | Vangelis Koukis | |
71 | 4161cb41 | Christos Stavrakakis | |
72 | 4161cb41 | Christos Stavrakakis | from datetime import datetime, timedelta |
73 | 7ab30015 | Christos Stavrakakis | from collections import namedtuple |
74 | 4161cb41 | Christos Stavrakakis | |
75 | a67419d8 | Christos Stavrakakis | from synnefo.db.models import (VirtualMachine, NetworkInterface, Flavor, |
76 | 7ab30015 | Christos Stavrakakis | pooled_rapi_client) |
77 | 3524241a | Christos Stavrakakis | from synnefo.logic.rapi import GanetiApiError |
78 | e77a29ab | Christos Stavrakakis | from synnefo.logic.backend import get_instances |
79 | d30f29aa | Christos Stavrakakis | from synnefo.logic import utils |
80 | 9fea53cc | Vangelis Koukis | |
81 | 9fea53cc | Vangelis Koukis | |
82 | 9e98ba3c | Giorgos Verigakis | log = logging.getLogger() |
83 | 9e98ba3c | Giorgos Verigakis | |
84 | e63050ca | Christos Stavrakakis | try:
|
85 | e63050ca | Christos Stavrakakis | CHECK_INTERVAL = settings.RECONCILIATION_CHECK_INTERVAL |
86 | e63050ca | Christos Stavrakakis | except AttributeError: |
87 | e63050ca | Christos Stavrakakis | CHECK_INTERVAL = 60
|
88 | e63050ca | Christos Stavrakakis | |
89 | e63050ca | Christos Stavrakakis | |
90 | e63050ca | Christos Stavrakakis | def needs_reconciliation(vm): |
91 | e63050ca | Christos Stavrakakis | now = datetime.now() |
92 | e63050ca | Christos Stavrakakis | return (now > vm.updated + timedelta(seconds=CHECK_INTERVAL)) or\ |
93 | e63050ca | Christos Stavrakakis | (now > vm.backendtime + timedelta(seconds=2*CHECK_INTERVAL))
|
94 | e63050ca | Christos Stavrakakis | |
95 | a67419d8 | Christos Stavrakakis | VMState = namedtuple("VMState", ["state", "cpu", "ram", "nics"]) |
96 | 7ab30015 | Christos Stavrakakis | |
97 | 9e98ba3c | Giorgos Verigakis | |
98 | 9fea53cc | Vangelis Koukis | def stale_servers_in_db(D, G): |
99 | 9fea53cc | Vangelis Koukis | idD = set(D.keys())
|
100 | 9fea53cc | Vangelis Koukis | idG = set(G.keys())
|
101 | 9fea53cc | Vangelis Koukis | |
102 | 4161cb41 | Christos Stavrakakis | stale = set()
|
103 | 4161cb41 | Christos Stavrakakis | for i in idD - idG: |
104 | 4161cb41 | Christos Stavrakakis | if D[i] == 'BUILD': |
105 | 4161cb41 | Christos Stavrakakis | vm = VirtualMachine.objects.get(id=i) |
106 | e63050ca | Christos Stavrakakis | if needs_reconciliation(vm):
|
107 | 4216cd83 | Christos Stavrakakis | with pooled_rapi_client(vm) as c: |
108 | 4216cd83 | Christos Stavrakakis | try:
|
109 | 3524241a | Christos Stavrakakis | job_status = c.GetJobStatus(vm.backendjobid)['status']
|
110 | 3524241a | Christos Stavrakakis | if job_status in ('queued', 'waiting', 'running'): |
111 | 3524241a | Christos Stavrakakis | # Server is still building in Ganeti
|
112 | 3524241a | Christos Stavrakakis | continue
|
113 | 3524241a | Christos Stavrakakis | else:
|
114 | 3524241a | Christos Stavrakakis | c.GetInstance(utils.id_to_instance_name(i)) |
115 | 3524241a | Christos Stavrakakis | # Server has just been created in Ganeti
|
116 | 3524241a | Christos Stavrakakis | continue
|
117 | 4216cd83 | Christos Stavrakakis | except GanetiApiError:
|
118 | 4216cd83 | Christos Stavrakakis | stale.add(i) |
119 | 4161cb41 | Christos Stavrakakis | else:
|
120 | 4161cb41 | Christos Stavrakakis | stale.add(i) |
121 | 4161cb41 | Christos Stavrakakis | |
122 | 4161cb41 | Christos Stavrakakis | return stale
|
123 | 9fea53cc | Vangelis Koukis | |
124 | 9fea53cc | Vangelis Koukis | |
125 | 9fea53cc | Vangelis Koukis | def orphan_instances_in_ganeti(D, G): |
126 | 9fea53cc | Vangelis Koukis | idD = set(D.keys())
|
127 | 9fea53cc | Vangelis Koukis | idG = set(G.keys())
|
128 | 9fea53cc | Vangelis Koukis | |
129 | 9fea53cc | Vangelis Koukis | return idG - idD
|
130 | 9fea53cc | Vangelis Koukis | |
131 | 9fea53cc | Vangelis Koukis | |
132 | 9fea53cc | Vangelis Koukis | def unsynced_operstate(D, G): |
133 | 9fea53cc | Vangelis Koukis | unsynced = set()
|
134 | 9fea53cc | Vangelis Koukis | idD = set(D.keys())
|
135 | 9fea53cc | Vangelis Koukis | idG = set(G.keys())
|
136 | 9fea53cc | Vangelis Koukis | |
137 | 9fea53cc | Vangelis Koukis | for i in idD & idG: |
138 | 7ab30015 | Christos Stavrakakis | dbstate = D[i].state |
139 | 7ab30015 | Christos Stavrakakis | gntstate = G[i].state |
140 | 7ab30015 | Christos Stavrakakis | vm_unsynced = (gntstate and dbstate != "STARTED") or\ |
141 | 7ab30015 | Christos Stavrakakis | (not gntstate and dbstate not in ('BUILD', 'ERROR', 'STOPPED')) |
142 | c4e45b57 | Christos Stavrakakis | if vm_unsynced:
|
143 | 7ab30015 | Christos Stavrakakis | unsynced.add((i, dbstate, gntstate)) |
144 | 7ab30015 | Christos Stavrakakis | if not gntstate and dbstate == 'BUILD': |
145 | 4161cb41 | Christos Stavrakakis | vm = VirtualMachine.objects.get(id=i) |
146 | e63050ca | Christos Stavrakakis | if needs_reconciliation(vm):
|
147 | 4216cd83 | Christos Stavrakakis | with pooled_rapi_client(vm) as c: |
148 | 4216cd83 | Christos Stavrakakis | try:
|
149 | 3524241a | Christos Stavrakakis | job_info = c.GetJobStatus(job_id=vm.backendjobid) |
150 | 3524241a | Christos Stavrakakis | if job_info['status'] == 'success': |
151 | 7ab30015 | Christos Stavrakakis | unsynced.add((i, dbstate, gntstate)) |
152 | 4216cd83 | Christos Stavrakakis | except GanetiApiError:
|
153 | 4216cd83 | Christos Stavrakakis | pass
|
154 | 9fea53cc | Vangelis Koukis | |
155 | 9fea53cc | Vangelis Koukis | return unsynced
|
156 | 9fea53cc | Vangelis Koukis | |
157 | 9fea53cc | Vangelis Koukis | |
158 | a67419d8 | Christos Stavrakakis | def unsynced_flavors(D, G): |
159 | a67419d8 | Christos Stavrakakis | unsynced = set()
|
160 | a67419d8 | Christos Stavrakakis | idD = set(D.keys())
|
161 | a67419d8 | Christos Stavrakakis | idG = set(G.keys())
|
162 | a67419d8 | Christos Stavrakakis | |
163 | a67419d8 | Christos Stavrakakis | for i in idD & idG: |
164 | a67419d8 | Christos Stavrakakis | if D[i].ram != G[i].ram or D[i].cpu != G[i].cpu: |
165 | a67419d8 | Christos Stavrakakis | db_flavor = VirtualMachine.objects.get(id=i).flavor |
166 | a67419d8 | Christos Stavrakakis | try:
|
167 | a67419d8 | Christos Stavrakakis | gnt_flavor = Flavor.objects.get( |
168 | a67419d8 | Christos Stavrakakis | ram=G[i].ram, cpu=G[i].cpu, |
169 | a67419d8 | Christos Stavrakakis | disk=db_flavor.disk, |
170 | a67419d8 | Christos Stavrakakis | disk_template=db_flavor.disk_template) |
171 | a67419d8 | Christos Stavrakakis | except Flavor.DoesNotExist:
|
172 | a67419d8 | Christos Stavrakakis | gnt_flavor = None
|
173 | a67419d8 | Christos Stavrakakis | unsynced.add((i, db_flavor, gnt_flavor)) |
174 | a67419d8 | Christos Stavrakakis | return unsynced
|
175 | a67419d8 | Christos Stavrakakis | |
176 | a67419d8 | Christos Stavrakakis | |
177 | 4161cb41 | Christos Stavrakakis | def instances_with_build_errors(D, G): |
178 | 4161cb41 | Christos Stavrakakis | failed = set()
|
179 | 4161cb41 | Christos Stavrakakis | idD = set(D.keys())
|
180 | 4161cb41 | Christos Stavrakakis | idG = set(G.keys())
|
181 | 4161cb41 | Christos Stavrakakis | |
182 | 4161cb41 | Christos Stavrakakis | for i in idD & idG: |
183 | 4161cb41 | Christos Stavrakakis | if not G[i] and D[i] == 'BUILD': |
184 | 4161cb41 | Christos Stavrakakis | vm = VirtualMachine.objects.get(id=i) |
185 | 1ad47ca5 | Christos Stavrakakis | if not vm.backendjobid: # VM has not been enqueued in the backend |
186 | 1ad47ca5 | Christos Stavrakakis | if datetime.now() > vm.created + timedelta(seconds=120): |
187 | 1ad47ca5 | Christos Stavrakakis | # If a job has not been enqueued after 2 minutues, then
|
188 | 1ad47ca5 | Christos Stavrakakis | # it must be a stale entry..
|
189 | 1ad47ca5 | Christos Stavrakakis | failed.add(i) |
190 | e63050ca | Christos Stavrakakis | elif needs_reconciliation(vm):
|
191 | 1ad47ca5 | Christos Stavrakakis | # Check time to avoid many rapi calls
|
192 | 4216cd83 | Christos Stavrakakis | with pooled_rapi_client(vm) as c: |
193 | 4216cd83 | Christos Stavrakakis | try:
|
194 | 3524241a | Christos Stavrakakis | job_info = c.GetJobStatus(job_id=vm.backendjobid) |
195 | 3524241a | Christos Stavrakakis | if job_info['status'] == 'error': |
196 | 3524241a | Christos Stavrakakis | failed.add(i) |
197 | 4216cd83 | Christos Stavrakakis | except GanetiApiError:
|
198 | 4216cd83 | Christos Stavrakakis | failed.add(i) |
199 | 4161cb41 | Christos Stavrakakis | |
200 | 4161cb41 | Christos Stavrakakis | return failed
|
201 | 4161cb41 | Christos Stavrakakis | |
202 | 4161cb41 | Christos Stavrakakis | |
203 | 7ab30015 | Christos Stavrakakis | def get_servers_from_db(backends, with_nics=True): |
204 | c414bc87 | Christos Stavrakakis | vms = VirtualMachine.objects.filter(deleted=False, backend__in=backends)
|
205 | a67419d8 | Christos Stavrakakis | vm_info = vms.values_list("id", "operstate", "flavor__cpu", "flavor__ram") |
206 | 7ab30015 | Christos Stavrakakis | if with_nics:
|
207 | 7ab30015 | Christos Stavrakakis | nics = NetworkInterface.objects.filter(machine__in=vms)\ |
208 | 7ab30015 | Christos Stavrakakis | .order_by("machine")\
|
209 | 7ab30015 | Christos Stavrakakis | .values_list("machine", "index", "mac", "ipv4", |
210 | 7ab30015 | Christos Stavrakakis | "network")
|
211 | 7ab30015 | Christos Stavrakakis | vm_nics = {} |
212 | 7ab30015 | Christos Stavrakakis | for machine, machine_nics in itertools.groupby(nics, |
213 | 7ab30015 | Christos Stavrakakis | lambda nic: nic[0]): |
214 | 7ab30015 | Christos Stavrakakis | vm_nics[machine] = {} |
215 | 7ab30015 | Christos Stavrakakis | for machine, index, mac, ipv4, network in machine_nics: |
216 | 7ab30015 | Christos Stavrakakis | nic = {'mac': mac,
|
217 | 7ab30015 | Christos Stavrakakis | 'network': utils.id_to_network_name(network),
|
218 | 7ab30015 | Christos Stavrakakis | 'ipv4': ipv4 if ipv4 != '' else None |
219 | 7ab30015 | Christos Stavrakakis | } |
220 | 7ab30015 | Christos Stavrakakis | vm_nics[machine][index] = nic |
221 | a67419d8 | Christos Stavrakakis | servers = dict([(vm_id, VMState(state=state,
|
222 | a67419d8 | Christos Stavrakakis | cpu=cpu, |
223 | a67419d8 | Christos Stavrakakis | ram=ram, |
224 | a67419d8 | Christos Stavrakakis | nics=vm_nics.get(vm_id, []))) |
225 | a67419d8 | Christos Stavrakakis | for vm_id, state, cpu, ram in vm_info]) |
226 | 7ab30015 | Christos Stavrakakis | return servers
|
227 | 9fea53cc | Vangelis Koukis | |
228 | 9fea53cc | Vangelis Koukis | |
229 | e77a29ab | Christos Stavrakakis | def get_instances_from_ganeti(backends): |
230 | e77a29ab | Christos Stavrakakis | instances = [] |
231 | e77a29ab | Christos Stavrakakis | for backend in backends: |
232 | e77a29ab | Christos Stavrakakis | instances.append(get_instances(backend)) |
233 | e77a29ab | Christos Stavrakakis | ganeti_instances = reduce(list.__add__, instances, []) |
234 | 9fea53cc | Vangelis Koukis | snf_instances = {} |
235 | 9fea53cc | Vangelis Koukis | |
236 | 9fea53cc | Vangelis Koukis | prefix = settings.BACKEND_PREFIX_ID |
237 | 9fea53cc | Vangelis Koukis | for i in ganeti_instances: |
238 | 9fea53cc | Vangelis Koukis | if i['name'].startswith(prefix): |
239 | 9fea53cc | Vangelis Koukis | try:
|
240 | d30f29aa | Christos Stavrakakis | id = utils.id_from_instance_name(i['name'])
|
241 | 9fea53cc | Vangelis Koukis | except Exception: |
242 | 9e98ba3c | Giorgos Verigakis | log.error("Ignoring instance with malformed name %s",
|
243 | cc92b70f | Christos Stavrakakis | i['name'])
|
244 | 9fea53cc | Vangelis Koukis | continue
|
245 | 9fea53cc | Vangelis Koukis | |
246 | 9fea53cc | Vangelis Koukis | if id in snf_instances: |
247 | 9e98ba3c | Giorgos Verigakis | log.error("Ignoring instance with duplicate Synnefo id %s",
|
248 | cc92b70f | Christos Stavrakakis | i['name'])
|
249 | 9fea53cc | Vangelis Koukis | continue
|
250 | 9fea53cc | Vangelis Koukis | |
251 | 7ab30015 | Christos Stavrakakis | nics = get_nics_from_instance(i) |
252 | a67419d8 | Christos Stavrakakis | beparams = i["beparams"]
|
253 | a67419d8 | Christos Stavrakakis | vcpus = beparams["vcpus"]
|
254 | a67419d8 | Christos Stavrakakis | ram = beparams["maxmem"]
|
255 | 7ab30015 | Christos Stavrakakis | snf_instances[id] = VMState(state=i["oper_state"], |
256 | a67419d8 | Christos Stavrakakis | cpu=vcpus, |
257 | a67419d8 | Christos Stavrakakis | ram=ram, |
258 | 7ab30015 | Christos Stavrakakis | nics=nics) |
259 | 9fea53cc | Vangelis Koukis | |
260 | 7ab30015 | Christos Stavrakakis | return snf_instances
|
261 | 9fea53cc | Vangelis Koukis | |
262 | cc92b70f | Christos Stavrakakis | |
263 | 0e9a423f | Christos Stavrakakis | #
|
264 | 0e9a423f | Christos Stavrakakis | # Nics
|
265 | 0e9a423f | Christos Stavrakakis | #
|
266 | e77a29ab | Christos Stavrakakis | def get_nics_from_ganeti(backends): |
267 | 0e9a423f | Christos Stavrakakis | """Get network interfaces for each ganeti instance.
|
268 | 0e9a423f | Christos Stavrakakis |
|
269 | 0e9a423f | Christos Stavrakakis | """
|
270 | e77a29ab | Christos Stavrakakis | instances = [] |
271 | e77a29ab | Christos Stavrakakis | for backend in backends: |
272 | e77a29ab | Christos Stavrakakis | instances.append(get_instances(backend)) |
273 | e77a29ab | Christos Stavrakakis | instances = reduce(list.__add__, instances, []) |
274 | 0e9a423f | Christos Stavrakakis | prefix = settings.BACKEND_PREFIX_ID |
275 | 0e9a423f | Christos Stavrakakis | |
276 | 0e9a423f | Christos Stavrakakis | snf_instances_nics = {} |
277 | 0e9a423f | Christos Stavrakakis | for i in instances: |
278 | 0e9a423f | Christos Stavrakakis | if i['name'].startswith(prefix): |
279 | 0e9a423f | Christos Stavrakakis | try:
|
280 | d30f29aa | Christos Stavrakakis | id = utils.id_from_instance_name(i['name'])
|
281 | 0e9a423f | Christos Stavrakakis | except Exception: |
282 | 0e9a423f | Christos Stavrakakis | log.error("Ignoring instance with malformed name %s",
|
283 | cc92b70f | Christos Stavrakakis | i['name'])
|
284 | 0e9a423f | Christos Stavrakakis | continue
|
285 | 0e9a423f | Christos Stavrakakis | if id in snf_instances_nics: |
286 | 0e9a423f | Christos Stavrakakis | log.error("Ignoring instance with duplicate Synnefo id %s",
|
287 | cc92b70f | Christos Stavrakakis | i['name'])
|
288 | 0e9a423f | Christos Stavrakakis | continue
|
289 | 0e9a423f | Christos Stavrakakis | |
290 | c6ad2f2d | Christos Stavrakakis | snf_instances_nics[id] = get_nics_from_instance(i)
|
291 | 0e9a423f | Christos Stavrakakis | |
292 | 0e9a423f | Christos Stavrakakis | return snf_instances_nics
|
293 | 0e9a423f | Christos Stavrakakis | |
294 | 0e9a423f | Christos Stavrakakis | |
295 | c6ad2f2d | Christos Stavrakakis | def get_nics_from_instance(i): |
296 | c6ad2f2d | Christos Stavrakakis | ips = zip(itertools.repeat('ipv4'), i['nic.ips']) |
297 | c6ad2f2d | Christos Stavrakakis | macs = zip(itertools.repeat('mac'), i['nic.macs']) |
298 | c6ad2f2d | Christos Stavrakakis | networks = zip(itertools.repeat('network'), i['nic.networks']) |
299 | c6ad2f2d | Christos Stavrakakis | # modes = zip(itertools.repeat('mode'), i['nic.modes'])
|
300 | c6ad2f2d | Christos Stavrakakis | # links = zip(itertools.repeat('link'), i['nic.links'])
|
301 | c6ad2f2d | Christos Stavrakakis | # nics = zip(ips,macs,modes,networks,links)
|
302 | c6ad2f2d | Christos Stavrakakis | nics = zip(ips, macs, networks)
|
303 | c6ad2f2d | Christos Stavrakakis | nics = map(lambda x: dict(x), nics) |
304 | c6ad2f2d | Christos Stavrakakis | nics = dict(enumerate(nics)) |
305 | c6ad2f2d | Christos Stavrakakis | return nics
|
306 | c6ad2f2d | Christos Stavrakakis | |
307 | c6ad2f2d | Christos Stavrakakis | |
308 | 7ab30015 | Christos Stavrakakis | def unsynced_nics(DBVMs, GanetiVMs): |
309 | 0e9a423f | Christos Stavrakakis | """Find unsynced network interfaces between DB and Ganeti.
|
310 | 0e9a423f | Christos Stavrakakis |
|
311 | 0e9a423f | Christos Stavrakakis | @ rtype: dict; {instance_id: ganeti_nics}
|
312 | 0e9a423f | Christos Stavrakakis | @ return Dictionary containing the instances ids that have unsynced network
|
313 | 0e9a423f | Christos Stavrakakis | interfaces between DB and Ganeti and the network interfaces in Ganeti.
|
314 | 0e9a423f | Christos Stavrakakis |
|
315 | 0e9a423f | Christos Stavrakakis | """
|
316 | 7ab30015 | Christos Stavrakakis | idD = set(DBVMs.keys())
|
317 | 7ab30015 | Christos Stavrakakis | idG = set(GanetiVMs.keys())
|
318 | 0e9a423f | Christos Stavrakakis | |
319 | 0e9a423f | Christos Stavrakakis | unsynced = {} |
320 | 0e9a423f | Christos Stavrakakis | for i in idD & idG: |
321 | 7ab30015 | Christos Stavrakakis | nicsD = DBVMs[i].nics |
322 | 7ab30015 | Christos Stavrakakis | nicsG = GanetiVMs[i].nics |
323 | 0e9a423f | Christos Stavrakakis | if len(nicsD) != len(nicsG): |
324 | 0e9a423f | Christos Stavrakakis | unsynced[i] = (nicsD, nicsG) |
325 | 0e9a423f | Christos Stavrakakis | continue
|
326 | 0e9a423f | Christos Stavrakakis | for index in nicsG.keys(): |
327 | 0e9a423f | Christos Stavrakakis | nicD = nicsD[index] |
328 | 0e9a423f | Christos Stavrakakis | nicG = nicsG[index] |
329 | c4e45b57 | Christos Stavrakakis | diff = (nicD['ipv4'] != nicG['ipv4'] or |
330 | c4e45b57 | Christos Stavrakakis | nicD['mac'] != nicG['mac'] or |
331 | c4e45b57 | Christos Stavrakakis | nicD['network'] != nicG['network']) |
332 | c4e45b57 | Christos Stavrakakis | if diff:
|
333 | cc92b70f | Christos Stavrakakis | unsynced[i] = (nicsD, nicsG) |
334 | cc92b70f | Christos Stavrakakis | break
|
335 | 0e9a423f | Christos Stavrakakis | |
336 | 0e9a423f | Christos Stavrakakis | return unsynced
|
337 | 0e9a423f | Christos Stavrakakis | |
338 | 0e9a423f | Christos Stavrakakis | #
|
339 | 0e9a423f | Christos Stavrakakis | # Networks
|
340 | 0e9a423f | Christos Stavrakakis | #
|
341 | 3524241a | Christos Stavrakakis | |
342 | 3524241a | Christos Stavrakakis | |
343 | 0e9a423f | Christos Stavrakakis | def get_networks_from_ganeti(backend): |
344 | 44e2c577 | Christos Stavrakakis | prefix = settings.BACKEND_PREFIX_ID + 'net-'
|
345 | 0e9a423f | Christos Stavrakakis | |
346 | 0e9a423f | Christos Stavrakakis | networks = {} |
347 | 3524241a | Christos Stavrakakis | with pooled_rapi_client(backend) as c: |
348 | 3524241a | Christos Stavrakakis | for net in c.GetNetworks(bulk=True): |
349 | 3524241a | Christos Stavrakakis | if net['name'].startswith(prefix): |
350 | 3524241a | Christos Stavrakakis | id = utils.id_from_network_name(net['name'])
|
351 | 3524241a | Christos Stavrakakis | networks[id] = net
|
352 | 0e9a423f | Christos Stavrakakis | |
353 | 0e9a423f | Christos Stavrakakis | return networks
|
354 | 0e9a423f | Christos Stavrakakis | |
355 | 0e9a423f | Christos Stavrakakis | |
356 | 0e9a423f | Christos Stavrakakis | def hanging_networks(backend, GNets): |
357 | 0e9a423f | Christos Stavrakakis | """Get networks that are not connected to all Nodegroups.
|
358 | 0e9a423f | Christos Stavrakakis |
|
359 | 0e9a423f | Christos Stavrakakis | """
|
360 | 0e9a423f | Christos Stavrakakis | def get_network_groups(group_list): |
361 | 0e9a423f | Christos Stavrakakis | groups = set()
|
362 | 0e9a423f | Christos Stavrakakis | for g in group_list: |
363 | 0e9a423f | Christos Stavrakakis | g_name = g.split('(')[0] |
364 | 0e9a423f | Christos Stavrakakis | groups.add(g_name) |
365 | 0e9a423f | Christos Stavrakakis | return groups
|
366 | 0e9a423f | Christos Stavrakakis | |
367 | 3524241a | Christos Stavrakakis | with pooled_rapi_client(backend) as c: |
368 | 3524241a | Christos Stavrakakis | groups = set(c.GetGroups())
|
369 | 0e9a423f | Christos Stavrakakis | |
370 | 0e9a423f | Christos Stavrakakis | hanging = {} |
371 | 0e9a423f | Christos Stavrakakis | for id, info in GNets.items(): |
372 | 0e9a423f | Christos Stavrakakis | group_list = get_network_groups(info['group_list'])
|
373 | 0e9a423f | Christos Stavrakakis | if group_list != groups:
|
374 | 0e9a423f | Christos Stavrakakis | hanging[id] = groups - group_list
|
375 | 0e9a423f | Christos Stavrakakis | return hanging
|
376 | 0e9a423f | Christos Stavrakakis | |
377 | 9fea53cc | Vangelis Koukis | |
378 | a65ee5fc | Vangelis Koukis | # Only for testing this module individually
|
379 | 9fea53cc | Vangelis Koukis | def main(): |
380 | 9fea53cc | Vangelis Koukis | print get_instances_from_ganeti()
|
381 | 9fea53cc | Vangelis Koukis | |
382 | 9fea53cc | Vangelis Koukis | |
383 | 9fea53cc | Vangelis Koukis | if __name__ == "__main__": |
384 | 9fea53cc | Vangelis Koukis | sys.exit(main()) |