91 lines
3.9 KiB
Python
91 lines
3.9 KiB
Python
"""printers: printerobservedqueues table (what a bay reported it HAS).
|
|
|
|
ShopDB already knows what a bay SHOULD have (usesprinter/defaultprinter rows on
|
|
the machine). This table holds the other half: the queues a PC reported through
|
|
POST /api/collector/printers. Observed and assigned stay in separate tables on
|
|
purpose, so observed drift can never be mistaken for desired state.
|
|
|
|
One row per observed queue; the latest report for a host replaces all of that
|
|
host's rows. The unique index on (hostname, queuename) is the guard that turns a
|
|
half-finished replace into an IntegrityError instead of duplicate queues.
|
|
|
|
Explicit ops rather than create_plugin_tables: the helper builds a per-plugin
|
|
MetaData filtered to the plugin's own tables, so the foreign key to the core
|
|
assets table cannot resolve at CreateTable-compile time. Same reason the backups
|
|
baseline spells its ops out.
|
|
|
|
Guarded both ways, so a re-run (or a database where db.create_all already built
|
|
the table) is a no-op.
|
|
|
|
Revision ID: printers0005observedqueues
|
|
Revises: printers0004drivervendor
|
|
"""
|
|
from alembic import op
|
|
|
|
from shopdb.plugins.alembic_template import (
|
|
create_index_if_missing,
|
|
create_table_if_missing,
|
|
)
|
|
import sqlalchemy as sa
|
|
|
|
|
|
# revision identifiers, used by Alembic.
|
|
revision = 'printers0005observedqueues'
|
|
down_revision = 'printers0004drivervendor'
|
|
branch_labels = None
|
|
depends_on = None
|
|
|
|
|
|
def upgrade():
|
|
bind = op.get_bind()
|
|
inspector = sa.inspect(bind)
|
|
if 'printerobservedqueues' in inspector.get_table_names():
|
|
return
|
|
create_table_if_missing(
|
|
'printerobservedqueues',
|
|
sa.Column('printerobservedqueueid', sa.Integer(), nullable=False),
|
|
# Nullable and no index of its own beyond the explicit one below: an
|
|
# unenrolled bay still gets to report, and hostname is what identifies
|
|
# the report.
|
|
sa.Column('assetid', sa.Integer(), nullable=True),
|
|
sa.Column('hostname', sa.String(length=255), nullable=False),
|
|
sa.Column('queuename', sa.String(length=255), nullable=False),
|
|
sa.Column('drivername', sa.String(length=255), nullable=True),
|
|
sa.Column('portname', sa.String(length=255), nullable=True),
|
|
sa.Column('portaddress', sa.String(length=255), nullable=True),
|
|
sa.Column('isdefault', sa.Boolean(), nullable=False,
|
|
server_default=sa.false()),
|
|
sa.Column('isshared', sa.Boolean(), nullable=False,
|
|
server_default=sa.false()),
|
|
sa.Column('observedat', sa.DateTime(), nullable=False),
|
|
sa.Column('createddate', sa.DateTime(), nullable=False),
|
|
sa.Column('modifieddate', sa.DateTime(), nullable=False),
|
|
sa.Column('isactive', sa.Boolean(), nullable=False,
|
|
server_default=sa.true()),
|
|
sa.ForeignKeyConstraint(['assetid'], ['assets.assetid'],
|
|
ondelete='CASCADE'),
|
|
sa.PrimaryKeyConstraint('printerobservedqueueid'),
|
|
# Doubles as the read index for the hostname filter (leftmost column),
|
|
# so no separate hostname index is created.
|
|
sa.UniqueConstraint('hostname', 'queuename',
|
|
name='uq_printerobservedqueue_host_queue'),
|
|
)
|
|
# Port address is the primary match key from an observed queue back to a
|
|
# printer asset, so every comparison read hits it.
|
|
create_index_if_missing('idx_printerobservedqueues_portaddress',
|
|
'printerobservedqueues', ['portaddress'])
|
|
create_index_if_missing('idx_printerobservedqueues_assetid',
|
|
'printerobservedqueues', ['assetid'])
|
|
|
|
|
|
def downgrade():
|
|
bind = op.get_bind()
|
|
inspector = sa.inspect(bind)
|
|
if 'printerobservedqueues' not in inspector.get_table_names():
|
|
return
|
|
op.drop_index('idx_printerobservedqueues_assetid',
|
|
table_name='printerobservedqueues')
|
|
op.drop_index('idx_printerobservedqueues_portaddress',
|
|
table_name='printerobservedqueues')
|
|
op.drop_table('printerobservedqueues')
|