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+
DaProfiler vous permet d'automatiser vos recherches sur des particuliers basés en France uniquement et d'afficher vos résultats sous forme d'arbre.

A but educatif seulement. DaProfiler DaProfiler vous permet de créer un profil sur votre target basé en France uniquement. La particularité de ce prog

Dalunacrobate 73 Dec 21, 2022
This is a very easy to use tool developed in python that will search for free courses from multiple sites including youtube and enroll in the ones in which it can.

Free-Course-Hunter-and-Enroller This is a very easy to use tool developed in python that will search for free courses from multiple sites including yo

Zain 12 Nov 12, 2022
Automatic generation of crypto-arts based on image layers

NFT Generator Автоматическая генерация крипто-артов на основе слоев изображения. Установка pip3 install -r requirements.txt rm -rf result/* Как это ра

Zproger 31 Dec 29, 2022
Wetterdienst - Open weather data for humans

We are a group of like-minded people trying to make access to weather data in Python feel like a warm summer breeze, similar to other projects like rdwd for the R language, which originally drew our

226 Jan 04, 2023
Python client and API for monitoring and controling energy diversion devices from MyEnergi

Python client and API for monitoring and controling energy diversion devices from MyEnergi A set of library functions and objects for interfacing with

1 Dec 17, 2021
A file-based quote bot written in Python

Let's Write a Python Quote Bot! This repository will get you started with building a quote bot in Python. It's meant to be used along with the Learnin

Jyoti prakash Rout 1 Jan 08, 2022
📢 Video Chat Stream Telegram Bot. Can ⏳ Stream Live Videos, Radios, YouTube Videos & Telegram Video Files On Your Video Chat Of Channels & Groups !

Telegram Video Chat Bot (Beta) 📢 Video Chat Stream Telegram Bot 🤖 Can Stream Live Videos, Radios, YouTube Videos & Telegram Video Files On Your Vide

brut✘⁶⁹ // ユスフ 15 Dec 24, 2022
Github repository started notify 💕

Github repository started notify 💕

4 Aug 06, 2022
Python async SDK for betsapi.com

Python async SDK for betsapi.com

1 Dec 21, 2021
基于nonebot2的twitter推送插件

HanayoriBot(Twitter插件) ✨ 基于NoneBot2的Twitter推送插件,自带百度翻译接口 ✨ 简介 本插件基于NoneBot2与go-cqhttp,可以及时将Twitter用户的最新推文推送至群聊,并且自带基于百度翻译的推文翻译接口,及时跟进你所关注的Vtuber的外网动态。

鹿乃まほろ / Mahoro Kano 16 Feb 12, 2022
Box SDK for Python

Box Python SDK Installing Getting Started Authorization Server-to-Server Auth with JWT Traditional 3-legged OAuth2 Other Auth Options Usage Documentat

Box 371 Dec 29, 2022
Scrape Twitter for Tweets

Backers Thank you to all our backers! 🙏 [Become a backer] Sponsors Support this project by becoming a sponsor. Your logo will show up here with a lin

Ahmet Taspinar 2.2k Jan 02, 2023
A Python wrapper for the tesseract-ocr API

tesserocr A simple, Pillow-friendly, wrapper around the tesseract-ocr API for Optical Character Recognition (OCR). tesserocr integrates directly with

Fayez 1.7k Jan 03, 2023
⚡ ʑɠ ცơɬ Is One Of The Fastest & Smoothest Bot On Telegram Based on Telethon ⚡

『ʑɠ ცơɬ』 ⚡ ʑɠ ცơɬ Is One Of The Fastest & Smoothest Bot On Telegram Based on Telethon ⚡ Status Of Bot Telegram 🏪 Dєρℓογ το нєяοκυ Variables APP_ID =

ʑɑʑɓɦɑɪ 0 Feb 12, 2022
A Powerful, Smart And Advance Group Manager ... Written with AioGram , Pyrogram and Telethon...

❤️ Shadow ❤️ A Powerful, Smart And Advance Group Manager ... Written with AioGram , Pyrogram and Telethon... ⭐️ Thanks to everyone who starred Shadow,

TeamShadow 17 Oct 21, 2022
The Best Telegram UserBot Made With Pyrogram [Python]

Asterix UserBot A Powerful Telegram userbot based on Pyrogram. How To Deploy Asterix Heroku Railway Qovery Termux Tutorial Railway Deploy Comming Soon

TeamAsterix 9 Oct 17, 2022
WhatsApp API Python ChatBot

WhatsApp Api Python - Esta documentação tem como objetivo exemplificar o uso do Moorse Whatsapp API na linguagem Python.

Douglas Alves 2 Jan 06, 2022
WIOpy - Walmart Affiliate API Python wrapper

WalmartIO Python Wrapper - WIOpy A python wrapper for the Walmart io API. Only s

6 Nov 14, 2022
Die wichtigsten APIs Deutschlands in einem Python Paket.

Deutschland A python package that gives you easy access to the most valuable datasets of Germany. Installation pip install deutschland Geographic data

Bundesstelle für Open Data 921 Jan 08, 2023
Nonebot2 简易群管

简易群管 ✨ NoneBot2 简易群管 ✨ _ 踢 改 禁 欢迎issue pr 权限说明:permission=SUPERUSER 安装 💿 pip install nonebot-plugin-admin 导入 📲 在bot.py 导入,语句: nonebot.load_plugin("n

幼稚园园长 74 Dec 22, 2022