ultravisor 1.0.0

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.
@@ -0,0 +1,15 @@
1
+ {
2
+ "version": "0.2.0",
3
+ "configurations": [
4
+ {
5
+ "type": "node",
6
+ "request": "launch",
7
+ "name": "Debug Harness",
8
+ "skipFiles": [
9
+ "<node_internals>/**"
10
+ ],
11
+ "program": "${workspaceFolder}/debug/Harness.js",
12
+ "cwd": "${workspaceFolder}/debug"
13
+ }
14
+ ]
15
+ }
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Steven Velozo
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,119 @@
1
+ # Ultravisor
2
+
3
+ Like a supervisor, only instead of super it's ULTRA. The hidden sixth hero of
4
+ Voltron. This tool allows you to run commands on schedule and process output
5
+ with llm models, providing user-friendly summaries and links back to the full
6
+ complete output from command running.
7
+
8
+ ## Use Cases
9
+
10
+ * Periodic data pull from a REST API with localized storage
11
+ * Data integrations between one system and another
12
+ * Automatic execution of image generation models with randomized word choices
13
+ * Parsing of massive sets of files for meaning leveraging ai
14
+
15
+ ## Primary Concepts
16
+
17
+ Ultravisor operates on a few key concepts:
18
+
19
+ * operation - one or many tasks that run in sequence and/or parallel
20
+ * task - this is the verb... "what to do"
21
+ * node - a specific executing ultravisor (often just one, but can be a cluster)
22
+ * global state - data shared across all tasks
23
+ * node state - data accessible locally only (when running with node affinity)
24
+ * metaoutput - the output from tasks and operations
25
+ * operation staging - temporary data from an operation
26
+ * output file store - final file output from an operation
27
+ * output data store - flexible database of final outputs from operations
28
+
29
+ ### Operations
30
+
31
+ An operation is, generally speaking, a set of tasks. Tasks can be composed to
32
+ react to certain data/state situations. With clever use of global state, they
33
+ can even perform complicated series of actions across operations.
34
+
35
+ For instance, I could have one operation that runs a number of tasks on a
36
+ schedule to pull temperature from various locations in my house. Each task
37
+ can store the values in some kind of API, and, keep track of the latest value
38
+ as well as timestamp in global state. These tasks might run every 5-10 seconds
39
+ or so; where they store the data may be
40
+
41
+ Then, a second operation could be running every minute that inspects the global
42
+ state and adjusts a localized thermostat based on the current temperatures.
43
+
44
+ Or maybe I have a NAS full of video files that I would like to run a series of
45
+ machine learning algorithms on, to generate metadata on when scene cuts were
46
+ made in each film. I could setup an operation with a task to watch the cpu,
47
+ iops and memory load of a machine and run parallel tasks that saturate the
48
+ iops/cpu on the machine. This would be a scheduled, parameterized parallel set
49
+ of tasks.
50
+
51
+ ### Tasks
52
+
53
+ Tasks can be really any program that is executable from a local shell, or,
54
+ within a browser environment. The browser part is especially interesting
55
+ since you can basically script sets of actions within web pages (e.g.
56
+ downloading all the files listed on a page... and/or enumerating all the pages
57
+ and running the recursive download task for each page).
58
+
59
+ Tasks can be executed based on a number of scenarios:
60
+
61
+ * On a schedule (5pm every day, every 5 minutes, up to 5 times a minute)
62
+ * After a condition is met (a condition in a browser, a disk drops below 5g)
63
+ * After another task is completed (ffmpeg returns successfully transcoding)
64
+
65
+ ### Nodes
66
+
67
+ Any execution of Ultravisor. Can be distributed across multiple machines.
68
+
69
+ When run with multiple nodes, there is a star topology with the capability for
70
+ nodes to self promote to be the central node if the central node goes away.
71
+
72
+ ### Global State
73
+
74
+ Global state is simple/plain JSON object that's synchronized across nodes. It
75
+ is meant to be used to store small facts and not process management state (e.g.
76
+ it isn't an appropriate storage location for a mutex lock but is great for the
77
+ most recent temperature readings from a set of sensors).
78
+
79
+ ### Node State
80
+
81
+ Node state is similar to global state, but is only accessible to the local node
82
+ the task is running on. This is useful for storing configuration, paths or
83
+ other node-specific information.
84
+
85
+ ### Metaoutput
86
+
87
+ Metaoutput is the output from running tasks and operations. It is stored in a
88
+ simple JSON manifest including consistent fields for understanding:
89
+
90
+ * Summary of Output
91
+ * Start Time, Stop Time, Status, Success/Failure for the Operation
92
+ * Start Time, Stop Time, Status, Success/Failure for each Task
93
+ * Output Data (text, json, binary, files, etc.)
94
+ * Run Log(s) for Tasks
95
+ * Links to Output
96
+ * Anything Else the Task/Operation Wants to Report
97
+
98
+ ### Operation Staging
99
+
100
+ Operation staging is temporary storage for data during the execution of an
101
+ operation. This is useful for storing intermediate files, logs, or other data
102
+ that is not needed after the operation completes.
103
+
104
+ Operations can be flagged to have node affinity, or not. If affinity is set,
105
+ all tasks for the operation will run on the same node, allowing for enormous
106
+ local file stores for the operation itself. This is great for Machine Learning
107
+ operations that need to store large source files, intermediate learning data
108
+ and final output files.
109
+
110
+ ### Output File Store
111
+
112
+ The centralized location for all final output files from operations. This is
113
+ meant to be a persistent storage location that is accessible across nodes.
114
+
115
+ ### Output Data Store
116
+
117
+ The output data store is a flexible database for storing final output data from
118
+ operations. This can be used to store structured data, metadata, or any other
119
+ information that needs to be queried or analyzed later.
@@ -0,0 +1,4 @@
1
+ let libUltravisor = require(`../source/cli/Ultravisor-CLIProgram.cjs`);
2
+
3
+ //libUltravisor.run(['node', 'Harness.js', 'explain-config']);
4
+ libUltravisor.run(['node', 'Harness.js', 'start']);
package/package.json ADDED
@@ -0,0 +1,51 @@
1
+ {
2
+ "name": "ultravisor",
3
+ "version": "1.0.0",
4
+ "description": "Cyclic process execution with ai integration.",
5
+ "main": "source/Ultravisor.js",
6
+ "bin": {
7
+ "ultravisor": "./source/cli/Ultravisor-Run.cjs"
8
+ },
9
+ "scripts": {
10
+ "start": "node source/cli/Ultravisor-Run.cjs",
11
+ "test": "npx mocha -u tdd -R spec",
12
+ "tests": "npx mocha -u tdd --exit -R spec --grep",
13
+ "coverage": "npx nyc --reporter=lcov --reporter=text-lcov npx mocha -- -u tdd -R spec",
14
+ "build": "npx quack build"
15
+ },
16
+ "repository": {
17
+ "type": "git",
18
+ "url": "git+https://github.com/stevenvelozo/ultravisor.git"
19
+ },
20
+ "author": "steven@velozo.com",
21
+ "license": "MIT",
22
+ "bugs": {
23
+ "url": "https://github.com/stevenvelozo/ultravisor/issues"
24
+ },
25
+ "homepage": "https://github.com/stevenvelozo/ultravisor#readme",
26
+ "dependencies": {
27
+ "orator": "^5.0.1",
28
+ "orator-serviceserver-restify": "^2.0.5",
29
+ "pict": "^1.0.343",
30
+ "pict-service-commandlineutility": "^1.0.17",
31
+ "pict-serviceproviderbase": "^1.0.0"
32
+ },
33
+ "mocha": {
34
+ "diff": true,
35
+ "extension": [
36
+ "js"
37
+ ],
38
+ "package": "./package.json",
39
+ "reporter": "spec",
40
+ "slow": "75",
41
+ "timeout": "5000",
42
+ "ui": "tdd",
43
+ "watch-files": [
44
+ "source/**/*.js",
45
+ "test/**/*.js"
46
+ ],
47
+ "watch-ignore": [
48
+ "lib/vendor"
49
+ ]
50
+ }
51
+ }
@@ -0,0 +1,5 @@
1
+ module.exports = (
2
+ {
3
+ Operation: requestAnimationFrame(`./services/Ultravisor-Operation.cjs`),
4
+ Task: requestAnimationFrame(`./services/Ultravisor-Task.cjs`),
5
+ });
@@ -0,0 +1,79 @@
1
+ const libCLIProgram = require('pict-service-commandlineutility');
2
+
3
+ const libServiceHypervisor = require(`../services/Ultravisor-Hypervisor.cjs`);
4
+
5
+ const libServiceHypervisorEventBase = require(`../services/Ultravisor-Hypervisor-Event-Base.cjs`);
6
+ const libServiceHypervisorEventCron = require(`../services/events/Ultravisor-Hypervisor-Event-Cron.cjs`);
7
+ const libServiceHypervisorEventSolver = require(`../services/events/Ultravisor-Hypervisor-Event-Solver.cjs`);
8
+
9
+ const libServiceOperation = require(`../services/Ultravisor-Operation.cjs`);
10
+ const libServiceOperationManifest = require(`../services/Ultravisor-Operation-Manifest.cjs`);
11
+
12
+ const libServiceTask = require(`../services/Ultravisor-Task.cjs`);
13
+
14
+ // TODO: Remove this when Restify is fixed.
15
+ process.removeAllListeners('warning')
16
+
17
+ const libWebServerAPIServer = require(`../web_server/Ultravisor-API-Server.cjs`);
18
+
19
+ let _Ultravisor_Pict = new libCLIProgram(
20
+ {
21
+ "Product": "Ultravisor-CLI",
22
+ "Version": require('../../package.json').version,
23
+ "Description": require('../../package.json').description,
24
+
25
+ "Package": require('../../package.json'),
26
+
27
+ "LogStreams":
28
+ [
29
+ {
30
+ "level": "trace",
31
+ "streamtype": "process.stdout"
32
+ }
33
+ ],
34
+
35
+ "Command": "ultravisor",
36
+
37
+ "DefaultProgramConfiguration": require(`../config/Ultravisor-Default-Command-Configuration.cjs`),
38
+
39
+ "ProgramConfigurationFileName": ".ultravisor.json",
40
+
41
+ "AutoGatherProgramConfiguration": true,
42
+ "AutoAddConfigurationExplanationCommand": true
43
+ },
44
+ [
45
+ // Display the current ultravisor schedule
46
+ require('./commands/Ultravisor-Command-ScheduleView.cjs'),
47
+
48
+ // Add a task or operation to the current ultravisor schedule
49
+ require('./commands/Ultravisor-Command-ScheduleOperation.cjs'),
50
+ require('./commands/Ultravisor-Command-ScheduleTask.cjs'),
51
+
52
+ // Execute a single operation or task immediately, no matter what
53
+ require('./commands/Ultravisor-Command-SingleOperation.cjs'),
54
+ require('./commands/Ultravisor-Command-SingleTask.cjs'),
55
+
56
+ // Start and/or stop the hypervisor, API and web server
57
+ require('./commands/Ultravisor-Command-Start.cjs'),
58
+ require('./commands/Ultravisor-Command-Stop.cjs')
59
+ ]);
60
+
61
+ // Instantiate the file persistence service
62
+ _Ultravisor_Pict.instantiateServiceProvider('FilePersistence');
63
+ // Instantiate the data generation service
64
+ _Ultravisor_Pict.instantiateServiceProvider('DataGeneration');
65
+
66
+ _Ultravisor_Pict.fable.addAndInstantiateServiceTypeIfNotExists('Ultravisor-Hypervisor', libServiceHypervisor);
67
+
68
+ _Ultravisor_Pict.fable.addAndInstantiateServiceTypeIfNotExists('Ultravisor-Hypervisor-Event-Base', libServiceHypervisorEventBase);
69
+ _Ultravisor_Pict.fable.addAndInstantiateServiceTypeIfNotExists('Ultravisor-Hypervisor-Event-Cron', libServiceHypervisorEventCron);
70
+ _Ultravisor_Pict.fable.addAndInstantiateServiceTypeIfNotExists('Ultravisor-Hypervisor-Event-Solver', libServiceHypervisorEventSolver);
71
+
72
+ _Ultravisor_Pict.fable.addAndInstantiateServiceTypeIfNotExists('Ultravisor-Operation', libServiceOperation);
73
+ _Ultravisor_Pict.fable.addAndInstantiateServiceTypeIfNotExists('Ultravisor-Operation-Manifest', libServiceOperationManifest);
74
+
75
+ _Ultravisor_Pict.fable.addAndInstantiateServiceTypeIfNotExists('Ultravisor-Task', libServiceTask);
76
+
77
+ _Ultravisor_Pict.fable.addAndInstantiateServiceTypeIfNotExists('Ultravisor-API-Server', libWebServerAPIServer);
78
+
79
+ module.exports = _Ultravisor_Pict;
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ let libQuackage = require('./Ultravisor-CLIProgram.cjs');
3
+ libQuackage.run();
@@ -0,0 +1,28 @@
1
+ const libCommandLineCommand = require('pict-service-commandlineutility').ServiceCommandLineCommand;
2
+
3
+ class UltravisorCommandScheduleOperation extends libCommandLineCommand
4
+ {
5
+ constructor(pFable, pManifest, pServiceHash)
6
+ {
7
+ super(pFable, pManifest, pServiceHash);
8
+
9
+ this.options.CommandKeyword = 'schedule_operation';
10
+ this.options.Description = 'Add an operation to the schedule.';
11
+
12
+ this.options.CommandArguments.push({ Name: '<operation>', Description: 'The operation to add to the schedule.' });
13
+
14
+ this.options.CommandOptions.push({ Name: '-t, --type [event_schedule_type]', Description: 'The event schedule type (cron, daily, hourly, solver).', Default: 'cron' });
15
+ this.options.CommandOptions.push({ Name: '-p, --parameters [event_schedule_parameters]', Description: 'The parameters for the schedule (e.g. the crontab entry or solver string).', Default: '' });
16
+
17
+ this.options.Aliases.push('so');
18
+
19
+ this.addCommand();
20
+ }
21
+
22
+ onRunAsync(fCallback)
23
+ {
24
+ return fCallback();
25
+ }
26
+ }
27
+
28
+ module.exports = UltravisorCommandScheduleOperation;
@@ -0,0 +1,28 @@
1
+ const libCommandLineCommand = require('pict-service-commandlineutility').ServiceCommandLineCommand;
2
+
3
+ class UltravisorCommandScheduleTask extends libCommandLineCommand
4
+ {
5
+ constructor(pFable, pManifest, pServiceHash)
6
+ {
7
+ super(pFable, pManifest, pServiceHash);
8
+
9
+ this.options.CommandKeyword = 'schedule_task';
10
+ this.options.Description = 'Add a task to the schedule.';
11
+
12
+ this.options.CommandArguments.push({ Name: '<task>', Description: 'The task to add to the schedule.' });
13
+
14
+ this.options.CommandOptions.push({ Name: '-t, --type [event_schedule_type]', Description: 'The event schedule type (cron, daily, hourly, solver).', Default: 'cron' });
15
+ this.options.CommandOptions.push({ Name: '-p, --parameters [event_schedule_parameters]', Description: 'The parameters for the schedule (e.g. the crontab entry or solver string).', Default: '' });
16
+
17
+ this.options.Aliases.push('st');
18
+
19
+ this.addCommand();
20
+ }
21
+
22
+ onRunAsync(fCallback)
23
+ {
24
+ return fCallback();
25
+ }
26
+ }
27
+
28
+ module.exports = UltravisorCommandScheduleTask;
@@ -0,0 +1,25 @@
1
+ const libCommandLineCommand = require('pict-service-commandlineutility').ServiceCommandLineCommand;
2
+
3
+ class UltravisorCommandScheduleView extends libCommandLineCommand
4
+ {
5
+ constructor(pFable, pManifest, pServiceHash)
6
+ {
7
+ super(pFable, pManifest, pServiceHash);
8
+
9
+ this.options.CommandKeyword = 'schedule';
10
+ this.options.Description = 'View the schedule.';
11
+
12
+ this.options.CommandOptions.push({ Name: '-f, --format [schedule_format]', Description: 'The visualization format (day, week, month) to output.', Default: 'day' });
13
+
14
+ this.options.Aliases.push('cal');
15
+
16
+ this.addCommand();
17
+ }
18
+
19
+ onRunAsync(fCallback)
20
+ {
21
+ return fCallback();
22
+ }
23
+ }
24
+
25
+ module.exports = UltravisorCommandScheduleView;
@@ -0,0 +1,26 @@
1
+ const libCommandLineCommand = require('pict-service-commandlineutility').ServiceCommandLineCommand;
2
+
3
+ class UltravisorCommandSingleOperationRun extends libCommandLineCommand
4
+ {
5
+ constructor(pFable, pManifest, pServiceHash)
6
+ {
7
+ super(pFable, pManifest, pServiceHash);
8
+
9
+ this.options.CommandKeyword = 'singleoperation';
10
+ this.options.Description = 'Execute a single ultravisor operation immediately, no matter what.';
11
+
12
+ this.options.CommandArguments.push({ Name: '<operation>', Description: 'The operation(s) to run.' });
13
+ this.options.CommandOptions.push({ Name: '-d, --dry_run', Description: 'Dry run the task.', Default: false });
14
+
15
+ this.options.Aliases.push('operation');
16
+
17
+ this.addCommand();
18
+ }
19
+
20
+ onRunAsync(fCallback)
21
+ {
22
+ return fCallback();
23
+ }
24
+ }
25
+
26
+ module.exports = UltravisorCommandSingleOperationRun;
@@ -0,0 +1,27 @@
1
+ const libCommandLineCommand = require('pict-service-commandlineutility').ServiceCommandLineCommand;
2
+
3
+ class UltravisorCommandSingleTaskRun extends libCommandLineCommand
4
+ {
5
+ constructor(pFable, pManifest, pServiceHash)
6
+ {
7
+ super(pFable, pManifest, pServiceHash);
8
+
9
+ this.options.CommandKeyword = 'singletask';
10
+ this.options.Description = 'Execute a single ultravisor task immediately, no matter what.';
11
+
12
+ this.options.CommandArguments.push({ Name: '<task>', Description: 'The task(s) to run.' });
13
+ this.options.CommandOptions.push({ Name: '-o, --operation [operation]', Description: 'The operation to scope the task(s) to.', Default: 'Default' });
14
+ this.options.CommandOptions.push({ Name: '-d, --dry_run', Description: 'Dry run the task.', Default: false });
15
+
16
+ this.options.Aliases.push('task');
17
+
18
+ this.addCommand();
19
+ }
20
+
21
+ onRunAsync(fCallback)
22
+ {
23
+ return fCallback();
24
+ }
25
+ }
26
+
27
+ module.exports = UltravisorCommandSingleTaskRun;
@@ -0,0 +1,25 @@
1
+ const libCommandLineCommand = require('pict-service-commandlineutility').ServiceCommandLineCommand;
2
+
3
+ class UltravisorCommandStartService extends libCommandLineCommand
4
+ {
5
+ constructor(pFable, pManifest, pServiceHash)
6
+ {
7
+ super(pFable, pManifest, pServiceHash);
8
+
9
+ this.options.CommandKeyword = 'start';
10
+ this.options.Description = 'Start the Ultravisor service.';
11
+
12
+ this.options.CommandOptions.push({ Name: '-v, --verbose', Description: 'Provide verbose console output.', Default: false });
13
+
14
+ this.addCommand();
15
+ }
16
+
17
+ onRunAsync(fCallback)
18
+ {
19
+ // TODO: What to do with verbose!
20
+ console.log(`Starting Ultravisor API Server...`);
21
+ return this.fable['Ultravisor-API-Server'].start(fCallback);
22
+ }
23
+ }
24
+
25
+ module.exports = UltravisorCommandStartService;
@@ -0,0 +1,21 @@
1
+ const libCommandLineCommand = require('pict-service-commandlineutility').ServiceCommandLineCommand;
2
+
3
+ class UltravisorCommandStopService extends libCommandLineCommand
4
+ {
5
+ constructor(pFable, pManifest, pServiceHash)
6
+ {
7
+ super(pFable, pManifest, pServiceHash);
8
+
9
+ this.options.CommandKeyword = 'stop';
10
+ this.options.Description = 'Stop the Ultravisor service.';
11
+
12
+ this.addCommand();
13
+ }
14
+
15
+ onRunAsync(fCallback)
16
+ {
17
+ return fCallback();
18
+ }
19
+ }
20
+
21
+ module.exports = UltravisorCommandStopService;
@@ -0,0 +1,5 @@
1
+ module.exports = (
2
+ {
3
+ "UltravisorAPIServerPort": 54321,
4
+ "UltravisorFileStorePath": `${process.cwd()}/dist/ultravisor_datastore`
5
+ });
@@ -0,0 +1,11 @@
1
+ const libPictService = require(`pict-serviceproviderbase`);
2
+
3
+ class UltravisorEventBase extends libPictService
4
+ {
5
+ constructor(pPict, pOptions, pServiceHash)
6
+ {
7
+ super(pPict, pOptions, pServiceHash);
8
+ }
9
+ }
10
+
11
+ module.exports = UltravisorEventBase;
@@ -0,0 +1,11 @@
1
+ const libPictService = require(`pict-serviceproviderbase`);
2
+
3
+ class UltravisorHypervisor extends libPictService
4
+ {
5
+ constructor(pPict, pOptions, pServiceHash)
6
+ {
7
+ super(pPict, pOptions, pServiceHash);
8
+ }
9
+ }
10
+
11
+ module.exports = UltravisorHypervisor;
@@ -0,0 +1,11 @@
1
+ const libPictService = require(`pict-serviceproviderbase`);
2
+
3
+ class UltravisorOperationManifest extends libPictService
4
+ {
5
+ constructor(pPict, pOptions, pServiceHash)
6
+ {
7
+ super(pPict, pOptions, pServiceHash);
8
+ }
9
+ }
10
+
11
+ module.exports = UltravisorOperationManifest;
@@ -0,0 +1,11 @@
1
+ const libPictService = require(`pict-serviceproviderbase`);
2
+
3
+ class UltravisorOperation extends libPictService
4
+ {
5
+ constructor(pPict, pOptions, pServiceHash)
6
+ {
7
+ super(pPict, pOptions, pServiceHash);
8
+ }
9
+ }
10
+
11
+ module.exports = UltravisorOperation;
@@ -0,0 +1,11 @@
1
+ const libPictService = require(`pict-serviceproviderbase`);
2
+
3
+ class UltravisorTask extends libPictService
4
+ {
5
+ constructor(pPict, pOptions, pServiceHash)
6
+ {
7
+ super(pPict, pOptions, pServiceHash);
8
+ }
9
+ }
10
+
11
+ module.exports = UltravisorTask;
@@ -0,0 +1,11 @@
1
+ const libUltravisorEventBase = require(`../Ultravisor-Hypervisor-Event-Base.cjs`);
2
+
3
+ class UltravisorEventCron extends libUltravisorEventBase
4
+ {
5
+ constructor(pPict, pOptions, pServiceHash)
6
+ {
7
+ super(pPict, pOptions, pServiceHash);
8
+ }
9
+ }
10
+
11
+ module.exports = UltravisorEventCron;
@@ -0,0 +1,11 @@
1
+ const libUltravisorEventBase = require(`../Ultravisor-Hypervisor-Event-Base.cjs`);
2
+
3
+ class UltravisorEventSolver extends libUltravisorEventBase
4
+ {
5
+ constructor(pPict, pOptions, pServiceHash)
6
+ {
7
+ super(pPict, pOptions, pServiceHash);
8
+ }
9
+ }
10
+
11
+ module.exports = UltravisorEventSolver;
@@ -0,0 +1,119 @@
1
+ const libPictService = require(`pict-serviceproviderbase`);
2
+
3
+ const libOrator = require('orator');
4
+ const libOratorServiceServerRestify = require(`orator-serviceserver-restify`);
5
+
6
+ class UltravisorAPIServer extends libPictService
7
+ {
8
+ constructor(pPict, pOptions, pServiceHash)
9
+ {
10
+ super(pPict, pOptions, pServiceHash);
11
+
12
+ // Add Restify as the default service server type
13
+ this.fable.addServiceTypeIfNotExists('OratorServiceServer', libOratorServiceServerRestify);
14
+ this._OratorServer = this.fable.instantiateServiceProvider('OratorServiceServer', {});
15
+
16
+ // Add Orator as a service
17
+ this.fable.addServiceTypeIfNotExists('Orator', libOrator);
18
+ }
19
+
20
+ wireEndpoints(fCallback)
21
+ {
22
+ if (!this._Orator)
23
+ {
24
+ return fCallback(new Error(`Ultravisor API Server: Cannot wire endpoints; Orator service is not initialized.`));
25
+ }
26
+
27
+ this._OratorServer.get
28
+ (
29
+ '/package',
30
+ (pRequest, pResponse, fNext) =>
31
+ {
32
+ // Send back the request parameters
33
+ pResponse.send(this.pict.settings.Package);
34
+ return fNext();
35
+ }
36
+ );
37
+
38
+ return fCallback();
39
+ }
40
+
41
+ start(fCallback)
42
+ {
43
+ const tmpAnticipate = this.fable.newAnticipate();
44
+
45
+ tmpAnticipate.anticipate(
46
+ function (fNext)
47
+ {
48
+ // Initialize the Orator service
49
+ if (!this.fable.settings.APIServerPort)
50
+ {
51
+ if (this.fable?.ProgramConfiguration?.UltravisorAPIServerPort)
52
+ {
53
+ this.fable.settings.APIServerPort = this.fable.ProgramConfiguration.UltravisorAPIServerPort;
54
+ }
55
+ else
56
+ {
57
+ this.fable.settings.APIServerPort = 55555;
58
+ }
59
+ }
60
+ return fNext();
61
+ }.bind(this));
62
+
63
+ this._Orator = this.fable.instantiateServiceProvider('Orator', {});
64
+
65
+ tmpAnticipate.anticipate(
66
+ function (fNext)
67
+ {
68
+ this.log.info(`Initializing Ultravisor Orator API Server on port ${this.fable.settings.APIServerPort}`);
69
+ this._Orator.initialize(
70
+ function (pError)
71
+ {
72
+ if (pError)
73
+ {
74
+ this.log.info(`Error initializing Orator for Ultravisor ${pError}`, pError);
75
+ return fCallback(pError);
76
+ }
77
+ this.log.info(`Orator initialized for Ultravisor API Server on port ${this.fable.settings.APIServerPort}`);
78
+ return fNext();
79
+ }.bind(this));
80
+ }.bind(this));
81
+
82
+ tmpAnticipate.anticipate(
83
+ function (fNext)
84
+ {
85
+ this.wireEndpoints(
86
+ function (pError)
87
+ {
88
+ if (pError)
89
+ {
90
+ this.log.info(`Error wiring Ultravisor API Server endpoints: ${pError}`, pError);
91
+ return fCallback(pError);
92
+ }
93
+ this.log.info(`Ultravisor API Server endpoints wired successfully.`);
94
+ return fNext();
95
+ }.bind(this));
96
+ }.bind(this));
97
+
98
+ tmpAnticipate.anticipate(
99
+ function (fNext)
100
+ {
101
+ this.log.info(`Starting Ultravisor Orator API Server on port ${this.fable.settings.APIServerPort}`);
102
+ this._Orator.startService(fNext);
103
+ }.bind(this));
104
+
105
+ tmpAnticipate.wait(
106
+ function (pError)
107
+ {
108
+ if (pError)
109
+ {
110
+ this.log.info(`Error starting Ultravisor API Server: ${pError}`, pError);
111
+ return fCallback(pError);
112
+ }
113
+ this.log.info(`Ultravisor Orator API Server started successfully.`);
114
+ return fCallback();
115
+ }.bind(this));
116
+ }
117
+ }
118
+
119
+ module.exports = UltravisorAPIServer;
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Unit tests for Ultravisor
3
+ */
4
+
5
+ var libUltravisor = require('../source/cli/Ultravisor-CLIProgram.cjs');
6
+
7
+ var Chai = require("chai");
8
+ var Expect = Chai.expect;
9
+
10
+ suite
11
+ (
12
+ 'Ultravisor',
13
+ function()
14
+ {
15
+ setup ( () => {} );
16
+
17
+ suite
18
+ (
19
+ 'Execution Sanity',
20
+ function()
21
+ {
22
+ test
23
+ (
24
+ 'Ultravisor should load up okay.',
25
+ function()
26
+ {
27
+ let testUltravisor = libUltravisor;
28
+ Expect(testUltravisor.settings.Product).to.equal('Ultravisor-CLI');
29
+ }
30
+ );
31
+ }
32
+ );
33
+ }
34
+ );