Initializing and Restoring: Difference between revisions

From Obsidian Scheduler
Jump to navigationJump to search
Created page with "'''As of Obsidian 3.0.0''' At times, you may wish to automate initialization or even restoration of an Obsidian configuration. For example, you may wish to take a known good c..."
 
No edit summary
 
(64 intermediate revisions by 2 users not shown)
Line 1: Line 1:
'''As of Obsidian 3.0.0'''
At times, you may wish to perform initialization, backup or restoration of an Obsidian installation. For example, you may wish to take a known good configuration from a development environment and apply it to a test environment.  
At times, you may wish to automate initialization or even restoration of an Obsidian configuration. For example, you may wish to take a known good configuration from a development environment and apply it to a test environment.  


In Obsidian 3.0.0, we introduce an expansion of our [[Implementing_Jobs#Initializing_Job_Schedules | Initializing Job Schedules]] support that leverages the system restore functionality of our API.
As of Obsidian 6.3.0, we introduce support for [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/job/SchedulableJob.Initializable.html annotation based initialization] that leverages our [[Implementing_Jobs#Classpath_Scanning|classpath scanning]].


By default, Obsidian will look for a file on the classpath named /obsidianInitialization.json. You may override the classpath resource name using the system property obsidianInitClasspath. For example, you could add the java system property -DobsidianInitClasspath=/com/mycompany/obsidianInit.json. You can also use a file-based resource by using the system property obsidianInitFile. For example, you could add the java system property -DobsidianInitFile=/var/obsidian/obsidianScheduleInitialization.json.
In Obsidian 3.0.0, we introduce support that leverages the [[Embedded_API#SystemRestoreManager_API|System Restore]] functionality of our API. Both the [[Embedded_API|Embedded API]] and [[REST_API|REST API]] expose functions for retrieving and updating the full configuration for an Obsidian installation. Rather than require you to individually retrieve all the configuration items and then apply them elsewhere, a full JSON snapshot can be generated and imported, allowing for easy backups and restores.


Note: Initialization only runs on scheduler instances. This means that a standalone Obsidian web application with no scheduler running will not do any initialization based on the presence of the appropriate JSON file.
== Uses ==
 
=== Annotation Initialization ===
''As of Obsidian 6.3.0''
 
Job configuration can be automated into target environments via via annotations and [[Implementing_Jobs#Classpath_Scanning|classpath scanning]]. The base annotation to configure a job is [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/job/SchedulableJob.Initializable.html Initializable]. It is a [https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/annotation/Repeatable.html @Repeatable] annotation. On every startup, the nickname in the annotation is used to determine if that job <code>Initializable</code> reference has been initialized before, either via annotation, API or UI. Any nickname conflict will prevent initialization. Initialization is best effort per annotation, with errors logged and event notifications dispatched.
 
Chains can be initialized via [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/job/SchedulableJob.InitializableChainAnnotation.html InitializableChainAnnotation] using nicknames. It is also a [https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/annotation/Repeatable.html @Repeatable] annotation. Descriptions along with source and target job are used to determine if the chain has been initialized previously, since source/target pairs can be repeated with different setups. Conditional chaining can be done via [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/job/SchedulableJob.InitializableChainConditionAnnotation.html InitializableChainConditionAnnotation]. Again, it is a [https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/annotation/Repeatable.html @Repeatable] annotation.
 
=== Backup or Export ===
Use the System Restore [[REST_Endpoints#GET_a_system_restore_configuration|GET REST endpoint]] or the [[Embedded_API#Get_System_Restore_Configuration|equivalent Embedded API]] to retrieve a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/system/restore/SystemRestoreConfiguration.html SystemRestoreConfiguration]. Store the JSON representation in your backup media.
 
=== Transfer or Restore a Configuration ===
Follow the [[Initializing_and_Restoring#Backup_or_Export|Backup]] instructions. Then, using the backup JSON, you can either place it on the file-system/classpath as described in [[#Startup_Initialization|Startup Initialization]], or use it in conjunction with the System Restore [[REST_Endpoints#PUT_a_system_restore_configuration|PUT REST endpoint]] or [[Embedded_API#Update_System_Restore_Configuration|equivalent Embedded API]].
 
You may choose to update parts of the exported configuration depending on your needs, or to set new user passwords.
 
'''Note:''' Users do not include the current passwords since they cannot be determined, and also as a security measure. All users will be returned with the password "changeme".
 
=== Startup Initialization ===
By default, Obsidian will look for a file on the classpath named <code>/obsidianInitialization.json</code> containing configuration data in the format described in [[#JSON_Configuration_Format|JSON Configuration Format]].
 
You may override the classpath resource name using the system property <code>obsidianInitClasspath</code>. For example, you could add the java system property <code>-DobsidianInitClasspath=/com/mycompany/obsidianInit.json</code>. You can also use a file-based resource by using the system property <code>obsidianInitFile</code>. For example, you could add the java system property <code>-DobsidianInitFile=/var/obsidian-3.0.0/obsidianScheduleInitialization.json</code>.
 
'''Note:''' Initialization only runs on scheduler instances. This means that a standalone Obsidian web application with no scheduler running will not do any initialization based on the presence of the appropriate JSON file.
 
== JSON Configuration Format ==
The file format is a JSON serialized version of the [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/system/restore/SystemRestoreConfiguration.html SystemRestoreConfiguration] class. Here we will define each configuration item and any special conditions associated with each one. A sample JSON is [[#Sample|provided]].
 
=== Jobs ===
The <code>jobs</code> key has a list of [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/system/restore/JobSaveRequest.html JobSaveRequest] objects. Each of these represents a configured job in Obsidian. This JobSaveRequest is very much like a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/JobCreationRequest.html JobCreationRequest] but having two extra attributes to handle the case where a job with the same nickname already exists. The <code>updateAttributes</code> flag is used to determine whether the job attributes (jobClass, recoveryType, pickupBufferMinutes, etc.) will be updated when the job exists. The <code>updateSchedule</code> flag is used to determine whether to apply the current schedule and any additional <code>jobSchedules</code> when the job already exists. If any of the schedules' end dates are in the past, they will be skipped.
 
=== Job Chains ===
The <code>chains</code> key is a [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/system/restore/ChainsRequest.html ChainsRequest] that houses a collection of chain configurations and a <code>replaceAll</code> attribute. The replaceAll attribute is used when chains already exist in the system. If chains exist and the flag is not set to true, the existing chains are left as is. If set to true, all existing chains are deleted and the new set of chains are created.
 
=== Job Conflicts ===
The <code>conflicts</code> key is similar to the [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/ConflictUpdateRequest.html ConflictUpdateRequest] but it uses job nicknames instead of job IDs. If an empty list is supplied, all chains will be deleted. Note that this is different from a null or missing value.
 
=== Users ===
The <code>users</code> key has a list of [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/system/restore/UserSaveRequest.html UserSaveRequest] objects. These are similar to the standard [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/user/UserCreationRequest.html UserCreationRequest], but they contain an <code>update</code> attribute that is used when the user already exists. If the same user name exists and the flag is not set to true, the user is left as is. Otherwise, the user is created or updated as the case dictates.
 
=== Global Parameters ===
The <code>globalParameters</code> key is a list of [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/job/GlobalParameter.html GlobalParameter] objects that are to be set into the system. Any current global parameters are either deleted or overridden.
 
=== Custom Calendars ===
The <code>customCalendars</code> key is a list of [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/calendar/CustomCalendarUpdateRequest.html CustomCalendarUpdateRequest] objects. Creates or updates as the case dictates by matching on the name.
 
=== System Parameters ===
The <code>systemParameters</code> key is a list of [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/system/SystemParameter.html SystemParameter] objects. Updates all parameters given.
 
=== Subscribers ===
The <code>subscribers</code> key is a list of [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/system/restore/SubscriberSaveRequest.html SubscriberSaveRequest] objects. Creates or updates as the case dictates by matching on the email address.
 
=== Templates ===
The <code>templates</code> key is a list of [https://web.obsidianscheduler.com/obsidianapi/com/carfey/ops/api/bean/system/restore/TemplateSaveRequest.html TemplateSaveRequest] objects. Creates or updates as the case dictates by matching on the name.
 
== Sample ==
 
<pre>
{
  "jobs": [
      {
        "updateSchedule": false,
        "updateAttributes": false,
        "jobSchedules": [
            {
              "state": "DISABLED",
              "effectiveDate": "2015-03-20T10:35:00-0700",
              "endDate": "2999-12-31T23:59:00-0800"
            }
        ],
        "jobClass": "com.carfey.ops.job.maint.LogCleanupJob",
        "minExecutionDuration": "2s",
        "maxExecutionDuration": "3s",
        "nickname": "Log Cleanup",
        "pickupBufferMinutes": 2,
        "recoveryType": "NONE",
        "hosts": [ "Demo-PC" ],
        "ordinalParameters": [ // as of 3.8.0, prior to 3.8.0, this was simply the child element "parameters"
          "ordinal": 0, // as of 3.8.0
          "parameters": [
              {
                "name": "level",
                "type": "STRING",
                "value": "ALL"
              },
              {
                "name": "maxAgeDays",
                "type": "INTEGER",
                "value": "120"
              }
          ]
        ],
        "chainAll": false,
        "hostPreference": true,
        "autoRetryCount": 0,
        "autoRetryInterval": 0,
        "autoRetryIntervalExponent": false,
        "state": "ENABLED",
        "schedule": "* * * * *",
        "effectiveDate": "2015-01-01T00:00:00-0700"
        "endDate": "2015-03-20T10:34:00-0700"
      },
      {
        "updateSchedule": false,
        "updateAttributes": false,
        "jobSchedules": [],
        "jobClass": "com.carfey.ops.job.script.GroovyJob",
        "nickname": "Script Job",
        "pickupBufferMinutes": 2,
        "recoveryType": "NONE",
        "hosts": [],
        "ordinalParameters": [
          "ordinal": 0,
          "parameters": [
              {
                "name": "script",
                "type": "STRING",
                "value": "sdfds"
              }
          ]
        ],
        "chainAll": false,
        "hostPreference": false,
        "autoRetryCount": 0,
        "autoRetryInterval": 0,
        "autoRetryIntervalExponent": false,
        "state": "DISABLED",
        "effectiveDate": "2015-01-01T00:00:00-0700"
        "endDate": "2999-12-31T23:59:00-0800"
      }
  ],
  "globalParameters": [
      {
        "name": "dbPassword",
        "type": "STRING",
        "values": ["secret"]
      }
  ],
  "users": [
      {
        "update": false,
        "userName": "admin",
        "active": true,
        "roles": [
            "API",
            "ADMIN",
            "WRITE"
        ],
        "password": "changeme"
      }
  ],
  "chains": {
      "replaceAll": false,
      "items": [
        {
            "sourceJobNickname": "Script Job",
            "targetJobNickname": "Log Cleanup",
            "active": true,
            "triggerStates": [
              "FAILED",
              "CONDITIONAL"
            ],
            "resultConditions": [
              {
                  "variableName": "dfdsfds",
                  "operator": "EQUALS",
                  "values": [
                    "sdfs"
                  ]
              }
            ]
        }
      ]
  },
  "conflicts": [
      [
        "Script Job",
        "Log Cleanup"
      ]
  ],
  "customCalendars": [
      {
        "name": "Sample Calendar",
        "dates": [
            "2011-01-01"
        ]
      }
  ],
  "systemParameters": [
      {
        "name": "adHocJobsRespectFixedHostsRestrictions",
        "description": "This value determines whether the Fixed Hosts restriction assigned to a Job is respected for Ad Hoc jobs.",
        "category": "JOB",
        "value": "true"
      }
  ],
  "templates": [
      {
        "jobNicknames": [],
        "name": "Obsidian Default Job Template",
        "active": true,
        "category": "JOB",
        "defaultForJobs": true,
        "subjectTemplate": "Obsidian [{{hostName}}] {{subject}}",
        "bodyTemplate": "Body Template"
      }
  ],
  "subscribers": [
      {
        "generalSubscriptions": [
            {
              "jobNickname": "Log Cleanup",
              "category": "JOB",
              "level": "ERROR",
              "active": true
            }
        ],
        "jobExecutionSubscriptions": [
            {
              "jobNicknames": [],
              "allJobs": true,
              "triggerStates": [
                  "CONDITIONAL",
                  "DIED",
                  "FAILED",
                  "RECOVERY"
              ],
              "resultConditions": [
                  {
                    "variableName": "someVar",
                    "operator": "EQUALS",
                    "values": [
                        "someValue"
                    ]
                  }
              ],
              "active": true
            }
        ],
        "emailAddress": "[email protected]",
        "active": true
      }
  ]
}
</pre>

Latest revision as of 21:57, 8 July 2025

At times, you may wish to perform initialization, backup or restoration of an Obsidian installation. For example, you may wish to take a known good configuration from a development environment and apply it to a test environment.

As of Obsidian 6.3.0, we introduce support for annotation based initialization that leverages our classpath scanning.

In Obsidian 3.0.0, we introduce support that leverages the System Restore functionality of our API. Both the Embedded API and REST API expose functions for retrieving and updating the full configuration for an Obsidian installation. Rather than require you to individually retrieve all the configuration items and then apply them elsewhere, a full JSON snapshot can be generated and imported, allowing for easy backups and restores.

Uses

Annotation Initialization

As of Obsidian 6.3.0

Job configuration can be automated into target environments via via annotations and classpath scanning. The base annotation to configure a job is Initializable. It is a @Repeatable annotation. On every startup, the nickname in the annotation is used to determine if that job Initializable reference has been initialized before, either via annotation, API or UI. Any nickname conflict will prevent initialization. Initialization is best effort per annotation, with errors logged and event notifications dispatched.

Chains can be initialized via InitializableChainAnnotation using nicknames. It is also a @Repeatable annotation. Descriptions along with source and target job are used to determine if the chain has been initialized previously, since source/target pairs can be repeated with different setups. Conditional chaining can be done via InitializableChainConditionAnnotation. Again, it is a @Repeatable annotation.

Backup or Export

Use the System Restore GET REST endpoint or the equivalent Embedded API to retrieve a SystemRestoreConfiguration. Store the JSON representation in your backup media.

Transfer or Restore a Configuration

Follow the Backup instructions. Then, using the backup JSON, you can either place it on the file-system/classpath as described in Startup Initialization, or use it in conjunction with the System Restore PUT REST endpoint or equivalent Embedded API.

You may choose to update parts of the exported configuration depending on your needs, or to set new user passwords.

Note: Users do not include the current passwords since they cannot be determined, and also as a security measure. All users will be returned with the password "changeme".

Startup Initialization

By default, Obsidian will look for a file on the classpath named /obsidianInitialization.json containing configuration data in the format described in JSON Configuration Format.

You may override the classpath resource name using the system property obsidianInitClasspath. For example, you could add the java system property -DobsidianInitClasspath=/com/mycompany/obsidianInit.json. You can also use a file-based resource by using the system property obsidianInitFile. For example, you could add the java system property -DobsidianInitFile=/var/obsidian-3.0.0/obsidianScheduleInitialization.json.

Note: Initialization only runs on scheduler instances. This means that a standalone Obsidian web application with no scheduler running will not do any initialization based on the presence of the appropriate JSON file.

JSON Configuration Format

The file format is a JSON serialized version of the SystemRestoreConfiguration class. Here we will define each configuration item and any special conditions associated with each one. A sample JSON is provided.

Jobs

The jobs key has a list of JobSaveRequest objects. Each of these represents a configured job in Obsidian. This JobSaveRequest is very much like a JobCreationRequest but having two extra attributes to handle the case where a job with the same nickname already exists. The updateAttributes flag is used to determine whether the job attributes (jobClass, recoveryType, pickupBufferMinutes, etc.) will be updated when the job exists. The updateSchedule flag is used to determine whether to apply the current schedule and any additional jobSchedules when the job already exists. If any of the schedules' end dates are in the past, they will be skipped.

Job Chains

The chains key is a ChainsRequest that houses a collection of chain configurations and a replaceAll attribute. The replaceAll attribute is used when chains already exist in the system. If chains exist and the flag is not set to true, the existing chains are left as is. If set to true, all existing chains are deleted and the new set of chains are created.

Job Conflicts

The conflicts key is similar to the ConflictUpdateRequest but it uses job nicknames instead of job IDs. If an empty list is supplied, all chains will be deleted. Note that this is different from a null or missing value.

Users

The users key has a list of UserSaveRequest objects. These are similar to the standard UserCreationRequest, but they contain an update attribute that is used when the user already exists. If the same user name exists and the flag is not set to true, the user is left as is. Otherwise, the user is created or updated as the case dictates.

Global Parameters

The globalParameters key is a list of GlobalParameter objects that are to be set into the system. Any current global parameters are either deleted or overridden.

Custom Calendars

The customCalendars key is a list of CustomCalendarUpdateRequest objects. Creates or updates as the case dictates by matching on the name.

System Parameters

The systemParameters key is a list of SystemParameter objects. Updates all parameters given.

Subscribers

The subscribers key is a list of SubscriberSaveRequest objects. Creates or updates as the case dictates by matching on the email address.

Templates

The templates key is a list of TemplateSaveRequest objects. Creates or updates as the case dictates by matching on the name.

Sample

{
   "jobs": [
      {
         "updateSchedule": false,
         "updateAttributes": false,
         "jobSchedules": [
            {
               "state": "DISABLED",
               "effectiveDate": "2015-03-20T10:35:00-0700",
               "endDate": "2999-12-31T23:59:00-0800"
            }
         ],
         "jobClass": "com.carfey.ops.job.maint.LogCleanupJob",
         "minExecutionDuration": "2s",
         "maxExecutionDuration": "3s",
         "nickname": "Log Cleanup",
         "pickupBufferMinutes": 2,
         "recoveryType": "NONE",
         "hosts": [ "Demo-PC" ],
         "ordinalParameters": [ // as of 3.8.0, prior to 3.8.0, this was simply the child element "parameters"
           "ordinal": 0, // as of 3.8.0
           "parameters": [
              {
                 "name": "level",
                 "type": "STRING",
                 "value": "ALL"
              },
              {
                 "name": "maxAgeDays",
                 "type": "INTEGER",
                 "value": "120"
              }
           ]
         ],
         "chainAll": false,
         "hostPreference": true,
         "autoRetryCount": 0,
         "autoRetryInterval": 0,
         "autoRetryIntervalExponent": false,
         "state": "ENABLED",
         "schedule": "* * * * *",
         "effectiveDate": "2015-01-01T00:00:00-0700"
         "endDate": "2015-03-20T10:34:00-0700"
      },
      {
         "updateSchedule": false,
         "updateAttributes": false,
         "jobSchedules": [],
         "jobClass": "com.carfey.ops.job.script.GroovyJob",
         "nickname": "Script Job",
         "pickupBufferMinutes": 2,
         "recoveryType": "NONE",
         "hosts": [],
         "ordinalParameters": [
           "ordinal": 0,
           "parameters": [
              {
                 "name": "script",
                 "type": "STRING",
                 "value": "sdfds"
              }
           ]
         ],
         "chainAll": false,
         "hostPreference": false,
         "autoRetryCount": 0,
         "autoRetryInterval": 0,
         "autoRetryIntervalExponent": false,
         "state": "DISABLED",
         "effectiveDate": "2015-01-01T00:00:00-0700"
         "endDate": "2999-12-31T23:59:00-0800"
      }
   ],
   "globalParameters": [
      {
         "name": "dbPassword",
         "type": "STRING",
         "values": ["secret"]
      }
   ],
   "users": [
      {
         "update": false,
         "userName": "admin",
         "active": true,
         "roles": [
            "API",
            "ADMIN",
            "WRITE"
         ],
         "password": "changeme"
      }
   ],
   "chains": {
      "replaceAll": false,
      "items": [
         {
            "sourceJobNickname": "Script Job",
            "targetJobNickname": "Log Cleanup",
            "active": true,
            "triggerStates": [
               "FAILED",
               "CONDITIONAL"
            ],
            "resultConditions": [
               {
                  "variableName": "dfdsfds",
                  "operator": "EQUALS",
                  "values": [
                     "sdfs"
                  ]
               }
            ]
         }
      ]
   },
   "conflicts": [
      [
         "Script Job",
         "Log Cleanup"
      ]
   ],
   "customCalendars": [
      {
         "name": "Sample Calendar",
         "dates": [
            "2011-01-01"
         ]
      }
   ],
   "systemParameters": [
      {
         "name": "adHocJobsRespectFixedHostsRestrictions",
         "description": "This value determines whether the Fixed Hosts restriction assigned to a Job is respected for Ad Hoc jobs.",
         "category": "JOB",
         "value": "true"
      }
   ],
   "templates": [
      {
         "jobNicknames": [],
         "name": "Obsidian Default Job Template",
         "active": true,
         "category": "JOB",
         "defaultForJobs": true,
         "subjectTemplate": "Obsidian [{{hostName}}] {{subject}}",
         "bodyTemplate": "Body Template"
      }
   ],
   "subscribers": [
      {
         "generalSubscriptions": [
            {
               "jobNickname": "Log Cleanup",
               "category": "JOB",
               "level": "ERROR",
               "active": true
            }
         ],
         "jobExecutionSubscriptions": [
            {
               "jobNicknames": [],
               "allJobs": true,
               "triggerStates": [
                  "CONDITIONAL",
                  "DIED",
                  "FAILED",
                  "RECOVERY"
               ],
               "resultConditions": [
                  {
                     "variableName": "someVar",
                     "operator": "EQUALS",
                     "values": [
                        "someValue"
                     ]
                  }
               ],
               "active": true
            }
         ],
         "emailAddress": "[email protected]",
         "active": true
      }
   ]
}