Skip to content

Commit 07306ed

Browse files
committed
Merge branch 'fix_type_specific_id_rebased' into 'main'
Fix missing id primary key on segment data tables for NetBox branching support See merge request 701/netbox/cesnet_service_path_plugin!48
2 parents c726929 + 3a2e7f5 commit 07306ed

5 files changed

Lines changed: 134 additions & 4 deletions

File tree

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
# Custom migration: switch primary key from segment_id to auto-generated id
2+
# for DarkFiberSegmentData, EthernetServiceSegmentData, OpticalSpectrumSegmentData.
3+
#
4+
# Django's auto-generated migration fails because it tries to add a new PK
5+
# column while the old PK constraint still exists. This migration uses raw SQL
6+
# to do the steps in the correct order:
7+
# 1. Drop the existing PK constraint on segment_id
8+
# 2. Add a new "id" identity column as the primary key
9+
# 3. Add a UNIQUE constraint on segment_id (required by OneToOneField)
10+
# 4. Register the state changes so Django's ORM stays in sync
11+
12+
import django.db.models.deletion
13+
from django.db import migrations, models
14+
15+
16+
# (table_name, old_pkey_constraint_name)
17+
# Constraint names come from the \d output in Postgres.
18+
TABLES = [
19+
(
20+
"cesnet_service_path_plugin_darkfibersegmentdata",
21+
"cesnet_service_path_plugin_darkfibersegmentdata_pkey",
22+
),
23+
(
24+
"cesnet_service_path_plugin_ethernetservicesegmentdata",
25+
"cesnet_service_path_plugin_ethernetservicesegmentdata_pkey",
26+
),
27+
(
28+
"cesnet_service_path_plugin_opticalspectrumsegmentdata",
29+
"cesnet_service_path_plugin_opticalspectrumsegmentdata_pkey",
30+
),
31+
]
32+
33+
34+
def forwards(apps, schema_editor):
35+
for table, pkey_name in TABLES:
36+
# 1. Drop the existing primary key (segment_id)
37+
schema_editor.execute(
38+
f'ALTER TABLE "{table}" DROP CONSTRAINT "{pkey_name}";'
39+
)
40+
# 2. Add new "id" column as identity primary key
41+
schema_editor.execute(
42+
f'ALTER TABLE "{table}" ADD COLUMN "id" bigint NOT NULL '
43+
f"GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY;"
44+
)
45+
# 3. Add unique constraint on segment_id (OneToOneField needs it)
46+
schema_editor.execute(
47+
f'ALTER TABLE "{table}" ADD CONSTRAINT '
48+
f'"{table}_segment_id_key" UNIQUE ("segment_id");'
49+
)
50+
51+
52+
def backwards(apps, schema_editor):
53+
for table, pkey_name in TABLES:
54+
# Reverse: drop the unique constraint, drop id column, re-add old PK
55+
schema_editor.execute(
56+
f'ALTER TABLE "{table}" DROP CONSTRAINT "{table}_segment_id_key";'
57+
)
58+
schema_editor.execute(
59+
f'ALTER TABLE "{table}" DROP COLUMN "id";'
60+
)
61+
schema_editor.execute(
62+
f'ALTER TABLE "{table}" ADD CONSTRAINT "{pkey_name}" '
63+
f'PRIMARY KEY ("segment_id");'
64+
)
65+
66+
67+
class Migration(migrations.Migration):
68+
69+
dependencies = [
70+
(
71+
"cesnet_service_path_plugin",
72+
"0036_alter_opticalspectrumsegmentdata_chromatic_dispersion",
73+
),
74+
]
75+
76+
operations = [
77+
# Raw SQL handles the actual schema change
78+
migrations.RunPython(forwards, backwards),
79+
# State-only operations so Django's ORM knows about the new fields
80+
migrations.SeparateDatabaseAndState(
81+
state_operations=[
82+
migrations.AddField(
83+
model_name="darkfibersegmentdata",
84+
name="id",
85+
field=models.BigAutoField(
86+
auto_created=True, primary_key=True, serialize=False
87+
),
88+
),
89+
migrations.AlterField(
90+
model_name="darkfibersegmentdata",
91+
name="segment",
92+
field=models.OneToOneField(
93+
on_delete=django.db.models.deletion.CASCADE,
94+
related_name="dark_fiber_data",
95+
to="cesnet_service_path_plugin.segment",
96+
),
97+
),
98+
migrations.AddField(
99+
model_name="ethernetservicesegmentdata",
100+
name="id",
101+
field=models.BigAutoField(
102+
auto_created=True, primary_key=True, serialize=False
103+
),
104+
),
105+
migrations.AlterField(
106+
model_name="ethernetservicesegmentdata",
107+
name="segment",
108+
field=models.OneToOneField(
109+
on_delete=django.db.models.deletion.CASCADE,
110+
related_name="ethernet_service_data",
111+
to="cesnet_service_path_plugin.segment",
112+
),
113+
),
114+
migrations.AddField(
115+
model_name="opticalspectrumsegmentdata",
116+
name="id",
117+
field=models.BigAutoField(
118+
auto_created=True, primary_key=True, serialize=False
119+
),
120+
),
121+
migrations.AlterField(
122+
model_name="opticalspectrumsegmentdata",
123+
name="segment",
124+
field=models.OneToOneField(
125+
on_delete=django.db.models.deletion.CASCADE,
126+
related_name="optical_spectrum_data",
127+
to="cesnet_service_path_plugin.segment",
128+
),
129+
),
130+
],
131+
database_operations=[], # Already handled by RunPython above
132+
),
133+
]

cesnet_service_path_plugin/models/dark_fiber_data.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ class DarkFiberSegmentData(NetBoxModel):
2424
"Segment",
2525
on_delete=models.CASCADE,
2626
related_name="dark_fiber_data",
27-
primary_key=True,
2827
help_text="Associated segment (1:1 relationship)",
2928
)
3029

cesnet_service_path_plugin/models/ethernet_service_data.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ class EthernetServiceSegmentData(NetBoxModel):
1919
"Segment",
2020
on_delete=models.CASCADE,
2121
related_name="ethernet_service_data",
22-
primary_key=True,
2322
help_text="Associated segment (1:1 relationship)",
2423
)
2524

cesnet_service_path_plugin/models/optical_spectrum_data.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ class OpticalSpectrumSegmentData(NetBoxModel):
1818
"Segment",
1919
on_delete=models.CASCADE,
2020
related_name="optical_spectrum_data",
21-
primary_key=True,
2221
help_text="Associated segment (1:1 relationship)",
2322
)
2423

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
44

55
[project]
66
name = "cesnet_service_path_plugin"
7-
version = "6.0.0"
7+
version = "6.0.1"
88
description = "Adds ability to create, edit and view service paths in the network."
99
authors = [
1010
{name = "Jan Krupa", email = "jan.krupa@cesnet.cz"},

0 commit comments

Comments
 (0)