Python client for Arista eAPI

Overview

Arista eAPI Python Library

Build Status Coverage Status Documentation Status

The Python library for Arista's eAPI command API implementation provides a client API work using eAPI and communicating with EOS nodes. The Python library can be used to communicate with EOS either locally (on-box) or remotely (off-box). It uses a standard INI-style configuration file to specify one or more nodes and connection properties.

The pyeapi library also provides an API layer for building native Python objects to interact with the destination nodes. The API layer is a convenient implementation for working with the EOS configuration and is extensible for developing custom implementations.

This library is freely provided to the open source community for building robust applications using Arista EOS. Support is provided as best effort through Github issues.

Documentation

Building Local Documentation

If you cannot access readthedocs.org you have the option of building the documentation locally.

  1. pip install -r dev-requirements.txt
  2. cd docs
  3. make html
  4. open _build/html/index.html

License

Copyright (c) 2015, Arista Networks EOS+ All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

  • Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.

  • Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

  • Neither the name of the Arista nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Comments
  • Certificate validation doesn't work

    Certificate validation doesn't work

    I tried to make certificate validation work, but it seems it's not possible at the moment.

    The validation is disabled by default, and if you want to enable it, you have to pass enforce_verification in kwargs to HttpsEapiConnection constructor.

    This constructor is only ever called from client.py / make_connection(), which in turn is only ever called from this line: https://github.com/arista-eosplus/pyeapi/blob/35557de723152bf00a981082805f173accb99485/pyeapi/client.py#L427

    As you can see, we never pass the enforce_verification to make_connection function.

    We need to either pass down **kwargs, or at the very least the enforce_verification should it ever be set.

    opened by zloo 14
  • add banner support to system api

    add banner support to system api

    TAC had a requirement for an internal tool to change the banner on lab switches programmatically, so I thought this would be a nice add to the pyeapi library

    enhancement 
    opened by dathelen 11
  • New release

    New release

    Hi Is anything blocking a new release? I'm interested in not maintaining my fork anymore -- if there's a pending task or so that you need help with to get a release out, I can help you!

    opened by DavidVentura 8
  • When excepting

    When excepting "pyeapi.eapilib.ConnectionError" I still get the pyeapi script spewing socket exceptions to the screen

    Traceback (most recent call last):
      File "/home/shimamizu/.pyenv/versions/3.9.11/lib/python3.9/site-packages/pyeapi/eapilib.py", line 447, in send
        response_content = response.read()
      File "/home/shimamizu/.pyenv/versions/3.9.11/lib/python3.9/http/client.py", line 470, in read
        return self._readall_chunked()
      File "/home/shimamizu/.pyenv/versions/3.9.11/lib/python3.9/http/client.py", line 577, in _readall_chunked
        chunk_left = self._get_chunk_left()
      File "/home/shimamizu/.pyenv/versions/3.9.11/lib/python3.9/http/client.py", line 560, in _get_chunk_left
        chunk_left = self._read_next_chunk_size()
      File "/home/shimamizu/.pyenv/versions/3.9.11/lib/python3.9/http/client.py", line 520, in _read_next_chunk_size
        line = self.fp.readline(_MAXLINE + 1)
      File "/home/shimamizu/.pyenv/versions/3.9.11/lib/python3.9/socket.py", line 704, in readinto
        return self._sock.recv_into(b)
      File "/home/shimamizu/.pyenv/versions/3.9.11/lib/python3.9/ssl.py", line 1241, in recv_into
        return self.read(nbytes, buffer)
      File "/home/shimamizu/.pyenv/versions/3.9.11/lib/python3.9/ssl.py", line 1099, in read
        return self._sslobj.read(len, buffer)
    socket.timeout: The read operation timed out
    Error connecting to the eAPI for {my_hostname}
    

    The last line is proof that my exception did catch it:

    except pyeapi.eapilib.ConnectionError as conn_error:
                print(f"Error connecting to the eAPI for {self.switch_hostname}")
    

    I have also tried adding an exception for socket.timeout in my pyeapi script wrapper, but that never catches it, since the socket.timeout portion of the error appears to be happening inside the pyeapi library, not handling well, and then just passing the pyeapi.eapilib.ConnectionError back to me which I am able to catch.

    In my logging file I then just see:

    self.logger.warning(
                    f"Connection error on {self.switch_hostname}:\n {str(conn_error.message)}"
                )
    
    2022-06-27 12:03:25,739 WARNING  Connection error on {my_hostname}:
     Socket error during eAPI connection: The read operation timed out
    

    That second line I assume been the error that the pyeapi sent back about socket.timeout

    I would like all the barfing from socket.timeout not to print on screen when I'm catching pyeapi.eapilib.ConnectionError correctly

    question 
    opened by shimamizu 7
  • ssl Handshake failure while connecting to devices when using python 3.10.2

    ssl Handshake failure while connecting to devices when using python 3.10.2

    Here is the failure log: /usr/local/lib/python3.10/site-packages/vane-1.0.0-py3.10.egg/vane/tests_tools.py:817: in return_show_cmd show_output = conn.enable(show_cmd) /usr/local/lib/python3.10/site-packages/pyeapi/client.py:712: in enable resp = self.run_commands(command, encoding, send_enable, /usr/local/lib/python3.10/site-packages/pyeapi/client.py:771: in run_commands response = self._connection.execute(commands, encoding, **kwargs) /usr/local/lib/python3.10/site-packages/pyeapi/eapilib.py:554: in execute response = self.send(request)


    self = EapiConnection(transport=https://10.255.74.38:443//command-api) data = b'{"jsonrpc": "2.0", "method": "runCmds", "params": {"version": 1, "cmds": ["enable", "show agent logs crash"], "format": "json"}, "id": "140108890278976", "streaming": false}' def send(self, data): """Sends the eAPI request to the destination node

        This method is responsible for sending an eAPI request to the
        destination node and returning a response based on the eAPI response
        object.  eAPI responds to request messages with either a success
        message or failure message.
    
        eAPI Response - success
    
        .. code-block:: json
    
            {
                "jsonrpc": "2.0",
                "result": [
                    {},
                    {}
                    {
                        "warnings": [
                            <message>
                        ]
                    },
                ],
                "id": <reqid>
            }
    
        eAPI Response - failure
    
        .. code-block:: json
    
            {
                "jsonrpc": "2.0",
                "error": {
                    "code": <int>,
                    "message": <string>
                    "data": [
                        {},
                        {},
                        {
                            "errors": [
                                <message>
                            ]
                        }
                    ]
                }
                "id": <reqid>
            }
    
        Args:
            data (string): The data to be included in the body of the eAPI
                request object
    
        Returns:
            A decoded response.  The response object is deserialized from
                JSON and returned as a standard Python dictionary object
    
        Raises:
            CommandError if an eAPI failure response object is returned from
                the node.   The CommandError exception includes the error
                code and error message from the eAPI response.
        """
        try:
            _LOGGER.debug('Request content: {}'.format(data))
            # debug('eapi_request: %s' % data)
    
            self.transport.putrequest('POST', '/command-api')
    
            self.transport.putheader('Content-type', 'application/json-rpc')
            self.transport.putheader('Content-length', '%d' % len(data))
    
            if self._auth:
                self.transport.putheader('Authorization',
                                         'Basic %s' % self._auth)
    
            if int(sys.version[0]) > 2:
                # For Python 3.x compatibility
                data = data.encode()
    
            self.transport.endheaders(message_body=data)
    
            try:  # Python 2.7: use buffering of HTTP responses
                response = self.transport.getresponse(buffering=True)
            except TypeError:  # Python 2.6: older, and 3.x on
                response = self.transport.getresponse()
    
            response_content = response.read()
            _LOGGER.debug('Response: status:{status}, reason:{reason}'.format(
                          status=response.status,
                          reason=response.reason))
            _LOGGER.debug('Response content: {}'.format(response_content))
    
            if response.status == 401:
                raise ConnectionError(str(self), '%s. %s' % (response.reason,
                                                             response_content))
    
            # Work around for Python 2.7/3.x compatibility
            if not type(response_content) == str:
                # For Python 3.x - decode bytes into string
                response_content = response_content.decode()
            decoded = json.loads(response_content)
            _LOGGER.debug('eapi_response: %s' % decoded)
    
            if 'error' in decoded:
                (code, msg, err, out) = self._parse_error_message(decoded)
                pattern = "unexpected keyword argument '(.*)'"
                match = re.search(pattern, msg)
                if match:
                    auto_msg = ('%s parameter is not supported in this'
                                ' version of EOS.' % match.group(1))
                    _LOGGER.error(auto_msg)
                    msg = msg + '. ' + auto_msg
                raise CommandError(code, msg, command_error=err, output=out)
    
            return decoded
    
        # socket.error is deprecated in python 3 and replaced with OSError.
        except (socket.error, OSError) as exc:
            _LOGGER.exception(exc)
            self.socket_error = exc
            self.error = exc
            error_msg = 'Socket error during eAPI connection: %s' % str(exc)
    
          raise ConnectionError(str(self), error_msg)
    

    E pyeapi.eapilib.ConnectionError: Socket error during eAPI connection: [SSL: SSLV3_ALERT_HANDSHAKE_FAILURE] sslv3 alert handshake failure (_ssl.c:997) /usr/local/lib/python3.10/site-packages/pyeapi/eapilib.py:483: ConnectionError

    Probably it is hitting this problem and we need to change pyeapi code? https://stackoverflow.com/questions/56719290/how-to-solve-the-handshake-failure-using-ssl-in-python

    opened by shachiagarwal 7
  • Switchports API crashing on subinterfaces

    Switchports API crashing on subinterfaces

    Device:

    Arista DCS-7050SX3-48YC8-R
    Hardware version:      11.15
    
    Software image version: 4.23.3M
    Architecture:           i686
    Internal build version: 4.23.3M-16431779.4233M
    

    Port config:

    interface Ethernet48.2044
       description some port description
       no shutdown
       default load-interval
       logging event link-status use-global
       encapsulation dot1q vlan 2044
       snmp trap link-change
       vrf DAT
       no ip proxy-arp
       no ip local-proxy-arp
       no arp gratuitous accept
       ip address 100.76.1.41/31
       no ip verify unicast
       no ip directed-broadcast
       ip attached-routes
       default arp aging timeout
       default ipv6 nd cache expire
       no bfd echo
       no bfd authentication mode
       default ip dhcp relay all-subnets
       no ip helper-address
       no ipv6 dhcp relay destination
       no ipv6 dhcp relay add vendor-option ccap-core
       no ipv6 dhcp relay install routes
       ip dhcp relay information option circuit-id Ethernet48.2044
       no dhcp server ipv4
       no dhcp server ipv6
       no ip attached-host route export
       no ipv6 attached-host route export
       no ip igmp
       ip igmp version 3
       ip igmp last-member-query-count 2
       ip igmp last-member-query-interval 10
       igmp query-max-response-time 100
       ip igmp query-interval 125
       ip igmp startup-query-count 2
       ip igmp startup-query-interval 310
       ip igmp router-alert optional connected
       no ip igmp host-proxy
       no ipv6 enable
       default ipv6 nd dad
       no ipv6 address
       no ipv6 nd ra rx accept default-route
       ipv6 attached-routes
       no ipv6 verify unicast
       no ipv6 nd ra disabled
       ipv6 nd ra interval msec 200000
       ipv6 nd ra lifetime 1800
       no ipv6 nd ra mtu suppress
       no ipv6 nd managed-config-flag
       no ipv6 nd other-config-flag
       ipv6 nd reachable-time 0
       ipv6 nd router-preference medium
       ipv6 nd ra dns-servers lifetime 300
       ipv6 nd ra dns-suffixes lifetime 300
       ipv6 nd ra hop-limit 64
       no tcp mss ceiling
       no multicast ipv4 source route export
       no multicast ipv6 source route export
       no multicast ipv4 static
       no multicast ipv6 static
       mfib ipv4 fastdrop
       no mld
       no mld static-group access-list
       mld query-interval 125
       mld query-response-interval 10
       no mld startup-query-interval
       mld startup-query-count 2
       mld robustness 2
       mld last-listener-query-interval 1
       mld last-listener-query-count 2
       mpls ip
       default ntp serve
       no pim ipv4 sparse-mode
       no pim ipv4 bidirectional
       no pim ipv4 border-router
       pim ipv4 hello interval 30
       pim ipv4 hello count 3.5
       pim ipv4 dr-priority 1
       pim ipv4 join-prune interval 60
       pim ipv4 join-prune count 3.5
       no pim ipv4 neighbor filter 
       default pim ipv4 bfd
       no  pim ipv4 join-prune transport sctp
       no  pim ipv4 local-interface
       no  pim ipv4 non-dr install-oifs
       no pim ipv6 sparse-mode
       no pim ipv6 border-router
       pim ipv6 hello interval 30
       pim ipv6 hello count 3.5
       pim ipv6 dr-priority 1
       pim ipv6 join-prune interval 60
       pim ipv6 join-prune count 3.5
       no pim ipv6 neighbor filter 
       default pim ipv6 bfd
       no pim bsr ipv4 border
       no pim bsr ipv6 border
       no rip v2 multicast disable
       no node-segment ipv4 index
       no node-segment ipv6 index
    !
    
    

    the key part is that this does not include the string "no switchport" - so it is getting parsed as an L2 interface as getall() does not filter out subinterfaces.

    opened by DavidVentura 6
  • No cipher option

    No cipher option

    EOS uses deprecated ciphers by default and we can’t specify the ciphers to use (with ssl.create_default_context().set_ciphers('DHE-RSA-AES256-SHA'), so it’s impossible to connect from a system removing deprecated ciphers by default:

    Traceback (most recent call last):
      File "/usr/lib/python3.9/site-packages/pyeapi/eapilib.py", line 440, in send
        self.transport.endheaders(message_body=data)
      File "/usr/lib/python3.9/http/client.py", line 1252, in endheaders
        self._send_output(message_body, encode_chunked=encode_chunked)
      File "/usr/lib/python3.9/http/client.py", line 1012, in _send_output
        self.send(msg)
      File "/usr/lib/python3.9/http/client.py", line 952, in send
        self.connect()
      File "/usr/lib/python3.9/http/client.py", line 1426, in connect
        self.sock = self._context.wrap_socket(self.sock,
      File "/usr/lib/python3.9/ssl.py", line 500, in wrap_socket
        return self.sslsocket_class._create(
      File "/usr/lib/python3.9/ssl.py", line 1040, in _create
        self.do_handshake()
      File "/usr/lib/python3.9/ssl.py", line 1309, in do_handshake
        self._sslobj.do_handshake()
    ssl.SSLError: [SSL: SSLV3_ALERT_HANDSHAKE_FAILURE] sslv3 alert handshake failure (_ssl.c:1145)
    
    During handling of the above exception, another exception occurred:
    
    Traceback (most recent call last):
      File "/usr/lib/python3.9/site-packages/napalm/eos/eos.py", line 167, in open
        sh_ver = self.device.run_commands(["show version"])
      File "/usr/lib/python3.9/site-packages/napalm/eos/pyeapi_syntax_wrapper.py", line 42, in run_commands
        return super(Node, self).run_commands(commands, *args, **kwargs)
      File "/usr/lib/python3.9/site-packages/pyeapi/client.py", line 771, in run_commands
        response = self._connection.execute(commands, encoding, **kwargs)
      File "/usr/lib/python3.9/site-packages/pyeapi/eapilib.py", line 554, in execute
        response = self.send(request)
      File "/usr/lib/python3.9/site-packages/pyeapi/eapilib.py", line 483, in send
        raise ConnectionError(str(self), error_msg)
    pyeapi.eapilib.ConnectionError: Socket error during eAPI connection: [SSL: SSLV3_ALERT_HANDSHAKE_FAILURE] sslv3 alert handshake failure (_ssl.c:1145)
    

    Running a simple urllib.request.Request without the cipher option from ssl returns the same error, by specifying the ciphers it works.

    ~ % python
    Python 3.9.6 (default, Sep 22 2021, 15:28:10) 
    [GCC 10.3.0] on linux
    Type "help", "copyright", "credits" or "license" for more information.
    >>> import ssl
    >>> import urllib.request
    >>> url = urllib.request.Request('https://edge-1/')
    >>> ssl_context = ssl.create_default_context()
    >>> ssl_context.set_ciphers('DHE-RSA-AES256-SHA, AES256-SHA')
    >>> data = urllib.request.urlopen(url).read().decode()
    Traceback (most recent call last):
      File "/usr/lib/python3.9/urllib/request.py", line 1346, in do_open
        h.request(req.get_method(), req.selector, req.data, headers,
      File "/usr/lib/python3.9/http/client.py", line 1257, in request
        self._send_request(method, url, body, headers, encode_chunked)
      File "/usr/lib/python3.9/http/client.py", line 1303, in _send_request
        self.endheaders(body, encode_chunked=encode_chunked)
      File "/usr/lib/python3.9/http/client.py", line 1252, in endheaders
        self._send_output(message_body, encode_chunked=encode_chunked)
      File "/usr/lib/python3.9/http/client.py", line 1012, in _send_output
        self.send(msg)
      File "/usr/lib/python3.9/http/client.py", line 952, in send
        self.connect()
      File "/usr/lib/python3.9/http/client.py", line 1426, in connect
        self.sock = self._context.wrap_socket(self.sock,
      File "/usr/lib/python3.9/ssl.py", line 500, in wrap_socket
        return self.sslsocket_class._create(
      File "/usr/lib/python3.9/ssl.py", line 1040, in _create
        self.do_handshake()
      File "/usr/lib/python3.9/ssl.py", line 1309, in do_handshake
        self._sslobj.do_handshake()
    ssl.SSLError: [SSL: SSLV3_ALERT_HANDSHAKE_FAILURE] sslv3 alert handshake failure (_ssl.c:1145)
    
    During handling of the above exception, another exception occurred:
    
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "/usr/lib/python3.9/urllib/request.py", line 214, in urlopen
        return opener.open(url, data, timeout)
      File "/usr/lib/python3.9/urllib/request.py", line 517, in open
        response = self._open(req, data)
      File "/usr/lib/python3.9/urllib/request.py", line 534, in _open
        result = self._call_chain(self.handle_open, protocol, protocol +
      File "/usr/lib/python3.9/urllib/request.py", line 494, in _call_chain
        result = func(*args)
      File "/usr/lib/python3.9/urllib/request.py", line 1389, in https_open
        return self.do_open(http.client.HTTPSConnection, req,
      File "/usr/lib/python3.9/urllib/request.py", line 1349, in do_open
        raise URLError(err)
    urllib.error.URLError: <urlopen error [SSL: SSLV3_ALERT_HANDSHAKE_FAILURE] sslv3 alert handshake failure (_ssl.c:1145)>
    >>> data = urllib.request.urlopen(url, context=ssl_context).read().decode()
    Traceback (most recent call last):
      File "/usr/lib/python3.9/urllib/request.py", line 1346, in do_open
        h.request(req.get_method(), req.selector, req.data, headers,
      File "/usr/lib/python3.9/http/client.py", line 1257, in request
        self._send_request(method, url, body, headers, encode_chunked)
      File "/usr/lib/python3.9/http/client.py", line 1303, in _send_request
        self.endheaders(body, encode_chunked=encode_chunked)
      File "/usr/lib/python3.9/http/client.py", line 1252, in endheaders
        self._send_output(message_body, encode_chunked=encode_chunked)
      File "/usr/lib/python3.9/http/client.py", line 1012, in _send_output
        self.send(msg)
      File "/usr/lib/python3.9/http/client.py", line 952, in send
        self.connect()
      File "/usr/lib/python3.9/http/client.py", line 1426, in connect
        self.sock = self._context.wrap_socket(self.sock,
      File "/usr/lib/python3.9/ssl.py", line 500, in wrap_socket
        return self.sslsocket_class._create(
      File "/usr/lib/python3.9/ssl.py", line 1040, in _create
        self.do_handshake()
      File "/usr/lib/python3.9/ssl.py", line 1309, in do_handshake
        self._sslobj.do_handshake()
    ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate (_ssl.c:1145)
    
    During handling of the above exception, another exception occurred:
    
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "/usr/lib/python3.9/urllib/request.py", line 214, in urlopen
        return opener.open(url, data, timeout)
      File "/usr/lib/python3.9/urllib/request.py", line 517, in open
        response = self._open(req, data)
      File "/usr/lib/python3.9/urllib/request.py", line 534, in _open
        result = self._call_chain(self.handle_open, protocol, protocol +
      File "/usr/lib/python3.9/urllib/request.py", line 494, in _call_chain
        result = func(*args)
      File "/usr/lib/python3.9/urllib/request.py", line 1389, in https_open
        return self.do_open(http.client.HTTPSConnection, req,
      File "/usr/lib/python3.9/urllib/request.py", line 1349, in do_open
        raise URLError(err)
    urllib.error.URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate (_ssl.c:1145)>
    >>> 
    

    Without a ssl context, urrlib can’t connect to the arista box at all, by specifing it, it’s only a matter of self signed certificate.

    opened by alarig 6
  • ConnectionError: Socket error during eAPI connection: The read operation timed out

    ConnectionError: Socket error during eAPI connection: The read operation timed out

    Please, note that this BUG s related to: https://github.com/napalm-automation/napalm-ansible/issues/165#issuecomment-582143234

    I am using NAPALM to perform config-replace on Arista DCS-7060SX2-48YC6-R version 4.21.8M-13902577.4218M.with pyeapi==0.8.3 The session times out no matter what timeout I configure, either http and https. I can use the library ok for other things like send commands.

    I can see the HTTP session up and the configure session created, however no packets are sent/received and configure session remains in pending

       User              Requests       Bytes in       Bytes out    Last hit
    ----------------- -------------- -------------- --------------- --------------
       prd2204.svc       456            530905         3856176      12 seconds ago
    
       User              Requests       Bytes in       Bytes out    Last hit
    ----------------- -------------- -------------- --------------- ---------------
       prd2204.svc       456            530905         3856176      171 seconds ago
    
    l1a.r5b1.ams7#show configuration sessions
    Maximum number of completed sessions: 1
    Maximum number of pending sessions: 5
    
      Name             State         User                 Terminal
      ------------- ------------- ----------------------- -----------
      napalm_101518    pending        prd2204.svc    command-api
    
    The read operation timed out
    Traceback (most recent call last):
      File "/Users/federicoolivieri/git/NaC/lib/python3.7/site-packages/pyeapi/eapilib.py", line 443, in send
        response_content = response.read()
      File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/http/client.py", line 454, in read
        return self._readall_chunked()
      File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/http/client.py", line 561, in _readall_chunked
        chunk_left = self._get_chunk_left()
      File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/http/client.py", line 544, in _get_chunk_left
        chunk_left = self._read_next_chunk_size()
      File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/http/client.py", line 504, in _read_next_chunk_size
        line = self.fp.readline(_MAXLINE + 1)
      File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/socket.py", line 589, in readinto
        return self._sock.recv_into(b)
      File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/ssl.py", line 1049, in recv_into
        return self.read(nbytes, buffer)
      File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/ssl.py", line 908, in read
        return self._sslobj.read(len, buffer)
    socket.timeout: The read operation timed out
    Traceback (most recent call last):
      File "/Users/federicoolivieri/git/NaC/lib/python3.7/site-packages/pyeapi/eapilib.py", line 443, in send
        response_content = response.read()
      File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/http/client.py", line 454, in read
        return self._readall_chunked()
      File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/http/client.py", line 561, in _readall_chunked
        chunk_left = self._get_chunk_left()
      File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/http/client.py", line 544, in _get_chunk_left
        chunk_left = self._read_next_chunk_size()
      File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/http/client.py", line 504, in _read_next_chunk_size
        line = self.fp.readline(_MAXLINE + 1)
      File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/socket.py", line 589, in readinto
        return self._sock.recv_into(b)
      File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/ssl.py", line 1049, in recv_into
        return self.read(nbytes, buffer)
      File "/usr/local/Cellar/python/3.7.0/Frameworks/Python.framework/Versions/3.7/lib/python3.7/ssl.py", line 908, in read
        return self._sslobj.read(len, buffer)
    socket.timeout: The read operation timed out
    
    During handling of the above exception, another exception occurred:
    
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "/Users/federicoolivieri/git/NaC/lib/python3.7/site-packages/napalm/eos/eos.py", line 297, in load_replace_candidate
        self._load_config(filename, config, True)
      File "/Users/federicoolivieri/git/NaC/lib/python3.7/site-packages/napalm/eos/eos.py", line 286, in _load_config
        self.device.run_commands(commands)
      File "/Users/federicoolivieri/git/NaC/lib/python3.7/site-packages/pyeapi/client.py", line 743, in run_commands
        response = self._connection.execute(commands, encoding, **kwargs)
      File "/Users/federicoolivieri/git/NaC/lib/python3.7/site-packages/pyeapi/eapilib.py", line 550, in execute
        response = self.send(request)
      File "/Users/federicoolivieri/git/NaC/lib/python3.7/site-packages/pyeapi/eapilib.py", line 479, in send
        raise ConnectionError(str(self), error_msg)
    pyeapi.eapilib.ConnectionError: Socket error during eAPI connection: The read operation timed out
    
    opened by lvrfrc87 6
  • VRRP module not getting the VRID information from an interface

    VRRP module not getting the VRID information from an interface

    Hello,

    I am using the vrrp.get(<interface>).get(vrid) method to collect VRRP group information but it seems it is not retrieving any data. Below I am pasting what I am receiving along with the configuration on the switch:

    Swtich configuration

    interface Vlan177
       load-interval 5
       ip address 10.177.0.68/28
       vrrp 70 priority 200
       vrrp 70 ip 10.177.0.70
       vrrp 70 track ETH46 shutdown
       vrrp 71 priority 200
       vrrp 71 ip 10.177.0.71
       vrrp 71 shutdown
       vrrp 72 priority 200
       vrrp 72 ip 10.177.0.72
       vrrp 72 shutdown
    

    Python Example

    vrrp = node.api('vrrp')
    >>> pprint(vrrp.get('Vlan177').get(71))
    {'bfd_ip': '',
     'delay_reload': None,
     'description': '',
     'enable': True,
     'ip_version': None,
     'mac_addr_adv_interval': 30,
     'preempt': True,
     'preempt_delay_min': 0,
     'preempt_delay_reload': 0,
     'primary_ip': None,
     'priority': None,
     'secondary_ip': [],
     'timers_advertise': None,
     'track': []}
    >>> pprint(vrrp.get('Vlan177').get(70))
    {'bfd_ip': '',
     'delay_reload': None,
     'description': '',
     'enable': True,
     'ip_version': None,
     'mac_addr_adv_interval': 30,
     'preempt': True,
     'preempt_delay_min': 0,
     'preempt_delay_reload': 0,
     'primary_ip': None,
     'priority': None,
     'secondary_ip': [],
     'timers_advertise': None,
     'track': []}
    

    You can see from the collected data that the priority = None, when the configuration is stated as 200, and even though the vrrp 71 shutdown it returns it as enabled = True.

    Was this working before? should I use another method?

    Thanks,

    opened by davidban77 6
  • Connection failure due to bad username/password fails to report reason

    Connection failure due to bad username/password fails to report reason

    Upon attempting to connect with bad credentials, a ConnectionError is reported with the following information:

    pyeapi.eapilib.ConnectionError: unable to connect to eAPI
    

    There could be a few reasons for this, I would imaging, for example, the device not being configured / enabled for eAPI.

    But the actual device response_content value in the underlying eapilib.py file, when debugged, provides the root cause:

    (Pdb) pp(response_content)
    'Unable to authenticate user: Bad username/password combination'
    

    It would be very helpful if this information (response_content) could be bubbled up as an additional argument value to the ConnectionError.

    Thank you!

    opened by jeremyschulman 6
  • Execute does not work well with long running commands

    Execute does not work well with long running commands

    When executing a long-running task, a ConnectionError is intermittently raised. From the python console:

    eapi = pyeapi.connect(transport='http', host='172.20.1.6', username='user', password='pass')
    cmds = ['enable', 'routing-context vrf management', 'copy http://172.20.1.4:8080/images/eos/EOS-4.18.1F.swi flash:']
    
    eapi.execute(commands=cmds, encoding='json')
    {u'jsonrpc': u'2.0', u'result': [{}, {}, {u'messages': [u'Copy completed successfully.']}], u'id': u'4542156176'}
    
    eapi.execute(commands=cmds, encoding='json')
    Traceback (most recent call last):
      File "<input>", line 1, in <module>
      File "/Users/bwatson/Projects/aeon-ztps/venv/lib/python2.7/site-packages/pyeapi/eapilib.py", line 490, in execute
        response = self.send(request)
      File "/Users/bwatson/Projects/aeon-ztps/venv/lib/python2.7/site-packages/pyeapi/eapilib.py", line 423, in send
        raise ConnectionError(str(self), 'unable to connect to eAPI')
    ConnectionError: unable to connect to eAPI
    

    The first copy completed without issue. The second raised a connection error.

    opened by bobbywatson3 6
  • Handle big response

    Handle big response

    Hi team, I am running a command "show ip route bgp" and the response is too big for my client, do you have any good idea to chunk the response? Thanks!

    opened by HanfordWu 0
  • New release to support py3.10

    New release to support py3.10

    develop branch has a fix required for py3.10 to work. https://github.com/arista-eosplus/pyeapi/blob/236503162d1aa3ecc953678ec05380f1f605be02/pyeapi/api/abstract.py#L44

    Is there plans for a release soon?

    question 
    opened by jeffkala 8
  • Support for login token to avoid login for each command

    Support for login token to avoid login for each command

    We are observing that for each EAPI request we make in case of offbox, the remote switch is making one login which results in one authentication request to TACACS, in case that is configured. Please confirm this is the expected behavior currently.

    This issue is a request to enhance this, such that EAPI server returns an authentication token that can be reused by clients and thus avoiding doing one login per request..

    enhancement 
    opened by Ragsboss 1
  • Add support for multiple/secondary Ip-addresses in ipinterfaces() function

    Add support for multiple/secondary Ip-addresses in ipinterfaces() function

    Hello, Im trying to get my secondary ip's configured from the api('ipinterfaces').get(interface) function, however it only returns the first it finds as per the def _parse_address function.

    Or is there another way to get all actual ip's configured via api and not parse the configuration with the client enable('show running-config') function?

    Can it perhaps be changed to also return a key with a list of secondary ip-addresses if one exists?

    Actual config:

    interface Loopback0 mtu 1554 ip address 10.128.6.1/32 ip address 10.255.255.1/24 secondary

    the api call:

    arista_device.api('ipinterfaces').get(name='Loopback0') {'name': 'Loopback0', 'address': '10.128.6.1/32', 'mtu': 1554}

    enhancement 
    opened by King-Joakim 0
  • Unable to process parallel requests over the same session

    Unable to process parallel requests over the same session

    When issuing two concomitant requests over the same eAPI session I can get the following errors:

      File "/usr/local/lib/python2.7/dist-packages/pyeapi/client.py", line 730, in run_commands
        response = self._connection.execute(commands, encoding, **kwargs)
      File "/usr/local/lib/python2.7/dist-packages/pyeapi/eapilib.py", line 495, in execute
        response = self.send(request)
      File "/usr/local/lib/python2.7/dist-packages/pyeapi/eapilib.py", line 388, in send
        response = self.transport.getresponse(buffering=True)
      File "/usr/lib/python2.7/httplib.py", line 1099, in getresponse
        raise ResponseNotReady()
    ResponseNotReady
    
      File "/usr/local/lib/python2.7/dist-packages/pyeapi/client.py", line 730, in run_commands
        response = self._connection.execute(commands, encoding, **kwargs)
      File "/usr/local/lib/python2.7/dist-packages/pyeapi/eapilib.py", line 495, in execute
        response = self.send(request)
      File "/usr/local/lib/python2.7/dist-packages/pyeapi/eapilib.py", line 372, in send
        self.transport.putrequest('POST', '/command-api')
      File "/usr/lib/python2.7/httplib.py", line 921, in putrequest
        raise CannotSendRequest()
    CannotSendRequest
    

    or

      File "/usr/local/lib/python2.7/dist-packages/pyeapi/client.py", line 730, in run_commands
        response = self._connection.execute(commands, encoding, **kwargs)
      File "/usr/local/lib/python2.7/dist-packages/pyeapi/eapilib.py", line 495, in execute
        response = self.send(request)
      File "/usr/local/lib/python2.7/dist-packages/pyeapi/eapilib.py", line 392, in send
        response_content = response.read()
      File "/usr/lib/python2.7/httplib.py", line 578, in read
        return self._read_chunked(amt)
      File "/usr/lib/python2.7/httplib.py", line 636, in _read_chunked
        value.append(self._safe_read(chunk_left))
      File "/usr/lib/python2.7/httplib.py", line 693, in _safe_read
        chunk = self.fp.read(min(amt, MAXAMOUNT))
    AttributeError: 'NoneType' object has no attribute 'read'
    

    For the moment I would only like to understand if this is known, desired or should be corrected.

    Thanks!

    opened by mirceaulinic 12
Releases(v0.8.4)
  • v0.8.4(Nov 13, 2020)

  • v0.8.3(Jan 26, 2020)

  • v0.8.2(Feb 9, 2018)

  • v0.8.1(Jul 21, 2017)

    • Fixes bug that breaks unix-socket connection.
    • Allows commands sent as unicode to be used.
    • Updated error messages for commands that timeout.
    Source code(tar.gz)
    Source code(zip)
  • v0.8.0(Mar 14, 2017)

    • Adds VRF API
    • Allows creation of Ethernet subinterfaces
    • Allow usage of expandAliases and autoComplete parameters
    • Adds extended ACL support
    Source code(tar.gz)
    Source code(zip)
  • v0.7.0(Sep 8, 2016)

  • v0.6.1(Mar 4, 2016)

  • v0.6.0(Feb 22, 2016)

    This is a targeted release to enhance the client.run_commands method. This method will now take MULTILINE commands where the command and input need to be split.

    Release Notes: http://pyeapi.readthedocs.org/en/latest/release-notes-0.6.0.html

    Source code(tar.gz)
    Source code(zip)
  • v0.5.0(Feb 17, 2016)

  • v0.4.0(Nov 6, 2015)

Owner
Arista Networks EOS+
Applications developed and supported by Arista EOS+
Arista Networks EOS+
Singer Tap for dbt Artifacts built with the Meltano SDK

tap-dbt-artifacts tap-dbt-artifacts is a Singer tap for dbtArtifacts. Built with the Meltano SDK for Singer Taps.

Prratek Ramchandani 9 Nov 25, 2022
Telegram bot to stream videos in telegram voicechat for both groups and channels.

Telegram bot to stream videos in telegram voicechat for both groups and channels. Supports live streams, YouTube videos and telegram media. With record stream support, Schedule streams, and many more

SOCIAL MECHANIC 4 Nov 13, 2022
The Official Twilio SendGrid Led, Community Driven Python API Library

The default branch name for this repository has been changed to main as of 07/27/2020. This library allows you to quickly and easily use the SendGrid

Twilio SendGrid 1.4k Jan 07, 2023
A wrapper for aqquiring Choice Coin directly through a Python Terminal. Leverages the TinyMan Python-SDK.

CHOICE_TinyMan_Wrapper A wrapper that allows users to acquire Choice Coin directly through their Terminal using ALGO and various Algorand Standard Ass

Choice Coin 16 Sep 24, 2022
Read manga from your favourites websites on telegram.

tg-manga-bot Read manga from your favourites websites on telegram. Current Development Bot @idkpythonbot Telegram Channel tg_manga_bot Commands start

Daniel Rivero 41 Dec 22, 2022
Fast and small Discord-Toolset.

Mooncord 🌙 Discord server: https://discord.gg/frnpk2rg Fast and small Discord-Toolset. Enjoy? Star this repo ⭐ (Main file in Mooncord/Moon-1.0.1/vers

7ua 9 Dec 11, 2021
Secure Tunnel Manager

Making life easy of those who are in need of OpenSource alternative of AWS Secure Tunnel.

Suyash Chavan 1 Sep 27, 2022
A Bot Telegram Anti Users Channel to automatic ban users who using channel to send message in group.

Tg_Anti_UsersChannel A Bot Telegram Anti Users Channel to automatic ban users who using channel to send message in group. Features: Automatic ban Whit

idzeroid 6 Dec 26, 2021
Python Proof of Concept for retrieving Now Playing on YouTube Music with TabFS

Youtube Music TabFS Python Proof of Concept for retrieving Now Playing on YouTube Music with TabFS. music_information = get_now_playing() pprint(music

Junho Yeo 41 Nov 06, 2022
A simple telegram bot to download from Zee5 links

Zee5 Downloader If you find any bugs, report at @TroJanzSupport My Features: 👉 Upload as file/video from any NON-DRM Zee5 link 👉 Permanent thumbnail

TroJanzHEX 95 Dec 20, 2022
Baby Villager Bot

This script scrapes and stores the availability of timeslots for Car Driving Test at all RTA Serivce NSW centres in the state. Dependencies Account wi

Milo Weinberg 3 Dec 16, 2021
Primeira etapa do processo seletivo para a bolsa de migração de conteúdo de Design de Software.

- Este processo já foi concluído. Obrigado pelo seu interesse! Processo Seletivo para a bolsa de migração de conteúdo de Design de Software Primeirame

Toshi Kurauchi 1 Feb 21, 2022
Erhalten Sie wichtige Warnmeldungen des Bevölkerungsschutzes für Gefahrenlagen wie zum Beispiel Gefahrstoffausbreitung oder Unwetter per Programmierschnittstelle.

nina-api Erhalten Sie wichtige Warnmeldungen des Bevölkerungsschutzes für Gefahrenlagen wie zum Beispiel Gefahrstoffausbreitung oder Unwetter per Prog

Bundesstelle für Open Data 68 Dec 19, 2022
:lock: Python 2.7/3.X client for HashiCorp Vault

hvac HashiCorp Vault API client for Python 3.x Tested against the latest release, HEAD ref, and 3 previous minor versions (counting back from the late

hvac 1k Dec 29, 2022
Asynchronous and also synchronous non-official QvaPay client for asyncio and Python language.

Asynchronous and also synchronous non-official QvaPay client for asyncio and Python language. This library is still under development, the interface could be changed.

Leynier Gutiérrez González 8 Sep 18, 2021
simple discord token grabber with webhook hiding feature.

Token Grabber A simple Discord token grabber with base64 webhook encoding, it uses pastebin as a database to get webhook, so next time u dont get your

0 Dec 01, 2021
Configure your linux server and check for vulnerabilities with serverlla

serverlla Configure your linux server and check for vulnerabilities with serverlla. Serverlla has a menu with options and allows you to configure your

Dylan Meca 10 Feb 01, 2022
WhatsApp Api Python - This documentation aims to exemplify the use of Moorse Whatsapp API in Python

WhatsApp API Python ChatBot Este repositório contém uma aplicação que se utiliza

Moorse.io 3 Jan 08, 2022
a Disqus alternative

Isso – a commenting server similar to Disqus Isso – Ich schrei sonst – is a lightweight commenting server written in Python and JavaScript. It aims to

Martin Zimmermann 4.7k Jan 02, 2023
Demonstrate how GitHub OIDC token getting should be included in boto3

boto3 should add direct support for AssumeRoleWithWebIdentity for GitHub Actions There is a aws-actions/configure-aws-credentials action that will get

Ben Kehoe 11 Aug 29, 2022