Test Failed
Pull Request — master (#80)
by
unknown
03:21
created

build.main   F

Complexity

Total Complexity 104

Size/Duplication

Total Lines 592
Duplicated Lines 9.97 %

Test Coverage

Coverage 19.81%

Importance

Changes 0
Metric Value
wmc 104
eloc 397
dl 59
loc 592
rs 2
c 0
b 0
f 0
ccs 65
cts 328
cp 0.1981

48 Methods

Rating   Name   Duplication   Size   Complexity  
A Main.notify_port_created() 0 6 1
A Main.disable_switch() 0 8 2
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.enable_switch() 0 8 2
A Main.disable_link() 0 9 2
B Main.enable_interface() 29 29 6
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.add_interface_metadata() 0 20 3
A Main.delete_interface_metadata() 0 21 4
B Main.update_instance_metadata() 0 19 8
A Main.get_switches() 0 4 1
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.shutdown() 0 3 1
A Main.notify_topology_update() 0 6 1
A Main.enable_link() 0 9 2
A Main.setup() 0 8 1
A Main.handle_new_switch() 0 12 1
A Main.execute() 0 2 1
A Main.get_switch_metadata() 0 8 2
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() 30 30 6
A Main.get_topology() 0 7 1
A Main.save_metadata_on_store() 0 25 4
A Main.handle_interface_link_down() 0 12 3
A Main._get_links_dict() 0 4 1
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._get_link_or_create() 0 9 3
A Main.add_link_metadata() 0 12 2
A Main._get_link_from_interface() 0 6 3
A Main.notify_metadata_changes() 0 17 4
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_link_metadata() 0 7 2
A Main._get_topology() 0 3 1

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