/usr/lib/python2.7/dist-packages/networking_arista/common/api.py is in python-networking-arista 2017.2.2-2ubuntu1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 | # Copyright (c) 2017 Arista Networks, Inc
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
# See the License for the specific language governing permissions and
# limitations under the License.
import json
from oslo_log import log as logging
from oslo_utils import excutils
import requests
from requests import exceptions as requests_exc
from six.moves.urllib import parse
from networking_arista._i18n import _LI, _LW
from networking_arista.common import exceptions as arista_exc
LOG = logging.getLogger(__name__)
# EAPI error message
ERR_CVX_NOT_LEADER = 'only available on cluster leader'
class EAPIClient(object):
def __init__(self, host, username=None, password=None, verify=False,
timeout=None):
self.host = host
self.timeout = timeout
self.url = self._make_url(host)
self.session = requests.Session()
self.session.headers['Content-Type'] = 'application/json'
self.session.headers['Accept'] = 'application/json'
self.session.verify = verify
if username and password:
self.session.auth = (username, password)
@staticmethod
def _make_url(host, scheme='https'):
return parse.urlunsplit(
(scheme, host, '/command-api', '', '')
)
def execute(self, commands, commands_to_log=None):
params = {
'timestamps': False,
'format': 'json',
'version': 1,
'cmds': commands
}
data = {
'id': 'Networking Arista Driver',
'method': 'runCmds',
'jsonrpc': '2.0',
'params': params
}
if commands_to_log:
log_data = dict(data)
log_data['params'] = dict(params)
log_data['params']['cmds'] = commands_to_log
else:
log_data = data
LOG.info(
_LI('EAPI request %(ip)s contains %(data)s'),
{'ip': self.host, 'data': json.dumps(log_data)}
)
# request handling
try:
error = None
response = self.session.post(
self.url,
data=json.dumps(data),
timeout=self.timeout
)
except requests_exc.ConnectionError:
error = _LW('Error while trying to connect to %(ip)s')
except requests_exc.ConnectTimeout:
error = _LW('Timed out while trying to connect to %(ip)s')
except requests_exc.Timeout:
error = _LW('Timed out during an EAPI request to %(ip)s')
except requests_exc.InvalidURL:
error = _LW('Ingoring attempt to connect to invalid URL at %(ip)s')
except Exception as e:
with excutils.save_and_reraise_exception():
LOG.warning(
_LW('Error during processing the EAPI request %(error)s'),
{'error': e}
)
finally:
if error:
msg = error % {'ip': self.host}
# stop processing since we've encountered request error
LOG.warning(msg)
raise arista_exc.AristaRpcError(msg=msg)
# response handling
try:
resp_data = response.json()
return resp_data['result']
except ValueError as e:
LOG.info(_LI('Ignoring invalid JSON response'))
except KeyError:
if 'error' in resp_data and resp_data['error']['code'] == 1002:
for d in resp_data['error']['data']:
if not isinstance(d, dict):
continue
elif ERR_CVX_NOT_LEADER in d.get('errors', {})[0]:
LOG.info(
_LI('%(ip)s is not the CVX leader'),
{'ip': self.host}
)
return
msg = _LI('Unexpected EAPI error')
LOG.info(msg)
raise arista_exc.AristaRpcError(msg=msg)
except Exception as e:
with excutils.save_and_reraise_exception():
LOG.warning(
_LW('Error during processing the EAPI response %(error)s'),
{'error': e}
)
|