ultravisor 1.0.3 → 1.0.8
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/.claude/launch.json +11 -0
- package/.claude/ultravisor-dev-config.json +3 -0
- package/card-audit.json +1545 -0
- package/docs/_sidebar.md +17 -0
- package/docs/css/docuserve.css +73 -0
- package/docs/features/beacon-authentication.md +209 -0
- package/docs/features/beacon-providers.md +1299 -0
- package/docs/features/beacons.md +530 -0
- package/docs/features/capabilities.md +193 -0
- package/docs/features/llm-model-setup.md +505 -0
- package/docs/features/llm.md +262 -0
- package/docs/features/tasks-content-system.md +110 -0
- package/docs/features/tasks-data-transform.md +233 -0
- package/docs/features/tasks-extension.md +36 -0
- package/docs/features/tasks-file-system.md +203 -0
- package/docs/features/tasks-flow-control.md +125 -0
- package/docs/features/tasks-http-client.md +119 -0
- package/docs/features/tasks-llm.md +118 -0
- package/docs/features/tasks-meadow-api.md +163 -0
- package/docs/features/tasks-user-interaction.md +49 -0
- package/docs/features/tasks.md +14 -0
- package/docs/index.html +1 -1
- package/docs/retold-catalog.json +1 -1
- package/docs/retold-keyword-index.json +17374 -5
- package/operation-library/api-data-pipeline.json +143 -0
- package/operation-library/beacon-remote-command.json +72 -0
- package/operation-library/conditional-file-backup.json +143 -0
- package/operation-library/config-processor.json +136 -0
- package/operation-library/csv-data-analysis.json +228 -0
- package/operation-library/csv-to-json.json +160 -0
- package/operation-library/directory-inventory.json +128 -0
- package/operation-library/expression-calculator.json +114 -0
- package/operation-library/file-search-replace.json +175 -0
- package/operation-library/git-status-report.json +368 -0
- package/operation-library/health-check-ping.json +329 -0
- package/operation-library/json-config-merge.json +313 -0
- package/operation-library/llm-embedding-tool-use.json +314 -0
- package/operation-library/llm-multi-turn-analysis.json +322 -0
- package/operation-library/llm-summarize.json +264 -0
- package/operation-library/log-line-counter.json +185 -0
- package/operation-library/meadow-crud-lifecycle.json +264 -0
- package/operation-library/npm-project-validator.json +193 -0
- package/operation-library/rest-api-orchestrator.json +218 -0
- package/operation-library/shell-system-info.json +137 -0
- package/operation-library/simple-echo.json +95 -0
- package/operation-library/template-processor.json +299 -0
- package/operation-library/text-sanitizer.json +176 -0
- package/package.json +12 -8
- package/source/Ultravisor.cjs +30 -3
- package/source/beacon/Ultravisor-Beacon-CLI.cjs +143 -0
- package/source/beacon/Ultravisor-Beacon-CapabilityProvider.cjs +129 -0
- package/source/beacon/Ultravisor-Beacon-Client.cjs +568 -0
- package/source/beacon/Ultravisor-Beacon-Executor.cjs +500 -0
- package/source/beacon/Ultravisor-Beacon-ProviderRegistry.cjs +330 -0
- package/source/beacon/providers/Ultravisor-Beacon-Provider-FileSystem.cjs +331 -0
- package/source/beacon/providers/Ultravisor-Beacon-Provider-LLM.cjs +966 -0
- package/source/beacon/providers/Ultravisor-Beacon-Provider-Shell.cjs +95 -0
- package/source/cli/Ultravisor-CLIProgram.cjs +44 -22
- package/source/cli/commands/Ultravisor-Command-SingleOperation.cjs +29 -18
- package/source/cli/commands/Ultravisor-Command-SingleTask.cjs +62 -19
- package/source/cli/commands/Ultravisor-Command-UpdateTask.cjs +27 -15
- package/source/config/Ultravisor-Default-Command-Configuration.cjs +12 -3
- package/source/services/Ultravisor-Beacon-Coordinator.cjs +966 -0
- package/source/services/Ultravisor-ExecutionEngine.cjs +1093 -0
- package/source/services/Ultravisor-ExecutionManifest.cjs +629 -0
- package/source/services/Ultravisor-Hypervisor-State.cjs +270 -97
- package/source/services/Ultravisor-Hypervisor.cjs +185 -75
- package/source/services/Ultravisor-Schedule-Persistence-Base.cjs +45 -0
- package/source/services/Ultravisor-StateManager.cjs +253 -0
- package/source/services/Ultravisor-TaskTypeRegistry.cjs +213 -0
- package/source/services/persistence/Ultravisor-Schedule-Persistence-JSONFile.cjs +140 -0
- package/source/services/tasks/Ultravisor-BuiltIn-TaskConfigs.cjs +19 -0
- package/source/services/tasks/Ultravisor-TaskHelper-BeaconDispatch.cjs +107 -0
- package/source/services/tasks/Ultravisor-TaskType-Base.cjs +125 -0
- package/source/services/tasks/content-system/Ultravisor-TaskConfigs-ContentSystem.cjs +90 -0
- package/source/services/tasks/content-system/definitions/content-create-folder.json +24 -0
- package/source/services/tasks/content-system/definitions/content-list-files.json +27 -0
- package/source/services/tasks/content-system/definitions/content-read-file.json +26 -0
- package/source/services/tasks/content-system/definitions/content-save-file.json +26 -0
- package/source/services/tasks/data-transform/Ultravisor-TaskConfigs-DataTransform.cjs +577 -0
- package/source/services/tasks/data-transform/Ultravisor-TaskType-ReplaceString.cjs +80 -0
- package/source/services/tasks/data-transform/Ultravisor-TaskType-SetValues.cjs +74 -0
- package/source/services/tasks/data-transform/Ultravisor-TaskType-StringAppender.cjs +90 -0
- package/source/services/tasks/data-transform/definitions/comprehension-intersect.json +24 -0
- package/source/services/tasks/data-transform/definitions/csv-transform.json +24 -0
- package/source/services/tasks/data-transform/definitions/expression-solver.json +20 -0
- package/source/services/tasks/data-transform/definitions/histogram.json +23 -0
- package/source/services/tasks/data-transform/definitions/parse-csv.json +27 -0
- package/source/services/tasks/data-transform/definitions/replace-string.json +27 -0
- package/source/services/tasks/data-transform/definitions/set-values.json +17 -0
- package/source/services/tasks/data-transform/definitions/string-appender.json +22 -0
- package/source/services/tasks/data-transform/definitions/template-string.json +20 -0
- package/source/services/tasks/extension/Ultravisor-TaskConfigs-Extension.cjs +87 -0
- package/source/services/tasks/extension/definitions/beacon-dispatch.json +32 -0
- package/source/services/tasks/file-system/Ultravisor-TaskConfigs-FileSystem.cjs +509 -0
- package/source/services/tasks/file-system/Ultravisor-TaskType-ReadFile.cjs +96 -0
- package/source/services/tasks/file-system/Ultravisor-TaskType-ReadFileBuffered.cjs +123 -0
- package/source/services/tasks/file-system/Ultravisor-TaskType-WriteFile.cjs +106 -0
- package/source/services/tasks/file-system/definitions/copy-file.json +27 -0
- package/source/services/tasks/file-system/definitions/list-files.json +27 -0
- package/source/services/tasks/file-system/definitions/read-file-buffered.json +31 -0
- package/source/services/tasks/file-system/definitions/read-file.json +26 -0
- package/source/services/tasks/file-system/definitions/read-json.json +23 -0
- package/source/services/tasks/file-system/definitions/write-file.json +29 -0
- package/source/services/tasks/file-system/definitions/write-json.json +30 -0
- package/source/services/tasks/flow-control/Ultravisor-TaskConfigs-FlowControl.cjs +353 -0
- package/source/services/tasks/flow-control/Ultravisor-TaskType-IfConditional.cjs +125 -0
- package/source/services/tasks/flow-control/Ultravisor-TaskType-LaunchOperation.cjs +186 -0
- package/source/services/tasks/flow-control/Ultravisor-TaskType-SplitExecute.cjs +164 -0
- package/source/services/tasks/flow-control/definitions/if-conditional.json +25 -0
- package/source/services/tasks/flow-control/definitions/launch-operation.json +27 -0
- package/source/services/tasks/flow-control/definitions/split-execute.json +32 -0
- package/source/services/tasks/http-client/Ultravisor-TaskConfigs-HttpClient.cjs +281 -0
- package/source/services/tasks/http-client/definitions/get-json.json +26 -0
- package/source/services/tasks/http-client/definitions/get-text.json +26 -0
- package/source/services/tasks/http-client/definitions/rest-request.json +32 -0
- package/source/services/tasks/http-client/definitions/send-json.json +28 -0
- package/source/services/tasks/llm/Ultravisor-TaskConfigs-LLM.cjs +605 -0
- package/source/services/tasks/llm/definitions/llm-chat-completion.json +46 -0
- package/source/services/tasks/llm/definitions/llm-embedding.json +31 -0
- package/source/services/tasks/llm/definitions/llm-tool-use.json +42 -0
- package/source/services/tasks/meadow-api/Ultravisor-TaskConfigs-MeadowApi.cjs +341 -0
- package/source/services/tasks/meadow-api/definitions/meadow-count.json +26 -0
- package/source/services/tasks/meadow-api/definitions/meadow-create.json +26 -0
- package/source/services/tasks/meadow-api/definitions/meadow-delete.json +23 -0
- package/source/services/tasks/meadow-api/definitions/meadow-read.json +26 -0
- package/source/services/tasks/meadow-api/definitions/meadow-reads.json +29 -0
- package/source/services/tasks/meadow-api/definitions/meadow-update.json +26 -0
- package/source/services/tasks/shell/Ultravisor-TaskConfigs-Shell.cjs +63 -0
- package/source/services/tasks/shell/definitions/command.json +29 -0
- package/source/services/tasks/user-interaction/Ultravisor-TaskConfigs-UserInteraction.cjs +64 -0
- package/source/services/tasks/user-interaction/Ultravisor-TaskType-ErrorMessage.cjs +55 -0
- package/source/services/tasks/user-interaction/Ultravisor-TaskType-ValueInput.cjs +47 -0
- package/source/services/tasks/user-interaction/definitions/error-message.json +18 -0
- package/source/services/tasks/user-interaction/definitions/value-input.json +23 -0
- package/source/web_server/Ultravisor-API-Server.cjs +849 -124
- package/test/Ultravisor_browser_tests.js +2226 -0
- package/test/Ultravisor_operation_library_tests.js +894 -0
- package/test/Ultravisor_tests.js +4946 -5044
- package/test/workflows/test-content-concatenate-all.json +339 -0
- package/test/workflows/test-content-full-pipeline.json +159 -0
- package/test/workflows/test-content-list-files.json +76 -0
- package/test/workflows/test-content-save-and-read.json +106 -0
- package/webinterface/css/ultravisor-themes.css +668 -0
- package/webinterface/css/ultravisor.css +37 -14
- package/webinterface/docs/card-help/beacon-dispatch.md +30 -0
- package/webinterface/docs/card-help/command.md +27 -0
- package/webinterface/docs/card-help/comprehension-intersect.md +24 -0
- package/webinterface/docs/card-help/content-create-folder.md +22 -0
- package/webinterface/docs/card-help/content-list-files.md +25 -0
- package/webinterface/docs/card-help/content-read-file.md +24 -0
- package/webinterface/docs/card-help/content-save-file.md +24 -0
- package/webinterface/docs/card-help/copy-file.md +25 -0
- package/webinterface/docs/card-help/csv-transform.md +24 -0
- package/webinterface/docs/card-help/end.md +11 -0
- package/webinterface/docs/card-help/error-message.md +16 -0
- package/webinterface/docs/card-help/expression-solver.md +21 -0
- package/webinterface/docs/card-help/get-json.md +24 -0
- package/webinterface/docs/card-help/get-text.md +24 -0
- package/webinterface/docs/card-help/histogram.md +23 -0
- package/webinterface/docs/card-help/if-conditional.md +23 -0
- package/webinterface/docs/card-help/launch-operation.md +25 -0
- package/webinterface/docs/card-help/list-files.md +25 -0
- package/webinterface/docs/card-help/llm-chat-completion.md +43 -0
- package/webinterface/docs/card-help/llm-embedding.md +24 -0
- package/webinterface/docs/card-help/llm-tool-use.md +39 -0
- package/webinterface/docs/card-help/meadow-count.md +24 -0
- package/webinterface/docs/card-help/meadow-create.md +24 -0
- package/webinterface/docs/card-help/meadow-delete.md +19 -0
- package/webinterface/docs/card-help/meadow-read.md +24 -0
- package/webinterface/docs/card-help/meadow-reads.md +27 -0
- package/webinterface/docs/card-help/meadow-update.md +24 -0
- package/webinterface/docs/card-help/parse-csv.md +27 -0
- package/webinterface/docs/card-help/read-file-buffered.md +29 -0
- package/webinterface/docs/card-help/read-file.md +24 -0
- package/webinterface/docs/card-help/read-json.md +21 -0
- package/webinterface/docs/card-help/replace-string.md +25 -0
- package/webinterface/docs/card-help/rest-request.md +30 -0
- package/webinterface/docs/card-help/send-json.md +26 -0
- package/webinterface/docs/card-help/set-values.md +16 -0
- package/webinterface/docs/card-help/split-execute.md +35 -0
- package/webinterface/docs/card-help/start.md +11 -0
- package/webinterface/docs/card-help/string-appender.md +22 -0
- package/webinterface/docs/card-help/template-string.md +21 -0
- package/webinterface/docs/card-help/value-input.md +24 -0
- package/webinterface/docs/card-help/write-file.md +27 -0
- package/webinterface/docs/card-help/write-json.md +28 -0
- package/webinterface/html/index.html +5 -0
- package/webinterface/package.json +13 -4
- package/webinterface/source/Pict-Application-Ultravisor.js +564 -70
- package/webinterface/source/Ultravisor-TimingUtils.js +99 -0
- package/webinterface/source/card-help-content.js +46 -0
- package/webinterface/source/cards/Ultravisor-BuiltIn-CardConfigs.js +174 -0
- package/webinterface/source/cards/Ultravisor-CardConfigGenerator.js +431 -0
- package/webinterface/source/data/ExampleFlow-CSVPipeline.js +231 -0
- package/webinterface/source/data/ExampleFlow-FileProcessor.js +315 -0
- package/webinterface/source/data/ExampleFlow-MeadowPipeline.js +328 -0
- package/webinterface/source/panels/Ultravisor-CardSettingsPanel.js +902 -0
- package/webinterface/source/providers/PictRouter-Ultravisor-Configuration.json +20 -8
- package/webinterface/source/views/PictView-Ultravisor-BeaconList.js +817 -0
- package/webinterface/source/views/PictView-Ultravisor-BottomBar.js +5 -5
- package/webinterface/source/views/PictView-Ultravisor-Dashboard.js +25 -25
- package/webinterface/source/views/PictView-Ultravisor-Documentation.js +856 -0
- package/webinterface/source/views/PictView-Ultravisor-FlowEditor.js +777 -0
- package/webinterface/source/views/PictView-Ultravisor-ManifestList.js +321 -58
- package/webinterface/source/views/PictView-Ultravisor-OperationEdit.js +36 -91
- package/webinterface/source/views/PictView-Ultravisor-OperationList.js +388 -16
- package/webinterface/source/views/PictView-Ultravisor-PendingInput.js +314 -0
- package/webinterface/source/views/PictView-Ultravisor-Schedule.js +521 -65
- package/webinterface/source/views/PictView-Ultravisor-TimingView.js +333 -71
- package/webinterface/source/views/PictView-Ultravisor-TopBar.js +257 -21
- package/webinterface/theme-sampler.html +645 -0
- package/debug/Harness.js +0 -6
- package/source/services/Ultravisor-Operation-Manifest.cjs +0 -160
- package/source/services/Ultravisor-Operation.cjs +0 -200
- package/source/services/Ultravisor-Task.cjs +0 -349
- package/source/services/events/Ultravisor-Hypervisor-Event-Solver.cjs +0 -11
- package/source/services/tasks/Ultravisor-Task-Base.cjs +0 -264
- package/source/services/tasks/Ultravisor-Task-CollectValues.cjs +0 -188
- package/source/services/tasks/Ultravisor-Task-Command.cjs +0 -65
- package/source/services/tasks/Ultravisor-Task-CommandEach.cjs +0 -190
- package/source/services/tasks/Ultravisor-Task-Conditional.cjs +0 -104
- package/source/services/tasks/Ultravisor-Task-DateWindow.cjs +0 -72
- package/source/services/tasks/Ultravisor-Task-GeneratePagedOperation.cjs +0 -336
- package/source/services/tasks/Ultravisor-Task-LaunchOperation.cjs +0 -143
- package/source/services/tasks/Ultravisor-Task-LaunchTask.cjs +0 -146
- package/source/services/tasks/Ultravisor-Task-LineMatch.cjs +0 -158
- package/source/services/tasks/Ultravisor-Task-Request.cjs +0 -56
- package/source/services/tasks/Ultravisor-Task-Solver.cjs +0 -89
- package/source/services/tasks/Ultravisor-Task-TemplateString.cjs +0 -93
- package/source/services/tasks/rest/Ultravisor-Task-GetBinary.cjs +0 -127
- package/source/services/tasks/rest/Ultravisor-Task-GetJSON.cjs +0 -119
- package/source/services/tasks/rest/Ultravisor-Task-GetText.cjs +0 -109
- package/source/services/tasks/rest/Ultravisor-Task-GetXML.cjs +0 -112
- package/source/services/tasks/rest/Ultravisor-Task-RestRequest.cjs +0 -499
- package/source/services/tasks/rest/Ultravisor-Task-SendJSON.cjs +0 -150
- package/source/services/tasks/stagingfiles/Ultravisor-Task-CopyFile.cjs +0 -110
- package/source/services/tasks/stagingfiles/Ultravisor-Task-ListFiles.cjs +0 -89
- package/source/services/tasks/stagingfiles/Ultravisor-Task-ReadBinary.cjs +0 -87
- package/source/services/tasks/stagingfiles/Ultravisor-Task-ReadJSON.cjs +0 -67
- package/source/services/tasks/stagingfiles/Ultravisor-Task-ReadText.cjs +0 -66
- package/source/services/tasks/stagingfiles/Ultravisor-Task-ReadXML.cjs +0 -69
- package/source/services/tasks/stagingfiles/Ultravisor-Task-WriteBinary.cjs +0 -95
- package/source/services/tasks/stagingfiles/Ultravisor-Task-WriteJSON.cjs +0 -96
- package/source/services/tasks/stagingfiles/Ultravisor-Task-WriteText.cjs +0 -99
- package/source/services/tasks/stagingfiles/Ultravisor-Task-WriteXML.cjs +0 -102
- package/webinterface/source/views/PictView-Ultravisor-TaskEdit.js +0 -220
- package/webinterface/source/views/PictView-Ultravisor-TaskList.js +0 -248
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
const libPictService = require(`pict-serviceproviderbase`);
|
|
2
2
|
|
|
3
|
+
const libFS = require('fs');
|
|
3
4
|
const libPath = require('path');
|
|
4
5
|
const libOrator = require('orator');
|
|
5
6
|
const libOratorServiceServerRestify = require(`orator-serviceserver-restify`);
|
|
7
|
+
const libOratorAuthentication = require('orator-authentication');
|
|
6
8
|
|
|
7
9
|
class UltravisorAPIServer extends libPictService
|
|
8
10
|
{
|
|
@@ -16,6 +18,37 @@ class UltravisorAPIServer extends libPictService
|
|
|
16
18
|
|
|
17
19
|
// Add Orator as a service
|
|
18
20
|
this.fable.addServiceTypeIfNotExists('Orator', libOrator);
|
|
21
|
+
|
|
22
|
+
this._OratorAuth = null;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Get a service instance from the fable services map.
|
|
27
|
+
*/
|
|
28
|
+
_getService(pTypeName)
|
|
29
|
+
{
|
|
30
|
+
return this.fable.servicesMap[pTypeName]
|
|
31
|
+
? Object.values(this.fable.servicesMap[pTypeName])[0]
|
|
32
|
+
: null;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
_requireSession(pRequest, pResponse, fNext)
|
|
36
|
+
{
|
|
37
|
+
if (!this._OratorAuth)
|
|
38
|
+
{
|
|
39
|
+
return {};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
let tmpSession = this._OratorAuth.getSessionForRequest(pRequest);
|
|
43
|
+
|
|
44
|
+
if (!tmpSession)
|
|
45
|
+
{
|
|
46
|
+
pResponse.send(401, { Error: 'Authentication required.', LoggedIn: false });
|
|
47
|
+
fNext();
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return tmpSession;
|
|
19
52
|
}
|
|
20
53
|
|
|
21
54
|
wireEndpoints(fCallback)
|
|
@@ -41,11 +74,11 @@ class UltravisorAPIServer extends libPictService
|
|
|
41
74
|
'/status',
|
|
42
75
|
function (pRequest, pResponse, fNext)
|
|
43
76
|
{
|
|
44
|
-
let tmpHypervisor = this.
|
|
77
|
+
let tmpHypervisor = this._getService('UltravisorHypervisor');
|
|
45
78
|
pResponse.send({
|
|
46
79
|
Status: 'Running',
|
|
47
|
-
ScheduleEntries: tmpHypervisor.getSchedule().length,
|
|
48
|
-
ScheduleRunning: tmpHypervisor._Running
|
|
80
|
+
ScheduleEntries: tmpHypervisor ? tmpHypervisor.getSchedule().length : 0,
|
|
81
|
+
ScheduleRunning: tmpHypervisor ? tmpHypervisor._Running : false
|
|
49
82
|
});
|
|
50
83
|
return fNext();
|
|
51
84
|
}.bind(this)
|
|
@@ -57,29 +90,33 @@ class UltravisorAPIServer extends libPictService
|
|
|
57
90
|
function (pRequest, pResponse, fNext)
|
|
58
91
|
{
|
|
59
92
|
this.log.info(`Ultravisor API Server: Received stop request via API; stopping server.`);
|
|
60
|
-
let tmpHypervisor = this.
|
|
61
|
-
tmpHypervisor
|
|
93
|
+
let tmpHypervisor = this._getService('UltravisorHypervisor');
|
|
94
|
+
if (tmpHypervisor)
|
|
95
|
+
{
|
|
96
|
+
tmpHypervisor.stopSchedule();
|
|
97
|
+
}
|
|
62
98
|
pResponse.send({ "Status": "STOPPING" });
|
|
63
99
|
pResponse.end();
|
|
64
100
|
return this._Orator.stopService(fNext);
|
|
65
101
|
}.bind(this)
|
|
66
102
|
);
|
|
67
103
|
|
|
68
|
-
// ---
|
|
104
|
+
// --- Node Template CRUD ---
|
|
69
105
|
this._OratorServer.get
|
|
70
106
|
(
|
|
71
|
-
'/
|
|
107
|
+
'/NodeTemplate',
|
|
72
108
|
function (pRequest, pResponse, fNext)
|
|
73
109
|
{
|
|
74
|
-
this.
|
|
75
|
-
|
|
110
|
+
let tmpState = this._getService('UltravisorHypervisorState');
|
|
111
|
+
tmpState.getNodeTemplateList(
|
|
112
|
+
function (pError, pTemplates)
|
|
76
113
|
{
|
|
77
114
|
if (pError)
|
|
78
115
|
{
|
|
79
116
|
pResponse.send(500, { Error: pError.message });
|
|
80
117
|
return fNext();
|
|
81
118
|
}
|
|
82
|
-
pResponse.send(
|
|
119
|
+
pResponse.send(pTemplates);
|
|
83
120
|
return fNext();
|
|
84
121
|
});
|
|
85
122
|
}.bind(this)
|
|
@@ -87,18 +124,19 @@ class UltravisorAPIServer extends libPictService
|
|
|
87
124
|
|
|
88
125
|
this._OratorServer.get
|
|
89
126
|
(
|
|
90
|
-
'/
|
|
127
|
+
'/NodeTemplate/:Hash',
|
|
91
128
|
function (pRequest, pResponse, fNext)
|
|
92
129
|
{
|
|
93
|
-
this.
|
|
94
|
-
|
|
130
|
+
let tmpState = this._getService('UltravisorHypervisorState');
|
|
131
|
+
tmpState.getNodeTemplate(pRequest.params.Hash,
|
|
132
|
+
function (pError, pTemplate)
|
|
95
133
|
{
|
|
96
134
|
if (pError)
|
|
97
135
|
{
|
|
98
136
|
pResponse.send(404, { Error: pError.message });
|
|
99
137
|
return fNext();
|
|
100
138
|
}
|
|
101
|
-
pResponse.send(
|
|
139
|
+
pResponse.send(pTemplate);
|
|
102
140
|
return fNext();
|
|
103
141
|
});
|
|
104
142
|
}.bind(this)
|
|
@@ -106,18 +144,19 @@ class UltravisorAPIServer extends libPictService
|
|
|
106
144
|
|
|
107
145
|
this._OratorServer.post
|
|
108
146
|
(
|
|
109
|
-
'/
|
|
147
|
+
'/NodeTemplate',
|
|
110
148
|
function (pRequest, pResponse, fNext)
|
|
111
149
|
{
|
|
112
|
-
this.
|
|
113
|
-
|
|
150
|
+
let tmpState = this._getService('UltravisorHypervisorState');
|
|
151
|
+
tmpState.updateNodeTemplate(pRequest.body,
|
|
152
|
+
function (pError, pTemplate)
|
|
114
153
|
{
|
|
115
154
|
if (pError)
|
|
116
155
|
{
|
|
117
156
|
pResponse.send(400, { Error: pError.message });
|
|
118
157
|
return fNext();
|
|
119
158
|
}
|
|
120
|
-
pResponse.send(
|
|
159
|
+
pResponse.send(pTemplate);
|
|
121
160
|
return fNext();
|
|
122
161
|
});
|
|
123
162
|
}.bind(this)
|
|
@@ -125,20 +164,21 @@ class UltravisorAPIServer extends libPictService
|
|
|
125
164
|
|
|
126
165
|
this._OratorServer.put
|
|
127
166
|
(
|
|
128
|
-
'/
|
|
167
|
+
'/NodeTemplate/:Hash',
|
|
129
168
|
function (pRequest, pResponse, fNext)
|
|
130
169
|
{
|
|
131
|
-
let
|
|
132
|
-
|
|
133
|
-
this.
|
|
134
|
-
|
|
170
|
+
let tmpTemplateData = pRequest.body || {};
|
|
171
|
+
tmpTemplateData.Hash = pRequest.params.Hash;
|
|
172
|
+
let tmpState = this._getService('UltravisorHypervisorState');
|
|
173
|
+
tmpState.updateNodeTemplate(tmpTemplateData,
|
|
174
|
+
function (pError, pTemplate)
|
|
135
175
|
{
|
|
136
176
|
if (pError)
|
|
137
177
|
{
|
|
138
178
|
pResponse.send(400, { Error: pError.message });
|
|
139
179
|
return fNext();
|
|
140
180
|
}
|
|
141
|
-
pResponse.send(
|
|
181
|
+
pResponse.send(pTemplate);
|
|
142
182
|
return fNext();
|
|
143
183
|
});
|
|
144
184
|
}.bind(this)
|
|
@@ -146,21 +186,21 @@ class UltravisorAPIServer extends libPictService
|
|
|
146
186
|
|
|
147
187
|
this._OratorServer.del
|
|
148
188
|
(
|
|
149
|
-
'/
|
|
189
|
+
'/NodeTemplate/:Hash',
|
|
150
190
|
function (pRequest, pResponse, fNext)
|
|
151
191
|
{
|
|
152
|
-
let tmpState = this.
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
192
|
+
let tmpState = this._getService('UltravisorHypervisorState');
|
|
193
|
+
tmpState.deleteNodeTemplate(pRequest.params.Hash,
|
|
194
|
+
function (pError)
|
|
195
|
+
{
|
|
196
|
+
if (pError)
|
|
197
|
+
{
|
|
198
|
+
pResponse.send(404, { Error: pError.message });
|
|
199
|
+
return fNext();
|
|
200
|
+
}
|
|
201
|
+
pResponse.send({ Status: 'Deleted', Hash: pRequest.params.Hash });
|
|
202
|
+
return fNext();
|
|
203
|
+
});
|
|
164
204
|
}.bind(this)
|
|
165
205
|
);
|
|
166
206
|
|
|
@@ -170,7 +210,8 @@ class UltravisorAPIServer extends libPictService
|
|
|
170
210
|
'/Operation',
|
|
171
211
|
function (pRequest, pResponse, fNext)
|
|
172
212
|
{
|
|
173
|
-
this.
|
|
213
|
+
let tmpState = this._getService('UltravisorHypervisorState');
|
|
214
|
+
tmpState.getOperationList(
|
|
174
215
|
function (pError, pOperations)
|
|
175
216
|
{
|
|
176
217
|
if (pError)
|
|
@@ -186,10 +227,11 @@ class UltravisorAPIServer extends libPictService
|
|
|
186
227
|
|
|
187
228
|
this._OratorServer.get
|
|
188
229
|
(
|
|
189
|
-
'/Operation/:
|
|
230
|
+
'/Operation/:Hash',
|
|
190
231
|
function (pRequest, pResponse, fNext)
|
|
191
232
|
{
|
|
192
|
-
this.
|
|
233
|
+
let tmpState = this._getService('UltravisorHypervisorState');
|
|
234
|
+
tmpState.getOperation(pRequest.params.Hash,
|
|
193
235
|
function (pError, pOperation)
|
|
194
236
|
{
|
|
195
237
|
if (pError)
|
|
@@ -208,7 +250,8 @@ class UltravisorAPIServer extends libPictService
|
|
|
208
250
|
'/Operation',
|
|
209
251
|
function (pRequest, pResponse, fNext)
|
|
210
252
|
{
|
|
211
|
-
this.
|
|
253
|
+
let tmpState = this._getService('UltravisorHypervisorState');
|
|
254
|
+
tmpState.updateOperation(pRequest.body,
|
|
212
255
|
function (pError, pOperation)
|
|
213
256
|
{
|
|
214
257
|
if (pError)
|
|
@@ -224,12 +267,13 @@ class UltravisorAPIServer extends libPictService
|
|
|
224
267
|
|
|
225
268
|
this._OratorServer.put
|
|
226
269
|
(
|
|
227
|
-
'/Operation/:
|
|
270
|
+
'/Operation/:Hash',
|
|
228
271
|
function (pRequest, pResponse, fNext)
|
|
229
272
|
{
|
|
230
273
|
let tmpOperationData = pRequest.body || {};
|
|
231
|
-
tmpOperationData.
|
|
232
|
-
this.
|
|
274
|
+
tmpOperationData.Hash = pRequest.params.Hash;
|
|
275
|
+
let tmpState = this._getService('UltravisorHypervisorState');
|
|
276
|
+
tmpState.updateOperation(tmpOperationData,
|
|
233
277
|
function (pError, pOperation)
|
|
234
278
|
{
|
|
235
279
|
if (pError)
|
|
@@ -245,69 +289,34 @@ class UltravisorAPIServer extends libPictService
|
|
|
245
289
|
|
|
246
290
|
this._OratorServer.del
|
|
247
291
|
(
|
|
248
|
-
'/Operation/:
|
|
249
|
-
function (pRequest, pResponse, fNext)
|
|
250
|
-
{
|
|
251
|
-
let tmpState = this.fable['Ultravisor-Hypervisor-State'];
|
|
252
|
-
if (tmpState._Operations.hasOwnProperty(pRequest.params.GUIDOperation))
|
|
253
|
-
{
|
|
254
|
-
delete tmpState._Operations[pRequest.params.GUIDOperation];
|
|
255
|
-
tmpState.persistState();
|
|
256
|
-
pResponse.send({ Status: 'Deleted', GUIDOperation: pRequest.params.GUIDOperation });
|
|
257
|
-
}
|
|
258
|
-
else
|
|
259
|
-
{
|
|
260
|
-
pResponse.send(404, { Error: `Operation ${pRequest.params.GUIDOperation} not found.` });
|
|
261
|
-
}
|
|
262
|
-
return fNext();
|
|
263
|
-
}.bind(this)
|
|
264
|
-
);
|
|
265
|
-
|
|
266
|
-
// --- Task Execution ---
|
|
267
|
-
this._OratorServer.get
|
|
268
|
-
(
|
|
269
|
-
'/Task/:GUIDTask/Execute',
|
|
292
|
+
'/Operation/:Hash',
|
|
270
293
|
function (pRequest, pResponse, fNext)
|
|
271
294
|
{
|
|
272
|
-
let tmpState = this.
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
tmpState.getTask(pRequest.params.GUIDTask,
|
|
276
|
-
function (pError, pTask)
|
|
295
|
+
let tmpState = this._getService('UltravisorHypervisorState');
|
|
296
|
+
tmpState.deleteOperation(pRequest.params.Hash,
|
|
297
|
+
function (pError)
|
|
277
298
|
{
|
|
278
299
|
if (pError)
|
|
279
300
|
{
|
|
280
301
|
pResponse.send(404, { Error: pError.message });
|
|
281
302
|
return fNext();
|
|
282
303
|
}
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
if (pExecError)
|
|
287
|
-
{
|
|
288
|
-
pResponse.send(500, { Error: pExecError.message });
|
|
289
|
-
return fNext();
|
|
290
|
-
}
|
|
291
|
-
// Store the task result as a manifest so it appears in /Manifest
|
|
292
|
-
let tmpManifestService = this.fable['Ultravisor-Operation-Manifest'];
|
|
293
|
-
tmpManifestService.createTaskManifest(pManifestEntry);
|
|
294
|
-
pResponse.send(pManifestEntry);
|
|
295
|
-
return fNext();
|
|
296
|
-
}.bind(this));
|
|
297
|
-
}.bind(this));
|
|
304
|
+
pResponse.send({ Status: 'Deleted', Hash: pRequest.params.Hash });
|
|
305
|
+
return fNext();
|
|
306
|
+
});
|
|
298
307
|
}.bind(this)
|
|
299
308
|
);
|
|
300
309
|
|
|
301
310
|
// --- Operation Execution ---
|
|
302
311
|
this._OratorServer.get
|
|
303
312
|
(
|
|
304
|
-
'/Operation/:
|
|
313
|
+
'/Operation/:Hash/Execute',
|
|
305
314
|
function (pRequest, pResponse, fNext)
|
|
306
315
|
{
|
|
307
|
-
let tmpState = this.
|
|
308
|
-
let
|
|
316
|
+
let tmpState = this._getService('UltravisorHypervisorState');
|
|
317
|
+
let tmpEngine = this._getService('UltravisorExecutionEngine');
|
|
309
318
|
|
|
310
|
-
tmpState.getOperation(pRequest.params.
|
|
319
|
+
tmpState.getOperation(pRequest.params.Hash,
|
|
311
320
|
function (pError, pOperation)
|
|
312
321
|
{
|
|
313
322
|
if (pError)
|
|
@@ -315,51 +324,69 @@ class UltravisorAPIServer extends libPictService
|
|
|
315
324
|
pResponse.send(404, { Error: pError.message });
|
|
316
325
|
return fNext();
|
|
317
326
|
}
|
|
318
|
-
|
|
319
|
-
|
|
327
|
+
|
|
328
|
+
let tmpRunMode = (pRequest.query && pRequest.query.RunMode) || undefined;
|
|
329
|
+
let tmpInitialState = tmpRunMode ? { RunMode: tmpRunMode } : {};
|
|
330
|
+
|
|
331
|
+
tmpEngine.executeOperation(pOperation, tmpInitialState,
|
|
332
|
+
function (pExecError, pContext)
|
|
320
333
|
{
|
|
321
334
|
if (pExecError)
|
|
322
335
|
{
|
|
323
336
|
pResponse.send(500, { Error: pExecError.message });
|
|
324
337
|
return fNext();
|
|
325
338
|
}
|
|
326
|
-
pResponse.send(
|
|
339
|
+
pResponse.send({
|
|
340
|
+
Status: pContext.Status,
|
|
341
|
+
Hash: pContext.Hash,
|
|
342
|
+
OperationHash: pContext.OperationHash,
|
|
343
|
+
RunMode: pContext.RunMode,
|
|
344
|
+
Output: pContext.Output,
|
|
345
|
+
TaskOutputs: pContext.TaskOutputs,
|
|
346
|
+
Log: pContext.Log,
|
|
347
|
+
Errors: pContext.Errors,
|
|
348
|
+
StartTime: pContext.StartTime,
|
|
349
|
+
StopTime: pContext.StopTime,
|
|
350
|
+
ElapsedMs: pContext.ElapsedMs,
|
|
351
|
+
TaskManifests: pContext.TaskManifests,
|
|
352
|
+
TimingSummary: pContext.TimingSummary,
|
|
353
|
+
EventLog: pContext.EventLog,
|
|
354
|
+
WaitingTasks: pContext.WaitingTasks
|
|
355
|
+
});
|
|
327
356
|
return fNext();
|
|
328
357
|
});
|
|
329
358
|
});
|
|
330
359
|
}.bind(this)
|
|
331
360
|
);
|
|
332
361
|
|
|
333
|
-
// ---
|
|
362
|
+
// --- Task Types ---
|
|
334
363
|
this._OratorServer.get
|
|
335
364
|
(
|
|
336
|
-
'/
|
|
365
|
+
'/TaskType',
|
|
337
366
|
function (pRequest, pResponse, fNext)
|
|
338
367
|
{
|
|
339
|
-
|
|
368
|
+
let tmpRegistry = this._getService('UltravisorTaskTypeRegistry');
|
|
369
|
+
if (tmpRegistry)
|
|
370
|
+
{
|
|
371
|
+
pResponse.send(tmpRegistry.listDefinitions());
|
|
372
|
+
}
|
|
373
|
+
else
|
|
374
|
+
{
|
|
375
|
+
pResponse.send([]);
|
|
376
|
+
}
|
|
340
377
|
return fNext();
|
|
341
378
|
}.bind(this)
|
|
342
379
|
);
|
|
343
380
|
|
|
344
|
-
|
|
381
|
+
// --- Schedule ---
|
|
382
|
+
this._OratorServer.get
|
|
345
383
|
(
|
|
346
|
-
'/Schedule
|
|
384
|
+
'/Schedule',
|
|
347
385
|
function (pRequest, pResponse, fNext)
|
|
348
386
|
{
|
|
349
|
-
let
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
tmpHypervisor.scheduleTask(tmpBody.GUIDTask, tmpBody.ScheduleType, tmpBody.Parameters,
|
|
353
|
-
function (pError, pEntry)
|
|
354
|
-
{
|
|
355
|
-
if (pError)
|
|
356
|
-
{
|
|
357
|
-
pResponse.send(400, { Error: pError.message });
|
|
358
|
-
return fNext();
|
|
359
|
-
}
|
|
360
|
-
pResponse.send(pEntry);
|
|
361
|
-
return fNext();
|
|
362
|
-
});
|
|
387
|
+
let tmpHypervisor = this._getService('UltravisorHypervisor');
|
|
388
|
+
pResponse.send(tmpHypervisor ? tmpHypervisor.getSchedule() : []);
|
|
389
|
+
return fNext();
|
|
363
390
|
}.bind(this)
|
|
364
391
|
);
|
|
365
392
|
|
|
@@ -369,9 +396,9 @@ class UltravisorAPIServer extends libPictService
|
|
|
369
396
|
function (pRequest, pResponse, fNext)
|
|
370
397
|
{
|
|
371
398
|
let tmpBody = pRequest.body || {};
|
|
372
|
-
let tmpHypervisor = this.
|
|
399
|
+
let tmpHypervisor = this._getService('UltravisorHypervisor');
|
|
373
400
|
|
|
374
|
-
tmpHypervisor.scheduleOperation(tmpBody.
|
|
401
|
+
tmpHypervisor.scheduleOperation(tmpBody.Hash, tmpBody.ScheduleType, tmpBody.Parameters,
|
|
375
402
|
function (pError, pEntry)
|
|
376
403
|
{
|
|
377
404
|
if (pError)
|
|
@@ -390,7 +417,8 @@ class UltravisorAPIServer extends libPictService
|
|
|
390
417
|
'/Schedule/:GUID',
|
|
391
418
|
function (pRequest, pResponse, fNext)
|
|
392
419
|
{
|
|
393
|
-
this.
|
|
420
|
+
let tmpHypervisor = this._getService('UltravisorHypervisor');
|
|
421
|
+
tmpHypervisor.removeScheduleEntry(pRequest.params.GUID,
|
|
394
422
|
function (pError, pResult)
|
|
395
423
|
{
|
|
396
424
|
if (pError)
|
|
@@ -409,7 +437,8 @@ class UltravisorAPIServer extends libPictService
|
|
|
409
437
|
'/Schedule/Start',
|
|
410
438
|
function (pRequest, pResponse, fNext)
|
|
411
439
|
{
|
|
412
|
-
this.
|
|
440
|
+
let tmpHypervisor = this._getService('UltravisorHypervisor');
|
|
441
|
+
tmpHypervisor.startSchedule(
|
|
413
442
|
function ()
|
|
414
443
|
{
|
|
415
444
|
pResponse.send({ Status: 'Schedule Started' });
|
|
@@ -418,12 +447,33 @@ class UltravisorAPIServer extends libPictService
|
|
|
418
447
|
}.bind(this)
|
|
419
448
|
);
|
|
420
449
|
|
|
450
|
+
this._OratorServer.get
|
|
451
|
+
(
|
|
452
|
+
'/Schedule/Start/:GUID',
|
|
453
|
+
function (pRequest, pResponse, fNext)
|
|
454
|
+
{
|
|
455
|
+
let tmpHypervisor = this._getService('UltravisorHypervisor');
|
|
456
|
+
tmpHypervisor.startScheduleEntry(pRequest.params.GUID,
|
|
457
|
+
function (pError, pEntry)
|
|
458
|
+
{
|
|
459
|
+
if (pError)
|
|
460
|
+
{
|
|
461
|
+
pResponse.send(404, { Error: pError.message });
|
|
462
|
+
return fNext();
|
|
463
|
+
}
|
|
464
|
+
pResponse.send({ Status: 'Entry Started', Entry: pEntry });
|
|
465
|
+
return fNext();
|
|
466
|
+
});
|
|
467
|
+
}.bind(this)
|
|
468
|
+
);
|
|
469
|
+
|
|
421
470
|
this._OratorServer.get
|
|
422
471
|
(
|
|
423
472
|
'/Schedule/Stop',
|
|
424
473
|
function (pRequest, pResponse, fNext)
|
|
425
474
|
{
|
|
426
|
-
this.
|
|
475
|
+
let tmpHypervisor = this._getService('UltravisorHypervisor');
|
|
476
|
+
tmpHypervisor.stopSchedule(
|
|
427
477
|
function ()
|
|
428
478
|
{
|
|
429
479
|
pResponse.send({ Status: 'Schedule Stopped' });
|
|
@@ -432,35 +482,694 @@ class UltravisorAPIServer extends libPictService
|
|
|
432
482
|
}.bind(this)
|
|
433
483
|
);
|
|
434
484
|
|
|
485
|
+
this._OratorServer.get
|
|
486
|
+
(
|
|
487
|
+
'/Schedule/Stop/:GUID',
|
|
488
|
+
function (pRequest, pResponse, fNext)
|
|
489
|
+
{
|
|
490
|
+
let tmpHypervisor = this._getService('UltravisorHypervisor');
|
|
491
|
+
tmpHypervisor.stopScheduleEntry(pRequest.params.GUID,
|
|
492
|
+
function (pError, pEntry)
|
|
493
|
+
{
|
|
494
|
+
if (pError)
|
|
495
|
+
{
|
|
496
|
+
pResponse.send(404, { Error: pError.message });
|
|
497
|
+
return fNext();
|
|
498
|
+
}
|
|
499
|
+
pResponse.send({ Status: 'Entry Stopped', Entry: pEntry });
|
|
500
|
+
return fNext();
|
|
501
|
+
});
|
|
502
|
+
}.bind(this)
|
|
503
|
+
);
|
|
504
|
+
|
|
435
505
|
// --- Manifests ---
|
|
436
506
|
this._OratorServer.get
|
|
437
507
|
(
|
|
438
508
|
'/Manifest',
|
|
439
509
|
function (pRequest, pResponse, fNext)
|
|
440
510
|
{
|
|
441
|
-
|
|
511
|
+
let tmpManifest = this._getService('UltravisorExecutionManifest');
|
|
512
|
+
pResponse.send(tmpManifest ? tmpManifest.listRuns() : []);
|
|
442
513
|
return fNext();
|
|
443
514
|
}.bind(this)
|
|
444
515
|
);
|
|
445
516
|
|
|
446
517
|
this._OratorServer.get
|
|
447
518
|
(
|
|
448
|
-
'/Manifest/:
|
|
519
|
+
'/Manifest/:RunHash',
|
|
449
520
|
function (pRequest, pResponse, fNext)
|
|
450
521
|
{
|
|
451
|
-
let tmpManifest = this.
|
|
452
|
-
|
|
522
|
+
let tmpManifest = this._getService('UltravisorExecutionManifest');
|
|
523
|
+
let tmpRun = tmpManifest ? tmpManifest.getRun(pRequest.params.RunHash) : null;
|
|
524
|
+
if (tmpRun)
|
|
453
525
|
{
|
|
454
|
-
pResponse.send(
|
|
526
|
+
pResponse.send(tmpRun);
|
|
455
527
|
}
|
|
456
528
|
else
|
|
457
529
|
{
|
|
458
|
-
pResponse.send(404, { Error: `Manifest ${pRequest.params.
|
|
530
|
+
pResponse.send(404, { Error: `Manifest ${pRequest.params.RunHash} not found.` });
|
|
531
|
+
}
|
|
532
|
+
return fNext();
|
|
533
|
+
}.bind(this)
|
|
534
|
+
);
|
|
535
|
+
|
|
536
|
+
// --- Pending Inputs ---
|
|
537
|
+
this._OratorServer.get
|
|
538
|
+
(
|
|
539
|
+
'/PendingInput',
|
|
540
|
+
function (pRequest, pResponse, fNext)
|
|
541
|
+
{
|
|
542
|
+
let tmpManifest = this._getService('UltravisorExecutionManifest');
|
|
543
|
+
if (!tmpManifest)
|
|
544
|
+
{
|
|
545
|
+
pResponse.send([]);
|
|
546
|
+
return fNext();
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
let tmpRuns = tmpManifest.listRuns();
|
|
550
|
+
let tmpPending = [];
|
|
551
|
+
|
|
552
|
+
for (let i = 0; i < tmpRuns.length; i++)
|
|
553
|
+
{
|
|
554
|
+
if (tmpRuns[i].Status === 'WaitingForInput')
|
|
555
|
+
{
|
|
556
|
+
let tmpFullRun = tmpManifest.getRun(tmpRuns[i].Hash);
|
|
557
|
+
if (tmpFullRun)
|
|
558
|
+
{
|
|
559
|
+
tmpPending.push({
|
|
560
|
+
RunHash: tmpFullRun.Hash,
|
|
561
|
+
OperationHash: tmpFullRun.OperationHash,
|
|
562
|
+
OperationName: tmpFullRun.OperationName,
|
|
563
|
+
StartTime: tmpFullRun.StartTime,
|
|
564
|
+
WaitingTasks: tmpFullRun.WaitingTasks
|
|
565
|
+
});
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
pResponse.send(tmpPending);
|
|
571
|
+
return fNext();
|
|
572
|
+
}.bind(this)
|
|
573
|
+
);
|
|
574
|
+
|
|
575
|
+
this._OratorServer.post
|
|
576
|
+
(
|
|
577
|
+
'/PendingInput/:RunHash',
|
|
578
|
+
function (pRequest, pResponse, fNext)
|
|
579
|
+
{
|
|
580
|
+
let tmpBody = pRequest.body || {};
|
|
581
|
+
let tmpEngine = this._getService('UltravisorExecutionEngine');
|
|
582
|
+
let tmpRunHash = pRequest.params.RunHash;
|
|
583
|
+
|
|
584
|
+
if (!tmpBody.NodeHash)
|
|
585
|
+
{
|
|
586
|
+
pResponse.send(400, { Error: 'NodeHash is required.' });
|
|
587
|
+
return fNext();
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
tmpEngine.resumeOperation(tmpRunHash, tmpBody.NodeHash, tmpBody.Value,
|
|
591
|
+
function (pError, pContext)
|
|
592
|
+
{
|
|
593
|
+
if (pError)
|
|
594
|
+
{
|
|
595
|
+
pResponse.send(400, { Error: pError.message });
|
|
596
|
+
return fNext();
|
|
597
|
+
}
|
|
598
|
+
pResponse.send({
|
|
599
|
+
Status: pContext.Status,
|
|
600
|
+
Hash: pContext.Hash,
|
|
601
|
+
TaskOutputs: pContext.TaskOutputs,
|
|
602
|
+
Log: pContext.Log,
|
|
603
|
+
Errors: pContext.Errors,
|
|
604
|
+
WaitingTasks: pContext.WaitingTasks
|
|
605
|
+
});
|
|
606
|
+
return fNext();
|
|
607
|
+
});
|
|
608
|
+
}.bind(this)
|
|
609
|
+
);
|
|
610
|
+
|
|
611
|
+
// --- Operation Resume (for value-input tasks) ---
|
|
612
|
+
this._OratorServer.post
|
|
613
|
+
(
|
|
614
|
+
'/Operation/Resume',
|
|
615
|
+
function (pRequest, pResponse, fNext)
|
|
616
|
+
{
|
|
617
|
+
let tmpBody = pRequest.body || {};
|
|
618
|
+
let tmpEngine = this._getService('UltravisorExecutionEngine');
|
|
619
|
+
|
|
620
|
+
if (!tmpBody.RunHash || !tmpBody.NodeHash)
|
|
621
|
+
{
|
|
622
|
+
pResponse.send(400, { Error: 'RunHash and NodeHash are required.' });
|
|
623
|
+
return fNext();
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
tmpEngine.resumeOperation(tmpBody.RunHash, tmpBody.NodeHash, tmpBody.Value,
|
|
627
|
+
function (pError, pContext)
|
|
628
|
+
{
|
|
629
|
+
if (pError)
|
|
630
|
+
{
|
|
631
|
+
pResponse.send(400, { Error: pError.message });
|
|
632
|
+
return fNext();
|
|
633
|
+
}
|
|
634
|
+
pResponse.send({
|
|
635
|
+
Status: pContext.Status,
|
|
636
|
+
Hash: pContext.Hash,
|
|
637
|
+
TaskOutputs: pContext.TaskOutputs,
|
|
638
|
+
Log: pContext.Log,
|
|
639
|
+
Errors: pContext.Errors,
|
|
640
|
+
WaitingTasks: pContext.WaitingTasks
|
|
641
|
+
});
|
|
642
|
+
return fNext();
|
|
643
|
+
});
|
|
644
|
+
}.bind(this)
|
|
645
|
+
);
|
|
646
|
+
|
|
647
|
+
// --- Operation Library ---
|
|
648
|
+
this._OratorServer.get
|
|
649
|
+
(
|
|
650
|
+
'/OperationLibrary',
|
|
651
|
+
function (pRequest, pResponse, fNext)
|
|
652
|
+
{
|
|
653
|
+
let tmpLibraryPath = this.fable?.ProgramConfiguration?.UltravisorOperationLibraryPath;
|
|
654
|
+
if (!tmpLibraryPath)
|
|
655
|
+
{
|
|
656
|
+
pResponse.send([]);
|
|
657
|
+
return fNext();
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
let tmpResolvedPath = libPath.resolve(process.cwd(), tmpLibraryPath);
|
|
661
|
+
|
|
662
|
+
let tmpFiles;
|
|
663
|
+
try
|
|
664
|
+
{
|
|
665
|
+
tmpFiles = libFS.readdirSync(tmpResolvedPath);
|
|
666
|
+
}
|
|
667
|
+
catch (pError)
|
|
668
|
+
{
|
|
669
|
+
this.log.warn(`OperationLibrary: could not read directory [${tmpResolvedPath}]: ${pError.message}`);
|
|
670
|
+
pResponse.send([]);
|
|
671
|
+
return fNext();
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
let tmpLibraryItems = [];
|
|
675
|
+
|
|
676
|
+
for (let i = 0; i < tmpFiles.length; i++)
|
|
677
|
+
{
|
|
678
|
+
let tmpFileName = tmpFiles[i];
|
|
679
|
+
if (!tmpFileName.endsWith('.json'))
|
|
680
|
+
{
|
|
681
|
+
continue;
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
try
|
|
685
|
+
{
|
|
686
|
+
let tmpFilePath = libPath.join(tmpResolvedPath, tmpFileName);
|
|
687
|
+
let tmpContent = libFS.readFileSync(tmpFilePath, 'utf8');
|
|
688
|
+
let tmpOperation = JSON.parse(tmpContent);
|
|
689
|
+
|
|
690
|
+
tmpLibraryItems.push({
|
|
691
|
+
FileName: tmpFileName,
|
|
692
|
+
Name: tmpOperation.Name || tmpFileName,
|
|
693
|
+
Description: tmpOperation.Description || '',
|
|
694
|
+
Tags: tmpOperation.Tags || [],
|
|
695
|
+
Author: tmpOperation.Author || '',
|
|
696
|
+
Version: tmpOperation.Version || '',
|
|
697
|
+
NodeCount: (tmpOperation.Graph && tmpOperation.Graph.Nodes) ? tmpOperation.Graph.Nodes.length : 0
|
|
698
|
+
});
|
|
699
|
+
}
|
|
700
|
+
catch (pError)
|
|
701
|
+
{
|
|
702
|
+
this.log.warn(`OperationLibrary: could not parse [${tmpFileName}]: ${pError.message}`);
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
tmpLibraryItems.sort(
|
|
707
|
+
function (a, b)
|
|
708
|
+
{
|
|
709
|
+
return a.Name.localeCompare(b.Name);
|
|
710
|
+
});
|
|
711
|
+
|
|
712
|
+
pResponse.send(tmpLibraryItems);
|
|
713
|
+
return fNext();
|
|
714
|
+
}.bind(this)
|
|
715
|
+
);
|
|
716
|
+
|
|
717
|
+
this._OratorServer.get
|
|
718
|
+
(
|
|
719
|
+
'/OperationLibrary/:FileName',
|
|
720
|
+
function (pRequest, pResponse, fNext)
|
|
721
|
+
{
|
|
722
|
+
let tmpFileName = pRequest.params.FileName;
|
|
723
|
+
|
|
724
|
+
// Security: prevent directory traversal
|
|
725
|
+
if (!tmpFileName || !tmpFileName.endsWith('.json') ||
|
|
726
|
+
tmpFileName.indexOf('/') >= 0 || tmpFileName.indexOf('\\') >= 0 ||
|
|
727
|
+
tmpFileName.indexOf('..') >= 0)
|
|
728
|
+
{
|
|
729
|
+
pResponse.send(400, { Error: 'Invalid file name.' });
|
|
730
|
+
return fNext();
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
let tmpLibraryPath = this.fable?.ProgramConfiguration?.UltravisorOperationLibraryPath;
|
|
734
|
+
if (!tmpLibraryPath)
|
|
735
|
+
{
|
|
736
|
+
pResponse.send(404, { Error: 'Operation library not configured.' });
|
|
737
|
+
return fNext();
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
let tmpResolvedPath = libPath.resolve(process.cwd(), tmpLibraryPath);
|
|
741
|
+
let tmpFilePath = libPath.join(tmpResolvedPath, tmpFileName);
|
|
742
|
+
|
|
743
|
+
try
|
|
744
|
+
{
|
|
745
|
+
let tmpContent = libFS.readFileSync(tmpFilePath, 'utf8');
|
|
746
|
+
let tmpOperation = JSON.parse(tmpContent);
|
|
747
|
+
pResponse.send(tmpOperation);
|
|
748
|
+
}
|
|
749
|
+
catch (pError)
|
|
750
|
+
{
|
|
751
|
+
pResponse.send(404, { Error: `Library operation [${tmpFileName}] not found.` });
|
|
752
|
+
}
|
|
753
|
+
return fNext();
|
|
754
|
+
}.bind(this)
|
|
755
|
+
);
|
|
756
|
+
|
|
757
|
+
// --- Operation Export ---
|
|
758
|
+
this._OratorServer.get
|
|
759
|
+
(
|
|
760
|
+
'/Operation/:Hash/Export',
|
|
761
|
+
function (pRequest, pResponse, fNext)
|
|
762
|
+
{
|
|
763
|
+
let tmpState = this._getService('UltravisorHypervisorState');
|
|
764
|
+
tmpState.getOperation(pRequest.params.Hash,
|
|
765
|
+
function (pError, pOperation)
|
|
766
|
+
{
|
|
767
|
+
if (pError)
|
|
768
|
+
{
|
|
769
|
+
pResponse.send(404, { Error: pError.message });
|
|
770
|
+
return fNext();
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
let tmpExport = {
|
|
774
|
+
Hash: pOperation.Hash,
|
|
775
|
+
Name: pOperation.Name || '',
|
|
776
|
+
Description: pOperation.Description || '',
|
|
777
|
+
Graph: pOperation.Graph || { Nodes: [], Connections: [], ViewState: {} },
|
|
778
|
+
SavedLayouts: pOperation.SavedLayouts || [],
|
|
779
|
+
InitialGlobalState: pOperation.InitialGlobalState || {},
|
|
780
|
+
InitialOperationState: pOperation.InitialOperationState || {},
|
|
781
|
+
ExportedAt: new Date().toISOString()
|
|
782
|
+
};
|
|
783
|
+
|
|
784
|
+
pResponse.send(tmpExport);
|
|
785
|
+
return fNext();
|
|
786
|
+
});
|
|
787
|
+
}.bind(this)
|
|
788
|
+
);
|
|
789
|
+
|
|
790
|
+
// ===================================================================
|
|
791
|
+
// Beacon Worker Endpoints
|
|
792
|
+
// ===================================================================
|
|
793
|
+
|
|
794
|
+
// --- Beacon Registration ---
|
|
795
|
+
this._OratorServer.post
|
|
796
|
+
(
|
|
797
|
+
'/Beacon/Register',
|
|
798
|
+
function (pRequest, pResponse, fNext)
|
|
799
|
+
{
|
|
800
|
+
let tmpSession = this._requireSession(pRequest, pResponse, fNext);
|
|
801
|
+
if (!tmpSession) { return; }
|
|
802
|
+
|
|
803
|
+
let tmpCoordinator = this._getService('UltravisorBeaconCoordinator');
|
|
804
|
+
if (!tmpCoordinator)
|
|
805
|
+
{
|
|
806
|
+
pResponse.send(500, { Error: 'BeaconCoordinator service not available.' });
|
|
807
|
+
return fNext();
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
let tmpBody = pRequest.body || {};
|
|
811
|
+
if (!tmpBody.Name || !tmpBody.Capabilities)
|
|
812
|
+
{
|
|
813
|
+
pResponse.send(400, { Error: 'Name and Capabilities are required.' });
|
|
814
|
+
return fNext();
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
let tmpBeacon = tmpCoordinator.registerBeacon(tmpBody, tmpSession.SessionID);
|
|
818
|
+
pResponse.send(tmpBeacon);
|
|
819
|
+
return fNext();
|
|
820
|
+
}.bind(this)
|
|
821
|
+
);
|
|
822
|
+
|
|
823
|
+
// --- List Beacons (no auth – management UI) ---
|
|
824
|
+
this._OratorServer.get
|
|
825
|
+
(
|
|
826
|
+
'/Beacon',
|
|
827
|
+
function (pRequest, pResponse, fNext)
|
|
828
|
+
{
|
|
829
|
+
let tmpCoordinator = this._getService('UltravisorBeaconCoordinator');
|
|
830
|
+
if (!tmpCoordinator)
|
|
831
|
+
{
|
|
832
|
+
pResponse.send([]);
|
|
833
|
+
return fNext();
|
|
834
|
+
}
|
|
835
|
+
|
|
836
|
+
pResponse.send(tmpCoordinator.listBeacons());
|
|
837
|
+
return fNext();
|
|
838
|
+
}.bind(this)
|
|
839
|
+
);
|
|
840
|
+
|
|
841
|
+
// --- List Work Items (no auth – management UI) ---
|
|
842
|
+
this._OratorServer.get
|
|
843
|
+
(
|
|
844
|
+
'/Beacon/Work',
|
|
845
|
+
function (pRequest, pResponse, fNext)
|
|
846
|
+
{
|
|
847
|
+
let tmpCoordinator = this._getService('UltravisorBeaconCoordinator');
|
|
848
|
+
if (!tmpCoordinator)
|
|
849
|
+
{
|
|
850
|
+
pResponse.send([]);
|
|
851
|
+
return fNext();
|
|
852
|
+
}
|
|
853
|
+
|
|
854
|
+
pResponse.send(tmpCoordinator.listWorkItems());
|
|
855
|
+
return fNext();
|
|
856
|
+
}.bind(this)
|
|
857
|
+
);
|
|
858
|
+
|
|
859
|
+
// --- List Affinity Bindings (no auth – management UI) ---
|
|
860
|
+
this._OratorServer.get
|
|
861
|
+
(
|
|
862
|
+
'/Beacon/Affinity',
|
|
863
|
+
function (pRequest, pResponse, fNext)
|
|
864
|
+
{
|
|
865
|
+
let tmpCoordinator = this._getService('UltravisorBeaconCoordinator');
|
|
866
|
+
if (!tmpCoordinator)
|
|
867
|
+
{
|
|
868
|
+
pResponse.send([]);
|
|
869
|
+
return fNext();
|
|
870
|
+
}
|
|
871
|
+
|
|
872
|
+
pResponse.send(tmpCoordinator.listAffinityBindings());
|
|
873
|
+
return fNext();
|
|
874
|
+
}.bind(this)
|
|
875
|
+
);
|
|
876
|
+
|
|
877
|
+
// --- Get Specific Beacon (no auth – management UI) ---
|
|
878
|
+
this._OratorServer.get
|
|
879
|
+
(
|
|
880
|
+
'/Beacon/:BeaconID',
|
|
881
|
+
function (pRequest, pResponse, fNext)
|
|
882
|
+
{
|
|
883
|
+
let tmpCoordinator = this._getService('UltravisorBeaconCoordinator');
|
|
884
|
+
if (!tmpCoordinator)
|
|
885
|
+
{
|
|
886
|
+
pResponse.send(404, { Error: 'BeaconCoordinator service not available.' });
|
|
887
|
+
return fNext();
|
|
888
|
+
}
|
|
889
|
+
|
|
890
|
+
let tmpBeacon = tmpCoordinator.getBeacon(pRequest.params.BeaconID);
|
|
891
|
+
if (!tmpBeacon)
|
|
892
|
+
{
|
|
893
|
+
pResponse.send(404, { Error: `Beacon [${pRequest.params.BeaconID}] not found.` });
|
|
894
|
+
return fNext();
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
pResponse.send(tmpBeacon);
|
|
898
|
+
return fNext();
|
|
899
|
+
}.bind(this)
|
|
900
|
+
);
|
|
901
|
+
|
|
902
|
+
// --- Deregister Beacon (no auth – management UI) ---
|
|
903
|
+
this._OratorServer.del
|
|
904
|
+
(
|
|
905
|
+
'/Beacon/:BeaconID',
|
|
906
|
+
function (pRequest, pResponse, fNext)
|
|
907
|
+
{
|
|
908
|
+
let tmpCoordinator = this._getService('UltravisorBeaconCoordinator');
|
|
909
|
+
if (!tmpCoordinator)
|
|
910
|
+
{
|
|
911
|
+
pResponse.send(500, { Error: 'BeaconCoordinator service not available.' });
|
|
912
|
+
return fNext();
|
|
913
|
+
}
|
|
914
|
+
|
|
915
|
+
let tmpRemoved = tmpCoordinator.deregisterBeacon(pRequest.params.BeaconID);
|
|
916
|
+
if (!tmpRemoved)
|
|
917
|
+
{
|
|
918
|
+
pResponse.send(404, { Error: `Beacon [${pRequest.params.BeaconID}] not found.` });
|
|
919
|
+
return fNext();
|
|
920
|
+
}
|
|
921
|
+
|
|
922
|
+
pResponse.send({ Status: 'Deregistered', BeaconID: pRequest.params.BeaconID });
|
|
923
|
+
return fNext();
|
|
924
|
+
}.bind(this)
|
|
925
|
+
);
|
|
926
|
+
|
|
927
|
+
// --- Beacon Heartbeat ---
|
|
928
|
+
this._OratorServer.post
|
|
929
|
+
(
|
|
930
|
+
'/Beacon/:BeaconID/Heartbeat',
|
|
931
|
+
function (pRequest, pResponse, fNext)
|
|
932
|
+
{
|
|
933
|
+
let tmpSession = this._requireSession(pRequest, pResponse, fNext);
|
|
934
|
+
if (!tmpSession) { return; }
|
|
935
|
+
|
|
936
|
+
let tmpCoordinator = this._getService('UltravisorBeaconCoordinator');
|
|
937
|
+
if (!tmpCoordinator)
|
|
938
|
+
{
|
|
939
|
+
pResponse.send(500, { Error: 'BeaconCoordinator service not available.' });
|
|
940
|
+
return fNext();
|
|
941
|
+
}
|
|
942
|
+
|
|
943
|
+
let tmpBeacon = tmpCoordinator.heartbeat(pRequest.params.BeaconID);
|
|
944
|
+
if (!tmpBeacon)
|
|
945
|
+
{
|
|
946
|
+
pResponse.send(404, { Error: `Beacon [${pRequest.params.BeaconID}] not found.` });
|
|
947
|
+
return fNext();
|
|
459
948
|
}
|
|
949
|
+
|
|
950
|
+
pResponse.send(tmpBeacon);
|
|
460
951
|
return fNext();
|
|
461
952
|
}.bind(this)
|
|
462
953
|
);
|
|
463
954
|
|
|
955
|
+
// --- Poll for Work ---
|
|
956
|
+
this._OratorServer.post
|
|
957
|
+
(
|
|
958
|
+
'/Beacon/Work/Poll',
|
|
959
|
+
function (pRequest, pResponse, fNext)
|
|
960
|
+
{
|
|
961
|
+
let tmpSession = this._requireSession(pRequest, pResponse, fNext);
|
|
962
|
+
if (!tmpSession) { return; }
|
|
963
|
+
|
|
964
|
+
let tmpCoordinator = this._getService('UltravisorBeaconCoordinator');
|
|
965
|
+
if (!tmpCoordinator)
|
|
966
|
+
{
|
|
967
|
+
pResponse.send(500, { Error: 'BeaconCoordinator service not available.' });
|
|
968
|
+
return fNext();
|
|
969
|
+
}
|
|
970
|
+
|
|
971
|
+
let tmpBody = pRequest.body || {};
|
|
972
|
+
if (!tmpBody.BeaconID)
|
|
973
|
+
{
|
|
974
|
+
pResponse.send(400, { Error: 'BeaconID is required.' });
|
|
975
|
+
return fNext();
|
|
976
|
+
}
|
|
977
|
+
|
|
978
|
+
let tmpWorkItem = tmpCoordinator.pollForWork(tmpBody.BeaconID);
|
|
979
|
+
pResponse.send({ WorkItem: tmpWorkItem });
|
|
980
|
+
return fNext();
|
|
981
|
+
}.bind(this)
|
|
982
|
+
);
|
|
983
|
+
|
|
984
|
+
// --- Complete Work Item ---
|
|
985
|
+
this._OratorServer.post
|
|
986
|
+
(
|
|
987
|
+
'/Beacon/Work/:WorkItemHash/Complete',
|
|
988
|
+
function (pRequest, pResponse, fNext)
|
|
989
|
+
{
|
|
990
|
+
let tmpSession = this._requireSession(pRequest, pResponse, fNext);
|
|
991
|
+
if (!tmpSession) { return; }
|
|
992
|
+
|
|
993
|
+
let tmpCoordinator = this._getService('UltravisorBeaconCoordinator');
|
|
994
|
+
if (!tmpCoordinator)
|
|
995
|
+
{
|
|
996
|
+
pResponse.send(500, { Error: 'BeaconCoordinator service not available.' });
|
|
997
|
+
return fNext();
|
|
998
|
+
}
|
|
999
|
+
|
|
1000
|
+
let tmpBody = pRequest.body || {};
|
|
1001
|
+
tmpCoordinator.completeWorkItem(pRequest.params.WorkItemHash,
|
|
1002
|
+
{ Outputs: tmpBody.Outputs || {}, Log: tmpBody.Log || [] },
|
|
1003
|
+
function (pError)
|
|
1004
|
+
{
|
|
1005
|
+
if (pError)
|
|
1006
|
+
{
|
|
1007
|
+
pResponse.send(400, { Error: pError.message });
|
|
1008
|
+
return fNext();
|
|
1009
|
+
}
|
|
1010
|
+
|
|
1011
|
+
pResponse.send({ Status: 'Completed', WorkItemHash: pRequest.params.WorkItemHash });
|
|
1012
|
+
return fNext();
|
|
1013
|
+
});
|
|
1014
|
+
}.bind(this)
|
|
1015
|
+
);
|
|
1016
|
+
|
|
1017
|
+
// --- Report Progress ---
|
|
1018
|
+
this._OratorServer.post
|
|
1019
|
+
(
|
|
1020
|
+
'/Beacon/Work/:WorkItemHash/Progress',
|
|
1021
|
+
function (pRequest, pResponse, fNext)
|
|
1022
|
+
{
|
|
1023
|
+
let tmpSession = this._requireSession(pRequest, pResponse, fNext);
|
|
1024
|
+
if (!tmpSession) { return; }
|
|
1025
|
+
|
|
1026
|
+
let tmpCoordinator = this._getService('UltravisorBeaconCoordinator');
|
|
1027
|
+
if (!tmpCoordinator)
|
|
1028
|
+
{
|
|
1029
|
+
pResponse.send(500, { Error: 'BeaconCoordinator service not available.' });
|
|
1030
|
+
return fNext();
|
|
1031
|
+
}
|
|
1032
|
+
|
|
1033
|
+
let tmpBody = pRequest.body || {};
|
|
1034
|
+
let tmpUpdated = tmpCoordinator.updateProgress(pRequest.params.WorkItemHash, tmpBody);
|
|
1035
|
+
|
|
1036
|
+
if (!tmpUpdated)
|
|
1037
|
+
{
|
|
1038
|
+
pResponse.send(404, { Error: `Work item [${pRequest.params.WorkItemHash}] not found or not running.` });
|
|
1039
|
+
return fNext();
|
|
1040
|
+
}
|
|
1041
|
+
|
|
1042
|
+
pResponse.send({ Success: true, WorkItemHash: pRequest.params.WorkItemHash });
|
|
1043
|
+
return fNext();
|
|
1044
|
+
}.bind(this)
|
|
1045
|
+
);
|
|
1046
|
+
|
|
1047
|
+
// --- Direct Dispatch (synchronous) ---
|
|
1048
|
+
this._OratorServer.post
|
|
1049
|
+
(
|
|
1050
|
+
'/Beacon/Work/Dispatch',
|
|
1051
|
+
function (pRequest, pResponse, fNext)
|
|
1052
|
+
{
|
|
1053
|
+
let tmpSession = this._requireSession(pRequest, pResponse, fNext);
|
|
1054
|
+
if (!tmpSession) { return; }
|
|
1055
|
+
|
|
1056
|
+
let tmpCoordinator = this._getService('UltravisorBeaconCoordinator');
|
|
1057
|
+
if (!tmpCoordinator)
|
|
1058
|
+
{
|
|
1059
|
+
pResponse.send(500, { Success: false, Error: 'BeaconCoordinator service not available.' });
|
|
1060
|
+
return fNext();
|
|
1061
|
+
}
|
|
1062
|
+
|
|
1063
|
+
let tmpBody = pRequest.body || {};
|
|
1064
|
+
if (!tmpBody.Capability)
|
|
1065
|
+
{
|
|
1066
|
+
pResponse.send(400, { Success: false, Error: 'Capability is required.' });
|
|
1067
|
+
return fNext();
|
|
1068
|
+
}
|
|
1069
|
+
|
|
1070
|
+
// Check if any Beacons are registered
|
|
1071
|
+
let tmpBeacons = tmpCoordinator.listBeacons();
|
|
1072
|
+
if (tmpBeacons.length === 0)
|
|
1073
|
+
{
|
|
1074
|
+
pResponse.send(503, { Success: false, Error: 'No Beacon workers are registered.' });
|
|
1075
|
+
return fNext();
|
|
1076
|
+
}
|
|
1077
|
+
|
|
1078
|
+
// Disable request timeout for long-running dispatch
|
|
1079
|
+
if (pRequest.connection)
|
|
1080
|
+
{
|
|
1081
|
+
pRequest.connection.setTimeout(0);
|
|
1082
|
+
}
|
|
1083
|
+
|
|
1084
|
+
let tmpWorkItemInfo = {
|
|
1085
|
+
Capability: tmpBody.Capability || 'Shell',
|
|
1086
|
+
Action: tmpBody.Action || 'Execute',
|
|
1087
|
+
Settings: tmpBody.Settings || {},
|
|
1088
|
+
AffinityKey: tmpBody.AffinityKey || '',
|
|
1089
|
+
TimeoutMs: tmpBody.TimeoutMs || 300000
|
|
1090
|
+
};
|
|
1091
|
+
|
|
1092
|
+
tmpCoordinator.dispatchAndWait(tmpWorkItemInfo,
|
|
1093
|
+
(pError, pResult) =>
|
|
1094
|
+
{
|
|
1095
|
+
if (pError)
|
|
1096
|
+
{
|
|
1097
|
+
pResponse.send(500, { Success: false, Error: pError.message });
|
|
1098
|
+
return fNext();
|
|
1099
|
+
}
|
|
1100
|
+
|
|
1101
|
+
pResponse.send(pResult);
|
|
1102
|
+
return fNext();
|
|
1103
|
+
});
|
|
1104
|
+
}.bind(this)
|
|
1105
|
+
);
|
|
1106
|
+
|
|
1107
|
+
// --- Beacon Capabilities (no auth – management UI) ---
|
|
1108
|
+
this._OratorServer.get
|
|
1109
|
+
(
|
|
1110
|
+
'/Beacon/Capabilities',
|
|
1111
|
+
function (pRequest, pResponse, fNext)
|
|
1112
|
+
{
|
|
1113
|
+
let tmpCoordinator = this._getService('UltravisorBeaconCoordinator');
|
|
1114
|
+
if (!tmpCoordinator)
|
|
1115
|
+
{
|
|
1116
|
+
pResponse.send({ Capabilities: [] });
|
|
1117
|
+
return fNext();
|
|
1118
|
+
}
|
|
1119
|
+
|
|
1120
|
+
let tmpBeacons = tmpCoordinator.listBeacons();
|
|
1121
|
+
let tmpCapabilitySet = {};
|
|
1122
|
+
|
|
1123
|
+
for (let i = 0; i < tmpBeacons.length; i++)
|
|
1124
|
+
{
|
|
1125
|
+
let tmpCaps = tmpBeacons[i].Capabilities || [];
|
|
1126
|
+
for (let j = 0; j < tmpCaps.length; j++)
|
|
1127
|
+
{
|
|
1128
|
+
tmpCapabilitySet[tmpCaps[j]] = true;
|
|
1129
|
+
}
|
|
1130
|
+
}
|
|
1131
|
+
|
|
1132
|
+
pResponse.send({
|
|
1133
|
+
Capabilities: Object.keys(tmpCapabilitySet),
|
|
1134
|
+
BeaconCount: tmpBeacons.length
|
|
1135
|
+
});
|
|
1136
|
+
return fNext();
|
|
1137
|
+
}.bind(this)
|
|
1138
|
+
);
|
|
1139
|
+
|
|
1140
|
+
// --- Fail Work Item ---
|
|
1141
|
+
this._OratorServer.post
|
|
1142
|
+
(
|
|
1143
|
+
'/Beacon/Work/:WorkItemHash/Error',
|
|
1144
|
+
function (pRequest, pResponse, fNext)
|
|
1145
|
+
{
|
|
1146
|
+
let tmpSession = this._requireSession(pRequest, pResponse, fNext);
|
|
1147
|
+
if (!tmpSession) { return; }
|
|
1148
|
+
|
|
1149
|
+
let tmpCoordinator = this._getService('UltravisorBeaconCoordinator');
|
|
1150
|
+
if (!tmpCoordinator)
|
|
1151
|
+
{
|
|
1152
|
+
pResponse.send(500, { Error: 'BeaconCoordinator service not available.' });
|
|
1153
|
+
return fNext();
|
|
1154
|
+
}
|
|
1155
|
+
|
|
1156
|
+
let tmpBody = pRequest.body || {};
|
|
1157
|
+
tmpCoordinator.failWorkItem(pRequest.params.WorkItemHash,
|
|
1158
|
+
{ ErrorMessage: tmpBody.ErrorMessage || 'Unknown error', Log: tmpBody.Log || [] },
|
|
1159
|
+
function (pError)
|
|
1160
|
+
{
|
|
1161
|
+
if (pError)
|
|
1162
|
+
{
|
|
1163
|
+
pResponse.send(400, { Error: pError.message });
|
|
1164
|
+
return fNext();
|
|
1165
|
+
}
|
|
1166
|
+
|
|
1167
|
+
pResponse.send({ Status: 'Failed', WorkItemHash: pRequest.params.WorkItemHash });
|
|
1168
|
+
return fNext();
|
|
1169
|
+
});
|
|
1170
|
+
}.bind(this)
|
|
1171
|
+
);
|
|
1172
|
+
|
|
464
1173
|
return fCallback();
|
|
465
1174
|
}
|
|
466
1175
|
|
|
@@ -513,6 +1222,22 @@ class UltravisorAPIServer extends libPictService
|
|
|
513
1222
|
return fNext();
|
|
514
1223
|
}.bind(this));
|
|
515
1224
|
|
|
1225
|
+
tmpAnticipate.anticipate(
|
|
1226
|
+
function (fNext)
|
|
1227
|
+
{
|
|
1228
|
+
this.fable.addServiceTypeIfNotExists('OratorAuthentication', libOratorAuthentication);
|
|
1229
|
+
this._OratorAuth = this.fable.instantiateServiceProvider('OratorAuthentication',
|
|
1230
|
+
{
|
|
1231
|
+
RoutePrefix: '/1.0/',
|
|
1232
|
+
SessionTTL: this.fable.settings.UltravisorBeaconSessionTTLMs || 86400000,
|
|
1233
|
+
CookieHttpOnly: true,
|
|
1234
|
+
CookieSecure: false
|
|
1235
|
+
});
|
|
1236
|
+
this._OratorAuth.connectRoutes();
|
|
1237
|
+
this.log.info('Ultravisor: OratorAuthentication routes registered.');
|
|
1238
|
+
return fNext();
|
|
1239
|
+
}.bind(this));
|
|
1240
|
+
|
|
516
1241
|
tmpAnticipate.anticipate(
|
|
517
1242
|
function (fNext)
|
|
518
1243
|
{
|
|
@@ -576,4 +1301,4 @@ class UltravisorAPIServer extends libPictService
|
|
|
576
1301
|
}
|
|
577
1302
|
}
|
|
578
1303
|
|
|
579
|
-
module.exports = UltravisorAPIServer;
|
|
1304
|
+
module.exports = UltravisorAPIServer;
|