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