[
  {
    "path": ".github/ISSUE_TEMPLATE/ask_question.md",
    "content": "---\r\nname: Ask Question\r\nabout: Ask all information you want\r\n---\r\n\r\n**Question**\r\n\r\nAll what you want to know\r\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "content": "---\r\nname: Bug Report\r\nabout: Report a bug in Netdev library\r\n---\r\n\r\n**Describe the bug**\r\n\r\nA clear and concise description of what the bug is.\r\n\r\n**General Information**\r\n\r\n - OS [e.g. Windows 10]\r\n - Netdev version [e.g. 0.9.0]\r\n - Device OS [e.g. Cisco IOS XE 3.4.6]\r\n\r\n**Debug information**\r\n\r\nI usually need a debug information for understanding what exactly happened. You can get it by using this code:\r\n\r\n```python\r\nimport netdev\r\nimport logging\r\n\r\nlogging.basicConfig(level=logging.INFO)\r\nnetdev.logger.setLevel(logging.DEBUG)\r\n```\r\n\r\n**Additional context**\r\n\r\nAdd any other context about the problem here.\r\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.md",
    "content": "---\r\nname: Feature Request\r\nabout: Feature Request in Netdev library\r\n---\r\n\r\n**Proposed functionality**\r\n\r\n\r\n**Use case**\r\n\r\n\r\n**Additional context**\r\n\r\nAdd any other context about the problem here.\r\n"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "content": "**Description**\r\n\r\nFull description of purpose and all changes\r\n"
  },
  {
    "path": ".gitignore",
    "content": "# Byte-compiled / optimized / DLL files\r\n__pycache__/\r\n*.py[cod]\r\n*$py.class\r\n\r\n# Distribution / packaging\r\n.Python\r\nvenv/\r\ndist/\r\n*.egg-info/\r\npoetry.lock\r\n\r\n# Unit tests\r\ntests/*.log\r\n*.yaml\r\n\r\n# Docs\r\n/docs/_build\r\n/docs/[Mm]ake*\r\n\r\n# Others\r\n.idea/\r\n.vscode/\r\n"
  },
  {
    "path": ".readthedocs.yml",
    "content": "---\r\nversion: 2\r\n\r\npython:\r\n  version: 3.7\r\n  install:\r\n      - method: pip\r\n        path: .\r\n        extra_requirements:\r\n            - docs\r\n\r\n"
  },
  {
    "path": "CONTRIBUTING.rst",
    "content": "Contributing to Netdev\r\n======================\r\n\r\nYou're welcome to contribute to this project.\r\n\r\nAsking questions\r\n----------------\r\n\r\nYou can always ask me any question about this project in:\r\n\r\n* `twitter (@selfuryon) <https://twitter.com/selfuryon>`_\r\n* telegram (@selfuryon)\r\n* selfuryon@gmail.com\r\n\r\nYou can also use the `issue tracker <https://github.com/selfuryon/netdev/issues>`_ for asking.\r\n\r\nReporting bugs\r\n--------------\r\n\r\nFor reporting bugs, you need to use the `issue tracker <https://github.com/selfuryon/netdev/issues>`_.\r\nBefore creating a new issue, please check the currently open issues to see\r\nif your problem has already been reported.\r\n\r\nRequesting feature enhancements\r\n-------------------------------\r\n\r\nThe `issue tracker <https://github.com/selfuryon/netdev/issues>`_\r\nshould also be used to post feature enhancement requests.\r\n\r\nContributing code\r\n-----------------\r\n\r\nI haven't any restrictions about contributing code. I can create PR with any fixes and features\r\nand you don't need to do anything else for it except PR. All PRs will be reviewed.\r\n\r\nYou should also know, that code is distributed by\r\nusing `3-clause BSD license <https://opensource.org/licenses/BSD-3-Clause>`_.\r\n\r\nBranches\r\n--------\r\nI have two main branches:\r\n\r\n* The master branch always has a latest stable version\r\n  of the code. All commits on this branch are Releases.\r\n\r\n* The develop branch is the main branch for implementing and testing new features and fixing bugs.\r\n  If you have a heavy feature you can create a separate branch for that. All PR is merged only to develop branch"
  },
  {
    "path": "LICENSE",
    "content": "                                 Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright 2019 Sergey Yakovlev\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n"
  },
  {
    "path": "README.rst",
    "content": "THIS PROJECT IS UNMAINTAINED\n****************************\nI'm not interested in this project anymore, sorry. \nI don't work as an network engineer anymore so I haven't any special goals to improve and maintain it.\n\nNetdev\n******\n\nAsynchronous multi-vendor library for interacting with network devices\n\nInspired by netmiko\n\nRequires:\n---------\n* asyncio\n* AsyncSSH\n* Python >=3.5\n* pyYAML\n  \n \nSupports:\n---------\n* Cisco IOS \n* Cisco IOS XE\n* Cisco IOS XR\n* Cisco ASA\n* Cisco NX-OS\n* Cisco SG3XX\n* HP Comware (like V1910 too)\n* Fujitsu Blade Switches\n* Mikrotik RouterOS\n* Arista EOS\n* Juniper JunOS\n* Aruba AOS 6.X\n* Aruba AOS 8.X\n* Terminal\n* Alcatel AOS\n\nExamples:\n---------\nExample of interacting with Cisco IOS devices:\n\n.. code-block:: python\n\n    import asyncio\n    import netdev\n\n    async def task(param):\n        async with netdev.create(**param) as ios:\n            # Testing sending simple command\n            out = await ios.send_command(\"show ver\")\n            print(out)\n            # Testing sending configuration set\n            commands = [\"line console 0\", \"exit\"]\n            out = await ios.send_config_set(commands)\n            print(out)\n            # Testing sending simple command with long output\n            out = await ios.send_command(\"show run\")\n            print(out)\n            # Testing interactive dialog\n            out = await ios.send_command(\"conf\", pattern=r'\\[terminal\\]\\?', strip_command=False)\n            out += await ios.send_command(\"term\", strip_command=False)\n            out += await ios.send_command(\"exit\", strip_command=False, strip_prompt=False)\n            print(out)\n\n\n    async def run():\n        dev1 = { 'username' : 'user',\n                 'password' : 'pass',\n                 'device_type': 'cisco_ios',\n                 'host': 'ip address',\n        }\n        dev2 = { 'username' : 'user',\n                 'password' : 'pass',\n                 'device_type': 'cisco_ios',\n                 'host': 'ip address',\n        }\n        devices = [dev1, dev2]\n        tasks = [task(dev) for dev in devices]\n        await asyncio.wait(tasks)\n\n\n    loop = asyncio.get_event_loop()\n    loop.run_until_complete(run())\n\n\n"
  },
  {
    "path": "docs/api.rst",
    "content": ".. module:: netdev\r\n\r\n.. _API:\r\n\r\nAPI Documentation\r\n*****************\r\n\r\nOverview\r\n========\r\n\r\nYou should use separate class for each device vendor.\r\nFor this purpose are used Factory method :func:`create`. You should specify device_type in params\r\nfor taking right class\r\n\r\n\r\nFactory method\r\n==============\r\n\r\n.. autofunction:: create\r\n\r\n.. module:: netdev.vendors\r\n\r\nClasses\r\n=======\r\n\r\nBase classes\r\n------------\r\nThese classes are abstract and used as parent by other classes:\r\n\r\nBaseDevice\r\n~~~~~~~~~~\r\n\r\n.. autoclass:: BaseDevice\r\n   :members:\r\n   :special-members: __init__\r\n\r\nIOSLikeDevice\r\n~~~~~~~~~~~~~\r\n\r\n.. autoclass:: IOSLikeDevice\r\n   :members:\r\n   :inherited-members:\r\n\r\nComwareLikeDevice\r\n~~~~~~~~~~~~~~~~~\r\n\r\n.. autoclass:: ComwareLikeDevice\r\n   :members:\r\n   :inherited-members:\r\n\r\n\r\nJunOSLikeDevice\r\n~~~~~~~~~~~~~~~\r\n\r\n.. autoclass:: JunOSLikeDevice\r\n   :members:\r\n   :inherited-members:\r\n\r\nEnd classes\r\n-----------\r\nThese classes are using for particular connection to end devices\r\n\r\nCiscoIOS\r\n~~~~~~~~\r\n\r\n.. autoclass:: CiscoIOS\r\n   :members:\r\n   :inherited-members:\r\n\r\nCiscoIOSXR\r\n~~~~~~~~~~\r\n\r\n.. autoclass:: CiscoIOSXR\r\n   :members:\r\n   :inherited-members:\r\n\r\nCiscoASA\r\n~~~~~~~~\r\n\r\n.. autoclass:: CiscoASA\r\n   :members:\r\n   :inherited-members:\r\n\r\nCiscoNXOS\r\n~~~~~~~~~\r\n\r\n.. autoclass:: CiscoNXOS\r\n   :members:\r\n   :inherited-members:\r\n\r\nCiscoSG3XX\r\n~~~~~~~~~\r\n\r\n.. autoclass:: CiscoSG3XX\r\n   :members:\r\n   :inherited-members:\r\n\r\nFujitsuSwitch\r\n~~~~~~~~~~~~~\r\n\r\n.. autoclass:: FujitsuSwitch\r\n   :members:\r\n   :inherited-members:\r\n\r\nHPComware\r\n~~~~~~~~~\r\n\r\n.. autoclass:: HPComware\r\n   :members:\r\n   :inherited-members:\r\n\r\nHPComwareLimited\r\n~~~~~~~~~~~~~~~~\r\n\r\n.. autoclass:: HPComwareLimited\r\n   :members:\r\n   :inherited-members:\r\n\r\nMikrotikRouterOS\r\n~~~~~~~~~~~~~~~~\r\n\r\n.. autoclass:: MikrotikRouterOS\r\n   :members:\r\n   :inherited-members:\r\n\r\nAristaEOS\r\n~~~~~~~~~\r\n\r\n.. autoclass:: AristaEOS\r\n   :members:\r\n   :inherited-members:\r\n\r\nArubaAOS6\r\n~~~~~~~~~\r\n\r\n.. autoclass:: ArubaAOS6\r\n   :members:\r\n   :inherited-members:\r\n\r\nJuniperJunOS\r\n~~~~~~~~~~~~\r\n\r\n.. autoclass:: JuniperJunOS\r\n   :members:\r\n   :inherited-members:\r\n\r\nTerminal\r\n~~~~~~~~\r\n\r\n.. autoclass:: Terminal\r\n   :members:\r\n   :inherited-members:\r\n\r\nAlcatelAOS\r\n~~~~~~~~\r\n\r\n.. autoclass:: AlcatelAOS\r\n   :members:\r\n   :inherited-members:\r\n"
  },
  {
    "path": "docs/conf.py",
    "content": "#!/usr/bin/env python3\r\n# -*- coding: utf-8 -*-\r\n#\r\n# netdev documentation build configuration file, created by\r\n# sphinx-quickstart on Sun Jul 17 21:52:23 2016.\r\n#\r\n# This file is execfile()d with the current directory set to its\r\n# containing dir.\r\n#\r\n# Note that not all possible configuration values are present in this\r\n# autogenerated file.\r\n#\r\n# All configuration values have a default; values that are commented out\r\n# serve to show the default.\r\nimport os\r\nimport sys\r\n\r\nimport sphinx_rtd_theme\r\n\r\nhtml_theme = 'sphinx_rtd_theme'\r\n\r\n# If extensions (or modules to document with autodoc) are in another directory,\r\n# add these directories to sys.path here. If the directory is relative to the\r\n# documentation root, use os.path.abspath to make it absolute, like shown here.\r\nsys.path.insert(0, os.path.abspath('..'))\r\n\r\nfrom netdev import __version__, __author__\r\n\r\n# -- General configuration ------------------------------------------------\r\n\r\n# If your documentation needs a minimal Sphinx version, state it here.\r\n# needs_sphinx = '1.0'\r\n\r\n# Add any Sphinx extension module names here, as strings. They can be\r\n# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom\r\n# ones.\r\nextensions = ['sphinx.ext.autodoc', 'sphinx.ext.intersphinx', 'sphinx.ext.viewcode', ]\r\n\r\n# Add any paths that contain templates here, relative to this directory.\r\ntemplates_path = ['_templates']\r\n\r\n# The suffix(es) of source filenames.\r\n# You can specify multiple suffix as a list of string:\r\n# source_suffix = ['.rst', '.md']\r\nsource_suffix = '.rst'\r\n\r\n# The encoding of source files.\r\n# source_encoding = 'utf-8-sig'\r\n\r\n# The master toctree document.\r\nmaster_doc = 'index'\r\n\r\n# General information about the project.\r\nproject = 'netdev'\r\ncopyright = '2016, {}'.format(__author__)\r\nauthor = __author__\r\n\r\n# The version info for the project you're documenting, acts as replacement for\r\n# |version| and |release|, also used in various other places throughout the\r\n# built documents.\r\n#\r\n# The short X.Y version.\r\nversion = '.'.join(__version__.split('.')[:2])\r\n# The full version, including alpha/beta/rc tags.\r\nrelease = __version__\r\n\r\n# The language for content autogenerated by Sphinx. Refer to documentation\r\n# for a list of supported languages.\r\n#\r\n# This is also used if you do content translation via gettext catalogs.\r\n# Usually you set \"language\" from the command line for these cases.\r\nlanguage = None\r\n\r\n# There are two options for replacing |today|: either, you set today to some\r\n# non-false value, then it is used:\r\n# today = ''\r\n# Else, today_fmt is used as the format for a strftime call.\r\n# today_fmt = '%B %d, %Y'\r\n\r\n# List of patterns, relative to source directory, that match files and\r\n# directories to ignore when looking for source files.\r\nexclude_patterns = ['_build']\r\n\r\n# The reST default role (used for this markup: `text`) to use for all\r\n# documents.\r\n# default_role = None\r\n\r\n# If true, '()' will be appended to :func: etc. cross-reference text.\r\n# add_function_parentheses = True\r\n\r\n# If true, the current module name will be prepended to all description\r\n# unit titles (such as .. function::).\r\n# add_module_names = True\r\n\r\n# If true, sectionauthor and moduleauthor directives will be shown in the\r\n# output. They are ignored by default.\r\n# show_authors = False\r\n\r\n# The name of the Pygments (syntax highlighting) style to use.\r\npygments_style = 'sphinx'\r\n\r\n# A list of ignored prefixes for module index sorting.\r\n# modindex_common_prefix = []\r\n\r\n# If true, keep warnings as \"system message\" paragraphs in the built documents.\r\n# keep_warnings = False\r\n\r\n# If true, `todo` and `todoList` produce output, else they produce nothing.\r\ntodo_include_todos = False\r\n\r\n# -- Options for HTML output ----------------------------------------------\r\n\r\n# The theme to use for HTML and HTML Help pages.  See the documentation for\r\n# a list of builtin themes.\r\n\r\n\r\n\r\n# Theme options are theme-specific and customize the look and feel of a theme\r\n# further.  For a list of options available for each theme, see the\r\n# documentation.\r\n# html_theme_options = {'display_version': True}\r\n\r\n# Add any paths that contain custom themes here, relative to this directory.\r\nhtml_theme_path = [sphinx_rtd_theme.get_html_theme_path()]\r\n\r\n# The name for this set of Sphinx documents.  If None, it defaults to\r\n# \"<project> v<release> documentation\".\r\n# html_title = None\r\n\r\n# A shorter title for the navigation bar.  Default is the same as html_title.\r\n# html_short_title = None\r\n\r\n# The name of an image file (relative to this directory) to place at the top\r\n# of the sidebar.\r\n# html_logo = None\r\n\r\n# The name of an image file (within the static path) to use as favicon of the\r\n# docs.  This file should be a Windows icon file (.ico) being 16x16 or 32x32\r\n# pixels large.\r\n# html_favicon = None\r\n\r\n# Add any paths that contain custom static files (such as style sheets) here,\r\n# relative to this directory. They are copied after the builtin static files,\r\n# so a file named \"default.css\" will overwrite the builtin \"default.css\".\r\nhtml_static_path = ['_static']\r\n\r\n# Add any extra paths that contain custom files (such as robots.txt or\r\n# .htaccess) here, relative to this directory. These files are copied\r\n# directly to the root of the documentation.\r\n# html_extra_path = []\r\n\r\n# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,\r\n# using the given strftime format.\r\n# html_last_updated_fmt = '%b %d, %Y'\r\n\r\n# If true, SmartyPants will be used to convert quotes and dashes to\r\n# typographically correct entities.\r\n# html_use_smartypants = True\r\n\r\n# Custom sidebar templates, maps document names to template names.\r\n# html_sidebars = {}\r\n\r\n# Additional templates that should be rendered to pages, maps page names to\r\n# template names.\r\n# html_additional_pages = {}\r\n\r\n# If false, no module index is generated.\r\n# html_domain_indices = True\r\n\r\n# If false, no index is generated.\r\n# html_use_index = True\r\n\r\n# If true, the index is split into individual pages for each letter.\r\n# html_split_index = False\r\n\r\n# If true, links to the reST sources are added to the pages.\r\n# html_show_sourcelink = True\r\n\r\n# If true, \"Created using Sphinx\" is shown in the HTML footer. Default is True.\r\n# html_show_sphinx = True\r\n\r\n# If true, \"(C) Copyright ...\" is shown in the HTML footer. Default is True.\r\n# html_show_copyright = True\r\n\r\n# If true, an OpenSearch description file will be output, and all pages will\r\n# contain a <link> tag referring to it.  The value of this option must be the\r\n# base URL from which the finished HTML is served.\r\n# html_use_opensearch = ''\r\n\r\n# This is the file name suffix for HTML files (e.g. \".xhtml\").\r\n# html_file_suffix = None\r\n\r\n# Language to be used for generating the HTML full-text search index.\r\n# Sphinx supports the following languages:\r\n#   'da', 'de', 'en', 'es', 'fi', 'fr', 'h', 'it', 'ja'\r\n#   'nl', 'no', 'pt', 'ro', 'r', 'sv', 'tr'\r\n# html_search_language = 'en'\r\n\r\n# A dictionary with options for the search language support, empty by default.\r\n# Now only 'ja' uses this config value\r\n# html_search_options = {'type': 'default'}\r\n\r\n# The name of a javascript file (relative to the configuration directory) that\r\n# implements a search results scorer. If empty, the default will be used.\r\n# html_search_scorer = 'scorer.js'\r\n\r\n# Output file base name for HTML help builder.\r\nhtmlhelp_basename = 'netdevdoc'\r\n\r\n# -- Options for LaTeX output ---------------------------------------------\r\n\r\nlatex_elements = {}  # The paper size ('letterpaper' or 'a4paper').# 'papersize': 'letterpaper',\r\n\r\n    # The font size ('10pt', '11pt' or '12pt').# 'pointsize': '10pt',\r\n\r\n    # Additional stuff for the LaTeX preamble.# 'preamble': '',\r\n\r\n    # Latex figure (float) alignment# 'figure_align': 'htbp',}}\r\n# Grouping the document tree into LaTeX files. List of tuples\r\n# (source start file, target name, title,\r\n#  author, documentclass [howto, manual, or own class]).}\r\nlatex_documents = [(master_doc, 'netdev.tex', 'netdev Documentation', 'Yakovlev Sergey', 'manual'), ]\r\n\r\n# The name of an image file (relative to this directory) to place at the top of\r\n# the title page.\r\n# latex_logo = None\r\n\r\n# For \"manual\" documents, if this is true, then toplevel headings are parts,\r\n# not chapters.\r\n# latex_use_parts = False\r\n\r\n# If true, show page references after internal links.\r\n# latex_show_pagerefs = False\r\n\r\n# If true, show URL addresses after external links.\r\n# latex_show_urls = False\r\n\r\n# Documents to append as an appendix to all manuals.\r\n# latex_appendices = []\r\n\r\n# If false, no module index is generated.\r\n# latex_domain_indices = True\r\n\r\n\r\n# -- Options for manual page output ---------------------------------------\r\n\r\n# One entry per manual page. List of tuples\r\n# (source start file, name, description, authors, manual section).\r\nman_pages = [(master_doc, 'netdev', 'netdev Documentation', [author], 1)]\r\n\r\n# If true, show URL addresses after external links.\r\n# man_show_urls = False\r\n\r\n\r\n# -- Options for Texinfo output -------------------------------------------\r\n\r\n# Grouping the document tree into Texinfo files. List of tuples\r\n# (source start file, target name, title, author,\r\n#  dir menu entry, description, category)\r\ntexinfo_documents = [(\r\nmaster_doc, 'netdev', 'netdev Documentation', author, 'netdev', 'One line description of project.', 'Miscellaneous'), ]\r\n\r\n# Documents to append as an appendix to all manuals.\r\n# texinfo_appendices = []\r\n\r\n# If false, no module index is generated.\r\n# texinfo_domain_indices = True\r\n\r\n# How to display URL addresses: 'footnote', 'no', or 'inline'.\r\n# texinfo_show_urls = 'footnote'\r\n\r\n# If true, do not generate a @detailmenu in the \"Top\" node's menu.\r\n# texinfo_no_detailmenu = False\r\n\r\n\r\n# Example configuration for intersphinx: refer to the Python standard library.\r\nintersphinx_mapping = {'https://docs.python.org/': None}\r\n"
  },
  {
    "path": "docs/examples.rst",
    "content": ".. _Examples:\r\n\r\nExamples\r\n********\r\n\r\nIn examples are used configuration files.\r\nconfig.yaml:\r\n\r\n.. code-block:: text\r\n\r\n   device_list: credentials.yaml\r\n\r\ncredentials.yaml\r\n\r\n.. code-block:: text\r\n\r\n   - device_type: cisco_asa\r\n     host: 1.1.1.1\r\n     password: ****\r\n     username: ****\r\n   - device_type: cisco_ios\r\n     host: 2.2.2.2\r\n     password: ****\r\n     username: ****\r\n   - device_type: fujitsu_switch\r\n     host: 3.3.3.3\r\n     password: ****\r\n     username: ****\r\n   - device_type: hp_comware\r\n     host: 4.4.4.4\r\n     password: ****\r\n     username: ****\r\n   - device_type: hp_comware_limited\r\n     host: 5.5.5.5\r\n     password: ****\r\n     username: ****\r\n     cmdline_password: '512900'\r\n   - device_type: arista_eos\r\n     host: 6.6.6.6\r\n     password: ****\r\n     username: ****\r\n   - device_type: juniper_junos\r\n     host: 7.7.7.7\r\n     password: ****\r\n     username: ****\r\n\r\nASA example\r\n-----------\r\n.. literalinclude:: ../examples/cisco_asa.py\r\n\r\nNX-OS example\r\n-------------\r\n.. literalinclude:: ../examples/cisco_nxos.py\r\n\r\nIOS example\r\n-----------\r\n.. literalinclude:: ../examples/cisco_ios.py\r\n\r\nIOS XR example\r\n--------------\r\n.. literalinclude:: ../examples/cisco_iosxr.py\r\n\r\nIOS SG3XX example\r\n--------------\r\n.. literalinclude:: ../examples/cisco_sg3xx.py\r\n\r\nFujitsu example\r\n---------------\r\n.. literalinclude:: ../examples/fujitsu_switch.py\r\n\r\nComware example\r\n---------------\r\n.. literalinclude:: ../examples/hp_comware.py\r\n\r\nComware Limited example\r\n-----------------------\r\n.. literalinclude:: ../examples/hp_comware_limited.py\r\n\r\nMikrotik RouterOS example\r\n-------------------------\r\n.. literalinclude:: ../examples/mikrotik_routeros.py\r\n\r\nArista EOS example\r\n------------------\r\n.. literalinclude:: ../examples/arista_eos.py\r\n\r\nAruba AOS 6.X example\r\n---------------------\r\n.. literalinclude:: ../examples/aruba_aos_6.py\r\n\r\nJuniper JunOS example\r\n---------------------\r\n.. literalinclude:: ../examples/juniper_junos.py\r\n\r\nTerminal example\r\n----------------\r\n.. literalinclude:: ../examples/terminal.py\r\n\r\nAlcatel AOS example\r\n----------------\r\n.. literalinclude:: ../examples/alcatel_aos.py"
  },
  {
    "path": "docs/index.rst",
    "content": ".. toctree::\r\n   :hidden:\r\n   :maxdepth: -1\r\n\r\n   overview\r\n   api\r\n   examples\r\n\r\n.. include:: ../README.rst\r\n"
  },
  {
    "path": "docs/overview.rst",
    "content": ".. module:: netdev\r\n\r\n.. _overview:\r\n\r\nLibrary information\r\n*******************\r\n\r\nOverview\r\n========\r\nNetdev is asynchronous multi-vendor library for interacting with network devices. So you can create many\r\nsimultaneous connection to network devices for parallel executing commands.\r\n\r\nFor creating connection to network device you should use function :func:`create` like this:\r\n\r\n.. code-block:: python\r\n\r\n   async def working_with_netdev():\r\n      dev = netdev.create(host='host', username='username', password='password', device_type='device_type')\r\n      await dev.connect() # Connecting and preparing session for working\r\n      output = await dev.send_command('command') # working with command in privilege/user mode\r\n      print(output)\r\n      output = await dev.send_config_set(['first_command','second_command'] #working with commands in config mode\r\n      print(output)\r\n      await dev.disconnect() #disconnecting from device\r\n\r\n   loop = asyncio.get_event_loop()\r\n   loop.run_until_complete(working_with_netdev())\r\n\r\nor the same with using async context manager:\r\n\r\n.. code-block:: python\r\n\r\n   async def working_with_netdev():\r\n      async with netdev.create(host='host', username='username', password='password', device_type='device_type') as dev:\r\n          output = await dev.send_command('command') # working with command in privilege/user mode\r\n          print(output)\r\n          output = await dev.send_config_set(['first_command','second_command'] #working with commands in config mode\r\n          print(output)\r\n\r\n   loop = asyncio.get_event_loop()\r\n   loop.run_until_complete(working_with_netdev())\r\n\r\n\r\nLibrary structure\r\n=================\r\n\r\n.. module:: netdev.vendors\r\n\r\nLibrary consist from several base classes and end classes which using for communication.\r\nThe main class is :class:`BaseDevice`. It provides some basic functionality regardless of device type.\r\nLibrary also have three common child classes: :class:`IOSLikeDevice`, :class:`ComwareLikeDevice`\r\nand :class:`JunOSLikeDevice`.\r\n\r\n:class:`IOSLikeDevice` class provides basic methods for Cisco IOS like devices: devices which have user exec,\r\nprivilege exec and conf mode concepts.\r\n\r\n:class:`ComwareLikeDevice` class provides basic methods for HP Comware like devices: these devices have only\r\nexec view and system view concepts.\r\n\r\n:class:`JunOSLikeDevice` class provides basic methods for Juniper JunOS like devices: they have operation mode and\r\nconfiguration mode concepts with committing changes.\r\n\r\nAll other classes are the end classes which you can use for working with particular device:\r\n\r\n* :class:`MikrotikRouterOS`\r\n* :class:`CiscoIOS`\r\n* :class:`CiscoIOSXR`\r\n* :class:`CiscoASA`\r\n* :class:`CiscoNXOS`\r\n* :class:`CiscoSG3XX`\r\n* :class:`FujitsuSwitch`\r\n* :class:`HPComware`\r\n* :class:`HPComwareLimited`\r\n* :class:`AristaEOS`\r\n* :class:`JuniperJunOS`\r\n* :class:`AlcatelAOS`\r\n\r\nThe particular class selected by parameter *device_type* in :func:`create`\r\n\r\nLogging\r\n=======\r\n\r\nFor debugging purpose library has :data:`logger` object. You can use it like this:\r\n\r\n.. code-block:: python\r\n\r\n    import netdev\r\n\r\n    netdev_logger = netdev.logger\r\n    netdev_logger.setLevel(logging.INFO)\r\n    netdev_logger.addHandler(logging.StreamHandler())\r\n\r\n    #Your own code\r\n\r\nCommon public methods and properties\r\n====================================\r\n\r\nBase classes have several common public methods.\r\n\r\nManaging flow\r\n-------------\r\nFor working with network device firstly you need to connect to device and after working you need\r\nto disconnect from device. For this purpose are used these methods:\r\n\r\n- :func:`BaseDevice.connect`\r\n- :func:`BaseDevice.disconnect`\r\n\r\nSending commands\r\n----------------\r\nSome devices using mode principle: exists exec mode and configuration mode. Exec mode are used for getting some\r\ninformation from device, configuration mode are used for configuration device. For this purpose netdev\r\nhave 2 basic methods:\r\n\r\n- :func:`BaseDevice.send_command`\r\n\r\nThis method is used for sending specific command to device in exec mode. Basically for getting some information\r\nfrom device\r\n\r\n- :func:`BaseDevice.send_config_set`\r\n\r\nThis method are used for sending command list to device in configuration mode. Command list is the list of all commands\r\nwhich configure device.\r\n\r\n\r\nSome others\r\n-----------\r\n\r\n- :attr:`BaseDevice.base_prompt`\r\n- :attr:`CiscoASA.current_context`\r\n- :attr:`CiscoASA.multiple_mode`\r\n"
  },
  {
    "path": "examples/alcatel_aos.py",
    "content": "#!/usr/bin/env python3\n\n# Import Python library\nimport asyncio, netdev\n\n# Coroutine used for the tasks\nasync def task(param):\n\n    # Create an object for the devices and open SSH connections\n    async with netdev.create(**param) as device:\n\n        # Testing sending simple command\n        \n        # Command to send\n        cmd = \"show system\"\n\n        # Sending command\n        output = await device.send_command(cmd)\n\n        # Display the output\n        print(output)\n\n        # Display separator\n        print(\"*\" * 80)\n\n        # Testing sending configuration set\n\n        # Commands to send\n        commands = [\"vlan 3000\", \"no vlan 3001\"]\n\n        # Sending command\n        output = await device.send_config_set(commands)\n\n        # Display the output\n        print(output)\n\n\n# Main coroutine\nasync def main():\n\n    # Parameters of the network device\n    my_device = {   'username' : 'LOGIN',\n                    'password' : 'PASSWORD',\n                    'host': 'IP_ADDRESS',\n                    'device_type': 'alcatel_aos',\n    }\n\n    # List of devices\n    devices = [my_device]\n    \n    # List of tasks\n    my_tasks = [task(dev) for dev in devices]\n    \n    # Starting the coroutine of the tasks\n    await asyncio.wait(my_tasks)\n\n\n# Main function call\nif __name__ == '__main__':\n\n    # Run the main coroutine\n    asyncio.run(main())\n\n    '''\n    Result:\n    ********************************************************************************\n    System:\n    Description:  Alcatel-Lucent Enterprise OS6860E-48 8.4.1.141.R03 GA, December 07, 2017.,\n    Object ID:    1.3.6.1.4.1.6486.801.1.1.2.1.11.1.7,\n    Up Time:      5 days 5 hours 3 minutes and 56 seconds,\n    Contact:      Alcatel-Lucent, http://enterprise.alcatel-lucent.com,\n    Name:         switch01,\n    Location:     Somewhere nearby,\n    Services:     78,\n    Date & Time:  SAT AUG 29 2020 18:48:53 (CEST)\n    Flash Space:\n        Primary CMM:\n        Available (bytes):  933896192,\n        Comments         :  None\n\n    ********************************************************************************\n    vlan 3000\n\n    switch01 ==> no vlan 3001\n\n    switch01 ==>\n\n    ********************************************************************************\n\n    '''"
  },
  {
    "path": "examples/arista_eos.py",
    "content": "import asyncio\r\nimport logging\r\n\r\nimport yaml\r\n\r\nimport netdev\r\n\r\nconfig_path = 'config.yaml'\r\n\r\nlogging.basicConfig(level=logging.INFO)\r\nnetdev.logger.setLevel(logging.DEBUG)\r\n\r\n\r\nasync def task(param):\r\n    async with netdev.create(**param) as arista:\r\n        # Testing sending simple command\r\n        out = await arista.send_command('show run', strip_command=True)\r\n        print(out)\r\n        # Testing sending configuration set\r\n        commands = [\"vlan 1\", \"exit\"]\r\n        out = await arista.send_config_set(commands)\r\n        print(out)\r\n\r\n\r\nasync def run():\r\n    config = yaml.safe_load(open(config_path, 'r'))\r\n    devices = yaml.safe_load(open(config['device_list'], 'r'))\r\n    tasks = [task(dev) for dev in devices if dev['device_type'] == 'arista_eos']\r\n    await asyncio.wait(tasks)\r\n\r\n\r\nloop = asyncio.get_event_loop()\r\nloop.run_until_complete(run())\r\n"
  },
  {
    "path": "examples/aruba_aos_6.py",
    "content": "import asyncio\r\nimport logging\r\n\r\nimport yaml\r\n\r\nimport netdev\r\n\r\nconfig_path = 'config.yaml'\r\n\r\nlogging.basicConfig(level=logging.INFO)\r\nnetdev.logger.setLevel(logging.DEBUG)\r\n\r\n\r\nasync def task(param):\r\n    async with netdev.create(**param) as ios:\r\n        # Testing sending simple command\r\n        out = await ios.send_command(\"show ver\")\r\n        print(out)\r\n        # Testing sending configuration set\r\n        commands = [\"interface loopback\", \"exit\"]\r\n        out = await ios.send_config_set(commands)\r\n        print(out)\r\n        # Testing sending simple command with long output\r\n        out = await ios.send_command(\"show run\")\r\n        print(out)\r\n\r\n\r\nasync def run():\r\n    config = yaml.safe_load(open(config_path, 'r'))\r\n    devices = yaml.safe_load(open(config['device_list'], 'r'))\r\n    tasks = [task(dev) for dev in devices if dev['device_type'] == 'aruba_aos_6']\r\n    await asyncio.wait(tasks)\r\n\r\n\r\nloop = asyncio.get_event_loop()\r\nloop.run_until_complete(run())\r\n"
  },
  {
    "path": "examples/aruba_aos_8.py",
    "content": "import asyncio\r\nimport logging\r\n\r\nimport yaml\r\n\r\nimport netdev\r\n\r\nconfig_path = 'config.yaml'\r\n\r\nlogging.basicConfig(level=logging.INFO)\r\nnetdev.logger.setLevel(logging.DEBUG)\r\n\r\n\r\nasync def task(param):\r\n    async with netdev.create(**param) as ios:\r\n        # Testing sending simple command\r\n        out = await ios.send_command(\"show ver\")\r\n        print(out)\r\n        # Testing sending configuration set\r\n        commands = [\"interface loopback\", \"exit\"]\r\n        out = await ios.send_config_set(commands)\r\n        print(out)\r\n        # Testing sending simple command with long output\r\n        out = await ios.send_command(\"show run\")\r\n        print(out)\r\n\r\n\r\nasync def run():\r\n    config = yaml.safe_load(open(config_path, 'r'))\r\n    devices = yaml.safe_load(open(config['device_list'], 'r'))\r\n    tasks = [task(dev) for dev in devices if dev['device_type'] == 'aruba_aos_8']\r\n    await asyncio.wait(tasks)\r\n\r\n\r\nloop = asyncio.get_event_loop()\r\nloop.run_until_complete(run())\r\n"
  },
  {
    "path": "examples/cisco_asa.py",
    "content": "import asyncio\r\nimport logging\r\n\r\nimport yaml\r\n\r\nimport netdev\r\n\r\nconfig_path = 'config.yaml'\r\n\r\nlogging.basicConfig(level=logging.INFO)\r\nnetdev.logger.setLevel(logging.DEBUG)\r\n\r\n\r\nasync def task(param):\r\n    async with netdev.create(**param) as asa:\r\n        # Testing sending simple command\r\n        out = await asa.send_command('show run')\r\n        print(out)\r\n        # Testing interactive dialog\r\n        out = await asa.send_command(\"copy r scp:\", pattern=r'\\[running-config\\]\\?', strip_command=False)\r\n        out += await asa.send_command(\"\\n\", pattern=r'\\[\\]\\?', strip_command=False)\r\n        out += await asa.send_command(\"\\n\", strip_command=False)\r\n        print(out)\r\n\r\n\r\nasync def run():\r\n    config = yaml.safe_load(open(config_path, 'r'))\r\n    devices = yaml.safe_load(open(config['device_list'], 'r'))\r\n    tasks = [task(dev) for dev in devices if dev['device_type'] == 'cisco_asa']\r\n    await asyncio.wait(tasks)\r\n\r\n\r\nloop = asyncio.get_event_loop()\r\nloop.run_until_complete(run())\r\n"
  },
  {
    "path": "examples/cisco_ios.py",
    "content": "import asyncio\r\nimport logging\r\n\r\nimport yaml\r\n\r\nimport netdev\r\n\r\nconfig_path = 'config.yaml'\r\n\r\nlogging.basicConfig(level=logging.INFO)\r\nnetdev.logger.setLevel(logging.DEBUG)\r\n\r\n\r\nasync def task(param):\r\n    async with netdev.create(**param) as ios:\r\n        # Testing sending simple command\r\n        out = await ios.send_command(\"show ver\")\r\n        print(out)\r\n        # Testing sending configuration set\r\n        commands = [\"line console 0\", \"exit\"]\r\n        out = await ios.send_config_set(commands)\r\n        print(out)\r\n        # Testing sending simple command with long output\r\n        out = await ios.send_command(\"show run\")\r\n        print(out)\r\n        # Testing interactive dialog\r\n        out = await ios.send_command(\"conf\", pattern=r'\\[terminal\\]\\?', strip_command=False)\r\n        out += await ios.send_command(\"term\", strip_command=False)\r\n        out += await ios.send_command(\"exit\", strip_command=False, strip_prompt=False)\r\n        print(out)\r\n\r\n\r\nasync def run():\r\n    config = yaml.safe_load(open(config_path, 'r'))\r\n    devices = yaml.safe_load(open(config['device_list'], 'r'))\r\n    tasks = [task(dev) for dev in devices if dev['device_type'] == 'cisco_ios']\r\n    await asyncio.wait(tasks)\r\n\r\n\r\nloop = asyncio.get_event_loop()\r\nloop.run_until_complete(run())\r\n"
  },
  {
    "path": "examples/cisco_iosxr.py",
    "content": "import asyncio\r\nimport logging\r\n\r\nimport yaml\r\n\r\nimport netdev\r\n\r\nconfig_path = 'config.yaml'\r\n\r\nlogging.basicConfig(level=logging.INFO)\r\nnetdev.logger.setLevel(logging.DEBUG)\r\n\r\n\r\nasync def task(param):\r\n    async with netdev.create(**param) as iosxr:\r\n        # Testing sending simple command\r\n        out = await iosxr.send_command(\"show ver\")\r\n        print(out)\r\n        # Testing sending simple command with long output\r\n        out = await iosxr.send_command(\"show run\")\r\n        print(out)\r\n        # Testing sending configuration set\r\n        commands = [\"interface loopback 0\", \"description TEST LOOPBACK\"]\r\n        out = await iosxr.send_config_set(commands, with_commit=True)\r\n        print(out)\r\n        # Testing failed commit\r\n        commands = [\"interface GigabitEthernet 0/0/0/0\", \"service-policy input 1\"]\r\n        out = await iosxr.send_config_set(commands, with_commit=False)\r\n        print(out)\r\n        try:\r\n            commands = [\"interface GigabitEthernet 0/0/0/0\", \"service-policy input 2\"]\r\n            await iosxr.send_config_set(commands)\r\n        except netdev.CommitError:\r\n            print(\"Commit Error\")\r\n\r\n\r\nasync def run():\r\n    config = yaml.safe_load(open(config_path, 'r'))\r\n    devices = yaml.safe_load(open(config['device_list'], 'r'))\r\n    tasks = [task(dev) for dev in devices if dev['device_type'] == 'cisco_ios_xr']\r\n    await asyncio.gather(*tasks)\r\n\r\n\r\nloop = asyncio.get_event_loop()\r\nloop.run_until_complete(run())\r\n"
  },
  {
    "path": "examples/cisco_nxos.py",
    "content": "import asyncio\r\nimport logging\r\n\r\nimport yaml\r\n\r\nimport netdev\r\n\r\nconfig_path = 'config.yaml'\r\n\r\nlogging.basicConfig(level=logging.INFO)\r\nnetdev.logger.setLevel(logging.DEBUG)\r\n\r\n\r\nasync def task(param):\r\n    async with netdev.create(**param) as nxos:\r\n        # Testing sending simple command\r\n        out = await nxos.send_command('show run', strip_command=True)\r\n        print(out)\r\n\r\n\r\nasync def run():\r\n    config = yaml.safe_load(open(config_path, 'r'))\r\n    devices = yaml.safe_load(open(config['device_list'], 'r'))\r\n    tasks = [task(dev) for dev in devices if dev['device_type'] == 'cisco_nxos']\r\n    await asyncio.wait(tasks)\r\n\r\n\r\nloop = asyncio.get_event_loop()\r\nloop.run_until_complete(run())\r\n"
  },
  {
    "path": "examples/cisco_sg3xx.py",
    "content": "#!/usr/bin/env python3\n\n# Import Python library\nimport asyncio, netdev\n\n# Coroutine used for the tasks\nasync def task(param):\n\n    # Create an object for the devices and open SSH connections\n    async with netdev.create(**param) as ios:\n\n        # Testing sending simple command\n        \n        # Command to send\n        cmd = \"show clock\"\n\n        # Sending command\n        output = await ios.send_command(cmd)\n\n        # Display the output\n        print(output)\n\n# Main coroutine\nasync def main():\n\n    # Parameters of the network device\n    my_device = {   'username' : 'LOGIN',\n                    'password' : 'PASSWORD',\n                    'host': 'IP_ADDRESS',\n                    'device_type': 'cisco_sg3xx',\n    }\n\n    # List of devices\n    devices = [my_device]\n    \n    # List of tasks\n    my_tasks = [task(dev) for dev in devices]\n    \n    # Starting the coroutine of the tasks\n    await asyncio.wait(my_tasks)\n\n\n# Main function call\nif __name__ == '__main__':\n\n    # Run the main coroutine\n    asyncio.run(main())\n\n    '''\n    Result:\n    ********************************************************************************\n    .14:07:35 J  Aug 28 2020\n    Time source is sntp\n    Time from Browser is disabled\n    ********************************************************************************\n\n    '''"
  },
  {
    "path": "examples/fujitsu_switch.py",
    "content": "import asyncio\r\nimport logging\r\n\r\nimport yaml\r\n\r\nimport netdev\r\n\r\nconfig_path = 'config.yaml'\r\n\r\nlogging.basicConfig(level=logging.INFO)\r\nnetdev.logger.setLevel(logging.DEBUG)\r\n\r\nasync def task(param):\r\n    async with netdev.create(**param) as fuj:\r\n        # Testing sending configuration set\r\n        out = await fuj.send_config_set(['vlan database', 'exit'])\r\n        print(out)\r\n        # Testing sending simple command\r\n        out = await fuj.send_command('show ver')\r\n        print(out)\r\n\r\n\r\nasync def run():\r\n    config = yaml.safe_load(open(config_path, 'r'))\r\n    devices = yaml.safe_load(open(config['device_list'], 'r'))\r\n    tasks = [task(dev) for dev in devices if dev['device_type'] == 'fujitsu_switch']\r\n    await asyncio.wait(tasks)\r\n\r\n\r\nloop = asyncio.get_event_loop()\r\nloop.run_until_complete(run())\r\n"
  },
  {
    "path": "examples/hp_comware.py",
    "content": "import asyncio\r\nimport logging\r\n\r\nimport yaml\r\n\r\nimport netdev\r\n\r\nconfig_path = 'config.yaml'\r\n\r\nlogging.basicConfig(level=logging.INFO)\r\nnetdev.logger.setLevel(logging.DEBUG)\r\n\r\n\r\nasync def task(param):\r\n    async with netdev.create(**param) as hp:\r\n        # Testing sending simple command\r\n        out = await hp.send_command('display ver')\r\n        print(out)\r\n        # Testing sending configuration set\r\n        commands = [\"Vlan 1\", \"quit\"]\r\n        out = await hp.send_config_set(commands)\r\n        print(out)\r\n        # Testing sending simple command with long output\r\n        out = await hp.send_command('display cur')\r\n        print(out)\r\n\r\n\r\nasync def run():\r\n    config = yaml.safe_load(open(config_path, 'r'))\r\n    devices = yaml.safe_load(open(config['device_list'], 'r'))\r\n    tasks = [task(dev) for dev in devices if dev['device_type'] == 'hp_comware']\r\n    await asyncio.wait(tasks)\r\n\r\n\r\nloop = asyncio.get_event_loop()\r\nloop.run_until_complete(run())\r\n"
  },
  {
    "path": "examples/hp_comware_limited.py",
    "content": "import asyncio\r\nimport logging\r\n\r\nimport yaml\r\n\r\nimport netdev\r\n\r\nconfig_path = 'config.yaml'\r\n\r\nlogging.basicConfig(level=logging.INFO)\r\nnetdev.logger.setLevel(logging.DEBUG)\r\n\r\n\r\nasync def task(param):\r\n    async with netdev.create(**param) as hp:\r\n        # Testing sending simple command\r\n        out = await hp.send_command('display ver')\r\n        print(out)\r\n        # Testing sending configuration set\r\n        commands = [\"Vlan 1\", \"quit\"]\r\n        out = await hp.send_config_set(commands)\r\n        print(out)\r\n        # Testing sending simple command with long output\r\n        out = await hp.send_command('display cur')\r\n        print(out)\r\n\r\n\r\nasync def run():\r\n    config = yaml.safe_load(open(config_path, 'r'))\r\n    devices = yaml.safe_load(open(config['device_list'], 'r'))\r\n    tasks = [task(dev) for dev in devices if dev['device_type'] == 'hp_comware_limited']\r\n    await asyncio.wait(tasks)\r\n\r\n\r\nloop = asyncio.get_event_loop()\r\nloop.run_until_complete(run())\r\n"
  },
  {
    "path": "examples/juniper_junos.py",
    "content": "import asyncio\r\nimport logging\r\n\r\nimport yaml\r\n\r\nimport netdev\r\n\r\nconfig_path = 'config.yaml'\r\n\r\nlogging.basicConfig(level=logging.INFO)\r\nnetdev.logger.setLevel(logging.DEBUG)\r\n\r\n\r\nasync def task(param):\r\n    async with netdev.create(**param) as junos:\r\n        # Testing sending simple command\r\n        out = await junos.send_command(\"show version\")\r\n        print(out)\r\n        # Testing sending configuration set\r\n        commands = [\"edit system\", \"edit login\"]\r\n        out = await junos.send_config_set(commands, with_commit=True)\r\n        print(out)\r\n        # Testing sending simple command with long output\r\n        out = await junos.send_command(\"show config\")\r\n        print(out)\r\n        # Testing interactive dialog\r\n        commands = [\"set system login message 123\", \"delete system login message 123\"]\r\n        out = await junos.send_config_set(commands, with_commit=False, exit_config_mode=False)\r\n        out += await junos.send_command(\"exit\", pattern=r'Exit with uncommitted changes\\?', strip_command=False)\r\n        out += await junos.send_command(\"no\", strip_command=False)\r\n        out += await junos.send_command(\"rollback 0\", strip_command=False)\r\n        out += await junos.send_command(\"exit configuration-mode\", strip_command=False)\r\n        print(out)\r\n\r\n\r\nasync def run():\r\n    config = yaml.safe_load(open(config_path, 'r'))\r\n    devices = yaml.safe_load(open(config['device_list'], 'r'))\r\n    tasks = [task(dev) for dev in devices if dev['device_type'] == 'juniper_junos']\r\n    await asyncio.wait(tasks)\r\n\r\n\r\nloop = asyncio.get_event_loop()\r\nloop.run_until_complete(run())\r\n"
  },
  {
    "path": "examples/mikrotik_routeros.py",
    "content": "import asyncio\r\nimport logging\r\n\r\nimport yaml\r\n\r\nimport netdev\r\n\r\nconfig_path = 'config.yaml'\r\n\r\nlogging.basicConfig(level=logging.INFO)\r\nnetdev.logger.setLevel(logging.DEBUG)\r\n\r\n\r\nasync def task(param):\r\n    async with netdev.create(**param) as routeros:\r\n        # Testing sending simple command\r\n        commands = ['/ip address', 'print', '/']\r\n        for cmd in commands:\r\n            print(await routeros.send_command(cmd))\r\n\r\n        # Testing sending configuration set\r\n        out = await routeros.send_config_set(commands)\r\n        print(out)\r\n\r\n\r\nasync def run():\r\n    config = yaml.safe_load(open(config_path, 'r'))\r\n    devices = yaml.safe_load(open(config['device_list'], 'r'))\r\n    tasks = [task(dev) for dev in devices if dev['device_type'] == 'mikrotik_routeros']\r\n    await asyncio.wait(tasks)\r\n\r\n\r\nloop = asyncio.get_event_loop()\r\nloop.run_until_complete(run())\r\n"
  },
  {
    "path": "examples/terminal.py",
    "content": "import asyncio\r\nimport logging\r\n\r\nimport yaml\r\n\r\nimport netdev\r\n\r\nconfig_path = 'config.yaml'\r\n\r\nlogging.basicConfig(level=logging.INFO)\r\nnetdev.logger.setLevel(logging.DEBUG)\r\n\r\n\r\nasync def task(param):\r\n    async with netdev.create(**param) as term:\r\n        # Testing sending simple command\r\n        out = await term.send_command('ls -al', strip_command=True)\r\n        print(out)\r\n        out = await term.send_command('pwd', strip_command=True)\r\n        print(out)\r\n        out = await term.send_command('echo test', strip_command=True)\r\n        print(out)\r\n\r\n\r\nasync def run():\r\n    config = yaml.safe_load(open(config_path, 'r'))\r\n    devices = yaml.safe_load(open(config['device_list'], 'r'))\r\n    tasks = [task(dev) for dev in devices if dev['device_type'] == 'terminal']\r\n    await asyncio.wait(tasks)\r\n\r\n\r\nloop = asyncio.get_event_loop()\r\nloop.run_until_complete(run())\r\n"
  },
  {
    "path": "netdev/__init__.py",
    "content": "import netdev.vendors\r\nfrom netdev.dispatcher import create, platforms\r\nfrom netdev.exceptions import DisconnectError, TimeoutError, CommitError\r\nfrom netdev.logger import logger\r\nfrom netdev.version import __author__, __author_email__, __url__, __version__\r\n\r\n__all__ = (\r\n    \"create\",\r\n    \"platforms\",\r\n    \"logger\",\r\n    \"DisconnectError\",\r\n    \"TimeoutError\",\r\n    \"CommitError\",\r\n    \"vendors\",\r\n)\r\n"
  },
  {
    "path": "netdev/dispatcher.py",
    "content": "\"\"\"\r\nFactory function for creating netdev classes\r\n\"\"\"\r\nfrom netdev.vendors import AlcatelAOS\r\nfrom netdev.vendors import AristaEOS\r\nfrom netdev.vendors import ArubaAOS6, ArubaAOS8\r\nfrom netdev.vendors import CiscoASA, CiscoIOS, CiscoIOSXR, CiscoNXOS, CiscoSG3XX\r\nfrom netdev.vendors import FujitsuSwitch\r\nfrom netdev.vendors import HPComware, HPComwareLimited\r\nfrom netdev.vendors import JuniperJunOS\r\nfrom netdev.vendors import MikrotikRouterOS\r\nfrom netdev.vendors import Terminal\r\nfrom netdev.vendors import UbiquityEdgeSwitch\r\nfrom netdev.vendors import HW1000\r\nfrom netdev.vendors import Huawei\r\n\r\n# @formatter:off\r\n# The keys of this dictionary are the supported device_types\r\nCLASS_MAPPER = {\r\n    \"alcatel_aos\": AlcatelAOS,\r\n    \"arista_eos\": AristaEOS,\r\n    \"aruba_aos_6\": ArubaAOS6,\r\n    \"aruba_aos_8\": ArubaAOS8,\r\n    \"cisco_asa\": CiscoASA,\r\n    \"cisco_ios\": CiscoIOS,\r\n    \"cisco_ios_xe\": CiscoIOS,\r\n    \"cisco_ios_xr\": CiscoIOSXR,\r\n    \"cisco_nxos\": CiscoNXOS,\r\n    \"cisco_sg3xx\": CiscoSG3XX,\r\n    \"fujitsu_switch\": FujitsuSwitch,\r\n    \"hp_comware\": HPComware,\r\n    \"hp_comware_limited\": HPComwareLimited,\r\n    \"juniper_junos\": JuniperJunOS,\r\n    \"mikrotik_routeros\": MikrotikRouterOS,\r\n    \"ubiquity_edge\": UbiquityEdgeSwitch,\r\n    \"terminal\": Terminal,\r\n    \"hw1000\": HW1000,\r\n    \"huawei\": Huawei,\r\n}\r\n\r\n# @formatter:on\r\n\r\nplatforms = list(CLASS_MAPPER.keys())\r\nplatforms.sort()\r\nplatforms_str = u\"\\n\".join(platforms)\r\n\r\n\r\ndef create(*args, **kwargs):\r\n    \"\"\"Factory function selects the proper class and creates object based on device_type\"\"\"\r\n    if kwargs[\"device_type\"] not in platforms:\r\n        raise ValueError(\r\n            \"Unsupported device_type: \"\r\n            \"currently supported platforms are: {0}\".format(platforms_str)\r\n        )\r\n    connection_class = CLASS_MAPPER[kwargs[\"device_type\"]]\r\n    return connection_class(*args, **kwargs)\r\n"
  },
  {
    "path": "netdev/exceptions.py",
    "content": "class DisconnectError(Exception):\r\n    \"\"\"AsyncSSH Disconnect Error with ip address\"\"\"\r\n\r\n    def __init__(self, ip_address, code, reason):\r\n        self.ip_address = ip_address\r\n        self.code = code\r\n        self.reason = reason\r\n        self.msg = \"Host {} Disconnect Error: {}\".format(ip_address, reason)\r\n        super().__init__(self.msg)\r\n\r\n\r\nclass TimeoutError(Exception):\r\n    \"\"\"concurrent.futures._base.TimeoutError with ip address\"\"\"\r\n\r\n    def __init__(self, ip_address):\r\n        self.ip_address = ip_address\r\n        self.msg = \"Host {} Timeout Error\".format(ip_address)\r\n        super().__init__(self.msg)\r\n\r\n\r\nclass CommitError(Exception):\r\n    \"\"\"concurrent.futures._base.TimeoutError with ip address\"\"\"\r\n\r\n    def __init__(self, ip_address, reason):\r\n        self.ip_address = ip_address\r\n        self.reason = reason\r\n        self.msg = \"Host {} Commit Error: {}\".format(ip_address, reason)\r\n        super().__init__(self.msg)\r\n"
  },
  {
    "path": "netdev/logger.py",
    "content": "\"\"\"\r\nLogging configuration for netdev\r\n\"\"\"\r\nimport logging\r\n\r\nlogger = logging.getLogger(__package__)\r\nlogger.setLevel(logging.WARNING)\r\n"
  },
  {
    "path": "netdev/vendors/__init__.py",
    "content": "from netdev.vendors.alcatel import AlcatelAOS\r\nfrom netdev.vendors.arista import AristaEOS\r\nfrom netdev.vendors.aruba import ArubaAOS8, ArubaAOS6\r\nfrom netdev.vendors.base import BaseDevice\r\nfrom netdev.vendors.cisco import CiscoNXOS, CiscoIOSXR, CiscoASA, CiscoIOS, CiscoSG3XX\r\nfrom netdev.vendors.comware_like import ComwareLikeDevice\r\nfrom netdev.vendors.fujitsu import FujitsuSwitch\r\nfrom netdev.vendors.hp import HPComware, HPComwareLimited\r\nfrom netdev.vendors.ios_like import IOSLikeDevice\r\nfrom netdev.vendors.juniper import JuniperJunOS\r\nfrom netdev.vendors.junos_like import JunOSLikeDevice\r\nfrom netdev.vendors.mikrotik import MikrotikRouterOS\r\nfrom netdev.vendors.terminal import Terminal\r\nfrom netdev.vendors.ubiquiti import UbiquityEdgeSwitch\r\nfrom netdev.vendors.infotecs import HW1000\r\nfrom netdev.vendors.huawei import Huawei\r\n\r\n__all__ = (\r\n    \"CiscoASA\",\r\n    \"CiscoIOS\",\r\n    \"CiscoIOSXR\",\r\n    \"CiscoNXOS\",\r\n    \"CiscoSG3XX\",\r\n    \"HPComware\",\r\n    \"HPComwareLimited\",\r\n    \"FujitsuSwitch\",\r\n    \"MikrotikRouterOS\",\r\n    \"JuniperJunOS\",\r\n    \"JunOSLikeDevice\",\r\n    \"AristaEOS\",\r\n    \"ArubaAOS6\",\r\n    \"ArubaAOS8\",\r\n    \"BaseDevice\",\r\n    \"IOSLikeDevice\",\r\n    \"ComwareLikeDevice\",\r\n    \"Terminal\",\r\n    \"arista\",\r\n    \"aruba\",\r\n    \"cisco\",\r\n    \"fujitsu\",\r\n    \"hp\",\r\n    \"juniper\",\r\n    \"mikrotik\",\r\n    \"UbiquityEdgeSwitch\",\r\n    \"HW1000\",\r\n    \"AlcatelAOS\",\r\n    \"Huawei\",\r\n)\r\n"
  },
  {
    "path": "netdev/vendors/alcatel/__init__.py",
    "content": "from .alcatel_aos import AlcatelAOS\n\n__all__ = [\"AlcatelAOS\"]\n"
  },
  {
    "path": "netdev/vendors/alcatel/alcatel_aos.py",
    "content": "from netdev.vendors.base import BaseDevice\nfrom netdev.logger import logger\nimport asyncio\nimport re\n\nclass AlcatelAOS(BaseDevice):\n    \"\"\"Class for working with Alcatel AOS\"\"\"\n\n\n    async def _read_until_prompt_or_pattern(self, pattern=\"\", re_flags=0):\n        \"\"\"Read until either self.base_pattern or pattern is detected. Return ALL data available\"\"\"\n        output = \"\"\n        logger.info(\"Host {}: Reading until prompt or pattern\".format(self._host))\n        if not pattern:\n            pattern = self._base_pattern\n        base_prompt_pattern = self._base_pattern\n        while True:\n            fut = self._stdout.read(self._MAX_BUFFER)\n            try:\n                output += await asyncio.wait_for(fut, self._timeout)\n            except asyncio.TimeoutError:\n                raise TimeoutError(self._host)\n            if re.search(\"\\n\" + pattern, output, flags=re_flags) or re.search(\n                \"\\n\" + base_prompt_pattern, output, flags=re_flags\n            ):\n                logger.debug(\n                    \"Host {}: Reading pattern '{}' or '{}' was found: {}\".format(\n                        self._host, pattern, base_prompt_pattern, repr(output)\n                    )\n                )\n                return output\n\n"
  },
  {
    "path": "netdev/vendors/arista/__init__.py",
    "content": "from .arista_eos import AristaEOS\r\n\r\n__all__ = [\"AristaEOS\"]\r\n"
  },
  {
    "path": "netdev/vendors/arista/arista_eos.py",
    "content": "from netdev.vendors.ios_like import IOSLikeDevice\r\n\r\n\r\nclass AristaEOS(IOSLikeDevice):\r\n    \"\"\"Class for working with Arista EOS\"\"\"\r\n\r\n    pass\r\n"
  },
  {
    "path": "netdev/vendors/aruba/__init__.py",
    "content": "from .aruba_aos_6 import ArubaAOS6\r\nfrom .aruba_aos_8 import ArubaAOS8\r\n\r\n__all__ = [\"ArubaAOS6\", \"ArubaAOS8\"]\r\n"
  },
  {
    "path": "netdev/vendors/aruba/aruba_aos_6.py",
    "content": "\"\"\"Subclass specific to Aruba AOS 6.x\"\"\"\r\n\r\nimport re\r\n\r\nfrom netdev.logger import logger\r\nfrom netdev.vendors.ios_like import IOSLikeDevice\r\n\r\n\r\nclass ArubaAOS6(IOSLikeDevice):\r\n    \"\"\"Class for working with Aruba OS 6.X\"\"\"\r\n\r\n    _disable_paging_command = \"no paging\"\r\n    \"\"\"Command for disabling paging\"\"\"\r\n\r\n    _config_exit = \"end\"\r\n    \"\"\"Command for existing from configuration mode to privilege exec\"\"\"\r\n\r\n    _config_check = \") (config\"\r\n    \"\"\"Checking string in prompt. If it's exist im prompt - we are in configuration mode\"\"\"\r\n\r\n    _pattern = r\"\\({prompt}.*?\\) (\\(.*?\\))?\\s?[{delimiters}]\"\r\n    \"\"\"Pattern for using in reading buffer. When it found processing ends\"\"\"\r\n\r\n    async def _set_base_prompt(self):\r\n        \"\"\"\r\n        Setting two important vars:\r\n\r\n            base_prompt - textual prompt in CLI (usually hostname)\r\n            base_pattern - regexp for finding the end of command. It's platform specific parameter\r\n\r\n        For Aruba AOS 6 devices base_pattern is \"(prompt) (\\(.*?\\))?\\s?[#|>]\r\n        \"\"\"\r\n        logger.info(\"Host {}: Setting base prompt\".format(self._host))\r\n        prompt = await self._find_prompt()\r\n\r\n        # Strip off trailing terminator\r\n        self._base_prompt = prompt[1:-3]\r\n        delimiters = map(re.escape, type(self)._delimiter_list)\r\n        delimiters = r\"|\".join(delimiters)\r\n        base_prompt = re.escape(self._base_prompt[:12])\r\n        pattern = type(self)._pattern\r\n        self._base_pattern = pattern.format(prompt=base_prompt, delimiters=delimiters)\r\n        logger.debug(\"Host {}: Base Prompt: {}\".format(self._host, self._base_prompt))\r\n        logger.debug(\"Host {}: Base Pattern: {}\".format(self._host, self._base_pattern))\r\n        return self._base_prompt\r\n"
  },
  {
    "path": "netdev/vendors/aruba/aruba_aos_8.py",
    "content": "\"\"\"Subclass specific to Aruba AOS 8.x\"\"\"\r\n\r\nimport re\r\n\r\nfrom netdev.logger import logger\r\nfrom netdev.vendors.ios_like import IOSLikeDevice\r\n\r\n\r\nclass ArubaAOS8(IOSLikeDevice):\r\n    \"\"\"Class for working with Aruba OS 8.X\"\"\"\r\n\r\n    _disable_paging_command = \"no paging\"\r\n    \"\"\"Command for disabling paging\"\"\"\r\n\r\n    _config_exit = \"end\"\r\n    \"\"\"Command for existing from configuration mode to privilege exec\"\"\"\r\n\r\n    _config_check = \"] (config\"\r\n    \"\"\"Checking string in prompt. If it's exist im prompt - we are in configuration mode\"\"\"\r\n\r\n    _pattern = r\"\\({prompt}.*?\\) [*^]?\\[.*?\\] (\\(.*?\\))?\\s?[{delimiters}]\"\r\n    \"\"\"Pattern for using in reading buffer. When it found processing ends\"\"\"\r\n\r\n    async def _set_base_prompt(self):\r\n        \"\"\"\r\n        Setting two important vars:\r\n\r\n            base_prompt - textual prompt in CLI (usually hostname)\r\n            base_pattern - regexp for finding the end of command. It's platform specific parameter\r\n\r\n        For Aruba AOS 8 devices base_pattern is \"(prompt) [node] (\\(.*?\\))?\\s?[#|>]\r\n        \"\"\"\r\n        logger.info(\"Host {}: Setting base prompt\".format(self._host))\r\n        prompt = await self._find_prompt()\r\n        prompt = prompt.split(\")\")[0]\r\n        # Strip off trailing terminator\r\n        self._base_prompt = prompt[1:]\r\n        delimiters = map(re.escape, type(self)._delimiter_list)\r\n        delimiters = r\"|\".join(delimiters)\r\n        base_prompt = re.escape(self._base_prompt[:12])\r\n        pattern = type(self)._pattern\r\n        self._base_pattern = pattern.format(prompt=base_prompt, delimiters=delimiters)\r\n        logger.debug(\"Host {}: Base Prompt: {}\".format(self._host, self._base_prompt))\r\n        logger.debug(\"Host {}: Base Pattern: {}\".format(self._host, self._base_pattern))\r\n        return self._base_prompt\r\n"
  },
  {
    "path": "netdev/vendors/base.py",
    "content": "\"\"\"\r\nBase Class for using in connection to network devices\r\n\r\nConnections Method are based upon AsyncSSH and should be running in asyncio loop\r\n\"\"\"\r\n\r\nimport asyncio\r\nimport re\r\n\r\nimport asyncssh\r\n\r\nfrom netdev.exceptions import TimeoutError, DisconnectError\r\nfrom netdev.logger import logger\r\n\r\n\r\nclass BaseDevice(object):\r\n    \"\"\"\r\n    Base Abstract Class for working with network devices\r\n    \"\"\"\r\n\r\n    def __init__(\r\n        self,\r\n        host=u\"\",\r\n        username=u\"\",\r\n        password=u\"\",\r\n        port=22,\r\n        device_type=u\"\",\r\n        timeout=15,\r\n        loop=None,\r\n        known_hosts=None,\r\n        local_addr=None,\r\n        client_keys=None,\r\n        passphrase=None,\r\n        tunnel=None,\r\n        pattern=None,\r\n        agent_forwarding=False,\r\n        agent_path=(),\r\n        client_version=u\"netdev\",\r\n        family=0,\r\n        kex_algs=(),\r\n        encryption_algs=(),\r\n        mac_algs=(),\r\n        compression_algs=(),\r\n        signature_algs=(),\r\n        server_host_key_algs=None,\r\n    ):\r\n        \"\"\"\r\n        Initialize base class for asynchronous working with network devices\r\n\r\n        :param host: device hostname or ip address for connection\r\n        :param username: username for logging to device\r\n        :param password: user password for logging to device\r\n        :param port: ssh port for connection. Default is 22\r\n        :param device_type: network device type\r\n        :param timeout: timeout in second for getting information from channel\r\n        :param loop: asyncio loop object\r\n        :param known_hosts: file with known hosts. Default is None (no policy). With () it will use default file\r\n        :param local_addr: local address for binding source of tcp connection\r\n        :param client_keys: path for client keys. Default in None. With () it will use default file in OS\r\n        :param passphrase: password for encrypted client keys\r\n        :param tunnel: An existing SSH connection that this new connection should be tunneled over\r\n        :param pattern: pattern for searching the end of device prompt.\r\n                Example: r\"{hostname}.*?(\\(.*?\\))?[{delimeters}]\"\r\n        :param agent_forwarding: Allow or not allow agent forward for server\r\n        :param agent_path:\r\n            The path of a UNIX domain socket to use to contact an ssh-agent\r\n            process which will perform the operations needed for client\r\n            public key authentication. If this is not specified and the environment\r\n            variable `SSH_AUTH_SOCK` is set, its value will be used as the path.\r\n            If `client_keys` is specified or this argument is explicitly set to `None`,\r\n            an ssh-agent will not be used.\r\n        :param client_version: version which advertised to ssh server\r\n        :param family:\r\n           The address family to use when creating the socket. By default,\r\n           the address family is automatically selected based on the host.\r\n        :param kex_algs:\r\n            A list of allowed key exchange algorithms in the SSH handshake,\r\n            taken from `key exchange algorithms\r\n            <https://asyncssh.readthedocs.io/en/latest/api.html#kexalgs>`_\r\n        :param encryption_algs:\r\n            A list of encryption algorithms to use during the SSH handshake,\r\n            taken from `encryption algorithms\r\n            <https://asyncssh.readthedocs.io/en/latest/api.html#encryptionalgs>`_\r\n        :param mac_algs:\r\n            A list of MAC algorithms to use during the SSH handshake, taken\r\n            from `MAC algorithms <https://asyncssh.readthedocs.io/en/latest/api.html#macalgs>`_\r\n        :param compression_algs:\r\n            A list of compression algorithms to use during the SSH handshake,\r\n            taken from `compression algorithms\r\n            <https://asyncssh.readthedocs.io/en/latest/api.html#compressionalgs>`_, or\r\n            `None` to disable compression\r\n        :param signature_algs:\r\n            A list of public key signature algorithms to use during the SSH\r\n            handshake, taken from `signature algorithms\r\n            <https://asyncssh.readthedocs.io/en/latest/api.html#signaturealgs>`_\r\n        :param server_host_key_algs:\r\n            A list of server host key algorithms to allow during the SSH handshake,\r\n            taken from server host key algorithms.\r\n            https://asyncssh.readthedocs.io/en/latest/api.html#publickeyalgs\r\n        \r\n\r\n        :type host: str\r\n        :type username: str\r\n        :type password: str\r\n        :type port: int\r\n        :type device_type: str\r\n        :type timeout: int\r\n        :type known_hosts:\r\n            *see* `SpecifyingKnownHosts\r\n            <https://asyncssh.readthedocs.io/en/latest/api.html#specifyingknownhosts>`_\r\n        :type loop: :class:`AbstractEventLoop <asyncio.AbstractEventLoop>`\r\n        :type pattern: str\r\n        :type tunnel: :class:`BaseDevice <netdev.vendors.BaseDevice>`\r\n        :type family:\r\n            :class:`socket.AF_UNSPEC` or :class:`socket.AF_INET` or :class:`socket.AF_INET6`\r\n        :type local_addr: tuple(str, int)\r\n        :type client_keys:\r\n            *see* `SpecifyingPrivateKeys\r\n            <https://asyncssh.readthedocs.io/en/latest/api.html#specifyingprivatekeys>`_\r\n        :type passphrase: str\r\n        :type agent_path: str\r\n        :type agent_forwarding: bool\r\n        :type client_version: str\r\n        :type kex_algs: list[str]\r\n        :type encryption_algs: list[str]\r\n        :type mac_algs: list[str]\r\n        :type compression_algs: list[str]\r\n        :type signature_algs: list[str]\r\n        :type server_host_key_algs: list[str]\r\n        \"\"\"\r\n        if host:\r\n            self._host = host\r\n        else:\r\n            raise ValueError(\"Host must be set\")\r\n        self._port = int(port)\r\n        self._device_type = device_type\r\n        self._timeout = timeout\r\n        if loop is None:\r\n            self._loop = asyncio.get_event_loop()\r\n        else:\r\n            self._loop = loop\r\n\r\n        \"\"\"Convert needed connect params to a dictionary for simplicity\"\"\"\r\n        self._connect_params_dict = {\r\n            \"host\": self._host,\r\n            \"port\": self._port,\r\n            \"username\": username,\r\n            \"password\": password,\r\n            \"known_hosts\": known_hosts,\r\n            \"local_addr\": local_addr,\r\n            \"client_keys\": client_keys,\r\n            \"passphrase\": passphrase,\r\n            \"tunnel\": tunnel,\r\n            \"agent_forwarding\": agent_forwarding,\r\n            \"family\": family,\r\n            \"agent_path\": agent_path,\r\n            \"client_version\": client_version,\r\n            \"kex_algs\": kex_algs,\r\n            \"encryption_algs\": encryption_algs,\r\n            \"mac_algs\": mac_algs,\r\n            \"compression_algs\": compression_algs,\r\n            \"signature_algs\": signature_algs,\r\n        }\r\n\r\n        if pattern is not None:\r\n            self._pattern = pattern\r\n            \r\n        \"\"\"\r\n        A list of server host key algorithms to use instead of the default of \r\n        those present in known_hosts when performing the SSH handshake. This should only be set,\r\n        when the user sets it.\r\n        \"\"\"\r\n        if server_host_key_algs is not None:\r\n            self._connect_params_dict['server_host_key_algs'] = server_host_key_algs\r\n\r\n        # Filling internal vars\r\n        self._stdin = self._stdout = self._stderr = self._conn = None\r\n        self._base_prompt = self._base_pattern = \"\"\r\n        self._MAX_BUFFER = 65535\r\n        self._ansi_escape_codes = False\r\n\r\n    _delimiter_list = [\">\", \"#\"]\r\n    \"\"\"All this characters will stop reading from buffer. It mean the end of device prompt\"\"\"\r\n\r\n    _pattern = r\"{prompt}.*?(\\(.*?\\))?[{delimiters}]\"\r\n    \"\"\"Pattern for using in reading buffer. When it found processing ends\"\"\"\r\n\r\n    _disable_paging_command = \"terminal length 0\"\r\n    \"\"\"Command for disabling paging\"\"\"\r\n\r\n    @property\r\n    def base_prompt(self):\r\n        \"\"\"Returning base prompt for this network device\"\"\"\r\n        return self._base_prompt\r\n\r\n    async def __aenter__(self):\r\n        \"\"\"Async Context Manager\"\"\"\r\n        await self.connect()\r\n        return self\r\n\r\n    async def __aexit__(self, exc_type, exc_val, exc_tb):\r\n        \"\"\"Async Context Manager\"\"\"\r\n        await self.disconnect()\r\n\r\n    async def connect(self):\r\n        \"\"\"\r\n        Basic asynchronous connection method\r\n\r\n        It connects to device and makes some preparation steps for working.\r\n        Usual using 3 functions:\r\n\r\n        * _establish_connection() for connecting to device\r\n        * _set_base_prompt() for finding and setting device prompt\r\n        * _disable_paging() for non interactive output in commands\r\n        \"\"\"\r\n        logger.info(\"Host {}: Trying to connect to the device\".format(self._host))\r\n        await self._establish_connection()\r\n        await self._set_base_prompt()\r\n        await self._disable_paging()\r\n        logger.info(\"Host {}: Has connected to the device\".format(self._host))\r\n\r\n    async def _establish_connection(self):\r\n        \"\"\"Establishing SSH connection to the network device\"\"\"\r\n        logger.info(\r\n            \"Host {}: Establishing connection to port {}\".format(self._host, self._port)\r\n        )\r\n        output = \"\"\r\n        # initiate SSH connection\r\n        fut = asyncssh.connect(**self._connect_params_dict)\r\n        try:\r\n            self._conn = await asyncio.wait_for(fut, self._timeout)\r\n        except asyncssh.DisconnectError as e:\r\n            raise DisconnectError(self._host, e.code, e.reason)\r\n        except asyncio.TimeoutError:\r\n            raise TimeoutError(self._host)\r\n        self._stdin, self._stdout, self._stderr = await self._conn.open_session(\r\n            term_type=\"Dumb\", term_size=(200, 24)\r\n        )\r\n        logger.info(\"Host {}: Connection is established\".format(self._host))\r\n        # Flush unnecessary data\r\n        delimiters = map(re.escape, type(self)._delimiter_list)\r\n        delimiters = r\"|\".join(delimiters)\r\n        output = await self._read_until_pattern(delimiters)\r\n        logger.debug(\r\n            \"Host {}: Establish Connection Output: {}\".format(self._host, repr(output))\r\n        )\r\n        return output\r\n\r\n    async def _set_base_prompt(self):\r\n        \"\"\"\r\n        Setting two important vars:\r\n\r\n            base_prompt - textual prompt in CLI (usually hostname)\r\n            base_pattern - regexp for finding the end of command. It's platform specific parameter\r\n\r\n        For Cisco devices base_pattern is \"prompt(\\(.*?\\))?[#|>]\r\n        \"\"\"\r\n        logger.info(\"Host {}: Setting base prompt\".format(self._host))\r\n        prompt = await self._find_prompt()\r\n\r\n        # Strip off trailing terminator\r\n        self._base_prompt = prompt[:-1]\r\n        delimiters = map(re.escape, type(self)._delimiter_list)\r\n        delimiters = r\"|\".join(delimiters)\r\n        base_prompt = re.escape(self._base_prompt[:12])\r\n        pattern = type(self)._pattern\r\n        self._base_pattern = pattern.format(prompt=base_prompt, delimiters=delimiters)\r\n        logger.debug(\"Host {}: Base Prompt: {}\".format(self._host, self._base_prompt))\r\n        logger.debug(\"Host {}: Base Pattern: {}\".format(self._host, self._base_pattern))\r\n        return self._base_prompt\r\n\r\n    async def _disable_paging(self):\r\n        \"\"\"Disable paging method\"\"\"\r\n        logger.info(\"Host {}: Trying to disable paging\".format(self._host))\r\n        command = type(self)._disable_paging_command\r\n        command = self._normalize_cmd(command)\r\n        logger.debug(\r\n            \"Host {}: Disable paging command: {}\".format(self._host, repr(command))\r\n        )\r\n        self._stdin.write(command)\r\n        output = await self._read_until_prompt()\r\n        logger.debug(\r\n            \"Host {}: Disable paging output: {}\".format(self._host, repr(output))\r\n        )\r\n        if self._ansi_escape_codes:\r\n            output = self._strip_ansi_escape_codes(output)\r\n        return output\r\n\r\n    async def _find_prompt(self):\r\n        \"\"\"Finds the current network device prompt, last line only\"\"\"\r\n        logger.info(\"Host {}: Finding prompt\".format(self._host))\r\n        self._stdin.write(self._normalize_cmd(\"\\n\"))\r\n        prompt = \"\"\r\n        delimiters = map(re.escape, type(self)._delimiter_list)\r\n        delimiters = r\"|\".join(delimiters)\r\n        prompt = await self._read_until_pattern(delimiters)\r\n        prompt = prompt.strip()\r\n        if self._ansi_escape_codes:\r\n            prompt = self._strip_ansi_escape_codes(prompt)\r\n        if not prompt:\r\n            raise ValueError(\r\n                \"Host {}: Unable to find prompt: {}\".format(self._host, repr(prompt))\r\n            )\r\n        logger.debug(\"Host {}: Found Prompt: {}\".format(self._host, repr(prompt)))\r\n        return prompt\r\n\r\n    async def send_command(\r\n        self,\r\n        command_string,\r\n        pattern=\"\",\r\n        re_flags=0,\r\n        strip_command=True,\r\n        strip_prompt=True,\r\n    ):\r\n        \"\"\"\r\n        Sending command to device (support interactive commands with pattern)\r\n\r\n        :param str command_string: command for executing basically in privilege mode\r\n        :param str pattern: pattern for waiting in output (for interactive commands)\r\n        :param re.flags re_flags: re flags for pattern\r\n        :param bool strip_command: True or False for stripping command from output\r\n        :param bool strip_prompt: True or False for stripping ending device prompt\r\n        :return: The output of the command\r\n        \"\"\"\r\n        logger.info(\"Host {}: Sending command\".format(self._host))\r\n        output = \"\"\r\n        command_string = self._normalize_cmd(command_string)\r\n        logger.debug(\r\n            \"Host {}: Send command: {}\".format(self._host, repr(command_string))\r\n        )\r\n        self._stdin.write(command_string)\r\n        output = await self._read_until_prompt_or_pattern(pattern, re_flags)\r\n\r\n        # Some platforms have ansi_escape codes\r\n        if self._ansi_escape_codes:\r\n            output = self._strip_ansi_escape_codes(output)\r\n        output = self._normalize_linefeeds(output)\r\n        if strip_prompt:\r\n            output = self._strip_prompt(output)\r\n        if strip_command:\r\n            output = self._strip_command(command_string, output)\r\n\r\n        logger.debug(\r\n            \"Host {}: Send command output: {}\".format(self._host, repr(output))\r\n        )\r\n        return output\r\n\r\n    def _strip_prompt(self, a_string):\r\n        \"\"\"Strip the trailing router prompt from the output\"\"\"\r\n        logger.info(\"Host {}: Stripping prompt\".format(self._host))\r\n        response_list = a_string.split(\"\\n\")\r\n        last_line = response_list[-1]\r\n        if self._base_prompt in last_line:\r\n            return \"\\n\".join(response_list[:-1])\r\n        else:\r\n            return a_string\r\n\r\n    async def _read_until_prompt(self):\r\n        \"\"\"Read channel until self.base_pattern detected. Return ALL data available\"\"\"\r\n        return await self._read_until_pattern(self._base_pattern)\r\n\r\n    async def _read_until_pattern(self, pattern=\"\", re_flags=0):\r\n        \"\"\"Read channel until pattern detected. Return ALL data available\"\"\"\r\n        output = \"\"\r\n        logger.info(\"Host {}: Reading until pattern\".format(self._host))\r\n        if not pattern:\r\n            pattern = self._base_pattern\r\n        logger.debug(\"Host {}: Reading pattern: {}\".format(self._host, pattern))\r\n        while True:\r\n            fut = self._stdout.read(self._MAX_BUFFER)\r\n            try:\r\n                output += await asyncio.wait_for(fut, self._timeout)\r\n            except asyncio.TimeoutError:\r\n                raise TimeoutError(self._host)\r\n            if re.search(pattern, output, flags=re_flags):\r\n                logger.debug(\r\n                    \"Host {}: Reading pattern '{}' was found: {}\".format(\r\n                        self._host, pattern, repr(output)\r\n                    )\r\n                )\r\n                return output\r\n\r\n    async def _read_until_prompt_or_pattern(self, pattern=\"\", re_flags=0):\r\n        \"\"\"Read until either self.base_pattern or pattern is detected. Return ALL data available\"\"\"\r\n        output = \"\"\r\n        logger.info(\"Host {}: Reading until prompt or pattern\".format(self._host))\r\n        if not pattern:\r\n            pattern = self._base_pattern\r\n        base_prompt_pattern = self._base_pattern\r\n        while True:\r\n            fut = self._stdout.read(self._MAX_BUFFER)\r\n            try:\r\n                output += await asyncio.wait_for(fut, self._timeout)\r\n            except asyncio.TimeoutError:\r\n                raise TimeoutError(self._host)\r\n            if re.search(pattern, output, flags=re_flags) or re.search(\r\n                base_prompt_pattern, output, flags=re_flags\r\n            ):\r\n                logger.debug(\r\n                    \"Host {}: Reading pattern '{}' or '{}' was found: {}\".format(\r\n                        self._host, pattern, base_prompt_pattern, repr(output)\r\n                    )\r\n                )\r\n                return output\r\n\r\n    @staticmethod\r\n    def _strip_backspaces(output):\r\n        \"\"\"Strip any backspace characters out of the output\"\"\"\r\n        backspace_char = \"\\x08\"\r\n        return output.replace(backspace_char, \"\")\r\n\r\n    @staticmethod\r\n    def _strip_command(command_string, output):\r\n        \"\"\"\r\n        Strip command_string from output string\r\n\r\n        Cisco IOS adds backspaces into output for long commands (i.e. for commands that line wrap)\r\n        \"\"\"\r\n        logger.info(\"Stripping command\")\r\n        backspace_char = \"\\x08\"\r\n\r\n        # Check for line wrap (remove backspaces)\r\n        if backspace_char in output:\r\n            output = output.replace(backspace_char, \"\")\r\n            output_lines = output.split(\"\\n\")\r\n            new_output = output_lines[1:]\r\n            return \"\\n\".join(new_output)\r\n        else:\r\n            command_length = len(command_string)\r\n            return output[command_length:]\r\n\r\n    @staticmethod\r\n    def _normalize_linefeeds(a_string):\r\n        \"\"\"Convert '\\r\\r\\n','\\r\\n', '\\n\\r' to '\\n\"\"\"\r\n        newline = re.compile(r\"(\\r\\r\\n|\\r\\n|\\n\\r)\")\r\n        return newline.sub(\"\\n\", a_string)\r\n\r\n    @staticmethod\r\n    def _normalize_cmd(command):\r\n        \"\"\"Normalize CLI commands to have a single trailing newline\"\"\"\r\n        command = command.rstrip(\"\\n\")\r\n        command += \"\\n\"\r\n        return command\r\n\r\n    async def send_config_set(self, config_commands=None):\r\n        \"\"\"\r\n        Sending configuration commands to device\r\n\r\n        The commands will be executed one after the other.\r\n\r\n        :param list config_commands: iterable string list with commands for applying to network device\r\n        :return: The output of this commands\r\n        \"\"\"\r\n        logger.info(\"Host {}: Sending configuration settings\".format(self._host))\r\n        if config_commands is None:\r\n            return \"\"\r\n        if not hasattr(config_commands, \"__iter__\"):\r\n            raise ValueError(\r\n                \"Host {}: Invalid argument passed into send_config_set\".format(\r\n                    self._host\r\n                )\r\n            )\r\n\r\n        # Send config commands\r\n        logger.debug(\"Host {}: Config commands: {}\".format(self._host, config_commands))\r\n        output = \"\"\r\n        for cmd in config_commands:\r\n            self._stdin.write(self._normalize_cmd(cmd))\r\n            output += await self._read_until_prompt()\r\n\r\n        if self._ansi_escape_codes:\r\n            output = self._strip_ansi_escape_codes(output)\r\n\r\n        output = self._normalize_linefeeds(output)\r\n        logger.debug(\r\n            \"Host {}: Config commands output: {}\".format(self._host, repr(output))\r\n        )\r\n        return output\r\n\r\n    @staticmethod\r\n    def _strip_ansi_escape_codes(string_buffer):\r\n        \"\"\"\r\n        Remove some ANSI ESC codes from the output\r\n\r\n        http://en.wikipedia.org/wiki/ANSI_escape_code\r\n\r\n        Note: this does not capture ALL possible ANSI Escape Codes only the ones\r\n        I have encountered\r\n\r\n        Current codes that are filtered:\r\n        ESC = '\\x1b' or chr(27)\r\n        ESC = is the escape character [^ in hex ('\\x1b')\r\n        ESC[24;27H   Position cursor\r\n        ESC[?25h     Show the cursor\r\n        ESC[E        Next line (HP does ESC-E)\r\n        ESC[K        Erase line. Clear from cursor to end of screen\r\n        ESC[2K       Erase line\r\n        ESC[1;24r    Enable scrolling from start to row end\r\n        ESC7         Save cursor position\r\n        ESC[r        Scroll all screen\r\n        ESC8         Restore cursor position\r\n        ESC[nA       Move cursor up to n cells\r\n        ESC[nB       Move cursor down to n cells\r\n\r\n        require:\r\n            HP ProCurve\r\n            F5 LTM's\r\n            Mikrotik\r\n        \"\"\"\r\n        logger.info(\"Stripping ansi escape codes\")\r\n        logger.debug(\"Unstripped output: {}\".format(repr(string_buffer)))\r\n\r\n        code_save_cursor = chr(27) + r\"7\"\r\n        code_scroll_screen = chr(27) + r\"\\[r\"\r\n        code_restore_cursor = chr(27) + r\"8\"\r\n        code_cursor_up = chr(27) + r\"\\[\\d+A\"\r\n        code_cursor_down = chr(27) + r\"\\[\\d+B\"\r\n\r\n        code_position_cursor = chr(27) + r\"\\[\\d+;\\d+H\"\r\n        code_show_cursor = chr(27) + r\"\\[\\?25h\"\r\n        code_next_line = chr(27) + r\"E\"\r\n        code_erase_line_from_cursor = chr(27) + r\"\\[K\"\r\n        code_erase_line = chr(27) + r\"\\[2K\"\r\n        code_enable_scroll = chr(27) + r\"\\[\\d+;\\d+r\"\r\n\r\n        code_set = [\r\n            code_save_cursor,\r\n            code_scroll_screen,\r\n            code_restore_cursor,\r\n            code_cursor_up,\r\n            code_cursor_down,\r\n            code_position_cursor,\r\n            code_show_cursor,\r\n            code_erase_line,\r\n            code_erase_line_from_cursor,\r\n            code_enable_scroll,\r\n        ]\r\n\r\n        output = string_buffer\r\n        for ansi_esc_code in code_set:\r\n            output = re.sub(ansi_esc_code, \"\", output)\r\n\r\n        # CODE_NEXT_LINE must substitute with '\\n'\r\n        output = re.sub(code_next_line, \"\\n\", output)\r\n\r\n        logger.debug(\"Stripped output: {}\".format(repr(output)))\r\n\r\n        return output\r\n\r\n    async def _cleanup(self):\r\n        \"\"\" Any needed cleanup before closing connection \"\"\"\r\n        logger.info(\"Host {}: Cleanup session\".format(self._host))\r\n        pass\r\n\r\n    async def disconnect(self):\r\n        \"\"\" Gracefully close the SSH connection \"\"\"\r\n        logger.info(\"Host {}: Disconnecting\".format(self._host))\r\n        await self._cleanup()\r\n        self._conn.close()\r\n        await self._conn.wait_closed()\r\n"
  },
  {
    "path": "netdev/vendors/cisco/__init__.py",
    "content": "from .cisco_asa import CiscoASA\r\nfrom .cisco_ios import CiscoIOS\r\nfrom .cisco_iosxr import CiscoIOSXR\r\nfrom .cisco_nxos import CiscoNXOS\r\nfrom .cisco_sg3xx import CiscoSG3XX\r\n\r\n__all__ = [\"CiscoIOS\", \"CiscoIOSXR\", \"CiscoASA\", \"CiscoNXOS\", \"CiscoSG3XX\"]\r\n"
  },
  {
    "path": "netdev/vendors/cisco/cisco_asa.py",
    "content": "\"\"\"Subclass specific to Cisco ASA\"\"\"\r\n\r\nimport re\r\n\r\nfrom netdev.logger import logger\r\nfrom netdev.vendors.ios_like import IOSLikeDevice\r\n\r\n\r\nclass CiscoASA(IOSLikeDevice):\r\n    \"\"\"Class for working with Cisco ASA\"\"\"\r\n\r\n    def __init__(self, *args, **kwargs):\r\n        \"\"\"\r\n        Initialize class for asynchronous working with network devices\r\n\r\n        :param str host: device hostname or ip address for connection\r\n        :param str username: username for logging to device\r\n        :param str password: user password for logging to device\r\n        :param str secret: secret password for privilege mode\r\n        :param int port: ssh port for connection. Default is 22\r\n        :param str device_type: network device type\r\n        :param known_hosts: file with known hosts. Default is None (no policy). With () it will use default file\r\n        :param str local_addr: local address for binding source of tcp connection\r\n        :param client_keys: path for client keys. Default in None. With () it will use default file in OS\r\n        :param str passphrase: password for encrypted client keys\r\n        :param float timeout: timeout in second for getting information from channel\r\n        :param loop: asyncio loop object\r\n        \"\"\"\r\n        super().__init__(*args, **kwargs)\r\n        self._multiple_mode = False\r\n\r\n    _disable_paging_command = \"terminal pager 0\"\r\n\r\n    @property\r\n    def multiple_mode(self):\r\n        \"\"\" Returning Bool True if ASA in multiple mode\"\"\"\r\n        return self._multiple_mode\r\n\r\n    async def connect(self):\r\n        \"\"\"\r\n        Async Connection method\r\n\r\n        Using 5 functions:\r\n\r\n        * _establish_connection() for connecting to device\r\n        * _set_base_prompt() for finding and setting device prompt\r\n        * _enable() for getting privilege exec mode\r\n        * _disable_paging() for non interact output in commands\r\n        *  _check_multiple_mode() for checking multiple mode in ASA\r\n        \"\"\"\r\n        logger.info(\"Host {}: trying to connect to the device\".format(self._host))\r\n        await self._establish_connection()\r\n        await self._set_base_prompt()\r\n        await self.enable_mode()\r\n        await self._disable_paging()\r\n        await self._check_multiple_mode()\r\n        logger.info(\"Host {}: Has connected to the device\".format(self._host))\r\n\r\n    async def _set_base_prompt(self):\r\n        \"\"\"\r\n        Setting two important vars for ASA\r\n            base_prompt - textual prompt in CLI (usually hostname)\r\n            base_pattern - regexp for finding the end of command. IT's platform specific parameter\r\n\r\n        For ASA devices base_pattern is \"prompt([\\/\\w]+)?(\\(.*?\\))?[#|>]\r\n        \"\"\"\r\n        logger.info(\"Host {}: Setting base prompt\".format(self._host))\r\n        prompt = await self._find_prompt()\r\n        # Cut off prompt from \"prompt/context/other\" if it exists\r\n        # If not we get all prompt\r\n        prompt = prompt[:-1].split(\"/\")\r\n        prompt = prompt[0]\r\n        self._base_prompt = prompt\r\n        delimiters = map(re.escape, type(self)._delimiter_list)\r\n        delimiters = r\"|\".join(delimiters)\r\n        base_prompt = re.escape(self._base_prompt[:12])\r\n        pattern = type(self)._pattern\r\n        self._base_pattern = pattern.format(prompt=base_prompt, delimiters=delimiters)\r\n        logger.debug(\"Host {}: Base Prompt: {}\".format(self._host, self._base_prompt))\r\n        logger.debug(\"Host {}: Base Pattern: {}\".format(self._host, self._base_pattern))\r\n        return self._base_prompt\r\n\r\n    async def _check_multiple_mode(self):\r\n        \"\"\"Check mode multiple. If mode is multiple we adding info about contexts\"\"\"\r\n        logger.info(\"Host {}:Checking multiple mode\".format(self._host))\r\n        out = await self.send_command(\"show mode\")\r\n        if \"multiple\" in out:\r\n            self._multiple_mode = True\r\n\r\n        logger.debug(\r\n            \"Host {}: Multiple mode: {}\".format(self._host, self._multiple_mode)\r\n        )\r\n"
  },
  {
    "path": "netdev/vendors/cisco/cisco_ios.py",
    "content": "from netdev.vendors.ios_like import IOSLikeDevice\r\n\r\n\r\nclass CiscoIOS(IOSLikeDevice):\r\n    \"\"\"Class for working with Cisco IOS/IOS XE\"\"\"\r\n\r\n    pass\r\n"
  },
  {
    "path": "netdev/vendors/cisco/cisco_iosxr.py",
    "content": "from netdev.exceptions import CommitError\r\nfrom netdev.logger import logger\r\nfrom netdev.vendors.ios_like import IOSLikeDevice\r\n\r\n\r\nclass CiscoIOSXR(IOSLikeDevice):\r\n    \"\"\"Class for working with Cisco IOS XR\"\"\"\r\n\r\n    _commit_command = \"commit\"\r\n    \"\"\"Command for committing changes\"\"\"\r\n\r\n    _commit_comment_command = \"commit comment {}\"\r\n    \"\"\"Command for committing changes with comment\"\"\"\r\n\r\n    _abort_command = \"abort\"\r\n    \"\"\"Command for aborting all changes and exit to privilege mode\"\"\"\r\n\r\n    _show_config_failed = \"show configuration failed\"\r\n    \"\"\"Command for showing the reason of failed commit\"\"\"\r\n\r\n    _show_commit_changes = \"show configuration commit changes\"\r\n    \"\"\"Command for showing the other commit which have occurred during our session\"\"\"\r\n\r\n    async def send_config_set(\r\n        self,\r\n        config_commands=None,\r\n        with_commit=True,\r\n        commit_comment=\"\",\r\n        exit_config_mode=True,\r\n    ):\r\n        \"\"\"\r\n        Sending configuration commands to device\r\n        By default automatically exits/enters configuration mode.\r\n\r\n        :param list config_commands: iterable string list with commands for applying to network devices in system view\r\n        :param bool with_commit: if true it commit all changes after applying all config_commands\r\n        :param string commit_comment: message for configuration commit\r\n        :param bool exit_config_mode: If true it will quit from configuration mode automatically\r\n        :return: The output of these commands\r\n        \"\"\"\r\n\r\n        if config_commands is None:\r\n            return \"\"\r\n\r\n        # Send config commands\r\n        output = await self.config_mode()\r\n        output += await super(IOSLikeDevice, self).send_config_set(\r\n            config_commands=config_commands\r\n        )\r\n        if with_commit:\r\n            commit = type(self)._commit_command\r\n            if commit_comment:\r\n                commit = type(self)._commit_comment_command.format(commit_comment)\r\n\r\n            self._stdin.write(self._normalize_cmd(commit))\r\n            output += await self._read_until_prompt_or_pattern(\r\n                r\"Do you wish to proceed with this commit anyway\\?\"\r\n            )\r\n            if \"Failed to commit\" in output:\r\n                show_config_failed = type(self)._show_config_failed\r\n                reason = await self.send_command(\r\n                    self._normalize_cmd(show_config_failed)\r\n                )\r\n                raise CommitError(self._host, reason)\r\n            if \"One or more commits have occurred\" in output:\r\n                show_commit_changes = type(self)._show_commit_changes\r\n                self._stdin.write(self._normalize_cmd(\"no\"))\r\n                reason = await self.send_command(\r\n                    self._normalize_cmd(show_commit_changes)\r\n                )\r\n                raise CommitError(self._host, reason)\r\n\r\n        if exit_config_mode:\r\n            output += await self.exit_config_mode()\r\n\r\n        output = self._normalize_linefeeds(output)\r\n        logger.debug(\r\n            \"Host {}: Config commands output: {}\".format(self._host, repr(output))\r\n        )\r\n        return output\r\n\r\n    async def exit_config_mode(self):\r\n        \"\"\"Exit from configuration mode\"\"\"\r\n        logger.info(\"Host {}: Exiting from configuration mode\".format(self._host))\r\n        output = \"\"\r\n        exit_config = type(self)._config_exit\r\n        if await self.check_config_mode():\r\n            self._stdin.write(self._normalize_cmd(exit_config))\r\n            output = await self._read_until_prompt_or_pattern(\r\n                r\"Uncommitted changes found\"\r\n            )\r\n            if \"Uncommitted changes found\" in output:\r\n                self._stdin.write(self._normalize_cmd(\"no\"))\r\n                output += await self._read_until_prompt()\r\n            if await self.check_config_mode():\r\n                raise ValueError(\"Failed to exit from configuration mode\")\r\n        return output\r\n\r\n    async def _cleanup(self):\r\n        \"\"\" Any needed cleanup before closing connection \"\"\"\r\n        abort = type(self)._abort_command\r\n        abort = self._normalize_cmd(abort)\r\n        self._stdin.write(abort)\r\n        logger.info(\"Host {}: Cleanup session\".format(self._host))\r\n"
  },
  {
    "path": "netdev/vendors/cisco/cisco_nxos.py",
    "content": "import re\r\n\r\nfrom netdev.vendors.ios_like import IOSLikeDevice\r\n\r\n\r\nclass CiscoNXOS(IOSLikeDevice):\r\n    \"\"\"Class for working with Cisco Nexus/NX-OS\"\"\"\r\n\r\n    @staticmethod\r\n    def _normalize_linefeeds(a_string):\r\n        \"\"\"\r\n        Convert '\\r\\n' or '\\r\\r\\n' to '\\n, and remove extra '\\r's in the text\r\n        \"\"\"\r\n        newline = re.compile(r\"(\\r\\r\\n|\\r\\n)\")\r\n\r\n        return newline.sub(\"\\n\", a_string).replace(\"\\r\", \"\")\r\n"
  },
  {
    "path": "netdev/vendors/cisco/cisco_sg3xx.py",
    "content": "\"\"\"Subclass specific to Cisco SG3XX\"\"\"\n\nfrom netdev.vendors.ios_like import IOSLikeDevice\n\nclass CiscoSG3XX(IOSLikeDevice):\n    \"\"\"Class for working with Cisco SG3XX\"\"\"\n\n    def __init__(self, *args, **kwargs):\n        \"\"\"\n        Initialize class for asynchronous working with network devices\n\n        :param str host: device hostname or ip address for connection\n        :param str username: username for logging to device\n        :param str password: user password for logging to device\n        :param str secret: secret password for privilege mode\n        :param int port: ssh port for connection. Default is 22\n        :param str device_type: network device type\n        :param known_hosts: file with known hosts. Default is None (no policy). With () it will use default file\n        :param str local_addr: local address for binding source of tcp connection\n        :param client_keys: path for client keys. Default in None. With () it will use default file in OS\n        :param str passphrase: password for encrypted client keys\n        :param float timeout: timeout in second for getting information from channel\n        :param loop: asyncio loop object\n        \"\"\"\n        super().__init__(*args, **kwargs)\n        self._ansi_escape_codes = True\n\n    _disable_paging_command = \"terminal datadump\"\n\n\n"
  },
  {
    "path": "netdev/vendors/comware_like.py",
    "content": "\"\"\"\r\nComwareLikeDevice Class is abstract class for using in HP Comware like devices\r\n\r\nConnection Method are based upon AsyncSSH and should be running in asyncio loop\r\n\"\"\"\r\n\r\nimport re\r\n\r\nfrom netdev.logger import logger\r\nfrom netdev.vendors.base import BaseDevice\r\n\r\n\r\nclass ComwareLikeDevice(BaseDevice):\r\n    \"\"\"\r\n    This Class for working with hp comware like devices\r\n\r\n    HP Comware like devices having several concepts:\r\n\r\n    * user exec or user view. This mode is using for getting information from device\r\n    * system view. This mode is using for configuration system\r\n    \"\"\"\r\n\r\n    _delimiter_list = [\">\", \"]\"]\r\n    \"\"\"All this characters will stop reading from buffer. It mean the end of device prompt\"\"\"\r\n\r\n    _delimiter_left_list = [\"<\", \"[\"]\r\n    \"\"\"Begging prompt characters. Prompt must contain it\"\"\"\r\n\r\n    _pattern = r\"[{delimiter_left}]{prompt}[\\-\\w]*[{delimiter_right}]\"\r\n    \"\"\"Pattern for using in reading buffer. When it found processing ends\"\"\"\r\n\r\n    _disable_paging_command = \"screen-length disable\"\r\n    \"\"\"Command for disabling paging\"\"\"\r\n\r\n    _system_view_enter = \"system-view\"\r\n    \"\"\"Command for entering to system view\"\"\"\r\n\r\n    _system_view_exit = \"return\"\r\n    \"\"\"Command for existing from system view to user view\"\"\"\r\n\r\n    _system_view_check = \"]\"\r\n    \"\"\"Checking string in prompt. If it's exist im prompt - we are in system view\"\"\"\r\n\r\n    async def _set_base_prompt(self):\r\n        \"\"\"\r\n        Setting two important vars\r\n            base_prompt - textual prompt in CLI (usually hostname)\r\n            base_pattern - regexp for finding the end of command. IT's platform specific parameter\r\n\r\n        For Comware devices base_pattern is \"[\\]|>]prompt(\\-\\w+)?[\\]|>]\r\n        \"\"\"\r\n        logger.info(\"Host {}: Setting base prompt\".format(self._host))\r\n        prompt = await self._find_prompt()\r\n        # Strip off trailing terminator\r\n        self._base_prompt = prompt[1:-1]\r\n        delimiter_right = map(re.escape, type(self)._delimiter_list)\r\n        delimiter_right = r\"|\".join(delimiter_right)\r\n        delimiter_left = map(re.escape, type(self)._delimiter_left_list)\r\n        delimiter_left = r\"|\".join(delimiter_left)\r\n        base_prompt = re.escape(self._base_prompt[:12])\r\n        pattern = type(self)._pattern\r\n        self._base_pattern = pattern.format(\r\n            delimiter_left=delimiter_left,\r\n            prompt=base_prompt,\r\n            delimiter_right=delimiter_right,\r\n        )\r\n        logger.debug(\"Host {}: Base Prompt: {}\".format(self._host, self._base_prompt))\r\n        logger.debug(\"Host {}: Base Pattern: {}\".format(self._host, self._base_pattern))\r\n        return self._base_prompt\r\n\r\n    async def _check_system_view(self):\r\n        \"\"\"Check if we are in system view. Return boolean\"\"\"\r\n        logger.info(\"Host {}: Checking system view\".format(self._host))\r\n        check_string = type(self)._system_view_check\r\n        self._stdin.write(self._normalize_cmd(\"\\n\"))\r\n        output = await self._read_until_prompt()\r\n        return check_string in output\r\n\r\n    async def _system_view(self):\r\n        \"\"\"Enter to system view\"\"\"\r\n        logger.info(\"Host {}: Entering to system view\".format(self._host))\r\n        output = \"\"\r\n        system_view_enter = type(self)._system_view_enter\r\n        if not await self._check_system_view():\r\n            self._stdin.write(self._normalize_cmd(system_view_enter))\r\n            output += await self._read_until_prompt()\r\n            if not await self._check_system_view():\r\n                raise ValueError(\"Failed to enter to system view\")\r\n        return output\r\n\r\n    async def _exit_system_view(self):\r\n        \"\"\"Exit from system view\"\"\"\r\n        logger.info(\"Host {}: Exiting from system view\".format(self._host))\r\n        output = \"\"\r\n        system_view_exit = type(self)._system_view_exit\r\n        if await self._check_system_view():\r\n            self._stdin.write(self._normalize_cmd(system_view_exit))\r\n            output += await self._read_until_prompt()\r\n            if await self._check_system_view():\r\n                raise ValueError(\"Failed to exit from system view\")\r\n        return output\r\n\r\n    async def send_config_set(self, config_commands=None, exit_system_view=False):\r\n        \"\"\"\r\n        Sending configuration commands to device\r\n        Automatically exits/enters system-view.\r\n\r\n        :param list config_commands: iterable string list with commands for applying to network devices in system view\r\n        :param bool exit_system_view: If true it will quit from system view automatically\r\n        :return: The output of this commands\r\n        \"\"\"\r\n\r\n        if config_commands is None:\r\n            return \"\"\r\n\r\n        # Send config commands\r\n        output = await self._system_view()\r\n        output += await super().send_config_set(config_commands=config_commands)\r\n\r\n        if exit_system_view:\r\n            output += await self._exit_system_view()\r\n\r\n        output = self._normalize_linefeeds(output)\r\n        logger.debug(\r\n            \"Host {}: Config commands output: {}\".format(self._host, repr(output))\r\n        )\r\n        return output\r\n"
  },
  {
    "path": "netdev/vendors/fujitsu/__init__.py",
    "content": "from .fujitsu_switch import FujitsuSwitch\r\n\r\n__all__ = [\"FujitsuSwitch\"]\r\n"
  },
  {
    "path": "netdev/vendors/fujitsu/fujitsu_switch.py",
    "content": "\"\"\"Subclass specific to Fujitsu Blade Switch\"\"\"\r\n\r\nimport re\r\n\r\nfrom netdev.logger import logger\r\nfrom netdev.vendors.ios_like import IOSLikeDevice\r\n\r\n\r\nclass FujitsuSwitch(IOSLikeDevice):\r\n    \"\"\"Class for working with Fujitsu Blade switch\"\"\"\r\n\r\n    _pattern = r\"\\({prompt}.*?\\) (\\(.*?\\))?[{delimiters}]\"\r\n    \"\"\"Pattern for using in reading buffer. When it found processing ends\"\"\"\r\n\r\n    _disable_paging_command = \"no pager\"\r\n    \"\"\"Command for disabling paging\"\"\"\r\n\r\n    _config_enter = \"conf\"\r\n    \"\"\"Command for entering to configuration mode\"\"\"\r\n\r\n    async def _set_base_prompt(self):\r\n        \"\"\"\r\n        Setting two important vars\r\n            base_prompt - textual prompt in CLI (usually hostname)\r\n            base_pattern - regexp for finding the end of command. IT's platform specific parameter\r\n\r\n        For Fujitsu devices base_pattern is \"(prompt) (\\(.*?\\))?[>|#]\"\r\n        \"\"\"\r\n        logger.info(\"Host {}: Setting base prompt\".format(self._host))\r\n        prompt = await self._find_prompt()\r\n        # Strip off trailing terminator\r\n        self._base_prompt = prompt[1:-3]\r\n        delimiters = map(re.escape, type(self)._delimiter_list)\r\n        delimiters = r\"|\".join(delimiters)\r\n        base_prompt = re.escape(self._base_prompt[:12])\r\n        pattern = type(self)._pattern\r\n        self._base_pattern = pattern.format(prompt=base_prompt, delimiters=delimiters)\r\n        logger.debug(\"Host {}: Base Prompt: {}\".format(self._host, self._base_prompt))\r\n        logger.debug(\"Host {}: Base Pattern: {}\".format(self._host, self._base_pattern))\r\n        return self._base_prompt\r\n\r\n    @staticmethod\r\n    def _normalize_linefeeds(a_string):\r\n        \"\"\"\r\n        Convert '\\r\\r\\n','\\r\\n', '\\n\\r' to '\\n and remove extra '\\n\\n' in the text\r\n        \"\"\"\r\n        newline = re.compile(r\"(\\r\\r\\n|\\r\\n|\\n\\r)\")\r\n        return newline.sub(\"\\n\", a_string).replace(\"\\n\\n\", \"\\n\")\r\n"
  },
  {
    "path": "netdev/vendors/hp/__init__.py",
    "content": "from .hp_comware import HPComware\r\nfrom .hp_comware_limited import HPComwareLimited\r\n\r\n__all__ = [\"HPComware\", \"HPComwareLimited\"]\r\n"
  },
  {
    "path": "netdev/vendors/hp/hp_comware.py",
    "content": "from netdev.vendors.comware_like import ComwareLikeDevice\r\n\r\n\r\nclass HPComware(ComwareLikeDevice):\r\n    \"\"\"Class for working with HP Comware\"\"\"\r\n\r\n    pass\r\n"
  },
  {
    "path": "netdev/vendors/hp/hp_comware_limited.py",
    "content": "from netdev.logger import logger\r\nfrom netdev.vendors.comware_like import ComwareLikeDevice\r\n\r\n\r\nclass HPComwareLimited(ComwareLikeDevice):\r\n    \"\"\"Class for working with HP Comware Limited like 1910 and 1920 models\"\"\"\r\n\r\n    def __init__(self, cmdline_password=u\"\", *args, **kwargs):\r\n        \"\"\"\r\n        Initialize  class for asynchronous working with network devices\r\n\r\n        :param str host: device hostname or ip address for connection\r\n        :param str username: username for logging to device\r\n        :param str password: user password for logging to device\r\n        :param str cmdline_password: password for entering to _cmd_line\r\n        :param int port: ssh port for connection. Default is 22\r\n        :param str device_type: network device type\r\n        :param known_hosts: file with known hosts. Default is None (no policy). With () it will use default file\r\n        :param str local_addr: local address for binding source of tcp connection\r\n        :param client_keys: path for client keys. Default in None. With () it will use default file in OS\r\n        :param str passphrase: password for encrypted client keys\r\n        :param float timeout: timeout in second for getting information from channel\r\n        :param loop: asyncio loop object\r\n        \"\"\"\r\n        super().__init__(*args, **kwargs)\r\n        self._cmdline_password = cmdline_password\r\n\r\n    _cmdline_mode_enter_command = \"_cmdline-mode on\"\r\n    \"\"\"Command for entering to cmdline model\"\"\"\r\n\r\n    _cmdline_mode_check = \"Invalid password\"\r\n    \"\"\"Checking string for wrong password in trying of entering to cmdline mode\"\"\"\r\n\r\n    async def connect(self):\r\n        \"\"\"\r\n        Basic asynchronous connection method\r\n\r\n        It connects to device and makes some preparation steps for working.\r\n        Usual using 4 functions:\r\n\r\n        * _establish_connection() for connecting to device\r\n        * _set_base_prompt() for finding and setting device prompt\r\n        * _cmdline_mode_enter() for entering hidden full functional mode\r\n        * _disable_paging() for non interact output in commands\r\n        \"\"\"\r\n        logger.info(\"Host {}: Trying to connect to the device\".format(self._host))\r\n        await self._establish_connection()\r\n        await self._set_base_prompt()\r\n        await self._cmdline_mode_enter()\r\n        await self._disable_paging()\r\n        logger.info(\"Host {}: Has connected to the device\".format(self._host))\r\n\r\n    async def _cmdline_mode_enter(self):\r\n        \"\"\"Entering to cmdline-mode\"\"\"\r\n        logger.info(\"Host {}: Entering to cmdline mode\".format(self._host))\r\n        output = \"\"\r\n        cmdline_mode_enter = type(self)._cmdline_mode_enter_command\r\n        check_error_string = type(self)._cmdline_mode_check\r\n\r\n        output = await self.send_command(cmdline_mode_enter, pattern=\"\\[Y\\/N\\]\")\r\n        output += await self.send_command(\"Y\", pattern=\"password\\:\")\r\n        output += await self.send_command(self._cmdline_password)\r\n\r\n        logger.debug(\r\n            \"Host {}: cmdline mode output: {}\".format(self._host, repr(output))\r\n        )\r\n        logger.info(\"Host {}: Checking cmdline mode\".format(self._host))\r\n        if check_error_string in output:\r\n            raise ValueError(\"Failed to enter to cmdline mode\")\r\n\r\n        return output\r\n"
  },
  {
    "path": "netdev/vendors/huawei/__init__.py",
    "content": "from .huawei import Huawei\n\n__all__ = [\"Huawei\"]"
  },
  {
    "path": "netdev/vendors/huawei/huawei.py",
    "content": "from netdev.vendors.comware_like import ComwareLikeDevice\nimport re\nfrom netdev.logger import logger\n\nclass Huawei(ComwareLikeDevice):\n    \"\"\"Class for working with Huawei\"\"\"\n\n    _disable_paging_command = \"screen-length 0 temporary\"\n    \"\"\"Command for disabling paging\"\"\"\n\n    async def _set_base_prompt(self):\n        \"\"\"\n        Setting two important vars\n            base_prompt - textual prompt in CLI (usually hostname)\n            base_pattern - regexp for finding the end of command. IT's platform specific parameter\n\n        For Comware devices base_pattern is \"[\\]|>]prompt(\\-\\w+)?[\\]|>]\n        \"\"\"\n        logger.info(\"Host {}: Setting base prompt\".format(self._host))\n        prompt = await self._find_prompt()\n        # Strip off any leading HRP_. characters for USGv5 HA\n        prompt = re.sub(r\"^HRP_.\", \"\", prompt, flags=re.M)\n        # Strip off trailing terminator\n        self._base_prompt = prompt[1:-1]\n        delimiter_right = map(re.escape, type(self)._delimiter_list)\n        delimiter_right = r\"|\".join(delimiter_right)\n        delimiter_left = map(re.escape, type(self)._delimiter_left_list)\n        delimiter_left = r\"|\".join(delimiter_left)\n        base_prompt = re.escape(self._base_prompt[:12])\n        pattern = type(self)._pattern\n        self._base_pattern = pattern.format(\n            delimiter_left=delimiter_left,\n            prompt=base_prompt,\n            delimiter_right=delimiter_right,\n        )\n        logger.debug(\"Host {}: Base Prompt: {}\".format(self._host, self._base_prompt))\n        logger.debug(\"Host {}: Base Pattern: {}\".format(self._host, self._base_pattern))\n        return self._base_prompt"
  },
  {
    "path": "netdev/vendors/infotecs/HW1000.py",
    "content": "\"\"\"\r\nHW1000 is a class for working with Vipnet HW1000 crypto gateways\r\n\"\"\"\r\nimport re\r\nfrom netdev.logger import logger\r\nfrom netdev.vendors.base import BaseDevice\r\n\r\nclass HW1000(BaseDevice):\r\n    \"\"\"\r\n    Class for working with Vipnet HW1000\r\n    \r\n    HW1000 devices have three administration modes:\r\n    *user exec or unprivileged exec. This mode allows you perform basic tests and get system information.\r\n    *privilege exec. This mode allows all EXEC mode commands available on the system. HW100 supports\r\n        only one active privilege session. Use preempt_privilege=True to close current privilege session\r\n    *shell. This mode exits standart device shell and enters Linux shell \r\n    \"\"\"\r\n    def __init__(self, secret=u'',preempt_privilege=False, *args, **kwargs):\r\n        \"\"\"\r\n        Initialize class for asynchronous working with network devices\r\n        :param str host: device hostname or ip address for connection\r\n        :param str username: username for logging to device\r\n        :param str password: user password for logging to device\r\n        :param str secret: secret password for privilege mode\r\n        :param bool preempt_privilege: close current privilige session (if exists). Default is False\r\n        :param int port: ssh port for connection. Default is 22\r\n        :param str device_type: network device type\r\n        :param known_hosts: file with known hosts. Default is None (no policy). With () it will use default file\r\n        :param str local_addr: local address for binding source of tcp connection\r\n        :param client_keys: path for client keys. Default in None. With () it will use default file in OS\r\n        :param str passphrase: password for encrypted client keys\r\n        :param float timeout: timeout in second for getting information from channel\r\n        :param loop: asyncio loop object\r\n        \"\"\"\r\n        self._secret = secret\r\n        self._preempt_privilege = preempt_privilege\r\n\r\n        super().__init__(*args, **kwargs)\r\n\r\n    _priv_enter = 'enable'\r\n    \"\"\"Command for entering to privilege exec\"\"\"\r\n\r\n    _priv_exit = 'exit'\r\n    \"\"\"Command for existing from privilege exec to user exec\"\"\"\r\n\r\n    _priv_check = '#'\r\n    \"\"\"Checking string in prompt. If it's exist im prompt - we are in privilege exec\"\"\"\r\n\r\n    _priv_confirm_message = \"Are you sure you want to force termination of the specified session\"\r\n    \"\"\"Confirmation message for privilege preemtion\"\"\" \r\n\r\n    _shell_enter = \"admin esc\"\r\n    \"\"\"Command for entering Linux shell\"\"\"\r\n    \r\n    _shell_exit = \"exit\"\r\n    \"\"\"Command for exiting Linux shell\"\"\"\r\n\r\n    _shell_check = \"sh\"\r\n    \"\"\"Checking string in prompt. If it's exist im prompt - we are in Linux shell\"\"\"\r\n\r\n    _shell_enter_message = \"Are you sure you want to exit to the Linux system shell?\"\r\n    \"\"\"Confirmation message for entering Linux shell\"\"\"\r\n\r\n    async def connect(self):\r\n        \"\"\"\r\n        Basic asynchronous connection method for HW1000 devices\r\n\r\n        It connects to device and makes some preparation steps for working.\r\n        Usual using 3 functions:\r\n\r\n        * _establish_connection() for connecting to device\r\n        * _set_base_prompt() for finding and setting device prompt\r\n        * _enable() for getting privilege exec mode\r\n        \"\"\"\r\n        logger.info(\"Host {}: Trying to connect to the device\".format(self._host))\r\n        await self._establish_connection()\r\n        await self._set_base_prompt()\r\n        await self.enable_mode()\r\n        logger.info(\"Host {}: Has connected to the device\".format(self._host))\r\n\r\n    async def check_enable_mode(self):\r\n        \"\"\"Check if we are in privilege exec. Return boolean\"\"\"\r\n        logger.info('Host {}: Checking privilege exec'.format(self._host))\r\n        check_string = type(self)._priv_check\r\n        self._stdin.write(self._normalize_cmd('\\n'))\r\n        output = await self._read_until_prompt()\r\n        return check_string in output\r\n\r\n    async def enable_mode(self, pattern='password', re_flags=re.IGNORECASE):\r\n        \"\"\"Enter to privilege exec\"\"\"\r\n        logger.info('Host {}: Entering to privilege exec'.format(self._host))\r\n        output = \"\"\r\n        enable_command = type(self)._priv_enter\r\n        if not await self.check_enable_mode():\r\n            self._stdin.write(self._normalize_cmd(enable_command))\r\n            output += await self._read_until_prompt_or_pattern(\r\n                pattern=pattern, re_flags=re_flags)\r\n            if re.search(pattern, output, re_flags):\r\n                self._stdin.write(self._normalize_cmd(self._secret))\r\n                output += await self._read_until_prompt_or_pattern(\r\n                    pattern=type(self)._priv_confirm_message,re_flags=re_flags)\r\n                if re.search(type(self)._priv_confirm_message,output,re_flags):\r\n                    if self._preempt_privilege:\r\n                        self._stdin.write(self._normalize_cmd(\"Yes\"))\r\n                    else:\r\n                        raise ValueError(\"Failed to enter privilege exec:\"\r\n                        \"there is already a active administration session.\"\r\n                        \"Use preempt_privilege=True\")\r\n            if not await self.check_enable_mode():\r\n                raise ValueError(\"Failed to enter to privilege exec\")\r\n        return output\r\n\r\n    async def exit_enable_mode(self):\r\n        \"\"\"Exit from privilege exec\"\"\"\r\n        logger.info('Host {}: Exiting from privilege exec'.format(self._host))\r\n        output = \"\"\r\n        exit_enable = type(self)._priv_exit\r\n        if await self.check_enable_mode():\r\n            self._stdin.write(self._normalize_cmd(exit_enable))\r\n            output += await self._read_until_prompt()\r\n            if await self.check_enable_mode():\r\n                raise ValueError(\"Failed to exit from privilege exec\")\r\n        return output\r\n\r\n    async def check_shell_mode(self):\r\n        \"\"\"Checks if device in shell mode or not\"\"\"\r\n        logger.info('Host {}: Checking shell mode'.format(self._host))\r\n        check_string = type(self)._shell_check\r\n        self._stdin.write(self._normalize_cmd('\\n'))\r\n        output = await self._read_until_pattern(r'[\\>|\\#]')\r\n        logger.info(output)\r\n        return check_string in output\r\n    \r\n    async def enter_shell_mode(self,re_flags=re.IGNORECASE):\r\n        \"\"\" Enter into shell mode\"\"\"\r\n        logger.info('Host {}: Entering to shell mode'.format(self._host))\r\n        output = ''\r\n        shell_command = type(self)._shell_enter\r\n        if not await self.check_shell_mode():\r\n            self._stdin.write(self._normalize_cmd(shell_command))\r\n            output += await self._read_until_pattern(\r\n                pattern=type(self)._shell_enter_message,re_flags=re_flags)\r\n            self._stdin.write(self._normalize_cmd(\"Yes\"))\r\n            output += await self._read_until_pattern('password:', re_flags=re_flags)\r\n            self._stdin.write(self._normalize_cmd(self._secret))\r\n            output += await self._read_until_pattern(r'[\\>|\\#]')\r\n            await self._set_base_prompt() # base promt differs in shell mode\r\n            if not await self.check_shell_mode():\r\n                raise ValueError('Failed to enter to shell mode')\r\n        return output\r\n    \r\n    async def exit_shell_mode(self):\r\n        \"\"\"Exit from shell mode\"\"\"\r\n        logger.info('Host {}: Exiting from shell mode'.format(self._host))\r\n        output = ''\r\n        exit_shell = type(self)._shell_exit\r\n        if await self.check_shell_mode():\r\n            self._stdin.write(self._normalize_cmd(exit_shell))\r\n            output = await self._read_until_pattern(r'[\\>|\\#]')\r\n            if await self.check_shell_mode():\r\n                raise ValueError(\"Failed to exit from shell mode\")\r\n            await self._set_base_prompt() # base promt differs in shell mode\r\n        return output\r\n    \r\n    async def _cleanup(self):\r\n        \"\"\" Any needed cleanup before closing connection \"\"\"\r\n        logger.info(\"Host {}: Cleanup session\".format(self._host))\r\n        await self.exit_shell_mode()\r\n        await self.exit_enable_mode()\r\n        "
  },
  {
    "path": "netdev/vendors/infotecs/__init__.py",
    "content": "from .HW1000 import HW1000\r\n\r\n__all__ = ['HW1000']\r\n"
  },
  {
    "path": "netdev/vendors/ios_like.py",
    "content": "\"\"\"\r\nIOSLikeDevice Class is abstract class for using in Cisco IOS like devices\r\n\r\nConnection Method are based upon AsyncSSH and should be running in asyncio loop\r\n\"\"\"\r\n\r\nimport re\r\n\r\nfrom netdev.logger import logger\r\nfrom netdev.vendors.base import BaseDevice\r\n\r\n\r\nclass IOSLikeDevice(BaseDevice):\r\n    \"\"\"\r\n    This Class is abstract class for working with Cisco IOS like devices\r\n\r\n    Cisco IOS like devices having several concepts:\r\n\r\n    * user exec or unprivileged exec. This mode allows you perform basic tests and get system information.\r\n    * privilege exec. This mode allows the use of all EXEC mode commands available on the system\r\n    * configuration mode or config mode. This mode are used for configuration whole system.\r\n    \"\"\"\r\n\r\n    def __init__(self, secret=u\"\", *args, **kwargs):\r\n        \"\"\"\r\n        Initialize class for asynchronous working with network devices\r\n\r\n        :param str host: device hostname or ip address for connection\r\n        :param str username: username for logging to device\r\n        :param str password: user password for logging to device\r\n        :param str secret: secret password for privilege mode\r\n        :param int port: ssh port for connection. Default is 22\r\n        :param str device_type: network device type\r\n        :param known_hosts: file with known hosts. Default is None (no policy). With () it will use default file\r\n        :param str local_addr: local address for binding source of tcp connection\r\n        :param client_keys: path for client keys. Default in None. With () it will use default file in OS\r\n        :param str passphrase: password for encrypted client keys\r\n        :param float timeout: timeout in second for getting information from channel\r\n        :param loop: asyncio loop object\r\n        \"\"\"\r\n        super().__init__(*args, **kwargs)\r\n        self._secret = secret\r\n\r\n    _priv_enter = \"enable\"\r\n    \"\"\"Command for entering to privilege exec\"\"\"\r\n\r\n    _priv_exit = \"disable\"\r\n    \"\"\"Command for existing from privilege exec to user exec\"\"\"\r\n\r\n    _priv_check = \"#\"\r\n    \"\"\"Checking string in prompt. If it's exist im prompt - we are in privilege exec\"\"\"\r\n\r\n    _config_enter = \"conf t\"\r\n    \"\"\"Command for entering to configuration mode\"\"\"\r\n\r\n    _config_exit = \"end\"\r\n    \"\"\"Command for existing from configuration mode to privilege exec\"\"\"\r\n\r\n    _config_check = \")#\"\r\n    \"\"\"Checking string in prompt. If it's exist im prompt - we are in configuration mode\"\"\"\r\n\r\n    async def connect(self):\r\n        \"\"\"\r\n        Basic asynchronous connection method for Cisco IOS like devices\r\n\r\n        It connects to device and makes some preparation steps for working.\r\n        Usual using 4 functions:\r\n\r\n        * _establish_connection() for connecting to device\r\n        * _set_base_prompt() for finding and setting device prompt\r\n        * _enable() for getting privilege exec mode\r\n        * _disable_paging() for non interact output in commands\r\n        \"\"\"\r\n        logger.info(\"Host {}: Trying to connect to the device\".format(self._host))\r\n        await self._establish_connection()\r\n        await self._set_base_prompt()\r\n        await self.enable_mode()\r\n        await self._disable_paging()\r\n        logger.info(\"Host {}: Has connected to the device\".format(self._host))\r\n\r\n    async def check_enable_mode(self):\r\n        \"\"\"Check if we are in privilege exec. Return boolean\"\"\"\r\n        logger.info(\"Host {}: Checking privilege exec\".format(self._host))\r\n        check_string = type(self)._priv_check\r\n        self._stdin.write(self._normalize_cmd(\"\\n\"))\r\n        output = await self._read_until_prompt()\r\n        return check_string in output\r\n\r\n    async def enable_mode(self, pattern=\"password\", re_flags=re.IGNORECASE):\r\n        \"\"\"Enter to privilege exec\"\"\"\r\n        logger.info(\"Host {}: Entering to privilege exec\".format(self._host))\r\n        output = \"\"\r\n        enable_command = type(self)._priv_enter\r\n        if not await self.check_enable_mode():\r\n            self._stdin.write(self._normalize_cmd(enable_command))\r\n            output += await self._read_until_prompt_or_pattern(\r\n                pattern=pattern, re_flags=re_flags\r\n            )\r\n            if re.search(pattern, output, re_flags):\r\n                self._stdin.write(self._normalize_cmd(self._secret))\r\n                output += await self._read_until_prompt()\r\n            if not await self.check_enable_mode():\r\n                raise ValueError(\"Failed to enter to privilege exec\")\r\n        return output\r\n\r\n    async def exit_enable_mode(self):\r\n        \"\"\"Exit from privilege exec\"\"\"\r\n        logger.info(\"Host {}: Exiting from privilege exec\".format(self._host))\r\n        output = \"\"\r\n        exit_enable = type(self)._priv_exit\r\n        if await self.check_enable_mode():\r\n            self._stdin.write(self._normalize_cmd(exit_enable))\r\n            output += await self._read_until_prompt()\r\n            if await self.check_enable_mode():\r\n                raise ValueError(\"Failed to exit from privilege exec\")\r\n        return output\r\n\r\n    async def check_config_mode(self):\r\n        \"\"\"Checks if the device is in configuration mode or not\"\"\"\r\n        logger.info(\"Host {}: Checking configuration mode\".format(self._host))\r\n        check_string = type(self)._config_check\r\n        self._stdin.write(self._normalize_cmd(\"\\n\"))\r\n        output = await self._read_until_prompt()\r\n        return check_string in output\r\n\r\n    async def config_mode(self):\r\n        \"\"\"Enter into config_mode\"\"\"\r\n        logger.info(\"Host {}: Entering to configuration mode\".format(self._host))\r\n        output = \"\"\r\n        config_command = type(self)._config_enter\r\n        if not await self.check_config_mode():\r\n            self._stdin.write(self._normalize_cmd(config_command))\r\n            output = await self._read_until_prompt()\r\n            if not await self.check_config_mode():\r\n                raise ValueError(\"Failed to enter to configuration mode\")\r\n        return output\r\n\r\n    async def exit_config_mode(self):\r\n        \"\"\"Exit from configuration mode\"\"\"\r\n        logger.info(\"Host {}: Exiting from configuration mode\".format(self._host))\r\n        output = \"\"\r\n        exit_config = type(self)._config_exit\r\n        if await self.check_config_mode():\r\n            self._stdin.write(self._normalize_cmd(exit_config))\r\n            output = await self._read_until_prompt()\r\n            if await self.check_config_mode():\r\n                raise ValueError(\"Failed to exit from configuration mode\")\r\n        return output\r\n\r\n    async def send_config_set(self, config_commands=None, exit_config_mode=True):\r\n        \"\"\"\r\n        Sending configuration commands to Cisco IOS like devices\r\n        Automatically exits/enters configuration mode.\r\n\r\n        :param list config_commands: iterable string list with commands for applying to network devices in conf mode\r\n        :param bool exit_config_mode: If true it will quit from configuration mode automatically\r\n        :return: The output of this commands\r\n        \"\"\"\r\n\r\n        if config_commands is None:\r\n            return \"\"\r\n\r\n        # Send config commands\r\n        output = await self.config_mode()\r\n        output += await super().send_config_set(config_commands=config_commands)\r\n\r\n        if exit_config_mode:\r\n            output += await self.exit_config_mode()\r\n\r\n        output = self._normalize_linefeeds(output)\r\n        logger.debug(\r\n            \"Host {}: Config commands output: {}\".format(self._host, repr(output))\r\n        )\r\n        return output\r\n\r\n    async def _cleanup(self):\r\n        \"\"\" Any needed cleanup before closing connection \"\"\"\r\n        logger.info(\"Host {}: Cleanup session\".format(self._host))\r\n        await self.exit_config_mode()\r\n"
  },
  {
    "path": "netdev/vendors/juniper/__init__.py",
    "content": "from .juniper_junos import JuniperJunOS\r\n\r\n__all__ = [\"JuniperJunOS\"]\r\n"
  },
  {
    "path": "netdev/vendors/juniper/juniper_junos.py",
    "content": "from netdev.logger import logger\r\nfrom netdev.vendors.junos_like import JunOSLikeDevice\r\n\r\n\r\nclass JuniperJunOS(JunOSLikeDevice):\r\n    \"\"\"Class for working with Juniper JunOS\"\"\"\r\n\r\n    _cli_check = \">\"\r\n    \"\"\"Checking string for shell mode\"\"\"\r\n\r\n    _cli_command = \"cli\"\r\n    \"\"\"Command for entering to cli mode\"\"\"\r\n\r\n    async def connect(self):\r\n        \"\"\"\r\n        Juniper JunOS asynchronous connection method\r\n\r\n        It connects to device and makes some preparation steps for working:\r\n\r\n        * _establish_connection() for connecting to device\r\n        * cli_mode() for checking shell mode. If we are in shell - we automatically enter to cli\r\n        * _set_base_prompt() for finding and setting device prompt\r\n        * _disable_paging() for non interact output in commands\r\n        \"\"\"\r\n        logger.info(\"Host {}: Trying to connect to the device\".format(self._host))\r\n        await self._establish_connection()\r\n        await self._set_base_prompt()\r\n        await self.cli_mode()\r\n        await self._disable_paging()\r\n        logger.info(\"Host {}: Entering to cmdline mode\".format(self._host))\r\n\r\n    async def check_cli_mode(self):\r\n        \"\"\"Check if we are in cli mode. Return boolean\"\"\"\r\n        logger.info(\"Host {}: Checking shell mode\".format(self._host))\r\n        cli_check = type(self)._cli_check\r\n        self._stdin.write(self._normalize_cmd(\"\\n\"))\r\n        output = await self._read_until_prompt()\r\n        return cli_check in output\r\n\r\n    async def cli_mode(self):\r\n        \"\"\"Enter to cli mode\"\"\"\r\n        logger.info(\"Host {}: Entering to cli mode\".format(self._host))\r\n        output = \"\"\r\n        cli_command = type(self)._cli_command\r\n        if not await self.check_cli_mode():\r\n            self._stdin.write(self._normalize_cmd(cli_command))\r\n            output += await self._read_until_prompt()\r\n            if not await self.check_cli_mode():\r\n                raise ValueError(\"Failed to enter to cli mode\")\r\n        return output\r\n"
  },
  {
    "path": "netdev/vendors/junos_like.py",
    "content": "\"\"\"\r\nJunOSLikeDevice Class is abstract class for using in Juniper JunOS like devices\r\n\r\nConnection Method are based upon AsyncSSH and should be running in asyncio loop\r\n\"\"\"\r\n\r\nimport re\r\n\r\nfrom netdev.logger import logger\r\nfrom netdev.vendors.base import BaseDevice\r\n\r\n\r\nclass JunOSLikeDevice(BaseDevice):\r\n    \"\"\"\r\n    JunOSLikeDevice Class for working with Juniper JunOS like devices\r\n\r\n    Juniper JunOS like devices having several concepts:\r\n\r\n    * shell mode (csh). This is csh shell for FreeBSD. This mode is not covered by this Class.\r\n    * cli mode (specific shell). The entire configuration is usual configured in this shell:\r\n\r\n      * operation mode. This mode is using for getting information from device\r\n      * configuration mode. This mode is using for configuration system\r\n    \"\"\"\r\n\r\n    _delimiter_list = [\"%\", \">\", \"#\"]\r\n    \"\"\"All this characters will stop reading from buffer. It mean the end of device prompt\"\"\"\r\n\r\n    _pattern = r\"\\w+(\\@[\\-\\w]*)?[{delimiters}]\"\r\n    \"\"\"Pattern for using in reading buffer. When it found processing ends\"\"\"\r\n\r\n    _disable_paging_command = \"set cli screen-length 0\"\r\n    \"\"\"Command for disabling paging\"\"\"\r\n\r\n    _config_enter = \"configure\"\r\n    \"\"\"Command for entering to configuration mode\"\"\"\r\n\r\n    _config_exit = \"exit configuration-mode\"\r\n    \"\"\"Command for existing from configuration mode to privilege exec\"\"\"\r\n\r\n    _config_check = \"#\"\r\n    \"\"\"Checking string in prompt. If it's exist im prompt - we are in configuration mode\"\"\"\r\n\r\n    _commit_command = \"commit\"\r\n    \"\"\"Command for committing changes\"\"\"\r\n\r\n    _commit_comment_command = \"commit comment {}\"\r\n    \"\"\"Command for committing changes with comment\"\"\"\r\n\r\n    async def _set_base_prompt(self):\r\n        \"\"\"\r\n        Setting two important vars\r\n            base_prompt - textual prompt in CLI (usually username or hostname)\r\n            base_pattern - regexp for finding the end of command. IT's platform specific parameter\r\n\r\n        For JunOS devices base_pattern is \"user(@[hostname])?[>|#]\r\n        \"\"\"\r\n        logger.info(\"Host {}: Setting base prompt\".format(self._host))\r\n        prompt = await self._find_prompt()\r\n        prompt = prompt[:-1]\r\n        # Strip off trailing terminator\r\n        if \"@\" in prompt:\r\n            prompt = prompt.split(\"@\")[1]\r\n        self._base_prompt = prompt\r\n        delimiters = map(re.escape, type(self)._delimiter_list)\r\n        delimiters = r\"|\".join(delimiters)\r\n        base_prompt = re.escape(self._base_prompt[:12])\r\n        pattern = type(self)._pattern\r\n        self._base_pattern = pattern.format(delimiters=delimiters)\r\n        logger.debug(\"Host {}: Base Prompt: {}\".format(self._host, self._base_prompt))\r\n        logger.debug(\"Host {}: Base Pattern: {}\".format(self._host, self._base_pattern))\r\n        return self._base_prompt\r\n\r\n    async def check_config_mode(self):\r\n        \"\"\"Check if are in configuration mode. Return boolean\"\"\"\r\n        logger.info(\"Host {}: Checking configuration mode\".format(self._host))\r\n        check_string = type(self)._config_check\r\n        self._stdin.write(self._normalize_cmd(\"\\n\"))\r\n        output = await self._read_until_prompt()\r\n        return check_string in output\r\n\r\n    async def config_mode(self):\r\n        \"\"\"Enter to configuration mode\"\"\"\r\n        logger.info(\"Host {}: Entering to configuration mode\".format(self._host))\r\n        output = \"\"\r\n        config_enter = type(self)._config_enter\r\n        if not await self.check_config_mode():\r\n            self._stdin.write(self._normalize_cmd(config_enter))\r\n            output += await self._read_until_prompt()\r\n            if not await self.check_config_mode():\r\n                raise ValueError(\"Failed to enter to configuration mode\")\r\n        return output\r\n\r\n    async def exit_config_mode(self):\r\n        \"\"\"Exit from configuration mode\"\"\"\r\n        logger.info(\"Host {}: Exiting from configuration mode\".format(self._host))\r\n        output = \"\"\r\n        config_exit = type(self)._config_exit\r\n        if await self.check_config_mode():\r\n            self._stdin.write(self._normalize_cmd(config_exit))\r\n            output += await self._read_until_prompt()\r\n            if await self.check_config_mode():\r\n                raise ValueError(\"Failed to exit from configuration mode\")\r\n        return output\r\n\r\n    async def send_config_set(\r\n        self,\r\n        config_commands=None,\r\n        with_commit=True,\r\n        commit_comment=\"\",\r\n        exit_config_mode=True,\r\n    ):\r\n        \"\"\"\r\n        Sending configuration commands to device\r\n        By default automatically exits/enters configuration mode.\r\n\r\n        :param list config_commands: iterable string list with commands for applying to network devices in system view\r\n        :param bool with_commit: if true it commit all changes after applying all config_commands\r\n        :param string commit_comment: message for configuration commit\r\n        :param bool exit_config_mode: If true it will quit from configuration mode automatically\r\n        :return: The output of these commands\r\n        \"\"\"\r\n\r\n        if config_commands is None:\r\n            return \"\"\r\n\r\n        # Send config commands\r\n        output = await self.config_mode()\r\n        output += await super().send_config_set(config_commands=config_commands)\r\n        if with_commit:\r\n            commit = type(self)._commit_command\r\n            if commit_comment:\r\n                commit = type(self)._commit_comment_command.format(commit_comment)\r\n\r\n            self._stdin.write(self._normalize_cmd(commit))\r\n            output += await self._read_until_prompt()\r\n\r\n        if exit_config_mode:\r\n            output += await self.exit_config_mode()\r\n\r\n        output = self._normalize_linefeeds(output)\r\n        logger.debug(\r\n            \"Host {}: Config commands output: {}\".format(self._host, repr(output))\r\n        )\r\n        return output\r\n"
  },
  {
    "path": "netdev/vendors/mikrotik/__init__.py",
    "content": "from .mikrotik_routeros import MikrotikRouterOS\r\n\r\n__all__ = [\"MikrotikRouterOS\"]\r\n"
  },
  {
    "path": "netdev/vendors/mikrotik/mikrotik_routeros.py",
    "content": "import asyncssh\r\nimport asyncio\r\n\r\nfrom netdev.exceptions import DisconnectError, TimeoutError\r\nfrom netdev.logger import logger\r\nfrom netdev.vendors.base import BaseDevice\r\n\r\n\r\nclass MikrotikRouterOS(BaseDevice):\r\n    \"\"\"Class for working with Mikrotik RouterOS\"\"\"\r\n\r\n    def __init__(self, *args, **kwargs):\r\n        \"\"\"\r\n        Initialize class for asynchronous working with network devices\r\n        Invoke init with some special params (base_pattern and username)\r\n\r\n        :param str host: device hostname or ip address for connection\r\n        :param str username: username for logging to device\r\n        :param str password: user password for logging to device\r\n        :param int port: ssh port for connection. Default is 22\r\n        :param str device_type: network device type\r\n        :param known_hosts: file with known hosts. Default is None (no policy). With () it will use default file\r\n        :param str local_addr: local address for binding source of tcp connection\r\n        :param client_keys: path for client keys. Default in None. With () it will use default file in OS\r\n        :param str passphrase: password for encrypted client keys\r\n        :param float timeout: timeout in second for getting information from channel\r\n        :param loop: asyncio loop object\r\n\r\n        Mikrotik duplicate prompt in connection, so we should use pattern like\r\n        prompt .* prompt.\r\n        For disabling colors in CLI output we should user this username = username+c\r\n        '+c' disables colors\r\n        '+t' disable auto term capabilities detection\r\n        '+200w' set terminal width to 200 rows\r\n        \"\"\"\r\n        super().__init__(*args, **kwargs)\r\n        self._base_pattern = r\"\\[.*?\\] \\>.*\\[.*?\\] \\>\"\r\n        self._connect_params_dict[\"username\"] += \"+ct200w\"\r\n        self._ansi_escape_codes = True\r\n\r\n    _pattern = r\"\\[.*?\\] (\\/.*?)?\\>\"\r\n\r\n    async def connect(self):\r\n        \"\"\"\r\n        Async Connection method\r\n\r\n        RouterOS using 2 functions:\r\n\r\n        * _establish_connection() for connecting to device\r\n        * _set_base_prompt() for finding and setting device prompt\r\n        \"\"\"\r\n        logger.info(\"Host {}: Connecting to device\".format(self._host))\r\n        await self._establish_connection()\r\n        await self._set_base_prompt()\r\n        logger.info(\"Host {}: Connected to device\".format(self._host))\r\n\r\n    async def _establish_connection(self):\r\n        \"\"\"Establish SSH connection to the network device\"\"\"\r\n        logger.info(\r\n            \"Host {}: Establishing connection to port {}\".format(self._host, self._port)\r\n        )\r\n        output = \"\"\r\n        # initiate SSH connection\r\n        fut = asyncssh.connect(**self._connect_params_dict)\r\n        try:\r\n            self._conn = await asyncio.wait_for(fut, self._timeout)\r\n        except asyncssh.DisconnectError as e:\r\n            raise DisconnectError(self._host, e.code, e.reason)\r\n        except asyncio.TimeoutError:\r\n            raise TimeoutError(self._host)\r\n        self._stdin, self._stdout, self._stderr = await self._conn.open_session(\r\n            term_type=\"Dumb\"\r\n        )\r\n        logger.info(\"Host {}: Connection is established\".format(self._host))\r\n        # Flush unnecessary data\r\n        output = await self._read_until_prompt()\r\n        logger.debug(\r\n            \"Host {}: Establish Connection Output: {}\".format(self._host, repr(output))\r\n        )\r\n        return output\r\n\r\n    async def _set_base_prompt(self):\r\n        \"\"\"\r\n        Setting two important vars\r\n        * base_prompt - textual prompt in CLI (usually hostname)\r\n        * base_pattern - regexp for finding the end of command. IT's platform specific parameter\r\n\r\n        For Mikrotik devices base_pattern is \"r\"\\[.*?\\] (\\/.*?)?\\>\"\r\n        \"\"\"\r\n        logger.info(\"Host {}: Setting base prompt\".format(self._host))\r\n        self._base_pattern = type(self)._pattern\r\n        prompt = await self._find_prompt()\r\n        user = \"\"\r\n        # Strip off trailing terminator\r\n        prompt = prompt[1:-3]\r\n        if \"@\" in prompt:\r\n            prompt = prompt.split(\"@\")[1]\r\n        self._base_prompt = prompt\r\n        logger.debug(\"Host {}: Base Prompt: {}\".format(self._host, self._base_prompt))\r\n        logger.debug(\"Host {}: Base Pattern: {}\".format(self._host, self._base_pattern))\r\n        return self._base_prompt\r\n\r\n    async def _find_prompt(self):\r\n        \"\"\"Finds the current network device prompt, last line only.\"\"\"\r\n        logger.info(\"Host {}: Finding prompt\".format(self._host))\r\n        self._stdin.write(\"\\r\")\r\n        prompt = \"\"\r\n        prompt = await self._read_until_prompt()\r\n        prompt = prompt.strip()\r\n        if self._ansi_escape_codes:\r\n            prompt = self._strip_ansi_escape_codes(prompt)\r\n        if not prompt:\r\n            raise ValueError(\"Unable to find prompt: {0}\".format(prompt))\r\n        logger.debug(\"Host {}: Prompt: {}\".format(self._host, prompt))\r\n        return prompt\r\n\r\n    @staticmethod\r\n    def _normalize_cmd(command):\r\n        \"\"\"Specific trailing newline for Mikrotik\"\"\"\r\n        command = command.rstrip(\"\\n\")\r\n        command += \"\\r\"\r\n        return command\r\n"
  },
  {
    "path": "netdev/vendors/terminal/__init__.py",
    "content": "from .terminal import Terminal\r\n\r\n__all__ = [\"Terminal\"]\r\n"
  },
  {
    "path": "netdev/vendors/terminal/terminal.py",
    "content": "import re\r\n\r\nfrom netdev.logger import logger\r\nfrom netdev.vendors.base import BaseDevice\r\n\r\n\r\nclass Terminal(BaseDevice):\r\n    \"\"\"Class for working with General Terminal\"\"\"\r\n\r\n    def __init__(self, delimeter_list=None, *args, **kwargs):\r\n        \"\"\"\r\n        Initialize class for asynchronous working with network devices\r\n        Invoke init with some special params (base_pattern and username)\r\n\r\n        :param str host: device hostname or ip address for connection\r\n        :param str username: username for logging to device\r\n        :param str password: user password for logging to device\r\n        :param int port: ssh port for connection. Default is 22\r\n        :param str device_type: network device type\r\n        :param known_hosts: file with known hosts. Default is None (no policy). With () it will use default file\r\n        :param delimeter_list: list with delimeters\r\n        :param str local_addr: local address for binding source of tcp connection\r\n        :param client_keys: path for client keys. Default in None. With () it will use default file in OS\r\n        :param str passphrase: password for encrypted client keys\r\n        :param float timeout: timeout in second for getting information from channel\r\n        :param loop: asyncio loop object\r\n        \"\"\"\r\n        super().__init__(*args, **kwargs)\r\n        if delimeter_list is not None:\r\n            self._delimiter_list = delimeter_list\r\n\r\n    _delimiter_list = [\"$\", \"#\"]\r\n    \"\"\"All this characters will stop reading from buffer. It mean the end of device prompt\"\"\"\r\n\r\n    _pattern = r\"[{delimiters}]\"\r\n    \"\"\"Pattern for using in reading buffer. When it found processing ends\"\"\"\r\n\r\n    async def connect(self):\r\n        \"\"\"\r\n        Async Connection method\r\n\r\n        General Terminal using 2 functions:\r\n\r\n        * _establish_connection() for connecting to device\r\n        * _set_base_prompt() for setting base pattern without setting base prompt\r\n        \"\"\"\r\n        logger.info(\"Host {}: Connecting to device\".format(self._host))\r\n        await self._establish_connection()\r\n        await self._set_base_prompt()\r\n        logger.info(\"Host {}: Connected to device\".format(self._host))\r\n\r\n    async def _set_base_prompt(self):\r\n        \"\"\"Setting base pattern\"\"\"\r\n        logger.info(\"Host {}: Setting base prompt\".format(self._host))\r\n        delimiters = map(re.escape, type(self)._delimiter_list)\r\n        delimiters = r\"|\".join(delimiters)\r\n        pattern = type(self)._pattern\r\n        self._base_pattern = pattern.format(delimiters=delimiters)\r\n        logger.debug(\"Host {}: Base Pattern: {}\".format(self._host, self._base_pattern))\r\n        return self._base_prompt\r\n"
  },
  {
    "path": "netdev/vendors/ubiquiti/__init__.py",
    "content": "from .ubiquity_edge import UbiquityEdgeSwitch\r\n\r\n__all__ = [\"UbiquityEdgeSwitch\"]\r\n"
  },
  {
    "path": "netdev/vendors/ubiquiti/ubiquity_edge.py",
    "content": "\"\"\"Subclass specific to Ubiquity Edge Switch\"\"\"\r\nimport re\r\n\r\nfrom netdev.logger import logger\r\nfrom netdev.vendors.ios_like import IOSLikeDevice\r\n\r\n\r\nclass UbiquityEdgeSwitch(IOSLikeDevice):\r\n    \"\"\"Class for working with Ubiquity Edge Switches\"\"\"\r\n\r\n    _pattern = r\"\\({prompt}.*?\\) (\\(.*?\\))?[{delimiters}]\"\r\n    \"\"\"Pattern for using in reading buffer. When it found processing ends\"\"\"\r\n\r\n    _config_enter = \"configure\"\r\n    \"\"\"Command for entering to configuration mode\"\"\"\r\n\r\n    async def _set_base_prompt(self):\r\n        \"\"\"\r\n        Setting two important vars\r\n            base_prompt - textual prompt in CLI (usually hostname)\r\n            base_pattern - regexp for finding the end of command. IT's platform specific parameter\r\n\r\n        For Ubiquity devices base_pattern is \"(prompt) (\\(.*?\\))?[>|#]\"\r\n        \"\"\"\r\n        logger.info(\"Host {}: Setting base prompt\".format(self._host))\r\n        prompt = await self._find_prompt()\r\n        # Strip off trailing terminator\r\n        self._base_prompt = prompt[1:-3]\r\n        delimiters = map(re.escape, type(self)._delimiter_list)\r\n        delimiters = r\"|\".join(delimiters)\r\n        base_prompt = re.escape(self._base_prompt[:12])\r\n        pattern = type(self)._pattern\r\n        self._base_pattern = pattern.format(prompt=base_prompt, delimiters=delimiters)\r\n        logger.debug(\"Host {}: Base Prompt: {}\".format(self._host, self._base_prompt))\r\n        logger.debug(\"Host {}: Base Pattern: {}\".format(self._host, self._base_pattern))\r\n        return self._base_prompt\r\n"
  },
  {
    "path": "netdev/version.py",
    "content": "\"\"\" Netdev Version information\r\n\"\"\"\r\n\r\n__version__ = \"0.9.3\"\r\n__author__ = \"Yakovlev Sergey\"\r\n__author_email__ = \"selfuryon@gmail.com\"\r\n__url__ = \"http://netdev.readthedocs.io/\"\r\n"
  },
  {
    "path": "pyproject.toml",
    "content": "[build-system]\nrequires = [\"poetry>=0.12\"]\nbuild-backend = \"poetry.masonry.api\"\n\n[tool.poetry]\nname = \"netdev\"\nversion = \"0.9.3\"\ndescription = \"Asynchronous multi-vendor library for interacting with network devices\"\nauthors = [\"Sergey Yakovlev <selfuryon@gmail.com>\"]\nlicense = \"Apache-2.0\"\nreadme = \"README.rst\"\nhomepage = \"https://netdev.readthedocs.io\"\ndocumentation = \"https://netdev.readthedocs.io\"\nrepository = \"https://github.com/selfuryon/netdev\"\nkeywords = ['netdev','network', 'netmiko', 'asyncio']\nclassifiers = [\n        \"Development Status :: 4 - Beta\",\n        \"Framework :: AsyncIO\",\n        \"Programming Language :: Python :: 3.6\",\n        \"Programming Language :: Python :: 3.7\",\n        \"Intended Audience :: Developers\",\n        \"Intended Audience :: System Administrators\",\n        \"Intended Audience :: Telecommunications Industry\",\n        \"Topic :: System :: Networking\",\n        \"Topic :: System :: Systems Administration\",\n]\n\n[tool.poetry.dependencies]\npython = \"^3.6\"\nPyYAML = \"^5.1\"\nasyncssh = \"^1.15\"\nsphinx = { version = \"^2.0\", optional = true}\nsphinx_rtd_theme = { version = \"^0.4\", optional = true}\n\n[tool.poetry.dev-dependencies]\nPyYAML = \"^5.1\"\nasyncssh = \"^1.16\"\nblack = {version = \"^19.3b0\",allows-prereleases = true}\npytest = \"^4.0\"\npylint = \"^2.3\"\nsphinx = \"^2.0\"\nsphinx_rtd_theme = \"^0.4\"\n\n[tool.poetry.extras]\ndocs = [\"sphinx\", \"sphinx_rtd_theme\"]\n\n"
  },
  {
    "path": "tests/test_arista_eos.py",
    "content": "import asyncio\r\nimport logging\r\nimport unittest\r\n\r\nimport yaml\r\n\r\nimport netdev\r\n\r\nlogging.basicConfig(filename='unittest.log', level=logging.DEBUG)\r\nconfig_path = 'config.yaml'\r\n\r\n\r\nclass TestArista(unittest.TestCase):\r\n    @staticmethod\r\n    def load_credits():\r\n        with open(config_path, 'r') as conf:\r\n            config = yaml.safe_load(conf)\r\n            with open(config['device_list'], 'r') as devs:\r\n                devices = yaml.safe_load(devs)\r\n                params = [p for p in devices if p['device_type'] == 'arista_eos']\r\n                return params\r\n\r\n    def setUp(self):\r\n        self.loop = asyncio.new_event_loop()\r\n        self.loop.set_debug(False)\r\n        asyncio.set_event_loop(self.loop)\r\n        self.devices = self.load_credits()\r\n        self.assertFalse(len(self.devices) == 0)\r\n\r\n    def test_show_run_hostname(self):\r\n        async def task():\r\n            for dev in self.devices:\r\n                async with netdev.create(**dev) as arista:\r\n                    out = await arista.send_command('show run | i hostname')\r\n                    self.assertIn(\"hostname\", out)\r\n\r\n        self.loop.run_until_complete(task())\r\n\r\n    def test_show_several_commands(self):\r\n        async def task():\r\n            for dev in self.devices:\r\n                async with netdev.create(**dev) as arista:\r\n                    commands = [\"dir\", \"show ver\", \"show run\"]\r\n                    for cmd in commands:\r\n                        out = await arista.send_command(cmd, strip_command=False)\r\n                        self.assertIn(cmd, out)\r\n\r\n        self.loop.run_until_complete(task())\r\n\r\n    def test_config_set(self):\r\n        async def task():\r\n            for dev in self.devices:\r\n                async with netdev.create(**dev) as arista:\r\n                    commands = [\"vlan 1\", \"exit\"]\r\n                    out = await arista.send_config_set(commands)\r\n                    self.assertIn(\"vlan 1\", out)\r\n                    self.assertIn(\"exit\", out)\r\n\r\n        self.loop.run_until_complete(task())\r\n\r\n    def test_base_prompt(self):\r\n        async def task():\r\n            for dev in self.devices:\r\n                async with netdev.create(**dev) as arista:\r\n                    out = await arista.send_command('sh run | i hostname')\r\n                    self.assertIn(arista.base_prompt, out)\r\n\r\n        self.loop.run_until_complete(task())\r\n\r\n    def test_timeout(self):\r\n        async def task():\r\n            for dev in self.devices:\r\n                with self.assertRaises(netdev.TimeoutError):\r\n                    async with netdev.create(**dev, timeout=0.1) as arista:\r\n                        await arista.send_command('sh run | i hostname')\r\n\r\n        self.loop.run_until_complete(task())\r\n\r\n    def test_interactive_commands(self):\r\n        async def task():\r\n            for dev in self.devices:\r\n                async with netdev.create(**dev) as arista:\r\n                    out = await arista.send_command(\"erase startup\", pattern=r'\\[confirm\\]', strip_command=False)\r\n                    out += await arista.send_command(\"no\", strip_command=False)\r\n                    out += await arista.send_command(\"show startup\", strip_command=False)\r\n                    self.assertIn('Startup-config last modified', out)\r\n\r\n        self.loop.run_until_complete(task())\r\n"
  },
  {
    "path": "tests/test_aruba_aos_6.py",
    "content": "import asyncio\r\nimport logging\r\nimport unittest\r\n\r\nimport yaml\r\n\r\nimport netdev\r\n\r\nlogging.basicConfig(filename='unittest.log', level=logging.DEBUG)\r\nconfig_path = 'config.yaml'\r\n\r\n\r\nclass TestAOS6(unittest.TestCase):\r\n    @staticmethod\r\n    def load_credits():\r\n        with open(config_path, 'r') as conf:\r\n            config = yaml.safe_load(conf)\r\n            with open(config['device_list'], 'r') as devs:\r\n                devices = yaml.safe_load(devs)\r\n                params = [p for p in devices if p['device_type'] == 'aruba_aos_6']\r\n                return params\r\n\r\n    def setUp(self):\r\n        self.loop = asyncio.new_event_loop()\r\n        self.loop.set_debug(False)\r\n        asyncio.set_event_loop(self.loop)\r\n        self.devices = self.load_credits()\r\n        self.assertFalse(len(self.devices) == 0)\r\n\r\n    def test_show_run_hostname(self):\r\n        async def task():\r\n            for dev in self.devices:\r\n                async with netdev.create(**dev) as aos:\r\n                    out = await aos.send_command('show run | i hostname')\r\n                    self.assertIn(\"hostname\", out)\r\n\r\n        self.loop.run_until_complete(task())\r\n\r\n    def test_show_several_commands(self):\r\n        async def task():\r\n            for dev in self.devices:\r\n                async with netdev.create(**dev) as aos:\r\n                    commands = [\"dir\", \"show ver\", \"show run\", \"show ssh\"]\r\n                    for cmd in commands:\r\n                        out = await aos.send_command(cmd, strip_command=False)\r\n                        self.assertIn(cmd, out)\r\n\r\n        self.loop.run_until_complete(task())\r\n\r\n    def test_config_set(self):\r\n        async def task():\r\n            for dev in self.devices:\r\n                async with netdev.create(**dev) as aos:\r\n                    commands = [\"interface loopback\", \"exit\"]\r\n                    out = await aos.send_config_set(commands)\r\n                    self.assertIn(\"interface loopback\", out)\r\n                    self.assertIn(\"exit\", out)\r\n\r\n        self.loop.run_until_complete(task())\r\n\r\n    def test_base_prompt(self):\r\n        async def task():\r\n            for dev in self.devices:\r\n                async with netdev.create(**dev) as aos:\r\n                    out = await aos.send_command('sh run | i hostname')\r\n                    self.assertIn(aos.base_prompt, out)\r\n\r\n        self.loop.run_until_complete(task())\r\n\r\n    def test_timeout(self):\r\n        async def task():\r\n            for dev in self.devices:\r\n                with self.assertRaises(netdev.TimeoutError):\r\n                    async with netdev.create(**dev, timeout=0.1) as aos:\r\n                        await aos.send_command('sh run | i hostname')\r\n\r\n        self.loop.run_until_complete(task())\r\n"
  },
  {
    "path": "tests/test_aruba_aos_8.py",
    "content": "import asyncio\r\nimport logging\r\nimport unittest\r\n\r\nimport yaml\r\n\r\nimport netdev\r\n\r\nlogging.basicConfig(filename='unittest.log', level=logging.DEBUG)\r\nconfig_path = 'config.yaml'\r\n\r\n\r\nclass TestAOS8(unittest.TestCase):\r\n    @staticmethod\r\n    def load_credits():\r\n        with open(config_path, 'r') as conf:\r\n            config = yaml.safe_load(conf)\r\n            with open(config['device_list'], 'r') as devs:\r\n                devices = yaml.safe_load(devs)\r\n                params = [p for p in devices if p['device_type'] == 'aruba_aos_8']\r\n                return params\r\n\r\n    def setUp(self):\r\n        self.loop = asyncio.new_event_loop()\r\n        self.loop.set_debug(False)\r\n        asyncio.set_event_loop(self.loop)\r\n        self.devices = self.load_credits()\r\n        self.assertFalse(len(self.devices) == 0)\r\n\r\n    def test_show_run_hostname(self):\r\n        async def task():\r\n            for dev in self.devices:\r\n                async with netdev.create(**dev) as aos:\r\n                    out = await aos.send_command('show run | i hostname')\r\n                    self.assertIn(\"hostname\", out)\r\n\r\n        self.loop.run_until_complete(task())\r\n\r\n    def test_show_several_commands(self):\r\n        async def task():\r\n            for dev in self.devices:\r\n                async with netdev.create(**dev) as aos:\r\n                    commands = [\"dir\", \"show ver\", \"show run\", \"show ssh\"]\r\n                    for cmd in commands:\r\n                        out = await aos.send_command(cmd, strip_command=False)\r\n                        self.assertIn(cmd, out)\r\n\r\n        self.loop.run_until_complete(task())\r\n\r\n    def test_config_set(self):\r\n        async def task():\r\n            for dev in self.devices:\r\n                async with netdev.create(**dev) as aos:\r\n                    commands = [\"interface loopback\", \"exit\"]\r\n                    out = await aos.send_config_set(commands)\r\n                    self.assertIn(\"loopback\", out)\r\n                    self.assertIn(\"exit\", out)\r\n\r\n        self.loop.run_until_complete(task())\r\n\r\n    def test_base_prompt(self):\r\n        async def task():\r\n            for dev in self.devices:\r\n                async with netdev.create(**dev) as aos:\r\n                    out = await aos.send_command('sh run | i hostname')\r\n                    self.assertIn(aos.base_prompt, out)\r\n\r\n        self.loop.run_until_complete(task())\r\n\r\n    def test_timeout(self):\r\n        async def task():\r\n            for dev in self.devices:\r\n                with self.assertRaises(netdev.TimeoutError):\r\n                    async with netdev.create(**dev, timeout=0.1) as aos:\r\n                        await aos.send_command('sh run | i hostname')\r\n\r\n        self.loop.run_until_complete(task())\r\n"
  },
  {
    "path": "tests/test_cisco_asa.py",
    "content": "import asyncio\r\nimport logging\r\nimport unittest\r\n\r\nimport yaml\r\n\r\nimport netdev\r\n\r\nlogging.basicConfig(filename='unittest.log', level=logging.DEBUG)\r\nconfig_path = 'config.yaml'\r\n\r\n\r\nclass TestASA(unittest.TestCase):\r\n    @staticmethod\r\n    def load_credits():\r\n        with open(config_path, 'r') as conf:\r\n            config = yaml.safe_load(conf)\r\n            with open(config['device_list'], 'r') as devs:\r\n                devices = yaml.safe_load(devs)\r\n                params = [p for p in devices if p['device_type'] == 'cisco_asa']\r\n                return params\r\n\r\n    def setUp(self):\r\n        self.loop = asyncio.new_event_loop()\r\n        self.loop.set_debug(False)\r\n        asyncio.set_event_loop(self.loop)\r\n        self.devices = self.load_credits()\r\n        self.assertFalse(len(self.devices) == 0)\r\n\r\n    def test_show_run_hostname(self):\r\n        async def task():\r\n            for dev in self.devices:\r\n                async with netdev.create(**dev) as asa:\r\n                    out = await asa.send_command('show run | i hostname')\r\n                    self.assertIn(\"hostname\", out)\r\n\r\n        self.loop.run_until_complete(task())\r\n\r\n    def test_timeout(self):\r\n        async def task():\r\n            for dev in self.devices:\r\n                with self.assertRaises(netdev.TimeoutError):\r\n                    async with netdev.create(**dev, timeout=0.1) as asa:\r\n                        await asa.send_command('show run | i hostname')\r\n\r\n        self.loop.run_until_complete(task())\r\n\r\n    def test_show_several_commands(self):\r\n        async def task():\r\n            for dev in self.devices:\r\n                async with netdev.create(**dev) as asa:\r\n                    commands = [\"show ver\", \"show run\", \"show ssh\"]\r\n                    for cmd in commands:\r\n                        out = await asa.send_command(cmd, strip_command=False)\r\n                        self.assertIn(cmd, out)\r\n\r\n        self.loop.run_until_complete(task())\r\n\r\n    def test_config_set(self):\r\n        async def task():\r\n            for dev in self.devices:\r\n                async with netdev.create(**dev) as asa:\r\n                    commands = [\"interface Management0/0\", \"exit\"]\r\n                    out = await asa.send_config_set(commands)\r\n                    self.assertIn(\"interface Management0/0\", out)\r\n                    self.assertIn(\"exit\", out)\r\n\r\n        self.loop.run_until_complete(task())\r\n\r\n    def test_interactive_commands(self):\r\n        async def task():\r\n            for dev in self.devices:\r\n                async with netdev.create(**dev) as asa:\r\n                    out = await asa.send_command(\"copy r scp:\", pattern=r'\\[running-config\\]\\?', strip_command=False)\r\n                    out += await asa.send_command(\"\\n\", pattern=r'\\[\\]\\?', strip_command=False)\r\n                    out += await asa.send_command(\"\\n\", strip_command=False)\r\n                    self.assertIn('%Error', out)\r\n\r\n        self.loop.run_until_complete(task())\r\n"
  },
  {
    "path": "tests/test_cisco_ios.py",
    "content": "import asyncio\r\nimport logging\r\nimport unittest\r\n\r\nimport yaml\r\n\r\nimport netdev\r\n\r\nlogging.basicConfig(filename='unittest.log', level=logging.DEBUG)\r\nconfig_path = 'config.yaml'\r\n\r\n\r\nclass TestIOS(unittest.TestCase):\r\n    @staticmethod\r\n    def load_credits():\r\n        with open(config_path, 'r') as conf:\r\n            config = yaml.safe_load(conf)\r\n            with open(config['device_list'], 'r') as devs:\r\n                devices = yaml.safe_load(devs)\r\n                params = [p for p in devices if p['device_type'] == 'cisco_ios']\r\n                return params\r\n\r\n    def setUp(self):\r\n        self.loop = asyncio.new_event_loop()\r\n        self.loop.set_debug(False)\r\n        asyncio.set_event_loop(self.loop)\r\n        self.devices = self.load_credits()\r\n        self.assertFalse(len(self.devices) == 0)\r\n\r\n    def test_show_run_hostname(self):\r\n        async def task():\r\n            for dev in self.devices:\r\n                async with netdev.create(**dev) as ios:\r\n                    out = await ios.send_command('show run | i hostname')\r\n                    self.assertIn(\"hostname\", out)\r\n\r\n        self.loop.run_until_complete(task())\r\n\r\n    def test_timeout(self):\r\n        async def task():\r\n            for dev in self.devices:\r\n                with self.assertRaises(netdev.TimeoutError):\r\n                    async with netdev.create(**dev, timeout=0.1) as ios:\r\n                        await ios.send_command('show run | i hostname')\r\n\r\n        self.loop.run_until_complete(task())\r\n\r\n    def test_show_several_commands(self):\r\n        async def task():\r\n            for dev in self.devices:\r\n                async with netdev.create(**dev) as ios:\r\n                    commands = [\"dir\", \"show ver\", \"show run\", \"show ssh\"]\r\n                    for cmd in commands:\r\n                        out = await ios.send_command(cmd, strip_command=False)\r\n                        self.assertIn(cmd, out)\r\n\r\n        self.loop.run_until_complete(task())\r\n\r\n    def test_config_set(self):\r\n        async def task():\r\n            for dev in self.devices:\r\n                async with netdev.create(**dev) as ios:\r\n                    commands = [\"line con 0\", \"exit\"]\r\n                    out = await ios.send_config_set(commands)\r\n                    self.assertIn(\"line con 0\", out)\r\n                    self.assertIn(\"exit\", out)\r\n\r\n        self.loop.run_until_complete(task())\r\n\r\n    def test_base_prompt(self):\r\n        async def task():\r\n            for dev in self.devices:\r\n                async with netdev.create(**dev) as ios:\r\n                    out = await ios.send_command('sh run | i hostname')\r\n                    self.assertIn(ios.base_prompt, out)\r\n\r\n        self.loop.run_until_complete(task())\r\n\r\n    def test_interactive_commands(self):\r\n        async def task():\r\n            for dev in self.devices:\r\n                async with netdev.create(**dev) as ios:\r\n                    out = await ios.send_command(\"conf\", pattern=r'\\[terminal\\]\\?', strip_command=False)\r\n                    out += await ios.send_command(\"term\", strip_command=False)\r\n                    out += await ios.send_command(\"exit\", strip_command=False)\r\n                    self.assertIn('Enter configuration commands', out)\r\n\r\n        self.loop.run_until_complete(task())\r\n"
  },
  {
    "path": "tests/test_cisco_iossg3xx.py",
    "content": "import asyncio\nimport logging\nimport unittest\n\nimport yaml\n\nimport netdev\n\nlogging.basicConfig(filename='unittest.log', level=logging.DEBUG)\nconfig_path = 'config.yaml'\n\n\nclass TestIOSSG3XX(unittest.TestCase):\n    @staticmethod\n    def load_credits():\n        with open(config_path, 'r') as conf:\n            config = yaml.safe_load(conf)\n            with open(config['device_list'], 'r') as devs:\n                devices = yaml.safe_load(devs)\n                params = [p for p in devices if p['device_type'] == 'cisco_sg3xx']\n                return params\n\n    def setUp(self):\n        self.loop = asyncio.new_event_loop()\n        self.loop.set_debug(False)\n        asyncio.set_event_loop(self.loop)\n        self.devices = self.load_credits()\n        self.assertFalse(len(self.devices) == 0)\n\n    def test_show_run_hostname(self):\n        async def task():\n            for dev in self.devices:\n                async with netdev.create(**dev) as ios:\n                    out = await ios.send_command('show run | i hostname')\n                    self.assertIn(\"hostname\", out)\n\n        self.loop.run_until_complete(task())\n\n    def test_timeout(self):\n        async def task():\n            for dev in self.devices:\n                with self.assertRaises(netdev.TimeoutError):\n                    async with netdev.create(**dev, timeout=0.1) as ios:\n                        await ios.send_command('show run | i hostname')\n\n        self.loop.run_until_complete(task())\n\n    def test_show_several_commands(self):\n        async def task():\n            for dev in self.devices:\n                async with netdev.create(**dev) as ios:\n                    commands = [\"dir\", \"show ver\", \"show run\", \"show ssh\"]\n                    for cmd in commands:\n                        out = await ios.send_command(cmd, strip_command=False)\n                        self.assertIn(cmd, out)\n\n        self.loop.run_until_complete(task())\n\n    def test_config_set(self):\n        async def task():\n            for dev in self.devices:\n                async with netdev.create(**dev) as ios:\n                    commands = [\"line con\", \"exit\"]\n                    out = await ios.send_config_set(commands)\n                    self.assertIn(\"line con\", out)\n                    self.assertIn(\"exit\", out)\n\n        self.loop.run_until_complete(task())\n\n    def test_base_prompt(self):\n        async def task():\n            for dev in self.devices:\n                async with netdev.create(**dev) as ios:\n                    out = await ios.send_command('sh run | i hostname')\n                    self.assertIn(ios.base_prompt, out)\n\n        self.loop.run_until_complete(task())\n\n    def test_interactive_commands(self):\n        async def task():\n            for dev in self.devices:\n                async with netdev.create(**dev) as ios:\n                    out = await ios.send_command(\"conf\", pattern=r'\\[terminal\\]\\?', strip_command=False)\n                    out += await ios.send_command(\"term\", strip_command=False)\n                    out += await ios.send_command(\"exit\", strip_command=False)\n                    self.assertIn('Enter configuration commands', out)\n\n        self.loop.run_until_complete(task())\n"
  },
  {
    "path": "tests/test_cisco_iosxr.py",
    "content": "import asyncio\r\nimport logging\r\nimport unittest\r\n\r\nimport yaml\r\n\r\nimport netdev\r\n\r\nlogging.basicConfig(filename='unittest.log', level=logging.DEBUG)\r\nconfig_path = 'config.yaml'\r\n\r\n\r\nclass TestIOSXR(unittest.TestCase):\r\n    @staticmethod\r\n    def load_credits():\r\n        with open(config_path, 'r') as conf:\r\n            config = yaml.safe_load(conf)\r\n            with open(config['device_list'], 'r') as devs:\r\n                devices = yaml.safe_load(devs)\r\n                params = [p for p in devices if p['device_type'] == 'cisco_ios_xr']\r\n                return params\r\n\r\n    def setUp(self):\r\n        self.loop = asyncio.new_event_loop()\r\n        self.loop.set_debug(False)\r\n        asyncio.set_event_loop(self.loop)\r\n        self.devices = self.load_credits()\r\n        self.assertFalse(len(self.devices) == 0)\r\n\r\n    def test_show_run_hostname(self):\r\n        async def task():\r\n            for dev in self.devices:\r\n                async with netdev.create(**dev) as iosxr:\r\n                    out = await iosxr.send_command('show run | i hostname')\r\n                    self.assertIn(\"hostname\", out)\r\n\r\n        self.loop.run_until_complete(task())\r\n\r\n    def test_timeout(self):\r\n        async def task():\r\n            for dev in self.devices:\r\n                with self.assertRaises(netdev.TimeoutError):\r\n                    async with netdev.create(**dev, timeout=0.1) as iosxr:\r\n                        await iosxr.send_command('show run | i hostname')\r\n\r\n        self.loop.run_until_complete(task())\r\n\r\n    def test_show_several_commands(self):\r\n        async def task():\r\n            for dev in self.devices:\r\n                async with netdev.create(**dev) as iosxr:\r\n                    commands = [\"dir\", \"show ver\", \"show run\", \"show ssh\"]\r\n                    for cmd in commands:\r\n                        out = await iosxr.send_command(cmd, strip_command=False)\r\n                        self.assertIn(cmd, out)\r\n\r\n        self.loop.run_until_complete(task())\r\n\r\n    def test_config_set(self):\r\n        async def task():\r\n            for dev in self.devices:\r\n                async with netdev.create(**dev) as iosxr:\r\n                    commands = [\"line con 0\", \"exit\"]\r\n                    out = await iosxr.send_config_set(commands)\r\n                    self.assertIn(\"line con 0\", out)\r\n                    self.assertIn(\"exit\", out)\r\n\r\n        self.loop.run_until_complete(task())\r\n\r\n    def test_interactive_commands(self):\r\n        async def task():\r\n            for dev in self.devices:\r\n                async with netdev.create(**dev) as ios:\r\n                    out = await ios.send_command(\"conf\", strip_command=False)\r\n                    out += await ios.send_command(\"hostname test\", strip_command=False)\r\n                    out += await ios.send_command(\"exit\", pattern=r'Uncommitted changes found', strip_command=False)\r\n                    out += await ios.send_command(\"no\", strip_command=False)\r\n                    self.assertIn('commit them before exiting', out)\r\n\r\n        self.loop.run_until_complete(task())\r\n\r\n    def test_exit_without_commit(self):\r\n        async def task():\r\n            for dev in self.devices:\r\n                async with netdev.create(**dev) as ios:\r\n                    commands = [\"interface GigabitEthernet 0/0/0/0\", \"service-policy input 1\"]\r\n                    out = await ios.send_config_set(commands, with_commit=False)\r\n                    self.assertIn('Uncommitted changes found', out)\r\n\r\n        self.loop.run_until_complete(task())\r\n\r\n    def test_errors_in_commit(self):\r\n        async def task():\r\n            for dev in self.devices:\r\n                with self.assertRaises(netdev.CommitError):\r\n                    async with netdev.create(**dev) as ios:\r\n                        commands = [\"interface GigabitEthernet 0/0/0/0\", \"service-policy input 1\"]\r\n                        await ios.send_config_set(commands)\r\n\r\n        self.loop.run_until_complete(task())\r\n"
  },
  {
    "path": "tests/test_cisco_nxos.py",
    "content": "import asyncio\r\nimport logging\r\nimport unittest\r\n\r\nimport yaml\r\n\r\nimport netdev\r\n\r\nlogging.basicConfig(filename='unittest.log', level=logging.DEBUG)\r\nnetdev.logger.setLevel(logging.DEBUG)\r\nconfig_path = 'config.yaml'\r\n\r\n\r\nclass TestNXOS(unittest.TestCase):\r\n    @staticmethod\r\n    def load_credits():\r\n        with open(config_path, 'r') as conf:\r\n            config = yaml.safe_load(conf)\r\n            with open(config['device_list'], 'r') as devs:\r\n                devices = yaml.safe_load(devs)\r\n                params = [p for p in devices if p['device_type'] == 'cisco_nxos']\r\n                return params\r\n\r\n    def setUp(self):\r\n        self.loop = asyncio.new_event_loop()\r\n        self.loop.set_debug(False)\r\n        asyncio.set_event_loop(self.loop)\r\n        self.devices = self.load_credits()\r\n        self.assertFalse(len(self.devices) == 0)\r\n\r\n    def test_show_run_hostname(self):\r\n        async def task():\r\n            for dev in self.devices:\r\n                async with netdev.create(**dev) as nxos:\r\n                    out = await nxos.send_command('show run | i hostname')\r\n                    self.assertIn(\"hostname\", out)\r\n\r\n        self.loop.run_until_complete(task())\r\n\r\n    def test_timeout(self):\r\n        async def task():\r\n            for dev in self.devices:\r\n                with self.assertRaises(netdev.TimeoutError):\r\n                    async with netdev.create(**dev, timeout=0.1) as nxos:\r\n                        await nxos.send_command('show run | i hostname')\r\n\r\n        self.loop.run_until_complete(task())\r\n\r\n    def test_show_several_commands(self):\r\n        async def task():\r\n            for dev in self.devices:\r\n                async with netdev.create(**dev) as nxos:\r\n                    commands = [\"dir\", \"show ver\", \"show run\", \"show ssh key\"]\r\n                    for cmd in commands:\r\n                        out = await nxos.send_command(cmd, strip_command=False)\r\n                        self.assertIn(cmd, out)\r\n\r\n        self.loop.run_until_complete(task())\r\n\r\n    def test_config_set(self):\r\n        async def task():\r\n            for dev in self.devices:\r\n                async with netdev.create(**dev) as nxos:\r\n                    commands = [\"line con\", \"exit\"]\r\n                    out = await nxos.send_config_set(commands)\r\n                    self.assertIn(\"line con\", out)\r\n                    self.assertIn(\"exit\", out)\r\n\r\n        self.loop.run_until_complete(task())\r\n\r\n    def test_base_prompt(self):\r\n        async def task():\r\n            for dev in self.devices:\r\n                async with netdev.create(**dev) as nxos:\r\n                    out = await nxos.send_command('sh run | i hostname')\r\n                    self.assertIn(nxos.base_prompt, out)\r\n\r\n        self.loop.run_until_complete(task())\r\n"
  },
  {
    "path": "tests/test_fujitsu_switch.py",
    "content": "import asyncio\r\nimport logging\r\nimport unittest\r\n\r\nimport yaml\r\n\r\nimport netdev\r\n\r\nlogging.basicConfig(filename='unittest.log', level=logging.DEBUG)\r\nconfig_path = 'config.yaml'\r\n\r\n\r\nclass TestFujitsu(unittest.TestCase):\r\n    @staticmethod\r\n    def load_credits():\r\n        with open(config_path, 'r') as conf:\r\n            config = yaml.safe_load(conf)\r\n            with open(config['device_list'], 'r') as devs:\r\n                devices = yaml.safe_load(devs)\r\n                params = [p for p in devices if p['device_type'] == 'fujitsu_switch']\r\n                return params\r\n\r\n    def setUp(self):\r\n        self.loop = asyncio.new_event_loop()\r\n        self.loop.set_debug(False)\r\n        asyncio.set_event_loop(self.loop)\r\n        self.devices = self.load_credits()\r\n        self.assertFalse(len(self.devices) == 0)\r\n\r\n    def test_show_run_hostname(self):\r\n        async def task():\r\n            for dev in self.devices:\r\n                async with netdev.create(**dev) as fuj:\r\n                    out = await fuj.send_command('show run | i snmp')\r\n                    self.assertIn(\"snmp\", out)\r\n\r\n        self.loop.run_until_complete(task())\r\n\r\n    def test_timeout(self):\r\n        async def task():\r\n            for dev in self.devices:\r\n                with self.assertRaises(netdev.TimeoutError):\r\n                    async with netdev.create(**dev, timeout=0.1) as fuj:\r\n                        await fuj.send_command('show run | i snmp')\r\n\r\n        self.loop.run_until_complete(task())\r\n\r\n    def test_show_several_commands(self):\r\n        async def task():\r\n            for dev in self.devices:\r\n                async with netdev.create(**dev) as fuj:\r\n                    commands = [\"dir\", \"show ver\", \"show run\", \"show ssh\"]\r\n                    for cmd in commands:\r\n                        out = await fuj.send_command(cmd, strip_command=False)\r\n                        self.assertIn(cmd, out)\r\n\r\n        self.loop.run_until_complete(task())\r\n\r\n    def test_config_set(self):\r\n        async def task():\r\n            for dev in self.devices:\r\n                async with netdev.create(**dev) as fuj:\r\n                    commands = [\"vlan database\", \"exit\"]\r\n                    out = await fuj.send_config_set(commands)\r\n                    self.assertIn(\"vlan database\", out)\r\n                    self.assertIn(\"exit\", out)\r\n\r\n        self.loop.run_until_complete(task())\r\n\r\n    def test_base_prompt(self):\r\n        async def task():\r\n            for dev in self.devices:\r\n                async with netdev.create(**dev) as fuj:\r\n                    out = await fuj.send_command(\"sh run | i 'switch '\")\r\n                    self.assertIn(fuj.base_prompt, out)\r\n\r\n        self.loop.run_until_complete(task())\r\n"
  },
  {
    "path": "tests/test_hp_comware.py",
    "content": "import asyncio\r\nimport logging\r\nimport unittest\r\n\r\nimport yaml\r\n\r\nimport netdev\r\n\r\nlogging.basicConfig(filename='unittest.log', level=logging.DEBUG)\r\nconfig_path = 'config.yaml'\r\n\r\n\r\nclass TestComware(unittest.TestCase):\r\n    @staticmethod\r\n    def load_credits():\r\n        with open(config_path, 'r') as conf:\r\n            config = yaml.safe_load(conf)\r\n            with open(config['device_list'], 'r') as devs:\r\n                devices = yaml.safe_load(devs)\r\n                params = [p for p in devices if p['device_type'] == 'hp_comware']\r\n                return params\r\n\r\n    def setUp(self):\r\n        self.loop = asyncio.new_event_loop()\r\n        self.loop.set_debug(False)\r\n        asyncio.set_event_loop(self.loop)\r\n        self.devices = self.load_credits()\r\n        self.assertFalse(len(self.devices) == 0)\r\n\r\n    def test_show_sysname(self):\r\n        async def task():\r\n            for dev in self.devices:\r\n                async with netdev.create(**dev) as hp:\r\n                    out = await hp.send_command('display cur | i sysname')\r\n                    self.assertIn(\"sysname\", out)\r\n\r\n        self.loop.run_until_complete(task())\r\n\r\n    def test_show_several_commands(self):\r\n        async def task():\r\n            for dev in self.devices:\r\n                async with netdev.create(**dev) as hp:\r\n                    commands = [\"dir\", \"display ver\", \"display cur\", \"display ssh server status\"]\r\n                    for cmd in commands:\r\n                        out = await hp.send_command(cmd, strip_command=False)\r\n                        self.assertIn(cmd, out)\r\n\r\n        self.loop.run_until_complete(task())\r\n\r\n    def test_config_set(self):\r\n        async def task():\r\n            for dev in self.devices:\r\n                async with netdev.create(**dev) as hp:\r\n                    commands = [\"vlan 1\", \"quit\"]\r\n                    out = await hp.send_config_set(commands)\r\n                    self.assertIn(\"vlan 1\", out)\r\n                    self.assertIn(\"quit\", out)\r\n\r\n        self.loop.run_until_complete(task())\r\n\r\n    def test_base_prompt(self):\r\n        async def task():\r\n            for dev in self.devices:\r\n                async with netdev.create(**dev) as hp:\r\n                    out = await hp.send_command('display cur | i sysname')\r\n                    self.assertIn(hp.base_prompt, out)\r\n\r\n        self.loop.run_until_complete(task())\r\n\r\n    def test_timeout(self):\r\n        async def task():\r\n            for dev in self.devices:\r\n                with self.assertRaises(netdev.TimeoutError):\r\n                    async with netdev.create(**dev, timeout=0.1) as hp:\r\n                        await hp.send_command('display cur | i sysname')\r\n\r\n        self.loop.run_until_complete(task())"
  },
  {
    "path": "tests/test_hp_comware_limited.py",
    "content": "import asyncio\r\nimport logging\r\nimport unittest\r\n\r\nimport yaml\r\n\r\nimport netdev\r\n\r\nlogging.basicConfig(filename='unittest.log', level=logging.DEBUG)\r\nconfig_path = 'config.yaml'\r\n\r\n\r\nclass TestComwareLimited(unittest.TestCase):\r\n    @staticmethod\r\n    def load_credits():\r\n        with open(config_path, 'r') as conf:\r\n            config = yaml.safe_load(conf)\r\n            with open(config['device_list'], 'r') as devs:\r\n                devices = yaml.safe_load(devs)\r\n                params = [p for p in devices if p['device_type'] == 'hp_comware_limited']\r\n                return params\r\n\r\n    def setUp(self):\r\n        self.loop = asyncio.new_event_loop()\r\n        self.loop.set_debug(False)\r\n        asyncio.set_event_loop(self.loop)\r\n        self.devices = self.load_credits()\r\n        self.assertFalse(len(self.devices) == 0)\r\n\r\n    def test_show_sysname(self):\r\n        async def task():\r\n            for dev in self.devices:\r\n                async with netdev.create(**dev) as hp:\r\n                    out = await hp.send_command('display cur | i sysname')\r\n                    self.assertIn(\"sysname\", out)\r\n\r\n        self.loop.run_until_complete(task())\r\n\r\n    def test_show_several_commands(self):\r\n        async def task():\r\n            for dev in self.devices:\r\n                async with netdev.create(**dev) as hp:\r\n                    commands = [\"dir\", \"display ver\", \"display cur\", \"display ssh server status\"]\r\n                    for cmd in commands:\r\n                        out = await hp.send_command(cmd, strip_command=False)\r\n                        self.assertIn(cmd, out)\r\n\r\n        self.loop.run_until_complete(task())\r\n\r\n    def test_config_set(self):\r\n        async def task():\r\n            for dev in self.devices:\r\n                async with netdev.create(**dev) as hp:\r\n                    commands = [\"vlan 1\", \"quit\"]\r\n                    out = await hp.send_config_set(commands)\r\n                    self.assertIn(\"vlan 1\", out)\r\n                    self.assertIn(\"quit\", out)\r\n\r\n        self.loop.run_until_complete(task())\r\n\r\n    def test_base_prompt(self):\r\n        async def task():\r\n            for dev in self.devices:\r\n                async with netdev.create(**dev) as hp:\r\n                    out = await hp.send_command('display cur | i sysname')\r\n                    self.assertIn(hp.base_prompt, out)\r\n\r\n        self.loop.run_until_complete(task())\r\n\r\n    def test_timeout(self):\r\n        async def task():\r\n            for dev in self.devices:\r\n                with self.assertRaises(netdev.TimeoutError):\r\n                    async with netdev.create(**dev, timeout=0.1) as hp:\r\n                        await hp.send_command('display cur | i sysname')\r\n\r\n        self.loop.run_until_complete(task())\r\n"
  },
  {
    "path": "tests/test_huawei.py",
    "content": "import asyncio\nimport logging\nimport unittest\n\nimport yaml\n\nimport netdev\n\nlogging.basicConfig(filename='unittest.log', level=logging.DEBUG)\nconfig_path = 'config.yaml'\n\n\nclass TestHuawei(unittest.TestCase):\n    @staticmethod\n    def load_credits():\n        with open(config_path, 'r') as conf:\n            config = yaml.safe_load(conf)\n            with open(config['device_list'], 'r') as devs:\n                devices = yaml.safe_load(devs)\n                params = [p for p in devices if p['device_type'] == 'huawei']\n                return params\n\n    def setUp(self):\n        self.loop = asyncio.new_event_loop()\n        self.loop.set_debug(False)\n        asyncio.set_event_loop(self.loop)\n        self.devices = self.load_credits()\n        self.assertFalse(len(self.devices) == 0)\n\n    def test_show_sysname(self):\n        async def task():\n            for dev in self.devices:\n                async with netdev.create(**dev) as huawei:\n                    out = await huawei.send_command('display cur | i sysname')\n                    self.assertIn(\"sysname\", out)\n\n        self.loop.run_until_complete(task())\n\n    def test_show_several_commands(self):\n        async def task():\n            for dev in self.devices:\n                async with netdev.create(**dev) as huawei:\n                    commands = [\"dir\", \"display ver\", \"display cur\"]\n                    for cmd in commands:\n                        out = await huawei.send_command(cmd, strip_command=False)\n                        self.assertIn(cmd, out)\n\n        self.loop.run_until_complete(task())\n\n    def test_config_set(self):\n        async def task():\n            for dev in self.devices:\n                async with netdev.create(**dev) as huawei:\n                    commands = [\"vlan 1\", \"quit\"]\n                    out = await huawei.send_config_set(commands)\n                    self.assertIn(\"vlan 1\", out)\n                    self.assertIn(\"quit\", out)\n\n        self.loop.run_until_complete(task())\n\n    def test_base_prompt(self):\n        async def task():\n            for dev in self.devices:\n                async with netdev.create(**dev) as huawei:\n                    out = await huawei.send_command('display cur | i sysname')\n                    self.assertIn(huawei.base_prompt, out)\n\n        self.loop.run_until_complete(task())\n\n    def test_timeout(self):\n        async def task():\n            for dev in self.devices:\n                with self.assertRaises(netdev.TimeoutError):\n                    async with netdev.create(**dev, timeout=0.1) as huawei:\n                        await huawei.send_command('display cur | i sysname')\n\n        self.loop.run_until_complete(task())"
  },
  {
    "path": "tests/test_hw1000.py",
    "content": "import asyncio\r\nimport logging\r\nimport unittest\r\nimport yaml\r\nimport netdev\r\n\r\nlogging.basicConfig(filename='unittest.log', level=logging.DEBUG)\r\nconfig_path = 'config.yaml'\r\n\r\nclass TestHW1000(unittest.TestCase):\r\n    @staticmethod\r\n    def load_credits():\r\n        with open(config_path, 'r') as conf:\r\n            config = yaml.load(conf)\r\n            with open(config['device_list'], 'r') as devs:\r\n                devices = yaml.load(devs)\r\n                params = [p for p in devices if p['device_type'] == 'hw1000']\r\n                return params\r\n\r\n    def setUp(self):\r\n        self.loop = asyncio.new_event_loop()\r\n        self.loop.set_debug(False)\r\n        asyncio.set_event_loop(self.loop)\r\n        self.devices = self.load_credits()\r\n        self.assertFalse(len(self.devices) == 0)\r\n\r\n    def test_simple_command(self):\r\n        async def task():\r\n            for dev in self.devices:\r\n                async with netdev.create(**dev) as hw:\r\n                    out = await hw.send_command(\"inet show snmp\")\r\n                    self.assertIn('SNMP',out)\r\n        self.loop.run_until_complete(task())\r\n\r\n    def test_long_command(self):\r\n        async def task():\r\n            for dev in self.devices:\r\n                async with netdev.create(**dev) as hw:\r\n                    out = await hw.send_command(\"inet show interface\")\r\n                    out_len=(len(out.split('\\n')))\r\n                    self.assertGreater(out_len,10)\r\n        self.loop.run_until_complete(task())\r\n\r\n    def test_linux_mode(self):\r\n        async def task():\r\n            for dev in self.devices:\r\n                async with netdev.create(**dev) as hw:\r\n                    out = await hw.enter_shell_mode()\r\n                    out = await hw.send_command(\"id\")\r\n                    self.assertIn('uid=0(root)',out)\r\n        self.loop.run_until_complete(task())\r\n\r\n    def test_linux_mode_indepotence(self):\r\n        async def task():\r\n            for dev in self.devices:\r\n                async with netdev.create(**dev) as hw:\r\n                    out = await hw.enter_shell_mode()\r\n                    out = await hw.enter_shell_mode()\r\n                    out = await hw.send_command(\"id\")\r\n                    self.assertIn('uid=0(root)',out)\r\n        self.loop.run_until_complete(task())\r\n"
  },
  {
    "path": "tests/test_juniper_junos.py",
    "content": "import asyncio\r\nimport logging\r\nimport unittest\r\n\r\nimport yaml\r\n\r\nimport netdev\r\n\r\nlogging.basicConfig(filename='unittest.log', level=logging.DEBUG)\r\nconfig_path = 'config.yaml'\r\n\r\n\r\nclass TestJunOS(unittest.TestCase):\r\n    @staticmethod\r\n    def load_credits():\r\n        with open(config_path, 'r') as conf:\r\n            config = yaml.safe_load(conf)\r\n            with open(config['device_list'], 'r') as devs:\r\n                devices = yaml.safe_load(devs)\r\n                params = [p for p in devices if p['device_type'] == 'juniper_junos']\r\n                return params\r\n\r\n    def setUp(self):\r\n        self.loop = asyncio.new_event_loop()\r\n        self.loop.set_debug(False)\r\n        asyncio.set_event_loop(self.loop)\r\n        self.devices = self.load_credits()\r\n        self.assertFalse(len(self.devices) == 0)\r\n\r\n    def test_show_system_hostname(self):\r\n        async def task():\r\n            for dev in self.devices:\r\n                async with netdev.create(**dev) as junos:\r\n                    out = await junos.send_command('show configuration system host-name')\r\n                    self.assertIn(\"host-name\", out)\r\n\r\n        self.loop.run_until_complete(task())\r\n\r\n    def test_timeout(self):\r\n        async def task():\r\n            for dev in self.devices:\r\n                with self.assertRaises(netdev.TimeoutError):\r\n                    async with netdev.create(**dev, timeout=0.1) as junos:\r\n                        await junos.send_command('show configuration system host-name')\r\n\r\n        self.loop.run_until_complete(task())\r\n\r\n    def test_show_several_commands(self):\r\n        async def task():\r\n            for dev in self.devices:\r\n                async with netdev.create(**dev) as junos:\r\n                    commands = [\"show ver\", \"show conf\", \"show chassis firmware\"]\r\n                    for cmd in commands:\r\n                        out = await junos.send_command(cmd, strip_command=False)\r\n                        self.assertIn(cmd, out)\r\n\r\n        self.loop.run_until_complete(task())\r\n\r\n    def test_config_set(self):\r\n        async def task():\r\n            for dev in self.devices:\r\n                async with netdev.create(**dev) as junos:\r\n                    commands = [\"edit system\", \"edit login\"]\r\n                    out = await junos.send_config_set(commands, with_commit=False)\r\n                    self.assertIn(\"edit system\", out)\r\n                    self.assertIn(\"edit login\", out)\r\n\r\n        self.loop.run_until_complete(task())\r\n\r\n    def test_base_prompt(self):\r\n        async def task():\r\n            for dev in self.devices:\r\n                async with netdev.create(**dev) as junos:\r\n                    out = await junos.send_command('show configuration system host-name')\r\n                    self.assertIn(junos.base_prompt, out)\r\n\r\n        self.loop.run_until_complete(task())\r\n\r\n    def test_interactive_commands(self):\r\n        async def task():\r\n            for dev in self.devices:\r\n                async with netdev.create(**dev) as junos:\r\n                    commands = [\"set system login message 123\", \"delete system login message 123\"]\r\n                    out = await junos.send_config_set(commands, with_commit=False, exit_config_mode=False)\r\n                    out += await junos.send_command(\"exit\", pattern=r'Exit with uncommitted changes\\?',\r\n                                                    strip_command=False)\r\n                    out += await junos.send_command(\"no\", strip_command=False)\r\n                    out += await junos.send_command(\"rollback 0\", strip_command=False)\r\n                    out += await junos.send_command(\"exit configuration-mode\", strip_command=False)\r\n                    self.assertIn('load complete', out)\r\n\r\n        self.loop.run_until_complete(task())\r\n"
  },
  {
    "path": "tests/test_mikrotik_routeros.py",
    "content": "import asyncio\r\nimport logging\r\nimport unittest\r\n\r\nimport yaml\r\n\r\nimport netdev\r\n\r\nlogging.basicConfig(filename='unittest.log', level=logging.DEBUG)\r\nconfig_path = 'config.yaml'\r\n\r\n\r\nclass TestRouterOS(unittest.TestCase):\r\n    @staticmethod\r\n    def load_credits():\r\n        with open(config_path, 'r') as conf:\r\n            config = yaml.safe_load(conf)\r\n            with open(config['device_list'], 'r') as devs:\r\n                devices = yaml.safe_load(devs)\r\n                params = [p for p in devices if p['device_type'] == 'mikrotik_routeros']\r\n                return params\r\n\r\n    def setUp(self):\r\n        self.loop = asyncio.new_event_loop()\r\n        self.loop.set_debug(False)\r\n        asyncio.set_event_loop(self.loop)\r\n        self.devices = self.load_credits()\r\n        self.assertFalse(len(self.devices) == 0)\r\n\r\n    def test_show_system_identity(self):\r\n        async def task():\r\n            for dev in self.devices:\r\n                async with netdev.create(**dev) as mik:\r\n                    out = await mik.send_command('/system identity print')\r\n                    self.assertIn(mik.base_prompt, out)\r\n\r\n        self.loop.run_until_complete(task())\r\n\r\n    def test_timeout(self):\r\n        async def task():\r\n            for dev in self.devices:\r\n                with self.assertRaises(netdev.TimeoutError):\r\n                    async with netdev.create(**dev, timeout=0.1) as mik:\r\n                        await mik.send_command('/system identity print')\r\n\r\n        self.loop.run_until_complete(task())\r\n\r\n    def test_show_several_commands(self):\r\n        async def task():\r\n            for dev in self.devices:\r\n                async with netdev.create(**dev) as mik:\r\n                    commands = [\"/ip address print\", \"/system package print\", \" /user print\"]\r\n                    for cmd in commands:\r\n                        out = await mik.send_command(cmd, strip_command=False)\r\n                        self.assertIn(cmd, out)\r\n\r\n        self.loop.run_until_complete(task())\r\n"
  },
  {
    "path": "tests/test_terminal.py",
    "content": "import asyncio\r\nimport logging\r\nimport unittest\r\n\r\nimport yaml\r\n\r\nimport netdev\r\n\r\nlogging.basicConfig(filename='unittest.log', level=logging.DEBUG)\r\nconfig_path = 'config.yaml'\r\n\r\n\r\nclass TestTerminal(unittest.TestCase):\r\n    @staticmethod\r\n    def load_credits():\r\n        with open(config_path, 'r') as conf:\r\n            config = yaml.safe_load(conf)\r\n            with open(config['device_list'], 'r') as devs:\r\n                devices = yaml.safe_load(devs)\r\n                params = [p for p in devices if p['device_type'] == 'terminal']\r\n                return params\r\n\r\n    def setUp(self):\r\n        self.loop = asyncio.new_event_loop()\r\n        self.loop.set_debug(False)\r\n        asyncio.set_event_loop(self.loop)\r\n        self.devices = self.load_credits()\r\n        self.assertFalse(len(self.devices) == 0)\r\n\r\n    def test_show_several_commands(self):\r\n        async def task():\r\n            for dev in self.devices:\r\n                async with netdev.create(**dev) as terminal:\r\n                    commands = [\"ls -al\", \"pwd\", \"echo test\"]\r\n                    for cmd in commands:\r\n                        out = await terminal.send_command(cmd, strip_command=False)\r\n                        self.assertIn(cmd, out)\r\n\r\n        self.loop.run_until_complete(task())\r\n\r\n    def test_timeout(self):\r\n        async def task():\r\n            for dev in self.devices:\r\n                with self.assertRaises(netdev.TimeoutError):\r\n                    async with netdev.create(**dev, timeout=0.1) as terminal:\r\n                        out = await terminal.send_command(\"uname -a\")\r\n\r\n        self.loop.run_until_complete(task())\r\n"
  }
]