Migrating Jobs from Nautobot v1.X to Nautobot v2.0¶
Quick Summary of Job Class Changes¶
self.run(self, data, commit)
must be changed to include all Job variablesself.test_*
andself.post_run()
methods were removedread_only
no longer changes the behavior of Nautobot coreself.job_result
should no longer be modified or saved from within a Job- Jobs must be registered in the celery task registry
self.failed
removed- The job logging methods have been renamed and their signature changed
- The
request
property has been changed to a celery request instead of a Django request
Overview¶
Some fundamental changes were made to Jobs in Nautobot v2.0. This document outlines the changes that were made and how to migrate your existing Jobs to work in Nautobot v2.0. For more information about the changes made to the Job class and Job model in Nautobot v2.0 see the Upgrading From Nautobot v1 documentation.
Job Package Names¶
All Jobs are now imported as normal Python packages, instead of virtually imported, which means that Job file code can be shared with other Jobs or Python modules.
App Provided Jobs¶
The package name for Jobs provided by Nautobot Apps has not changed.
Jobs in JOBS_ROOT
¶
All Python modules in JOBS_ROOT
will be imported when loading Jobs. The package name for Jobs in JOBS_ROOT
will be <job_file>
, where <job_file>
is the name of the Job file without the .py
extension. If desired, submodules may be used in JOBS_ROOT
like any normal Python package. For example, a Job class called AddJob
in $JOBS_ROOT/my_jobs/math.py
would be imported as my_jobs.math.AddJob
.
Caution
Take care to avoid naming collisions with existing Python packages when naming Job files in JOBS_ROOT
.
Git Repository Jobs¶
The package name for Jobs provided by Git Repositories has changed to <git_repository_slug>.jobs
, where <git_repository_slug>
is the slug of the Git Repository as provided by the user when creating the Git Repository object in Nautobot. All jobs provided by Git Repositories must use the .jobs
submodule of the Git Repository.
Important
As a result of the changes to the way jobs are imported the top-level directory of any Git Repository that provides Jobs must now contain an __init__.py
file.
Run Method Signature¶
The signature of the run()
method for Jobs must now accept keyword arguments for every Job variable defined on the Job class. The run()
method no longer uses the data
and commit
arguments used in v1.X.
Example
test_*
and post_run()
Methods¶
The test_*
and post_run
methods, previously provided for backwards compatibility to NetBox scripts and reports, have been removed. Celery implements before_start
, on_success
, on_retry
, on_failure
, and after_return
methods that can be used by Job authors to perform similar functions.
Important
Be sure to call the super()
method when overloading any of the job's before_start
, on_success
, on_retry
, on_failure
, or after_return
methods
Database Transaction Handling¶
Jobs no longer run in a single atomic database transaction by default. If a Job needs to run in a database transaction, you can use the @transaction.atomic
decorator on the run()
method or wrap parts of your Job code in the with transaction.atomic()
context manager.
Example
from django.db import transaction
from nautobot.apps.jobs import Job, ObjectVar
from nautobot.dcim import models
class UpdateDeviceTypeHeightJob(Job):
device_type = ObjectVar(model=models.DeviceType)
u_height = IntegerVar(label="New Height (U)")
@transaction.atomic
def run(self, device_type, u_height):
device_type.u_height = u_height
device_type.save()
Commit Argument¶
As a result of the default database transaction being removed from Nautobot core, the commit
argument has been removed. If a Job author wants to provide users the ability to bypass approval when approval_required
is set, the Job must implement a dryrun
variable using the newly-introduced DryRunVar
. The desired value of the variable will be passed to the run
method just like any other variable, but the Job author must implement the logic to handle the dry run.
The presence of a dryrun = DryRunVar()
property on the Job class sets the supports_dryrun
flag on the Job model, which allows users to bypass approval when approval_required
is set. To implement a dry run variable without allowing users to bypass approval, the dryrun
variable should use the BooleanVar
class instead of DryRunVar
.
The Job commit_default
property has been renamed to dryrun_default
and the default value as well as any existing database values have been flipped.
Read-Only Meta Attribute¶
The read_only
Job field no longer forces an automatic database rollback at the end of the Job; it is informational only in v2.0.
Job Registration¶
Changed in version 2.0.0
All Job classes, including JobHookReceiver
and JobButtonReceiver
classes must be registered at import time using the nautobot.apps.jobs.register_jobs
method. This method accepts one or more job classes as arguments. You must account for how your jobs are imported when deciding where to call this method.
Registering Jobs in JOBS_ROOT or Git Repositories¶
Only top level module names within JOBS_ROOT are imported by Nautobot at runtime. This means that if you're using submodules, you need to ensure that your jobs are either registered in your top level __init__.py
or that this file imports your submodules where the jobs are registered:
from nautobot.apps.jobs import Job, register_jobs
class MyJob(Job):
...
register_jobs(MyJob)
Similarly, only the jobs
module is loaded from Git repositories. If you're using submodules, you need to ensure that your jobs are either registered in the repository's jobs/__init__.py
or that this file imports your submodules where the jobs are registered.
If not using submodules, you should register your job in the file where your job is defined.
Registering Jobs in an App¶
Apps should register jobs in the module defined in their NautobotAppConfig.jobs
property. This defaults to the jobs
module of the App.
Job Logging¶
All of the custom log
methods have been removed from the Job class. Instead, use either the Python logger from nautobot.extras.jobs.get_task_logger
or use self.logger
in the Job class.
The following table describes the mapping of the old log methods to the new methods:
Old Method | New Method |
---|---|
self.log_debug |
self.logger.debug |
self.log_info |
self.logger.info |
self.log_success |
self.logger.info |
self.log_warning |
self.logger.warning |
self.log_failure |
self.logger.error |
self.log |
self.logger.info |
No equivalent | self.logger.critical |
Some logging features from v1.X are accessible when passing a dict
to the extra
kwarg in any logger method:
logger.debug("message", extra={"skip_db_logging": True})
- Log the message to the console but not to the databaselogger.debug("message", extra={"object": obj})
- Replaces theobj
kwarg in Nautobot v1.X Job logging methodslogger.debug("message", extra={"grouping": "string"})
- Replaces theactive_test
Job property in Nautobot v1.X
For more detailed documentation on Job logging see the Job Logging section of the Jobs feature documentation.
Tracking Job State¶
JobResult.status
is now automatically tracked by Celery. Job authors should no longer manually change self.job_result.status
or self.job_result.completed
and should instead raise an exception if the Job status should be set to failed (the failed status is now "FAILURE"
).
The Job's built-inself.failed
flag, that was used to determine if a Job failed, has been removed. This flag was previously set to True
automatically when the log_failure
method was called. Job authors should track their Job's internal state and raise an exception to fail the Job when desired.
Request Property¶
The request
property has been changed to a Celery request instead of a Django request and no longer includes the information from the web request that initiated the Job. The user
object is now available as self.user
instead of self.request.user
.
Note: Migrating from v1.x to v2.0 provides a general migration guide.