ultravisor 1.0.0 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.babelrc +6 -0
- package/.browserslistrc +1 -0
- package/.browserslistrc-BACKUP +1 -0
- package/.gulpfile-quackage-config.json +7 -0
- package/.gulpfile-quackage.js +2 -0
- package/CONTRIBUTING.md +50 -0
- package/README.md +34 -0
- package/debug/Harness.js +2 -1
- package/docs/.nojekyll +0 -0
- package/docs/_sidebar.md +18 -0
- package/docs/_topbar.md +7 -0
- package/docs/architecture.md +103 -0
- package/docs/cover.md +15 -0
- package/docs/features/api.md +230 -0
- package/docs/features/cli.md +182 -0
- package/docs/features/configuration.md +245 -0
- package/docs/features/manifests.md +177 -0
- package/docs/features/operations.md +292 -0
- package/docs/features/scheduling.md +179 -0
- package/docs/features/tasks.md +1857 -0
- package/docs/index.html +39 -0
- package/docs/overview.md +75 -0
- package/docs/quickstart.md +167 -0
- package/docs/retold-catalog.json +24 -0
- package/docs/retold-keyword-index.json +19 -0
- package/package.json +5 -2
- package/source/Ultravisor.cjs +2 -2
- package/source/cli/Ultravisor-CLIProgram.cjs +38 -0
- package/source/cli/commands/Ultravisor-Command-ScheduleOperation.cjs +26 -2
- package/source/cli/commands/Ultravisor-Command-ScheduleTask.cjs +26 -2
- package/source/cli/commands/Ultravisor-Command-ScheduleView.cjs +22 -0
- package/source/cli/commands/Ultravisor-Command-SingleOperation.cjs +49 -1
- package/source/cli/commands/Ultravisor-Command-SingleTask.cjs +51 -1
- package/source/cli/commands/Ultravisor-Command-Stop.cjs +4 -0
- package/source/cli/commands/Ultravisor-Command-UpdateTask.cjs +91 -0
- package/source/config/Ultravisor-Default-Command-Configuration.cjs +6 -1
- package/source/services/Ultravisor-Hypervisor-Event-Base.cjs +18 -1
- package/source/services/Ultravisor-Hypervisor-State.cjs +213 -0
- package/source/services/Ultravisor-Hypervisor.cjs +225 -1
- package/source/services/Ultravisor-Operation-Manifest.cjs +150 -1
- package/source/services/Ultravisor-Operation.cjs +190 -1
- package/source/services/Ultravisor-Task.cjs +339 -1
- package/source/services/events/Ultravisor-Hypervisor-Event-Cron.cjs +71 -1
- package/source/services/tasks/Ultravisor-Task-Base.cjs +264 -0
- package/source/services/tasks/Ultravisor-Task-CollectValues.cjs +188 -0
- package/source/services/tasks/Ultravisor-Task-Command.cjs +65 -0
- package/source/services/tasks/Ultravisor-Task-CommandEach.cjs +190 -0
- package/source/services/tasks/Ultravisor-Task-Conditional.cjs +104 -0
- package/source/services/tasks/Ultravisor-Task-DateWindow.cjs +72 -0
- package/source/services/tasks/Ultravisor-Task-GeneratePagedOperation.cjs +336 -0
- package/source/services/tasks/Ultravisor-Task-LaunchOperation.cjs +143 -0
- package/source/services/tasks/Ultravisor-Task-LaunchTask.cjs +146 -0
- package/source/services/tasks/Ultravisor-Task-LineMatch.cjs +158 -0
- package/source/services/tasks/Ultravisor-Task-Request.cjs +56 -0
- package/source/services/tasks/Ultravisor-Task-Solver.cjs +89 -0
- package/source/services/tasks/Ultravisor-Task-TemplateString.cjs +93 -0
- package/source/services/tasks/rest/Ultravisor-Task-GetBinary.cjs +127 -0
- package/source/services/tasks/rest/Ultravisor-Task-GetJSON.cjs +119 -0
- package/source/services/tasks/rest/Ultravisor-Task-GetText.cjs +109 -0
- package/source/services/tasks/rest/Ultravisor-Task-GetXML.cjs +112 -0
- package/source/services/tasks/rest/Ultravisor-Task-RestRequest.cjs +499 -0
- package/source/services/tasks/rest/Ultravisor-Task-SendJSON.cjs +150 -0
- package/source/services/tasks/stagingfiles/Ultravisor-Task-CopyFile.cjs +110 -0
- package/source/services/tasks/stagingfiles/Ultravisor-Task-ListFiles.cjs +89 -0
- package/source/services/tasks/stagingfiles/Ultravisor-Task-ReadBinary.cjs +87 -0
- package/source/services/tasks/stagingfiles/Ultravisor-Task-ReadJSON.cjs +67 -0
- package/source/services/tasks/stagingfiles/Ultravisor-Task-ReadText.cjs +66 -0
- package/source/services/tasks/stagingfiles/Ultravisor-Task-ReadXML.cjs +69 -0
- package/source/services/tasks/stagingfiles/Ultravisor-Task-WriteBinary.cjs +95 -0
- package/source/services/tasks/stagingfiles/Ultravisor-Task-WriteJSON.cjs +96 -0
- package/source/services/tasks/stagingfiles/Ultravisor-Task-WriteText.cjs +99 -0
- package/source/services/tasks/stagingfiles/Ultravisor-Task-WriteXML.cjs +102 -0
- package/source/web_server/Ultravisor-API-Server.cjs +463 -3
- package/test/Ultravisor_tests.js +6097 -1
- package/webinterface/.babelrc +6 -0
- package/webinterface/.browserslistrc +1 -0
- package/webinterface/.browserslistrc-BACKUP +1 -0
- package/webinterface/.gulpfile-quackage-config.json +7 -0
- package/webinterface/.gulpfile-quackage.js +2 -0
- package/webinterface/css/ultravisor.css +121 -0
- package/webinterface/html/index.html +32 -0
- package/webinterface/package.json +39 -0
- package/webinterface/source/Pict-Application-Ultravisor-Configuration.json +15 -0
- package/webinterface/source/Pict-Application-Ultravisor.js +414 -0
- package/webinterface/source/providers/PictRouter-Ultravisor-Configuration.json +42 -0
- package/webinterface/source/views/PictView-Ultravisor-BottomBar.js +65 -0
- package/webinterface/source/views/PictView-Ultravisor-Dashboard.js +236 -0
- package/webinterface/source/views/PictView-Ultravisor-Layout.js +83 -0
- package/webinterface/source/views/PictView-Ultravisor-ManifestList.js +273 -0
- package/webinterface/source/views/PictView-Ultravisor-OperationEdit.js +243 -0
- package/webinterface/source/views/PictView-Ultravisor-OperationList.js +141 -0
- package/webinterface/source/views/PictView-Ultravisor-Schedule.js +280 -0
- package/webinterface/source/views/PictView-Ultravisor-TaskEdit.js +220 -0
- package/webinterface/source/views/PictView-Ultravisor-TaskList.js +248 -0
- package/webinterface/source/views/PictView-Ultravisor-TimingView.js +420 -0
- package/webinterface/source/views/PictView-Ultravisor-TopBar.js +147 -0
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
const libCommandLineCommand = require('pict-service-commandlineutility').ServiceCommandLineCommand;
|
|
2
|
+
|
|
3
|
+
const libFS = require('fs');
|
|
4
|
+
const libPath = require('path');
|
|
5
|
+
|
|
6
|
+
class UltravisorCommandAddTask extends libCommandLineCommand
|
|
7
|
+
{
|
|
8
|
+
constructor(pFable, pManifest, pServiceHash)
|
|
9
|
+
{
|
|
10
|
+
super(pFable, pManifest, pServiceHash);
|
|
11
|
+
|
|
12
|
+
this.options.CommandKeyword = 'updatetask';
|
|
13
|
+
this.options.Description = 'Update (or add) a task to the available tasks.';
|
|
14
|
+
|
|
15
|
+
this.options.CommandOptions.push({ Name:'-f, --file [json_filepath]', Description:'JSON Task definition file path.', Default:false });
|
|
16
|
+
|
|
17
|
+
this.options.CommandOptions.push({ Name:'-g, --guid [task_guid]', Description:'The guid for the task.', Default:false });
|
|
18
|
+
this.options.CommandOptions.push({ Name:'-c, --code [task_code]', Description:'The code for the task.', Default:false });
|
|
19
|
+
this.options.CommandOptions.push({ Name:'-n, --name [task_name]', Description:'The name of the task.', Default:false });
|
|
20
|
+
|
|
21
|
+
this.options.CommandOptions.push({ Name:'-t, --type [task_type]', Description:'The type of task.', Default:'CRON' });
|
|
22
|
+
this.options.CommandOptions.push({ Name:'-p, --parameters [task_parameters]', Description:'The parameters of the task.', Default:'0 0 * * * *' });
|
|
23
|
+
|
|
24
|
+
this.addCommand();
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
onRunAsync(fCallback)
|
|
28
|
+
{
|
|
29
|
+
const tmpOperationState = {};
|
|
30
|
+
|
|
31
|
+
tmpOperationState.JSONFile = false;
|
|
32
|
+
|
|
33
|
+
if (this.CommandOptions.json_filepath)
|
|
34
|
+
{
|
|
35
|
+
tmpOperationState.TaskDefinition_JSONFilePathRaw = this.CommandOptions.json_filepath;
|
|
36
|
+
tmpOperationState.TaskDefinition_JSONFilePath = libPath.resolve(tmpOperationState.TaskDefinition_JSONFilePathRaw);
|
|
37
|
+
|
|
38
|
+
if (!libFS.existsSync(tmpOperationState.TaskDefinition_JSONFilePath))
|
|
39
|
+
{
|
|
40
|
+
tmpOperationState.TaskDefinition_JSONFilePath = libPath.resolve(process.cwd(), tmpOperationState.TaskDefinition_JSONFilePathRaw);
|
|
41
|
+
|
|
42
|
+
if (!libFS.existsSync(tmpOperationState.TaskDefinition_JSONFilePath))
|
|
43
|
+
{
|
|
44
|
+
return fCallback(new Error(`The specified task definition JSON file could not be found at either path: ${tmpOperationState.TaskDefinition_JSONFilePathRaw} or ${tmpOperationState.TaskDefinition_JSONFilePath}`));
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
if (tmpOperationState.TaskDefinition_JSONFilePath && (tmpOperationState.TaskDefinition_JSONFilePath.length > 0))
|
|
48
|
+
{
|
|
49
|
+
try
|
|
50
|
+
{
|
|
51
|
+
const tmpFileContents = libFS.readFileSync(tmpOperationState.TaskDefinition_JSONFilePath, 'utf8');
|
|
52
|
+
tmpOperationState.JSONFile = JSON.parse(tmpFileContents);
|
|
53
|
+
}
|
|
54
|
+
catch(pError)
|
|
55
|
+
{
|
|
56
|
+
return fCallback(new Error(`The specified task definition JSON file could not be read or parsed: ${pError.message}`));
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
else
|
|
61
|
+
{
|
|
62
|
+
tmpOperationState.JSONFile = {};
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
tmpOperationState.TaskDefinition_Parameterized = {};
|
|
66
|
+
|
|
67
|
+
tmpOperationState.TaskDefinition_Parameterized.GUIDTask = this.CommandOptions.guid;
|
|
68
|
+
tmpOperationState.TaskDefinition_Parameterized.Code = this.CommandOptions.code;
|
|
69
|
+
tmpOperationState.TaskDefinition_Parameterized.Name = this.CommandOptions.name;
|
|
70
|
+
|
|
71
|
+
tmpOperationState.TaskDefinition_Parameterized.Type = this.CommandOptions.type;
|
|
72
|
+
tmpOperationState.TaskDefinition_Parameterized.Parameters = this.CommandOptions.parameters;
|
|
73
|
+
|
|
74
|
+
tmpOperationState.TaskDefinition = Object.assign({}, tmpOperationState.TaskDefinition_Parameterized, tmpOperationState.JSONFile);
|
|
75
|
+
|
|
76
|
+
this.fable['Ultravisor-Hypervisor-State'].updateTask(tmpOperationState.TaskDefinition,
|
|
77
|
+
function (pError, pUpdatedTask)
|
|
78
|
+
{
|
|
79
|
+
if (pError)
|
|
80
|
+
{
|
|
81
|
+
return fCallback(new Error(`Could not update task: ${pError.message}`));
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
console.log(`Task with GUID ${pUpdatedTask.GUIDTask} updated successfully.`);
|
|
85
|
+
|
|
86
|
+
return fCallback();
|
|
87
|
+
}.bind(this));
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
module.exports = UltravisorCommandAddTask;
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
module.exports = (
|
|
2
2
|
{
|
|
3
3
|
"UltravisorAPIServerPort": 54321,
|
|
4
|
-
"UltravisorFileStorePath": `${process.cwd()}/dist/ultravisor_datastore
|
|
4
|
+
"UltravisorFileStorePath": `${process.cwd()}/dist/ultravisor_datastore`,
|
|
5
|
+
"UltravisorStagingRoot": `${process.cwd()}/dist/ultravisor_staging`,
|
|
6
|
+
"UltravisorTickIntervalMilliseconds": 60000,
|
|
7
|
+
"UltravisorCommandTimeoutMilliseconds": 300000,
|
|
8
|
+
"UltravisorCommandMaxBufferBytes": 10485760,
|
|
9
|
+
"UltravisorWebInterfacePath": false
|
|
5
10
|
});
|
|
@@ -5,7 +5,24 @@ class UltravisorEventBase extends libPictService
|
|
|
5
5
|
constructor(pPict, pOptions, pServiceHash)
|
|
6
6
|
{
|
|
7
7
|
super(pPict, pOptions, pServiceHash);
|
|
8
|
+
|
|
9
|
+
this._Active = false;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
start(pScheduleEntry, fOnTick)
|
|
13
|
+
{
|
|
14
|
+
this._Active = true;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
stop()
|
|
18
|
+
{
|
|
19
|
+
this._Active = false;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
get active()
|
|
23
|
+
{
|
|
24
|
+
return this._Active;
|
|
8
25
|
}
|
|
9
26
|
}
|
|
10
27
|
|
|
11
|
-
module.exports = UltravisorEventBase;
|
|
28
|
+
module.exports = UltravisorEventBase;
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
const libPictService = require(`pict-serviceproviderbase`);
|
|
2
|
+
|
|
3
|
+
const libFS = require('fs');
|
|
4
|
+
const libPath = require('path');
|
|
5
|
+
|
|
6
|
+
class UltravisorHypervisorState extends libPictService
|
|
7
|
+
{
|
|
8
|
+
constructor(pPict, pOptions, pServiceHash)
|
|
9
|
+
{
|
|
10
|
+
super(pPict, pOptions, pServiceHash);
|
|
11
|
+
|
|
12
|
+
this._Tasks = {};
|
|
13
|
+
this._Operations = {};
|
|
14
|
+
|
|
15
|
+
this._ConfigurationOutcome = this.fable.gatherProgramConfiguration(false);
|
|
16
|
+
|
|
17
|
+
// Load tasks and operations from the gathered configuration
|
|
18
|
+
let tmpConfig = this.fable.ProgramConfiguration || {};
|
|
19
|
+
|
|
20
|
+
if (tmpConfig.Tasks && typeof(tmpConfig.Tasks) === 'object')
|
|
21
|
+
{
|
|
22
|
+
let tmpTaskKeys = Object.keys(tmpConfig.Tasks);
|
|
23
|
+
for (let i = 0; i < tmpTaskKeys.length; i++)
|
|
24
|
+
{
|
|
25
|
+
this._Tasks[tmpTaskKeys[i]] = tmpConfig.Tasks[tmpTaskKeys[i]];
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (tmpConfig.Operations && typeof(tmpConfig.Operations) === 'object')
|
|
30
|
+
{
|
|
31
|
+
let tmpOperationKeys = Object.keys(tmpConfig.Operations);
|
|
32
|
+
for (let i = 0; i < tmpOperationKeys.length; i++)
|
|
33
|
+
{
|
|
34
|
+
this._Operations[tmpOperationKeys[i]] = tmpConfig.Operations[tmpOperationKeys[i]];
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
persistState()
|
|
40
|
+
{
|
|
41
|
+
// Check the _ConfigurationOutcome to see where we should be persisting state
|
|
42
|
+
let tmpFinalGatherPhasePath = false;
|
|
43
|
+
for (let i = 0; i < this._ConfigurationOutcome.GatherPhases.length; i++)
|
|
44
|
+
{
|
|
45
|
+
let tmpGatherPhase = this._ConfigurationOutcome.GatherPhases[i];
|
|
46
|
+
if ((tmpGatherPhase.Phase != 'Default Program Configuration') && (tmpGatherPhase.Path))
|
|
47
|
+
{
|
|
48
|
+
tmpFinalGatherPhasePath = tmpGatherPhase.Path;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (!tmpFinalGatherPhasePath && this.fable.settings.ProgramConfigurationFileName)
|
|
53
|
+
{
|
|
54
|
+
tmpFinalGatherPhasePath = libPath.resolve(process.cwd(), this.fable.settings.ProgramConfigurationFileName);
|
|
55
|
+
this.pict.log.warn(`Ultravisor Hypervisor State: persistState could not determine a valid configuration path to persist state to;.`);
|
|
56
|
+
}
|
|
57
|
+
else if (!tmpFinalGatherPhasePath)
|
|
58
|
+
{
|
|
59
|
+
this.pict.log.error(`Ultravisor Hypervisor State: persistState could not determine a valid configuration path to persist state to; state will not be saved.`);
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Now merge all the data
|
|
64
|
+
const tmpStateToPersist = this._ConfigurationOutcome.ConfigurationOutcome;
|
|
65
|
+
|
|
66
|
+
// Merge in Tasks
|
|
67
|
+
if (!tmpStateToPersist.hasOwnProperty('Tasks'))
|
|
68
|
+
{
|
|
69
|
+
tmpStateToPersist.Tasks = {};
|
|
70
|
+
}
|
|
71
|
+
const tmpTaskKeys = Object.keys(this._Tasks);
|
|
72
|
+
for (let i=0; i<tmpTaskKeys.length; i++)
|
|
73
|
+
{
|
|
74
|
+
if (tmpStateToPersist.Tasks.hasOwnProperty(tmpTaskKeys[i]))
|
|
75
|
+
{
|
|
76
|
+
tmpStateToPersist.Tasks[tmpTaskKeys[i]] = Object.assign({}, tmpStateToPersist.Tasks[tmpTaskKeys[i]], this._Tasks[tmpTaskKeys[i]]);
|
|
77
|
+
}
|
|
78
|
+
else
|
|
79
|
+
{
|
|
80
|
+
tmpStateToPersist.Tasks[tmpTaskKeys[i]] = this._Tasks[tmpTaskKeys[i]];
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (!tmpStateToPersist.hasOwnProperty('Operations'))
|
|
85
|
+
{
|
|
86
|
+
tmpStateToPersist.Operations = {};
|
|
87
|
+
}
|
|
88
|
+
const tmpOperationKeys = Object.keys(this._Operations);
|
|
89
|
+
for (let i=0; i<tmpOperationKeys.length; i++)
|
|
90
|
+
{
|
|
91
|
+
if (tmpStateToPersist.Operations.hasOwnProperty(tmpOperationKeys[i]))
|
|
92
|
+
{
|
|
93
|
+
tmpStateToPersist.Operations[tmpOperationKeys[i]] = Object.assign({}, tmpStateToPersist.Operations[tmpOperationKeys[i]], this._Operations[tmpOperationKeys[i]]);
|
|
94
|
+
}
|
|
95
|
+
else
|
|
96
|
+
{
|
|
97
|
+
tmpStateToPersist.Operations[tmpOperationKeys[i]] = this._Operations[tmpOperationKeys[i]];
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
this.fable.log.info(`Ultravisor Hypervisor State: persisting hypervisor state to ${tmpFinalGatherPhasePath}.`);
|
|
102
|
+
|
|
103
|
+
try
|
|
104
|
+
{
|
|
105
|
+
libFS.writeFileSync(tmpFinalGatherPhasePath, JSON.stringify(tmpStateToPersist, null, 4), 'utf8');
|
|
106
|
+
}
|
|
107
|
+
catch(pError)
|
|
108
|
+
{
|
|
109
|
+
this.fable.log.error(`Ultravisor Hypervisor State: an error occurred while attempting to persist hypervisor state to ${tmpFinalGatherPhasePath}: ${pError.message}`);
|
|
110
|
+
return false;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return true
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
updateOperation(pOperation, fCallback)
|
|
118
|
+
{
|
|
119
|
+
if (typeof(pOperation) !== 'object' || pOperation === null)
|
|
120
|
+
{
|
|
121
|
+
return fCallback(new Error(`Ultravisor Hypervisor State: updateOperation requires a valid operation object.`));
|
|
122
|
+
}
|
|
123
|
+
if (!pOperation.hasOwnProperty('GUIDOperation') || typeof(pOperation.GUIDOperation) !== 'string' || pOperation.GUIDOperation.length === 0)
|
|
124
|
+
{
|
|
125
|
+
return fCallback(new Error(`Ultravisor Hypervisor State: updateOperation requires the operation object to have a GUIDOperation property.`));
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (this._Operations.hasOwnProperty(pOperation.GUIDOperation))
|
|
129
|
+
{
|
|
130
|
+
// Update the existing operation
|
|
131
|
+
this._Operations[pOperation.GUIDOperation] = Object.assign(this._Operations[pOperation.GUIDOperation], pOperation);
|
|
132
|
+
}
|
|
133
|
+
else
|
|
134
|
+
{
|
|
135
|
+
// Add a new operation
|
|
136
|
+
this._Operations[pOperation.GUIDOperation] = pOperation;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
this.persistState();
|
|
140
|
+
|
|
141
|
+
return fCallback(null, this._Operations[pOperation.GUIDOperation]);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
getOperationList(pFilters, fCallback)
|
|
145
|
+
{
|
|
146
|
+
const tmpOperationKeys = Object.keys(this._Operations);
|
|
147
|
+
const tmpOperations = [];
|
|
148
|
+
for (let i=0; i<tmpOperationKeys.length; i++)
|
|
149
|
+
{
|
|
150
|
+
tmpOperations.push(this._Operations[tmpOperationKeys[i]]);
|
|
151
|
+
}
|
|
152
|
+
return fCallback(null, tmpOperations);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
getOperation(pGUIDOperation, fCallback)
|
|
156
|
+
{
|
|
157
|
+
if (!this._Operations.hasOwnProperty(pGUIDOperation))
|
|
158
|
+
{
|
|
159
|
+
return fCallback(new Error(`Ultravisor Hypervisor State: getOperation could not find operation with GUID ${pGUIDOperation}.`));
|
|
160
|
+
}
|
|
161
|
+
return fCallback(null, this._Operations[pGUIDOperation]);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
updateTask(pTask, fCallback)
|
|
166
|
+
{
|
|
167
|
+
if (typeof(pTask) !== 'object' || pTask === null)
|
|
168
|
+
{
|
|
169
|
+
return fCallback(new Error(`Ultravisor Hypervisor State: updateTask requires a valid task object.`));
|
|
170
|
+
}
|
|
171
|
+
if (!pTask.hasOwnProperty('GUIDTask') || typeof(pTask.GUIDTask) !== 'string' || pTask.GUIDTask.length === 0)
|
|
172
|
+
{
|
|
173
|
+
return fCallback(new Error(`Ultravisor Hypervisor State: updateTask requires the task object to have a GUIDTask property.`));
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
if (this._Tasks.hasOwnProperty(pTask.GUIDTask))
|
|
177
|
+
{
|
|
178
|
+
// Update the existing task
|
|
179
|
+
this._Tasks[pTask.GUIDTask] = Object.assign(this._Tasks[pTask.GUIDTask], pTask);
|
|
180
|
+
}
|
|
181
|
+
else
|
|
182
|
+
{
|
|
183
|
+
// Add a new task
|
|
184
|
+
this._Tasks[pTask.GUIDTask] = pTask;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
this.persistState();
|
|
188
|
+
|
|
189
|
+
return fCallback(null, this._Tasks[pTask.GUIDTask]);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
getTaskList(pFilters, fCallback)
|
|
193
|
+
{
|
|
194
|
+
const tmpTaskKeys = Object.keys(this._Tasks);
|
|
195
|
+
const tmpTasks = [];
|
|
196
|
+
for (let i=0; i<tmpTaskKeys.length; i++)
|
|
197
|
+
{
|
|
198
|
+
tmpTasks.push(this._Tasks[tmpTaskKeys[i]]);
|
|
199
|
+
}
|
|
200
|
+
return fCallback(null, tmpTasks);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
getTask(pGUIDTask, fCallback)
|
|
204
|
+
{
|
|
205
|
+
if (!this._Tasks.hasOwnProperty(pGUIDTask))
|
|
206
|
+
{
|
|
207
|
+
return fCallback(new Error(`Ultravisor Hypervisor State: getTask could not find task with GUID ${pGUIDTask}.`));
|
|
208
|
+
}
|
|
209
|
+
return fCallback(null, this._Tasks[pGUIDTask]);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
module.exports = UltravisorHypervisorState;
|
|
@@ -1,11 +1,235 @@
|
|
|
1
1
|
const libPictService = require(`pict-serviceproviderbase`);
|
|
2
2
|
|
|
3
|
+
const libCron = require('cron');
|
|
4
|
+
|
|
3
5
|
class UltravisorHypervisor extends libPictService
|
|
4
6
|
{
|
|
5
7
|
constructor(pPict, pOptions, pServiceHash)
|
|
6
8
|
{
|
|
7
9
|
super(pPict, pOptions, pServiceHash);
|
|
10
|
+
|
|
11
|
+
this.CronJob = libCron.CronJob;
|
|
12
|
+
|
|
13
|
+
this._Schedule = [];
|
|
14
|
+
this._Running = false;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
get schedule()
|
|
18
|
+
{
|
|
19
|
+
return this.getSchedule();
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
getSchedule()
|
|
23
|
+
{
|
|
24
|
+
return this._Schedule;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Add a task to the schedule.
|
|
29
|
+
*
|
|
30
|
+
* @param {string} pTaskGUID - The task GUID to schedule.
|
|
31
|
+
* @param {string} pType - Schedule type (cron, daily, hourly).
|
|
32
|
+
* @param {string} pParameters - Schedule parameters (e.g. cron expression).
|
|
33
|
+
* @param {function} fCallback - Callback.
|
|
34
|
+
*/
|
|
35
|
+
scheduleTask(pTaskGUID, pType, pParameters, fCallback)
|
|
36
|
+
{
|
|
37
|
+
let tmpScheduleEntry = {
|
|
38
|
+
GUID: `sched-task-${pTaskGUID}-${Date.now()}`,
|
|
39
|
+
TargetType: 'Task',
|
|
40
|
+
TargetGUID: pTaskGUID,
|
|
41
|
+
ScheduleType: pType || 'cron',
|
|
42
|
+
Parameters: pParameters || '0 * * * *',
|
|
43
|
+
CronExpression: this._resolveScheduleExpression(pType, pParameters),
|
|
44
|
+
Active: false,
|
|
45
|
+
CreatedAt: new Date().toISOString()
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
this._Schedule.push(tmpScheduleEntry);
|
|
49
|
+
this.log.info(`Ultravisor Hypervisor: scheduled task ${pTaskGUID} as ${tmpScheduleEntry.ScheduleType} (${tmpScheduleEntry.CronExpression})`);
|
|
50
|
+
|
|
51
|
+
return fCallback(null, tmpScheduleEntry);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Add an operation to the schedule.
|
|
56
|
+
*
|
|
57
|
+
* @param {string} pOperationGUID - The operation GUID to schedule.
|
|
58
|
+
* @param {string} pType - Schedule type (cron, daily, hourly).
|
|
59
|
+
* @param {string} pParameters - Schedule parameters.
|
|
60
|
+
* @param {function} fCallback - Callback.
|
|
61
|
+
*/
|
|
62
|
+
scheduleOperation(pOperationGUID, pType, pParameters, fCallback)
|
|
63
|
+
{
|
|
64
|
+
let tmpScheduleEntry = {
|
|
65
|
+
GUID: `sched-op-${pOperationGUID}-${Date.now()}`,
|
|
66
|
+
TargetType: 'Operation',
|
|
67
|
+
TargetGUID: pOperationGUID,
|
|
68
|
+
ScheduleType: pType || 'cron',
|
|
69
|
+
Parameters: pParameters || '0 * * * *',
|
|
70
|
+
CronExpression: this._resolveScheduleExpression(pType, pParameters),
|
|
71
|
+
Active: false,
|
|
72
|
+
CreatedAt: new Date().toISOString()
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
this._Schedule.push(tmpScheduleEntry);
|
|
76
|
+
this.log.info(`Ultravisor Hypervisor: scheduled operation ${pOperationGUID} as ${tmpScheduleEntry.ScheduleType} (${tmpScheduleEntry.CronExpression})`);
|
|
77
|
+
|
|
78
|
+
return fCallback(null, tmpScheduleEntry);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Resolve a schedule type and parameters into a cron expression.
|
|
83
|
+
*/
|
|
84
|
+
_resolveScheduleExpression(pType, pParameters)
|
|
85
|
+
{
|
|
86
|
+
let tmpType = (pType || 'cron').toLowerCase();
|
|
87
|
+
|
|
88
|
+
switch (tmpType)
|
|
89
|
+
{
|
|
90
|
+
case 'daily':
|
|
91
|
+
// Default to midnight, or use the parameters as a time
|
|
92
|
+
return pParameters || '0 0 * * *';
|
|
93
|
+
case 'hourly':
|
|
94
|
+
return pParameters || '0 * * * *';
|
|
95
|
+
case 'cron':
|
|
96
|
+
default:
|
|
97
|
+
return pParameters || '0 * * * *';
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Start all scheduled jobs via the cron event service.
|
|
103
|
+
*/
|
|
104
|
+
startSchedule(fCallback)
|
|
105
|
+
{
|
|
106
|
+
let tmpCronService = this.fable['Ultravisor-Hypervisor-Event-Cron'];
|
|
107
|
+
let tmpTaskService = this.fable['Ultravisor-Task'];
|
|
108
|
+
let tmpOperationService = this.fable['Ultravisor-Operation'];
|
|
109
|
+
let tmpStateService = this.fable['Ultravisor-Hypervisor-State'];
|
|
110
|
+
|
|
111
|
+
this._Running = true;
|
|
112
|
+
|
|
113
|
+
for (let i = 0; i < this._Schedule.length; i++)
|
|
114
|
+
{
|
|
115
|
+
let tmpEntry = this._Schedule[i];
|
|
116
|
+
|
|
117
|
+
if (tmpEntry.Active)
|
|
118
|
+
{
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
tmpEntry.Active = true;
|
|
123
|
+
|
|
124
|
+
tmpCronService.start(tmpEntry,
|
|
125
|
+
(pScheduleEntry) =>
|
|
126
|
+
{
|
|
127
|
+
// On tick, execute the target
|
|
128
|
+
if (pScheduleEntry.TargetType === 'Task')
|
|
129
|
+
{
|
|
130
|
+
tmpStateService.getTask(pScheduleEntry.TargetGUID,
|
|
131
|
+
(pError, pTask) =>
|
|
132
|
+
{
|
|
133
|
+
if (pError)
|
|
134
|
+
{
|
|
135
|
+
this.log.error(`Ultravisor Hypervisor: scheduled task ${pScheduleEntry.TargetGUID} not found: ${pError.message}`);
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
tmpTaskService.executeTask(pTask, {},
|
|
139
|
+
(pTaskError, pResult) =>
|
|
140
|
+
{
|
|
141
|
+
if (pTaskError)
|
|
142
|
+
{
|
|
143
|
+
this.log.error(`Ultravisor Hypervisor: scheduled task execution error: ${pTaskError.message}`);
|
|
144
|
+
}
|
|
145
|
+
else
|
|
146
|
+
{
|
|
147
|
+
this.log.info(`Ultravisor Hypervisor: scheduled task ${pScheduleEntry.TargetGUID} completed: ${pResult.Status}`);
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
else if (pScheduleEntry.TargetType === 'Operation')
|
|
153
|
+
{
|
|
154
|
+
tmpStateService.getOperation(pScheduleEntry.TargetGUID,
|
|
155
|
+
(pError, pOperation) =>
|
|
156
|
+
{
|
|
157
|
+
if (pError)
|
|
158
|
+
{
|
|
159
|
+
this.log.error(`Ultravisor Hypervisor: scheduled operation ${pScheduleEntry.TargetGUID} not found: ${pError.message}`);
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
tmpOperationService.executeOperation(pOperation,
|
|
163
|
+
(pOpError, pManifest) =>
|
|
164
|
+
{
|
|
165
|
+
if (pOpError)
|
|
166
|
+
{
|
|
167
|
+
this.log.error(`Ultravisor Hypervisor: scheduled operation execution error: ${pOpError.message}`);
|
|
168
|
+
}
|
|
169
|
+
else
|
|
170
|
+
{
|
|
171
|
+
this.log.info(`Ultravisor Hypervisor: scheduled operation ${pScheduleEntry.TargetGUID} completed: ${pManifest.Status}`);
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
this.log.info(`Ultravisor Hypervisor: schedule started with ${this._Schedule.length} entries.`);
|
|
180
|
+
|
|
181
|
+
if (typeof(fCallback) === 'function')
|
|
182
|
+
{
|
|
183
|
+
return fCallback();
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Stop all scheduled jobs.
|
|
189
|
+
*/
|
|
190
|
+
stopSchedule(fCallback)
|
|
191
|
+
{
|
|
192
|
+
let tmpCronService = this.fable['Ultravisor-Hypervisor-Event-Cron'];
|
|
193
|
+
|
|
194
|
+
tmpCronService.stop();
|
|
195
|
+
this._Running = false;
|
|
196
|
+
|
|
197
|
+
for (let i = 0; i < this._Schedule.length; i++)
|
|
198
|
+
{
|
|
199
|
+
this._Schedule[i].Active = false;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
this.log.info(`Ultravisor Hypervisor: schedule stopped.`);
|
|
203
|
+
|
|
204
|
+
if (typeof(fCallback) === 'function')
|
|
205
|
+
{
|
|
206
|
+
return fCallback();
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Remove a schedule entry by GUID.
|
|
212
|
+
*/
|
|
213
|
+
removeScheduleEntry(pGUID, fCallback)
|
|
214
|
+
{
|
|
215
|
+
let tmpCronService = this.fable['Ultravisor-Hypervisor-Event-Cron'];
|
|
216
|
+
|
|
217
|
+
for (let i = 0; i < this._Schedule.length; i++)
|
|
218
|
+
{
|
|
219
|
+
if (this._Schedule[i].GUID === pGUID)
|
|
220
|
+
{
|
|
221
|
+
if (this._Schedule[i].Active)
|
|
222
|
+
{
|
|
223
|
+
tmpCronService.stopJob(pGUID);
|
|
224
|
+
}
|
|
225
|
+
this._Schedule.splice(i, 1);
|
|
226
|
+
this.log.info(`Ultravisor Hypervisor: removed schedule entry ${pGUID}`);
|
|
227
|
+
return fCallback(null, true);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
return fCallback(new Error(`Schedule entry ${pGUID} not found.`));
|
|
8
232
|
}
|
|
9
233
|
}
|
|
10
234
|
|
|
11
|
-
module.exports = UltravisorHypervisor;
|
|
235
|
+
module.exports = UltravisorHypervisor;
|