1# Copyright 2015 Spotify AB. All rights reserved.
2#
3# The contents of this file are licensed under the Apache License, Version 2.0
4# (the "License"); you may not use this file except in compliance with the
5# License. You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12# License for the specific language governing permissions and limitations under
13# the License.
14
15import sys
16
17from netmiko import ConnectHandler, NetMikoTimeoutException
18
19# local modules
20import napalm.base.exceptions
21import napalm.base.helpers
22from napalm.base import constants as c
23from napalm.base import validate
24from napalm.base.exceptions import ConnectionException
25
26
27class NetworkDriver(object):
28    def __init__(self, hostname, username, password, timeout=60, optional_args=None):
29        """
30        This is the base class you have to inherit from when writing your own Network Driver to
31        manage any device. You will, in addition, have to override all the methods specified on
32        this class. Make sure you follow the guidelines for every method and that you return the
33        correct data.
34
35        :param hostname: (str) IP or FQDN of the device you want to connect to.
36        :param username: (str) Username you want to use
37        :param password: (str) Password
38        :param timeout: (int) Time in seconds to wait for the device to respond.
39        :param optional_args: (dict) Pass additional arguments to underlying driver
40        :return:
41        """
42        raise NotImplementedError
43
44    def __enter__(self):
45        try:
46            self.open()
47            return self
48        except:  # noqa: E722
49            # Swallow exception if __exit__ returns a True value
50            if self.__exit__(*sys.exc_info()):
51                pass
52            else:
53                raise
54
55    def __exit__(self, exc_type, exc_value, exc_traceback):
56        self.close()
57        if exc_type is not None and (
58            exc_type.__name__ not in dir(napalm.base.exceptions)
59            and exc_type.__name__ not in __builtins__.keys()
60        ):
61            epilog = (
62                "NAPALM didn't catch this exception. Please, fill a bugfix on "
63                "https://github.com/napalm-automation/napalm/issues\n"
64                "Don't forget to include this traceback."
65            )
66            print(epilog)
67            return False
68
69    def __del__(self):
70        """
71        This method is used to cleanup when the program is terminated suddenly.
72        We need to make sure the connection is closed properly and the configuration DB
73        is released (unlocked).
74        """
75        try:
76            if self.is_alive()["is_alive"]:
77                self.close()
78        except Exception:
79            pass
80
81    def _netmiko_open(self, device_type, netmiko_optional_args=None):
82        """Standardized method of creating a Netmiko connection using napalm attributes."""
83        if netmiko_optional_args is None:
84            netmiko_optional_args = {}
85        try:
86            self._netmiko_device = ConnectHandler(
87                device_type=device_type,
88                host=self.hostname,
89                username=self.username,
90                password=self.password,
91                timeout=self.timeout,
92                **netmiko_optional_args
93            )
94        except NetMikoTimeoutException:
95            raise ConnectionException("Cannot connect to {}".format(self.hostname))
96
97        # Disable enable mode if force_no_enable is true (for NAPALM drivers
98        # that support force_no_enable)
99        try:
100            if not self.force_no_enable:
101                self._netmiko_device.enable()
102        except AttributeError:
103            self._netmiko_device.enable()
104
105        return self._netmiko_device
106
107    def _netmiko_close(self):
108        """Standardized method of closing a Netmiko connection."""
109        if getattr(self, "_netmiko_device", None):
110            self._netmiko_device.disconnect()
111            self._netmiko_device = None
112        self.device = None
113
114    def open(self):
115        """
116        Opens a connection to the device.
117        """
118        raise NotImplementedError
119
120    def close(self):
121        """
122        Closes the connection to the device.
123        """
124        raise NotImplementedError
125
126    def is_alive(self):
127        """
128        Returns a flag with the connection state.
129        Depends on the nature of API used by each driver.
130        The state does not reflect only on the connection status (when SSH), it must also take into
131        consideration other parameters, e.g.: NETCONF session might not be usable, althought the
132        underlying SSH session is still open etc.
133        """
134        raise NotImplementedError
135
136    def pre_connection_tests(self):
137        """
138        This is a helper function used by the cli tool cl_napalm_show_tech. Drivers
139        can override this method to do some tests, show information, enable debugging, etc.
140        before a connection with the device is attempted.
141        """
142        raise NotImplementedError
143
144    def connection_tests(self):
145        """
146        This is a helper function used by the cli tool cl_napalm_show_tech. Drivers
147        can override this method to do some tests, show information, enable debugging, etc.
148        before a connection with the device has been successful.
149        """
150        raise NotImplementedError
151
152    def post_connection_tests(self):
153        """
154        This is a helper function used by the cli tool cl_napalm_show_tech. Drivers
155        can override this method to do some tests, show information, enable debugging, etc.
156        after a connection with the device has been closed successfully.
157        """
158        raise NotImplementedError
159
160    def load_template(
161        self, template_name, template_source=None, template_path=None, **template_vars
162    ):
163        """
164        Will load a templated configuration on the device.
165
166        :param cls: Instance of the driver class.
167        :param template_name: Identifies the template name.
168        :param template_source: Custom config template rendered and loaded on device
169        :type template_source: optional
170        :param template_path: Absolute path to directory for the configuration templates
171        :type template_path: optional
172        :param template_vars: Dictionary with arguments to be used when the template is rendered.
173        :raise DriverTemplateNotImplemented: No template defined for the device type.
174        :raise TemplateNotImplemented: The template specified in template_name does not exist in \
175        the default path or in the custom path if any specified using parameter `template_path`.
176        :raise TemplateRenderException: The template could not be rendered. Either the template \
177        source does not have the right format, either the arguments in `template_vars` are not \
178        properly specified.
179        """
180        return napalm.base.helpers.load_template(
181            self,
182            template_name,
183            template_source=template_source,
184            template_path=template_path,
185            **template_vars
186        )
187
188    def load_replace_candidate(self, filename=None, config=None):
189        """
190        Populates the candidate configuration. You can populate it from a file or from a string.
191        If you send both a filename and a string containing the configuration, the file takes
192        precedence.
193
194        If you use this method the existing configuration will be replaced entirely by the
195        candidate configuration once you commit the changes. This method will not change the
196        configuration by itself.
197
198        :param filename: Path to the file containing the desired configuration. By default is None.
199        :param config: String containing the desired configuration.
200        :raise ReplaceConfigException: If there is an error on the configuration sent.
201        """
202        raise NotImplementedError
203
204    def load_merge_candidate(self, filename=None, config=None):
205        """
206        Populates the candidate configuration. You can populate it from a file or from a string.
207        If you send both a filename and a string containing the configuration, the file takes
208        precedence.
209
210        If you use this method the existing configuration will be merged with the candidate
211        configuration once you commit the changes. This method will not change the configuration
212        by itself.
213
214        :param filename: Path to the file containing the desired configuration. By default is None.
215        :param config: String containing the desired configuration.
216        :raise MergeConfigException: If there is an error on the configuration sent.
217        """
218        raise NotImplementedError
219
220    def compare_config(self):
221        """
222        :return: A string showing the difference between the running configuration and the \
223        candidate configuration. The running_config is loaded automatically just before doing the \
224        comparison so there is no need for you to do it.
225        """
226        raise NotImplementedError
227
228    def commit_config(self, message="", revert_in=None):
229        """
230        Commits the changes requested by the method load_replace_candidate or load_merge_candidate.
231
232        NAPALM drivers that support 'commit confirm' should cause self.has_pending_commit
233        to return True when a 'commit confirm' is in progress.
234
235        Implementations should raise an exception if commit_config is called multiple times while a
236        'commit confirm' is pending.
237
238        :param message: Optional - configuration session commit message
239        :type message: str
240        :param revert_in: Optional - number of seconds before the configuration will be reverted
241        :type revert_in: int|None
242        """
243        raise NotImplementedError
244
245    def confirm_commit(self):
246        """
247        Confirm the changes requested via commit_config when commit_confirm=True.
248
249        Should cause self.has_pending_commit to return False when done.
250        """
251        raise NotImplementedError
252
253    def has_pending_commit(self):
254        """
255        :return Boolean indicating if a commit_config that needs confirmed is in process.
256        """
257        raise NotImplementedError
258
259    def discard_config(self):
260        """
261        Discards the configuration loaded into the candidate.
262        """
263        raise NotImplementedError
264
265    def rollback(self):
266        """
267        If changes were made, revert changes to the original state.
268
269        If commit confirm is in process, rollback changes and clear has_pending_commit.
270        """
271        raise NotImplementedError
272
273    def get_facts(self):
274        """
275        Returns a dictionary containing the following information:
276         * uptime - Uptime of the device in seconds.
277         * vendor - Manufacturer of the device.
278         * model - Device model.
279         * hostname - Hostname of the device
280         * fqdn - Fqdn of the device
281         * os_version - String with the OS version running on the device.
282         * serial_number - Serial number of the device
283         * interface_list - List of the interfaces of the device
284
285        Example::
286
287            {
288            'uptime': 151005.57332897186,
289            'vendor': u'Arista',
290            'os_version': u'4.14.3-2329074.gaatlantarel',
291            'serial_number': u'SN0123A34AS',
292            'model': u'vEOS',
293            'hostname': u'eos-router',
294            'fqdn': u'eos-router',
295            'interface_list': [u'Ethernet2', u'Management1', u'Ethernet1', u'Ethernet3']
296            }
297
298        """
299        raise NotImplementedError
300
301    def get_interfaces(self):
302        """
303        Returns a dictionary of dictionaries. The keys for the first dictionary will be the \
304        interfaces in the devices. The inner dictionary will containing the following data for \
305        each interface:
306
307         * is_up (True/False)
308         * is_enabled (True/False)
309         * description (string)
310         * last_flapped (float in seconds)
311         * speed (int in Mbit)
312         * MTU (in Bytes)
313         * mac_address (string)
314
315        Example::
316
317            {
318            u'Management1':
319                {
320                'is_up': False,
321                'is_enabled': False,
322                'description': '',
323                'last_flapped': -1.0,
324                'speed': 1000,
325                'mtu': 1500,
326                'mac_address': 'FA:16:3E:57:33:61',
327                },
328            u'Ethernet1':
329                {
330                'is_up': True,
331                'is_enabled': True,
332                'description': 'foo',
333                'last_flapped': 1429978575.1554043,
334                'speed': 1000,
335                'mtu': 1500,
336                'mac_address': 'FA:16:3E:57:33:62',
337                },
338            u'Ethernet2':
339                {
340                'is_up': True,
341                'is_enabled': True,
342                'description': 'bla',
343                'last_flapped': 1429978575.1555667,
344                'speed': 1000,
345                'mtu': 1500,
346                'mac_address': 'FA:16:3E:57:33:63',
347                },
348            u'Ethernet3':
349                {
350                'is_up': False,
351                'is_enabled': True,
352                'description': 'bar',
353                'last_flapped': -1.0,
354                'speed': 1000,
355                'mtu': 1500,
356                'mac_address': 'FA:16:3E:57:33:64',
357                }
358            }
359        """
360        raise NotImplementedError
361
362    def get_lldp_neighbors(self):
363        """
364        Returns a dictionary where the keys are local ports and the value is a list of \
365        dictionaries with the following information:
366            * hostname
367            * port
368
369        Example::
370
371            {
372            u'Ethernet2':
373                [
374                    {
375                    'hostname': u'junos-unittest',
376                    'port': u'520',
377                    }
378                ],
379            u'Ethernet3':
380                [
381                    {
382                    'hostname': u'junos-unittest',
383                    'port': u'522',
384                    }
385                ],
386            u'Ethernet1':
387                [
388                    {
389                    'hostname': u'junos-unittest',
390                    'port': u'519',
391                    },
392                    {
393                    'hostname': u'ios-xrv-unittest',
394                    'port': u'Gi0/0/0/0',
395                    }
396                ],
397            u'Management1':
398                [
399                    {
400                    'hostname': u'junos-unittest',
401                    'port': u'508',
402                    }
403                ]
404            }
405        """
406        raise NotImplementedError
407
408    def get_bgp_neighbors(self):
409        """
410        Returns a dictionary of dictionaries. The keys for the first dictionary will be the vrf
411        (global if no vrf). The inner dictionary will contain the following data for each vrf:
412
413          * router_id
414          * peers - another dictionary of dictionaries. Outer keys are the IPs of the neighbors. \
415            The inner keys are:
416             * local_as (int)
417             * remote_as (int)
418             * remote_id - peer router id
419             * is_up (True/False)
420             * is_enabled (True/False)
421             * description (string)
422             * uptime (int in seconds)
423             * address_family (dictionary) - A dictionary of address families available for the \
424               neighbor. So far it can be 'ipv4' or 'ipv6'
425                * received_prefixes (int)
426                * accepted_prefixes (int)
427                * sent_prefixes (int)
428
429            Note, if is_up is False and uptime has a positive value then this indicates the
430            uptime of the last active BGP session.
431
432            Example::
433
434                {
435                  "global": {
436                    "router_id": "10.0.1.1",
437                    "peers": {
438                      "10.0.0.2": {
439                        "local_as": 65000,
440                        "remote_as": 65000,
441                        "remote_id": "10.0.1.2",
442                        "is_up": True,
443                        "is_enabled": True,
444                        "description": "internal-2",
445                        "uptime": 4838400,
446                        "address_family": {
447                          "ipv4": {
448                            "sent_prefixes": 637213,
449                            "accepted_prefixes": 3142,
450                            "received_prefixes": 3142
451                          },
452                          "ipv6": {
453                            "sent_prefixes": 36714,
454                            "accepted_prefixes": 148,
455                            "received_prefixes": 148
456                          }
457                        }
458                      }
459                    }
460                  }
461                }
462        """
463        raise NotImplementedError
464
465    def get_environment(self):
466        """
467        Returns a dictionary where:
468
469            * fans is a dictionary of dictionaries where the key is the location and the values:
470                 * status (True/False) - True if it's ok, false if it's broken
471            * temperature is a dict of dictionaries where the key is the location and the values:
472                 * temperature (float) - Temperature in celsius the sensor is reporting.
473                 * is_alert (True/False) - True if the temperature is above the alert threshold
474                 * is_critical (True/False) - True if the temp is above the critical threshold
475            * power is a dictionary of dictionaries where the key is the PSU id and the values:
476                 * status (True/False) - True if it's ok, false if it's broken
477                 * capacity (float) - Capacity in W that the power supply can support
478                 * output (float) - Watts drawn by the system
479            * cpu is a dictionary of dictionaries where the key is the ID and the values
480                 * %usage
481            * memory is a dictionary with:
482                 * available_ram (int) - Total amount of RAM installed in the device
483                 * used_ram (int) - RAM in use in the device
484        """
485        raise NotImplementedError
486
487    def get_interfaces_counters(self):
488        """
489        Returns a dictionary of dictionaries where the first key is an interface name and the
490        inner dictionary contains the following keys:
491
492            * tx_errors (int)
493            * rx_errors (int)
494            * tx_discards (int)
495            * rx_discards (int)
496            * tx_octets (int)
497            * rx_octets (int)
498            * tx_unicast_packets (int)
499            * rx_unicast_packets (int)
500            * tx_multicast_packets (int)
501            * rx_multicast_packets (int)
502            * tx_broadcast_packets (int)
503            * rx_broadcast_packets (int)
504
505        Example::
506
507            {
508                u'Ethernet2': {
509                    'tx_multicast_packets': 699,
510                    'tx_discards': 0,
511                    'tx_octets': 88577,
512                    'tx_errors': 0,
513                    'rx_octets': 0,
514                    'tx_unicast_packets': 0,
515                    'rx_errors': 0,
516                    'tx_broadcast_packets': 0,
517                    'rx_multicast_packets': 0,
518                    'rx_broadcast_packets': 0,
519                    'rx_discards': 0,
520                    'rx_unicast_packets': 0
521                },
522                u'Management1': {
523                     'tx_multicast_packets': 0,
524                     'tx_discards': 0,
525                     'tx_octets': 159159,
526                     'tx_errors': 0,
527                     'rx_octets': 167644,
528                     'tx_unicast_packets': 1241,
529                     'rx_errors': 0,
530                     'tx_broadcast_packets': 0,
531                     'rx_multicast_packets': 0,
532                     'rx_broadcast_packets': 80,
533                     'rx_discards': 0,
534                     'rx_unicast_packets': 0
535                },
536                u'Ethernet1': {
537                     'tx_multicast_packets': 293,
538                     'tx_discards': 0,
539                     'tx_octets': 38639,
540                     'tx_errors': 0,
541                     'rx_octets': 0,
542                     'tx_unicast_packets': 0,
543                     'rx_errors': 0,
544                     'tx_broadcast_packets': 0,
545                     'rx_multicast_packets': 0,
546                     'rx_broadcast_packets': 0,
547                     'rx_discards': 0,
548                     'rx_unicast_packets': 0
549                }
550            }
551        """
552        raise NotImplementedError
553
554    def get_lldp_neighbors_detail(self, interface=""):
555        """
556        Returns a detailed view of the LLDP neighbors as a dictionary
557        containing lists of dictionaries for each interface.
558
559        Empty entries are returned as an empty string (e.g. '') or list where applicable.
560
561        Inner dictionaries contain fields:
562
563            * parent_interface (string)
564            * remote_port (string)
565            * remote_port_description (string)
566            * remote_chassis_id (string)
567            * remote_system_name (string)
568            * remote_system_description (string)
569            * remote_system_capab (list) with any of these values
570                * other
571                * repeater
572                * bridge
573                * wlan-access-point
574                * router
575                * telephone
576                * docsis-cable-device
577                * station
578            * remote_system_enabled_capab (list)
579
580        Example::
581
582            {
583                'TenGigE0/0/0/8': [
584                    {
585                        'parent_interface': u'Bundle-Ether8',
586                        'remote_chassis_id': u'8c60.4f69.e96c',
587                        'remote_system_name': u'switch',
588                        'remote_port': u'Eth2/2/1',
589                        'remote_port_description': u'Ethernet2/2/1',
590                        'remote_system_description': u'''Cisco Nexus Operating System (NX-OS)
591                              Software 7.1(0)N1(1a)
592                              TAC support: http://www.cisco.com/tac
593                              Copyright (c) 2002-2015, Cisco Systems, Inc. All rights reserved.''',
594                        'remote_system_capab': ['bridge', 'repeater'],
595                        'remote_system_enable_capab': ['bridge']
596                    }
597                ]
598            }
599        """
600        raise NotImplementedError
601
602    def get_bgp_config(self, group="", neighbor=""):
603        """
604        Returns a dictionary containing the BGP configuration.
605        Can return either the whole config, either the config only for a group or neighbor.
606
607        :param group: Returns the configuration of a specific BGP group.
608        :param neighbor: Returns the configuration of a specific BGP neighbor.
609
610        Main dictionary keys represent the group name and the values represent a dictionary having
611        the keys below. Neighbors which aren't members of a group will be stored in a key named "_":
612
613            * type (string)
614            * description (string)
615            * apply_groups (string list)
616            * multihop_ttl (int)
617            * multipath (True/False)
618            * local_address (string)
619            * local_as (int)
620            * remote_as (int)
621            * import_policy (string)
622            * export_policy (string)
623            * remove_private_as (True/False)
624            * prefix_limit (dictionary)
625            * neighbors (dictionary)
626
627        Neighbors is a dictionary of dictionaries with the following keys:
628
629            * description (string)
630            * import_policy (string)
631            * export_policy (string)
632            * local_address (string)
633            * local_as (int)
634            * remote_as (int)
635            * authentication_key (string)
636            * prefix_limit (dictionary)
637            * route_reflector_client (True/False)
638            * nhs (True/False)
639
640        The inner dictionary prefix_limit has the same structure for both layers::
641
642            {
643                [FAMILY_NAME]: {
644                    [FAMILY_TYPE]: {
645                        'limit': [LIMIT],
646                        ... other options
647                    }
648                }
649            }
650
651        Example::
652
653            {
654                'PEERS-GROUP-NAME':{
655                    'type'              : u'external',
656                    'description'       : u'Here we should have a nice description',
657                    'apply_groups'      : [u'BGP-PREFIX-LIMIT'],
658                    'import_policy'     : u'PUBLIC-PEER-IN',
659                    'export_policy'     : u'PUBLIC-PEER-OUT',
660                    'remove_private_as' : True,
661                    'multipath'         : True,
662                    'multihop_ttl'      : 30,
663                    'neighbors'         : {
664                        '192.168.0.1': {
665                            'description'   : 'Facebook [CDN]',
666                            'prefix_limit'  : {
667                                'inet': {
668                                    'unicast': {
669                                        'limit': 100,
670                                        'teardown': {
671                                            'threshold' : 95,
672                                            'timeout'   : 5
673                                        }
674                                    }
675                                }
676                            }
677                            'remote_as'             : 32934,
678                            'route_reflector_client': False,
679                            'nhs'                   : True
680                        },
681                        '172.17.17.1': {
682                            'description'   : 'Twitter [CDN]',
683                            'prefix_limit'  : {
684                                'inet': {
685                                    'unicast': {
686                                        'limit': 500,
687                                        'no-validate': 'IMPORT-FLOW-ROUTES'
688                                    }
689                                }
690                            }
691                            'remote_as'               : 13414
692                            'route_reflector_client': False,
693                            'nhs'                   : False
694                        }
695                    }
696                }
697            }
698        """
699        raise NotImplementedError
700
701    def cli(self, commands):
702
703        """
704        Will execute a list of commands and return the output in a dictionary format.
705
706        Example::
707
708            {
709                u'show version and haiku':  u'''Hostname: re0.edge01.arn01
710                                                Model: mx480
711                                                Junos: 13.3R6.5
712
713                                                        Help me, Obi-Wan
714                                                        I just saw Episode Two
715                                                        You're my only hope
716                                            ''',
717                u'show chassis fan'     :   u'''
718                    Item               Status  RPM     Measurement
719                    Top Rear Fan       OK      3840    Spinning at intermediate-speed
720                    Bottom Rear Fan    OK      3840    Spinning at intermediate-speed
721                    Top Middle Fan     OK      3900    Spinning at intermediate-speed
722                    Bottom Middle Fan  OK      3840    Spinning at intermediate-speed
723                    Top Front Fan      OK      3810    Spinning at intermediate-speed
724                    Bottom Front Fan   OK      3840    Spinning at intermediate-speed'''
725            }
726        """
727        raise NotImplementedError
728
729    def get_bgp_neighbors_detail(self, neighbor_address=""):
730
731        """
732        Returns a detailed view of the BGP neighbors as a dictionary of lists.
733
734        :param neighbor_address: Retuns the statistics for a spcific BGP neighbor.
735
736        Returns a dictionary of dictionaries. The keys for the first dictionary will be the vrf
737        (global if no vrf).
738        The keys of the inner dictionary represent the AS number of the neighbors.
739        Leaf dictionaries contain the following fields:
740
741            * up (True/False)
742            * local_as (int)
743            * remote_as (int)
744            * router_id (string)
745            * local_address (string)
746            * routing_table (string)
747            * local_address_configured (True/False)
748            * local_port (int)
749            * remote_address (string)
750            * remote_port (int)
751            * multihop (True/False)
752            * multipath (True/False)
753            * remove_private_as (True/False)
754            * import_policy (string)
755            * export_policy (string)
756            * input_messages (int)
757            * output_messages (int)
758            * input_updates (int)
759            * output_updates (int)
760            * messages_queued_out (int)
761            * connection_state (string)
762            * previous_connection_state (string)
763            * last_event (string)
764            * suppress_4byte_as (True/False)
765            * local_as_prepend (True/False)
766            * holdtime (int)
767            * configured_holdtime (int)
768            * keepalive (int)
769            * configured_keepalive (int)
770            * active_prefix_count (int)
771            * received_prefix_count (int)
772            * accepted_prefix_count (int)
773            * suppressed_prefix_count (int)
774            * advertised_prefix_count (int)
775            * flap_count (int)
776
777        Example::
778
779            {
780                'global': {
781                    8121: [
782                        {
783                            'up'                        : True,
784                            'local_as'                  : 13335,
785                            'remote_as'                 : 8121,
786                            'local_address'             : u'172.101.76.1',
787                            'local_address_configured'  : True,
788                            'local_port'                : 179,
789                            'routing_table'             : u'inet.0',
790                            'remote_address'            : u'192.247.78.0',
791                            'remote_port'               : 58380,
792                            'multihop'                  : False,
793                            'multipath'                 : True,
794                            'remove_private_as'         : True,
795                            'import_policy'             : u'4-NTT-TRANSIT-IN',
796                            'export_policy'             : u'4-NTT-TRANSIT-OUT',
797                            'input_messages'            : 123,
798                            'output_messages'           : 13,
799                            'input_updates'             : 123,
800                            'output_updates'            : 5,
801                            'messages_queued_out'       : 23,
802                            'connection_state'          : u'Established',
803                            'previous_connection_state' : u'EstabSync',
804                            'last_event'                : u'RecvKeepAlive',
805                            'suppress_4byte_as'         : False,
806                            'local_as_prepend'          : False,
807                            'holdtime'                  : 90,
808                            'configured_holdtime'       : 90,
809                            'keepalive'                 : 30,
810                            'configured_keepalive'      : 30,
811                            'active_prefix_count'       : 132808,
812                            'received_prefix_count'     : 566739,
813                            'accepted_prefix_count'     : 566479,
814                            'suppressed_prefix_count'   : 0,
815                            'advertised_prefix_count'   : 0,
816                            'flap_count'                : 27
817                        }
818                    ]
819                }
820            }
821        """
822        raise NotImplementedError
823
824    def get_arp_table(self, vrf=""):
825
826        """
827        Returns a list of dictionaries having the following set of keys:
828            * interface (string)
829            * mac (string)
830            * ip (string)
831            * age (float)
832
833        'vrf' of null-string will default to all VRFs. Specific 'vrf' will return the ARP table
834        entries for that VRFs (including potentially 'default' or 'global').
835
836        In all cases the same data structure is returned and no reference to the VRF that was used
837        is included in the output.
838
839        Example::
840
841            [
842                {
843                    'interface' : 'MgmtEth0/RSP0/CPU0/0',
844                    'mac'       : '5C:5E:AB:DA:3C:F0',
845                    'ip'        : '172.17.17.1',
846                    'age'       : 1454496274.84
847                },
848                {
849                    'interface' : 'MgmtEth0/RSP0/CPU0/0',
850                    'mac'       : '5C:5E:AB:DA:3C:FF',
851                    'ip'        : '172.17.17.2',
852                    'age'       : 1435641582.49
853                }
854            ]
855
856        """
857        raise NotImplementedError
858
859    def get_ntp_peers(self):
860
861        """
862        Returns the NTP peers configuration as dictionary.
863        The keys of the dictionary represent the IP Addresses of the peers.
864        Inner dictionaries do not have yet any available keys.
865
866        Example::
867
868            {
869                '192.168.0.1': {},
870                '17.72.148.53': {},
871                '37.187.56.220': {},
872                '162.158.20.18': {}
873            }
874
875        """
876
877        raise NotImplementedError
878
879    def get_ntp_servers(self):
880
881        """
882        Returns the NTP servers configuration as dictionary.
883        The keys of the dictionary represent the IP Addresses of the servers.
884        Inner dictionaries do not have yet any available keys.
885
886        Example::
887
888            {
889                '192.168.0.1': {},
890                '17.72.148.53': {},
891                '37.187.56.220': {},
892                '162.158.20.18': {}
893            }
894
895        """
896
897        raise NotImplementedError
898
899    def get_ntp_stats(self):
900
901        """
902        Returns a list of NTP synchronization statistics.
903
904            * remote (string)
905            * referenceid (string)
906            * synchronized (True/False)
907            * stratum (int)
908            * type (string)
909            * when (string)
910            * hostpoll (int)
911            * reachability (int)
912            * delay (float)
913            * offset (float)
914            * jitter (float)
915
916        Example::
917
918            [
919                {
920                    'remote'        : u'188.114.101.4',
921                    'referenceid'   : u'188.114.100.1',
922                    'synchronized'  : True,
923                    'stratum'       : 4,
924                    'type'          : u'-',
925                    'when'          : u'107',
926                    'hostpoll'      : 256,
927                    'reachability'  : 377,
928                    'delay'         : 164.228,
929                    'offset'        : -13.866,
930                    'jitter'        : 2.695
931                }
932            ]
933        """
934        raise NotImplementedError
935
936    def get_interfaces_ip(self):
937
938        """
939        Returns all configured IP addresses on all interfaces as a dictionary of dictionaries.
940        Keys of the main dictionary represent the name of the interface.
941        Values of the main dictionary represent are dictionaries that may consist of two keys
942        'ipv4' and 'ipv6' (one, both or none) which are themselves dictionaries with the IP
943        addresses as keys.
944        Each IP Address dictionary has the following keys:
945
946            * prefix_length (int)
947
948        Example::
949
950            {
951                u'FastEthernet8': {
952                    u'ipv4': {
953                        u'10.66.43.169': {
954                            'prefix_length': 22
955                        }
956                    }
957                },
958                u'Loopback555': {
959                    u'ipv4': {
960                        u'192.168.1.1': {
961                            'prefix_length': 24
962                        }
963                    },
964                    u'ipv6': {
965                        u'1::1': {
966                            'prefix_length': 64
967                        },
968                        u'2001:DB8:1::1': {
969                            'prefix_length': 64
970                        },
971                        u'2::': {
972                            'prefix_length': 64
973                        },
974                        u'FE80::3': {
975                            'prefix_length': u'N/A'
976                        }
977                    }
978                },
979                u'Tunnel0': {
980                    u'ipv4': {
981                        u'10.63.100.9': {
982                            'prefix_length': 24
983                        }
984                    }
985                }
986            }
987        """
988        raise NotImplementedError
989
990    def get_mac_address_table(self):
991
992        """
993        Returns a lists of dictionaries. Each dictionary represents an entry in the MAC Address
994        Table, having the following keys:
995
996            * mac (string)
997            * interface (string)
998            * vlan (int)
999            * active (boolean)
1000            * static (boolean)
1001            * moves (int)
1002            * last_move (float)
1003
1004        However, please note that not all vendors provide all these details.
1005        E.g.: field last_move is not available on JUNOS devices etc.
1006
1007        Example::
1008
1009            [
1010                {
1011                    'mac'       : '00:1C:58:29:4A:71',
1012                    'interface' : 'Ethernet47',
1013                    'vlan'      : 100,
1014                    'static'    : False,
1015                    'active'    : True,
1016                    'moves'     : 1,
1017                    'last_move' : 1454417742.58
1018                },
1019                {
1020                    'mac'       : '00:1C:58:29:4A:C1',
1021                    'interface' : 'xe-1/0/1',
1022                    'vlan'       : 100,
1023                    'static'    : False,
1024                    'active'    : True,
1025                    'moves'     : 2,
1026                    'last_move' : 1453191948.11
1027                },
1028                {
1029                    'mac'       : '00:1C:58:29:4A:C2',
1030                    'interface' : 'ae7.900',
1031                    'vlan'      : 900,
1032                    'static'    : False,
1033                    'active'    : True,
1034                    'moves'     : None,
1035                    'last_move' : None
1036                }
1037            ]
1038        """
1039        raise NotImplementedError
1040
1041    def get_route_to(self, destination="", protocol="", longer=False):
1042
1043        """
1044        Returns a dictionary of dictionaries containing details of all available routes to a
1045        destination.
1046
1047        :param destination: The destination prefix to be used when filtering the routes.
1048        :param protocol: Retrieve the routes only for a specific protocol.
1049        :type protocol: optional
1050        :param longer: Retrieve more specific routes as well.
1051        :type longer: optional
1052
1053        Each inner dictionary contains the following fields:
1054
1055            * protocol (string)
1056            * current_active (True/False)
1057            * last_active (True/False)
1058            * age (int)
1059            * next_hop (string)
1060            * outgoing_interface (string)
1061            * selected_next_hop (True/False)
1062            * preference (int)
1063            * inactive_reason (string)
1064            * routing_table (string)
1065            * protocol_attributes (dictionary)
1066
1067        protocol_attributes is a dictionary with protocol-specific information, as follows:
1068
1069        - BGP
1070            * local_as (int)
1071            * remote_as (int)
1072            * peer_id (string)
1073            * as_path (string)
1074            * communities (list)
1075            * local_preference (int)
1076            * preference2 (int)
1077            * metric (int)
1078            * metric2 (int)
1079        - ISIS:
1080            * level (int)
1081
1082        Example::
1083
1084            {
1085                "1.0.0.0/24": [
1086                    {
1087                        "protocol"          : u"BGP",
1088                        "inactive_reason"   : u"Local Preference",
1089                        "last_active"       : False,
1090                        "age"               : 105219,
1091                        "next_hop"          : u"172.17.17.17",
1092                        "selected_next_hop" : True,
1093                        "preference"        : 170,
1094                        "current_active"    : False,
1095                        "outgoing_interface": u"ae9.0",
1096                        "routing_table"     : "inet.0",
1097                        "protocol_attributes": {
1098                            "local_as"          : 13335,
1099                            "as_path"           : u"2914 8403 54113 I",
1100                            "communities"       : [
1101                                u"2914:1234",
1102                                u"2914:5678",
1103                                u"8403:1717",
1104                                u"54113:9999"
1105                            ],
1106                            "preference2"       : -101,
1107                            "remote_as"         : 2914,
1108                            "local_preference"  : 100
1109                        }
1110                    }
1111                ]
1112            }
1113        """
1114        raise NotImplementedError
1115
1116    def get_snmp_information(self):
1117
1118        """
1119        Returns a dict of dicts containing SNMP configuration.
1120        Each inner dictionary contains these fields
1121
1122            * chassis_id (string)
1123            * community (dictionary)
1124            * contact (string)
1125            * location (string)
1126
1127        'community' is a dictionary with community string specific information, as follows:
1128
1129            * acl (string) # acl number or name
1130            * mode (string) # read-write (rw), read-only (ro)
1131
1132        Example::
1133
1134            {
1135                'chassis_id': u'Asset Tag 54670',
1136                'community': {
1137                    u'private': {
1138                        'acl': u'12',
1139                        'mode': u'rw'
1140                    },
1141                    u'public': {
1142                        'acl': u'11',
1143                        'mode': u'ro'
1144                    },
1145                    u'public_named_acl': {
1146                        'acl': u'ALLOW-SNMP-ACL',
1147                        'mode': u'ro'
1148                    },
1149                    u'public_no_acl': {
1150                        'acl': u'N/A',
1151                        'mode': u'ro'
1152                    }
1153                },
1154                'contact' : u'Joe Smith',
1155                'location': u'123 Anytown USA Rack 404'
1156            }
1157        """
1158        raise NotImplementedError
1159
1160    def get_probes_config(self):
1161        """
1162        Returns a dictionary with the probes configured on the device.
1163        Probes can be either RPM on JunOS devices, either SLA on IOS-XR. Other vendors do not
1164        support probes.
1165        The keys of the main dictionary represent the name of the probes.
1166        Each probe consists on multiple tests, each test name being a key in the probe dictionary.
1167        A test has the following keys:
1168
1169            * probe_type (str)
1170            * target (str)
1171            * source (str)
1172            * probe_count (int)
1173            * test_interval (int)
1174
1175        Example::
1176
1177            {
1178                'probe1':{
1179                    'test1': {
1180                        'probe_type'   : 'icmp-ping',
1181                        'target'       : '192.168.0.1',
1182                        'source'       : '192.168.0.2',
1183                        'probe_count'  : 13,
1184                        'test_interval': 3
1185                    },
1186                    'test2': {
1187                        'probe_type'   : 'http-ping',
1188                        'target'       : '172.17.17.1',
1189                        'source'       : '192.17.17.2',
1190                        'probe_count'  : 5,
1191                        'test_interval': 60
1192                    }
1193                }
1194            }
1195        """
1196        raise NotImplementedError
1197
1198    def get_probes_results(self):
1199        """
1200        Returns a dictionary with the results of the probes.
1201        The keys of the main dictionary represent the name of the probes.
1202        Each probe consists on multiple tests, each test name being a key in the probe dictionary.
1203        A test has the following keys:
1204
1205            * target (str)
1206            * source (str)
1207            * probe_type (str)
1208            * probe_count (int)
1209            * rtt (float)
1210            * round_trip_jitter (float)
1211            * current_test_loss (float)
1212            * current_test_min_delay (float)
1213            * current_test_max_delay (float)
1214            * current_test_avg_delay (float)
1215            * last_test_min_delay (float)
1216            * last_test_max_delay (float)
1217            * last_test_avg_delay (float)
1218            * global_test_min_delay (float)
1219            * global_test_max_delay (float)
1220            * global_test_avg_delay (float)
1221
1222        Example::
1223
1224            {
1225                'probe1':  {
1226                    'test1': {
1227                        'last_test_min_delay'   : 63.120,
1228                        'global_test_min_delay' : 62.912,
1229                        'current_test_avg_delay': 63.190,
1230                        'global_test_max_delay' : 177.349,
1231                        'current_test_max_delay': 63.302,
1232                        'global_test_avg_delay' : 63.802,
1233                        'last_test_avg_delay'   : 63.438,
1234                        'last_test_max_delay'   : 65.356,
1235                        'probe_type'            : 'icmp-ping',
1236                        'rtt'                   : 63.138,
1237                        'current_test_loss'     : 0,
1238                        'round_trip_jitter'     : -59.0,
1239                        'target'                : '192.168.0.1',
1240                        'source'                : '192.168.0.2'
1241                        'probe_count'           : 15,
1242                        'current_test_min_delay': 63.138
1243                    },
1244                    'test2': {
1245                        'last_test_min_delay'   : 176.384,
1246                        'global_test_min_delay' : 169.226,
1247                        'current_test_avg_delay': 177.098,
1248                        'global_test_max_delay' : 292.628,
1249                        'current_test_max_delay': 180.055,
1250                        'global_test_avg_delay' : 177.959,
1251                        'last_test_avg_delay'   : 177.178,
1252                        'last_test_max_delay'   : 184.671,
1253                        'probe_type'            : 'icmp-ping',
1254                        'rtt'                   : 176.449,
1255                        'current_test_loss'     : 0,
1256                        'round_trip_jitter'     : -34.0,
1257                        'target'                : '172.17.17.1',
1258                        'source'                : '172.17.17.2'
1259                        'probe_count'           : 15,
1260                        'current_test_min_delay': 176.402
1261                    }
1262                }
1263            }
1264        """
1265        raise NotImplementedError
1266
1267    def ping(
1268        self,
1269        destination,
1270        source=c.PING_SOURCE,
1271        ttl=c.PING_TTL,
1272        timeout=c.PING_TIMEOUT,
1273        size=c.PING_SIZE,
1274        count=c.PING_COUNT,
1275        vrf=c.PING_VRF,
1276        source_interface=c.PING_SOURCE_INTERFACE,
1277    ):
1278        """
1279        Executes ping on the device and returns a dictionary with the result
1280
1281        :param destination: Host or IP Address of the destination
1282        :param source: Source address of echo request
1283        :type source: optional
1284        :param ttl: Maximum number of hops
1285        :type ttl: optional
1286        :param timeout: Maximum seconds to wait after sending final packet
1287        :type timeout: optional
1288        :param size: Size of request (bytes)
1289        :type size: optional
1290        :param count: Number of ping request to send
1291        :type count: optional
1292        :param vrf: Use a specific VRF to execute the ping
1293        :type vrf: optional
1294        :param source_interface: Use an IP from a source interface as source address of echo request
1295        :type source_interface: optional
1296
1297        Output dictionary has one of following keys:
1298
1299            * success
1300            * error
1301
1302        In case of success, inner dictionary will have the following keys:
1303
1304            * probes_sent (int)
1305            * packet_loss (int)
1306            * rtt_min (float)
1307            * rtt_max (float)
1308            * rtt_avg (float)
1309            * rtt_stddev (float)
1310            * results (list)
1311
1312        'results' is a list of dictionaries with the following keys:
1313
1314            * ip_address (str)
1315            * rtt (float)
1316
1317        Example::
1318
1319            {
1320                'success': {
1321                    'probes_sent': 5,
1322                    'packet_loss': 0,
1323                    'rtt_min': 72.158,
1324                    'rtt_max': 72.433,
1325                    'rtt_avg': 72.268,
1326                    'rtt_stddev': 0.094,
1327                    'results': [
1328                        {
1329                            'ip_address': u'1.1.1.1',
1330                            'rtt': 72.248
1331                        },
1332                        {
1333                            'ip_address': '2.2.2.2',
1334                            'rtt': 72.299
1335                        }
1336                    ]
1337                }
1338            }
1339
1340            OR
1341
1342            {
1343                'error': 'unknown host 8.8.8.8.8'
1344            }
1345
1346        """
1347        raise NotImplementedError
1348
1349    def traceroute(
1350        self,
1351        destination,
1352        source=c.TRACEROUTE_SOURCE,
1353        ttl=c.TRACEROUTE_TTL,
1354        timeout=c.TRACEROUTE_TIMEOUT,
1355        vrf=c.TRACEROUTE_VRF,
1356    ):
1357        """
1358        Executes traceroute on the device and returns a dictionary with the result.
1359
1360        :param destination: Host or IP Address of the destination
1361        :param source: Use a specific IP Address to execute the traceroute
1362        :type source: optional
1363        :param ttl: Maximum number of hops
1364        :type ttl: optional
1365        :param timeout: Number of seconds to wait for response
1366        :type timeout: optional
1367        :param vrf: Use a specific VRF to execute the traceroute
1368        :type vrf: optional
1369
1370        Output dictionary has one of the following keys:
1371
1372            * success
1373            * error
1374
1375        In case of success, the keys of the dictionary represent the hop ID, while values are
1376        dictionaries containing the probes results:
1377
1378            * rtt (float)
1379            * ip_address (str)
1380            * host_name (str)
1381
1382        Example::
1383
1384            {
1385                'success': {
1386                    1: {
1387                        'probes': {
1388                            1: {
1389                                'rtt': 1.123,
1390                                'ip_address': u'206.223.116.21',
1391                                'host_name': u'eqixsj-google-gige.google.com'
1392                            },
1393                            2: {
1394                                'rtt': 1.9100000000000001,
1395                                'ip_address': u'206.223.116.21',
1396                                'host_name': u'eqixsj-google-gige.google.com'
1397                            },
1398                            3: {
1399                                'rtt': 3.347,
1400                                'ip_address': u'198.32.176.31',
1401                                'host_name': u'core2-1-1-0.pao.net.google.com'}
1402                            }
1403                        },
1404                        2: {
1405                            'probes': {
1406                                1: {
1407                                    'rtt': 1.586,
1408                                    'ip_address': u'209.85.241.171',
1409                                    'host_name': u'209.85.241.171'
1410                                    },
1411                                2: {
1412                                    'rtt': 1.6300000000000001,
1413                                    'ip_address': u'209.85.241.171',
1414                                    'host_name': u'209.85.241.171'
1415                                },
1416                                3: {
1417                                    'rtt': 1.6480000000000001,
1418                                    'ip_address': u'209.85.241.171',
1419                                    'host_name': u'209.85.241.171'}
1420                                }
1421                            },
1422                        3: {
1423                            'probes': {
1424                                1: {
1425                                    'rtt': 2.529,
1426                                    'ip_address': u'216.239.49.123',
1427                                    'host_name': u'216.239.49.123'},
1428                                2: {
1429                                    'rtt': 2.474,
1430                                    'ip_address': u'209.85.255.255',
1431                                    'host_name': u'209.85.255.255'
1432                                },
1433                                3: {
1434                                    'rtt': 7.813,
1435                                    'ip_address': u'216.239.58.193',
1436                                    'host_name': u'216.239.58.193'}
1437                                }
1438                            },
1439                        4: {
1440                            'probes': {
1441                                1: {
1442                                    'rtt': 1.361,
1443                                    'ip_address': u'8.8.8.8',
1444                                    'host_name': u'google-public-dns-a.google.com'
1445                                },
1446                                2: {
1447                                    'rtt': 1.605,
1448                                    'ip_address': u'8.8.8.8',
1449                                    'host_name': u'google-public-dns-a.google.com'
1450                                },
1451                                3: {
1452                                    'rtt': 0.989,
1453                                    'ip_address': u'8.8.8.8',
1454                                    'host_name': u'google-public-dns-a.google.com'}
1455                                }
1456                            }
1457                        }
1458                    }
1459
1460            OR
1461
1462            {
1463                'error': 'unknown host 8.8.8.8.8'
1464            }
1465        """
1466        raise NotImplementedError
1467
1468    def get_users(self):
1469        """
1470        Returns a dictionary with the configured users.
1471        The keys of the main dictionary represents the username. The values represent the details
1472        of the user, represented by the following keys:
1473
1474            * level (int)
1475            * password (str)
1476            * sshkeys (list)
1477
1478        The level is an integer between 0 and 15, where 0 is the lowest access and 15 represents
1479        full access to the device.
1480
1481        Example::
1482
1483            {
1484                'mircea': {
1485                    'level': 15,
1486                    'password': '$1$0P70xKPa$z46fewjo/10cBTckk6I/w/',
1487                    'sshkeys': [
1488                        'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC4pFn+shPwTb2yELO4L7NtQrKOJXNeCl1je\
1489                         l9STXVaGnRAnuc2PXl35vnWmcUq6YbUEcgUTRzzXfmelJKuVJTJIlMXii7h2xkbQp0YZIEs4P\
1490                         8ipwnRBAxFfk/ZcDsN3mjep4/yjN56eorF5xs7zP9HbqbJ1dsqk1p3A/9LIL7l6YewLBCwJj6\
1491                         D+fWSJ0/YW+7oH17Fk2HH+tw0L5PcWLHkwA4t60iXn16qDbIk/ze6jv2hDGdCdz7oYQeCE55C\
1492                         CHOHMJWYfN3jcL4s0qv8/u6Ka1FVkV7iMmro7ChThoV/5snI4Ljf2wKqgHH7TfNaCfpU0WvHA\
1493                         nTs8zhOrGScSrtb mircea@master-roshi'
1494                    ]
1495                }
1496            }
1497        """
1498        raise NotImplementedError
1499
1500    def get_optics(self):
1501        """Fetches the power usage on the various transceivers installed
1502        on the switch (in dbm), and returns a view that conforms with the
1503        openconfig model openconfig-platform-transceiver.yang
1504
1505        Returns a dictionary where the keys are as listed below:
1506
1507            * intf_name (unicode)
1508                * physical_channels
1509                    * channels (list of dicts)
1510                        * index (int)
1511                        * state
1512                            * input_power
1513                                * instant (float)
1514                                * avg (float)
1515                                * min (float)
1516                                * max (float)
1517                            * output_power
1518                                * instant (float)
1519                                * avg (float)
1520                                * min (float)
1521                                * max (float)
1522                            * laser_bias_current
1523                                * instant (float)
1524                                * avg (float)
1525                                * min (float)
1526                                * max (float)
1527
1528        Example::
1529
1530            {
1531                'et1': {
1532                    'physical_channels': {
1533                        'channel': [
1534                            {
1535                                'index': 0,
1536                                'state': {
1537                                    'input_power': {
1538                                        'instant': 0.0,
1539                                        'avg': 0.0,
1540                                        'min': 0.0,
1541                                        'max': 0.0,
1542                                    },
1543                                    'output_power': {
1544                                        'instant': 0.0,
1545                                        'avg': 0.0,
1546                                        'min': 0.0,
1547                                        'max': 0.0,
1548                                    },
1549                                    'laser_bias_current': {
1550                                        'instant': 0.0,
1551                                        'avg': 0.0,
1552                                        'min': 0.0,
1553                                        'max': 0.0,
1554                                    },
1555                                }
1556                            }
1557                        ]
1558                    }
1559                }
1560            }
1561        """
1562        raise NotImplementedError
1563
1564    def get_config(self, retrieve="all", full=False, sanitized=False):
1565        """
1566        Return the configuration of a device.
1567
1568        Args:
1569            retrieve(string): Which configuration type you want to populate, default is all of them.
1570                              The rest will be set to "".
1571            full(bool): Retrieve all the configuration. For instance, on ios, "sh run all".
1572            sanitized(bool): Remove secret data. Default: ``False``.
1573
1574        Returns:
1575          The object returned is a dictionary with a key for each configuration store:
1576
1577            - running(string) - Representation of the native running configuration
1578            - candidate(string) - Representation of the native candidate configuration. If the
1579              device doesnt differentiate between running and startup configuration this will an
1580              empty string
1581            - startup(string) - Representation of the native startup configuration. If the
1582              device doesnt differentiate between running and startup configuration this will an
1583              empty string
1584        """
1585        raise NotImplementedError
1586
1587    def get_network_instances(self, name=""):
1588        """
1589        Return a dictionary of network instances (VRFs) configured, including default/global
1590
1591        Args:
1592            name(string) - Name of the network instance to return, default is all.
1593
1594        Returns:
1595            A dictionary of network instances in OC format:
1596            * name (dict)
1597                * name (unicode)
1598                * type (unicode)
1599                * state (dict)
1600                    * route_distinguisher (unicode)
1601                * interfaces (dict)
1602                    * interface (dict)
1603                        * interface name: (dict)
1604
1605        Example::
1606
1607            {
1608                u'MGMT': {
1609                    u'name': u'MGMT',
1610                    u'type': u'L3VRF',
1611                    u'state': {
1612                        u'route_distinguisher': u'123:456',
1613                    },
1614                    u'interfaces': {
1615                        u'interface': {
1616                            u'Management1': {}
1617                        }
1618                    }
1619                },
1620                u'default': {
1621                    u'name': u'default',
1622                    u'type': u'DEFAULT_INSTANCE',
1623                    u'state': {
1624                        u'route_distinguisher': None,
1625                    },
1626                    u'interfaces: {
1627                        u'interface': {
1628                            u'Ethernet1': {}
1629                            u'Ethernet2': {}
1630                            u'Ethernet3': {}
1631                            u'Ethernet4': {}
1632                        }
1633                    }
1634                }
1635            }
1636        """
1637        raise NotImplementedError
1638
1639    def get_firewall_policies(self):
1640        """
1641        Returns a dictionary of lists of dictionaries where the first key is an unique policy
1642        name and the inner dictionary contains the following keys:
1643
1644        * position (int)
1645        * packet_hits (int)
1646        * byte_hits (int)
1647        * id (text_type)
1648        * enabled (bool)
1649        * schedule (text_type)
1650        * log (text_type)
1651        * l3_src (text_type)
1652        * l3_dst (text_type)
1653        * service (text_type)
1654        * src_zone (text_type)
1655        * dst_zone (text_type)
1656        * action (text_type)
1657
1658        Example::
1659
1660            {
1661                'policy_name': [{
1662                    'position': 1,
1663                    'packet_hits': 200,
1664                    'byte_hits': 83883,
1665                    'id': '230',
1666                    'enabled': True,
1667                    'schedule': 'Always',
1668                    'log': 'all',
1669                    'l3_src': 'any',
1670                    'l3_dst': 'any',
1671                    'service': 'HTTP',
1672                    'src_zone': 'port2',
1673                    'dst_zone': 'port3',
1674                    'action': 'Permit'
1675                }]
1676            }
1677        """
1678        raise NotImplementedError
1679
1680    def get_ipv6_neighbors_table(self):
1681        """
1682        Get IPv6 neighbors table information.
1683
1684        Return a list of dictionaries having the following set of keys:
1685
1686            * interface (string)
1687            * mac (string)
1688            * ip (string)
1689            * age (float) in seconds
1690            * state (string)
1691
1692        For example::
1693
1694            [
1695                {
1696                    'interface' : 'MgmtEth0/RSP0/CPU0/0',
1697                    'mac'       : '5c:5e:ab:da:3c:f0',
1698                    'ip'        : '2001:db8:1:1::1',
1699                    'age'       : 1454496274.84,
1700                    'state'     : 'REACH'
1701                },
1702                {
1703                    'interface': 'MgmtEth0/RSP0/CPU0/0',
1704                    'mac'       : '66:0e:94:96:e0:ff',
1705                    'ip'        : '2001:db8:1:1::2',
1706                    'age'       : 1435641582.49,
1707                    'state'     : 'STALE'
1708                }
1709            ]
1710        """
1711        raise NotImplementedError
1712
1713    def get_vlans(self):
1714        """
1715        Return structure being spit balled is as follows.
1716            * vlan_id (int)
1717                * name (text_type)
1718                * interfaces (list)
1719
1720        Example::
1721
1722            {
1723                1: {
1724                    "name": "default",
1725                    "interfaces": ["GigabitEthernet0/0/1", "GigabitEthernet0/0/2"]
1726                },
1727                2: {
1728                    "name": "vlan2",
1729                    "interfaces": []
1730                }
1731            }
1732        """
1733        raise NotImplementedError
1734
1735    def compliance_report(self, validation_file=None, validation_source=None):
1736        """
1737        Return a compliance report.
1738
1739        Verify that the device complies with the given validation file and writes a compliance
1740        report file. See https://napalm.readthedocs.io/en/latest/validate/index.html.
1741
1742        :param validation_file: Path to the file containing compliance definition. Default is None.
1743        :param validation_source: Dictionary containing compliance rules.
1744        :raise ValidationException: File is not valid.
1745        :raise NotImplementedError: Method not implemented.
1746        """
1747        return validate.compliance_report(
1748            self, validation_file=validation_file, validation_source=validation_source
1749        )
1750
1751    def _canonical_int(self, interface):
1752        """Expose the helper function within this class."""
1753        if self.use_canonical_interface is True:
1754            return napalm.base.helpers.canonical_interface_name(
1755                interface, addl_name_map=None
1756            )
1757        else:
1758            return interface
1759