cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
681
Views
3
Helpful
10
Replies

API access to SD WAN routers

georgi-stoyanov
Level 1
Level 1

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

10 Replies 10

Torbjørn
VIP
VIP

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. 

Happy to help! Please mark as helpful/solution if applicable.
Get in touch: https://torbjorn.dev

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

 

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.

Happy to help! Please mark as helpful/solution if applicable.
Get in touch: https://torbjorn.dev

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

@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"
    }
  ]
}

 

Please mark this as helpful or solution accepted to help others
Connect with me https://bigevilbeard.github.io

Hello, @bigevilbeard 

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

 

@georgi-stoyanov which sandbox are you using please, i am looking at SD-WAN 20.10 and see no BGP on the routers here.

Please mark this as helpful or solution accepted to help others
Connect with me https://bigevilbeard.github.io

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.

@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')

 

Please mark this as helpful or solution accepted to help others
Connect with me https://bigevilbeard.github.io

Torbjørn
VIP
VIP

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.

Happy to help! Please mark as helpful/solution if applicable.
Get in touch: https://torbjorn.dev