Statistics
| Branch: | Tag: | Revision:

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())