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+
Raphtory-client - The python client for the Raphtory project

Raphtory Client This is the python client for the Raphtory project Install via p

Raphtory 5 Apr 28, 2022
Drcom-pt-client - Drcom Pt version client with refresh timer

drcom-pt-client Drcom Pt version client with refresh timer Dr.com Pt版本客户端 可用于网页认

null 4 Nov 16, 2022
Official Python client for the MonkeyLearn API. Build and consume machine learning models for language processing from your Python apps.

MonkeyLearn API for Python Official Python client for the MonkeyLearn API. Build and run machine learning models for language processing from your Pyt

MonkeyLearn 157 Nov 22, 2022
🖥️ Python - P1 Monitor API Asynchronous Python Client

??️ Asynchronous Python client for the P1 Monitor

Klaas Schoute 9 Dec 12, 2022
🐍 The official Python client library for Google's discovery based APIs.

Google API Client This is the Python client library for Google's discovery based APIs. To get started, please see the docs folder. These client librar

Google APIs 6.2k Jan 8, 2023
Python API Client for Close

Close API A convenient Python wrapper for the Close API. API docs: http://developer.close.com Support: [email protected] Installation pip install clos

Close 56 Nov 30, 2022
Python client for CoinPayments API

pyCoinPayments - Python API client for CoinPayments Updates This library has now been converted to work with python3 This is an unofficial client for

James 27 Sep 21, 2022
DEPRECATED - Official Python Client for the Discogs API

⚠️ DEPRECATED This repository is no longer maintained. You can still use a REST client like Requests or other third-party Python library to access the

Discogs 483 Dec 31, 2022
The Foursquare API client for Python

foursquare Python client for the foursquare API. Philosophy: Map foursquare's endpoints one-to-one Clean, simple, Pythonic calls Only handle raw data,

Mike Lewis 400 Dec 19, 2022
python3.5+ hubspot client based on hapipy, but modified to use the newer endpoints and non-legacy python

A python wrapper around HubSpot's APIs, for python 3.5+. Built initially around hapipy, but heavily modified. Check out the documentation here! (thank

Jacobi Petrucciani 140 Dec 21, 2022
Python Client for Instagram API

This project is not actively maintained. Proceed at your own risk! python-instagram A Python 2/3 client for the Instagram REST and Search APIs Install

Facebook Archive 2.9k Dec 30, 2022
The official Python client library for the Kite Connect trading APIs

The Kite Connect API Python client - v3 The official Python client for communicating with the Kite Connect API. Kite Connect is a set of REST-like API

Zerodha Technology 756 Jan 6, 2023
A Python Client for News API

newsapi-python A Python client for the News API. License Provided under MIT License by Matt Lisivick. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRAN

Matt Lisivick 281 Dec 29, 2022
SmartFile API Client (Python).

A SmartFile Open Source project. Read more about how SmartFile uses and contributes to Open Source software. Summary This library includes two API cli

SmartFile 19 Jan 11, 2022
Python client for the Socrata Open Data API

sodapy sodapy is a python client for the Socrata Open Data API. Installation You can install with pip install sodapy. If you want to install from sour

Cristina 368 Dec 9, 2022
Python client for the Echo Nest API

Pyechonest Tap into The Echo Nest's Musical Brain for the best music search, information, recommendations and remix tools on the web. Pyechonest is an

The Echo Nest 655 Dec 29, 2022
A Python Tumblr API v2 Client

PyTumblr Installation Install via pip: $ pip install pytumblr Install from source: $ git clone https://github.com/tumblr/pytumblr.git $ cd pytumblr $

Tumblr 677 Dec 21, 2022
A super awesome Twitter API client for Python.

birdy birdy is a super awesome Twitter API client for Python in just a little under 400 LOC. TL;DR Features Future proof dynamic API with full REST an

Inueni 259 Dec 28, 2022
Unirest in Python: Simplified, lightweight HTTP client library.

Unirest for Python Unirest is a set of lightweight HTTP libraries available in multiple languages, built and maintained by Mashape, who also maintain

Kong 432 Dec 21, 2022