@lossless.org/objectstorage 11.0.0 → 11.1.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.
- package/.smartconfig.json +19 -1
- package/dist_rust/ruststorage_linux_amd64 +0 -0
- package/dist_rust/ruststorage_linux_amd64.tsrust-build.json +4 -4
- package/dist_rust/ruststorage_linux_amd64_musl +0 -0
- package/dist_rust/ruststorage_linux_amd64_musl.tsrust-build.json +4 -4
- package/dist_rust/ruststorage_linux_arm64 +0 -0
- package/dist_rust/ruststorage_linux_arm64.tsrust-build.json +4 -4
- package/dist_rust/ruststorage_linux_arm64_musl +0 -0
- package/dist_rust/ruststorage_linux_arm64_musl.tsrust-build.json +4 -4
- package/dist_rust/ruststorage_macos_amd64 +0 -0
- package/dist_rust/ruststorage_macos_amd64.tsrust-build.json +4 -4
- package/dist_rust/ruststorage_macos_arm64 +0 -0
- package/dist_rust/ruststorage_macos_arm64.tsrust-build.json +4 -4
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/classes.dashboard.d.ts +49 -0
- package/dist_ts/classes.dashboard.js +234 -0
- package/dist_ts/dashboard.bundled.d.ts +4 -0
- package/dist_ts/dashboard.bundled.js +20 -0
- package/dist_ts/dashboard.interfaces.d.ts +132 -0
- package/dist_ts/dashboard.interfaces.js +2 -0
- package/dist_ts/dashboard.plugins.d.ts +5 -0
- package/dist_ts/dashboard.plugins.js +10 -0
- package/dist_ts/index.d.ts +94 -1
- package/dist_ts/index.js +63 -1
- package/package.json +11 -7
- package/readme.md +192 -9
- package/third-party-notices.md +20 -4
- package/third_party_licenses/borsh-1.8.1-license.txt +23 -0
- package/third_party_licenses/borsh-derive-1.8.1-apache-2.0.txt +201 -0
- package/third_party_licenses/cargo-dependencies.html +420 -0
- package/third_party_licenses/dyn-clone-1.0.20-license.txt +23 -0
- package/third_party_licenses/equivalent-1.0.3-license.txt +25 -0
- package/third_party_licenses/hashbrown-0.17.1-license.txt +25 -0
- package/third_party_licenses/indexmap-2.14.2-license.txt +25 -0
- package/third_party_licenses/inventory.json +310 -8
- package/third_party_licenses/proc-macro-crate-3.5.0-license.txt +23 -0
- package/third_party_licenses/ref-cast-1.0.27-license.txt +23 -0
- package/third_party_licenses/ref-cast-impl-1.0.27-license.txt +23 -0
- package/third_party_licenses/schemars-1.2.3-license.txt +21 -0
- package/third_party_licenses/syn-3.0.9-license.txt +23 -0
- package/third_party_licenses/toml_datetime-1.1.2-license.txt +19 -0
- package/third_party_licenses/toml_edit-0.25.17-license.txt +19 -0
- package/third_party_licenses/toml_parser-1.1.5-license.txt +19 -0
- package/third_party_licenses/winnow-1.0.4-license.txt +18 -0
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/classes.dashboard.ts +280 -0
- package/ts/dashboard.bundled.ts.third-party-notices.json +1741 -0
- package/ts/dashboard.bundled.ts.third-party-notices.txt +5015 -0
- package/ts/dashboard.interfaces.ts +148 -0
- package/ts/dashboard.plugins.ts +13 -0
- package/ts/index.ts +162 -1
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import type { ITypedRequest, implementsTR } from '@api.global/typedrequest-interfaces';
|
|
2
|
+
import type { ITypedSocketEvent } from '@api.global/typedsocket';
|
|
3
|
+
/**
|
|
4
|
+
* Engine snapshot shapes, as `ObjectStorage.getClusterSnapshot()` returns
|
|
5
|
+
* them. The engine builds them from memory only: the drive states the last
|
|
6
|
+
* heartbeat probe left, runtime stats, healing state, S3 listener counters
|
|
7
|
+
* and a bounded ring of recent events. Times are milliseconds since the Unix
|
|
8
|
+
* epoch; absent values are `null`.
|
|
9
|
+
*/
|
|
10
|
+
export interface IObjectStorageTelemetryEvent {
|
|
11
|
+
/** Numbered per node from 1; a gap means older events left the ring. */
|
|
12
|
+
seq: number;
|
|
13
|
+
at: number;
|
|
14
|
+
kind: 'engine' | 'peer' | 'drive' | 'healing';
|
|
15
|
+
severity: 'info' | 'warning' | 'error';
|
|
16
|
+
message: string;
|
|
17
|
+
}
|
|
18
|
+
/** S3 listener counters since the engine started; bytes include HTTP headers. */
|
|
19
|
+
export interface IObjectStorageTrafficCounters {
|
|
20
|
+
requestsTotal: number;
|
|
21
|
+
errorResponses: number;
|
|
22
|
+
bytesIn: number;
|
|
23
|
+
bytesOut: number;
|
|
24
|
+
}
|
|
25
|
+
export interface IObjectStorageStorageTotals {
|
|
26
|
+
bucketCount: number;
|
|
27
|
+
objectCount: number;
|
|
28
|
+
totalBytes: number;
|
|
29
|
+
}
|
|
30
|
+
export interface IObjectStorageDriveSnapshot {
|
|
31
|
+
index: number;
|
|
32
|
+
path: string;
|
|
33
|
+
status: 'online' | 'degraded' | 'offline' | 'healing';
|
|
34
|
+
totalBytes: number;
|
|
35
|
+
usedBytes: number;
|
|
36
|
+
availableBytes: number;
|
|
37
|
+
errorCount: number;
|
|
38
|
+
lastError: string | null;
|
|
39
|
+
lastCheck: number | null;
|
|
40
|
+
erasureSetId: number | null;
|
|
41
|
+
}
|
|
42
|
+
export interface IObjectStorageHealingSnapshot {
|
|
43
|
+
active: boolean;
|
|
44
|
+
scanIntervalMs: number;
|
|
45
|
+
lastRunStartedAt: number | null;
|
|
46
|
+
lastRunCompletedAt: number | null;
|
|
47
|
+
lastDurationMs: number | null;
|
|
48
|
+
shardsChecked: number | null;
|
|
49
|
+
shardsHealed: number | null;
|
|
50
|
+
shardsPending: number | null;
|
|
51
|
+
failed: number | null;
|
|
52
|
+
lastError: string | null;
|
|
53
|
+
}
|
|
54
|
+
/** What one node reports about itself; local and remote nodes share this shape. */
|
|
55
|
+
export interface IObjectStorageNodeSnapshot {
|
|
56
|
+
/** Absent in standalone mode. */
|
|
57
|
+
nodeId: string | null;
|
|
58
|
+
mode: 'standalone' | 'cluster';
|
|
59
|
+
startedAt: number;
|
|
60
|
+
capturedAt: number;
|
|
61
|
+
traffic: IObjectStorageTrafficCounters;
|
|
62
|
+
storage: IObjectStorageStorageTotals;
|
|
63
|
+
/** Local drives (cluster mode); empty in standalone mode. */
|
|
64
|
+
drives: IObjectStorageDriveSnapshot[];
|
|
65
|
+
healing: IObjectStorageHealingSnapshot | null;
|
|
66
|
+
/** Recent events, oldest first. */
|
|
67
|
+
events: IObjectStorageTelemetryEvent[];
|
|
68
|
+
}
|
|
69
|
+
export interface IObjectStoragePeerSnapshot {
|
|
70
|
+
nodeId: string;
|
|
71
|
+
status: 'online' | 'suspect' | 'offline';
|
|
72
|
+
quicAddress: string;
|
|
73
|
+
s3Address: string;
|
|
74
|
+
driveCount: number;
|
|
75
|
+
lastHeartbeat: number;
|
|
76
|
+
missedHeartbeats: number;
|
|
77
|
+
/** The peer's own snapshot, when it answered within a second. */
|
|
78
|
+
snapshot: IObjectStorageNodeSnapshot | null;
|
|
79
|
+
unavailableReason: string | null;
|
|
80
|
+
}
|
|
81
|
+
export interface IObjectStorageErasureSnapshot {
|
|
82
|
+
dataShards: number;
|
|
83
|
+
parityShards: number;
|
|
84
|
+
chunkSizeBytes: number;
|
|
85
|
+
totalShards: number;
|
|
86
|
+
readQuorum: number;
|
|
87
|
+
writeQuorum: number;
|
|
88
|
+
erasureSetCount: number;
|
|
89
|
+
}
|
|
90
|
+
export interface IObjectStorageClusterViewSnapshot {
|
|
91
|
+
nodeId: string;
|
|
92
|
+
quorumHealthy: boolean;
|
|
93
|
+
majorityHealthy: boolean;
|
|
94
|
+
erasure: IObjectStorageErasureSnapshot;
|
|
95
|
+
peers: IObjectStoragePeerSnapshot[];
|
|
96
|
+
}
|
|
97
|
+
export interface IObjectStorageClusterSnapshot {
|
|
98
|
+
capturedAt: number;
|
|
99
|
+
clusterEnabled: boolean;
|
|
100
|
+
local: IObjectStorageNodeSnapshot;
|
|
101
|
+
/** Absent in standalone mode. */
|
|
102
|
+
cluster: IObjectStorageClusterViewSnapshot | null;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Dashboard configuration. The dashboard is off unless `enabled` is true.
|
|
106
|
+
*/
|
|
107
|
+
export interface IObjectStorageDashboardConfig {
|
|
108
|
+
enabled: boolean;
|
|
109
|
+
/** Interface the dashboard listens on. Default `127.0.0.1`. */
|
|
110
|
+
address?: string;
|
|
111
|
+
/** TCP port; `0` asks the OS for one. Default 3001; must differ from the S3 port. */
|
|
112
|
+
port?: number;
|
|
113
|
+
}
|
|
114
|
+
/** One dashboard sample, as pushed to every connected dashboard. */
|
|
115
|
+
export interface IObjectStorageDashboardSample {
|
|
116
|
+
sampledAt: number;
|
|
117
|
+
/** The snapshot, or `null` when the engine could not answer. */
|
|
118
|
+
snapshot: IObjectStorageClusterSnapshot | null;
|
|
119
|
+
error: string | null;
|
|
120
|
+
/** Events were left out of peer snapshots to keep the sample within the push limit. */
|
|
121
|
+
eventsTruncated: boolean;
|
|
122
|
+
}
|
|
123
|
+
/** Answers with the latest sample, taking one when none exists yet. */
|
|
124
|
+
export interface IReq_ObjectStorageDashboardGetSample extends implementsTR<ITypedRequest, IReq_ObjectStorageDashboardGetSample> {
|
|
125
|
+
method: 'objectStorageDashboardGetSample';
|
|
126
|
+
request: Record<string, never>;
|
|
127
|
+
response: IObjectStorageDashboardSample;
|
|
128
|
+
}
|
|
129
|
+
/** Pushed every two seconds while at least one dashboard is connected. */
|
|
130
|
+
export interface IEvent_ObjectStorageDashboardSample extends ITypedSocketEvent<IObjectStorageDashboardSample> {
|
|
131
|
+
name: 'objectStorageDashboardSample';
|
|
132
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
// Loaded only by the dashboard module, which `ObjectStorage` imports
|
|
2
|
+
// dynamically when the dashboard is enabled.
|
|
3
|
+
// @api.global scope
|
|
4
|
+
import * as typedrequest from '@api.global/typedrequest';
|
|
5
|
+
import * as typedsocket from '@api.global/typedsocket';
|
|
6
|
+
export { typedrequest, typedsocket };
|
|
7
|
+
// @push.rocks scope
|
|
8
|
+
import * as smartserve from '@push.rocks/smartserve';
|
|
9
|
+
export { smartserve };
|
|
10
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGFzaGJvYXJkLnBsdWdpbnMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9kYXNoYm9hcmQucGx1Z2lucy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxxRUFBcUU7QUFDckUsNkNBQTZDO0FBRTdDLG9CQUFvQjtBQUNwQixPQUFPLEtBQUssWUFBWSxNQUFNLDBCQUEwQixDQUFDO0FBQ3pELE9BQU8sS0FBSyxXQUFXLE1BQU0seUJBQXlCLENBQUM7QUFFdkQsT0FBTyxFQUFFLFlBQVksRUFBRSxXQUFXLEVBQUUsQ0FBQztBQUVyQyxvQkFBb0I7QUFDcEIsT0FBTyxLQUFLLFVBQVUsTUFBTSx3QkFBd0IsQ0FBQztBQUVyRCxPQUFPLEVBQUUsVUFBVSxFQUFFLENBQUMifQ==
|
package/dist_ts/index.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import * as plugins from './plugins.js';
|
|
2
|
+
import type { IObjectStorageClusterSnapshot, IObjectStorageDashboardConfig } from './dashboard.interfaces.js';
|
|
3
|
+
export * from './dashboard.interfaces.js';
|
|
2
4
|
/**
|
|
3
5
|
* Authentication configuration
|
|
4
6
|
*/
|
|
@@ -125,11 +127,33 @@ export interface IDriveConfig {
|
|
|
125
127
|
*/
|
|
126
128
|
allowSharedDevice?: boolean;
|
|
127
129
|
}
|
|
130
|
+
/**
|
|
131
|
+
* Mutual TLS for the cluster transport. Every file is read once at startup and
|
|
132
|
+
* must lie outside the control and drive roots, at an absolute path without
|
|
133
|
+
* symbolic links; a restart reloads them.
|
|
134
|
+
*/
|
|
135
|
+
export interface IClusterTlsConfig {
|
|
136
|
+
/** PEM file with one or two CA certificates (two only during a CA rotation). */
|
|
137
|
+
caFile: string;
|
|
138
|
+
/**
|
|
139
|
+
* PEM file with this node's certificate, optionally followed by intermediates. It has one DNS SAN,
|
|
140
|
+
* equal to nodeId, and is valid for server and client authentication: an extended key usage
|
|
141
|
+
* extension listing serverAuth and clientAuth, or no extended key usage extension.
|
|
142
|
+
*/
|
|
143
|
+
certFile: string;
|
|
144
|
+
/** PEM private key of certFile; owned by the engine's user, mode 0600 or 0400. */
|
|
145
|
+
keyFile: string;
|
|
146
|
+
}
|
|
128
147
|
/**
|
|
129
148
|
* Cluster configuration for distributed mode
|
|
130
149
|
*/
|
|
131
150
|
export interface IClusterConfig {
|
|
132
151
|
enabled: boolean;
|
|
152
|
+
/**
|
|
153
|
+
* This node's id. Generated and persisted when omitted, except with `tls`:
|
|
154
|
+
* then it is required and must be a lowercase DNS name equal to the node
|
|
155
|
+
* certificate's DNS subject alternative name.
|
|
156
|
+
*/
|
|
133
157
|
nodeId?: string;
|
|
134
158
|
quicPort?: number;
|
|
135
159
|
seedNodes?: string[];
|
|
@@ -147,11 +171,17 @@ export interface IClusterConfig {
|
|
|
147
171
|
* 60,000 (1 minute) to 604,800,000 (7 days).
|
|
148
172
|
*/
|
|
149
173
|
getDeadlineMs?: number;
|
|
174
|
+
/**
|
|
175
|
+
* Mutual TLS for the cluster transport. Without it the transport is
|
|
176
|
+
* encrypted but authenticates no peer. Every node of a cluster sets it, or
|
|
177
|
+
* none does: enabling it is a full stop of every node, not a rolling change.
|
|
178
|
+
*/
|
|
179
|
+
tls?: IClusterTlsConfig;
|
|
150
180
|
}
|
|
151
181
|
/**
|
|
152
182
|
* Configuration as the engine receives it: every section resolved.
|
|
153
183
|
*/
|
|
154
|
-
export type TObjectStorageResolvedConfig = Required<Omit<IObjectStorageConfig, 'binaryPath'>>;
|
|
184
|
+
export type TObjectStorageResolvedConfig = Required<Omit<IObjectStorageConfig, 'binaryPath' | 'dashboard'>>;
|
|
155
185
|
/**
|
|
156
186
|
* Complete objectstorage configuration
|
|
157
187
|
*/
|
|
@@ -171,6 +201,11 @@ export interface IObjectStorageConfig {
|
|
|
171
201
|
limits?: ILimitsConfig;
|
|
172
202
|
multipart?: IMultipartConfig;
|
|
173
203
|
cluster?: IClusterConfig;
|
|
204
|
+
/**
|
|
205
|
+
* The read-only visibility dashboard, served by this process on its own
|
|
206
|
+
* port. Off unless `enabled` is true; never sent to the engine.
|
|
207
|
+
*/
|
|
208
|
+
dashboard?: IObjectStorageDashboardConfig;
|
|
174
209
|
}
|
|
175
210
|
/**
|
|
176
211
|
* Logical bucket stats maintained by the Rust runtime.
|
|
@@ -725,6 +760,33 @@ export interface IClusterPeerHealth {
|
|
|
725
760
|
lastHeartbeat?: number;
|
|
726
761
|
missedHeartbeats?: number;
|
|
727
762
|
}
|
|
763
|
+
/**
|
|
764
|
+
* A drive's medium: `'rotational'` and `'flash'` (network volumes included),
|
|
765
|
+
* `'smr'` for drive-managed SMR, which reports itself as rotational and is
|
|
766
|
+
* never detected, and `'zoned'` for host-managed or host-aware SMR and ZNS.
|
|
767
|
+
*/
|
|
768
|
+
export type TDriveMedia = 'rotational' | 'smr' | 'flash' | 'zoned';
|
|
769
|
+
/**
|
|
770
|
+
* A drive's media.
|
|
771
|
+
*/
|
|
772
|
+
export interface IClusterDriveMedia {
|
|
773
|
+
/**
|
|
774
|
+
* The media the configuration declares for the drive. Not reported yet:
|
|
775
|
+
* drives cannot declare their media.
|
|
776
|
+
*/
|
|
777
|
+
declared?: TDriveMedia;
|
|
778
|
+
/**
|
|
779
|
+
* What the engine detected once at startup, from the whole disk behind the
|
|
780
|
+
* drive root's filesystem (Linux sysfs `queue/zoned` and `queue/rotational`;
|
|
781
|
+
* a partition counts as its disk). `'unknown'` for filesystems without a
|
|
782
|
+
* block device of their own (tmpfs, overlay, network filesystems),
|
|
783
|
+
* device-mapper, md, loop and other virtual block devices, and on every
|
|
784
|
+
* platform but Linux. Virtual and network block devices report the
|
|
785
|
+
* rotational flag their driver or hypervisor sets (QEMU disks show
|
|
786
|
+
* `'rotational'` unless configured with `rotation_rate=1`).
|
|
787
|
+
*/
|
|
788
|
+
detected: TDriveMedia | 'unknown';
|
|
789
|
+
}
|
|
728
790
|
/**
|
|
729
791
|
* Local drive health as measured by objectstorage's runtime probes.
|
|
730
792
|
*/
|
|
@@ -739,6 +801,7 @@ export interface IClusterDriveHealth {
|
|
|
739
801
|
lastError?: string;
|
|
740
802
|
lastCheck?: number;
|
|
741
803
|
erasureSetId?: number;
|
|
804
|
+
media: IClusterDriveMedia;
|
|
742
805
|
}
|
|
743
806
|
export interface IClusterErasureHealth {
|
|
744
807
|
dataShards: number;
|
|
@@ -762,6 +825,23 @@ export interface IClusterRepairHealth {
|
|
|
762
825
|
failed?: number;
|
|
763
826
|
lastError?: string;
|
|
764
827
|
}
|
|
828
|
+
export interface IClusterTransportCertificate {
|
|
829
|
+
/** SHA-256 of the DER certificate, lowercase hex. */
|
|
830
|
+
sha256: string;
|
|
831
|
+
/** Milliseconds since the Unix epoch. */
|
|
832
|
+
notAfter: number;
|
|
833
|
+
}
|
|
834
|
+
/**
|
|
835
|
+
* How the cluster transport authenticates peers, and the certificates it
|
|
836
|
+
* loaded at startup.
|
|
837
|
+
*/
|
|
838
|
+
export interface IClusterTransportHealth {
|
|
839
|
+
mode: 'mutualTls' | 'unauthenticated';
|
|
840
|
+
/** This node's certificate; only in mode 'mutualTls'. */
|
|
841
|
+
certificate?: IClusterTransportCertificate;
|
|
842
|
+
/** The loaded CA bundle in file order; only in mode 'mutualTls'. */
|
|
843
|
+
caCertificates?: IClusterTransportCertificate[];
|
|
844
|
+
}
|
|
765
845
|
/**
|
|
766
846
|
* Cluster runtime health from the Rust core.
|
|
767
847
|
* When clustering is disabled, the response is `{ enabled: false }`.
|
|
@@ -777,6 +857,7 @@ export interface IClusterHealth {
|
|
|
777
857
|
drives?: IClusterDriveHealth[];
|
|
778
858
|
erasure?: IClusterErasureHealth;
|
|
779
859
|
repairs?: IClusterRepairHealth;
|
|
860
|
+
transport?: IClusterTransportHealth;
|
|
780
861
|
}
|
|
781
862
|
/**
|
|
782
863
|
* The result of one cluster healing scan, as `ObjectStorage.runHealingScan()`
|
|
@@ -829,11 +910,15 @@ export declare class ObjectStorage {
|
|
|
829
910
|
private bridgeOwned;
|
|
830
911
|
private stopRequested;
|
|
831
912
|
private stopCompleted;
|
|
913
|
+
private readonly dashboardConfig;
|
|
914
|
+
private dashboard;
|
|
832
915
|
constructor(configArg?: IObjectStorageConfig);
|
|
833
916
|
start(): Promise<void>;
|
|
834
917
|
private startInternal;
|
|
835
918
|
/** Actual TCP port while running; the requested config port before/afterward. */
|
|
836
919
|
get port(): number;
|
|
920
|
+
/** The dashboard's bound TCP port while it runs; `undefined` otherwise. */
|
|
921
|
+
get dashboardPort(): number | undefined;
|
|
837
922
|
getStorageDescriptor(optionsArg?: Partial<plugins.tsclass.storage.IS3Descriptor>): Promise<plugins.tsclass.storage.IS3Descriptor>;
|
|
838
923
|
private getEndpoint;
|
|
839
924
|
private buildBucketTenantDescriptor;
|
|
@@ -902,6 +987,14 @@ export declare class ObjectStorage {
|
|
|
902
987
|
*/
|
|
903
988
|
replaceCredentials(credentials: IStorageCredential[]): Promise<void>;
|
|
904
989
|
getClusterHealth(): Promise<IClusterHealth>;
|
|
990
|
+
/**
|
|
991
|
+
* The dashboard's snapshot, built by the engine from memory only: it never
|
|
992
|
+
* probes a drive, syncs or walks storage. A cluster node also asks each
|
|
993
|
+
* online peer for its own snapshot, waiting up to a second per peer, in
|
|
994
|
+
* parallel; a peer that does not answer is reported unavailable. One
|
|
995
|
+
* snapshot runs at a time: a call while another runs rejects.
|
|
996
|
+
*/
|
|
997
|
+
getClusterSnapshot(): Promise<IObjectStorageClusterSnapshot>;
|
|
905
998
|
/**
|
|
906
999
|
* Runs a healing scan on this cluster node and resolves with its result.
|
|
907
1000
|
* The scan covers the manifests this node coordinated. The request joins
|