Skip to content

BGP Routing Models

Overview

The BGP Routing models provide a structured way to manage BGP (Border Gateway Protocol) routing configurations in Palo Alto Networks' Strata Cloud Manager. These models define the structure, validation rules, and behavior for BGP routing settings, which control global routing preferences and behaviors for Service Connections.

BGP routing in Strata Cloud Manager is implemented as a singleton object, meaning there is only one global BGP routing configuration per tenant. The models handle validation of inputs and outputs when interacting with the SCM API.

Attributes

Attribute Type Required Default Description
routing_preference Union[DefaultRoutingModel, HotPotatoRoutingModel] Yes* None The routing preference setting (default or hot potato)
backbone_routing BackboneRoutingEnum Yes* None Controls asymmetric routing options
accept_route_over_SC bool Yes* False Whether to accept routes over service connections
outbound_routes_for_services List[str] Yes* [] List of outbound routes for services in CIDR format
add_host_route_to_ike_peer bool Yes* False Whether to add host route to IKE peer
withdraw_static_route bool Yes* False Whether to withdraw static routes

* Required for CreateModel, optional for UpdateModel, required for ResponseModel

Enums and Sub-Models

BackboneRoutingEnum

The BackboneRoutingEnum defines the possible backbone routing options:

Value Description
NO_ASYMMETRIC_ROUTING No asymmetric routing allowed
ASYMMETRIC_ROUTING_ONLY Only asymmetric routing allowed
ASYMMETRIC_ROUTING_WITH_LOAD_SHARE Asymmetric routing with load sharing enabled

DefaultRoutingModel

Model for default routing preference configuration:

class DefaultRoutingModel(BaseModel):
    default: Dict[str, Any] = Field(
        default_factory=dict,
        description="Default routing configuration",
    )

HotPotatoRoutingModel

Model for hot potato routing preference configuration:

class HotPotatoRoutingModel(BaseModel):
    hot_potato_routing: Dict[str, Any] = Field(
        default_factory=dict,
        description="Hot potato routing configuration",
    )

Exceptions

The BGP Routing models can raise the following exceptions during validation:

  • ValueError: Raised in several scenarios:
  • When routing_preference is not a valid type
  • When no fields are specified for an update
  • When outbound_routes_for_services contains invalid entries
  • When backbone_routing is not a valid enum value

Model Validators

Routing Preference Type Validation

The models enforce that routing_preference must be either DefaultRoutingModel or HotPotatoRoutingModel:

# This will raise a validation error
from scm.models.deployment import BGPRoutingCreateModel

# Error: invalid routing_preference type
try:
    routing_config = BGPRoutingCreateModel(
        routing_preference="invalid-type",  # Not a valid routing preference type
        backbone_routing="no-asymmetric-routing",
        accept_route_over_SC=False
    )
except ValueError as e:
    print(e)  # "routing_preference must be either DefaultRoutingModel or HotPotatoRoutingModel"

Update Model Validation

For update operations, at least one field must be specified:

# This will raise a validation error
from scm.models.deployment import BGPRoutingUpdateModel

# Error: no fields specified for update
try:
    update_config = BGPRoutingUpdateModel()
except ValueError as e:
    print(e)  # "At least one field must be specified for update"

Outbound Routes Validation

The outbound_routes_for_services field is validated to ensure proper formatting:

# This will handle various input formats
from scm.models.deployment import BGPRoutingCreateModel
from scm.models.deployment import BackboneRoutingEnum

# Convert single string to list
config1 = BGPRoutingCreateModel(
    routing_preference={"default": {}},
    backbone_routing=BackboneRoutingEnum.NO_ASYMMETRIC_ROUTING,
    outbound_routes_for_services="192.168.0.0/24"  # Will be converted to ["192.168.0.0/24"]
)
print(config1.outbound_routes_for_services)  # ["192.168.0.0/24"]

# Handle empty list
config2 = BGPRoutingCreateModel(
    routing_preference={"default": {}},
    backbone_routing=BackboneRoutingEnum.NO_ASYMMETRIC_ROUTING,
    outbound_routes_for_services=[]  # Empty list is allowed
)
print(config2.outbound_routes_for_services)  # []

# Error: invalid type
try:
    config3 = BGPRoutingCreateModel(
        routing_preference={"default": {}},
        backbone_routing=BackboneRoutingEnum.NO_ASYMMETRIC_ROUTING,
        outbound_routes_for_services=123  # Not a list or string
    )
except ValueError as e:
    print(e)  # "outbound_routes_for_services must be a list of strings"

Usage Examples

Creating BGP Routing Configuration

# Using dictionary approach
from scm.client import ScmClient
from scm.models.deployment import BackboneRoutingEnum

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

# Create with direct dictionary (automatically converted to models)
bgp_config = {
    "routing_preference": {"default": {}},
    "backbone_routing": BackboneRoutingEnum.NO_ASYMMETRIC_ROUTING,
    "accept_route_over_SC": False,
    "outbound_routes_for_services": ["10.0.0.0/8", "172.16.0.0/12"],
    "add_host_route_to_ike_peer": False,
    "withdraw_static_route": False
}

result = client.bgp_routing.create(bgp_config)

# Using Pydantic models directly
from scm.models.deployment import (
    BGPRoutingCreateModel,
    DefaultRoutingModel,
    HotPotatoRoutingModel
)

# Create with Pydantic model (explicit instantiation)
bgp_model = BGPRoutingCreateModel(
    routing_preference=DefaultRoutingModel(),
    backbone_routing=BackboneRoutingEnum.NO_ASYMMETRIC_ROUTING,
    accept_route_over_SC=False,
    outbound_routes_for_services=["10.0.0.0/8"],
    add_host_route_to_ike_peer=False,
    withdraw_static_route=False
)

# Convert to dictionary for API call
model_dict = bgp_model.model_dump(exclude_unset=True)
result = client.bgp_routing.create(model_dict)

Creating with Hot Potato Routing

# Using Hot Potato routing preference
from scm.models.deployment import (
    BGPRoutingCreateModel,
    HotPotatoRoutingModel,
    BackboneRoutingEnum
)

# Create with Hot Potato routing
hot_potato_model = BGPRoutingCreateModel(
    routing_preference=HotPotatoRoutingModel(),
    backbone_routing=BackboneRoutingEnum.ASYMMETRIC_ROUTING_WITH_LOAD_SHARE,
    accept_route_over_SC=True,
    outbound_routes_for_services=["192.168.0.0/16", "10.0.0.0/8"],
    add_host_route_to_ike_peer=True,
    withdraw_static_route=False
)

payload = hot_potato_model.model_dump(exclude_unset=True)
result = client.bgp_routing.create(payload)

Updating BGP Routing Configuration

# Partial updates with only specified fields
from scm.models.deployment import BGPRoutingUpdateModel, BackboneRoutingEnum

# Update only specific fields
update_model = BGPRoutingUpdateModel(
    backbone_routing=BackboneRoutingEnum.ASYMMETRIC_ROUTING_ONLY,
    accept_route_over_SC=True
)

# Convert to dictionary, excluding unset fields
payload = update_model.model_dump(exclude_unset=True)
result = client.bgp_routing.update(payload)

# Dictionary approach for partial update
partial_update = {
    "outbound_routes_for_services": ["172.16.0.0/12", "192.168.0.0/16"],
    "add_host_route_to_ike_peer": True
}

result = client.bgp_routing.update(partial_update)

Handling Response Models

# Working with response models
from scm.client import ScmClient

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

# Get current BGP routing configuration
response = client.bgp_routing.get()

# Determine routing preference type
if hasattr(response.routing_preference, "default"):
    print("Using Default routing")
elif hasattr(response.routing_preference, "hot_potato_routing"):
    print("Using Hot Potato routing")

# Check backbone routing configuration
if response.backbone_routing == "no-asymmetric-routing":
    print("No asymmetric routing allowed")
elif response.backbone_routing == "asymmetric-routing-only":
    print("Only asymmetric routing allowed")
elif response.backbone_routing == "asymmetric-routing-with-load-share":
    print("Asymmetric routing with load sharing enabled")

# Check if accepting routes over Service Connections
if response.accept_route_over_SC:
    print("Accepting routes over Service Connections")
else:
    print("Not accepting routes over Service Connections")

# Display outbound routes
if response.outbound_routes_for_services:
    print("Outbound routes:")
    for route in response.outbound_routes_for_services:
        print(f"  - {route}")
else:
    print("No outbound routes configured")

# Check other settings
print(f"Add host route to IKE peer: {response.add_host_route_to_ike_peer}")
print(f"Withdraw static route: {response.withdraw_static_route}")

Field Serialization

The BGP Routing models include a custom serializer for the routing_preference field to ensure it's properly serialized for API requests:

@field_serializer('routing_preference')
def serialize_routing_preference(self, value: Optional[Union[DefaultRoutingModel, HotPotatoRoutingModel]]) -> Optional[Dict[str, Any]]:
    """Serialize routing_preference to correct format for API requests."""
    if value is None:
        return None

    if isinstance(value, DefaultRoutingModel):
        return {"default": {}}
    elif isinstance(value, HotPotatoRoutingModel):
        return {"hot_potato_routing": {}}

    return None

This serializer ensures that the models are correctly converted to the format expected by the API, regardless of how they were created or modified in your code.