root / snf-cyclades-app / synnefo / logic / reconciliation.py @ 567ffb85
History | View | Annotate | Download (4.3 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 | 9fea53cc | Vangelis Koukis | |
62 | 9fea53cc | Vangelis Koukis | from django.core.management import setup_environ |
63 | 9fea53cc | Vangelis Koukis | try:
|
64 | 9fea53cc | Vangelis Koukis | from synnefo import settings |
65 | 9fea53cc | Vangelis Koukis | except ImportError: |
66 | 9fea53cc | Vangelis Koukis | raise Exception("Cannot import settings, make sure PYTHONPATH contains " |
67 | 9fea53cc | Vangelis Koukis | "the parent directory of the Synnefo Django project.")
|
68 | 9fea53cc | Vangelis Koukis | setup_environ(settings) |
69 | 9fea53cc | Vangelis Koukis | |
70 | 9fea53cc | Vangelis Koukis | from synnefo.db.models import VirtualMachine |
71 | 9e98ba3c | Giorgos Verigakis | from synnefo.util.dictconfig import dictConfig |
72 | 9fea53cc | Vangelis Koukis | from synnefo.util.rapi import GanetiRapiClient |
73 | 9fea53cc | Vangelis Koukis | |
74 | 9fea53cc | Vangelis Koukis | |
75 | 9e98ba3c | Giorgos Verigakis | log = logging.getLogger() |
76 | 9e98ba3c | Giorgos Verigakis | |
77 | 9e98ba3c | Giorgos Verigakis | |
78 | 9fea53cc | Vangelis Koukis | def stale_servers_in_db(D, G): |
79 | 9fea53cc | Vangelis Koukis | idD = set(D.keys())
|
80 | 9fea53cc | Vangelis Koukis | idG = set(G.keys())
|
81 | 9fea53cc | Vangelis Koukis | |
82 | 9fea53cc | Vangelis Koukis | return idD - idG
|
83 | 9fea53cc | Vangelis Koukis | |
84 | 9fea53cc | Vangelis Koukis | |
85 | 9fea53cc | Vangelis Koukis | def orphan_instances_in_ganeti(D, G): |
86 | 9fea53cc | Vangelis Koukis | idD = set(D.keys())
|
87 | 9fea53cc | Vangelis Koukis | idG = set(G.keys())
|
88 | 9fea53cc | Vangelis Koukis | |
89 | 9fea53cc | Vangelis Koukis | return idG - idD
|
90 | 9fea53cc | Vangelis Koukis | |
91 | 9fea53cc | Vangelis Koukis | |
92 | 9fea53cc | Vangelis Koukis | def unsynced_operstate(D, G): |
93 | 9fea53cc | Vangelis Koukis | unsynced = set()
|
94 | 9fea53cc | Vangelis Koukis | idD = set(D.keys())
|
95 | 9fea53cc | Vangelis Koukis | idG = set(G.keys())
|
96 | 9fea53cc | Vangelis Koukis | |
97 | 9fea53cc | Vangelis Koukis | for i in idD & idG: |
98 | 9fea53cc | Vangelis Koukis | if (G[i] and D[i] != 'STARTED' or |
99 | 9fea53cc | Vangelis Koukis | not G[i] and D[i] not in ('BUILD', 'ERROR', 'STOPPED')): |
100 | 9fea53cc | Vangelis Koukis | unsynced.add((i, D[i], G[i])) |
101 | 9fea53cc | Vangelis Koukis | |
102 | 9fea53cc | Vangelis Koukis | return unsynced
|
103 | 9fea53cc | Vangelis Koukis | |
104 | 9fea53cc | Vangelis Koukis | |
105 | 9fea53cc | Vangelis Koukis | def get_servers_from_db(): |
106 | 9fea53cc | Vangelis Koukis | vms = VirtualMachine.objects.filter(deleted=False)
|
107 | 9fea53cc | Vangelis Koukis | return dict(map(lambda x: (x.id, x.operstate), vms)) |
108 | 9fea53cc | Vangelis Koukis | |
109 | 9fea53cc | Vangelis Koukis | |
110 | 9fea53cc | Vangelis Koukis | def get_instances_from_ganeti(): |
111 | 9fea53cc | Vangelis Koukis | rapi = GanetiRapiClient(*settings.GANETI_CLUSTER_INFO) |
112 | 9fea53cc | Vangelis Koukis | ganeti_instances = rapi.GetInstances(bulk=True)
|
113 | 9fea53cc | Vangelis Koukis | snf_instances = {} |
114 | 9fea53cc | Vangelis Koukis | |
115 | 9fea53cc | Vangelis Koukis | prefix = settings.BACKEND_PREFIX_ID |
116 | 9fea53cc | Vangelis Koukis | for i in ganeti_instances: |
117 | 9fea53cc | Vangelis Koukis | if i['name'].startswith(prefix): |
118 | 9fea53cc | Vangelis Koukis | try:
|
119 | 9fea53cc | Vangelis Koukis | id = int(i['name'].split(prefix)[1]) |
120 | 9fea53cc | Vangelis Koukis | except Exception: |
121 | 9e98ba3c | Giorgos Verigakis | log.error("Ignoring instance with malformed name %s",
|
122 | 9fea53cc | Vangelis Koukis | i['name'])
|
123 | 9fea53cc | Vangelis Koukis | continue
|
124 | 9fea53cc | Vangelis Koukis | |
125 | 9fea53cc | Vangelis Koukis | if id in snf_instances: |
126 | 9e98ba3c | Giorgos Verigakis | log.error("Ignoring instance with duplicate Synnefo id %s",
|
127 | 9fea53cc | Vangelis Koukis | i['name'])
|
128 | 9fea53cc | Vangelis Koukis | continue
|
129 | 9fea53cc | Vangelis Koukis | |
130 | 9fea53cc | Vangelis Koukis | snf_instances[id] = i['oper_state'] |
131 | 9fea53cc | Vangelis Koukis | |
132 | 9fea53cc | Vangelis Koukis | return snf_instances
|
133 | 9fea53cc | Vangelis Koukis | |
134 | 9fea53cc | Vangelis Koukis | |
135 | a65ee5fc | Vangelis Koukis | # Only for testing this module individually
|
136 | 9fea53cc | Vangelis Koukis | def main(): |
137 | 9fea53cc | Vangelis Koukis | print get_instances_from_ganeti()
|
138 | 9fea53cc | Vangelis Koukis | |
139 | 9fea53cc | Vangelis Koukis | |
140 | 9fea53cc | Vangelis Koukis | if __name__ == "__main__": |
141 | 9fea53cc | Vangelis Koukis | sys.exit(main()) |