The SLM provides some Django management commands out of the box.
Management commands are a standard way to implement routine tasks that are installable with your
site and may interface with the database using a fully bootstrapped Django stack configured for
your site.
The SLM management commands are implemented using Django Typer which extends
Django’s base command to work with the Typer CLI library. This also gives us some convenient
extra features like shell tab completions.
Most of our SLM management commands manipulate data in ways that would be difficult or too time
consuming through the web interface. We also provide some commands that perform backup and restore
operations.
We use Django Routines to provide a few named routines to execute batched groups of
commands for typical work flows that are required during installation and update deployment.
Management commands are invoked using a Django manage script. If
using startproject this script will be called manage.py. If using our
Start Project the manage script will be named after your site and indicated in the output
report. Manage scripts are typically simple and can be thought of as the main of Django. They
bootstrap the Django stack configured for your site and then run the command indicated by the CLI
arguments.
Here’s an example of a typical SLM management script:
importosimportsys# Use SLM_DEPLOYMENT environment variable to switch between deployments. In# production you may want to just set this to "production" in your# administrative user's shell profiledefmain(default_settings:str= \
f"sites.<site>.{os.environ.get('SLM_DEPLOYMENT','develop')}"):"""Run administrative tasks."""# SLM configures loggers differently when running management commands# so we can distinguish logs on the server that were from requests or# admin tasks. This environment variable is used to signal that the SLM# runtime is in management mode.iflen(sys.argv)>1andsys.argv[1]!="runserver":os.environ['SLM_MANAGEMENT_FLAG']='ON'# Django bootstraps off the settings file defined in this import path.os.environ.setdefault('DJANGO_SETTINGS_MODULE',default_settings)try:fromdjango.core.managementimportexecute_from_command_lineexceptImportErrorasexc:raiseImportError("Couldn't import Django. Are you sure it's installed and ""available on your PYTHONPATH environment variable? Did you ""forget to activate a virtual environment?")fromexcexecute_from_command_line(sys.argv)if__name__=="__main__":main()
Note
In the command helps below, replace <slm> with the name of your manage script.
Occasionally it is helpful to delete all the migration files and start anew with one
simple initial migration. Changes accumulate over time, or old migration files may
cause errors on new software stacks. This command facilitates a transition back to
one initial migration file on a version upgrade. One side effect of this is that you
may need to migrate through multiple versions instead of being able to make one big
jump. This command will check for these cases and fail if the migration from the
current software version is unsafe on the current database version.
check_upgradeUsage: <slm> check_upgrade [OPTIONS] COMMAND [ARGS]...Make sure the attempted upgrade is safe. And if it is, make anymigration table edits that are necessary.╭─ Options ─────────────────────────────────────────────────────╮│--helpShow this message and exit.│╰───────────────────────────────────────────────────────────────╯╭─ Django ──────────────────────────────────────────────────────╮│--versionShow program's version number and ││exit. ││--settingsTEXTThe Python path to a settings ││module, e.g. ││"myproject.settings.main". If this││isn't provided, the ││DJANGO_SETTINGS_MODULE environment││variable will be used. ││--pythonpathPATHA directory to add to the Python ││path, e.g. ││"/home/djangoprojects/myproject". ││[default: None] ││--tracebackRaise on CommandError exceptions││--no-colorDon't colorize the command output.││--force-colorForce colorization of the command ││output. ││--skip-checksSkip system checks.│╰───────────────────────────────────────────────────────────────╯╭─ Commands ────────────────────────────────────────────────────╮│is-safe Check that it is safe to run migrations from││the installed version of igs-slm. ││set-db-version Force the database igs-slm version to the ││installed igs-slm version or the given ││value. │╰───────────────────────────────────────────────────────────────╯
Under normal operations, each time a station’s information is published, a new point
in time index is created and logs are serialized in all of the supported formats at
that index. If for whatever reason, those logs were not generated or the indexed
archived of site logs becomes stale you may run this command to generate indexed site
log files of the specified formats.
Warning
This will not regenerate the historical index, but only files from the current
database state.
build_indexUsage: <slm> build_index [OPTIONS]Update the site index from the current data. This will generatenew serialized files for all published data that is not up to date in the index of archived site log files.╭─ Options ─────────────────────────────────────────────────────╮│--rebuildClear the existing index first. ││WARNING: cannot be undone. ││--formatFORMATOnly import any site logs of the ││specified format(s). ││[default: json, log, xml] ││--helpShow this message and exit.│╰───────────────────────────────────────────────────────────────╯╭─ Django ──────────────────────────────────────────────────────╮│--tracebackRaise on CommandError exceptions││--no-colorDon't colorize the command output.││--force-colorForce colorization of the command ││output. ││--skip-checksSkip system checks.│╰───────────────────────────────────────────────────────────────╯
Extend this command and (re)implement section producers if you want to customize sinex output.
generate_sinexUsage: <slm> generate_sinex [OPTIONS] [DESTINATION]Generate a SINEX file from sitelog data.╭─ Arguments ───────────────────────────────────────────────────╮│destination[DESTINATION]The destination to write ││the sinex file to, if none ││provided will print to ││stdout. ││[default: None] │╰───────────────────────────────────────────────────────────────╯╭─ Options ─────────────────────────────────────────────────────╮│--antex-fileTEXTThe antex file to use. ││[default: ││https://files.igs.org/pub/st…││--include-networksTXT Include all sites in the ││given networks. ││[default: None] ││--include-formerInclude former sites in the ││list. ││--utf8Allow multi-byte UTF-8 ││characters in the output. ││--creatorTEXTThe creating agency short ││name. ││[default: SLM] ││--originTEXTThe originating agency short ││name. ││[default: SLM] ││--helpShow this message and exit.│╰───────────────────────────────────────────────────────────────╯╭─ Django ──────────────────────────────────────────────────────╮│--tracebackRaise on CommandError exceptions││--no-colorDon't colorize the command output.││--force-colorForce colorization of the command ││output. │╰───────────────────────────────────────────────────────────────╯
If your site log file index is more current than the database state
(i.e. you’ve run import_archive), you may run this command to pull data
from the most recent indexed files into the database.
Tip
By default, rich HTML logs of the import process will be written to:
settings.SLM_LOG_DIR/head_from_index.TIMESTAMP
ImportAlerts will also be issued for any errors flagged during import. When,
appropriate validation flags will be attached to site log fields. This allows you
to manually clean up any import errors through the web interface after the process
completes.
head_from_indexUsage: <slm> head_from_index [OPTIONS] [SITES]...Update the head state of each site from the most recent index.╭─ Arguments ───────────────────────────────────────────────────╮│sites[SITES]...The sites (by name) to update. (all ││active sites by default) ││[default: None] │╰───────────────────────────────────────────────────────────────╯╭─ Options ─────────────────────────────────────────────────────╮│--no-promptDo not ask before proceeding.││--logsPATH Write logs to this directory. No ││logs will be written by default. ││[default: ││{SLM_LOG_DIR}/head_from_index.{TI…││--formatFORMATOnly import state from these ││specified format(s) (in preference││order). ││[default: log] ││--helpShow this message and exit.│╰───────────────────────────────────────────────────────────────╯╭─ Django ──────────────────────────────────────────────────────╮│--verbosityINTEGER RANGE Verbosity level; ││[0<=x<=3]0=minimal output, ││1=normal output, ││2=verbose output, ││3=very verbose ││output ││[default: 1] ││--tracebackRaise on ││CommandError ││exceptions ││--no-colorDon't colorize the ││command output. ││--force-colorForce colorization ││of the command ││output. ││--skip-checksSkip system checks.│╰───────────────────────────────────────────────────────────────╯
When transitioning site log management into an SLM you will have to import all of the
existing data. There are two primary steps involved in doing this:
Import the index of existing serialized point in time site logs.
Populate the site log fields in the database from the most recent site logs for each
station.
This command will perform #1 and optionally call head_from_index on the
imported stations to also perform #2.
Tip
Rich HTML logs of the import process will be written to:
settings.SLM_LOG_DIR/import_archive.TIMESTAMP
Logs will be parsed and errors reported, but parsing errors will not prevent logs from
being indexed.
Warning
If timestamps cannot be determined for files they will not be indexed
because each entry in the file index requires a begin and end time.
import_archiveUsage: <slm> import_archive [OPTIONS] [ARCHIVE]Import an archive of old site logs - creating indexes and optionally importing the latest file information into the database.╭─ Arguments ───────────────────────────────────────────────────╮│archive[ARCHIVE]The path to the archive containing ││the legacy site logs to import. May││be a tar file, a directory or a ││single site log. ││[default: None] │╰───────────────────────────────────────────────────────────────╯╭─ Options ─────────────────────────────────────────────────────╮│--no-create-sitesDo not create sites if they ││do not already exist in the ││database. ││--set-statusSTATUSSet this status as the site ││status for imported sites. ││[default: None] ││--no-update-headFor all indexes added at the││head index for each site, ││import that site log data ││into the database. ││--agencyTXT Assign all sites to this ││agency or these agencies. ││--ownerEMAIL Assign all sites to this ││owner. ││[default: None] ││--logsPATH Write parser logs to this ││directory. ││[default: ││{SLM_LOG_DIR}/import_archiv…││--formatFORMATOnly import any site logs of││the specified format(s). ││[default: json, log, xml] ││--site-dirsInterpret the directories ││containing the logs as the ││site names. ││--helpShow this message and exit.│╰───────────────────────────────────────────────────────────────╯╭─ Django ──────────────────────────────────────────────────────╮│--verbosityINTEGER RANGE Verbosity level; ││[0<=x<=3]0=minimal output, ││1=normal output, ││2=verbose output, ││3=very verbose ││output ││[default: 1] ││--tracebackRaise on ││CommandError ││exceptions ││--no-colorDon't colorize the ││command output. ││--force-colorForce colorization ││of the command ││output. ││--skip-checksSkip system checks.│╰───────────────────────────────────────────────────────────────╯
Station equipment including Antennas, Radomes and Receivers are coded by IGS and
those standard codes are used to uniquely identify equipment in site log files.
The full IGS change log for equipment codes is recorded in rcvr_ant.tab.
The SLM stores these codes in database tables, so it is possible to instantiate an
SLM with a different set of equipment codes. This command can be used to load codes
from another SLM or from the IGS by default:
import_equipment can be run routinely to synchronize with upstream equipment
sources. No equipment will be removed if any site logs reference it in the database.
import_equipmentUsage: <slm> import_equipment [OPTIONS] COMMAND1 [ARGS]... [COMMAND2 [ARGS]...]...Import equipment (Antennas, Receivers and Radomes). Imports aremade from the IGS public network API by default. You may periodically run this to synchronize with external equipment sources. These codings are used to standardize references to equipment in site logs. For a full change log of equipment encodings used by IGS, see: https://files.igs.org/pub/station/general/rcvr_ant.tab ╭─ Options ─────────────────────────────────────────────────────╮│--removeRemove any equipment from the ││database not present in ││sources. ││--no-synchronizeDo not synchronize ancillary ││equipment meta data with ││source(s). ││[default: True] ││--slmTEXT The url to the SLM to pull ││equipment data from (if ││different than source ││defaults). ││[default: ││https://network.igs.org] ││--stateSTATEOnly import equipment from ││these specified state(s). ││[default: ACTIVE] ││--helpShow this message and exit. │╰───────────────────────────────────────────────────────────────╯╭─ Django ──────────────────────────────────────────────────────╮│--tracebackRaise on CommandError exceptions ││--no-colorDon't colorize the command output. ││--force-colorForce colorization of the command ││output. ││--skip-checksSkip system checks. │╰───────────────────────────────────────────────────────────────╯╭─ Commands ────────────────────────────────────────────────────╮│manufacturers Import manufacturers. ││antennas Import antennas. ││receivers Import receivers. ││radomes Import radomes. │╰───────────────────────────────────────────────────────────────╯
The Django Sites framework
is used by the SLM and SLM extensions to store information about the organization name and
domain name being served by the current instance. This command populates that information
from SLM specific settings:
SLM_SITE_NAME
SLM_ORG_NAME
Note
The sites framework is typically used to support serving multiple domains off the same
software stack. In our experience it is usually preferable to serve separate domains
off customized software stacks because their requirements may differ substantially.
For example network.igs.org and slm.igs.org are both instances of the SLM with
different configurations.
set_siteUsage: <slm> set_site [OPTIONS]Set the Django Site database object to reflect SLM_SITE_NAME and SLM_ORG_NAME in settings.╭─ Options ─────────────────────────────────────────────────────╮│--helpShow this message and exit.│╰───────────────────────────────────────────────────────────────╯╭─ Django ──────────────────────────────────────────────────────╮│--tracebackRaise on CommandError exceptions││--no-colorDon't colorize the command output.││--force-colorForce colorization of the command ││output. │╰───────────────────────────────────────────────────────────────╯
Generate a serialized site log of the given format for a station’s published or
unpublished head state. Optionally the file will be pulled from the index of archived
site log files.
It is usually more convenient to go through the web interface if you just want to view
a sitelog, but this command can be useful for entering into the debugger to troubleshoot
parts of this pipeline.
sitelogUsage: <slm> sitelog [OPTIONS] SITE COMMAND [ARGS]...Generate a site log in the specified format for the specified site and print it to stdout. Optionally pull the log from the archive or regenerate it based on given parameters.╭─ Arguments ───────────────────────────────────────────────────╮│*siteTXTThe name of the site.[default: None]││[required] │╰───────────────────────────────────────────────────────────────╯╭─ Options ─────────────────────────────────────────────────────╮│--headGenerate the log from ││the head edits ││(unpublished). ││--archive[%Y-%m-%d|%Y-%m-%dT%Pull from archive ││H:%M:%S|%Y-%m-%d rather than ││%H:%M:%S]generating. ││[default: None] ││--helpShow this message and ││exit. │╰───────────────────────────────────────────────────────────────╯╭─ Django ──────────────────────────────────────────────────────╮│--tracebackRaise on CommandError exceptions││--no-colorDon't colorize the command output.││--force-colorForce colorization of the command ││output. │╰───────────────────────────────────────────────────────────────╯╭─ Commands ────────────────────────────────────────────────────╮│legacy ││xml │╰───────────────────────────────────────────────────────────────╯
<slm> sitelog legacyUsage: SITE <slm> sitelog legacy [OPTIONS]╭─ Options ─────────────────────────────────────────────────────╮│--helpShow this message and exit.│╰───────────────────────────────────────────────────────────────╯
<slm> sitelog xmlUsage: SITE <slm> sitelog xml [OPTIONS]╭─ Options ─────────────────────────────────────────────────────╮│--versionVERSIONThe Geodesy ML version. (0.4, 0.5)││[default: None] ││--helpShow this message and exit.│╰───────────────────────────────────────────────────────────────╯
To keep the SLM APIs performant some database state is
denormalized. In normal
operations this state is synchronized when it needs to be, but if for
whatever reason the denormalized state becomes unsynchronized, this command
can be manually invoked to force synchronization.
Some examples of denormalized state in the SLM include:
Counts of validation flags
Maximum alert levels for stations
Site log status indicators (PUBLISHED/UNPUBLISHED) for stations.
synchronizeUsage: <slm> synchronize [OPTIONS] [SITES]...Synchronize all denormalized data - that is data that is cachedfor performance reasons that may become out of sync if updates are performed outside of normal request/response cycles.╭─ Arguments ───────────────────────────────────────────────────╮│sites[SITES]...The station(s) to synchronize, if ││unspecified, synchronize all of ││them. ││[default: None] │╰───────────────────────────────────────────────────────────────╯╭─ Options ─────────────────────────────────────────────────────╮│--helpShow this message and exit.│╰───────────────────────────────────────────────────────────────╯╭─ Django ──────────────────────────────────────────────────────╮│--tracebackRaise on CommandError exceptions││--no-colorDon't colorize the command output.││--force-colorForce colorization of the command ││output. ││--skip-checksSkip system checks.│╰───────────────────────────────────────────────────────────────╯
The SLM supports pluggable validation logic for all site log sections and fields. Since
this logic is configuration specific, it may change, diverging from the validation flags
recorded against the previous validation configuration in the database.
Run this command to run all validation routines against all current site log fields
in the database.
validate_dbUsage: <slm> validate_db [OPTIONS] [SITES]...Validate and update status of head state of all existing site logs. This might be necessary to run if the validation configuration is updated.╭─ Arguments ───────────────────────────────────────────────────╮│sites[SITES]...The name of the site(s). Default - ││all sites. ││[default: None] │╰───────────────────────────────────────────────────────────────╯╭─ Options ─────────────────────────────────────────────────────╮│--clearClear existing validation flags.││--schemaAlso perform validation of generated ││GeodesyML files against the latest schema. ││--allValidate all sites, not just the currently ││public sites. ││--helpShow this message and exit.│╰───────────────────────────────────────────────────────────────╯╭─ Django ──────────────────────────────────────────────────────╮│--tracebackRaise on CommandError exceptions││--no-colorDon't colorize the command output.││--force-colorForce colorization of the command ││output. ││--skip-checksSkip system checks.│╰───────────────────────────────────────────────────────────────╯
Routines are groupings of commands that can be configured in settings and run together.
They are defined using the app django-routines. The commands that are run as part of a routine
can be added to or subtracted from in customized deployments of the SLM. Out of the box the
SLM provides the following routines:
The deploy routine includes a collection of commands that should be run each time an updated
version of the SLM code base is deployed on a system. These commands will do things
like bring the database structure into compliance with the code base, render any static
artifacts and copy those artifacts to where the web server expects.
Warning
deploy does not run makemigrations because these files should be checked into version
control and we do not want to accidentally generate files and apply them to the database in
production. This would likely cause conflicting migration files to be generated in development
and production.
migrate will warn if the code is out of sync with the database structure. And you should
always run makemigrations before packaging a new version of your software for deployment.
If the SLM validation configuration has changed you will likely want to run deploy with the
--re-validate flag to run the updated routines:
<slm>routinedeploy--re-validate
You may also wish to not re-validate everything and instead let the new validation routines
be run each time a stations data is updated.
<slm> routine deployUsage: <slm> routine deploy [OPTIONS] COMMAND [ARGS]...Run collection of commands that likely need to be run whenever code is updated.[0] check --deploy[0] shellcompletion install | initial[11] migrate[20] renderstatic[21] collectstatic --no-input[23] set_site[30] validate_db --schema | re-validate[32] synchronize | re-validate╭─ Options ─────────────────────────────────────────────────────╮│--subprocessRun commands as subprocesses.││--atomicRun all commands in the same ││transaction. ││--continueContinue through the routine if any ││commands fail. ││--allInclude all switched commands.││--initial││--re-validate││--helpShow this message and exit.│╰───────────────────────────────────────────────────────────────╯╭─ Commands ────────────────────────────────────────────────────╮│list List the commands that will be run. │╰───────────────────────────────────────────────────────────────╯
The import routine runs a collection of data import commands you will likely need to run when
importing an archive of old site logs.
These commands will import the serialized site logs and attempt to read the data out of those
logs and store them in the database.
Note
This import process will import equipment codes from the IGS. You will also be prompted for
a path to an archive of historical site logs (either a directory or tar file).
If you need a more bespoke import process you should run each of these import routines
separately with customized parameters.
<slm> routine importUsage: <slm> routine import [OPTIONS] COMMAND [ARGS]...Import equipment from the IGS and site log data from your own archive.[10] import_equipment antennas radomes receivers[20] import_archive[30] validate_db --schema╭─ Options ─────────────────────────────────────────────────────╮│--subprocessRun commands as subprocesses.││--atomicRun all commands in the same ││transaction. ││--continueContinue through the routine if any ││commands fail. ││--allInclude all switched commands.││--helpShow this message and exit.│╰───────────────────────────────────────────────────────────────╯╭─ Commands ────────────────────────────────────────────────────╮│list List the commands that will be run. │╰───────────────────────────────────────────────────────────────╯
The install routine runs the initial routinedeploy routine as well as the
routineimport routine. In addition it asks you to create a superuser account.
Run this routine on a fresh database if you have a bunch of site logs to import.
<slm> routine installUsage: <slm> routine install [OPTIONS] COMMAND [ARGS]...Install a fresh deployment of the SLM and import data from external sources.[0] routine deploy --initial[10] createsuperuser[20] routine import╭─ Options ─────────────────────────────────────────────────────╮│--subprocessRun commands as subprocesses.││--atomicRun all commands in the same ││transaction. ││--continueContinue through the routine if any ││commands fail. ││--allInclude all switched commands.││--helpShow this message and exit.│╰───────────────────────────────────────────────────────────────╯╭─ Commands ────────────────────────────────────────────────────╮│list List the commands that will be run. │╰───────────────────────────────────────────────────────────────╯