1
0
Fork 0

Merging upstream version 1.3.2+dfsg.

Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
Daniel Baumann 2025-02-05 14:18:14 +01:00
parent 77fa26eaf5
commit aa182b4768
Signed by: daniel
GPG key ID: FBB4F0E80A80222F
7 changed files with 127 additions and 29 deletions

View file

@ -4,25 +4,31 @@
## Table of Contents
1. [Overview](#overview)
- [Arista Cloudvision® Portal RESTful API Client](#arista-cloudvision-portal-restful-api-client)
- [Table of Contents](#table-of-contents)
- [Overview](#overview)
- [Requirements](#requirements)
1. [Installation](#installation)
- [Installation](#installation)
- [Development: Run from Source](#development-run-from-source)
1. [Getting Started](#getting-started)
- [Step 1: Clone the cvprac Github repo](#step-1-clone-the-cvprac-github-repo)
- [Step 2: Check out the desired version or branch](#step-2-check-out-the-desired-version-or-branch)
- [Step 3: Install cvprac using Pip with -e switch](#step-3-install-cvprac-using-pip-with--e-switch)
- [Step 4: Install cvprac development requirements](#step-4-install-cvprac-development-requirements)
- [Getting Started](#getting-started)
- [Connecting](#connecting)
- [CVP On Premises](#cvp-on-premises)
- [CVaaS](#cvaas)
- [CVP Version Handling](#cvp-version-handling)
- [Examples](#examples)
1. [Notes For API Class Usage](#notes-for-api-class-usage)
- [Notes for API Class Usage](#notes-for-api-class-usage)
- [Containers](#containers)
1. [Testing](#testing)
1. [Contact or Questions](#contact-or-questions)
1. [Contributing](#contributing)
- [Testing](#testing)
- [Contact or Questions](#contact-or-questions)
- [Contributing](#contributing)
- [Working With Git](#working-with-git)
- [Submitting Pull Requests](#submitting-pull-requests)
- [Pull Request Semantics](#pull-request-semantics)
1. [License](#license)
- [License](#license)
## Overview
@ -151,7 +157,7 @@ examples below demonstrate connecting to CVP On Premises setups.
### CVaaS
CVaaS is CloudVision as a Service. Users with CVaaS must use a REST API
token for accessing CVP with REST APIs.
token (service account tokens) for accessing CVP with REST APIs.
- In the case where users authenticate with CVP (CVaaS) using Oauth a
- REST API token is required to be generated and used for running REST
@ -170,6 +176,22 @@ generic in this sense. If you are using the cvaas\_token parameter
please convert to api\_token because the cvaas\_token parameter will be
deprecated in the future.
Please note that the correct regional URL where the CVaaS tenant is deployed must be used. The following are the
cluster URLs used in production:
| Region | URL |
|--------|-----|
| United States 1a | [www.arista.io](https://www.arista.io) |
| United States 1c| [www.cv-prod-us-central1-c.arista.io](https://www.cv-prod-us-central1-c.arista.io)|
| Canada | [www.cv-prod-na-northeast1-b.arista.io](https://www.cv-prod-na-northeast1-b.arista.io)|
| Europe West 2| [www.cv-prod-euwest-2.arista.io](https://www.cv-prod-euwest-2.arista.io)|
| Japan| [www.cv-prod-apnortheast-1.arista.io](https://www.cv-prod-apnortheast-1.arista.io)|
| Australia | [www.cv-prod-ausoutheast-1.arista.io](https://www.cv-prod-ausoutheast-1.arista.io)|
!!! Warning
URLs without `www` are not supported.
### CVP Version Handling
The CVP RESTful APIs often change between releases of CVP. Cvprac

View file

@ -1 +1 @@
1.3.1
1.3.2

View file

@ -32,5 +32,5 @@
''' RESTful API Client class for Cloudvision(R) Portal
'''
__version__ = '1.3.1'
__version__ = '1.3.2'
__author__ = 'Arista Networks, Inc.'

View file

@ -572,7 +572,7 @@ class CvpApi(object):
'%s&queryparam=&startIndex=%d&endIndex=%d' %
(key, start, end), timeout=self.request_timeout)
def get_inventory(self, start=0, end=0, query=''):
def get_inventory(self, start=0, end=0, query='', provisioned=True):
''' Returns the a dict of the net elements known to CVP.
Args:
@ -595,7 +595,7 @@ class CvpApi(object):
timeout=self.request_timeout)
return data['netElementList']
self.log.debug('v2 Inventory API Call')
data = self.clnt.get('/inventory/devices?provisioned=true',
data = self.clnt.get('/inventory/devices?provisioned=%s' % provisioned,
timeout=self.request_timeout)
containers = self.get_containers()
for dev in data:
@ -1463,7 +1463,7 @@ class CvpApi(object):
return self.clnt.post(url, data=data, timeout=self.request_timeout)
def apply_configlets_to_device(self, app_name, dev, new_configlets,
create_task=True, reorder_configlets=False):
create_task=True, reorder_configlets=False, validate=False):
''' Apply the configlets to the device.
Args:
@ -1484,6 +1484,12 @@ class CvpApi(object):
directly. Set this parameter to True only with the full
list of configlets being applied to the device provided
via the new_configlets parameter.
validate (bool): Defaults to False. If set to True, the function
will validate and compare the configlets to be attached and
populate the configCompareCount field in the data dict. In case
all keys are 0, ie there is no difference between designed-config
and running-config after applying the configlets, no task will be
generated.
Returns:
response (dict): A dict that contains a status and a list of
@ -1536,6 +1542,16 @@ class CvpApi(object):
'nodeTargetIpAddress': dev['ipAddress'],
'childTasks': [],
'parentTask': ''}]}
if validate:
validation_result = self.validate_configlets_for_device(dev['systemMacAddress'], ckeys)
data['data'][0].update({
"configCompareCount": {
"mismatch": validation_result['mismatch'],
"reconcile": validation_result['reconcile'],
"new": validation_result['new']
}
}
)
self.log.debug('apply_configlets_to_device: saveTopology data:\n%s' %
data['data'])
self._add_temp_action(data)
@ -1545,7 +1561,7 @@ class CvpApi(object):
# pylint: disable=too-many-locals
def remove_configlets_from_device(self, app_name, dev, del_configlets,
create_task=True):
create_task=True, validate=False):
''' Remove the configlets from the device.
Args:
@ -1554,6 +1570,12 @@ class CvpApi(object):
del_configlets (list): List of configlet name and key pairs
create_task (bool): Determines whether or not to execute a save
and create the tasks (if any)
validate (bool): Defaults to False. If set to True, the function
will validate and compare the configlets to be attached and
populate the configCompareCount field in the data dict. In case
all keys are 0, ie there is no difference between designed-config
and running-config after applying the configlets, no task will be
generated.
Returns:
response (dict): A dict that contains a status and a list of
@ -1612,6 +1634,16 @@ class CvpApi(object):
'nodeTargetIpAddress': dev['ipAddress'],
'childTasks': [],
'parentTask': ''}]}
if validate:
validation_result = self.validate_configlets_for_device(dev['systemMacAddress'], keep_keys)
data['data'][0].update({
"configCompareCount": {
"mismatch": validation_result['mismatch'],
"reconcile": validation_result['reconcile'],
"new": validation_result['new']
}
}
)
self.log.debug('remove_configlets_from_device: saveTopology data:\n%s'
% data['data'])
self._add_temp_action(data)
@ -3775,8 +3807,13 @@ class CvpApi(object):
'deviceId': 'BAD032986065E8DC14CBB6472EC314A6'},
'time': '2022-02-12T02:58:30.765459650Z'}
'''
device_info = self.get_device_by_serial(device_id)
if device_info is not None and 'serialNumber' in device_info:
device_exists = False
inventory = self.get_inventory(provisioned=False)
for device in inventory:
if device['serialNumber'] == device_id:
device_exists = True
break
if device_exists:
msg = 'Decommissioning via Resource APIs are supported from 2021.3.0 or newer.'
# For on-prem check the version as it is only supported from 2021.3.0+
if self.cvp_version_compare('>=', 7.0, msg):

View file

@ -114,7 +114,7 @@ class CvpClient(object):
# Maximum number of times to retry a get or post to the same
# CVP node.
NUM_RETRY_REQUESTS = 3
LATEST_API_VERSION = 8.0
LATEST_API_VERSION = 9.0
def __init__(self, logger='cvprac', syslog=False, filename=None,
log_level='INFO'):
@ -212,7 +212,8 @@ class CvpClient(object):
self.version = version
self.log.info('Version %s', version)
# Set apiversion to latest available API version for CVaaS
# Set apiversion to 8.0 for 2022.1.x
# Set apiversion to 9.0 for 2023.1.x
# Set apiversion to 8.0 for 2022.1.x - 2022.3.x
# Set apiversion to 7.0 for 2021.3.x
# Set apiversion to 6.0 for 2021.2.x
# Set apiversion to 5.0 for 2020.2.4 through 2021.1.x
@ -232,7 +233,10 @@ class CvpClient(object):
' Appending 0. Updated Version String - %s',
".".join(version_components))
full_version = ".".join(version_components)
if parse_version(full_version) >= parse_version('2022.1.0'):
if parse_version(full_version) >= parse_version('2023.1.0'):
self.log.info('Setting API version to v9')
self.apiversion = 9.0
elif parse_version(full_version) >= parse_version('2022.1.0'):
self.log.info('Setting API version to v8')
self.apiversion = 8.0
elif parse_version(full_version) >= parse_version('2021.3.0'):
@ -561,6 +565,14 @@ class CvpClient(object):
# Alternative to adding token to headers it can be added to
# cookies as shown below.
# self.cookies = {'access_token': self.api_token}
url = self.url_prefix_short + '/api/v1/rest/'
response = self.session.get(url,
cookies=self.cookies,
headers=self.headers,
timeout=self.connect_timeout,
verify=self.cert)
# Verify that the generic request was successful
self._is_good_response(response, 'Authenticate: %s' % url)
def logout(self):
'''
@ -710,7 +722,7 @@ class CvpClient(object):
err_str)
if 'Extra data' in str(error):
self.log.debug('Found multiple objects or NO objects in'
'response data. Attempt to decode')
' response data. Attempt to decode')
decoded_data = json_decoder(response.text)
return {'data': decoded_data}
else:

View file

@ -5,10 +5,12 @@ to help users interact with Arista CloudVision easily and automate the provision
## Table of Contents
1. [Authentication](#authentication)
- [cvprac labs](#cvprac-labs)
- [Table of Contents](#table-of-contents)
- [Authentication](#authentication)
- [Password Authentication](#password-authentication)
- [Service Account Token Authentication](#service-account-token-authentication)
1. [Known Limitations](#known-limitations)
- [Known Limitations](#known-limitations)
## Authentication
@ -60,6 +62,8 @@ clnt = CvpClient()
clnt.connect(nodes=['10.83.13.33'], username='',password='',api_token=token)
```
> Note that for CVaaS the correct regional URL must be used including `www.`. Please refer to the main page's [README.md](../../README.md#cvaas)
## Known Limitations
- for any APIs that interact with EOS devices, the service account name must match the name of the username

View file

@ -0,0 +1,23 @@
######
v1.3.2
######
2023-12-14
Enhancements
^^^^^^^^^^^^
* Add handling of new password change logout functionality in 2023.1.0. (`254 <https://github.com/aristanetworks/cvprac/pull/254>`_) [`mharista <https://github.com/mharista>`_]
* Add support for config validation during config assign. (`255 <https://github.com/aristanetworks/cvprac/pull/255>`_) [`noredistribution <https://github.com/noredistribution>`_]
* Add support for config validation during config removal. (`256 <https://github.com/aristanetworks/cvprac/pull/256>`_) [`noredistribution <https://github.com/noredistribution>`_]
Fixed
^^^^^
* Add ability to use device_decommissioning for unprovisioned devices. (`253 <https://github.com/aristanetworks/cvprac/pull/253>`_) [`noredistribution <https://github.com/noredistribution>`_]
* Add check to connect() to ensure token works. (`258 <https://github.com/aristanetworks/cvprac/pull/258>`_) [`chetryan <https://github.com/chetryan>`_]
Documentation
^^^^^^^^^^^^^
* Add documentation for CVaaS regional URLs. (`259 <https://github.com/aristanetworks/cvprac/pull/259>`_) [`noredistribution <https://github.com/noredistribution>`_]