withdraw_flow()   C
last analyzed

Complexity

Conditions 9

Size

Total Lines 44
Code Lines 36

Duplication

Lines 40
Ratio 90.91 %

Importance

Changes 0
Metric Value
cc 9
eloc 36
nop 4
dl 40
loc 44
rs 6.6666
c 0
b 0
f 0
1
# encoding: utf-8
2
"""
3
line/watchdog.py
4
5
Created by Thomas Mangin on 2017-07-01.
6
Copyright (c) 2009-2017 Exa Networks. All rights reserved.
7
License: 3-clause BSD. (See the COPYRIGHT file)
8
"""
9
10
from exabgp.reactor.api.command.command import Command
11
from exabgp.reactor.api.command.limit import match_neighbors
12
from exabgp.reactor.api.command.limit import extract_neighbors
13
14
from exabgp.protocol.ip import NoNextHop
15
from exabgp.bgp.message import OUT
16
from exabgp.bgp.message.update.attribute import NextHop
17
18
from exabgp.configuration.static import ParseStaticRoute
19
20
21
def register_announce():
22
    pass
23
24
25 View Code Duplication
@Command.register('text', 'announce route')
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
26
def announce_route(self, reactor, service, line):
27
    def callback():
28
        try:
29
            descriptions, command = extract_neighbors(line)
30
            peers = match_neighbors(reactor.peers(), descriptions)
31
            if not peers:
32
                self.log_failure('no neighbor matching the command : %s' % command)
33
                reactor.processes.answer_error(service)
34
                yield True
35
                return
36
37
            changes = self.api_route(command)
38
            if not changes:
39
                self.log_failure('command could not parse route in : %s' % command)
40
                reactor.processes.answer_error(service)
41
                yield True
42
                return
43
44
            for change in changes:
45
                if not ParseStaticRoute.check(change):
46
                    self.log_message(
47
                        'invalid route for %s : %s' % (', '.join(peers) if peers else 'all peers', change.extensive())
48
                    )
49
                    continue
50
                change.nlri.action = OUT.ANNOUNCE
51
                reactor.configuration.inject_change(peers, change)
52
                self.log_message(
53
                    'route added to %s : %s' % (', '.join(peers) if peers else 'all peers', change.extensive())
54
                )
55
                yield False
56
57
            reactor.processes.answer_done(service)
58
        except ValueError:
59
            self.log_failure('issue parsing the route')
60
            reactor.processes.answer_error(service)
61
            yield True
62
        except IndexError:
63
            self.log_failure('issue parsing the route')
64
            reactor.processes.answer_error(service)
65
            yield True
66
67
    reactor.asynchronous.schedule(service, line, callback())
68
    return True
69
70
71
@Command.register('text', 'withdraw route')
72
def withdraw_route(self, reactor, service, line):
73
    def callback():
74
        try:
75
            descriptions, command = extract_neighbors(line)
76
            peers = match_neighbors(reactor.peers(), descriptions)
77
            if not peers:
78
                self.log_failure('no neighbor matching the command : %s' % command)
79
                reactor.processes.answer_error(service)
80
                yield True
81
                return
82
83
            changes = self.api_route(command)
84
            if not changes:
85
                self.log_failure('command could not parse route in : %s' % command)
86
                reactor.processes.answer_error(service)
87
                yield True
88
                return
89
90
            for change in changes:
91
                # Change the action to withdraw before checking the route
92
                change.nlri.action = OUT.WITHDRAW
93
                # NextHop is a mandatory field (but we do not require in)
94
                if change.nlri.nexthop is NoNextHop:
95
                    change.nlri.nexthop = NextHop('0.0.0.0')
96
97
                if not ParseStaticRoute.check(change):
98
                    self.log_message(
99
                        'invalid route for %s : %s' % (', '.join(peers) if peers else 'all peers', change.extensive())
100
                    )
101
                    continue
102
                if reactor.configuration.inject_change(peers, change):
103
                    self.log_message(
104
                        'route removed from %s : %s' % (', '.join(peers) if peers else 'all peers', change.extensive())
105
                    )
106
                    yield False
107
                else:
108
                    self.log_failure(
109
                        'route not found on %s : %s' % (', '.join(peers) if peers else 'all peers', change.extensive())
110
                    )
111
                    yield False
112
113
            reactor.processes.answer_done(service)
114
        except ValueError:
115
            self.log_failure('issue parsing the route')
116
            reactor.processes.answer_error(service)
117
            yield True
118
        except IndexError:
119
            self.log_failure('issue parsing the route')
120
            reactor.processes.answer_error(service)
121
            yield True
122
123
    reactor.asynchronous.schedule(service, line, callback())
124
    return True
125
126
127 View Code Duplication
@Command.register('text', 'announce vpls')
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
128
def announce_vpls(self, reactor, service, line):
129
    def callback():
130
        try:
131
            descriptions, command = extract_neighbors(line)
132
            peers = match_neighbors(reactor.peers(), descriptions)
133
            if not peers:
134
                self.log_failure('no neighbor matching the command : %s' % command)
135
                reactor.processes.answer_error(service)
136
                yield True
137
                return
138
139
            changes = self.api_vpls(command)
140
            if not changes:
141
                self.log_failure('command could not parse vpls in : %s' % command)
142
                reactor.processes.answer_error(service)
143
                yield True
144
                return
145
146
            for change in changes:
147
                change.nlri.action = OUT.ANNOUNCE
148
                reactor.configuration.inject_change(peers, change)
149
                self.log_message(
150
                    'vpls added to %s : %s' % (', '.join(peers) if peers else 'all peers', change.extensive())
151
                )
152
                yield False
153
154
            reactor.processes.answer_done(service)
155
        except ValueError:
156
            self.log_failure('issue parsing the vpls')
157
            reactor.processes.answer_error(service)
158
            yield True
159
        except IndexError:
160
            self.log_failure('issue parsing the vpls')
161
            reactor.processes.answer_error(service)
162
            yield True
163
164
    reactor.asynchronous.schedule(service, line, callback())
165
    return True
166
167
168 View Code Duplication
@Command.register('text', 'withdraw vpls')
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
169
def withdraw_vpls(self, reactor, service, line):
170
    def callback():
171
        try:
172
            descriptions, command = extract_neighbors(line)
173
            peers = match_neighbors(reactor.peers(), descriptions)
174
            if not peers:
175
                self.log_failure('no neighbor matching the command : %s' % command)
176
                reactor.processes.answer_error(service)
177
                yield True
178
                return
179
180
            changes = self.api_vpls(command)
181
182
            if not changes:
183
                self.log_failure('command could not parse vpls in : %s' % command)
184
                reactor.processes.answer_error(service)
185
                yield True
186
                return
187
188
            for change in changes:
189
                change.nlri.action = OUT.WITHDRAW
190
                if reactor.configuration.inject_change(peers, change):
191
                    self.log_message(
192
                        'vpls removed from %s : %s' % (', '.join(peers) if peers else 'all peers', change.extensive())
193
                    )
194
                    yield False
195
                else:
196
                    self.log_failure(
197
                        'vpls not found on %s : %s' % (', '.join(peers) if peers else 'all peers', change.extensive())
198
                    )
199
                    yield False
200
201
            reactor.processes.answer_done(service)
202
        except ValueError:
203
            self.log_failure('issue parsing the vpls')
204
            reactor.processes.answer_error(service)
205
            yield True
206
        except IndexError:
207
            self.log_failure('issue parsing the vpls')
208
            reactor.processes.answer_error(service)
209
            yield True
210
211
    reactor.asynchronous.schedule(service, line, callback())
212
    return True
213
214
215
@Command.register('text', 'announce attribute')
216
@Command.register('text', 'announce attributes')
217
def announce_attributes(self, reactor, service, line):
218
    def callback():
219
        try:
220
            descriptions, command = extract_neighbors(line)
221
            peers = match_neighbors(reactor.peers(), descriptions)
222
            if not peers:
223
                self.log_failure('no neighbor matching the command : %s' % command)
224
                reactor.processes.answer_error(service)
225
                yield True
226
                return
227
228
            changes = self.api_attributes(command, peers)
229
            if not changes:
230
                self.log_failure('command could not parse route in : %s' % command)
231
                reactor.processes.answer_error(service)
232
                yield True
233
                return
234
235
            for change in changes:
236
                change.nlri.action = OUT.ANNOUNCE
237
                reactor.configuration.inject_change(peers, change)
238
                self.log_message(
239
                    'route added to %s : %s' % (', '.join(peers) if peers else 'all peers', change.extensive())
240
                )
241
                yield False
242
243
            reactor.processes.answer_done(service)
244
        except ValueError:
245
            self.log_failure('issue parsing the route')
246
            reactor.processes.answer_error(service)
247
            yield True
248
        except IndexError:
249
            self.log_failure('issue parsing the route')
250
            reactor.processes.answer_error(service)
251
            yield True
252
253
    reactor.asynchronous.schedule(service, line, callback())
254
    return True
255
256
257 View Code Duplication
@Command.register('text', 'withdraw attributes')
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
258
def withdraw_attribute(self, reactor, service, line):
259
    def callback():
260
        try:
261
            descriptions, command = extract_neighbors(line)
262
            peers = match_neighbors(reactor.peers(), descriptions)
263
            if not peers:
264
                self.log_failure('no neighbor matching the command : %s' % command)
265
                reactor.processes.answer_error(service)
266
                yield True
267
                return
268
269
            changes = self.api_attributes(command, peers)
270
            if not changes:
271
                self.log_failure('command could not parse route in : %s' % command)
272
                reactor.processes.answer_error(service)
273
                yield True
274
                return
275
276
            for change in changes:
277
                change.nlri.action = OUT.WITHDRAW
278
                if reactor.configuration.inject_change(peers, change):
279
                    self.log_message(
280
                        'route removed from %s : %s' % (', '.join(peers) if peers else 'all peers', change.extensive())
281
                    )
282
                    yield False
283
                else:
284
                    self.log_failure(
285
                        'route not found on %s : %s' % (', '.join(peers) if peers else 'all peers', change.extensive())
286
                    )
287
                    yield False
288
289
            reactor.processes.answer_done(service)
290
        except ValueError:
291
            self.log_failure('issue parsing the route')
292
            reactor.processes.answer_error(service)
293
            yield True
294
        except IndexError:
295
            self.log_failure('issue parsing the route')
296
            reactor.processes.answer_error(service)
297
            yield True
298
299
    reactor.asynchronous.schedule(service, line, callback())
300
    return True
301
302
303 View Code Duplication
@Command.register('text', 'announce flow')
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
304
def announce_flow(self, reactor, service, line):
305
    def callback():
306
        try:
307
            descriptions, command = extract_neighbors(line)
308
            peers = match_neighbors(reactor.peers(), descriptions)
309
            if not peers:
310
                self.log_failure('no neighbor matching the command : %s' % command)
311
                reactor.processes.answer_error(service)
312
                yield True
313
                return
314
315
            changes = self.api_flow(command)
316
            if not changes:
317
                self.log_failure('command could not parse flow in : %s' % command)
318
                reactor.processes.answer_error(service)
319
                yield True
320
                return
321
322
            for change in changes:
323
                change.nlri.action = OUT.ANNOUNCE
324
                reactor.configuration.inject_change(peers, change)
325
                self.log_message(
326
                    'flow added to %s : %s' % (', '.join(peers) if peers else 'all peers', change.extensive())
327
                )
328
                yield False
329
330
            reactor.processes.answer_done(service)
331
        except ValueError:
332
            self.log_failure('issue parsing the flow')
333
            reactor.processes.answer_error(service)
334
            yield True
335
        except IndexError:
336
            self.log_failure('issue parsing the flow')
337
            reactor.processes.answer_error(service)
338
            yield True
339
340
    reactor.asynchronous.schedule(service, line, callback())
341
    return True
342
343
344 View Code Duplication
@Command.register('text', 'withdraw flow')
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
345
def withdraw_flow(self, reactor, service, line):
346
    def callback():
347
        try:
348
            descriptions, command = extract_neighbors(line)
349
            peers = match_neighbors(reactor.peers(), descriptions)
350
            if not peers:
351
                self.log_failure('no neighbor matching the command : %s' % command)
352
                reactor.processes.answer_error(service)
353
                yield True
354
                return
355
356
            changes = self.api_flow(command)
357
358
            if not changes:
359
                self.log_failure('command could not parse flow in : %s' % command)
360
                reactor.processes.answer_error(service)
361
                yield True
362
                return
363
364
            for change in changes:
365
                change.nlri.action = OUT.WITHDRAW
366
                if reactor.configuration.inject_change(peers, change):
367
                    self.log_message(
368
                        'flow removed from %s : %s' % (', '.join(peers) if peers else 'all peers', change.extensive())
369
                    )
370
                else:
371
                    self.log_failure(
372
                        'flow not found on %s : %s' % (', '.join(peers) if peers else 'all peers', change.extensive())
373
                    )
374
                yield False
375
376
            reactor.processes.answer_done(service)
377
        except ValueError:
378
            self.log_failure('issue parsing the flow')
379
            reactor.processes.answer_error(service)
380
            yield True
381
        except IndexError:
382
            self.log_failure('issue parsing the flow')
383
            reactor.processes.answer_error(service)
384
            yield True
385
386
    reactor.asynchronous.schedule(service, line, callback())
387
    return True
388
389
390 View Code Duplication
@Command.register('text', 'announce eor')
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
391
def announce_eor(self, reactor, service, command):
392
    def callback(self, command, peers):
393
        family = self.api_eor(command)
394
        if not family:
395
            self.log_failure("Command could not parse eor : %s" % command)
396
            reactor.processes.answer_error(service)
397
            yield True
398
            return
399
400
        reactor.configuration.inject_eor(peers, family)
401
        self.log_message(
402
            "Sent to %s : %s"
403
            % (', '.join(peers if peers else []) if peers is not None else 'all peers', family.extensive())
404
        )
405
        yield False
406
407
        reactor.processes.answer_done(service)
408
409
    try:
410
        descriptions, command = extract_neighbors(command)
411
        peers = match_neighbors(reactor.established_peers(), descriptions)
412
        if not peers:
413
            self.log_failure('no neighbor matching the command : %s' % command)
414
            reactor.processes.answer_error(service)
415
            return False
416
        reactor.asynchronous.schedule(service, command, callback(self, command, peers))
417
        return True
418
    except ValueError:
419
        self.log_failure('issue parsing the command')
420
        reactor.processes.answer_error(service)
421
        return False
422
    except IndexError:
423
        self.log_failure('issue parsing the command')
424
        reactor.processes.answer_error(service)
425
        return False
426
427
428 View Code Duplication
@Command.register('text', 'announce route-refresh')
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
429
def announce_refresh(self, reactor, service, command):
430
    def callback(self, command, peers):
431
        refreshes = self.api_refresh(command)
432
        if not refreshes:
433
            self.log_failure("Command could not parse route-refresh command : %s" % command)
434
            reactor.processes.answer_error(service)
435
            yield True
436
            return
437
438
        reactor.configuration.inject_refresh(peers, refreshes)
439
        for refresh in refreshes:
440
            self.log_message(
441
                "Sent to %s : %s"
442
                % (', '.join(peers if peers else []) if peers is not None else 'all peers', refresh.extensive())
443
            )
444
445
        yield False
446
        reactor.processes.answer_done(service)
447
448
    try:
449
        descriptions, command = extract_neighbors(command)
450
        peers = match_neighbors(reactor.established_peers(), descriptions)
451
        if not peers:
452
            self.log_failure('no neighbor matching the command : %s' % command)
453
            reactor.processes.answer_error(service)
454
            return False
455
        reactor.asynchronous.schedule(service, command, callback(self, command, peers))
456
        return True
457
    except ValueError:
458
        self.log_failure('issue parsing the command')
459
        reactor.processes.answer_error(service)
460
        return False
461
    except IndexError:
462
        self.log_failure('issue parsing the command')
463
        reactor.processes.answer_error(service)
464
        return False
465
466
467
@Command.register('text', 'announce operational')
468
def announce_operational(self, reactor, service, command):
469
    def callback(self, command, peers):
470
        operational = self.api_operational(command)
471
        if not operational:
472
            self.log_failure("Command could not parse operational command : %s" % command)
473
            reactor.processes.answer_error(service)
474
            yield True
475
            return
476
477
        reactor.configuration.inject_operational(peers, operational)
478
        self.log_message(
479
            "operational message sent to %s : %s"
480
            % (', '.join(peers if peers else []) if peers is not None else 'all peers', operational.extensive())
481
        )
482
        yield False
483
        reactor.processes.answer_done(service)
484
485
    if (command.split() + ['be', 'safe'])[2].lower() not in (
486
        'asm',
487
        'adm',
488
        'rpcq',
489
        'rpcp',
490
        'apcq',
491
        'apcp',
492
        'lpcq',
493
        'lpcp',
494
    ):
495
        reactor.processes.answer_done(service)
496
        return False
497
498
    try:
499
        descriptions, command = extract_neighbors(command)
500
        peers = match_neighbors(reactor.peers(), descriptions)
501
        if not peers:
502
            self.log_failure('no neighbor matching the command : %s' % command)
503
            reactor.processes.answer_error(service)
504
            return False
505
        reactor.asynchronous.schedule(service, command, callback(self, command, peers))
506
        return True
507
    except ValueError:
508
        self.log_failure('issue parsing the command')
509
        reactor.processes.answer_error(service)
510
        return False
511
    except IndexError:
512
        self.log_failure('issue parsing the command')
513
        reactor.processes.answer_error(service)
514
        return False
515