Skip to content

Commit 28fba7c

Browse files
committed
Add support for VlanRanges to NSISTP and
- update netbox sap payload function and create a new vlan group payload function. - rename CustomVlanRange to OrchestratorVlanRange - update validate vlan in use validation
1 parent a105e19 commit 28fba7c

File tree

16 files changed

+271
-213
lines changed

16 files changed

+271
-213
lines changed

products/product_blocks/port.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,8 @@ def vlans(self) -> List[int]:
7373

7474
@computed_field # type: ignore[misc]
7575
@property
76-
def vlan_ims_ids(self) -> List[int]:
77-
"""Get list of active VLAN IMS IDs by looking at SAPBlock's that use this PortBlock."""
76+
def vlan_group_ims_ids(self) -> List[int]:
77+
"""Get list of active IMS VLAN GROUP IDs by looking at SAPBlock's that use this PortBlock."""
7878
return [sap_block.ims_id for sap_block in self._active_sap_blocks()]
7979

8080
@computed_field # type: ignore[misc]

products/product_blocks/sap.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,18 @@
1717
from pydantic import computed_field
1818

1919
from products.product_blocks.port import PortBlock, PortBlockInactive, PortBlockProvisioning
20+
from workflows.nsistp.shared.shared import OrchestratorVlanRanges
2021

2122

2223
class SAPBlockInactive(ProductBlockModel, product_block_name="SAP"):
2324
port: PortBlockInactive | None = None
24-
vlan: int | None = None
25+
vlan: OrchestratorVlanRanges | None = None
2526
ims_id: int | None = None
2627

2728

2829
class SAPBlockProvisioning(SAPBlockInactive, lifecycle=[SubscriptionLifecycle.PROVISIONING]):
2930
port: PortBlockProvisioning
30-
vlan: int # TODO: refactor to CustomVlanRanges together with L2VPN product and workflow
31+
vlan: OrchestratorVlanRanges
3132
ims_id: int | None = None
3233

3334
@computed_field # type: ignore[misc]
@@ -38,5 +39,5 @@ def title(self) -> str:
3839

3940
class SAPBlock(SAPBlockProvisioning, lifecycle=[SubscriptionLifecycle.ACTIVE]):
4041
port: PortBlock
41-
vlan: int # TODO: refactor to CustomVlanRanges together with L2VPN product and workflow
42+
vlan: OrchestratorVlanRanges
4243
ims_id: int

products/product_types/nsistp.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
from orchestrator.types import SubscriptionLifecycle
1717

1818
from products.product_blocks.nsistp import NsistpBlock, NsistpBlockInactive, NsistpBlockProvisioning
19-
from workflows.nsistp.shared.shared import CustomVlanRanges
19+
from workflows.nsistp.shared.shared import OrchestratorVlanRanges
2020

2121

2222
class NsistpInactive(SubscriptionModel, is_base=True):
@@ -31,5 +31,5 @@ class Nsistp(NsistpProvisioning, lifecycle=[SubscriptionLifecycle.ACTIVE]):
3131
nsistp: NsistpBlock
3232

3333
@property
34-
def vlan_range(self) -> CustomVlanRanges:
34+
def vlan_range(self) -> OrchestratorVlanRanges:
3535
return self.nsistp.sap.vlan

products/services/netbox/payload/port.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,13 @@ def build_port_payload(model: PortBlockProvisioning, subscription: SubscriptionM
4444
Returns: :class:`netbox.InterfacePayload`
4545
4646
"""
47+
print(model.vlan_group_ims_ids)
48+
vlan_ids = [vlan.id for group_id in model.vlan_group_ims_ids for vlan in netbox.get_vlans(group_id=group_id)]
4749
return netbox.InterfacePayload(
4850
device=model.node.ims_id,
4951
name=model.port_name,
5052
type=model.port_type,
51-
tagged_vlans=sorted(model.vlan_ims_ids),
53+
tagged_vlans=sorted(vlan_ids),
5254
mode="tagged" if model.port_mode == PortMode.TAGGED else "",
5355
description=model.port_description,
5456
enabled=model.enabled,

products/services/netbox/payload/sap.py

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,19 @@
1616

1717
from products.product_blocks.sap import SAPBlockProvisioning
1818
from services import netbox
19+
import itertools
1920

2021

21-
def build_sap_payload(model: SAPBlockProvisioning, subscription: SubscriptionModel) -> netbox.VlanPayload:
22+
def build_sap_payload(model: SAPBlockProvisioning, subscription: SubscriptionModel) -> list[netbox.VlanPayload]:
2223
"""Create and return a Netbox payload object for a :class:`~products.product_blocks.sap.SAPBlockProvisioning`.
2324
2425
Example payload::
2526
2627
{
2728
"vid": 4,
2829
"name": "paris01a 0/0/1 vlan 4",
29-
"status": "active"
30+
"status": "active",
31+
"group": 1
3032
}
3133
3234
Args:
@@ -36,4 +38,28 @@ def build_sap_payload(model: SAPBlockProvisioning, subscription: SubscriptionMod
3638
Returns: :class:`netbox.VlanPayload`
3739
3840
"""
39-
return netbox.VlanPayload(vid=int(model.vlan), name=f"{model.port.node.node_name} {model.port.port_name}")
41+
name = f"{model.port.node.node_name} {model.port.port_name}"
42+
vlan_list = [vlan for vlan_start, vlan_end in model.vlan.to_list_of_tuples() for vlan in range(vlan_start, vlan_end+1)]
43+
return [netbox.VlanPayload(vid=vlan, group=model.ims_id, name=f"{name} - {vlan}") for vlan in vlan_list]
44+
45+
46+
def build_sap_vlan_group_payload(model: SAPBlockProvisioning, subscription: SubscriptionModel) -> netbox.VlanGroupPayload:
47+
"""Create
48+
49+
Example payload::
50+
51+
{
52+
"name": "paris01a 0/0/1 vlan 4",
53+
"vid_ranges": "5, 10, 15-20",
54+
}
55+
56+
Args:
57+
model: SAPBlockProvisioning
58+
subscription: The Subscription that will be provisioned
59+
60+
Returns: :class:`netbox.VlanGroupPayload`
61+
62+
"""
63+
name = f"{model.port.node.node_name} {model.port.port_name}"
64+
slug = name.replace(" ", "-").replace("/", "-")
65+
return netbox.VlanGroupPayload(name=name, slug=slug, vid_ranges=model.vlan.to_list_of_tuples())

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ version = "0.1.0"
44
requires-python = ">=3.12,<3.14"
55
dependencies = [
66
"deepdiff==8.6.1",
7-
"orchestrator-core==4.0.4",
7+
"orchestrator-core==4.5.3",
88
"pynetbox==7.4.1",
99
"rich==13.9.4",
1010
]

services/netbox.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525

2626
from settings import settings
2727
from utils.singledispatch import single_dispatch_base
28+
from workflows.nsistp.shared.shared import OrchestratorVlanRanges
2829

2930
logger = structlog.get_logger(__name__)
3031

@@ -129,11 +130,19 @@ class AvailableIpPayload:
129130

130131
@dataclass
131132
class VlanPayload(NetboxPayload):
132-
vid: int
133+
vid: OrchestratorVlanRanges
133134
name: str
135+
group: int
134136
status: str | None = "active"
135137

136138

139+
@dataclass
140+
class VlanGroupPayload(NetboxPayload):
141+
name: str
142+
slug: str
143+
vid_ranges: list[list[int, int]]
144+
145+
137146
@dataclass
138147
class L2vpnPayload(NetboxPayload):
139148
name: str
@@ -271,6 +280,9 @@ def delete_l2vpn(**kwargs) -> None:
271280
def delete_vlan(**kwargs) -> None:
272281
delete_from_netbox(api.ipam.vlans, **kwargs)
273282

283+
def delete_vlan_group(**kwargs) -> None:
284+
delete_from_netbox(api.ipam.vlan_groups, **kwargs)
285+
274286

275287
def skip_network_address(ip_prefix: Prefixes) -> None:
276288
"""Assign placeholders for network address(es) in available IPS of the prefix.
@@ -416,6 +428,11 @@ def _(payload: VlanPayload, **kwargs: Any) -> int:
416428
return _create_object(payload, endpoint=api.ipam.vlans)
417429

418430

431+
@create.register
432+
def _(payload: VlanGroupPayload, **kwargs: Any) -> int:
433+
return _create_object(payload, endpoint=api.ipam.vlan_groups)
434+
435+
419436
@create.register
420437
def _(payload: L2vpnPayload, **kwargs: Any) -> int:
421438
return _create_object(payload, endpoint=api.vpn.l2vpns)

0 commit comments

Comments
 (0)