Revision 0e9a423f snf-cyclades-app/synnefo/logic/management/commands/reconcile.py

b/snf-cyclades-app/synnefo/logic/management/commands/reconcile.py
36 36
"""
37 37
import sys
38 38
import datetime
39
import subprocess
39 40

  
40 41
from optparse import make_option
41 42

  
......
65 66
        make_option('--detect-build-errors', action='store_true',
66 67
                    dest='detect_build_errors', default=False,
67 68
                    help='Detect instances with build error'),
69
        make_option('--detect-unsynced-nics', action='store_true',
70
                    dest='detect_unsynced_nics', default=False,
71
                    help='Detect unsynced nics between DB and Ganeti'),
68 72
        make_option('--detect-all', action='store_true',
69 73
                    dest='detect_all',
70 74
                    default=False, help='Enable all --detect-* arguments'),
......
78 82
        make_option('--fix-build-errors', action='store_true',
79 83
                    dest='fix_build_errors', default=False,
80 84
                    help='Fix (remove) instances with build errors'),
85
         make_option('--fix-unsynced-nics', action='store_true',
86
                    dest='fix_unsynced_nics', default=False,
87
                    help='Fix unsynced nics between DB and Ganeti'),
81 88
        make_option('--fix-all', action='store_true', dest='fix_all',
82 89
                    default=False, help='Enable all --fix-* arguments'))
83 90

  
......
109 116
        D = reconciliation.get_servers_from_db()
110 117
        G = reconciliation.get_instances_from_ganeti()
111 118

  
119
        DBNics = reconciliation.get_nics_from_db()
120
        GNics = reconciliation.get_nics_from_ganeti()
112 121
        #
113 122
        # Detect problems
114 123
        #
......
152 161
            elif verbosity == 2:
153 162
                print >> sys.stderr, "Found no instances with build errors."
154 163

  
164
        if options['detect_unsynced_nics']:
165
            def pretty_print_nics(nics):
166
                if not nics:
167
                    print ''.ljust(18) + 'None'
168
                for index, info in nics.items():
169
                    print ''.ljust(18) + 'nic/' + str(index) + ': MAC: %s, IP: %s, Network: %s' % \
170
                      (info['mac'], info['ipv4'], info['network'])
171

  
172
            unsynced_nics = reconciliation.unsynced_nics(DBNics, GNics)
173
            if len(unsynced_nics) > 0:
174
                print >> sys.stderr, "The nics of servers with the folloing ID's "\
175
                                     "are unsynced:"
176
                for id, nics in unsynced_nics.items():
177
                    print ''.ljust(2) + '%6d:' % id
178
                    print ''.ljust(8) + '%8s:' % 'DB'
179
                    pretty_print_nics(nics[0])
180
                    print ''.ljust(8) + '%8s:' % 'Ganeti'
181
                    pretty_print_nics(nics[1])
182
            elif verbosity == 2:
183
                print >> sys.stderr, "All instance nics are synced."
184

  
155 185
        #
156 186
        # Then fix them
157 187
        #
......
184 214
                opcode = "OP_INSTANCE_REBOOT" if ganeti_up \
185 215
                         else "OP_INSTANCE_SHUTDOWN"
186 216
                event_time = datetime.datetime.now()
187
                backend.process_op_status(vm=vm, etime=event_time ,jobid=-0,
217
                backend.process_op_status(vm=vm, etime=event_time, jobid=-0,
188 218
                    opcode=opcode, status='success',
189 219
                    logmsg='Reconciliation: simulated Ganeti event')
190 220
            print >> sys.stderr, "    ...done"
......
195 225
            for id in build_errors:
196 226
                vm = VirtualMachine.objects.get(pk=id)
197 227
                event_time = datetime.datetime.now()
198
                backend.process_op_status(vm=vm, etime=event_time ,jobid=-0,
228
                backend.process_op_status(vm=vm, etime=event_time, jobid=-0,
199 229
                    opcode="OP_INSTANCE_CREATE", status='error',
200 230
                    logmsg='Reconciliation: simulated Ganeti event')
201 231
            print >> sys.stderr, "    ...done"
202 232

  
233
        if options['fix_unsynced_nics'] and len(unsynced_nics) > 0:
234
            print >> sys.stderr, "Setting the nics of %d out-of-sync VMs:" % \
235
                                  len(unsynced_nics)
236
            for id, nics in unsynced_nics.items():
237
                vm = VirtualMachine.objects.get(pk=id)
238
                nics = nics[1]  # Ganeti nics
239
                if nics == {}:  # No nics
240
                    vm.nics.all.delete()
241
                    continue
242
                for index, nic in nics.items():
243
                    # Produce ipv6
244
                    ipv6 = mac2eui64(nic['mac'], settings.PUBLIC_IPV6_PREFIX)
245
                    nic['ipv6'] = ipv6
246
                    # Rename ipv4 to ip
247
                    nic['ip'] = nic['ipv4']
248
                # Dict to sorted list
249
                final_nics = []
250
                nics_keys = nics.keys()
251
                nics_keys.sort()
252
                for i in nics_keys:
253
                    if nics[i]['network']:
254
                        final_nics.append(nics[i])
255
                    else:
256
                        print 'Network of nic %d of vm %s is None. ' \
257
                              'Can not reconcile' % (i, vm.backend_vm_id)
258
                event_time = datetime.datetime.now()
259
                backend.process_net_status(vm=vm, etime=event_time, nics=final_nics)
260
            print >> sys.stderr, "    ...done"
261

  
262

  
263
def mac2eui64(mac, prefixstr):
264
    process = subprocess.Popen(["mac2eui64", mac, prefixstr],
265
                                stdout=subprocess.PIPE)
266
    return process.stdout.read().rstrip()

Also available in: Unified diff