network: generate a device's asset number instead of asking twice
Every network device on this fleet already follows one convention, applied by hand: AP-<name>, SW-<name>, SVR-<name>, IDF-<name>. 45 records, no exceptions. The create form demanded the asset number anyway, so the same value was typed twice and the convention held only as long as everyone remembered it. The prefix now lives on the device type, and a blank asset number is generated as <PREFIX>-<name>. Left explicit, an asset number always wins: a device carrying a real identifier of its own - a vendor tag, a controller name, a serial - keeps it. That is the platform rule, adopt where an identifier exists and derive only where none does. The prefix is NOT derived from the type name. "Access Point" and "Access Panel" both initialise to AP, and assetnumber is unique, so the second type would collide with the first on every device it created. It is nullable, so a type that wants no prefix generates the bare name rather than needing one invented. Names are sanitised before they reach a business key - the existing data already shows why, with IDF-Telco-Demarc-#1 carrying a '#' into an identifier. An existing prefix is never stacked: IDF-03 under type IDF stays IDF-03.
This commit is contained in:
@@ -0,0 +1,69 @@
|
||||
"""Asset-number prefix per network device type.
|
||||
|
||||
Every network device already follows one convention, applied by hand:
|
||||
AP-<name>, SW-<name>, SVR-<name>, IDF-<name>. 45 records, no exceptions. This
|
||||
stores the prefix on the type so the create path can generate the asset number
|
||||
instead of asking someone to retype the same value twice.
|
||||
|
||||
Nullable: a type with no prefix generates the bare name. Nobody has to invent
|
||||
one for a type that does not want it.
|
||||
|
||||
It deliberately is NOT derived from the type name - 'Access Point' and 'Access
|
||||
Panel' both initialise to AP, and assetnumber is unique, so the second type
|
||||
would collide with the first on every device it created.
|
||||
|
||||
Backfilled for the four types already in use so existing conventions carry
|
||||
forward. A site whose types are named differently gets NULL and generates bare
|
||||
names, which is correct rather than wrong.
|
||||
"""
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = 'network0003prefix'
|
||||
down_revision = 'network0002model'
|
||||
branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
# type name -> prefix, from what the existing records already use
|
||||
SEEDPREFIXES = {
|
||||
'Access Point': 'AP',
|
||||
'Switch': 'SW',
|
||||
'Server': 'SVR',
|
||||
'IDF': 'IDF',
|
||||
}
|
||||
|
||||
|
||||
def upgrade():
|
||||
# Guarded like network0002model: on a FRESH database the table is built from
|
||||
# the SQLAlchemy models, which already declare this column, so an
|
||||
# unconditional add fails with "duplicate column name".
|
||||
bind = op.get_bind()
|
||||
insp = sa.inspect(bind)
|
||||
if 'networkdevicetypes' not in insp.get_table_names():
|
||||
return
|
||||
cols = {c['name'] for c in insp.get_columns('networkdevicetypes')}
|
||||
if 'prefix' not in cols:
|
||||
op.add_column('networkdevicetypes',
|
||||
sa.Column('prefix', sa.String(length=12), nullable=True))
|
||||
|
||||
# Backfill only where the type exists and has no prefix yet, so a re-run and
|
||||
# a site that already set its own are both left alone.
|
||||
for typename, prefix in SEEDPREFIXES.items():
|
||||
bind.execute(
|
||||
sa.text('UPDATE networkdevicetypes SET prefix = :prefix '
|
||||
'WHERE networkdevicetype = :typename '
|
||||
'AND (prefix IS NULL OR prefix = :empty)'),
|
||||
{'prefix': prefix, 'typename': typename, 'empty': ''})
|
||||
|
||||
|
||||
def downgrade():
|
||||
bind = op.get_bind()
|
||||
insp = sa.inspect(bind)
|
||||
if 'networkdevicetypes' not in insp.get_table_names():
|
||||
return
|
||||
cols = {c['name'] for c in insp.get_columns('networkdevicetypes')}
|
||||
if 'prefix' in cols:
|
||||
op.drop_column('networkdevicetypes', 'prefix')
|
||||
Reference in New Issue
Block a user