scripts: reclassify server 'computer' assets to network_device
Servers were imported as computers (a PC type) so they show under PCs, not Network. This one-shot re-points each server's asset in place - assetid is unchanged, so comms/relationships/map/name/location/audit all carry over; only the extension row is swapped (computers -> networkdevices), the asset type is flipped, and the device gets the 'Server' networkdevicetype (created if absent). Identify servers by their computer type name (--type, default 'Server'). Dry-run by default; --commit applies. Run on the target instance.
This commit is contained in:
101
scripts/reclassify_servers_to_network.py
Normal file
101
scripts/reclassify_servers_to_network.py
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
"""Reclassify server 'computer' assets into 'network_device' assets.
|
||||||
|
|
||||||
|
Servers were imported as computers (a PC type), so they show under PCs instead
|
||||||
|
of Network. This re-points each server's asset in place - the assetid does NOT
|
||||||
|
change, so its communications, relationships, map position, name, location, and
|
||||||
|
audit history all carry over. Only the extension row is swapped (computers ->
|
||||||
|
networkdevices) and the asset's type is flipped, and the network device is given
|
||||||
|
the 'Server' networkdevicetype.
|
||||||
|
|
||||||
|
Identify servers by their computer type name (default 'Server'); pass --type to
|
||||||
|
match a different one.
|
||||||
|
|
||||||
|
Usage (on the target instance, in the app dir):
|
||||||
|
DATABASE_URL=... venv/bin/python scripts/reclassify_servers_to_network.py # dry run
|
||||||
|
DATABASE_URL=... venv/bin/python scripts/reclassify_servers_to_network.py --commit # apply
|
||||||
|
... --type "Server" --commit
|
||||||
|
"""
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
|
||||||
|
# Run from anywhere: put the repo root (parent of scripts/) on the path.
|
||||||
|
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||||
|
|
||||||
|
from shopdb import create_app
|
||||||
|
from shopdb.api import db
|
||||||
|
from shopdb.core.models import Asset, AssetType
|
||||||
|
from plugins.computers.models import Computer, ComputerType
|
||||||
|
from plugins.network.models import NetworkDevice, NetworkDeviceType
|
||||||
|
|
||||||
|
|
||||||
|
def _get_or_create_networkdevicetype(name):
|
||||||
|
ndt = NetworkDeviceType.query.filter_by(networkdevicetype=name).first()
|
||||||
|
if not ndt:
|
||||||
|
ndt = NetworkDeviceType(networkdevicetype=name,
|
||||||
|
description='Server (reclassified from PCs)')
|
||||||
|
db.session.add(ndt)
|
||||||
|
db.session.flush()
|
||||||
|
return ndt
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument('--type', default='Server',
|
||||||
|
help="computer type name that holds the servers (default 'Server')")
|
||||||
|
parser.add_argument('--commit', action='store_true',
|
||||||
|
help='apply the change; without it this is a dry run')
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
app = create_app()
|
||||||
|
with app.app_context():
|
||||||
|
nd_assettype = AssetType.query.filter_by(assettype='network_device').first()
|
||||||
|
if not nd_assettype:
|
||||||
|
sys.exit("No 'network_device' asset type - is the network plugin installed?")
|
||||||
|
|
||||||
|
ctype = ComputerType.query.filter_by(computertype=args.type).first()
|
||||||
|
if not ctype:
|
||||||
|
sys.exit("No computer type named %r. Pass --type with the exact name."
|
||||||
|
% args.type)
|
||||||
|
|
||||||
|
servers = (Computer.query
|
||||||
|
.filter(Computer.computertypeid == ctype.computertypeid)
|
||||||
|
.all())
|
||||||
|
if not servers:
|
||||||
|
print("No computers under type %r - nothing to do." % args.type)
|
||||||
|
return
|
||||||
|
|
||||||
|
ndt = _get_or_create_networkdevicetype('Server')
|
||||||
|
print("%d server(s) under computer type %r -> network_device / type 'Server':"
|
||||||
|
% (len(servers), args.type))
|
||||||
|
|
||||||
|
moved = 0
|
||||||
|
for computer in servers:
|
||||||
|
asset = computer.asset
|
||||||
|
if not asset:
|
||||||
|
continue
|
||||||
|
label = asset.name or asset.assetnumber or ('asset %d' % asset.assetid)
|
||||||
|
print(" - %s (assetid %d)" % (label, asset.assetid))
|
||||||
|
if args.commit:
|
||||||
|
# Swap extension: create the network device on the SAME asset,
|
||||||
|
# re-point the asset's type, then drop the computer extension.
|
||||||
|
asset.assettypeid = nd_assettype.assettypeid
|
||||||
|
db.session.add(NetworkDevice(
|
||||||
|
assetid=asset.assetid,
|
||||||
|
networkdevicetypeid=ndt.networkdevicetypeid,
|
||||||
|
hostname=getattr(computer, 'hostname', None),
|
||||||
|
vendorid=getattr(computer, 'vendorid', None),
|
||||||
|
))
|
||||||
|
db.session.delete(computer) # asset stays (FK cascade is asset->computer)
|
||||||
|
moved += 1
|
||||||
|
|
||||||
|
if args.commit:
|
||||||
|
db.session.commit()
|
||||||
|
print("\nDone: %d reclassified. They now appear under Network." % moved)
|
||||||
|
else:
|
||||||
|
print("\nDRY RUN - nothing changed. Re-run with --commit to apply.")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
Reference in New Issue
Block a user