diff --git a/gso/cli/imports.py b/gso/cli/imports.py index fc81b03b3f3c45c54f95db64a872c91cbeee1be6..d8f82908330a35f9602db3bf0fdbf3a58b741776 100644 --- a/gso/cli/imports.py +++ b/gso/cli/imports.py @@ -204,6 +204,7 @@ class EdgePortImportModel(BaseModel): ignore_if_down: bool ae_members: LAGMemberList[LAGMember] description: str | None = None + custom_service_name: str | None = None @field_validator("partner") def check_if_partner_exists(cls, value: str) -> str: @@ -269,6 +270,7 @@ class L3CoreServiceImportModel(BaseModel): edge_port: str ap_type: str + custom_service_name: str | None = None gs_id: IMPORTED_GS_ID sbp_type: SBPType = SBPType.L3 is_tagged: bool = False @@ -355,6 +357,7 @@ class Layer2CircuitServiceImportModel(BaseModel): policer_enabled: bool = False policer_bandwidth: BandwidthString | None = None policer_burst_rate: BandwidthString | None = None + custom_service_name: str | None = None @field_validator("partner") def check_if_partner_exists(cls, value: str) -> str: diff --git a/gso/migrations/versions/2025-01-13_db6e86c6d4e1_add_custom_service_name_to_edgeport_.py b/gso/migrations/versions/2025-01-13_db6e86c6d4e1_add_custom_service_name_to_edgeport_.py new file mode 100644 index 0000000000000000000000000000000000000000..e8019940d221ca42d6712f290936a1e3b8a6c4d7 --- /dev/null +++ b/gso/migrations/versions/2025-01-13_db6e86c6d4e1_add_custom_service_name_to_edgeport_.py @@ -0,0 +1,41 @@ +"""Add custom service name to EdgePort, L2Circuit and L3CoreService.. + +Revision ID: db6e86c6d4e1 +Revises: 8a65d0ed588e +Create Date: 2025-01-13 11:13:05.149307 + +""" +import sqlalchemy as sa +from alembic import op + +# revision identifiers, used by Alembic. +revision = 'db6e86c6d4e1' +down_revision = '8a65d0ed588e' +branch_labels = None +depends_on = None + + +def upgrade() -> None: + conn = op.get_bind() + conn.execute(sa.text(""" +INSERT INTO resource_types (resource_type, description) VALUES ('custom_service_name', 'Custom Service Name mainly used by IMS') RETURNING resource_types.resource_type_id + """)) + conn.execute(sa.text(""" +INSERT INTO product_block_resource_types (product_block_id, resource_type_id) VALUES ((SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('AccessPort')), (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('custom_service_name'))), ((SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('Layer2CircuitBlock')), (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('custom_service_name'))), ((SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('EdgePortBlock')), (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('custom_service_name'))) + """)) + + +def downgrade() -> None: + conn = op.get_bind() + conn.execute(sa.text(""" +DELETE FROM product_block_resource_types WHERE product_block_resource_types.product_block_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('AccessPort', 'Layer2CircuitBlock', 'EdgePortBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('custom_service_name')) + """)) + conn.execute(sa.text(""" +DELETE FROM subscription_instance_values USING product_block_resource_types WHERE subscription_instance_values.subscription_instance_id IN (SELECT subscription_instances.subscription_instance_id FROM subscription_instances WHERE subscription_instances.subscription_instance_id IN (SELECT product_blocks.product_block_id FROM product_blocks WHERE product_blocks.name IN ('AccessPort', 'Layer2CircuitBlock', 'EdgePortBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('custom_service_name')) + """)) + conn.execute(sa.text(""" +DELETE FROM subscription_instance_values WHERE subscription_instance_values.resource_type_id IN (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('custom_service_name')) + """)) + conn.execute(sa.text(""" +DELETE FROM resource_types WHERE resource_types.resource_type IN ('custom_service_name') + """)) diff --git a/gso/products/product_blocks/edge_port.py b/gso/products/product_blocks/edge_port.py index d7249d34bbfa6410834a28b0770ce6b1e3c6a08d..e09372341ba01456b7ce744365e57826bd873ea5 100644 --- a/gso/products/product_blocks/edge_port.py +++ b/gso/products/product_blocks/edge_port.py @@ -72,6 +72,7 @@ class EdgePortBlockInactive( ignore_if_down: bool = False ga_id: str | None = None edge_port_ae_members: LAGMemberList[EdgePortAEMemberBlockInactive] + custom_service_name: str | None = None class EdgePortBlockProvisioning(EdgePortBlockInactive, lifecycle=[SubscriptionLifecycle.PROVISIONING]): @@ -89,6 +90,7 @@ class EdgePortBlockProvisioning(EdgePortBlockInactive, lifecycle=[SubscriptionLi ignore_if_down: bool = False ga_id: str | None = None edge_port_ae_members: LAGMemberList[EdgePortAEMemberBlockProvisioning] # type: ignore[assignment] + custom_service_name: str | None = None class EdgePortBlock(EdgePortBlockProvisioning, lifecycle=[SubscriptionLifecycle.ACTIVE]): @@ -107,6 +109,7 @@ class EdgePortBlock(EdgePortBlockProvisioning, lifecycle=[SubscriptionLifecycle. ignore_if_down: If set to True, the edge port will be ignored if it is down. ga_id: The GEANT GA ID associated with this edge port, if any. edge_port_ae_members: A list of LAG members associated with this edge port. + custom_service_name: The name of the custom service, if any. """ node: RouterBlock @@ -121,3 +124,4 @@ class EdgePortBlock(EdgePortBlockProvisioning, lifecycle=[SubscriptionLifecycle. ignore_if_down: bool = False ga_id: str | None = None edge_port_ae_members: LAGMemberList[EdgePortAEMemberBlock] # type: ignore[assignment] + custom_service_name: str | None = None diff --git a/gso/products/product_blocks/l3_core_service.py b/gso/products/product_blocks/l3_core_service.py index ce2db1782410311e8d37f34d4b92cd27abed8d01..2c3149db7b75babb58baa91358d8ddaa84d9ad2d 100644 --- a/gso/products/product_blocks/l3_core_service.py +++ b/gso/products/product_blocks/l3_core_service.py @@ -17,6 +17,7 @@ class AccessPortInactive(ProductBlockModel, lifecycle=[SubscriptionLifecycle.INI ap_type: APType | None = None sbp: ServiceBindingPortInactive + custom_service_name: str | None = None class AccessPortProvisioning(AccessPortInactive, lifecycle=[SubscriptionLifecycle.PROVISIONING]): @@ -24,6 +25,7 @@ class AccessPortProvisioning(AccessPortInactive, lifecycle=[SubscriptionLifecycl ap_type: APType sbp: ServiceBindingPortProvisioning + custom_service_name: str | None = None class AccessPort(AccessPortProvisioning, lifecycle=[SubscriptionLifecycle.ACTIVE]): @@ -32,10 +34,12 @@ class AccessPort(AccessPortProvisioning, lifecycle=[SubscriptionLifecycle.ACTIVE Attributes: ap_type: The type of Access Port sbp: The corresponding SBP of this Access Port. + custom_service_name: The name of the custom service, if any. """ ap_type: APType sbp: ServiceBindingPort + custom_service_name: str | None = None class L3CoreServiceBlockInactive( diff --git a/gso/products/product_blocks/layer_2_circuit.py b/gso/products/product_blocks/layer_2_circuit.py index 2e1a7c53b7a995efedc6c09377ef19f4d2ee158b..0b8dc92db06509d1eeb15244592db900357acb63 100644 --- a/gso/products/product_blocks/layer_2_circuit.py +++ b/gso/products/product_blocks/layer_2_circuit.py @@ -79,6 +79,7 @@ class Layer2CircuitBlockInactive( policer_enabled: bool | None = None policer_burst_rate: BandwidthString | None = None bandwidth: BandwidthString | None = None + custom_service_name: str | None = None class Layer2CircuitBlockProvisioning(Layer2CircuitBlockInactive, lifecycle=[SubscriptionLifecycle.PROVISIONING]): @@ -92,6 +93,7 @@ class Layer2CircuitBlockProvisioning(Layer2CircuitBlockInactive, lifecycle=[Subs policer_enabled: bool policer_burst_rate: BandwidthString | None bandwidth: BandwidthString | None + custom_service_name: str | None = None class Layer2CircuitBlock(Layer2CircuitBlockProvisioning, lifecycle=[SubscriptionLifecycle.ACTIVE]): @@ -106,6 +108,7 @@ class Layer2CircuitBlock(Layer2CircuitBlockProvisioning, lifecycle=[Subscription policer_enabled: Whether this Layer 2 Circuit is policed. policer_burst_rate: If policed, the burst rate of the policer. bandwidth: If policed, the bandwidth of the policer is stored. + custom_service_name: The name of the service which is used in IMS. """ layer_2_circuit_sides: Layer2CircuitSides[Layer2CircuitSideBlock] @@ -116,3 +119,4 @@ class Layer2CircuitBlock(Layer2CircuitBlockProvisioning, lifecycle=[Subscription policer_enabled: bool policer_burst_rate: BandwidthString | None bandwidth: BandwidthString | None + custom_service_name: str | None = None diff --git a/gso/workflows/edge_port/create_edge_port.py b/gso/workflows/edge_port/create_edge_port.py index f715e10470ede68c7993f7af58c1344c20ffe3b4..03d1fe69aabca012b2b772a67d0f6118586cffb2 100644 --- a/gso/workflows/edge_port/create_edge_port.py +++ b/gso/workflows/edge_port/create_edge_port.py @@ -53,6 +53,7 @@ def initial_input_form_generator(product_name: str) -> FormGenerator: minimum_links: int mac_address: str | None = None ignore_if_down: bool = False + custom_service_name: str | None = None @model_validator(mode="after") def validate_number_of_members(self) -> Self: @@ -94,6 +95,7 @@ def initial_input_form_generator(product_name: str) -> FormGenerator: "edge_port_name": input_forms_data["name"], "edge_port_description": input_forms_data["description"], "edge_port_type": input_forms_data["service_type"], + "custom_service_name": input_forms_data["custom_service_name"], } summary_fields = [ "node", @@ -108,6 +110,7 @@ def initial_input_form_generator(product_name: str) -> FormGenerator: "edge_port_name", "edge_port_description", "edge_port_ae_members", + "custom_service_name", ] yield from create_summary_form(summary_form_data, product_name, summary_fields) return input_forms_data @@ -139,6 +142,7 @@ def initialize_subscription( ignore_if_down: bool, # noqa: FBT001 ae_members: list[dict[str, Any]], description: str | None = None, + custom_service_name: str | None = None, ) -> State: """Initialise the subscription object in the service database.""" router = Router.from_subscription(node).router @@ -156,6 +160,7 @@ def initialize_subscription( partner_name = get_partner_by_id(partner).name subscription.description = f"Edge Port {name} on {router.router_fqdn}, {partner_name}, {ga_id or ""}" subscription.edge_port.edge_port_description = description + subscription.edge_port.custom_service_name = custom_service_name for member in ae_members: subscription.edge_port.edge_port_ae_members.append( EdgePortAEMemberBlockInactive.new(subscription_id=uuid4(), **member) diff --git a/gso/workflows/edge_port/create_imported_edge_port.py b/gso/workflows/edge_port/create_imported_edge_port.py index cd5f7a7b164977d188272cb94bbdba366f66982e..e7cc9dbeb33f0bcc1e212a71498822dd77465d5d 100644 --- a/gso/workflows/edge_port/create_imported_edge_port.py +++ b/gso/workflows/edge_port/create_imported_edge_port.py @@ -53,6 +53,7 @@ def initial_input_form_generator() -> FormGenerator: description: str | None = None name: str ae_members: Annotated[list[LAGMember], AfterValidator(validate_unique_list)] + custom_service_name: str | None = None user_input = yield ImportEdgePort @@ -75,6 +76,7 @@ def initialize_subscription( ignore_if_down: bool, # noqa: FBT001 ae_members: list[dict[str, Any]], description: str | None = None, + custom_service_name: str | None = None, ) -> State: """Initialise the subscription object in the service database.""" router = Router.from_subscription(node).router @@ -89,6 +91,7 @@ def initialize_subscription( subscription.edge_port.edge_port_type = service_type subscription.edge_port.ignore_if_down = ignore_if_down subscription.edge_port.ga_id = ga_id + subscription.edge_port.custom_service_name = custom_service_name subscription.description = f"Edge Port {name} on {router.router_fqdn}, {partner}, {ga_id or ""}" for member in ae_members: subscription.edge_port.edge_port_ae_members.append( diff --git a/gso/workflows/edge_port/modify_edge_port.py b/gso/workflows/edge_port/modify_edge_port.py index b176eafcc9450dbbd7d8da0608bd0d13891c3f91..395d7358ac63247dd899e3b1d05c42826e9141f0 100644 --- a/gso/workflows/edge_port/modify_edge_port.py +++ b/gso/workflows/edge_port/modify_edge_port.py @@ -45,6 +45,7 @@ def initial_input_form_generator(subscription_id: UUIDstr) -> FormGenerator: minimum_links: int | None = subscription.edge_port.minimum_links or None mac_address: str | None = subscription.edge_port.mac_address or None ignore_if_down: bool = subscription.edge_port.ignore_if_down + custom_service_name: str | None = subscription.edge_port.custom_service_name ga_id: ( Annotated[ str, AfterValidator(partial(validate_field_is_unique, subscription_id)), Field(pattern=r"^GA-\d{5}$") @@ -129,6 +130,7 @@ def modify_edge_port_subscription( ae_members: list[dict[str, str]], ignore_if_down: bool, # noqa: FBT001 description: str | None = None, + custom_service_name: str | None = None, ) -> State: """Modify the edge port subscription with the given parameters.""" previous_ae_members = [ @@ -147,6 +149,7 @@ def modify_edge_port_subscription( subscription.edge_port.ignore_if_down = ignore_if_down subscription.edge_port.ga_id = ga_id subscription.edge_port.edge_port_description = description + subscription.edge_port.custom_service_name = custom_service_name subscription.description = ( f"Edge Port {subscription.edge_port.edge_port_name} on" f" {subscription.edge_port.node.router_fqdn}," diff --git a/gso/workflows/l2_circuit/create_imported_layer_2_circuit.py b/gso/workflows/l2_circuit/create_imported_layer_2_circuit.py index 3e5e97c992ce33c7fb0fe5300c0a1f5e0034d072..4afcb8f4dbd27ec3aadc2d1ad69a06ea3c530144 100644 --- a/gso/workflows/l2_circuit/create_imported_layer_2_circuit.py +++ b/gso/workflows/l2_circuit/create_imported_layer_2_circuit.py @@ -50,6 +50,7 @@ def initial_input_form_generator() -> FormGenerator: policer_enabled: bool = False policer_bandwidth: BandwidthString | None = None policer_burst_rate: BandwidthString | None = None + custom_service_name: str | None = None @model_validator(mode="after") def tagged_layer_2_circuit_has_vlan_bounds(self) -> Self: @@ -101,6 +102,7 @@ def initialize_subscription( policer_enabled: bool, # noqa: FBT001 policer_bandwidth: BandwidthString | None, policer_burst_rate: BandwidthString | None, + custom_service_name: str | None, vc_id: VC_ID, ) -> State: """Initialize the subscription object.""" @@ -125,6 +127,7 @@ def initialize_subscription( subscription.layer_2_circuit.policer_enabled = policer_enabled subscription.layer_2_circuit.bandwidth = policer_bandwidth subscription.layer_2_circuit.policer_burst_rate = policer_burst_rate + subscription.layer_2_circuit.custom_service_name = custom_service_name subscription.description = f"{subscription.product.name} - {subscription.layer_2_circuit.virtual_circuit_id}" return {"subscription": subscription} diff --git a/gso/workflows/l2_circuit/create_layer_2_circuit.py b/gso/workflows/l2_circuit/create_layer_2_circuit.py index acf5beefa74860e548d272598d37f10fa3d69221..eb76abdb839d1e13645dc905c08600c6555a08c3 100644 --- a/gso/workflows/l2_circuit/create_layer_2_circuit.py +++ b/gso/workflows/l2_circuit/create_layer_2_circuit.py @@ -40,6 +40,7 @@ def initial_input_generator(product_name: str) -> FormGenerator: layer_2_circuit_type: Layer2CircuitType policer_enabled: bool = False + custom_service_name: str | None = None initial_user_input = yield CreateLayer2CircuitServicePage @@ -105,6 +106,7 @@ def initialize_subscription( policer_enabled: bool, # noqa: FBT001 policer_bandwidth: BandwidthString | None, policer_burst_rate: BandwidthString | None, + custom_service_name: str | None, ) -> State: """Build a subscription object from all user input.""" layer_2_circuit_sides = [] @@ -129,6 +131,7 @@ def initialize_subscription( subscription.layer_2_circuit.policer_enabled = policer_enabled subscription.layer_2_circuit.bandwidth = policer_bandwidth subscription.layer_2_circuit.policer_burst_rate = policer_burst_rate + subscription.layer_2_circuit.custom_service_name = custom_service_name subscription.description = f"{subscription.product.name} - {subscription.layer_2_circuit.virtual_circuit_id}" subscription = Layer2Circuit.from_other_lifecycle(subscription, SubscriptionLifecycle.PROVISIONING) diff --git a/gso/workflows/l2_circuit/modify_layer_2_circuit.py b/gso/workflows/l2_circuit/modify_layer_2_circuit.py index 0ac2d3919763596fdb34c6f9223c2efccc5694de..05c3ebd7494728e7a7a04457a88cfa7d277d9b09 100644 --- a/gso/workflows/l2_circuit/modify_layer_2_circuit.py +++ b/gso/workflows/l2_circuit/modify_layer_2_circuit.py @@ -32,6 +32,7 @@ def initial_input_form_generator(subscription_id: UUIDstr) -> FormGenerator: layer_2_circuit_type: Layer2CircuitType = subscription.layer_2_circuit.layer_2_circuit_type policer_enabled: bool = subscription.layer_2_circuit.policer_enabled + custom_service_name: str | None = subscription.layer_2_circuit.custom_service_name layer_2_circuit_input = yield ModifyL2CircuitForm @@ -83,6 +84,7 @@ def modify_layer_2_circuit_subscription( policer_enabled: bool, # noqa: FBT001 policer_bandwidth: BandwidthString | None, policer_burst_rate: BandwidthString | None, + custom_service_name: str | None, ) -> dict: """Update the Layer 2 Circuit subscription with the new values.""" subscription.layer_2_circuit.layer_2_circuit_type = layer_2_circuit_type @@ -91,6 +93,7 @@ def modify_layer_2_circuit_subscription( subscription.layer_2_circuit.policer_enabled = policer_enabled subscription.layer_2_circuit.bandwidth = policer_bandwidth subscription.layer_2_circuit.policer_burst_rate = policer_burst_rate + subscription.layer_2_circuit.custom_service_name = custom_service_name for layer_2_circuit_side in subscription.layer_2_circuit.layer_2_circuit_sides: layer_2_circuit_side.sbp.is_tagged = layer_2_circuit_type == Layer2CircuitType.TAGGED diff --git a/gso/workflows/l3_core_service/create_imported_l3_core_service.py b/gso/workflows/l3_core_service/create_imported_l3_core_service.py index a4948f7dc378668b077eb1e72be0b0b8452e8dfc..289cbdaad89ac16c063e0d0059ee9053cf217956 100644 --- a/gso/workflows/l3_core_service/create_imported_l3_core_service.py +++ b/gso/workflows/l3_core_service/create_imported_l3_core_service.py @@ -51,6 +51,7 @@ def initial_input_form_generator() -> FormGenerator: class ServiceBindingPort(BaseModel): edge_port: UUIDstr ap_type: str + custom_service_name: str | None = None gs_id: IMPORTED_GS_ID sbp_type: SBPType = SBPType.L3 is_tagged: bool = False @@ -127,6 +128,7 @@ def initialize_subscription(subscription: ImportedL3CoreServiceInactive, service subscription_id=uuid4(), ap_type=service_binding_port["ap_type"], sbp=service_binding_port_subscription, + custom_service_name=service_binding_port.get("custom_service_name"), ) ) diff --git a/gso/workflows/l3_core_service/create_l3_core_service.py b/gso/workflows/l3_core_service/create_l3_core_service.py index 3cf358d2316173bcd3d6c8dadc83bbf6a2857c44..e1832f5dfe58bdb898e7e1679c963839860339f4 100644 --- a/gso/workflows/l3_core_service/create_l3_core_service.py +++ b/gso/workflows/l3_core_service/create_l3_core_service.py @@ -46,6 +46,7 @@ def initial_input_form_generator(product_name: str) -> FormGenerator: class EdgePortSelection(BaseModel): edge_port: active_edge_port_selector(partner_id=initial_user_input.partner) # type: ignore[valid-type] ap_type: APType + custom_service_name: str | None = None class EdgePortSelectionForm(FormPage): model_config = ConfigDict(title=f"{product_name} - Select Edge Ports") @@ -181,6 +182,7 @@ def initialize_subscription( subscription_id=uuid4(), ap_type=edge_port["ap_type"], sbp=service_binding_port, + custom_service_name=edge_port.get("custom_service_name"), ) ) edge_port_fqdn_list.append(edge_port_subscription.edge_port.node.router_fqdn) diff --git a/gso/workflows/l3_core_service/modify_l3_core_service.py b/gso/workflows/l3_core_service/modify_l3_core_service.py index af3218c54f88d082d87fa89698e6ec833485dcf7..949cc280dc35f3c25dbfa759f917ec7af4f6d3d6 100644 --- a/gso/workflows/l3_core_service/modify_l3_core_service.py +++ b/gso/workflows/l3_core_service/modify_l3_core_service.py @@ -33,6 +33,7 @@ def initial_input_form_generator(subscription_id: UUIDstr) -> FormGenerator: class AccessPortSelection(BaseModel): edge_port: active_edge_port_selector(partner_id=subscription.customer_id) | str # type: ignore[valid-type] ap_type: APType + custom_service_name: str | None = None def validate_edge_ports_are_unique(access_ports: list[AccessPortSelection]) -> list[AccessPortSelection]: """Verify if interfaces are unique.""" @@ -48,6 +49,7 @@ def initial_input_form_generator(subscription_id: UUIDstr) -> FormGenerator: AccessPortSelection( edge_port=str(access_port.sbp.edge_port.owner_subscription_id), ap_type=access_port.ap_type, + custom_service_name=access_port.custom_service_name, ) for access_port in subscription.l3_core_service.ap_list ] @@ -123,12 +125,23 @@ def initial_input_form_generator(subscription_id: UUIDstr) -> FormGenerator: ), None, ), + next( + ( + ap.custom_service_name + for ap in input_ap_list + if str(ap.edge_port) == str(access_port.sbp.edge_port.owner_subscription_id) + ), + ), ) for access_port in subscription.l3_core_service.ap_list if str(access_port.sbp.edge_port.owner_subscription_id) in input_ep_list ] added_ap_list = [ - (ep, next(ap.ap_type for ap in input_ap_list if str(ap.edge_port) == ep)) + ( + ep, + next(ap.ap_type for ap in input_ap_list if str(ap.edge_port) == ep), + next(ap.custom_service_name for ap in input_ap_list if str(ap.edge_port) == ep), + ) for ep in input_ep_list if ep not in existing_ep_list ] @@ -136,7 +149,7 @@ def initial_input_form_generator(subscription_id: UUIDstr) -> FormGenerator: # First, the user can modify existing Edge Ports sbp_inputs = [] for access_port_index, ap_entry in enumerate(modified_ap_list): - access_port, new_ap_type = ap_entry + access_port, new_ap_type, new_custom_service_name = ap_entry current_sbp = access_port.sbp v4_peer = next(peer for peer in current_sbp.bgp_session_list if IPFamily.V4UNICAST in peer.families) v6_peer = next(peer for peer in current_sbp.bgp_session_list if IPFamily.V6UNICAST in peer.families) @@ -190,13 +203,14 @@ def initial_input_form_generator(subscription_id: UUIDstr) -> FormGenerator: | { "new_ap_type": new_ap_type, "current_sbp_id": current_sbp.subscription_instance_id, + "custom_service_name": new_custom_service_name, } ) # Second, newly added Edge Ports are configured binding_port_inputs = [] for ap_index, access_port_tuple in enumerate(added_ap_list): - edge_port_id, ap_type = access_port_tuple + edge_port_id, ap_type, new_custom_service_name = access_port_tuple class BindingPortInputForm(FormPage): model_config = ConfigDict( @@ -234,6 +248,7 @@ def initial_input_form_generator(subscription_id: UUIDstr) -> FormGenerator: ], "edge_port_id": edge_port_id, "ap_type": ap_type, + "custom_service_name": new_custom_service_name, } ) @@ -285,6 +300,7 @@ def modify_existing_sbp_blocks(subscription: L3CoreService, modified_sbp_list: l current_sbp.ipv6_address = modified_sbp_data["ipv6_address"] current_sbp.custom_firewall_filters = modified_sbp_data["custom_firewall_filters"] access_port.ap_type = modified_sbp_data["new_ap_type"] + access_port.custom_service_name = modified_sbp_data["custom_service_name"] return {"subscription": subscription} @@ -314,6 +330,7 @@ def create_new_sbp_blocks(subscription: L3CoreService, added_service_binding_por subscription_id=uuid4(), ap_type=sbp_input["ap_type"], sbp=service_binding_port, + custom_service_name=sbp_input.get("custom_service_name"), ) ) diff --git a/test/cli/test_imports.py b/test/cli/test_imports.py index a1b0c75702f18c59ad30e2c3711fe695fb912d95..9cb01c1fd205971e68dc8094cb80d81758167f17 100644 --- a/test/cli/test_imports.py +++ b/test/cli/test_imports.py @@ -423,6 +423,7 @@ def layer_2_circuit_data(temp_file, faker, partner_factory, edge_port_subscripti "vlan_range_lower_bound": faker.vlan_id(), "vlan_range_upper_bound": faker.vlan_id(), "policer_enabled": False, + "custom_service_name": faker.sentence(), } layer_2_circuit_input_data.update(**kwargs) @@ -692,6 +693,7 @@ def test_import_l3_core_service_with_invalid_edge_port( { "edge_port": fake_uuid, "ap_type": "PRIMARY", + "custom_service_name": faker.sentence(), "gs_id": faker.imported_gs_id(), "vlan_id": faker.vlan_id(), "ipv4_address": faker.ipv4(), diff --git a/test/fixtures/edge_port_fixtures.py b/test/fixtures/edge_port_fixtures.py index 0ea8744983148d97f4c9920498ea2da8a3b17ff7..90a30c672d38fa295b29d543a8a50f0342b05d23 100644 --- a/test/fixtures/edge_port_fixtures.py +++ b/test/fixtures/edge_port_fixtures.py @@ -33,6 +33,7 @@ def edge_port_subscription_factory(faker, partner_factory, router_subscription_f ga_id=None, edge_port_ae_members=None, status: SubscriptionLifecycle | None = None, + custom_service_name=None, *, enable_lacp=True, ignore_if_down=False, @@ -63,6 +64,7 @@ def edge_port_subscription_factory(faker, partner_factory, router_subscription_f edge_port_subscription.edge_port.minimum_links = minimum_links or faker.pyint(1, 2) edge_port_subscription.edge_port.edge_port_type = edge_port_type edge_port_subscription.edge_port.ignore_if_down = ignore_if_down + edge_port_subscription.edge_port.custom_service_name = custom_service_name or faker.text(max_nb_chars=30) edge_port_subscription.edge_port.edge_port_ae_members = edge_port_ae_members or [ EdgePortAEMemberBlock.new( faker.uuid4(), diff --git a/test/workflows/edge_port/test_create_edge_port.py b/test/workflows/edge_port/test_create_edge_port.py index 107dab95f2a328b4d1c7746ba0e605a65e255906..df3a40245dfc172f12c7344ab9c3cbefec866760 100644 --- a/test/workflows/edge_port/test_create_edge_port.py +++ b/test/workflows/edge_port/test_create_edge_port.py @@ -55,6 +55,7 @@ def input_form_wizard_data(request, router_subscription_factory, partner_factory "encapsulation": EncapsulationType.DOT1Q, "number_of_members": 2, "minimum_links": 1, + "custom_service_name": faker.sentence(), } create_edge_port_interface_step = { "name": "lag-21", diff --git a/test/workflows/edge_port/test_create_imported_edge_port.py b/test/workflows/edge_port/test_create_imported_edge_port.py index ea5b024e5ef9bdc1de35214e5c487a22979f7b6e..ab558bfb1787058a3c548f6aeefaf70cf7237032 100644 --- a/test/workflows/edge_port/test_create_imported_edge_port.py +++ b/test/workflows/edge_port/test_create_imported_edge_port.py @@ -33,6 +33,7 @@ def imported_edge_port_creation_input_form_data(router_subscription_factory, par }, ], "description": faker.sentence(), + "custom_service_name": faker.sentence(), } diff --git a/test/workflows/edge_port/test_modify_edge_port.py b/test/workflows/edge_port/test_modify_edge_port.py index 0f7ed1401db0e4e4fecac754ab938b5f1b246748..227cde2380bb5a9aaa0fc112a55660cdb83bf575 100644 --- a/test/workflows/edge_port/test_modify_edge_port.py +++ b/test/workflows/edge_port/test_modify_edge_port.py @@ -25,6 +25,7 @@ def input_form_wizard_data(request, faker, edge_port_subscription_factory, partn "ga_id": faker.ga_id(), "member_speed": PhysicalPortCapacity.FOUR_HUNDRED_GIGABIT_PER_SECOND, "number_of_members": 1, + "custom_service_name": faker.sentence(), }, { "description": faker.sentence(), diff --git a/test/workflows/l2_circuit/test_create_layer_2_circuit.py b/test/workflows/l2_circuit/test_create_layer_2_circuit.py index c14ab1213a41f24414b56046fbeb4a8afef43110..29eb825ab6a533c80783f914a959bbe14b111560 100644 --- a/test/workflows/l2_circuit/test_create_layer_2_circuit.py +++ b/test/workflows/l2_circuit/test_create_layer_2_circuit.py @@ -22,6 +22,7 @@ def layer_2_circuit_input(faker, partner_factory, edge_port_subscription_factory "partner": partner["partner_id"], "layer_2_circuit_type": Layer2CircuitType.TAGGED, "policer_enabled": policer_enabled, + "custom_service_name": faker.sentence(), }, { "vlan_range_lower_bound": faker.vlan_id(), @@ -70,3 +71,4 @@ def test_create_layer_2_circuit_success( assert subscription.layer_2_circuit.bandwidth == layer_2_circuit_input[2]["policer_bandwidth"] assert subscription.layer_2_circuit.policer_burst_rate == layer_2_circuit_input[2]["policer_burst_rate"] assert subscription.layer_2_circuit.policer_enabled == layer_2_circuit_input[1]["policer_enabled"] + assert subscription.layer_2_circuit.custom_service_name == layer_2_circuit_input[1]["custom_service_name"] diff --git a/test/workflows/l2_circuit/test_modify_layer_2_circuit.py b/test/workflows/l2_circuit/test_modify_layer_2_circuit.py index 3879a0fe085f746990baa4198ebb04ee394750db..0e20789722003af945f273076022a33ada5aa700 100644 --- a/test/workflows/l2_circuit/test_modify_layer_2_circuit.py +++ b/test/workflows/l2_circuit/test_modify_layer_2_circuit.py @@ -24,6 +24,7 @@ def test_modify_layer_2_circuit_change_policer_bandwidth( "tt_number": faker.tt_number(), "layer_2_circuit_type": Layer2CircuitType.TAGGED, "policer_enabled": False, + "custom_service_name": faker.sentence(), }, { "vlan_range_lower_bound": subscription.layer_2_circuit.vlan_range_lower_bound, @@ -33,11 +34,13 @@ def test_modify_layer_2_circuit_change_policer_bandwidth( }, ] result, _, _ = run_workflow("modify_layer_2_circuit", input_form_data) + subscription = Layer2Circuit.from_subscription(subscription_id) assert_complete(result) assert subscription.status == SubscriptionLifecycle.ACTIVE assert subscription.layer_2_circuit.policer_enabled is False assert subscription.layer_2_circuit.bandwidth is None assert subscription.layer_2_circuit.policer_burst_rate is None + assert subscription.layer_2_circuit.custom_service_name == input_form_data[1]["custom_service_name"] @pytest.mark.parametrize("layer_2_circuit_service_type", [ProductName.GEANT_PLUS, ProductName.EXPRESSROUTE]) diff --git a/test/workflows/l3_core_service/test_create_l3_core_service.py b/test/workflows/l3_core_service/test_create_l3_core_service.py index c26e649443f01d44d024062038d5d7192c54fa3a..a8f34c4f633f12c52725f9c74659d94432e80d8a 100644 --- a/test/workflows/l3_core_service/test_create_l3_core_service.py +++ b/test/workflows/l3_core_service/test_create_l3_core_service.py @@ -47,7 +47,7 @@ def test_create_l3_core_service_success( form_input_data = [ {"product": product_id}, {"tt_number": faker.tt_number(), "partner": partner["partner_id"]}, - {"edge_port": {"edge_port": edge_port_a, "ap_type": APType.PRIMARY}}, + {"edge_port": {"edge_port": edge_port_a, "ap_type": APType.PRIMARY, "custom_service_name": faker.sentence()}}, { "is_tagged": faker.boolean(), "vlan_id": faker.vlan_id(), diff --git a/test/workflows/l3_core_service/test_modify_l3_core_service.py b/test/workflows/l3_core_service/test_modify_l3_core_service.py index dc7f3a510f92ed1d6361f0c1799528dbbe63c523..64bf4df41e2825e82afc430654db578bc4f517ce 100644 --- a/test/workflows/l3_core_service/test_modify_l3_core_service.py +++ b/test/workflows/l3_core_service/test_modify_l3_core_service.py @@ -28,6 +28,7 @@ def test_modify_l3_core_service_remove_edge_port_success(l3_core_service_subscri { "edge_port": str(access_port.sbp.edge_port.owner_subscription_id), "ap_type": APType.LOAD_BALANCED, + "custom_service_name": access_port.custom_service_name, } ] # The factory generates a subscription with two Access Ports, this will remove the second one. }, @@ -71,6 +72,7 @@ def test_modify_l3_core_service_add_new_edge_port_success( { "edge_port": str(port.sbp.edge_port.owner_subscription_id), "ap_type": port.ap_type, + "custom_service_name": port.custom_service_name, } for port in subscription.l3_core_service.ap_list ] @@ -78,6 +80,7 @@ def test_modify_l3_core_service_add_new_edge_port_success( { "edge_port": str(new_edge_port), "ap_type": APType.BACKUP, + "custom_service_name": faker.sentence(), } ] },