GithubHelp home page GithubHelp logo

cisco-en-programmability / dnacentersdk Goto Github PK

View Code? Open in Web Editor NEW
67.0 15.0 31.0 11.41 MB

Cisco DNA Center Python SDK

Home Page: https://dnacentersdk.readthedocs.io/en/latest/

License: MIT License

Python 99.98% Shell 0.02%

dnacentersdk's Introduction

dnacentersdk

Work with the DNA Center APIs in native Python!


dnacentersdk is a community developed Python library for working with the DNA Center APIs. Our goal is to make working with DNA Center in Python a native and natural experience!

from dnacentersdk import api

# Create a DNACenterAPI connection object;
# it uses DNA Center sandbox URL, username and password, with DNA Center API version 2.3.5.3.
# and requests to verify the server's TLS certificate with verify=True.
dnac = api.DNACenterAPI(username="devnetuser",
                        password="Cisco123!",
                        base_url="https://sandboxdnac.cisco.com:443",
                        version='2.3.7.6',
                        verify=True)

# Find all devices that have 'Switches and Hubs' in their family
devices = dnac.devices.get_device_list(family='Switches and Hubs')

# Print all of demo devices
for device in devices.response:
    print('{:20s}{}'.format(device.hostname, device.upTime))

# Find all tags
all_tags = dnac.tag.get_tag(sort_by='name', order='des')
demo_tags = [tag for tag in all_tags.response if 'Demo' in tag.name ]

#  Delete all of the demo tags
for tag in demo_tags:
    dnac.tag.delete_tag(tag.id)

# Create a new demo tag
demo_tag = dnac.tag.create_tag(name='dna Demo')
task_demo_tag = dnac.task.get_task_by_id(task_id=demo_tag.response.taskId)

if not task_demo_tag.response.isError:
    # Retrieve created tag
    created_tag = dnac.tag.get_tag(name='dna Demo')

    # Update tag
    update_tag = dnac.tag.update_tag(id=created_tag.response[0].id, 
                                     name='Updated ' + created_tag.response[0].name,
                                     description='DNA demo tag')

    print(dnac.task.get_task_by_id(task_id=update_tag.response.taskId).response.progress)

    # Retrieved updated
    updated_tag = dnac.tag.get_tag(name='Updated dna Demo')
    print(updated_tag)
else:
    # Get task error details 
    print('Unfortunately ', task_demo_tag.response.progress)
    print('Reason: ', task_demo_tag.response.failureReason)

# Advance usage example using Custom Caller functions
# Define the get_global_credentials and create_netconf_credentials functions
# under the custom_caller wrapper.
# Call them with:
#     dnac.custom_caller.get_global_credentials('NETCONF')
#     dnac.custom_caller.create_netconf_credentials('65533')
def setup_custom():
    dnac.custom_caller.add_api('get_global_credentials',
                            lambda credential_type:
                                dnac.custom_caller.call_api(
                                    'GET',
                                    '/dna/intent/api/v1/global-credential',
                                    params={
                                        'credentialSubType': credential_type
                                    }).response
                            )
    dnac.custom_caller.add_api('create_netconf_credentials',
                            lambda port:
                                dnac.custom_caller.call_api(
                                    'POST',
                                    '/dna/intent/api/v1/global-credential/netconf',
                                    json=[{
                                        "netconfPort": port
                                    }])
                            )

# Add the custom API calls to the connection object under the custom_caller wrapper
setup_custom()
# Call the newly added functions
dnac.custom_caller.create_netconf_credentials('65533')
print(dnac.custom_caller.get_global_credentials('NETCONF'))

Introduction

Check out the complete Introduction

dnacentersdk handles all of this for you:

  • Reads your DNA Center credentials from environment variables.
  • Reads your DNA Center API version from environment variable DNA_CENTER_VERSION.
  • Controls whether to verify the server's TLS certificate or not according to the verify parameter.
  • Reads your DNA Center debug from environment variable DNA_CENTER_DEBUG. Boolean.
  • Wraps and represents all DNA Center API calls as a simple hierarchical tree of native-Python methods
  • If your Python IDE supports auto-completion (like PyCharm_), you can navigate the available methods and object attributes right within your IDE
  • Represents all returned JSON objects as native Python objects - you can access all of the object's attributes using native dot.syntax
  • Automatic Rate-Limit Handling Sending a lot of requests to DNA Center? Don't worry; we have you covered. DNA Center will respond with a rate-limit response, which will automatically be caught and "handled" for you.
  • Refresh token Each time the token becomes invalid, the SDK will generate a new valid token for you.

Installation

Installing and upgrading dnacentersdk is easy:

Install via PIP

$ pip install dnacentersdk

Upgrading to the latest Version

$ pip install dnacentersdk --upgrade

Compatibility matrix

The following table shows the supported versions.

Cisco DNA Center version Python "dnacentersdk" version
2.2.2.3 2.3.3
2.2.3.3 2.4.11
2.3.3.0 2.5.6
2.3.5.3 2.6.11
2.3.7.6 2.7.1

If your SDK is older please consider updating it first.

Documentation

Excellent documentation is now available at: https://dnacentersdk.readthedocs.io

Check out the Quickstart to dive in and begin using dnacentersdk.

Release Notes

Please see the releases page for release notes on the incremental functionality and bug fixes incorporated into the published releases.

Questions, Support & Discussion

dnacentersdk is a community developed and community supported project. If you experience any issues using this package, please report them using the issues page.

Contribution

dnacentersdk is a community development projects. Feedback, thoughts, ideas, and code contributions are welcome! Please see the Contributing guide for more information.

Inspiration

This library is inspired by the webexteamssdk library

Changelog

All notable changes to this project will be documented in the CHANGELOG file.

The development team may make additional name changes as the library evolves with the Cisco DNA Center APIs.

Copyright (c) 2019-2021 Cisco Systems.

dnacentersdk's People

Contributors

bvargasre avatar dbarrantese avatar fmunozmiranda avatar jbogarin avatar legion49f avatar tomvrugt avatar wastorga avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

dnacentersdk's Issues

delete_ip_pool_from_sda_virtual_network

Prerequisites

  • Have you tested the operation in the API directly?
  • Do you have the latest SDK version?

Describe the bug
A clear and concise description of what the bug is.
you need to add "siteNameHierarchy" in the parameters

def delete_ip_pool_from_sda_virtual_network(self,
                                            ip_pool_name,
                                            virtual_network_name,
                                            **siteNameHierarchy**,
                                            headers=None,
                                            **request_parameters):

Expected behavior
You need to have 3 parameters and siteNameHierarchy is missing
'Could not find siteNameHierarchy query parameter. please provide valid siteNameHierarchy and try again.'

Screenshots

Environment (please complete the following information):

  • Cisco DNA Center Version and patch:
  • Python version:
  • SDK version:
  • OS Version:

Additional context
Add any other context about the problem here.

Add support for business-api

The sites.create_site endpoint returns an executionId that links to:

{'executionId': '9ea46ac1-d8ed-4da6-9dab-b88adf488c4e',
'executionStatusUrl': '/dna/platform/management/business-api/v1/execution-status/9ea46ac1-d8ed-4da6-9dab-b88adf488c4e',
'message': 'The request has been accepted for execution'}

Are there plans to include this api endpoint in a separate module or add it to the tasks.py? I can try to submit a PR if someone has some direction here.

Need to be able to get full list of L2 and L3 VLANs from network device

I would like to be able to retrieve a complete list of layer 2 VLANs configured on a network device. Currently the get_device_interface_vlans() function only returns VLAN interfaces.

Describe the solution you'd like
get_device_interface_vlans() uses the api/v1/network-device/{{id}}/vlan endpoint. There is a v2 endpoint available on DNAC 2.2.3.4 (not sure about earlier versions) that returns all L2 and L3 VLANs configured on the device. Could get_device_interface_vlans() be updated, or a new get_device_vlans() method be created that uses the v2 endpoint?

I don't see the v2 endpoint in the current API documentation, but it works on our DNAC 2.2.3.4 system. Information was provided by Cisco.

Describe alternatives you've considered
We can make the API call directly as a work-around.

download file API call returns HTTP object incorrectly

Hi,

I believe the method file.download_a_file_by_fileid(fileid) is not working correctly. It works correctly when the save_file flag is set to True but doesn't return the expected json response when set to default False

I will be submitting a PR that fixes this issue.

Cheers

template_programmer

I'm trying to use template_programmer API from DNA center and it seems to be missing from api version 2.2.2.3.
When I try to use the API I get exception 'DNACenterAPI' object has no attribute 'template_programmer'.
template_programmer API is defined for earlier API versions - v1.2.10 and 1.3.0

Is that an accidental omission or I'm supposed to use other methods?

Dict_of_str not used in custom_caller

Prerequisites

  • [x ] Have you tested the operation in the API directly?
  • [x ] Do you have the latest SDK version?

Describe the bug
When adding a custom api caller the headers aren't processed through the dict_of_str function

headers.update(kwargs.pop('headers'))

Expected behavior
Expecting the same behaviour as in the non custom modules.
Example:

_headers.update(dict_of_str(headers))

Environment (please complete the following information):

  • Cisco DNA Center Version and patch: N/A
  • Python version: N/A
  • SDK version: dnacentersdk==2.5.4
  • OS Version: N/A

Additional context
Workaround is to import it on your own.

from dnacentersdk.utils import dict_of_str

dnac.custom_caller.add_api("get_vns", lambda headers: dnac.custom_caller.call_api("GET", "api/v1/aca-controller-service/getAcaVnSummary", headers=dict_of_str(headers)))

Issue with Ver 2.2.0

After successfully installing , when importing this errors out (on Mac and Windows)

Python 3.8.5 (default, Jan 27 2021, 15:41:15) 
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import dnacentersdk
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/rceara/venv/lib/python3.8/site-packages/dnacentersdk/__init__.py", line 36, in <module>
    from .api import DNACenterAPI
  File "/home/rceara/venv/lib/python3.8/site-packages/dnacentersdk/api/__init__.py", line 313, in <module>
    from .v2_2_1.event_management import \
  File "/home/rceara/venv/lib/python3.8/site-packages/dnacentersdk/api/v2_2_1/event_management.py", line 46, in <module>
    class EventManagement(object):
  File "/home/rceara/venv/lib/python3.8/site-packages/dnacentersdk/api/v2_2_1/event_management.py", line 544, in EventManagement
    is_parent_only=false,
NameError: name 'false' is not defined
>>> 

DNA Center 2.3.3.4 - Report API Issue

Issue description:
The report creation API doesn't work on DNA Center 2.3.3.4 version (the latest when writing this ). All the parameters are provided and they do work on earlier DNA Center releases (I've tried it on 2.2.3.4) and it works perfectly with dnacentersdk versions 2.2.3.3 & 2.3.3.0

The output when running the code is as follows:

dnacentersdk.exceptions.ApiError: [412] Precondition Failed - report create validation fail message 'category cant be null/empty

I'm not sure whether there is a new parameter called category or its a bug.

Any feedback would be appreciated,

Thank you

PS the code I'm using along with a mini documentation are available on my account https://github.com/jumaluwati/dnac

sync_devices doesnt give proper guidance

Prerequisites

  • [yes ] Have you tested the operation in the API directly?
  • [ yes] Do you have the latest SDK version?
  • [ yes] Review the compatibility matrix before opening an issue.

Describe the bug
When using the sync_devices function in the dnacentersdk module to update the management IP address of a device, the updateMgmtIPaddressList parameter does not work with a list of dictionaries. However, when making a raw JSON API call with the same data, it works without issues.

This code works with a raw JSON API call:
"updateMgmtIPaddressList": [{
"existMgmtIpAddress": "{{ old_ip }}",
"newMgmtIpAddress": "{{ new_ip }}"
}]
However, this code does not work with the sync_devices function:
updateMgmtIPaddressList = [{"existMgmtIpAddress": old_ip, "newMgmtIpAddress": new_ip}]
The DNAC API documentation specifies that updateMgmtIPaddressList should be a list of objects. What should the object for the new IP address be? Can we just copy the existing DNAC object for the device and replace the IP address with the new one? If that is the case, can the update_dnac_mgmt_ip function be modified to match the format expected by the DNAC API and the documentation?

dnacentersdk==2.5.6

API Urls have changed

We are using DNA Center 1.3.3.3 and the api urls seems to have changed thus breaking this SDK. I noticed it when playing around with getting our templates.
The hardcoded URL in the SDK is:
/dna/intent/api/v1/template-programmer/template

but in the new version of DNA Center it is:
api/v1/template-programmer/template

retrieves_all_network_devices limits to 500

how can I query to get all my devices instead of limiting to the first 500. I do not know how much devices I should expect. Is there a function that grabs all of the devices in one response

Traceback using script to export templates to JSON file

I'm using a script from Github built to backup templates from DNA Center and it's giving a traceback error on a script in the dnacentersdk library. Not sure what I need to do to fix it but wanted to report this. Here's the script from Github I'm trying to run:

https://github.com/CiscoDevNet/DNAC-TemplateTool

Here's the error I'm getting:
Traceback (most recent call last):
File "template_archive.py", line 201, in
archive_templates(dnac)
File "template_archive.py", line 57, in archive_templates
templates = dnac.template_programmer.gets_the_templates_available()
File "C:\Users\me\AppData\Local\Programs\Python\Python37-32\lib\site-packages\dnacentersdk\api\v1_3_0\template_programmer.py", line 275, in gets_the_templates_available
json=_payload)
File "C:\Users\me\AppData\Local\Programs\Python\Python37-32\lib\site-packages\dnacentersdk\restsession.py", line 390, in get
with self.request('GET', url, erc, 0, params=params, **kwargs) as resp:
AttributeError: enter

I assume it's an issue with the library cause that's where it's failing but maybe it's the script I'm running. I just can't get past this issue. Thanks.

support async request sdk

now python sdk is only support sync way, is there any plan to add async with httpx or aiohttp client?
or I don't not if you will aceept PR/MR for community?

ApiError 404 when using DNAC system other than the sandbox

I am trying to get the sdk working with my lab system. The lab system is using a cert from an inter Microsoft CA server. The root certificate from this CA had to be appended to the cacert.pem file from the certifi package. Using verify=false would allow an API connection but subsequents calls would fail. This problem was resolved when I updated the capers.pem file

(https://geekcontainer.wordpress.com/2018/07/20/sslerror-ssl-certificate_verify_failed-certificate-verify-failed-_ssl-c661-requests-gethttps-somedomain-com/)

After resolving that problem I can establish an API connection with verify=True enabled by subsequent calls are failing...

devices = dnac.devices.get_device_list()
Traceback (most recent call last):
File "", line 1, in
File "/Users/dsheaffe/mycode/dnac-env/lib/python3.7/site-packages/dnacentersdk/api/v1_3_3/devices.py", line 395, in get_device_list
json_data = self._session.get(endpoint_full_url, params=params)
File "/Users/dsheaffe/mycode/dnac-env/lib/python3.7/site-packages/dnacentersdk/restsession.py", line 398, in get
with self.request('GET', url, erc, 0, params=params, **kwargs) as resp:
File "/Users/dsheaffe/mycode/dnac-env/lib/python3.7/site-packages/dnacentersdk/restsession.py", line 320, in request
check_response_code(response, erc)
File "/Users/dsheaffe/mycode/dnac-env/lib/python3.7/site-packages/dnacentersdk/utils.py", line 216, in check_response_code
raise ApiError(response)
dnacentersdk.exceptions.ApiError: [404] Not Found - The URI requested is invalid or the resource requested, such as a user, does not exist. Also returned when the requested format is not supported by the requested method.

How do I fix this problem? I tried using the debug environment variable to get more info but it doesn't seem to work.

Auth URL Auth for 1.2.10

When installing using pip, I am unable to authenticate against DNA Center 1.2.10 even when setting the version to '1.2.10'

I believe this is due to the 'temp_url' setting in;

https://github.com/cisco-en-programmability/dnacentersdk/blob/master/dnacentersdk/api/authentication.py

which is currently set /dna/system/api/v1/auth/token

On 1.2.10 the working auth path I found is /api/system/v1/auth/token

Maybe the authentication_api function should also implement version support?

SDA :: add_default_authentication_profile

Prerequisites

  • Have you tested the operation in the API directly?
  • Do you have the latest SDK version?
  • Review the compatibility matrix before opening an issue.

Describe the bug
End point URL : "/dna/intent/api/v1/business/sda/authentication-profile"

Schema : siteNameHierarchy(string, required): Path of sda Fabric Site
authenticateTemplateName(string, required, enum: No Authentication , Open Authentication, Closed Authentication, Low Impact)

For authenticateTemplateName parameter , input string "No Authentication" [without white space at end] is failing at parameter validation.
Actual API call would still take both strings with and without white spaces.

Expected behavior
Api call should still happen as API accepts both strings with and without white.

Screenshots
Screenshot 2023-04-27 at 12 54 35 AM

Environment (please complete the following information):

  • Cisco DNA Center Version and patch: 2.3.6.0
  • Python version:3.6
  • SDK version:2.3.3
  • OS Version:

Additional context
Add any other context about the problem here.

Sda.adds_border_device boolean not accepted for connectedToInternet and borderWithExternalConnectivity

Prerequisites

  • Have you tested the operation in the API directly?

Yes →

Example Payload:

[
    {
        "deviceManagementIpAddress": "172.22.4.2",
        "siteNameHierarchy": "Global/SH-2",
        "deviceRole": [
            "Border_Node", 
            "Control_Plane_Node",
            "Edge_Node"
        ],
        "externalDomainRoutingProtocolName": "BGP",
        "externalConnectivityIpPoolName": "L3-Handoff",
        "internalAutonomouSystemNumber": "65101",
        "borderPriority": "10",
        "borderSessionType": "ANYWHERE",
        "connectedToInternet": "True",
        "borderWithExternalConnectivity": "False",
    }
]
  • Do you have the latest SDK version?
pip show dnacentersdk
Name: dnacentersdk
Version: 2.5.2
Summary: Cisco DNA Center Platform SDK
Home-page: https://dnacentersdk.readthedocs.io/en/latest/
Author: Jose Bogarin Solano
Author-email: [email protected]
License: MIT
Location: c:\users\username\appdata\local\packages\pythonsoftwarefoundation.python.3.10_qbz5n2kfra8p0\localcache\local-packages\python310\site-packages
Requires: fastjsonschema, future, requests, requests-toolbelt
Required-by: 

Describe the bug

Class: classSda
Function: adds_border_device(headers=None, payload=None, active_validation=True, **request_parameters)

First issue:
The scheme under Developer DNAC Docs wants booleans for the keys borderWithExternalConnectivity and connectedToInternet as values. Unfortunately, in reality only strings are accepted by the DNA Center here.

Payload:

[
    {
        "deviceManagementIpAddress": "172.22.4.2",
        "siteNameHierarchy": "Global/SH-2",
        "deviceRole": [
            "Border_Node", 
            "Control_Plane_Node",
            "Edge_Node"
        ],
        "externalDomainRoutingProtocolName": "BGP",
        "externalConnectivityIpPoolName": "L3-Handoff",
        "internalAutonomouSystemNumber": "65101",
        "borderPriority": "10",
        "borderSessionType": "ANYWHERE",
        "connectedToInternet": True,
        "borderWithExternalConnectivity": False,
    }
]

Error message:

PS E:\Users\username\ios-xe-nc-trial> python3 .\add_border_node.py
Traceback (most recent call last):
  File "E:\Users\username\ios-xe-nc-trial\add_border_node.py", line 70, in <module>
    dnac.sda.adds_border_device(payload = payload)
  File "C:\Users\username\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\dnacentersdk\api\v2_3_3_0\sda.py", line 370, in adds_border_device
    json_data = self._session.post(endpoint_full_url, params=_params,
  File "C:\Users\username\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\dnacentersdk\restsession.py", line 619, in post
    response = self.request('POST', url, erc, 0, params=params,
  File "C:\Users\username\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\dnacentersdk\restsession.py", line 471, in request  
    check_response_code(response, erc)
  File "C:\Users\username\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\dnacentersdk\utils.py", line 209, in check_response_code
    raise ApiError(response)
dnacentersdk.exceptions.ApiError: [400] Bad Request - The request was invalid or cannot be otherwise served.

When I adjust the validator, the API call works.

"borderWithExternalConnectivity": {
"type": "string"
},
"connectedToInternet": {
"type": "string"
},

Also following values are accepted with adjusted validators:

"connectedToInternet": true,
"borderWithExternalConnectivity": false,

Expected behavior
The API should accept Boolean according to the schema, but it does not.

Screenshots
image
image

Environment (please complete the following information):

  • Cisco DNA Center Version and patch: Version 2.3.3.4
  • Python version: Python 3.10.6
  • SDK version: 2.5.2
  • OS Version: Python:3 Windows 10, 21H2

Additional context

Thanks for maintaining the very good SDK 😊

api.task.get_task_by_id(taskid) return object does not include "endTime"

Prerequisites

  • Have you tested the operation in the API directly?
  • Do you have the latest SDK version?

Describe the bug
api.task.get_task_by_id(taskid) return object must include "endTime" when the task has completed.
presence of the "endTime" key in the response data signifies the completion of the task and hence is very useful for executing conditional loops to check task status.
Below is the response for obtained for a completed task using the SDK (api.task.get_task_by_id(taskid))
{
'version': 1667597378807,
'startTime': 1667597377102,
'progress': '{"fileId":"f4b356e7-d132-4eab-811a-bbad2001d08f"}',
'username': 'admin',
'serviceType': 'Command Runner Service',
'lastUpdate': 1667597378807,
'isError': False,
'instanceTenantId': '6334ab5f519bd86f3b93a4ee',
'id': '2eee4e7c-93b7-41c0-9c8f-de71e171d546'
}

Output from POSTMAN for the same task

"response": {
    "endTime": 1667597382798,       <---- Important endTime key/value pair 
    "version": 1667597382798,
    "startTime": 1667597377102,
    "progress": "{\"fileId\":\"f4b356e7-d132-4eab-811a-bbad2001d08f\"}",
    "username": "admin",
    "serviceType": "Command Runner Service",
    "lastUpdate": 1667597378807,
    "isError": false,
    "instanceTenantId": "6334ab5f519bd86f3b93a4ee",
    "id": "2eee4e7c-93b7-41c0-9c8f-de71e171d546"
},
"version": "1.0"

}
Expected behavior
Expected return object:
{
'version': 1667597378807,
'startTime': 1667597377102,
"endTime": 1667597382798,
'progress': '{"fileId":"f4b356e7-d132-4eab-811a-bbad2001d08f"}',
'username': 'admin',
'serviceType': 'Command Runner Service',
'lastUpdate': 1667597378807,
'isError': False,
'instanceTenantId': '6334ab5f519bd86f3b93a4ee',
'id': '2eee4e7c-93b7-41c0-9c8f-de71e171d546'
}

Screenshots
Please provide an screenshot of the successful API call with cuRL, Postman, etc.

Environment (please complete the following information):

  • Cisco DNA Center Version and patch: 2.2.2.5
  • Python version: 3.9.13
  • SDK version: 2.5.4
  • OS Version: Windows10 / ubuntu 20.4

Additional context
Add any other context about the problem here.

504 timed out error after setting timed out to 999999

using the dnac.sites.get_site_health() function and while using it inside a big scaled dnac environment the api call returns with a 504 timed out error after a minute of loading. What is strange is that i declared the single_request_timeout=99999 when declaring the api.DNACenterAPI. Also tried changing the timed out through environmental variables. Any suggestions or tips?

`base_url` kwarg is ignored causing ApiError to be raised.

I'm trying out this sdk and my initial attempts at calling the api methods are failing with dnacentersdk.exceptions.ApiError: [404] Not Found.

I'm running Python 3.8.2 on Ubuntu 18.04 with dnacentersdk==2.0.0. My Cisco DNA appliance is running 1.3.3.6. I've added my configuration to my ~/.profile and loaded it with source ~/.profile. My environment variables are all accessible from bash:

$ echo $DNA_CENTER_DEBUG
False
$ echo $DNA_CENTER_VERSION
1.3.3
$ echo $DNA_CENTER_ENCODED_AUTH
Y-REDACTED-=
$ echo $DNA_CENTER_USERNAME
myusername
$ echo $DNA_CENTER_PASSWORD
myplaintextpassword
$ echo $DNA_CENTER_BASE_URL
https://my.dnac-url.com:443

I'm simply trying to call the get_device_list() from the device onboarding. Here's what my interpreter looks like:

Python 3.8.2 (default, Jul 16 2020, 14:00:26) 
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from dnacentersdk import DNACenterAPI
>>> api = DNACenterAPI()
>>> api.device_onboarding_pnp.get_device_list()

url is: /dna/intent/api/v1/onboarding/pnp-device | erc: [200, 202, 204, 206] | params: {} | kwargs: {}
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/hnadmin/python-projects/network-verification/venv/lib/python3.8/site-packages/dnacentersdk/api/v1_3_3/device_onboarding_pnp.py", line 2278, in get_device_list
    json_data = self._session.get(endpoint_full_url, params=params)
  File "/home/hnadmin/python-projects/network-verification/venv/lib/python3.8/site-packages/dnacentersdk/restsession.py", line 400, in get
    with self.request('GET', url, erc, 0, params=params, **kwargs) as resp:
  File "/home/hnadmin/python-projects/network-verification/venv/lib/python3.8/site-packages/dnacentersdk/restsession.py", line 321, in request
    check_response_code(response, erc)
  File "/home/hnadmin/python-projects/network-verification/venv/lib/python3.8/site-packages/dnacentersdk/utils.py", line 216, in check_response_code
    raise ApiError(response)
dnacentersdk.exceptions.ApiError: [404] Not Found - The URI requested is invalid or the resource requested, such as a user, does not exist. Also returned when the requested format is not supported by the requested method.

You may have noticed the url is output right before the error is raised. This is from my debugging - I wanted to see exactly what URL is being called, and why it's 404'ing. You can see it's trying to send the GET to /dna/intent/api/v1/onboarding/pnp-device - it's missing the base URL.

The print statement was added to restsession.py in line 399 because this is where the error is being raised:

        print(f"\nurl is: {url} | erc: {erc} | params: {params} | kwargs: {kwargs}")
        with self.request('GET', url, erc, 0, params=params, **kwargs) as resp:

Just to rule out an issue with my environment variable setting, I put the parameters directly in the DNACenterAPI object as keyword args:

from dnacentersdk import DNACenterAPI

api = DNACenterAPI(username='myusername', password='myplaintextpw', base_url='https://my.dnac-url.com:443', version='1.3.3')
api.device_onboarding_pnp.get_device_list()

Executing this raises the same error, and my "url is" line is also missing the base_url (same traceback as above).

Self-signed certificate - disabling warning

Thanks for creating this SDK!
Trying it out with the DevNet sandbox DNAC - it works fine.
However, when I tried pulling my lab's DNAC, I got the following error:

requests.exceptions.SSLError: HTTPSConnectionPool(host='X.X.X.X', port=443): Max retries exceeded with url: /dna/system/api/v1/auth/token (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate in certificate chain (_ssl.c:1056)')))

Adding "requests.packages.urllib3.disable_warnings() " to the script did not help.

How can I use the SDK with self-signed certificates?

Regards,
Oren.

DNA_CENTER_VERIFY not being imported correctly from the environment

Prerequisites

  • Have you tested the operation in the API directly?
  • Do you have the latest SDK version?
  • Review the compatibility matrix before opening an issue.

Describe the bug
In environment.py the following string:

VERIFY_STRING_ENVIRONMENT_VARIABLE = 'DNA_CENTER_VERIFY_STRING'

doesn't match with the one described on the docs, it should be changed to:

VERIFY_STRING_ENVIRONMENT_VARIABLE = 'DNA_CENTER_VERIFY'

This prevents the SDK from working correctly since the environment variable is not loaded correctly.

Environment (please complete the following information):

  • Cisco DNA Center Version and patch: N/A
  • Python version: 3.8
  • SDK version: 2.6.1
  • OS Version: MacOS 13.3.1

Constancy in "offset" and "limit" implementation by using datatype to be either "Int" or "string"

Prerequisites

  • Have you tested the operation in the API directly?
  • Do you have the latest SDK version?

Describe the bug
when using offset and limit for large API outputs, some methods in sdk are using "string" datatype for offset and others are using "int" data type
example:
api.devices.get_device_list( limit:int, offset: int))
api.tag.get_tag_members_by_id(tag_id, "networkdevice",offset:str ,limit:str )

Expected behavior
Consistency in datatype for "offset" and "limit".

Screenshots
Please provide an screenshot of the successful API call with cuRL, Postman, etc.

Environment (please complete the following information):

  • Cisco DNA Center Version and patch: Any
  • Python version: 3.9.10
  • SDK version: 2.5.4
  • OS Version: Windows10 / Ubuntu 20.4

Additional context

Sda.adds_border_device virtualNetwork array not accepted as value

Prerequisites

  • Have you tested the operation in the API directly?

Yes →

Example Payload:

[
    {
        "deviceManagementIpAddress": "172.22.4.2",
        "siteNameHierarchy": "Global/SH-2",
        "deviceRole": [
            "Border_Node", 
            "Control_Plane_Node",
            "Edge_Node"
        ],
        "externalDomainRoutingProtocolName": "BGP",
        "externalConnectivityIpPoolName": "L3-Handoff",
        "internalAutonomouSystemNumber": "65101",
        "borderPriority": "10",
        "borderSessionType": "ANYWHERE",
        "connectedToInternet": "True",
        "borderWithExternalConnectivity": "True",
        "externalConnectivitySettings": [
            {
                "interfaceName": "GigabitEthernet1/0/24",
                "interfaceDescription": "Automated Value",
                "externalAutonomouSystemNumber": "65100",
                "l3Handoff": [
                    {
                        "virtualNetwork": 
                            {
                                "virtualNetworkName": "INFRA_VN",
                                "vlanId": "3200" 
                            }                       
                    },
                    {
                        "virtualNetwork": 
                            {
                                "virtualNetworkName": "BECHTLAB",
                                "vlanId": "3201" 
                            }                           
                    }                      
                ]
            }
        ]
    }
]
  • Do you have the latest SDK version?
pip show dnacentersdk
Name: dnacentersdk
Version: 2.5.2
Summary: Cisco DNA Center Platform SDK
Home-page: https://dnacentersdk.readthedocs.io/en/latest/
Author: Jose Bogarin Solano
Author-email: [email protected]
License: MIT
Location: c:\users\username\appdata\local\packages\pythonsoftwarefoundation.python.3.10_qbz5n2kfra8p0\localcache\local-packages\python310\site-packages
Requires: fastjsonschema, future, requests, requests-toolbelt
Required-by: 

Describe the bug

Class: classSda
Function: adds_border_device(headers=None, payload=None, active_validation=True, **request_parameters)

The scheme under Developer DNAC Docs wants arrays for the key virtualNetworkand as values. Unfortunately, in reality arrays are not accepted by the DNA Center here.

Payload:

[
    {
        "deviceManagementIpAddress": "172.22.4.2",
        "siteNameHierarchy": "Global/SH-2",
        "deviceRole": [
            "Border_Node", 
            "Control_Plane_Node",
            "Edge_Node"
        ],
        "externalDomainRoutingProtocolName": "BGP",
        "externalConnectivityIpPoolName": "L3-Handoff",
        "internalAutonomouSystemNumber": "65101",
        "borderPriority": "10",
        "borderSessionType": "ANYWHERE",
        "connectedToInternet": "True",
        "borderWithExternalConnectivity": "True",
        "externalConnectivitySettings": [
            {
                "interfaceName": "GigabitEthernet1/0/24",
                "interfaceDescription": "Automated Value",
                "externalAutonomouSystemNumber": "65100",
                "l3Handoff": [
                    {
                        "virtualNetwork": [
                            {
                                "virtualNetworkName": "INFRA_VN",
                                "vlanId": "3200" 
                            } 
                        ]                          
                    },  
                    {
                        "virtualNetwork": [
                            {
                                "virtualNetworkName": "BECHTLAB",
                                "vlanId": "3201" 
                            } 
                        ]                          
                    }             
                ]
            }
        ]
    }
]

Error message:

PS E:\Users\username\ios-xe-nc-trial> python3 .\add_border_node.py
Traceback (most recent call last):
  File "E:\Users\username\ios-xe-nc-trial\add_border_node.py", line 78, in <module>
    dnac.sda.adds_border_device(payload = payload)
  File "C:\Users\username\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\dnacentersdk\api\v2_3_3_0\sda.py", line 370, in adds_border_device
    json_data = self._session.post(endpoint_full_url, params=_params,
  File "C:\Users\username\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\dnacentersdk\restsession.py", line 619, in post
    response = self.request('POST', url, erc, 0, params=params,
  File "C:\Users\username\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\dnacentersdk\restsession.py", line 471, in request
    check_response_code(response, erc)
  File "C:\Users\username\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.10_qbz5n2kfra8p0\LocalCache\local-packages\Python310\site-packages\dnacentersdk\utils.py", line 209, in check_response_code
    raise ApiError(response)
dnacentersdk.exceptions.ApiError: [400] Bad Request - The request was invalid or cannot be otherwise served.

image

Expected behavior
The API should accept arrays according to the schema, but it does not.

Screenshots
image
image

Environment (please complete the following information):

  • Cisco DNA Center Version and patch: Version 2.3.3.4
  • Python version: Python 3.10.6
  • SDK version: 2.5.2
  • OS Version: Python:3 Windows 10, 21H2

Additional context

Thanks for maintaining the very good SDK 😊

CDP neighbor

I would like to know if there is a module in the latest SDK for DNAC version 1.3.X to get a CDP neighbor detail. I would like to get the ID and the interface of the neighbor node. Via API n DNAC something like this it is achieved by : /dna/intent/api/v1/device-enrichment-details.

Somehow i can get the data via dnac.sites.get_physical_topology(). But there is a big amount of data process. The simulated network is about 3000+ devices.

Make MyDict cachable

Hi,
I'm using flask_caching to cache certain responses from DNA Center, where the responses are MyDicts
flask_cache uses Pickle for object serialisation, and would support MyDicts also with a slight modification - namely adding these overrides:

def __getstate__(self):
    return self.__dict__

def __setstate__(self, d):
    self.__dict__.update(d)

I can find no harm in doing this, and it allows me to cache the responses, so I think this should be considered into the build?

dnacentersdk appears to add extra logging.StreamHandler()

I have boiled this down to a basic issue introduced when importing dnacentersdk, so I'm using the basic logging example from https://docs.python.org/3.7/howto/logging.html#configuring-logging to demonstrate the issue. When DNACenterAPI is imported, logging messages are sent to stdout twice (once following the configured formatter and once unformatted)

import logging
from dnacentersdk import DNACenterAPI

# create logger
logger = logging.getLogger('simple_example')
logger.setLevel(logging.DEBUG)

# create console handler and set level to debug
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)

# create formatter
formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s')

# add formatter to ch
ch.setFormatter(formatter)

# add ch to logger
logger.addHandler(ch)

# 'application' code
logger.debug('debug message')

Output with from dnacentersdk import DNACenterAPI

2020-10-09 15:16:49,099 - simple_example - DEBUG - debug message
DEBUG:simple_example:debug message

Output without from dnacentersdk import DNACenterAPI

2020-10-09 15:22:38,215 - simple_example - DEBUG - debug message

Any thoughts on how to stop the extra output would be appreciated.

Thanks!

DNACenterAPI.sites.assign_device_to_site() not working?

I can successfully issue a call to DNACenterAPI.sites.assign_device_to_site(device=[list of device objects], site_id="site ID"). I get back the following:
{'executionId': '39ff436e-5733-4f69-9efe-bd327ab72bd3', 'executionStatusUrl': '/dna/platform/management/business-api/v1/execution-status/39ff436e-5733-4f69-9efe-bd327ab72bd3', 'message': 'The request has been accepted for execution'}

And nothing happens. Not sure what I'm doing wrong here.

Some sda endpoints does not work

Prerequisites

  • yes have tested with the API directly /dna/intent/api/v1/business/sda/fabric-site
  • version: dnacentersdk==2.5.4

When trying to get the sda fabric count and creating a new fabric site the SDK fails with an HTTP error 400

Cannot test the fabric count from the DNAC GUI as it is not on the list, but have tested the POST:fabric-site endpoint and I am able to create a fabric site using it on the DNAC GUI.
API endpoint: /dna/intent/api/v1/business/sda/fabric-site
request body:
{
"fabricName": "Default LAN Fabric",
"siteNameHierarchy": "Global/EMEA/Denmark/Aarhus/Tangen9, 8200"
}

Screenshots
image

Environment (please complete the following information):
2..2.3.6
Python 3.8.2
dnacentersdk==2.5.4
Windows 10

Additional context

from pprint import pprint


from dnacentersdk import api


# Create a DNACenterAPI connection object;
# it uses DNA Center sandbox URL, username and password, with DNA Center API version 2.2.3.3.
# and requests to verify the server's TLS certificate with verify=True.
dnac = api.DNACenterAPI(username="admin",
                        password="MySecret",
                        base_url="https://172.26.1.11:443",
                        version='2.2.3.3',
                        verify=False)

devices = dnac.devices.get_device_list()
print("Printing the hostname of all devices on the DNAC:")
for device in devices.response:
    print(device.hostname)

payload = {
    "fabricName": "Default LAN Fabric",
    "siteNameHierarchy": "Global/EMEA/Denmark/Aarhus/Tangen9, 8200"
}
task = dnac.sda.add_site(payload=payload)
print(task)

Error code:

python step02.py
Printing the hostname of all devices on the DNAC:
DK-SJ2-TEST.dna.das-i.dk
EXPO-FIAB.lab.sdalab.dk
Traceback (most recent call last):
  File "step02.py", line 25, in <module>
    task = dnac.sda.add_site(payload=payload)
  File "C:\Users\rael\Documents\Coding\DNAC-sdk\.venv\lib\site-packages\dnacentersdk\api\v2_2_3_3\sda.py", line 1456, in add_site
    json_data = self._session.post(endpoint_full_url, params=_params,
  File "C:\Users\rael\Documents\Coding\DNAC-sdk\.venv\lib\site-packages\dnacentersdk\restsession.py", line 619, in post
    response = self.request('POST', url, erc, 0, params=params,
  File "C:\Users\rael\Documents\Coding\DNAC-sdk\.venv\lib\site-packages\dnacentersdk\restsession.py", line 471, in request
    check_response_code(response, erc)
  File "C:\Users\rael\Documents\Coding\DNAC-sdk\.venv\lib\site-packages\dnacentersdk\utils.py", line 209, in check_response_code
    raise ApiError(response)
dnacentersdk.exceptions.ApiError: [400] Bad Request - The request was invalid or cannot be otherwise served.

Support for DNA Center version 1.3.3.x?

I'm just getting started with this Python package but it appears it only support 1.2.10 and 1.3.0 versions of DNA Center currently. Any plans on adding/changing the APIs to support 1.3.3? (outside of the custom APIs feature)

preview_template function overwrites params

From api/v2_1_2/configuration_templates.py

params = { } params.update(request_parameters) params = dict_from_items_with_values(params)

I'm just going to submit a check for None before this entry.

DNACenterAPI constructor allows for optional arguments

The DNACenterAPI constructor allows for optional arguments for username and password. These are technically not optional, they are required. They must be provided by the consumer of the API -OR- set as environment variables. The arguments are populated if environment variables are set, but those must be set before the module is imported, which is before _init_.py is interpreted, or else they will be 'None.' It seems it would be better to retrieve these environment variables at DNACenterAPI construction so that someone can import the sdk package, set the variables, and then instantiate the class--for example if demonstrating or testing the SDK via interpreter CLI. If they attempt to follow that order in the current design, the environment variables will be 'None.' Additionally, the roll up of environment variables from config.py, to environment.py, and _init_.py is a bit complex, obfuscated and not following OOP design.

Add the ability to depaginate API queries that paginate

Is your feature request related to a problem? Please describe.

My network is quite large, and as such I'm very frequently running queries that return results in excess of the "limit" variable set for the particular function.

As a result, I need to create a loop that re-runs the queries, increasing the offset by the limit (which isn't consistent between functions) until the response is empty, then concatenates the returned lists to give me my full result.

Describe the solution you'd like

Add an option (e.g. "limit=max") that returns all responsive items, regardless of the limit.

Describe alternatives you've considered

This is relatively trivial to workaround on a function by function basis using the method above, but it requires you to have prior knowledge of how the particular function will paginate. It also requires you to know in advance that pagination will be a concern for your particular query, which isn't always obvious.

Let's say that you're using the get_devices API function and currently have 490 switches. You write a bunch of scripts leveraging this API call. Your network then grows, adding a new site, increasing your total to 510. Your script will now only receive the first 500 switches. No exception or warning is raised to alert that this list is incomplete, and your script requires a re-write to handle the new network size.

pip install dnacentersdk fails on Windows 10

pip install dnacentersdk fails on Windows 10.
PS C:\Windows\system32> pip install dnacentersdk
ERROR: Exception:
Traceback (most recent call last):
File "c:\program files\python39\lib\site-packages\pip_internal\cli\base_command.py", line 180, in _main
status = self.run(options, args)
File "c:\program files\python39\lib\site-packages\pip_internal\cli\req_command.py", line 204, in wrapper
return func(self, options, args)
File "c:\program files\python39\lib\site-packages\pip_internal\commands\install.py", line 318, in run
requirement_set = resolver.resolve(
File "c:\program files\python39\lib\site-packages\pip_internal\resolution\resolvelib\resolver.py", line 127, in resolve
result = self._result = resolver.resolve(
File "c:\program files\python39\lib\site-packages\pip_vendor\resolvelib\resolvers.py", line 473, in resolve
state = resolution.resolve(requirements, max_rounds=max_rounds)
File "c:\program files\python39\lib\site-packages\pip_vendor\resolvelib\resolvers.py", line 341, in resolve
name, crit = self._merge_into_criterion(r, parent=None)
File "c:\program files\python39\lib\site-packages\pip_vendor\resolvelib\resolvers.py", line 172, in _merge_into_criterion
if not criterion.candidates:
File "c:\program files\python39\lib\site-packages\pip_vendor\resolvelib\structs.py", line 139, in bool
return bool(self._sequence)
File "c:\program files\python39\lib\site-packages\pip_internal\resolution\resolvelib\found_candidates.py", line 143, in bool
return any(self)
File "c:\program files\python39\lib\site-packages\pip_internal\resolution\resolvelib\found_candidates.py", line 129, in
return (c for c in iterator if id(c) not in self._incompatible_ids)
File "c:\program files\python39\lib\site-packages\pip_internal\resolution\resolvelib\found_candidates.py", line 30, in _iter_built
for version, func in infos:
File "c:\program files\python39\lib\site-packages\pip_internal\resolution\resolvelib\factory.py", line 258, in iter_index_candidate_infos
result = self._finder.find_best_candidate(
File "c:\program files\python39\lib\site-packages\pip_internal\index\package_finder.py", line 879, in find_best_candidate
candidates = self.find_all_candidates(project_name)
File "c:\program files\python39\lib\site-packages\pip_internal\index\package_finder.py", line 824, in find_all_candidates
page_candidates = list(page_candidates_it)
File "c:\program files\python39\lib\site-packages\pip_internal\index\sources.py", line 134, in page_candidates
yield from self._candidates_from_page(self._link)
File "c:\program files\python39\lib\site-packages\pip_internal\index\package_finder.py", line 783, in process_project_url
html_page = self._link_collector.fetch_page(project_url)
File "c:\program files\python39\lib\site-packages\pip_internal\index\collector.py", line 512, in fetch_page
return _get_html_page(location, session=self.session)
File "c:\program files\python39\lib\site-packages\pip_internal\index\collector.py", line 422, in _get_html_page
resp = _get_html_response(url, session=session)
File "c:\program files\python39\lib\site-packages\pip_internal\index\collector.py", line 120, in _get_html_response
resp = session.get(
File "c:\program files\python39\lib\site-packages\pip_vendor\requests\sessions.py", line 555, in get
return self.request('GET', url, **kwargs)
File "c:\program files\python39\lib\site-packages\pip_internal\network\session.py", line 449, in request
return super().request(method, url, *args, **kwargs)
File "c:\program files\python39\lib\site-packages\pip_vendor\requests\sessions.py", line 542, in request
resp = self.send(prep, **send_kwargs)
File "c:\program files\python39\lib\site-packages\pip_vendor\requests\sessions.py", line 655, in send
r = adapter.send(request, **kwargs)
File "c:\program files\python39\lib\site-packages\pip_vendor\cachecontrol\adapter.py", line 53, in send
resp = super(CacheControlAdapter, self).send(request, **kw)
File "c:\program files\python39\lib\site-packages\pip_vendor\requests\adapters.py", line 439, in send
resp = conn.urlopen(
File "c:\program files\python39\lib\site-packages\pip_vendor\urllib3\connectionpool.py", line 696, in urlopen
self._prepare_proxy(conn)
File "c:\program files\python39\lib\site-packages\pip_vendor\urllib3\connectionpool.py", line 964, in _prepare_proxy
conn.connect()
File "c:\program files\python39\lib\site-packages\pip_vendor\urllib3\connection.py", line 359, in connect
conn = self._connect_tls_proxy(hostname, conn)
File "c:\program files\python39\lib\site-packages\pip_vendor\urllib3\connection.py", line 500, in connect_tls_proxy
return ssl_wrap_socket(
File "c:\program files\python39\lib\site-packages\pip_vendor\urllib3\util\ssl
.py", line 432, in ssl_wrap_socket
ssl_sock = ssl_wrap_socket_impl(sock, context, tls_in_tls)
File "c:\program files\python39\lib\site-packages\pip_vendor\urllib3\util\ssl
.py", line 474, in _ssl_wrap_socket_impl
return ssl_context.wrap_socket(sock)
File "c:\program files\python39\lib\ssl.py", line 500, in wrap_socket
return self.sslsocket_class._create(
File "c:\program files\python39\lib\ssl.py", line 997, in _create
raise ValueError("check_hostname requires server_hostname")
ValueError: check_hostname requires server_hostname

reserve-ip-subpool fails

Hi All
Reserve IP Subpool fails with dnacentersdk as well as via postman direct to DNAC.
https://{{dnac}}/dna/intent/api/v1/reserve-ip-subpool/{{siteid}}

Try with following input:
{
"name": "Test1",
"type": "Generic",
"ipv6AddressSpace": false,
"ipv4GlobalPool": "3.0.0.0/24",
"ipv4Prefix": true,
"ipv4PrefixLength": 24,
"ipv4Subnet": "3.1.0.0"
}


Output is Ipv6 Global pool(3.0.0.0/24) is not present even though setting ipv6AddressSpace to false if global pool does not exist.
Another output that can be provoked is "Invalid ip subnet(3.0.0.0/8) address for ipv4 global pool" even if global pool exists.
Input works as excpected through the UI.

GET for /dna/intent/api/v1/network-device breaks with empty JSON payload

There is a defect in the DNAC SDK devices.py code, line 547:

if with_custom_headers:
    json_data = self._session.get(endpoint_full_url, params=params,
                                  json=_payload, headers=_headers)
else:
    json_data = self._session.get(endpoint_full_url, params=params,
                                  json=_payload)

Passing in json=_payload for a get request is generally unusual, and for this specific API, e_url = ('/dna/intent/api/v1/network-device') definitely not supported. In 2.1.1.1 it breaks.

Create_Network malformed request for 2.3.3

Hi team,

I've DNAC 2.3.3.3 and using the dnacentersdk.
I'm trying to configure the network settings of DNAC by using the create_network function under network_settings class.

I'm passing the following schema

{
"settings" : {
"dnsServer": {
"domainName" : "domain.local",
"primaryIpAddress": "x.x.x.x"
}
}
}

The SDK returns "MalformedRequest", Reason: data.settings.dnsServer.domainName must be one of ['can only contain alphanumeric characters or hypen']

However, when I call the API directly with Python or using the DNAC GUI developer toolkit with exactly the same schema as above, it passes and gets configured.

Regards.

re-auth after 50 requests

I have experienced that after using Sites.assign_device_to_site() 50 times with the same DNACenterAPI object, it doesn't work anymore. I suppose the authentication token might be invalidated by DNAC after 50 use?

It would be nice if DNACenterAPI would request automatically a new token once the current token becomes invalid. Alternatively it would be still nice to have a method which checks the validity of the current token and another method which would initiate a reauthentication.

As an alternative solution, splitting jobs into smaller, <50 request chunks is a feasible workaround.

import ERROR: cannot import name api?

@Ubuntu1:~/labs/lab01$ python3
Python 3.6.9 (default, Oct 8 2020, 12:12:24)
[GCC 8.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.

from dnacentersdk import api
Traceback (most recent call last):
File "", line 1, in
ImportError: cannot import name 'api'

Attribute error

Traceback (most recent call last):
File "./dnac_assurance.py", line 17, in
network_health= dnac.networks.get_overall_network_health(timestamp='')
AttributeError: 'DNACenterAPI' object has no attribute 'networks'

Can be solved by adding version number '1.3.1.' to dnac instance creation or replace attribute networks with topology for API 2.x

Support for Event Management (webhook) - DNA Center 1.3.1

  • Delete Event Subscriptions
  • Count of Event Subscriptions
  • Get Events
  • Count of Events
  • Count of Notifications
  • Get Status API for Events
  • Get Event Subscriptions
  • Get Notifications
  • Create Event Subscriptions
  • Update Event Subscriptions

image

Command Runner issue: cannot save command output to file

From this blog: https://blogs.cisco.com/developer/network-automation-cisco-dna-center-sdk-2

How do you "Retrieve the results and save them to file"? This part is missing from the blog.

The result from the code given in the blog is a class cmd_output, not a file with the results.

More discussion here: https://community.cisco.com/t5/cisco-digital-network/dnac-command-runner-question/m-p/4570843

Need to have a way to save the command runner to a file to complete the task.

SDK implementation for API Add Edge Device to Sda fabric on DNAC Version 2.3.3.0 inconsistent with previous DNAC versions implementation

Prerequisites

  • [* ] Have you tested the operation in the API directly?
  • [ *] Do you have the latest SDK version?
  • [ *] Review the compatibility matrix before opening an issue.

Describe the bug
To add edge device to sda, the api implementation in 2.3.3.0 is missing input vars ( which is inconsistent with previous implementations).
Must include input vars 'deviceManagementIpAddress' and 'siteNameHierarchy'
in 2.2.3.3 method def --->
def add_edge_device(self,
deviceManagementIpAddress=None,
siteNameHierarchy=None,
headers=None,
payload=None,
active_validation=True,
**request_parameters):

in 2.3.3.0 method def -->
def add_edge_device(self,
headers=None,
payload=None,
active_validation=True,
**request_parameters):

Also 'payload' type set to 'list'. must be 'dict' which matches with expected API 'body' documentation as well as 2.2.3.3 implemenation of the same method
Expected behavior

  1. dnac_api.sda. add_edge_device() must provide option for input vars 'deviceManagementIpAddress' and 'siteNameHierarchy' ( consitent with 2.2.3.3 release implementation
  2. input var 'payload' type set to 'list'. must be 'dict' which matches with expected API 'body' documentation of DNAC API. as well as 2.2.3.3 implemenation of the same method

Screenshots
[Please provide an screenshot of the successful API call with cuRL, Postman, etc.]
links to both implementations from the docs.
https://dnacentersdk.readthedocs.io/en/latest/_modules/dnacentersdk/api/v2_3_3_0/sda.html#Sda.add_edge_device
https://dnacentersdk.readthedocs.io/en/latest/_modules/dnacentersdk/api/v2_2_3_3/sda.html#Sda.add_edge_device

Environment (please complete the following information):

  • Cisco DNA Center Version and patch: 2.3.3.5
  • Python version: 3.9
  • SDK version: 2.5.6
  • OS Version: Windows 11

Additional context
Add any other context about the problem here.

Code where the bug is identified:

device_payload = {
            "deviceManagementIpAddress": mgmt_ip,
            "siteNameHierarchy": site_name
        }

**above device_payload causes an error. Debug shown below
edge_status = None

try:
    add_edge_status = api_.sda.add_edge_device(payload=device_payload) ####  --> had to change to this for 2.3.3.0 release from below method
    #add_edge_status = api_.sda.add_edge_device(deviceManagementIpAddress=mgmt_ip,siteNameHierarchy = site_name)  ###  ---> this one can be used in 2.2.3.3 release
    logger.info(add_edge_status)
    pprint(add_edge_status)

**dnacentersdk output:
2023-04-22 15:06:10,999::main::-dnac_edge_disvoery::-: add_edge_device - ERROR :: - We were expecting to receive an instance of one of the following types: 'list'or 'None'; but instead we received {'deviceManagementIpAddress': '172.20.1.162', 'siteNameHierarchy': 'Global/United States/JFK'} which is a 'dict'.
2023-04-22 15:06:10,999::main::-dnac_edge_disvoery::-: add_edge_device - ERROR :: - Edge device not added to fabric : {'deviceManagementIpAddress': '172.20.1.162', 'siteNameHierarchy': 'Global/United States/JFK'}

It is not possible to create a global pool with network_settings.create_global_pool

Prerequisites

  • Have you tested the operation in the API directly?

Yes →

Example Payload:

{
    "settings": { 
        "ippool": [ 
            { 
                "ipPoolName": "TestPool", 
                "type": "Generic", 
                "ipPoolCidr": "10.253.0.0/20",
                "IpAddressSpace": "IPv4"
            }
        ] 
    }
}
  • Do you have the latest SDK version?
pip show dnacentersdk
Name: dnacentersdk
Version: 2.5.0
Summary: Cisco DNA Center Platform SDK
Home-page: https://dnacentersdk.readthedocs.io/en/latest/
Author: Jose Bogarin Solano
Author-email: [email protected]
License: MIT
Location: c:\users\user1\appdata\local\packages\pythonsoftwarefoundation.python.3.10_qbz5n2kfra8p0\localcache\local-packages\python310\site-packages
Requires: fastjsonschema, future, requests, requests-toolbelt
Required-by: 

Describe the bug

Class: classNetworkSettings
Function: create_global_pool(settings=None, headers=None, payload=None, active_validation=True, **request_parameters)

The parameter "IpAddressSpace" in the payload does not allow valid values. This is apparently due to the validator.

Error message:

Traceback (most recent call last):
  File "/usr/local/lib/python3.10/site-packages/dnacentersdk/models/validators/v2_3_3_0/jsd_eecf4323cb285985be72a7e061891059.py", line 97, in validate
    self._validator(request)
  File "<string>", line 37, in validate
fastjsonschema.exceptions.JsonSchemaValueException: data.settings.ippool[0].IpAddressSpace must be one of ['IPv6 or IPv4']

When I adjust the validator, the API call works.

"IpAddressSpace": {
    "enum": [
        "IPv6",   
        "IPv4"
    ]

Expected behavior
"IPv4" or "IPv6" should be accepted as value for "IpAddressSpace".

Screenshots
CreateIPPool1
CreateIPPool2
CreateIPPool3

Environment (please complete the following information):

  • Cisco DNA Center Version and patch: Version 2.2.3.5
  • Python version: Python 3.10.5
  • SDK version: 2.5.0
  • OS Version: Python:3 Docker Container

Additional context

Thanks for maintaining the very good SDK 😊

network_settings.create_network() issue

Hi All
JSON Schema Validation is incorrect for all DNS related stuff in this request.

Original Request / dnacentersdk.exceptions.MalformedRequest:
{'settings': {'dnsServer': {'primaryIpAddress': '10.5.5.5', 'secondaryIpAddress': '10.6.6.6'}, 'dhcpServer': ['10.1.1.1', '10.2.2.2'], 'ntpServer': ['10.3.3.3', '10.4.4.4']}

If you put in the value of the acutal enum the validation passes and the request "works", or at least gets sent off to the DNAC. But of course fail because of wrong arguments.
{'dnsServer': {'primaryIpAddress': 'valid range : 1.0.0.0 - 223.255.255.255', 'secondaryIpAddress': 'valid range : 1.0.0.0 - 223.255.255.255'}, 'dhcpServer': ['10.1.1.1', '10.2.2.2'], 'ntpServer': ['10.3.3.3', '10.4.4.4'], 'timezone': 'Europe/Berlin (CEST)'}

same with the domain name:
Reason: data.settings.dnsServer.domainName must be one of ['can only contain alphanumeric characters or hyphen']

if you put in that value ( can only....) it passes validation and get sent to dnac
{'dnsServer': {'domainName': 'can only contain alphanumeric characters or hyphen', 'primaryIpAddress': 'valid range : 1.0.0.0 - 223.255.255.255', 'secondaryIpAddress': 'valid range : 1.0.0.0 - 223.255.255.255'}, 'dhcpServer': ['10.1.1.1', '10.2.2.2'], 'ntpServer': ['10.3.3.3', '10.4.4.4'], 'timezone': 'Europe/Berlin (CEST)'}

Update readthedocs-sphinx-search

Looks like you are using an old version of the extension

dnacentersdk/Pipfile.lock

Lines 381 to 384 in b752b32

"readthedocs-sphinx-search": {
"git": "https://github.com/readthedocs/readthedocs-sphinx-search",
"ref": "b34c28365debd685c51310c9d131a156ce244cf2"
},

We updated the endpoint used by the search extension, so old versions will stop working soon. Please use the new version of the extension https://github.com/readthedocs/readthedocs-sphinx-search (we have releases in pypi now ;))

DNA_CENTER_VERIFY environment variable is not parsed correctly

Prerequisites

  • Have you tested the operation in the API directly?
  • Do you have the latest SDK version?

Describe the bug
When environment variable DNA_CENTER_VERIFY is set to "false" or 0, the DNACenterAPI Connection Object still gets initialized with verify=True.

Expected behavior
The DNACenterAPI Connection Object gets initialized with verify=False.

Screenshots

(env) $export DNA_CENTER_BASE_URL=https://***:443
(env) $export DNA_CENTER_USERNAME=admin
(env) $export DNA_CENTER_PASSWORD=***
(env) $export DNA_CENTER_VERIFY=0
(env) $python3
Python 3.9.5 (default, Nov 23 2021, 15:27:38)
[GCC 9.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from dnacentersdk import DNACenterAPI
>>> api = DNACenterAPI()
Traceback (most recent call last):
...
ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate in certificate chain (_ssl.c:1129)

Environment (please complete the following information):

  • Cisco DNA Center Version and patch: 2.2.2.6
  • Python version: 3.9.5
  • SDK version: 2.4.10
  • OS Version: Ubuntu 20.04.4 LTS

Additional context
Add any other context about the problem here.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.