Skip to content
This repository has been archived by the owner on Nov 21, 2024. It is now read-only.

Commit

Permalink
Merge pull request #636 from cisco-open/dev/wan/interface/t1e1serial
Browse files Browse the repository at this point in the history
Config converter: Transport and Management feature profile, parcels and interfaces
  • Loading branch information
jpkrajewski authored May 8, 2024
2 parents 37b9888 + 42b282b commit 9f8d419
Show file tree
Hide file tree
Showing 28 changed files with 1,499 additions and 161 deletions.
9 changes: 8 additions & 1 deletion catalystwan/api/builders/feature_profiles/builder_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,25 @@
from catalystwan.api.builders.feature_profiles.other import OtherFeatureProfileBuilder
from catalystwan.api.builders.feature_profiles.service import ServiceFeatureProfileBuilder
from catalystwan.api.builders.feature_profiles.system import SystemFeatureProfileBuilder
from catalystwan.api.builders.feature_profiles.transport import TransportAndManagementProfileBuilder
from catalystwan.exceptions import CatalystwanException
from catalystwan.models.configuration.feature_profile.common import ProfileType

if TYPE_CHECKING:
from catalystwan.session import ManagerSession

FeatureProfileBuilder = Union[ServiceFeatureProfileBuilder, SystemFeatureProfileBuilder, OtherFeatureProfileBuilder]
FeatureProfileBuilder = Union[
ServiceFeatureProfileBuilder,
SystemFeatureProfileBuilder,
OtherFeatureProfileBuilder,
TransportAndManagementProfileBuilder,
]

BUILDER_MAPPING: Mapping[ProfileType, Callable] = {
"service": ServiceFeatureProfileBuilder,
"system": SystemFeatureProfileBuilder,
"other": OtherFeatureProfileBuilder,
"transport": TransportAndManagementProfileBuilder,
}


Expand Down
14 changes: 10 additions & 4 deletions catalystwan/api/builders/feature_profiles/other.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
from __future__ import annotations

import logging
from typing import TYPE_CHECKING, List
from uuid import UUID

from catalystwan.api.feature_profile_api import OtherFeatureProfileAPI
from catalystwan.endpoints.configuration.feature_profile.sdwan.other import OtherFeatureProfile
from catalystwan.exceptions import ManagerHTTPError
from catalystwan.models.configuration.feature_profile.common import FeatureProfileCreationPayload
from catalystwan.models.configuration.feature_profile.sdwan.other import AnyOtherParcel

logger = logging.getLogger(__name__)

if TYPE_CHECKING:
from catalystwan.session import ManagerSession

Expand Down Expand Up @@ -62,8 +66,10 @@ def build(self) -> UUID:
Returns:
UUID: The UUID of the created feature profile.
"""

profile_uuid = self._endpoints.create_sdwan_other_feature_profile(self._profile).id
for parcel in self._independent_items:
self._api.create_parcel(profile_uuid, parcel)
try:
profile_uuid = self._endpoints.create_sdwan_other_feature_profile(self._profile).id
for parcel in self._independent_items:
self._api.create_parcel(profile_uuid, parcel)
except ManagerHTTPError as e:
logger.error(f"Error occured during building profile: {e.info}")
return profile_uuid
23 changes: 13 additions & 10 deletions catalystwan/api/builders/feature_profiles/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

from catalystwan.api.feature_profile_api import ServiceFeatureProfileAPI
from catalystwan.endpoints.configuration.feature_profile.sdwan.service import ServiceFeatureProfile
from catalystwan.exceptions import ManagerHTTPError
from catalystwan.models.configuration.feature_profile.common import FeatureProfileCreationPayload
from catalystwan.models.configuration.feature_profile.sdwan.service import (
AppqoeParcel,
Expand Down Expand Up @@ -117,15 +118,17 @@ def build(self) -> UUID:
Service feature profile UUID
"""
profile_uuid = self._endpoints.create_sdwan_service_feature_profile(self._profile).id

for parcel in self._independent_items:
self._api.create_parcel(profile_uuid, parcel)

for vpn_tag, vpn_parcel in self._independent_items_vpns.items():
vpn_uuid = self._api.create_parcel(profile_uuid, vpn_parcel).id

for sub_parcel in self._depended_items_on_vpns[vpn_tag]:
logger.debug(f"Creating subparcel parcel {sub_parcel.parcel_name} to VPN {vpn_uuid}")
self._api.create_parcel(profile_uuid, sub_parcel, vpn_uuid)
try:
for parcel in self._independent_items:
self._api.create_parcel(profile_uuid, parcel)

for vpn_tag, vpn_parcel in self._independent_items_vpns.items():
vpn_uuid = self._api.create_parcel(profile_uuid, vpn_parcel).id

for sub_parcel in self._depended_items_on_vpns[vpn_tag]:
logger.debug(f"Creating subparcel parcel {sub_parcel.parcel_name} to VPN {vpn_uuid}")
self._api.create_parcel(profile_uuid, sub_parcel, vpn_uuid)
except ManagerHTTPError as e:
logger.error(f"Error occured during building profile: {e.info}")

return profile_uuid
12 changes: 10 additions & 2 deletions catalystwan/api/builders/feature_profiles/system.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
# Copyright 2023 Cisco Systems, Inc. and its affiliates
from __future__ import annotations

import logging
from typing import TYPE_CHECKING, List
from uuid import UUID

from catalystwan.api.feature_profile_api import SystemFeatureProfileAPI
from catalystwan.endpoints.configuration.feature_profile.sdwan.system import SystemFeatureProfile
from catalystwan.exceptions import ManagerHTTPError
from catalystwan.models.configuration.feature_profile.common import FeatureProfileCreationPayload
from catalystwan.models.configuration.feature_profile.sdwan.system import AnySystemParcel

logger = logging.getLogger(__name__)

if TYPE_CHECKING:
from catalystwan.session import ManagerSession

Expand Down Expand Up @@ -64,6 +69,9 @@ def build(self) -> UUID:
"""

profile_uuid = self._endpoints.create_sdwan_system_feature_profile(self._profile).id
for parcel in self._independent_items:
self._api.create_parcel(profile_uuid, parcel)
try:
for parcel in self._independent_items:
self._api.create_parcel(profile_uuid, parcel)
except ManagerHTTPError as e:
logger.error(f"Error occured during building profile: {e.info}")
return profile_uuid
116 changes: 116 additions & 0 deletions catalystwan/api/builders/feature_profiles/transport.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
# Copyright 2023 Cisco Systems, Inc. and its affiliates
from __future__ import annotations

import logging
from collections import defaultdict
from typing import TYPE_CHECKING, Dict, List
from uuid import UUID, uuid4

from catalystwan.api.feature_profile_api import TransportFeatureProfileAPI
from catalystwan.endpoints.configuration.feature_profile.sdwan.transport import TransportFeatureProfile
from catalystwan.exceptions import ManagerHTTPError
from catalystwan.models.configuration.feature_profile.common import FeatureProfileCreationPayload
from catalystwan.models.configuration.feature_profile.sdwan.transport import (
AnyTransportSuperParcel,
AnyTransportVpnParcel,
AnyTransportVpnSubParcel,
)

logger = logging.getLogger(__name__)

if TYPE_CHECKING:
from catalystwan.session import ManagerSession


class TransportAndManagementProfileBuilder:
"""
A class for building system feature profiles.
"""

def __init__(self, session: ManagerSession) -> None:
"""
Initialize a new instance of the Service class.
Args:
session (ManagerSession): The ManagerSession object used for API communication.
profile_uuid (UUID): The UUID of the profile.
"""
self._profile: FeatureProfileCreationPayload
self._api = TransportFeatureProfileAPI(session)
self._endpoints = TransportFeatureProfile(session)
self._independent_items: List[AnyTransportSuperParcel] = []
self._independent_items_vpns: Dict[UUID, AnyTransportVpnParcel] = {}
self._dependent_items_on_vpns: Dict[UUID, List[AnyTransportVpnSubParcel]] = defaultdict(list)

def add_profile_name_and_description(self, feature_profile: FeatureProfileCreationPayload) -> None:
"""
Adds a name and description to the feature profile.
Args:
name (str): The name of the feature profile.
description (str): The description of the feature profile.
Returns:
None
"""
self._profile = feature_profile

def add_parcel(self, parcel: AnyTransportSuperParcel) -> None:
"""
Adds a parcel to the feature profile.
Args:
parcel (AnyTransportSuperParcel): The parcel to add.
Returns:
None
"""
self._independent_items.append(parcel)

def add_parcel_vpn(self, parcel: AnyTransportVpnParcel) -> UUID:
"""
Adds a VPN parcel to the builder.
Args:
parcel (LanVpnParcel): The VPN parcel to add.
Returns:
UUID: The UUID tag of the added VPN parcel.
"""
vpn_tag = uuid4()
logger.debug(f"Adding VPN parcel {parcel.parcel_name} with tag {vpn_tag}")
self._independent_items_vpns[vpn_tag] = parcel
return vpn_tag

def add_vpn_subparcel(self, parcel: AnyTransportVpnSubParcel, vpn_tag: UUID) -> None:
"""
Adds a parcel to the feature profile.
Args:
parcel (AnyTransportVpnSubParcel): The parcel to add.
Returns:
None
"""
self._dependent_items_on_vpns[vpn_tag].append(parcel)

def build(self) -> UUID:
"""
Builds the feature profile.
Returns:
UUID: The UUID of the created feature profile.
"""

profile_uuid = self._endpoints.create_transport_feature_profile(self._profile).id
try:
for parcel in self._independent_items:
self._api.create_parcel(profile_uuid, parcel)
for vpn_tag, vpn_parcel in self._independent_items_vpns.items():
# TODO: Add subparcels to VPN
vpn_uuid = self._api.create_parcel(profile_uuid, vpn_parcel).id
for subparcel in self._dependent_items_on_vpns[vpn_tag]:
self._api.create_parcel(profile_uuid, subparcel, vpn_uuid)
except ManagerHTTPError as e:
logger.error(f"Error occured during building profile: {e.info}")
return profile_uuid
67 changes: 65 additions & 2 deletions catalystwan/api/feature_profile_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,18 @@
from catalystwan.endpoints.configuration.feature_profile.sdwan.service import ServiceFeatureProfile
from catalystwan.endpoints.configuration.feature_profile.sdwan.system import SystemFeatureProfile
from catalystwan.endpoints.configuration.feature_profile.sdwan.transport import TransportFeatureProfile
from catalystwan.exceptions import ManagerHTTPError
from catalystwan.models.configuration.feature_profile.sdwan.other import AnyOtherParcel
from catalystwan.models.configuration.feature_profile.sdwan.policy_object.security.url import URLParcel
from catalystwan.models.configuration.feature_profile.sdwan.service import AnyServiceParcel
from catalystwan.models.configuration.feature_profile.sdwan.service.multicast import MulticastParcel
from catalystwan.models.configuration.feature_profile.sdwan.transport import AnyTransportParcel
from catalystwan.models.configuration.feature_profile.sdwan.transport.bgp import WanRoutingBgpParcel
from catalystwan.models.configuration.feature_profile.sdwan.transport.cellular_controller import (
CellularControllerParcel,
)
from catalystwan.models.configuration.feature_profile.sdwan.transport.t1e1controller import T1E1ControllerParcel
from catalystwan.models.configuration.feature_profile.sdwan.transport.vpn import ManagementVpnParcel, TransportVpnParcel
from catalystwan.typed_list import DataSequence

if TYPE_CHECKING:
Expand Down Expand Up @@ -172,13 +179,69 @@ def delete_profile(self, profile_id: UUID) -> None:
"""
self.endpoint.delete_transport_feature_profile(profile_id)

def create_parcel(self, profile_id: UUID, payload: AnyTransportParcel) -> ParcelCreationResponse:
def create_parcel(
self, profile_id: UUID, payload: AnyTransportParcel, vpn_uuid: Optional[UUID] = None
) -> ParcelCreationResponse:
"""
Create Transport Parcel for selected profile_id based on payload type
"""

if vpn_uuid is not None:
vpn_parcel = self._get_vpn_parcel(profile_id, vpn_uuid).payload
if vpn_parcel._get_parcel_type() == TransportVpnParcel._get_parcel_type():
return self.endpoint.create_transport_vpn_sub_parcel(
profile_id, vpn_uuid, payload._get_parcel_type(), payload
)
else:
return self.endpoint.create_management_vpn_sub_parcel(
profile_id, vpn_uuid, payload._get_parcel_type(), payload
)
return self.endpoint.create_transport_parcel(profile_id, payload._get_parcel_type(), payload)

def _get_vpn_parcel(
self, profile_id: UUID, vpn_uuid: UUID
) -> Union[Parcel[TransportVpnParcel], Parcel[ManagementVpnParcel]]:
"""Resolve the VPN parcel type based on the VPN UUID."""
try:
return self.endpoint.get_transport_parcel(profile_id, TransportVpnParcel._get_parcel_type(), vpn_uuid)
except ManagerHTTPError:
return self.endpoint.get_transport_parcel(profile_id, ManagementVpnParcel._get_parcel_type(), vpn_uuid)

@overload
def get_parcel(
self, profile_id: UUID, parcel_type: Type[CellularControllerParcel], parcel_id: UUID
) -> Parcel[CellularControllerParcel]:
...

@overload
def get_parcel(
self, profile_id: UUID, parcel_type: Type[T1E1ControllerParcel], parcel_id: UUID
) -> Parcel[T1E1ControllerParcel]:
...

@overload
def get_parcel(
self, profile_id: UUID, parcel_type: Type[WanRoutingBgpParcel], parcel_id: UUID
) -> Parcel[WanRoutingBgpParcel]:
...

@overload
def get_parcel(
self, profile_id: UUID, parcel_type: Type[TransportVpnParcel], parcel_id: UUID
) -> Parcel[TransportVpnParcel]:
...

@overload
def get_parcel(
self, profile_id: UUID, parcel_type: Type[ManagementVpnParcel], parcel_id: UUID
) -> Parcel[ManagementVpnParcel]:
...

def get_parcel(self, profile_id: UUID, parcel_type: Type[AnyTransportParcel], parcel_id: UUID) -> Parcel:
"""
Get one Transport Parcel given profile id, parcel type and parcel id
"""
return self.endpoint.get_transport_parcel(profile_id, parcel_type._get_parcel_type(), parcel_id)


class OtherFeatureProfileAPI:
"""
Expand Down
Loading

0 comments on commit 9f8d419

Please sign in to comment.