07 Project Template Examples - fortinet-solutions-cse/sdwan-advpn-reference GitHub Wiki

Overview

Preparing your Project Template is the first and the most crucial step to use our Jinja Templates. As you have probably seen, under each design flavor directory there are examples of the Project Templates (see under projects/Project.*.j2). Some of them are simple, but others are used to render a quite complex dual-region deployment. There are also some examples of the inventory files, corresponding to the example Project Templates.

This section steps back a little bit and provides a few simpler examples of the Project Templates, step-by-step, probably much better for your first deployments.

You can start by trying to render these examples, using your own inventory files and our Python renderer. Do not forget to specify explicitly the Project Template and the inventory file to use:

% ./render_config.py -f bgp-on-loopback -p <project_template> -i <inventory_file>

All the examples below are done for release/7.2, so make sure you are playing with the right branch!

Single-Hub Region

Let's start with the most basic example, a very simple Single-Region Single-Hub project:

  • The Hub is "site1-H1"
  • All SD-WAN sites (Hub and Edges) have a single WAN interface (port1), receiving its IP from DHCP
  • All SD-WAN sites (Hub and Edges) have a single LAN interface (port5), with its IP set by a per-device lan_ip variable

Project.j2:

{# Optional Settings #}
{% set cert_auth = false %}

{#  Mandatory Global Definitions #}
{% set lo_summary = '10.200.0.0/14' %}
{% set lan_summary = '10.0.0.0/8' %}

{# Regions #}
{% set regions = {
    'SuperWAN': {
      'as': '65001',
      'hubs': [ 'site1-H1' ]
    }
  }
%}

{# Device Profiles #}
{% set profiles = {

    'SingleISP': {
      'interfaces': [
        {
          'name': 'port1',
          'role': 'wan',
          'ol_type': 'ISP1',
          'ip': 'dhcp',
          'dia': true
        },
        {
          'name': 'port5',
          'role': 'lan',
          'ip': lan_ip
        }
      ]
    } 

  }
%}

{# Hubs #}
{% set hubs = {

    'site1-H1': {
      'lo_bgp': '10.200.1.253',
      'overlays': {
        'ISP1': {
          'wan_ip': '100.64.1.1',
          'network_id': '11'
        },
        'ISP2': {
          'wan_ip': '100.64.1.9',
          'network_id': '12'
        }
      }
    }

  }
%}

You need an inventory file to test the rendering, so here it comes (we use the JSON format, but note that we now also support CSV inventories - check the README in the release/7.2 branch!).

inventory.json:

{
  "Hub": {

    "site1-H1": {
      "hostname": "site1-H1",
      "loopback": "10.200.1.253",
      "profile": "SingleISP",
      "region": "SuperWAN",
      "lan_ip": "10.1.0.1/24"
    }

  },

  "Edge": {

    "site1-1": {
      "hostname": "site1-1",
      "loopback": "10.200.1.1",
      "profile": "SingleISP",
      "region": "SuperWAN",
      "lan_ip": "10.0.1.1/24"
    },

    "site1-2": {
      "hostname": "site1-2",
      "loopback": "10.200.1.2",
      "profile": "SingleISP",
      "region": "SuperWAN",
      "lan_ip": "10.0.2.1/24"
    }

  }
}

Dual-Hub Region

The following example describes a very typical Single-Region Dual-Hub project:

  • The Hubs are "site1-H1" and "site1-H2"
  • All SD-WAN sites (both Hubs and Edges) have two WAN interfaces (port1, port2), both receiving their IP from DHCP
  • All SD-WAN sites (both Hubs and Edges) have a single LAN interface (port5), with its IP set by a per-device lan_ip variable

Project.j2:

{# Optional Settings #}
{% set cert_auth = false %}

{#  Mandatory Global Definitions #}
{% set lo_summary = '10.200.0.0/14' %}
{% set lan_summary = '10.0.0.0/8' %}

{# Regions #}
{% set regions = {
    'SuperWAN': {
      'as': '65001',
      'hubs': [ 'site1-H1', 'site1-H2' ]
    }
  }
%}

{# Device Profiles #}
{% set profiles = {

    'DualISP': {
      'interfaces': [
        {
          'name': 'port1',
          'role': 'wan',
          'ol_type': 'ISP1',
          'ip': 'dhcp',
          'dia': true
        },
        {
          'name': 'port2',
          'role': 'wan',
          'ol_type': 'ISP2',
          'ip': 'dhcp',
          'dia': true
        },
        {
          'name': 'port5',
          'role': 'lan',
          'ip': lan_ip
        }
      ]
    } 

  }
%}

{# Hubs #}
{% set hubs = {

    'site1-H1': {
      'lo_bgp': '10.200.1.253',
      'overlays': {
        'ISP1': {
          'wan_ip': '100.64.1.1',
          'network_id': '11'
        },
        'ISP2': {
          'wan_ip': '100.64.1.9',
          'network_id': '12'
        }
      }
    },

    'site1-H2': {
      'lo_bgp': '10.200.1.254',      
      'overlays': {
        'ISP1': {
          'wan_ip': '100.64.2.1',
          'network_id': '21'
        },
        'ISP2': {
          'wan_ip': '100.64.2.9',
          'network_id': '22'
        }
      }
    }

  }
%}

inventory.json:

{
  "Hub": {

    "site1-H1": {
      "hostname": "site1-H1",
      "loopback": "10.200.1.253",
      "profile": "DualISP",
      "region": "SuperWAN",
      "lan_ip": "10.1.0.1/24"
    },

    "site1-H2": {
      "hostname": "site1-H2",
      "loopback": "10.200.1.254",
      "profile": "DualISP",
      "region": "SuperWAN",
      "lan_ip": "10.2.0.1/24"
    }    

  },

  "Edge": {

    "site1-1": {
      "hostname": "site1-1",
      "loopback": "10.200.1.1",
      "profile": "DualISP",
      "region": "SuperWAN",
      "lan_ip": "10.0.1.1/24"
    },

    "site1-2": {
      "hostname": "site1-2",
      "loopback": "10.200.1.2",
      "profile": "DualISP",
      "region": "SuperWAN",
      "lan_ip": "10.0.2.1/24"
    }

  }
}

Generic Profiles

In the above examples, the interface names are written directly in the profile. For example:

{# Device Profiles #}
{% set profiles = {

    'SingleISP': {
      'interfaces': [
        {
          'name': 'port1',
          'role': 'wan',
          'ol_type': 'ISP1',
          'ip': 'dhcp',
          'dia': true
        },
        {
          'name': 'port5',
          'role': 'lan',
          'ip': lan_ip
        }
      ]
    } 

  }
%}

This makes the profile hardware-dependent, because different hardware models may have different interface names. In fact, the previous examples are prepared for a FortiGate-VM, hence the interface names (port1, port2 etc.).

Luckily, it is easy to make your profiles hardware-independent, simply using per-device variables instead of explicit interface names:

{# Device Profiles #}
{% set profiles = {

    'SingleISP': {
      'interfaces': [
        {
          'name': inet_interface,
          'role': 'wan',
          'ol_type': 'ISP1',
          'ip': 'dhcp',
          'dia': true
        },
        {
          'name': lan_interface,
          'role': 'lan',
          'ip': lan_ip
        }
      ]
    } 

  }
%}

Now you will have to set the values of the variables inet_interface and lan_interface for each device (just like you set the value of lan_ip to specify the LAN IP).

Another interesting feature is that the Jinja Templates will automatically skip any interfaces without a name. Consider the following profile:

{# Device Profiles #}
{% set profiles = {

    'GenericMultiISP': {
      'interfaces': [
        {
          'name': inet1_interface,
          'role': 'wan',
          'ol_type': 'ISP1',
          'ip': 'dhcp',
          'dia': true
        },
        {
          'name': inet2_interface,
          'role': 'wan',
          'ol_type': 'ISP2',
          'ip': 'dhcp',
          'dia': true
        },
        {
          'name': lan_interface,
          'role': 'lan',
          'ip': lan_ip
        }
      ]
    } 

  }
%}

Here we introduce two variables - inet1_interface and inet2_interface - to support sites with two Internet links. But what is interesting is that sites with just a single Internet link can still use this same profile! They simply won't set the value of the inet2_interface variable. The Jinja Template will find an interface without a name, hence simply skipping it.

You could have the following in your inventory.json:

{
  "Edge": {

    "dualISP-site": {
      "hostname": "site1-1",
      "loopback": "10.200.1.1",
      "profile": "GenericMultiISP",
      "region": "SuperWAN",
      "inet1_interface": "port1",
      "inet2_interface": "port2",
      "lan_interface": "port5",
      "lan_ip": "10.0.1.1/24"
    },

    "singleISP-site": {
      "hostname": "site1-2",
      "loopback": "10.200.1.2",
      "profile": "GenericMultiISP",
      "region": "SuperWAN",
      "inet1_interface": "port1",
      "lan_interface": "port5",
      "lan_ip": "10.0.1.1/24"
    },
  }
}

This is how you can make your profiles generic. A single profile can now handle not only differnet hardware models, but also different connectivity options!

SD-Branch Profiles

The Jinja Templates include basic support of SD-Branch deployments. Here is an example of a profile:

{# Device Profiles #}
{% set profiles = {

    'SDB-SingleISP': {
      'interfaces': [
        {
          'name': 'port1',
          'role': 'wan',
          'ol_type': 'ISP1',
          'ip': 'dhcp',
          'dia': true
        },
        {
          'name': 'port8',
          'role': 'sd_branch'
        },
        {
          'name': 'vl_users',
          'role': 'lan',
          'ip': lan_ip,
          'vlanid': 10,
          'parent': 'fortilink'
        }
      ]
    }

  }
%}

Here, port8 is connected to a FortiSwitch device. It will be added as a member to the "fortilink" interface, due to the special sd_branch role set in the profile.

We also show how to define a VLAN `vl_users" on the FortiSwitch (note the parent interface set to the "fortilink" interface, inline with the expected FOS configuration).