Skip to main content

Logical Router

The LogicalRouter class manages logical router objects in Palo Alto Networks' Strata Cloud Manager. It extends from BaseObject and offers methods to create, retrieve, update, list, fetch, and delete logical routers. Logical routers serve as the routing backbone for SCM-managed devices, replacing the legacy Virtual Router for ARE-enabled devices. All routing configuration -- static routes, BGP, OSPF, ECMP, and RIP -- is organized within VRF (Virtual Routing and Forwarding) objects attached to the router. The underlying Pydantic model hierarchy comprises 93 model classes to represent the full depth of the routing configuration.

Class Overview

from scm.client import Scm

# Initialize client
client = Scm(
client_id="your_client_id",
client_secret="your_client_secret",
tsg_id="your_tsg_id"
)

# Access the Logical Router service directly through the client
logical_routers = client.logical_router
MethodDescriptionParametersReturn Type
create()Creates a new logical routerdata: Dict[str, Any]LogicalRouterResponseModel
get()Retrieves a logical router by its unique IDobject_id: strLogicalRouterResponseModel
update()Updates an existing logical routerrouter: LogicalRouterUpdateModelLogicalRouterResponseModel
list()Lists logical routers with optional filteringfolder: Optional[str], snippet: Optional[str], device: Optional[str], exact_match: bool = False, plus additional filtersList[LogicalRouterResponseModel]
fetch()Fetches a single logical router by name within a containername: str, folder: Optional[str], snippet: Optional[str], device: Optional[str]LogicalRouterResponseModel
delete()Deletes a logical router by its IDobject_id: strNone

Logical Router Model Attributes

AttributeTypeRequiredDefaultDescription
namestrYesNoneThe name of the logical router
idUUIDYes*NoneUnique identifier (*response/update only)
routing_stackRoutingStackEnumNoNoneRouting stack type: "legacy" or "advanced"
vrfList[VrfConfig]NoNoneList of VRF configurations
folderstrNo**NoneFolder location. Max 64 chars
snippetstrNo**NoneSnippet location. Max 64 chars
devicestrNo**NoneDevice location. Max 64 chars

* Only required for update and response models ** Exactly one container (folder/snippet/device) must be provided for create operations

VRF Configuration

The vrf attribute contains a list of VRF objects. Each VRF is the central organizing unit for all routing configuration within a logical router.

VrfConfig

AttributeTypeRequiredDescription
namestrYesVRF name
interfaceList[str]NoInterfaces assigned to this VRF
global_vridintNoGlobal VRID
zone_namestrNoZone name
sdwan_typestrNoSD-WAN type
admin_distsAdminDistsNoAdministrative distance settings
vr_admin_distsVrAdminDistsNoVR administrative distance settings
rib_filterRibFilterNoRIB filter configuration (IPv4/IPv6)
routing_tableRoutingTableNoRouting table with static routes
ospfOspfConfigNoOSPF routing protocol configuration
ospfv3Dict[str, Any]NoOSPFv3 routing protocol configuration
ecmpEcmpConfigNoECMP configuration
multicastDict[str, Any]NoMulticast configuration
ripRipConfigNoRIP routing protocol configuration
bgpBgpConfigNoBGP routing protocol configuration

AdminDists

AttributeTypeRequiredDescription
staticintNoStatic route admin distance
static_ipv6intNoStatic IPv6 route admin distance
ospf_interintNoOSPF inter-area admin distance
ospf_intraintNoOSPF intra-area admin distance
ospf_extintNoOSPF external admin distance
ospfv3_interintNoOSPFv3 inter-area admin distance
ospfv3_intraintNoOSPFv3 intra-area admin distance
ospfv3_extintNoOSPFv3 external admin distance
bgp_internalintNoBGP internal admin distance
bgp_externalintNoBGP external admin distance
bgp_localintNoBGP local admin distance
ripintNoRIP admin distance

Static Routes

Static routes live inside a VRF's routing_table attribute, which contains separate ip (IPv4) and ipv6 sections, each holding a list of static route objects.

IPv4StaticRoute

AttributeTypeRequiredDescription
namestrYesStatic route name
destinationstrNoDestination network (CIDR notation)
interfacestrNoEgress interface
nexthopIPv4NexthopNoNexthop configuration (oneOf: ip_address, fqdn, next_lr, next_vr, tunnel, discard, receive)
route_tableIPv4RouteTableNoRoute table selection (unicast, multicast, both, no_install)
admin_distintNoAdministrative distance
metricintNoRoute metric
bfdBfdProfileNoBFD profile reference
path_monitorPathMonitorNoPath monitor configuration

IPv6StaticRoute

AttributeTypeRequiredDescription
namestrYesStatic route name
destinationstrNoDestination network (IPv6 CIDR notation)
interfacestrNoEgress interface
nexthopIPv6NexthopNoNexthop configuration (oneOf: ipv6_address, fqdn, next_lr, next_vr, tunnel, discard, receive)
route_tableIPv6RouteTableNoRoute table selection (unicast, multicast, both, no_install)
admin_distintNoAdministrative distance
metricintNoRoute metric
bfdBfdProfileNoBFD profile reference
path_monitorPathMonitorNoPath monitor configuration

BGP Configuration

The bgp attribute within a VRF provides full BGP routing protocol support including peer groups, redistribution, and policy configuration.

BgpConfig

AttributeTypeRequiredDescription
enableboolNoEnable BGP
router_idstrNoBGP router ID
local_asstrNoLocal AS number
confederation_member_asstrNoConfederation member AS
install_routeboolNoInstall routes into the routing table
enforce_first_asboolNoEnforce first AS in AS path
fast_external_failoverboolNoEnable fast external failover
ecmp_multi_asboolNoECMP multi-AS support
default_local_preferenceintNoDefault local preference value
reject_default_routeboolNoReject default route
allow_redist_default_routeboolNoAllow redistribution of default route
medBgpMedNoMED configuration
graceful_restartBgpGracefulRestartNoGraceful restart configuration
global_bfdBfdProfileNoGlobal BFD profile
peer_groupList[BgpPeerGroup]NoBGP peer groups
aggregate_routesList[BgpAggregateRoute]NoAggregate route entries
redistribution_profileBgpRedistProfileNoRedistribution profile
advertise_networkBgpAdvertiseNetworkNoNetworks to advertise
policyBgpPolicyNoBGP policy configuration
redist_rulesList[BgpRedistRule]NoRedistribution rules

BgpPeerGroup

AttributeTypeRequiredDescription
namestrYesPeer group name
enableboolNoEnable peer group
typeBgpPeerGroupTypeNoPeer group type (ibgp, ebgp, ebgp_confed, ibgp_confed)
address_familyBgpPeerGroupAddressFamilyNoAddress family configuration
filtering_profileBgpPeerGroupFilteringProfileNoFiltering profile configuration
connection_optionsBgpPeerGroupConnectionOptionsNoConnection options
peerList[BgpPeer]NoPeers in this group

OSPF Configuration

The ospf attribute within a VRF provides OSPF routing protocol support with areas, interfaces, authentication, and graceful restart.

OspfConfig

AttributeTypeRequiredDescription
router_idstrNoOSPF router ID
enableboolNoEnable OSPF
rfc1583boolNoRFC 1583 compatibility
reject_default_routeboolNoReject default route
allow_redist_default_routeboolNoAllow redistribution of default route
spf_timerstrNoSPF timer profile
global_if_timerstrNoGlobal interface timer profile
redistribution_profilestrNoRedistribution profile name
global_bfdBfdProfileNoGlobal BFD profile
flood_preventionOspfFloodPreventionNoFlood prevention configuration
vr_timersOspfVrTimersNoVR timer settings
auth_profileList[OspfAuthProfile]NoAuthentication profiles
areaList[OspfArea]NoOSPF areas
export_rulesList[OspfExportRule]NoExport rules
graceful_restartOspfGracefulRestartNoGraceful restart configuration

OspfArea

AttributeTypeRequiredDescription
namestrYesArea ID (e.g., "0.0.0.0" for backbone)
authenticationstrNoAuthentication profile name
typeOspfAreaTypeNoArea type (normal, stub, or nssa)
rangeList[OspfAreaRange]NoArea ranges
vr_rangeList[OspfAreaVrRange]NoVR area ranges
interfaceList[OspfInterface]NoOSPF interfaces in this area
virtual_linkList[OspfVirtualLink]NoOSPF virtual links

ECMP Configuration

The ecmp attribute within a VRF configures Equal-Cost Multi-Path routing with algorithm selection and path limits.

EcmpConfig

AttributeTypeRequiredDescription
enableboolNoEnable ECMP
algorithmEcmpAlgorithmNoECMP algorithm (ip_modulo, ip_hash, weighted_round_robin, balanced_round_robin)
max_pathintNoMaximum number of ECMP paths
symmetric_returnboolNoEnable symmetric return
strict_source_pathboolNoEnable strict source path

EcmpAlgorithm

Only one algorithm can be selected at a time (oneOf):

AttributeTypeDescription
ip_moduloDict[str, Any]IP modulo algorithm (empty object)
ip_hashEcmpIpHashIP hash with src_only, use_port, hash_seed
weighted_round_robinEcmpWeightedRoundRobinWeighted round-robin with interface weights
balanced_round_robinDict[str, Any]Balanced round-robin algorithm (empty object)

Exceptions

ExceptionHTTP CodeDescription
InvalidObjectError400Thrown when provided data or parameters are invalid
MissingQueryParameterError400Thrown when required query parameters (e.g., name or folder) are missing
NameNotUniqueError409Logical router name already exists
ObjectNotPresentError404Logical router not found
ReferenceNotZeroError409Logical router still referenced by other objects
AuthenticationError401Authentication failed
ServerError500Internal server error

Methods

List Logical Routers

# List all logical routers in a folder
routers = client.logical_router.list(
folder="Texas"
)

# Process results
for router in routers:
print(f"Name: {router.name}")
if router.routing_stack:
print(f" Routing Stack: {router.routing_stack.value}")
if router.vrf:
for vrf in router.vrf:
print(f" VRF: {vrf.name}")
if vrf.bgp and vrf.bgp.enable:
print(f" BGP: AS {vrf.bgp.local_as}")
if vrf.ospf and vrf.ospf.enable:
print(f" OSPF: Router ID {vrf.ospf.router_id}")
if vrf.ecmp and vrf.ecmp.enable:
print(f" ECMP: max_path={vrf.ecmp.max_path}")

# List with routing_stack filter
advanced_routers = client.logical_router.list(
folder="Texas",
routing_stack=["advanced"]
)

for router in advanced_routers:
print(f"Advanced router: {router.name}")

Filtering Responses

The list() method supports additional parameters to refine your query results even further. Alongside basic filters, you can leverage the exact_match, exclude_folders, exclude_snippets, and exclude_devices parameters to control which objects are included or excluded after the initial API response is fetched.

Parameters:

  • exact_match (bool): When True, only objects defined exactly in the specified container (folder, snippet, or device) are returned. Inherited or propagated objects are filtered out.
  • exclude_folders (List[str]): Provide a list of folder names that you do not want included in the results.
  • exclude_snippets (List[str]): Provide a list of snippet values to exclude from the results.
  • exclude_devices (List[str]): Provide a list of device values to exclude from the results.

Examples:

# Only return routers defined exactly in 'Texas'
exact_routers = client.logical_router.list(
folder='Texas',
exact_match=True
)

for router in exact_routers:
print(f"Exact match: {router.name} in {router.folder}")

# Exclude all routers from the 'All' folder
no_all_routers = client.logical_router.list(
folder='Texas',
exclude_folders=['All']
)

for router in no_all_routers:
assert router.folder != 'All'
print(f"Filtered out 'All': {router.name}")

Controlling Pagination with max_limit

The SDK supports pagination through the max_limit parameter, which defines how many objects are retrieved per API call. By default, max_limit is set to 2500. The API itself imposes a maximum allowed value of 5000. If you set max_limit higher than 5000, it will be capped to the API's maximum. The list() method will continue to iterate through all objects until all results have been retrieved. Adjusting max_limit can help manage retrieval performance and memory usage when working with large datasets.

Example:

from scm.client import Scm

# Initialize client
client = Scm(
client_id="your_client_id",
client_secret="your_client_secret",
tsg_id="your_tsg_id"
)

# Configure max_limit using the property setter
client.logical_router.max_limit = 4000

# List all routers - auto-paginates through results
all_routers = client.logical_router.list(folder='Texas')

Fetch a Logical Router

# Fetch by name and folder
router = client.logical_router.fetch(
name="branch-router-01",
folder="Texas"
)
print(f"Found router: {router.name}")
print(f" Routing stack: {router.routing_stack}")
if router.vrf:
for vrf in router.vrf:
print(f" VRF: {vrf.name}")
if vrf.interface:
print(f" Interfaces: {', '.join(vrf.interface)}")

# Get by ID
router_by_id = client.logical_router.get(router.id)
print(f"Retrieved router: {router_by_id.name}")

Create a Logical Router

from scm.client import Scm

# Initialize client
client = Scm(
client_id="your_client_id",
client_secret="your_client_secret",
tsg_id="your_tsg_id"
)

# Create a basic logical router with a VRF and static routes
router_data = {
"name": "branch-router-01",
"routing_stack": "advanced",
"vrf": [
{
"name": "vrf-production",
"interface": ["ethernet1/1", "ethernet1/2"],
"routing_table": {
"ip": {
"static_route": [
{
"name": "default-route",
"destination": "0.0.0.0/0",
"nexthop": {
"ip_address": "10.0.0.1"
},
"metric": 10
},
{
"name": "internal-subnet",
"destination": "192.168.0.0/16",
"nexthop": {
"ip_address": "10.0.0.2"
},
"admin_dist": 15
}
]
}
}
}
],
"folder": "Texas"
}

new_router = client.logical_router.create(router_data)
print(f"Created logical router with ID: {new_router.id}")

# Create a logical router with BGP configuration
bgp_router_data = {
"name": "core-router-01",
"routing_stack": "advanced",
"vrf": [
{
"name": "vrf-transit",
"interface": ["ethernet1/3", "ethernet1/4"],
"bgp": {
"enable": True,
"router_id": "10.255.0.1",
"local_as": "65001",
"peer_group": [
{
"name": "upstream-peers",
"enable": True,
"type": {
"ebgp": {}
},
"peer": [
{
"name": "isp-peer-1",
"enable": True,
"peer_as": "64512",
"peer_address": {
"ip": "203.0.113.1"
},
"local_address": {
"interface": "ethernet1/3",
"ip": "203.0.113.2"
}
}
]
}
]
}
}
],
"folder": "Texas"
}

bgp_router = client.logical_router.create(bgp_router_data)
print(f"Created BGP router with ID: {bgp_router.id}")

# Create a logical router with OSPF configuration
ospf_router_data = {
"name": "campus-router-01",
"routing_stack": "advanced",
"vrf": [
{
"name": "vrf-campus",
"interface": ["ethernet1/1", "ethernet1/2"],
"ospf": {
"enable": True,
"router_id": "10.255.0.2",
"area": [
{
"name": "0.0.0.0",
"type": {
"normal": {}
},
"interface": [
{
"name": "ethernet1/1",
"enable": True,
"metric": 10,
"link_type": {
"broadcast": {}
}
},
{
"name": "ethernet1/2",
"enable": True,
"passive": True
}
]
}
],
"graceful_restart": {
"enable": True,
"grace_period": 120
}
}
}
],
"folder": "Texas"
}

ospf_router = client.logical_router.create(ospf_router_data)
print(f"Created OSPF router with ID: {ospf_router.id}")

Update a Logical Router

# Fetch existing router
existing_router = client.logical_router.fetch(
name="branch-router-01",
folder="Texas"
)

# Add ECMP configuration to the first VRF
if existing_router.vrf:
existing_router.vrf[0].ecmp = {
"enable": True,
"algorithm": {
"ip_hash": {
"src_only": False,
"use_port": True,
"hash_seed": 42
}
},
"max_path": 4,
"symmetric_return": True
}

# Perform update
updated_router = client.logical_router.update(existing_router)
print(f"Updated router: {updated_router.name}")

# Update a router to add a BGP peer group
router_with_bgp = client.logical_router.fetch(
name="core-router-01",
folder="Texas"
)

# Add a second peer to the existing peer group
if router_with_bgp.vrf and router_with_bgp.vrf[0].bgp:
bgp = router_with_bgp.vrf[0].bgp
if bgp.peer_group:
bgp.peer_group[0].peer.append({
"name": "isp-peer-2",
"enable": True,
"peer_as": "64513",
"peer_address": {
"ip": "198.51.100.1"
},
"local_address": {
"interface": "ethernet1/4",
"ip": "198.51.100.2"
}
})

updated_bgp_router = client.logical_router.update(router_with_bgp)
print(f"Updated BGP router with additional peer")

# Add OSPF stub area to a router
router_with_ospf = client.logical_router.fetch(
name="campus-router-01",
folder="Texas"
)

if router_with_ospf.vrf and router_with_ospf.vrf[0].ospf:
router_with_ospf.vrf[0].ospf.area.append({
"name": "0.0.0.1",
"type": {
"stub": {
"accept_summary": True,
"default_route": {
"advertise": {}
}
}
},
"interface": [
{
"name": "ethernet1/5",
"enable": True,
"metric": 20
}
]
})

updated_ospf_router = client.logical_router.update(router_with_ospf)
print(f"Updated OSPF router with stub area")

Delete a Logical Router

# Delete by ID
router_id = "123e4567-e89b-12d3-a456-426655440000"
client.logical_router.delete(router_id)

Use Cases

Performing Commits

# Prepare commit parameters
commit_params = {
"folders": ["Texas"],
"description": "Updated logical router configurations",
"sync": True,
"timeout": 300 # 5 minute timeout
}

# Commit the changes directly on the client
result = client.commit(**commit_params)

print(f"Commit job ID: {result.job_id}")

Monitoring Jobs

# Get status of specific job directly from the client
job_status = client.get_job_status(result.job_id)
print(f"Job status: {job_status.data[0].status_str}")

# List recent jobs directly from the client
recent_jobs = client.list_jobs(limit=10)
for job in recent_jobs.data:
print(f"Job {job.id}: {job.type_str} - {job.status_str}")

Error Handling

from scm.client import Scm
from scm.exceptions import (
InvalidObjectError,
MissingQueryParameterError,
NameNotUniqueError,
ObjectNotPresentError,
ReferenceNotZeroError
)

# Initialize client
client = Scm(
client_id="your_client_id",
client_secret="your_client_secret",
tsg_id="your_tsg_id"
)

try:
# Create logical router configuration
router_config = {
"name": "test-router",
"routing_stack": "advanced",
"vrf": [
{
"name": "vrf-default",
"interface": ["ethernet1/1"],
"routing_table": {
"ip": {
"static_route": [
{
"name": "default-route",
"destination": "0.0.0.0/0",
"nexthop": {
"ip_address": "10.0.0.1"
},
"metric": 10
}
]
}
}
}
],
"folder": "Texas"
}

# Create the router using the unified client interface
new_router = client.logical_router.create(router_config)

# Commit changes directly from the client
result = client.commit(
folders=["Texas"],
description="Added test logical router",
sync=True
)

# Check job status directly from the client
status = client.get_job_status(result.job_id)

except InvalidObjectError as e:
print(f"Invalid router data: {e.message}")
except NameNotUniqueError as e:
print(f"Router name already exists: {e.message}")
except ObjectNotPresentError as e:
print(f"Router not found: {e.message}")
except ReferenceNotZeroError as e:
print(f"Router still in use: {e.message}")
except MissingQueryParameterError as e:
print(f"Missing parameter: {e.message}")