Passed
Pull Request — master (#80)
by
unknown
01:57
created

build.main   F

Complexity

Total Complexity 108

Size/Duplication

Total Lines 595
Duplicated Lines 9.08 %

Test Coverage

Coverage 36.69%

Importance

Changes 0
Metric Value
eloc 402
dl 54
loc 595
ccs 131
cts 357
cp 0.3669
rs 2
c 0
b 0
f 0
wmc 108

49 Methods

Rating   Name   Duplication   Size   Complexity  
A Main.shutdown() 0 3 1
A Main.setup() 0 8 1
A Main.execute() 0 2 1
A Main._get_link_or_create() 0 9 3
A Main.disable_switch() 0 8 2
A Main.enable_switch() 0 8 2
A Main.add_switch_metadata() 0 12 2
A Main.get_interfaces() 0 10 3
A Main._get_switches_dict() 0 4 1
A Main.get_switches() 0 4 1
A Main.get_switch_metadata() 0 8 2
A Main.get_topology() 0 7 1
A Main._get_links_dict() 0 4 1
A Main._get_link_from_interface() 0 6 3
A Main._get_data() 0 5 1
A Main.delete_switch_metadata() 0 11 2
A Main._get_topology_dict() 0 4 1
A Main._get_interfaces() 0 8 2
A Main._get_topology() 0 3 1
A Main.notify_port_created() 0 6 1
A Main.verify_storehouse() 0 8 1
A Main.load_from_store() 0 8 2
A Main.request_retrieve_entities() 0 18 2
A Main.disable_link() 0 9 2
B Main.enable_interface() 27 27 7
A Main.delete_interface_metadata() 0 21 4
A Main.add_interface_metadata() 0 20 3
B Main.update_instance_metadata() 0 19 8
A Main.notify_link_status_change() 0 9 2
A Main.handle_interface_down() 0 9 1
A Main.handle_interface_link_up() 0 13 3
A Main.handle_interface_created() 0 4 1
A Main.get_interface_metadata() 0 16 3
A Main.delete_link_metadata() 0 13 3
A Main.notify_topology_update() 0 6 1
A Main.enable_link() 0 9 2
A Main.handle_new_switch() 0 12 1
A Main.update_instance() 0 8 2
A Main.handle_connection_lost() 0 12 2
A Main.get_links() 0 7 1
B Main.disable_interface() 27 27 7
A Main.save_metadata_on_store() 0 25 4
A Main.handle_interface_link_down() 0 12 3
A Main.add_links() 0 14 1
A Main.handle_interface_deleted() 0 4 1
A Main.handle_interface_up() 0 9 1
A Main.add_link_metadata() 0 12 2
A Main.notify_metadata_changes() 0 17 4
A Main.get_link_metadata() 0 7 2

How to fix   Duplicated Code    Complexity   

Duplicated Code

Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.

Common duplication problems, and corresponding solutions are:

Complexity

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like build.main often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

1
"""Main module of kytos/topology Kytos Network Application.
2
3
Manage the network topology
4
"""
5 1
from flask import jsonify, request
6
7 1
from kytos.core import KytosEvent, KytosNApp, log, rest
8 1
from kytos.core.helpers import listen_to
9 1
from kytos.core.interface import Interface
10 1
from kytos.core.link import Link
11 1
from kytos.core.switch import Switch
12
# from napps.kytos.topology import settings
13 1
from napps.kytos.topology.models import Topology
14
15
16 1
class Main(KytosNApp):  # pylint: disable=too-many-public-methods
17
    """Main class of kytos/topology NApp.
18
19
    This class is the entry point for this napp.
20
    """
21
22 1
    def setup(self):
23
        """Initialize the NApp's links list."""
24 1
        self.links = {}
25 1
        self.store_items = {}
26
27 1
        self.verify_storehouse('switches')
28 1
        self.verify_storehouse('interfaces')
29 1
        self.verify_storehouse('links')
30
31 1
    def execute(self):
32
        """Do nothing."""
33
34 1
    def shutdown(self):
35
        """Do nothing."""
36
        log.info('NApp kytos/topology shutting down.')
37
38 1
    def _get_link_or_create(self, endpoint_a, endpoint_b):
39
        new_link = Link(endpoint_a, endpoint_b)
40
41
        for link in self.links.values():
42
            if new_link == link:
43
                return link
44
45
        self.links[new_link.id] = new_link
46
        return new_link
47
48 1
    def _get_interfaces(self, dpid):
49
        """Return a list all interfaces from a swicth."""
50
        try:
51
            switch = self.controller.switches[dpid]
52
        except KeyError as exc:
53
            raise KeyError(f"Switch not found :{exc}")
54
        return [iface.as_dict().get('id') for iface in
55
                switch.interfaces.values()]
56
57 1
    def _get_switches_dict(self):
58
        """Return a dictionary with the known switches."""
59
        return {'switches': {s.id: s.as_dict() for s in
60
                             self.controller.switches.values()}}
61
62 1
    def _get_links_dict(self):
63
        """Return a dictionary with the known links."""
64
        return {'links': {l.id: l.as_dict() for l in
65
                          self.links.values()}}
66
67 1
    def _get_topology_dict(self):
68
        """Return a dictionary with the known topology."""
69
        return {'topology': {**self._get_switches_dict(),
70
                             **self._get_links_dict()}}
71
72 1
    def _get_topology(self):
73
        """Return an object representing the topology."""
74 1
        return Topology(self.controller.switches, self.links)
75
76 1
    def _get_link_from_interface(self, interface):
77
        """Return the link of the interface, or None if it does not exist."""
78
        for link in self.links.values():
79
            if interface in (link.endpoint_a, link.endpoint_b):
80
                return link
81
        return None
82
83 1
    @staticmethod
84
    def _get_data(req):
85
        """Get request data."""
86
        data = req.get_json() or {}  # Valid format { "interfaces": [...] }
87
        return data.get('interfaces', [])
88
89 1
    @rest('v3/')
90
    def get_topology(self):
91
        """Return the latest known topology.
92
93
        This topology is updated when there are network events.
94
        """
95
        return jsonify(self._get_topology_dict())
96
97
    # Switch related methods
98 1
    @rest('v3/switches')
99
    def get_switches(self):
100
        """Return a json with all the switches in the topology."""
101
        return jsonify(self._get_switches_dict())
102
103 1
    @rest('v3/switches/<dpid>/enable', methods=['POST'])
104
    def enable_switch(self, dpid):
105
        """Administratively enable a switch in the topology."""
106
        try:
107
            self.controller.switches[dpid].enable()
108
            return jsonify("Operation successful"), 201
109
        except KeyError:
110
            return jsonify("Switch not found"), 404
111
112 1
    @rest('v3/switches/<dpid>/disable', methods=['POST'])
113
    def disable_switch(self, dpid):
114
        """Administratively disable a switch in the topology."""
115
        try:
116
            self.controller.switches[dpid].disable()
117
            return jsonify("Operation successful"), 201
118
        except KeyError:
119
            return jsonify("Switch not found"), 404
120
121 1
    @rest('v3/switches/<dpid>/metadata')
122
    def get_switch_metadata(self, dpid):
123
        """Get metadata from a switch."""
124
        try:
125
            return jsonify({"metadata":
126
                            self.controller.switches[dpid].metadata}), 200
127
        except KeyError:
128
            return jsonify("Switch not found"), 404
129
130 1
    @rest('v3/switches/<dpid>/metadata', methods=['POST'])
131
    def add_switch_metadata(self, dpid):
132
        """Add metadata to a switch."""
133
        metadata = request.get_json()
134
        try:
135
            switch = self.controller.switches[dpid]
136
        except KeyError:
137
            return jsonify("Switch not found"), 404
138
139
        switch.extend_metadata(metadata)
140
        self.notify_metadata_changes(switch, 'added')
141
        return jsonify("Operation successful"), 201
142
143 1
    @rest('v3/switches/<dpid>/metadata/<key>', methods=['DELETE'])
144
    def delete_switch_metadata(self, dpid, key):
145
        """Delete metadata from a switch."""
146
        try:
147
            switch = self.controller.switches[dpid]
148
        except KeyError:
149
            return jsonify("Switch not found"), 404
150
151
        switch.remove_metadata(key)
152
        self.notify_metadata_changes(switch, 'removed')
153
        return jsonify("Operation successful"), 200
154
155
    # Interface related methods
156 1
    @rest('v3/interfaces')
157
    def get_interfaces(self):
158
        """Return a json with all the interfaces in the topology."""
159
        interfaces = {}
160
        switches = self._get_switches_dict()
161
        for switch in switches['switches'].values():
162
            for interface_id, interface in switch['interfaces'].items():
163
                interfaces[interface_id] = interface
164
165
        return jsonify({'interfaces': interfaces})
166
167 1 View Code Duplication
    @rest('v3/interfaces/switch/<dpid>/enable', methods=['POST'])
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
168 1
    @rest('v3/interfaces/<interface_enable_id>/enable', methods=['POST'])
169 1
    def enable_interface(self, interface_enable_id=None, dpid=None):
170
        """Administratively enable interfaces in the topology."""
171
        error_list = []  # List of interfaces that were not activated.
172
        msg_error = "Some interfaces couldn't be found and activated: "
173
        if dpid is None:
174
            dpid = ":".join(interface_enable_id.split(":")[:-1])
175
        try:
176
            switch = self.controller.switches[dpid]
177
        except KeyError as exc:
178
            return jsonify(f"Switch not found: {exc}"), 404
179
180
        if interface_enable_id:
181
            interface_number = int(interface_enable_id.split(":")[-1])
182
183
            try:
184
                switch.interfaces[interface_number].enable()
185
            except KeyError as exc:
186
                error_list.append(f"Switch {dpid} Interface {exc}")
187
        else:
188
            for interface in switch.interfaces.values():
189
                interface.enable()
190
        if not error_list:
191
            return jsonify("Operation successful"), 200
192
        return jsonify({msg_error:
193
                        error_list}), 409
194
195 1 View Code Duplication
    @rest('v3/interfaces/switch/<dpid>/disable', methods=['POST'])
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
196 1
    @rest('v3/interfaces/<interface_disable_id>/disable', methods=['POST'])
197 1
    def disable_interface(self, interface_disable_id=None, dpid=None):
198
        """Administratively disable interfaces in the topology."""
199
        error_list = []  # List of interfaces that were not deactivated.
200
        msg_error = "Some interfaces couldn't be found and deactivated: "
201
        if dpid is None:
202
            dpid = ":".join(interface_disable_id.split(":")[:-1])
203
        try:
204
            switch = self.controller.switches[dpid]
205
        except KeyError as exc:
206
            return jsonify(f"Switch not found: {exc}"), 404
207
208
        if interface_disable_id:
209
            interface_number = int(interface_disable_id.split(":")[-1])
210
211
            try:
212
                switch.interfaces[interface_number].disable()
213
            except KeyError as exc:
214
                error_list.append(f"Switch {dpid} Interface {exc}")
215
        else:
216
            for interface in switch.interfaces.values():
217
                interface.disable()
218
        if not error_list:
219
            return jsonify("Operation successful"), 200
220
        return jsonify({msg_error:
221
                        error_list}), 409
222
223 1
    @rest('v3/interfaces/<interface_id>/metadata')
224
    def get_interface_metadata(self, interface_id):
225
        """Get metadata from an interface."""
226
        switch_id = ":".join(interface_id.split(":")[:-1])
227
        interface_number = int(interface_id.split(":")[-1])
228
        try:
229
            switch = self.controller.switches[switch_id]
230
        except KeyError:
231
            return jsonify("Switch not found"), 404
232
233
        try:
234
            interface = switch.interfaces[interface_number]
235
        except KeyError:
236
            return jsonify("Interface not found"), 404
237
238
        return jsonify({"metadata": interface.metadata}), 200
239
240 1
    @rest('v3/interfaces/<interface_id>/metadata', methods=['POST'])
241
    def add_interface_metadata(self, interface_id):
242
        """Add metadata to an interface."""
243
        metadata = request.get_json()
244
245
        switch_id = ":".join(interface_id.split(":")[:-1])
246
        interface_number = int(interface_id.split(":")[-1])
247
        try:
248
            switch = self.controller.switches[switch_id]
249
        except KeyError:
250
            return jsonify("Switch not found"), 404
251
252
        try:
253
            interface = switch.interfaces[interface_number]
254
        except KeyError:
255
            return jsonify("Interface not found"), 404
256
257
        interface.extend_metadata(metadata)
258
        self.notify_metadata_changes(interface, 'added')
259
        return jsonify("Operation successful"), 201
260
261 1
    @rest('v3/interfaces/<interface_id>/metadata/<key>', methods=['DELETE'])
262
    def delete_interface_metadata(self, interface_id, key):
263
        """Delete metadata from an interface."""
264
        switch_id = ":".join(interface_id.split(":")[:-1])
265
        interface_number = int(interface_id.split(":")[-1])
266
267
        try:
268
            switch = self.controller.switches[switch_id]
269
        except KeyError:
270
            return jsonify("Switch not found"), 404
271
272
        try:
273
            interface = switch.interfaces[interface_number]
274
        except KeyError:
275
            return jsonify("Interface not found"), 404
276
277
        if interface.remove_metadata(key) is False:
278
            return jsonify("Metadata not found"), 404
279
280
        self.notify_metadata_changes(interface, 'removed')
281
        return jsonify("Operation successful"), 200
282
283
    # Link related methods
284 1
    @rest('v3/links')
285
    def get_links(self):
286
        """Return a json with all the links in the topology.
287
288
        Links are connections between interfaces.
289
        """
290
        return jsonify(self._get_links_dict()), 200
291
292 1
    @rest('v3/links/<link_id>/enable', methods=['POST'])
293
    def enable_link(self, link_id):
294
        """Administratively enable a link in the topology."""
295
        try:
296
            self.links[link_id].enable()
297
        except KeyError:
298
            return jsonify("Link not found"), 404
299
300
        return jsonify("Operation successful"), 201
301
302 1
    @rest('v3/links/<link_id>/disable', methods=['POST'])
303
    def disable_link(self, link_id):
304
        """Administratively disable a link in the topology."""
305
        try:
306
            self.links[link_id].disable()
307
        except KeyError:
308
            return jsonify("Link not found"), 404
309
310
        return jsonify("Operation successful"), 201
311
312 1
    @rest('v3/links/<link_id>/metadata')
313
    def get_link_metadata(self, link_id):
314
        """Get metadata from a link."""
315
        try:
316
            return jsonify({"metadata": self.links[link_id].metadata}), 200
317
        except KeyError:
318
            return jsonify("Link not found"), 404
319
320 1
    @rest('v3/links/<link_id>/metadata', methods=['POST'])
321
    def add_link_metadata(self, link_id):
322
        """Add metadata to a link."""
323
        metadata = request.get_json()
324
        try:
325
            link = self.links[link_id]
326
        except KeyError:
327
            return jsonify("Link not found"), 404
328
329
        link.extend_metadata(metadata)
330
        self.notify_metadata_changes(link, 'added')
331
        return jsonify("Operation successful"), 201
332
333 1
    @rest('v3/links/<link_id>/metadata/<key>', methods=['DELETE'])
334
    def delete_link_metadata(self, link_id, key):
335
        """Delete metadata from a link."""
336
        try:
337
            link = self.links[link_id]
338
        except KeyError:
339
            return jsonify("Link not found"), 404
340
341
        if link.remove_metadata(key) is False:
342
            return jsonify("Metadata not found"), 404
343
344
        self.notify_metadata_changes(link, 'removed')
345
        return jsonify("Operation successful"), 200
346
347 1
    @listen_to('.*.switch.(new|reconnected)')
348
    def handle_new_switch(self, event):
349
        """Create a new Device on the Topology.
350
351
        Handle the event of a new created switch and update the topology with
352
        this new device.
353
        """
354 1
        switch = event.content['switch']
355 1
        switch.activate()
356 1
        log.debug('Switch %s added to the Topology.', switch.id)
357 1
        self.notify_topology_update()
358 1
        self.update_instance_metadata(switch)
359
360 1
    @listen_to('.*.connection.lost')
361
    def handle_connection_lost(self, event):
362
        """Remove a Device from the topology.
363
364
        Remove the disconnected Device and every link that has one of its
365
        interfaces.
366
        """
367 1
        switch = event.content['source'].switch
368 1
        if switch:
369 1
            switch.deactivate()
370 1
            log.debug('Switch %s removed from the Topology.', switch.id)
371 1
            self.notify_topology_update()
372
373 1
    def handle_interface_up(self, event):
374
        """Update the topology based on a Port Modify event.
375
376
        The event notifies that an interface was changed to 'up'.
377
        """
378 1
        interface = event.content['interface']
379 1
        interface.activate()
380 1
        self.notify_topology_update()
381 1
        self.update_instance_metadata(interface)
382
383 1
    @listen_to('.*.switch.interface.created')
384
    def handle_interface_created(self, event):
385
        """Update the topology based on a Port Create event."""
386 1
        self.handle_interface_up(event)
387
388 1
    def handle_interface_down(self, event):
389
        """Update the topology based on a Port Modify event.
390
391
        The event notifies that an interface was changed to 'down'.
392
        """
393 1
        interface = event.content['interface']
394 1
        interface.deactivate()
395 1
        self.handle_interface_link_down(event)
396 1
        self.notify_topology_update()
397
398 1
    @listen_to('.*.switch.interface.deleted')
399
    def handle_interface_deleted(self, event):
400
        """Update the topology based on a Port Delete event."""
401 1
        self.handle_interface_down(event)
402
403 1
    @listen_to('.*.switch.interface.link_up')
404
    def handle_interface_link_up(self, event):
405
        """Update the topology based on a Port Modify event.
406
407
        The event notifies that an interface's link was changed to 'up'.
408
        """
409 1
        interface = event.content['interface']
410 1
        link = self._get_link_from_interface(interface)
411 1
        if link and not link.is_active():
412 1
            link.activate()
413 1
            self.notify_topology_update()
414 1
            self.update_instance_metadata(interface.link)
415 1
            self.notify_link_status_change(link)
416
417 1
    @listen_to('.*.switch.interface.link_down')
418
    def handle_interface_link_down(self, event):
419
        """Update the topology based on a Port Modify event.
420
421
        The event notifies that an interface's link was changed to 'down'.
422
        """
423 1
        interface = event.content['interface']
424 1
        link = self._get_link_from_interface(interface)
425 1
        if link and link.is_active():
426 1
            link.deactivate()
427 1
            self.notify_topology_update()
428 1
            self.notify_link_status_change(link)
429
430 1
    @listen_to('.*.interface.is.nni')
431
    def add_links(self, event):
432
        """Update the topology with links related to the NNI interfaces."""
433 1
        interface_a = event.content['interface_a']
434 1
        interface_b = event.content['interface_b']
435
436 1
        link = self._get_link_or_create(interface_a, interface_b)
437 1
        interface_a.update_link(link)
438 1
        interface_b.update_link(link)
439
440 1
        interface_a.nni = True
441 1
        interface_b.nni = True
442
443 1
        self.notify_topology_update()
444
445
    # def add_host(self, event):
446
    #    """Update the topology with a new Host."""
447
448
    #    interface = event.content['port']
449
    #    mac = event.content['reachable_mac']
450
451
    #    host = Host(mac)
452
    #    link = self.topology.get_link(interface.id)
453
    #    if link is not None:
454
    #        return
455
456
    #    self.topology.add_link(interface.id, host.id)
457
    #    self.topology.add_device(host)
458
459
    #    if settings.DISPLAY_FULL_DUPLEX_LINKS:
460
    #        self.topology.add_link(host.id, interface.id)
461
462 1
    def notify_topology_update(self):
463
        """Send an event to notify about updates on the topology."""
464 1
        name = 'kytos/topology.updated'
465 1
        event = KytosEvent(name=name, content={'topology':
466
                                               self._get_topology()})
467 1
        self.controller.buffers.app.put(event)
468
469 1
    def notify_link_status_change(self, link):
470
        """Send an event to notify about a status change on a link."""
471 1
        name = 'kytos/topology.'
472 1
        if link.is_active():
473 1
            status = 'link_up'
474
        else:
475
            status = 'link_down'
476 1
        event = KytosEvent(name=name+status, content={'link': link})
477 1
        self.controller.buffers.app.put(event)
478
479 1
    def notify_metadata_changes(self, obj, action):
480
        """Send an event to notify about metadata changes."""
481 1
        if isinstance(obj, Switch):
482 1
            entity = 'switch'
483 1
            entities = 'switches'
484
        elif isinstance(obj, Interface):
485
            entity = 'interface'
486
            entities = 'interfaces'
487
        elif isinstance(obj, Link):
488
            entity = 'link'
489
            entities = 'links'
490
491 1
        name = f'kytos/topology.{entities}.metadata.{action}'
492 1
        event = KytosEvent(name=name, content={entity: obj,
0 ignored issues
show
introduced by
The variable entity does not seem to be defined for all execution paths.
Loading history...
493
                                               'metadata': obj.metadata})
494 1
        self.controller.buffers.app.put(event)
495 1
        log.debug(f'Metadata from {obj.id} was {action}.')
496
497 1
    @listen_to('.*.switch.port.created')
498
    def notify_port_created(self, original_event):
499
        """Notify when a port is created."""
500 1
        name = 'kytos/topology.port.created'
501 1
        event = KytosEvent(name=name, content=original_event.content)
502 1
        self.controller.buffers.app.put(event)
503
504 1
    @listen_to('kytos/topology.*.metadata.*')
505
    def save_metadata_on_store(self, event):
506
        """Send to storehouse the data updated."""
507
        name = 'kytos.storehouse.update'
508
        if 'switch' in event.content:
509
            store = self.store_items.get('switches')
510
            obj = event.content.get('switch')
511
            namespace = 'kytos.topology.switches.metadata'
512
        elif 'interface' in event.content:
513
            store = self.store_items.get('interfaces')
514
            obj = event.content.get('interface')
515
            namespace = 'kytos.topology.iterfaces.metadata'
516
        elif 'link' in event.content:
517
            store = self.store_items.get('links')
518
            obj = event.content.get('link')
519
            namespace = 'kytos.topology.links.metadata'
520
521
        store.data[obj.id] = obj.metadata
0 ignored issues
show
introduced by
The variable store does not seem to be defined for all execution paths.
Loading history...
introduced by
The variable obj does not seem to be defined for all execution paths.
Loading history...
522
        content = {'namespace': namespace,
0 ignored issues
show
introduced by
The variable namespace does not seem to be defined for all execution paths.
Loading history...
523
                   'box_id': store.box_id,
524
                   'data': store.data,
525
                   'callback': self.update_instance}
526
527
        event = KytosEvent(name=name, content=content)
528
        self.controller.buffers.app.put(event)
529
530 1
    @staticmethod
531
    def update_instance(event, _data, error):
532
        """Display in Kytos console if the data was updated."""
533
        entities = event.content.get('namespace', '').split('.')[-2]
534
        if error:
535
            log.error(f'Error trying to update storehouse {entities}.')
536
        else:
537
            log.debug(f'Storehouse update to entities: {entities}.')
538
539 1
    def verify_storehouse(self, entities):
540
        """Request a list of box saved by specific entity."""
541 1
        name = 'kytos.storehouse.list'
542 1
        content = {'namespace': f'kytos.topology.{entities}.metadata',
543
                   'callback': self.request_retrieve_entities}
544 1
        event = KytosEvent(name=name, content=content)
545 1
        self.controller.buffers.app.put(event)
546 1
        log.info(f'verify data in storehouse for {entities}.')
547
548 1
    def request_retrieve_entities(self, event, data, _error):
549
        """Create a box or retrieve an existent box from storehouse."""
550
        msg = ''
551
        content = {'namespace': event.content.get('namespace'),
552
                   'callback': self.load_from_store,
553
                   'data': {}}
554
555
        if not data:
556
            name = 'kytos.storehouse.create'
557
            msg = 'Create new box in storehouse'
558
        else:
559
            name = 'kytos.storehouse.retrieve'
560
            content['box_id'] = data[0]
561
            msg = 'Retrieve data from storeohouse.'
562
563
        event = KytosEvent(name=name, content=content)
564
        self.controller.buffers.app.put(event)
565
        log.debug(msg)
566
567 1
    def load_from_store(self, event, box, error):
568
        """Save the data retrived from storehouse."""
569
        entities = event.content.get('namespace', '').split('.')[-2]
570
        if error:
571
            log.error('Error while get a box from storehouse.')
572
        else:
573
            self.store_items[entities] = box
574
            log.debug('Data updated')
575
576 1
    def update_instance_metadata(self, obj):
577
        """Update object instance with saved metadata."""
578
        metadata = None
579
        if isinstance(obj, Interface):
580
            all_metadata = self.store_items.get('interfaces', None)
581
            if all_metadata:
582
                metadata = all_metadata.data.get(obj.id)
583
        elif isinstance(obj, Switch):
584
            all_metadata = self.store_items.get('switches', None)
585
            if all_metadata:
586
                metadata = all_metadata.data.get(obj.id)
587
        elif isinstance(obj, Link):
588
            all_metadata = self.store_items.get('links', None)
589
            if all_metadata:
590
                metadata = all_metadata.data.get(obj.id)
591
592
        if metadata:
593
            obj.extend_metadata(metadata)
594
            log.debug(f'Metadata to {obj.id} was updated')
595