From ecfdbbca876aae6480e2694f3607c3b51ef8139a Mon Sep 17 00:00:00 2001 From: Karel van Klink <karel.vanklink@geant.org> Date: Thu, 5 Dec 2024 11:52:02 +0100 Subject: [PATCH] Add new attribute to site --- ...add_optical_equipment_attribute_to_site.py | 44 +++++++++++++++++++ gso/oss-params-example.json | 2 +- gso/products/product_blocks/site.py | 4 ++ gso/utils/types/base_site.py | 1 + gso/workflows/site/create_imported_site.py | 2 + gso/workflows/site/create_site.py | 1 + gso/workflows/switch/create_switch.py | 2 +- 7 files changed, 54 insertions(+), 2 deletions(-) create mode 100644 gso/migrations/versions/2024-12-04_fc7bd696014e_add_optical_equipment_attribute_to_site.py diff --git a/gso/migrations/versions/2024-12-04_fc7bd696014e_add_optical_equipment_attribute_to_site.py b/gso/migrations/versions/2024-12-04_fc7bd696014e_add_optical_equipment_attribute_to_site.py new file mode 100644 index 00000000..80f277e0 --- /dev/null +++ b/gso/migrations/versions/2024-12-04_fc7bd696014e_add_optical_equipment_attribute_to_site.py @@ -0,0 +1,44 @@ +"""Add optical equipment attribute to Site. + +Revision ID: fc7bd696014e +Revises: 79a76b22ca53 +Create Date: 2024-12-04 10:15:40.529552 + +""" +import sqlalchemy as sa +from alembic import op + +# revision identifiers, used by Alembic. +revision = 'fc7bd696014e' +down_revision = '79a76b22ca53' +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 ('site_contains_optical_equipment', 'Whether a site contains optical equipment') 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 ('SiteBlock')), (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('site_contains_optical_equipment'))) + """)) + conn.execute(sa.text(""" +WITH rt_id AS (SELECT resource_type_id FROM resource_types WHERE resource_type = 'site_contains_optical_equipment') INSERT INTO subscription_instance_values (subscription_instance_id, resource_type_id, value) SELECT subscription_instance_id, rt_id.resource_type_id, 'True' FROM rt_id, subscription_instances WHERE product_block_id = (SELECT product_block_id FROM product_blocks WHERE name = 'SiteBlock'); + """)) + + +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 ('SiteBlock')) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('site_contains_optical_equipment')) + """)) + 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 ('SiteBlock'))) AND product_block_resource_types.resource_type_id = (SELECT resource_types.resource_type_id FROM resource_types WHERE resource_types.resource_type IN ('site_contains_optical_equipment')) + """)) + 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 ('site_contains_optical_equipment')) + """)) + conn.execute(sa.text(""" +DELETE FROM resource_types WHERE resource_types.resource_type IN ('site_contains_optical_equipment') + """)) diff --git a/gso/oss-params-example.json b/gso/oss-params-example.json index f6e85ed8..ac0a29de 100644 --- a/gso/oss-params-example.json +++ b/gso/oss-params-example.json @@ -54,7 +54,7 @@ }, "LAN_SWITCH_INTERCONNECT": { "V4": {"containers": ["10.2.0.0/16"], "networks": [], "mask": 24}, - "V6": {"containers": [], "networks": [], "mask": 126}, + "V6": {"containers": ["beef:cafe::/56"], "networks": [], "mask": 64}, "domain_name": ".geant.net", "dns_view": "default", "network_view": "default" diff --git a/gso/products/product_blocks/site.py b/gso/products/product_blocks/site.py index 11c8e336..871707b4 100644 --- a/gso/products/product_blocks/site.py +++ b/gso/products/product_blocks/site.py @@ -38,6 +38,7 @@ class SiteBlockInactive( site_bgp_community_id: int | None = None site_tier: SiteTier | None = None site_ts_address: IPAddress | None = None + site_contains_optical_equipment: bool | None = None class SiteBlockProvisioning(SiteBlockInactive, lifecycle=[SubscriptionLifecycle.PROVISIONING]): @@ -53,6 +54,7 @@ class SiteBlockProvisioning(SiteBlockInactive, lifecycle=[SubscriptionLifecycle. site_bgp_community_id: int site_tier: SiteTier site_ts_address: IPAddress + site_contains_optical_equipment: bool class SiteBlock(SiteBlockProvisioning, lifecycle=[SubscriptionLifecycle.ACTIVE]): @@ -82,3 +84,5 @@ class SiteBlock(SiteBlockProvisioning, lifecycle=[SubscriptionLifecycle.ACTIVE]) #: access. This is required in case a link goes down, or when a router is initially added to the network and it #: does not have any IP trunks connected to it. site_ts_address: IPAddress + #: Whether this site contains optical equipment, which dictates the need for a DCN management VLAN + site_contains_optical_equipment: bool diff --git a/gso/utils/types/base_site.py b/gso/utils/types/base_site.py index c5af009a..753d0ab3 100644 --- a/gso/utils/types/base_site.py +++ b/gso/utils/types/base_site.py @@ -24,3 +24,4 @@ class BaseSiteValidatorModel(BaseModel): site_latitude: LatitudeCoordinate site_longitude: LongitudeCoordinate partner: str + site_contains_optical_equipment: bool = True diff --git a/gso/workflows/site/create_imported_site.py b/gso/workflows/site/create_imported_site.py index b1190863..d3c1720b 100644 --- a/gso/workflows/site/create_imported_site.py +++ b/gso/workflows/site/create_imported_site.py @@ -55,6 +55,7 @@ def initialize_subscription( site_internal_id: int, site_ts_address: IPAddress, site_tier: SiteTier, + site_contains_optical_equipment: bool, # noqa: FBT001 ) -> State: """Initialise the subscription object with all input.""" subscription.site.site_name = site_name @@ -67,6 +68,7 @@ def initialize_subscription( subscription.site.site_internal_id = site_internal_id subscription.site.site_tier = site_tier subscription.site.site_ts_address = site_ts_address + subscription.site.site_contains_optical_equipment = site_contains_optical_equipment subscription.description = f"Site in {site_city}, {site_country}" diff --git a/gso/workflows/site/create_site.py b/gso/workflows/site/create_site.py index 6bf4bd74..9fe35fc1 100644 --- a/gso/workflows/site/create_site.py +++ b/gso/workflows/site/create_site.py @@ -85,6 +85,7 @@ def initialize_subscription( subscription.site.site_internal_id = site_internal_id subscription.site.site_tier = site_tier subscription.site.site_ts_address = site_ts_address + subscription.site.site_contains_optical_equipment = True subscription.description = f"Site in {site_city}, {site_country}" diff --git a/gso/workflows/switch/create_switch.py b/gso/workflows/switch/create_switch.py index 7bbcfbda..0a8d2793 100644 --- a/gso/workflows/switch/create_switch.py +++ b/gso/workflows/switch/create_switch.py @@ -40,7 +40,7 @@ def _initial_input_form_generator(product_name: str) -> FormGenerator: hostname: str ts_port: PortNumber vendor: ReadOnlyField(Vendor.JUNIPER, default_type=Vendor) # type: ignore[valid-type] - model: SwitchModel = Choice("Switch model", SwitchModel.values()) + model: SwitchModel = Choice("Switch model", SwitchModel.values()) # type: ignore[assignment, arg-type] @model_validator(mode="after") def hostname_must_be_available(self) -> Self: -- GitLab