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+
Irenedao-nft-generator - Original scripts used to generate IreneDAO NFTs

IreneDAO NFT Generator Scripts to generate IreneDAO NFT. Make sure you have Pill

libevm 60 Oct 27, 2022
Checks if Minecraft accounts are available, or taken.

MCNameChecker Checks validity of Minecraft IGN's. Using async to make it even faster. Has rate-limit detections and Proxy support Usage Q. How do I us

Dimitri Demarkus 5 Apr 22, 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
Python library to connect to Firebots API

This is a firebot library to connect to Firebots API. https://firebot.app/ From Firebots Website: "Firebot is a fully featured open-source bot that c

1 Jan 08, 2022
DoriBot -Discord Chat Bot

DoriBot -Discord Chat Bot Please do not use these source files for commercial use. Be sure to mark the source. 이제 더이상의 메이저 업데이트는 없습니다. 마이너 업데이트들은 존재합니

queenanna1999 0 Mar 30, 2022
Dashboard to monitor the performance of your Binance Futures account

futuresboard A python based scraper and dashboard to monitor the performance of your Binance Futures account. Note: A local sqlite3 database config/fu

86 Dec 29, 2022
We propose the adversarial blur attack (ABA) against visual object tracking.

ABA We propose the adversarial blur attack (ABA) against visual object tracking. The ICCV link: https://arxiv.org/abs/2107.12085 and, https://openacce

Qing Guo 13 Dec 01, 2022
An API wrapper around Discord API.

NeoCord This project is work in progress not for production use. An asynchronous API wrapper around Discord API written in Python. Features Modern API

Izhar Ahmad 14 Jan 03, 2022
A simple Discord Bot that uses the free CryptoCompare API to display cryptocurrency prices

What is this? This is a simple Discord Bot coded in Python that uses the free CryptoCompare API to display cryptocurrency prices Download Use git to c

Kevin 10 Apr 17, 2022
A Bot To Find Telegram User ID Easily

Telegram ID Bot 🤖 A Bot To Find Telegram User ID Easily Made with Python3 (C) @BXBotz Copyright permission under MIT License License - https://githu

MuFaz-TG 6 Nov 21, 2022
A discord bot that will help you browse/download nhentai sources.

Risa Introduction Risa is an nHentai discord bot that will help you browse and download your favorite doujin inside your own discord server. Hosting M

markee7 14 Oct 25, 2021
A Google Charts API for Python, meant to be used as an alternative to matplotlib.

GooPyCharts A Google Charts API for Python 2 and 3, meant to be used as an alternative to matplotlib. Syntax is similar to MATLAB. The goal of this pr

Sagnik Ghosh 202 Oct 04, 2022
Телеграм бот решающий задания ЦДЗ, написанный на библиотеке libmesh.

MESHBot-Telegram Телеграм бот решающий задания ЦДЗ. Описание: Бот написан с использованием библиотеки libmesh. Для начала работы отправьте ему ссылку

2 Jun 19, 2022
The official wrapper for spyse.com API, written in Python, aimed to help developers build their integrations with Spyse.

Python wrapper for Spyse API The official wrapper for spyse.com API, written in Python, aimed to help developers build their integrations with Spyse.

Spyse 15 Nov 22, 2022
A script to forward mass number of media to another group/channel. Heroku deploy

Telegram Forward Script 😇 This is a Script to Forward Large Number of Files to Another Telegram Channel. Star එකක් දාල fork එකක් ගහපියව් 🥴 If You Tr

Anjana Madu 17 Oct 21, 2022
A GitHub Action that automatically reports your Advent of Code progress in a table in your README

Advent README Stars This action adds and maintains a stars report in your README based on your Advent of Code progress. Example Table 2021 Results Day

Kevin Duff 36 Dec 30, 2022
Using Streamlit to build a simple UI on top of the OpenSea API

OpenSea API Explorer Using Streamlit to build a simple UI on top of the OpenSea API. 🤝 Contributing Contributions, issues and feature requests are we

Gavin Capriola 1 Jan 04, 2022
SSH-Restricted deploys an SSH compliance rule (AWS Config) with auto-remediation via AWS Lambda if SSH access is public.

SSH-Restricted SSH-Restricted deploys an SSH compliance rule with auto-remediation via AWS Lambda if SSH access is public. SSH-Auto-Restricted checks

Adrian Hornsby 30 Nov 08, 2022
Pluggable Telethon - Telegram UserBot

A stable pluggable Telegram userbot, based on Telethon.

Team Ultroid 2.3k Dec 30, 2022
Python script to download WAX transactions

WAXtax Python script to download WAX transactions WAXtax uses the CoinGecko API and the WAX Blockchain History API to download csvs for each account y

SixPM Software 11 Oct 09, 2022