12-05-2024
11:14 AM
- last edited on
12-06-2024
09:24 PM
by
rupeshah
Hello Everyone,
I am in need to pull various configurations from Catalyst Center switches via the API. I know Netmiko/Paramiko can be used but the request is to leverage Catalyst Center. I am aware of "devices.get_device_config_by_id('deviceUUID')" or "command_runner.run_read_only_commands_on_devices(commands=cmds, deviceUuids=[device['id']])" however both of these return data masqueraded.
Example:
snmp-server community xxxxxxxx RO
I noticed there is another API call called export_device_configurations. Unfortunately I am struggling to figure out how to use it. I am hoping someone within the community can assist with the structure required. I've reviewed the documentation here and tried setting up the payload with a dictionary with a deviceId and password but still fails:
r = api_.configuration_archive.export_device_configurations(payload=json.dumps(payload))
I tried all sort of variations without success and could use any advice that can be shared.
r = api_.configuration_archive.export_device_configurations(deviceId='xxxxxx', password=p, headers=None, payload=json.dumps(payload), active_validation=True)
Thanks in advance.
-E
Solved! Go to Solution.
12-06-2024 12:50 PM - edited 12-06-2024 01:24 PM
That's odd. I just tested against a Cat-C running 2.3.7.6 in my lab and found that the API docs(and hence the SDK) is wrong in that deviceId should be a string in 2.3.7.X. There also seems to be changes to the API for file download between 2.3.5 and 2.3.7, so my guess would be that cmd_output.json() fails due to version incompatibility(data/objects don't adhere to expected format for 2.3.5). I don't think it is a good use of time to troubleshoot this further until the SDK error has been mended.
I have created an Issue for this on github and will (probably) create a fix at some point in the coming days. You should bring up the API documentation & SDK error with TAC.
EDIT: Are you able to pass deviceId as a list without setting version if you set active_validation to False? If so that could be a workaround for the time being.
12-05-2024 12:41 PM
What does the payload look like, and what error are you getting specifically?
I don't believe you are required to specify a payload for this. Can you try this and post outputs?
r = api_.configuration_archive.export_device_configurations(deviceId='your-device-id', password="Password1!")
12-05-2024 02:27 PM
Appreciate the prompt reply Torbjorn. I tried that earlier but spits out the following:
>>> r = api_.configuration_archive.export_device_configurations(deviceId='xxxxxx-xxxxx-xxxx-xxxx-xxxxxxx', password="Password1!")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\virtualenv\lib\site-packages\dnacentersdk\api\v2_3_7_6\configuration_archive.py", line 272, in export_device_configurations
return self.export_device_configurations_v1(
File "C:\virtualenv\lib\site-packages\dnacentersdk\api\v2_3_7_6\configuration_archive.py", line 147, in export_device_configurations_v1
json_data = self._session.post(endpoint_full_url, params=_params,
File "C:\virtualenv\lib\site-packages\dnacentersdk\restsession.py", line 629, in post
response = self.request('POST', url, erc, 0, params=params,
File "C:\virtualenv\lib\site-packages\dnacentersdk\restsession.py", line 481, in request
check_response_code(response, erc)
File "C:\virtualenv\lib\site-packages\dnacentersdk\utils.py", line 204, in check_response_code
raise ApiError(response)
dnacentersdk.exceptions.ApiError: [400] Bad Request - BadRequest - JSON parse error: Cannot construct instance of `java.util.ArrayList` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('xxxxxx-xxxxx-xxxx-xxxx-xxxxxxx'); nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `java.util.ArrayList` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('xxxxxx-xxxxx-xxxx-xxxx-xxxxxxx')
at [Source: (PushbackInputStream); line: 1, column: 40] (through reference chain: com.cisco.apicem.config.archive.request.dto.ExportDeviceConfigWrapperDTO["deviceId"]): JSON parse error: Cannot construct instance of `java.util.ArrayList` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('xxxxxx-xxxxx-xxxx-xxxx-xxxxxxx'); nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of `java.util.ArrayList` (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('xxxxxx-xxxxx-xxxx-xxxx-xxxxxxx')
at [Source: (PushbackInputStream); line: 1, column: 40] (through reference chain: com.cisco.apicem.config.archive.request.dto.ExportDeviceConfigWrapperDTO["deviceId"])
I've opened a TAC case but they are being very slow to respond.
Thanks again for trying to help out.
12-06-2024 12:42 AM - edited 12-06-2024 12:44 AM
Which version of Catalyst center are you using? Prior to 2.3.7.X the API and SDK expects deviceId to be a list of device IDs while 2.3.7.X expects a string with a single device ID.
This should start working if you create the api_ object with the attribute version=2.3.5.3 and update your code to this:
r = api_.configuration_archive.export_device_configurations(deviceId=['your-device-id'], password="Password1!")
If you are running something else than 2.3.5.X the accepted versions you can set are: 2.2.2.3, 2.2.3.3, 2.3.3.0, 2.3.5.3 and 2.3.7.6.
12-06-2024 08:18 AM
Thanks Torbjorn. I feel progress is being made but still not fully there. Good suggestion with specifying the version and structuring the deviceId as a list. Not sure why I need to downgrade when we are running Catalyst Center version 2.3.7.6-70319 but defining 2.3.5.3 during the initial API call accepts the command. I am now encountering a separate issue however. The file created and being downloaded is corrupted. I see the last Export_Configs-06_Dec_2024_15_54_50_734-DW0.zip but cannot open it. Also seeing a decode error (UnicodeDecodeError: 'utf-8' codec can't decode byte 0xd9 in position 10: invalid continuation byte).
>>> r = api_.configuration_archive.export_device_configurations(deviceId=['xxxxx-xxxx-xxxx-xxxxxxx'], password="Password1!")
>>> r
{'response': {'taskId': '01939c86-1591-7c62-9ee5-d89768d0e43f', 'url': '/api/v1/task/01939c86-1591-7c62-9ee5-d89768d0e43f'}, 'version': '1.0'}
>>> r = api_.task.get_task_by_id(r.response.taskId)
>>> r
{'response': {'taskId': xxxxxx-xxxx-xxxx-xxxx-d89768d0e43f', 'url': '/api/v1/task/xxxxxx-xxxx-xxxx-xxxx-d89768d0e43f'}, 'version': '1.0'}
>>> r = api_.task.get_task_by_id(r.response.taskId)
>>> r
{'response': {'startTime': 1733497853329, 'progress': 'Device configuration Successfully exported as password protected ZIP.', 'version': 1733497854065, 'data': "Total Device Count: '1', Total Success Count: '1", 'endTime': 1733497854065, 'lastUpdate': 1733497853331, 'additionalStatusURL': '/api/v1/file/xxxxxx-xxxx-xxxx-xxxx-007d0ddf1caa', 'serviceType': 'NCAR', 'isError': False, 'username': 'NCAR88888', 'instanceTenantId': 'xxxxxxxxxxxxx972f', 'id': 'xxxxxx-xxxx-xxxx-xxxx-d89768d0e43f'}, 'version': '1.0'}
>>>cmd_output = api_.file.download_a_file_by_fileid('xxxxxx-xxxx-xxxx-xxxx-007d0ddf1caa', save_file=True, dirpath="logs")
>>> cmd_output.json()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "C:\virtualenv\lib\site-packages\urllib3\response.py", line 384, in json
data = self.data.decode("utf-8")
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xd9 in position 10: invalid continuation byte
Any idea what I am doing wrong?
Thanks in advance.
12-06-2024 12:50 PM - edited 12-06-2024 01:24 PM
That's odd. I just tested against a Cat-C running 2.3.7.6 in my lab and found that the API docs(and hence the SDK) is wrong in that deviceId should be a string in 2.3.7.X. There also seems to be changes to the API for file download between 2.3.5 and 2.3.7, so my guess would be that cmd_output.json() fails due to version incompatibility(data/objects don't adhere to expected format for 2.3.5). I don't think it is a good use of time to troubleshoot this further until the SDK error has been mended.
I have created an Issue for this on github and will (probably) create a fix at some point in the coming days. You should bring up the API documentation & SDK error with TAC.
EDIT: Are you able to pass deviceId as a list without setting version if you set active_validation to False? If so that could be a workaround for the time being.
12-06-2024 01:40 PM - edited 12-06-2024 01:54 PM
Thank you so much Torbjorn! FYI, I was able to get SDK '2.3.7.6' to accept the "configuration_archive.export_device_configurations" call with active_validation set to false. I still run into the issue however of exporting the configuration file.
UnicodeDecodeError: 'utf-8' codec can't decode byte 0x86 in position 12: invalid start byte
TAC confirmed they can reproduce it and will work internally on getting a resolution for the API documentation & SDK error. I've send you a little e-transfer for coffee or beer.
Regards.
-E
Discover and save your favorite ideas. Come back to expert answers, step-by-step guides, recent topics, and more.
New here? Get started with these tips. How to use Community New member guide