12-16-2024 05:15 AM
Hello Team,
I have to remove MPLS BGP configuration from cEDGE but the configuration was attached from 3 templates. It took me 1-2h to find which exactly because one of them was CLI template.
I would like to safe time generate API token in vmanage and to access SD WAN routers via API.
It will be good if someone share with me script in python which help me to see which line from running config of the vEDGE router from which feature template is attached.
Could you help me with this task? Is there ready script for this which may help me for future.
If you have working solution for this problem please share with me.
Thank you!
Georgi Stoyanov
georgistoyanov@dundeeprecious.com
+359899543691
12-16-2024 08:31 AM
I unfortunately don't think there is any API endpoint which will give you this easily. There is AFAIK no way to render the specific feature templates into the final config output without adding it to a device template & attaching it to a device. Once you render the device template it only gives you the combined result of all feature templates without any pointers to what came from where.
The most feasible way I can see to do this is to add and remove each feature template from the device template for a test device and check for presence of the line of config you're looking for.
12-16-2024 11:15 PM - edited 12-16-2024 11:16 PM
Hello @Torbjørn,
I could give you example for better understanding. I have BGP configuration which is attached from 2-3 templates. The output below is cli output:
vEDGE01#sh run | in bgp
redistribute bgp 65666 route-map BGP_TO_OSPF_APN_CHE
router bgp 65666
bgp log-neighbor-changes
bgp router-id 172.18.2.3
distance bgp 20 200 20
snmp-server enable traps bgp
snmp-server enable traps bgp cbgp2
vEDGE01#
The goal is to understand if all 5 line config is from 1 feature template or it's from 2-3 feature template. The templates are already attached. This will help you when you remove it in case of decommission of BGP session with MPLS provider.
Thank you!
Best regards,
georgi.stoyanov@dundeeprecious.com
+359899543691
12-16-2024 11:39 PM
There is no documented API endpoint that will give you this information and there is no way to preview the device config before attaching it through the API. You will have to deduce which templates generate which lines of config through attaching and reattaching feature templates to a test device and checking it's config if you wish to figure out this through the API.
I agree that this would be a useful tool as it isn't always intuitive.
12-17-2024 12:03 AM
Hello @Torbjørn
Sorry but I will try to explain because I am not sure if you understood me right.
The idea is we have already configured SD WAN router and we wanna to remove some configuration. We have attached all template all is working properly. Execute from CLI "show run" or "sh sdwan run" specify which configure should be remove. After that with API or script paste our part of configuration from CLI which we wanna to remove it and the API or script show us from which templates are attached. The go to vmanage and remove/edit specific template.
I am also not sure if there is specific tool/script for this task that's why try to write here.
Best regards,
Georgi Stoyanov
georgi.stoyanov@dundeeprecious.com
+359 899543691
12-16-2024 08:49 AM
@georgi-stoyanov from the running configuration - you cannot see this via the API i do not think, i am using /device/config endpoint, which is the only one i know which shows running conifg, by using device ID.
You could try this idea, you would need to grab the device id, here i am using the always on sandbox and device .11. It look through templates that have devices attached, then for each of these templates, check if your specific device is one of the attached device, then shows detailed information about the template if found.
print("\nGetting Template Information for Device")
print("---------------------------------------")
device_ip = '10.10.1.11'
device_uuid = None
device_model = None
# Get device UUID and model
for device in response['data']:
if device['deviceId'] == device_ip:
device_uuid = device['uuid']
device_model = device.get('device-model', '')
break
if device_uuid:
# First try to get all template associations
template_url = 'https://sandbox-sdwan-2.cisco.com/dataservice/template/device'
template_response = session.get(url=template_url, verify=False)
if template_response.status_code == 200:
try:
template_data = template_response.json()
print(f"\nSearching for attached template for device: {device_ip}")
print(f"Device UUID: {device_uuid}")
print("------------------------------------")
# Look for templates that have this device attached
for template in template_data.get('data', []):
if template.get('devicesAttached', 0) > 0:
# Try to get detailed attachment information for this template
detail_url = f'https://sandbox-sdwan-2.cisco.com/dataservice/template/device/config/attached/{template["templateId"]}'
detail_response = session.get(url=detail_url, verify=False)
if detail_response.status_code == 200:
try:
detail_data = detail_response.json()
# Check if our device UUID is in the attached devices
if any(device_uuid in str(device) for device in detail_data.get('data', [])):
print(f"\nFound attached template:")
print(f"Template Name: {template['templateName']}")
print(f"Template ID: {template['templateId']}")
print(f"Description: {template['templateDescription']}")
print(f"Type: {template['configType']}")
print("------------------------------------")
print("Template Details:")
print(json.dumps(detail_data, indent=2))
break
except json.JSONDecodeError:
continue
except json.JSONDecodeError as e:
print(f"Error decoding JSON: {e}")
else:
print(f"Failed to get template information. Status code: {template_response.status_code}")
else:
print(f"Could not find UUID for device with IP {device_ip}")
Output
Searching for attached template for device: 10.10.1.11
Device UUID: C8K-E2D91A30-814B-F22D-4E7B-7D39BE74EE32
------------------------------------
Found attached template:
Template Name: DC_cEdge_Template
Template ID: a5e2ba39-87a6-4d38-9053-7ca4c781857d
Description: DC_cEdge_Template
Type: template
------------------------------------
Template Details:
{
"header": {
"generatedOn": 1734367400765,
"viewKeys": {
"uniqueKey": [
"uuid"
],
"preferenceKey": "grid-MasterTemplateDevice"
},
"columns": [
{
"title": "Chassis Number",
"property": "uuid",
"hideable": false,
"width": 250,
"dataType": "string"
},
{
"title": "Hostname",
"property": "host-name",
"hideable": false,
"dataType": "string"
},
{
"title": "System IP",
"property": "local-system-ip",
"dataType": "ipv4"
},
{
"title": "Site ID",
"property": "site-id",
"hideable": false,
"dataType": "numberStr"
}
],
"fields": [
{
"property": "uuid",
"dataType": "string"
},
{
"property": "host-name",
"dataType": "string"
},
{
"property": "local-system-ip",
"dataType": "ipv4"
},
{
"property": "site-id",
"dataType": "numberStr"
}
]
},
"data": [
{
"host-name": "dc-cedge01",
"deviceIP": "10.10.1.11",
"local-system-ip": "10.10.1.11",
"site-id": "100",
"device-groups": [
"No groups"
],
"uuid": "C8K-E2D91A30-814B-F22D-4E7B-7D39BE74EE32",
"personality": "vedge",
"configCloudxMode": "none"
}
]
}
12-16-2024 11:42 PM
Hello, @bigevilbeard
I could give you example for better understanding. I have BGP configuration which is attached from 2-3 templates. The output below is cli output:
vEDGE01#sh run | in bgp
redistribute bgp 65666 route-map BGP_TO_OSPF_APN_CHE
router bgp 65666
bgp log-neighbor-changes
bgp router-id 172.18.2.3
distance bgp 20 200 20
snmp-server enable traps bgp
snmp-server enable traps bgp cbgp2
vEDGE01#
The goal is to understand if all 5 line config is from 1 feature template or it's from 2-3 feature template and what is the name of template. If I choose specific part of configuration to give me as result that this configuration is from x, y or z, specific feature templates. In the example above the templates are already attached.
Thank you!
Best regards,
georgi.stoyanov@dundeeprecious.com
+359899543691
12-17-2024 04:29 AM
@georgi-stoyanov which sandbox are you using please, i am looking at SD-WAN 20.10 and see no BGP on the routers here.
12-17-2024 04:47 AM
Hello @bigevilbeard ,
We are using ISR 4351 Cisco. This is connection between Headquarter office and AWS via MPLS, but we plan to decom MPLS because have 2 internet lines. We use Internet to access Sandbox.
12-17-2024 06:15 AM
@georgi-stoyanov ok thanks, i thought you was testing against the devnet sandbox, and trying both i was not to see any devices with the output you mentioned. I think it is possible, but i am unable to validate this, as i do not have the same infra set up as you. This updated script looks at all device feature template for a device (i am using the sandbox here) and looks for any template which has BGP added, you could update this to be more detailed and check for certain lines of configuration, this would be a lot of work if you was looking for lots of lines of cli on a device, but possible if you know your use case well. Sadly with the API you cannot run show commands you as you had below (i dont think anyway).
Hope this helps.
# Check for redistribute BGP
if 'redistribute' in str(config_data).lower() and 'bgp' in str(config_data).lower():
bgp_found = True
print(f"\nFound BGP redistribute configuration in {template_name}")
bgp_configs[f"redistribute bgp configuration"] = template_name
Try this script. I have left out the jsecuirty and token section as this is boiler plate stuff you can add for your own vManage IP etc.. You could update this so it goes over every device, using the systemId of the device, i am just checking one, to make sure the code works and shows information
def find_bgp_template_sources(session, device_ip, base_url='https://10.10.20.90'):
print(f"\nStarting BGP template search for device: {device_ip}")
# Get device UUID from the device list
device_url = f'{base_url}/dataservice/device'
device_response = session.get(url=device_url, verify=False)
if device_response.status_code != 200:
print(f"Failed to get device list. Status code: {device_response.status_code}")
return
device_data = device_response.json()
device_uuid = None
for device in device_data.get('data', []):
if device['deviceId'] == device_ip:
device_uuid = device['uuid']
break
if not device_uuid:
print(f"Device UUID not found for IP: {device_ip}")
return
print(f"Found device UUID: {device_uuid}")
# Get feature templates directly
feature_url = f'{base_url}/dataservice/template/feature?deviceId={device_uuid}'
feature_response = session.get(url=feature_url, verify=False)
if feature_response.status_code != 200:
print(f"Failed to get feature templates. Status code: {feature_response.status_code}")
return
feature_data = feature_response.json()
templates = feature_data.get('data', [])
print(f"Found {len(templates)} feature templates")
for template in templates:
template_id = template.get('templateId')
template_name = template.get('templateName')
template_type = template.get('templateType')
# Get template details
detail_url = f'{base_url}/dataservice/template/feature/object/{template_id}'
detail_response = session.get(url=detail_url, verify=False)
if detail_response.status_code == 200:
try:
detail_data = detail_response.json()
# Check if template contains BGP configuration
if 'bgp' in str(detail_data).lower():
print(f"\nFound BGP configuration in template:")
print(f"Template Name: {template_name}")
print(f"Template Type: {template_type}")
print("BGP Configuration Details:")
print("--------------------------")
def print_bgp_config(data, indent=0):
if isinstance(data, dict):
for key, value in data.items():
if 'bgp' in str(key).lower():
print(f"{' ' * indent}{key}:")
if isinstance(value, (dict, list)):
print_bgp_config(value, indent + 2)
else:
print(f"{' ' * (indent + 2)}{value}")
elif isinstance(value, (dict, list)):
if 'bgp' in str(value).lower():
print(f"{' ' * indent}{key}:")
print_bgp_config(value, indent + 2)
elif isinstance(data, list):
for item in data:
print_bgp_config(item, indent)
# Print the configuration data
if 'configData' in detail_data:
print_bgp_config(detail_data['configData'])
print("--------------------------")
except json.JSONDecodeError as e:
print(f"Error parsing template {template_name}: {str(e)}")
except Exception as e:
print(f"Error processing template {template_name}: {str(e)}")
# Execute the function
print("Starting BGP configuration analysis...")
find_bgp_template_sources(session, '10.10.1.13')
12-17-2024 01:26 AM
You want to see which feature template generates which lines of config/You want to be able to enter a line of configuration and see which feature template has generated it.
English isn't my native language - sorry if I'm not communicating clearly.
The tool you're describing would be very useful, but it doesn't currently exist as far as I know. It is also not easy to implement as the information tying feature templates to final configuration isn't available from the API directly. If you are to try to create this, you will have to apply the feature templates to a test device individually to see which config lines each template creates.
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