mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-13 08:44:51 -06:00
Merge 453ca57225
into 875a641687
This commit is contained in:
commit
5ee3afb9cd
@ -1,17 +0,0 @@
|
||||
[Unit]
|
||||
Description=NetBox Housekeeping Service
|
||||
Documentation=https://docs.netbox.dev/
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
|
||||
User=netbox
|
||||
Group=netbox
|
||||
WorkingDirectory=/opt/netbox
|
||||
|
||||
ExecStart=/opt/netbox/venv/bin/python /opt/netbox/netbox/manage.py housekeeping
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
@ -1,9 +0,0 @@
|
||||
#!/bin/sh
|
||||
# This shell script invokes NetBox's housekeeping management command, which
|
||||
# intended to be run nightly. This script can be copied into your system's
|
||||
# daily cron directory (e.g. /etc/cron.daily), or referenced directly from
|
||||
# within the cron configuration file.
|
||||
#
|
||||
# If NetBox has been installed into a nonstandard location, update the paths
|
||||
# below.
|
||||
/opt/netbox/venv/bin/python /opt/netbox/netbox/manage.py housekeeping
|
@ -1,13 +0,0 @@
|
||||
[Unit]
|
||||
Description=NetBox Housekeeping Timer
|
||||
Documentation=https://docs.netbox.dev/
|
||||
After=network-online.target
|
||||
Wants=network-online.target
|
||||
|
||||
[Timer]
|
||||
OnCalendar=daily
|
||||
AccuracySec=1h
|
||||
Persistent=true
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
@ -1,49 +0,0 @@
|
||||
# Housekeeping
|
||||
|
||||
NetBox includes a `housekeeping` management command that should be run nightly. This command handles:
|
||||
|
||||
* Clearing expired authentication sessions from the database
|
||||
* Deleting changelog records older than the configured [retention time](../configuration/miscellaneous.md#changelog_retention)
|
||||
* Deleting job result records older than the configured [retention time](../configuration/miscellaneous.md#job_retention)
|
||||
* Check for new NetBox releases (if [`RELEASE_CHECK_URL`](../configuration/miscellaneous.md#release_check_url) is set)
|
||||
|
||||
This command can be invoked directly, or by using the shell script provided at `/opt/netbox/contrib/netbox-housekeeping.sh`.
|
||||
|
||||
## Scheduling
|
||||
|
||||
### Using Cron
|
||||
|
||||
This script can be linked from your cron scheduler's daily jobs directory (e.g. `/etc/cron.daily`) or referenced directly within the cron configuration file.
|
||||
|
||||
```shell
|
||||
sudo ln -s /opt/netbox/contrib/netbox-housekeeping.sh /etc/cron.daily/netbox-housekeeping
|
||||
```
|
||||
|
||||
!!! note
|
||||
On Debian-based systems, be sure to omit the `.sh` file extension when linking to the script from within a cron directory. Otherwise, the task may not run.
|
||||
|
||||
### Using Systemd
|
||||
|
||||
First, create symbolic links for the systemd service and timer files. Link the existing service and timer files from the `/opt/netbox/contrib/` directory to the `/etc/systemd/system/` directory:
|
||||
|
||||
```bash
|
||||
sudo ln -s /opt/netbox/contrib/netbox-housekeeping.service /etc/systemd/system/netbox-housekeeping.service
|
||||
sudo ln -s /opt/netbox/contrib/netbox-housekeeping.timer /etc/systemd/system/netbox-housekeeping.timer
|
||||
```
|
||||
|
||||
Then, reload the systemd configuration and enable the timer to start automatically at boot:
|
||||
|
||||
```bash
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl enable --now netbox-housekeeping.timer
|
||||
```
|
||||
|
||||
Check the status of your timer by running:
|
||||
|
||||
```bash
|
||||
sudo systemctl list-timers --all
|
||||
```
|
||||
|
||||
This command will show a list of all timers, including your `netbox-housekeeping.timer`. Make sure the timer is active and properly scheduled.
|
||||
|
||||
That's it! Your NetBox housekeeping service is now configured to run daily using systemd.
|
@ -264,18 +264,6 @@ cd /opt/netbox/netbox
|
||||
python3 manage.py createsuperuser
|
||||
```
|
||||
|
||||
## Schedule the Housekeeping Task
|
||||
|
||||
NetBox includes a `housekeeping` management command that handles some recurring cleanup tasks, such as clearing out old sessions and expired change records. Although this command may be run manually, it is recommended to configure a scheduled job using the system's `cron` daemon or a similar utility.
|
||||
|
||||
A shell script which invokes this command is included at `contrib/netbox-housekeeping.sh`. It can be copied to or linked from your system's daily cron task directory, or included within the crontab directly. (If installing NetBox into a nonstandard path, be sure to update the system paths within this script first.)
|
||||
|
||||
```shell
|
||||
sudo ln -s /opt/netbox/contrib/netbox-housekeeping.sh /etc/cron.daily/netbox-housekeeping
|
||||
```
|
||||
|
||||
See the [housekeeping documentation](../administration/housekeeping.md) for further details.
|
||||
|
||||
## Test the Application
|
||||
|
||||
At this point, we should be able to run NetBox's development server for testing. We can check by starting a development instance locally.
|
||||
|
@ -183,13 +183,3 @@ Finally, restart the gunicorn and RQ services:
|
||||
```no-highlight
|
||||
sudo systemctl restart netbox netbox-rq
|
||||
```
|
||||
|
||||
## 6. Verify Housekeeping Scheduling
|
||||
|
||||
If upgrading from a release prior to NetBox v3.0, check that a cron task (or similar scheduled process) has been configured to run NetBox's nightly housekeeping command. A shell script which invokes this command is included at `contrib/netbox-housekeeping.sh`. It can be linked from your system's daily cron task directory, or included within the crontab directly. (If NetBox has been installed in a nonstandard path, be sure to update the system paths within this script first.)
|
||||
|
||||
```shell
|
||||
sudo ln -s /opt/netbox/contrib/netbox-housekeeping.sh /etc/cron.daily/netbox-housekeeping
|
||||
```
|
||||
|
||||
See the [housekeeping documentation](../administration/housekeeping.md) for further details.
|
||||
|
@ -434,7 +434,7 @@ A new management command has been added: `manage.py housekeeping`. This command
|
||||
* Delete change log records which have surpassed the configured retention period (if configured)
|
||||
* Check for new NetBox releases (if enabled)
|
||||
|
||||
A convenience script for calling this command via an automated scheduler has been included at `/contrib/netbox-housekeeping.sh`. Please see the [housekeeping documentation](../administration/housekeeping.md) for further details.
|
||||
A convenience script for calling this command via an automated scheduler has been included at `/contrib/netbox-housekeeping.sh`. Please see the housekeeping documentation for further details.
|
||||
|
||||
#### Custom Queue Support for Plugins ([#6651](https://github.com/netbox-community/netbox/issues/6651))
|
||||
|
||||
|
@ -158,7 +158,6 @@ nav:
|
||||
- Okta: 'administration/authentication/okta.md'
|
||||
- Permissions: 'administration/permissions.md'
|
||||
- Error Reporting: 'administration/error-reporting.md'
|
||||
- Housekeeping: 'administration/housekeeping.md'
|
||||
- Replicating NetBox: 'administration/replicating-netbox.md'
|
||||
- NetBox Shell: 'administration/netbox-shell.md'
|
||||
- Data Model:
|
||||
|
@ -1,8 +1,16 @@
|
||||
import logging
|
||||
import requests
|
||||
import sys
|
||||
from datetime import timedelta
|
||||
from importlib import import_module
|
||||
|
||||
import requests
|
||||
from django.conf import settings
|
||||
from django.core.cache import cache
|
||||
from django.utils import timezone
|
||||
from packaging import version
|
||||
|
||||
from core.models import Job, ObjectChange
|
||||
from netbox.config import Config
|
||||
from netbox.jobs import JobRunner, system_job
|
||||
from netbox.search.backends import search_backend
|
||||
from utilities.proxy import resolve_proxies
|
||||
@ -50,16 +58,23 @@ class SystemHousekeepingJob(JobRunner):
|
||||
if settings.DEBUG or 'test' in sys.argv:
|
||||
return
|
||||
|
||||
# TODO: Migrate other housekeeping functions from the `housekeeping` management command.
|
||||
self.send_census_report()
|
||||
self.clear_expired_sessions()
|
||||
self.prune_changelog()
|
||||
self.delete_expired_jobs()
|
||||
self.check_for_new_releases()
|
||||
|
||||
@staticmethod
|
||||
def send_census_report():
|
||||
"""
|
||||
Send a census report (if enabled).
|
||||
"""
|
||||
# Skip if census reporting is disabled
|
||||
if settings.ISOLATED_DEPLOYMENT or not settings.CENSUS_REPORTING_ENABLED:
|
||||
logging.info("Reporting census data...")
|
||||
if settings.ISOLATED_DEPLOYMENT:
|
||||
logging.info("ISOLATED_DEPLOYMENT is enabled; skipping")
|
||||
return
|
||||
if not settings.CENSUS_REPORTING_ENABLED:
|
||||
logging.info("CENSUS_REPORTING_ENABLED is disabled; skipping")
|
||||
return
|
||||
|
||||
census_data = {
|
||||
@ -76,3 +91,94 @@ class SystemHousekeepingJob(JobRunner):
|
||||
)
|
||||
except requests.exceptions.RequestException:
|
||||
pass
|
||||
|
||||
@staticmethod
|
||||
def clear_expired_sessions():
|
||||
"""
|
||||
Clear any expired sessions from the database.
|
||||
"""
|
||||
logging.info("Clearing expired sessions...")
|
||||
engine = import_module(settings.SESSION_ENGINE)
|
||||
try:
|
||||
engine.SessionStore.clear_expired()
|
||||
logging.info("Sessions cleared.")
|
||||
except NotImplementedError:
|
||||
logging.warning(
|
||||
f"The configured session engine ({settings.SESSION_ENGINE}) does not support "
|
||||
f"clearing sessions; skipping."
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def prune_changelog():
|
||||
"""
|
||||
Delete any ObjectChange records older than the configured changelog retention time (if any).
|
||||
"""
|
||||
logging.info("Pruning old changelog entries...")
|
||||
config = Config()
|
||||
if not config.CHANGELOG_RETENTION:
|
||||
logging.info("No retention period specified; skipping.")
|
||||
return
|
||||
|
||||
cutoff = timezone.now() - timedelta(days=config.CHANGELOG_RETENTION)
|
||||
logging.debug(f"Retention period: {config.CHANGELOG_RETENTION} days")
|
||||
logging.debug(f"Cut-off time: {cutoff}")
|
||||
|
||||
count = ObjectChange.objects.filter(time__lt=cutoff).delete()[0]
|
||||
logging.info(f"Deleted {count} expired records")
|
||||
|
||||
@staticmethod
|
||||
def delete_expired_jobs():
|
||||
"""
|
||||
Delete any jobs older than the configured retention period (if any).
|
||||
"""
|
||||
logging.info("Deleting expired jobs...")
|
||||
config = Config()
|
||||
if not config.JOB_RETENTION:
|
||||
logging.info("No retention period specified; skipping.")
|
||||
return
|
||||
|
||||
cutoff = timezone.now() - timedelta(days=config.JOB_RETENTION)
|
||||
logging.debug(f"Retention period: {config.CHANGELOG_RETENTION} days")
|
||||
logging.debug(f"Cut-off time: {cutoff}")
|
||||
|
||||
count = Job.objects.filter(created__lt=cutoff).delete()[0]
|
||||
logging.info(f"Deleted {count} expired records")
|
||||
|
||||
@staticmethod
|
||||
def check_for_new_releases():
|
||||
"""
|
||||
Check for new releases and cache the latest release.
|
||||
"""
|
||||
logging.info("Checking for new releases...")
|
||||
if settings.ISOLATED_DEPLOYMENT:
|
||||
logging.info("ISOLATED_DEPLOYMENT is enabled; skipping")
|
||||
return
|
||||
if not settings.RELEASE_CHECK_URL:
|
||||
logging.info("RELEASE_CHECK_URL is not set; skipping")
|
||||
return
|
||||
|
||||
# Fetch the latest releases
|
||||
logging.debug(f"Release check URL: {settings.RELEASE_CHECK_URL}")
|
||||
try:
|
||||
response = requests.get(
|
||||
url=settings.RELEASE_CHECK_URL,
|
||||
headers={'Accept': 'application/vnd.github.v3+json'},
|
||||
proxies=resolve_proxies(url=settings.RELEASE_CHECK_URL)
|
||||
)
|
||||
response.raise_for_status()
|
||||
except requests.exceptions.RequestException as exc:
|
||||
logging.error(f"Error fetching release: {exc}")
|
||||
return
|
||||
|
||||
# Determine the most recent stable release
|
||||
releases = []
|
||||
for release in response.json():
|
||||
if 'tag_name' not in release or release.get('devrelease') or release.get('prerelease'):
|
||||
continue
|
||||
releases.append((version.parse(release['tag_name']), release.get('html_url')))
|
||||
latest_release = max(releases)
|
||||
logging.debug(f"Found {len(response.json())} releases; {len(releases)} usable")
|
||||
logging.info(f"Latest release: {latest_release[0]}")
|
||||
|
||||
# Cache the most recent release
|
||||
cache.set('latest_release', latest_release, None)
|
||||
|
@ -14,9 +14,16 @@ from utilities.proxy import resolve_proxies
|
||||
|
||||
|
||||
class Command(BaseCommand):
|
||||
help = "Perform nightly housekeeping tasks. (This command can be run at any time.)"
|
||||
help = "Perform nightly housekeeping tasks [DEPRECATED]"
|
||||
|
||||
def handle(self, *args, **options):
|
||||
self.stdout.write(
|
||||
"Running this command is no longer necessary: All housekeeping tasks\n"
|
||||
"are addressed automatically via NetBox's built-in job scheduler. It\n"
|
||||
"will be removed in a future release.",
|
||||
self.style.WARNING
|
||||
)
|
||||
|
||||
config = Config()
|
||||
|
||||
# Clear expired authentication sessions (essentially replicating the `clearsessions` command)
|
||||
|
Loading…
Reference in New Issue
Block a user