feat: curio: alertManager (#11926)
* add alert task * maxbalance config, storage alert * docs gen * improve storage alert * fix empty alert
This commit is contained in:
parent
33876bf81c
commit
22ccaf91ef
@ -33,8 +33,6 @@ RUN set -eux; \
|
||||
COPY ./ /opt/curio
|
||||
WORKDIR /opt/curio
|
||||
|
||||
#RUN scripts/docker-git-state-check.sh
|
||||
|
||||
### make configurable filecoin-ffi build
|
||||
ARG FFI_BUILD_FROM_SOURCE=0
|
||||
ENV FFI_BUILD_FROM_SOURCE=${FFI_BUILD_FROM_SOURCE}
|
||||
|
@ -207,7 +207,7 @@ func (deps *Deps) PopulateRemainingDeps(ctx context.Context, cctx *cli.Context,
|
||||
}
|
||||
}
|
||||
|
||||
if deps.Cfg == nil {
|
||||
if deps.DB == nil {
|
||||
deps.DB, err = MakeDB(cctx)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -250,7 +250,7 @@ func complete(d *MigrationData) {
|
||||
|
||||
func completeInit(d *MigrationData) {
|
||||
stepCompleted(d, d.T("New Miner initialization complete."))
|
||||
d.say(plain, "Try the web interface with %s for further guided improvements.", "--layers=gui")
|
||||
d.say(plain, "Try the web interface with %s for further guided improvements.", code.Render("curio run --layers=gui"))
|
||||
}
|
||||
|
||||
func configToDB(d *MigrationData) {
|
||||
|
@ -40,168 +40,173 @@ func init() {
|
||||
}
|
||||
|
||||
var messageKeyToIndex = map[string]int{
|
||||
"Aborting migration.": 45,
|
||||
"Aborting migration.": 21,
|
||||
"Aborting remaining steps.": 9,
|
||||
"Aggregate-Anonymous: version, chain, and Miner power (bucketed).": 22,
|
||||
"Cannot reach the DB: %s": 90,
|
||||
"Cannot read the config.toml file in the provided directory, Error: %s": 65,
|
||||
"Compare the configurations %s to %s. Changes between the miner IDs other than wallet addreses should be a new, minimal layer for runners that need it.": 116,
|
||||
"Confidence epochs": 86,
|
||||
"Confidence epochs: %d": 76,
|
||||
"Configuration 'base' was created to resemble this lotus-miner's config.toml .": 117,
|
||||
"Configuration 'base' was updated to include this miner's address": 99,
|
||||
"Configuration 'base' was updated to include this miner's address (%s) and its wallet setup.": 115,
|
||||
"Connected to Yugabyte": 59,
|
||||
"Connected to Yugabyte. Schema is current.": 47,
|
||||
"Continue to connect and update schema.": 109,
|
||||
"Continue to verify the addresses and create a new miner actor.": 77,
|
||||
"Could not create repo from directory: %s. Aborting migration": 66,
|
||||
"Could not lock miner repo. Your miner must be stopped: %s\n Aborting migration": 67,
|
||||
"Aggregate-Anonymous: version, chain, and Miner power (bucketed).": 26,
|
||||
"Cannot reach the DB: %s": 93,
|
||||
"Cannot read the config.toml file in the provided directory, Error: %s": 68,
|
||||
"Compare the configurations %s to %s. Changes between the miner IDs other than wallet addreses should be a new, minimal layer for runners that need it.": 120,
|
||||
"Confidence epochs": 89,
|
||||
"Confidence epochs: %d": 79,
|
||||
"Configuration 'base' was created to resemble this lotus-miner's config.toml .": 121,
|
||||
"Configuration 'base' was updated to include this miner's address": 102,
|
||||
"Configuration 'base' was updated to include this miner's address (%s) and its wallet setup.": 119,
|
||||
"Connected to Yugabyte": 62,
|
||||
"Connected to Yugabyte. Schema is current.": 50,
|
||||
"Continue to connect and update schema.": 112,
|
||||
"Continue to verify the addresses and create a new miner actor.": 80,
|
||||
"Could not create repo from directory: %s. Aborting migration": 69,
|
||||
"Could not lock miner repo. Your miner must be stopped: %s\n Aborting migration": 70,
|
||||
"Create a new miner": 8,
|
||||
"Ctrl+C pressed in Terminal": 5,
|
||||
"Database config error occurred, abandoning migration: %s ": 110,
|
||||
"Database: %s": 108,
|
||||
"Documentation: ": 32,
|
||||
"Database config error occurred, abandoning migration: %s ": 113,
|
||||
"Database: %s": 111,
|
||||
"Documentation: ": 36,
|
||||
"Each step needs your confirmation and can be reversed. Press Ctrl+C to exit at any time.": 4,
|
||||
"Enabling Sector Indexing in the database.": 48,
|
||||
"Enter %s address": 82,
|
||||
"Enter the Yugabyte database %s": 113,
|
||||
"Enter the Yugabyte database host(s)": 111,
|
||||
"Enter the info to connect to your Yugabyte database installation (https://download.yugabyte.com/)": 103,
|
||||
"Enter the info to create a new miner": 71,
|
||||
"Enter the owner address": 79,
|
||||
"Enter the path to the configuration directory used by %s": 63,
|
||||
"Enter the sector size": 83,
|
||||
"Error closing backup file: %s": 56,
|
||||
"Error connecting to Yugabyte database: %s": 114,
|
||||
"Error connecting to full node API: %s": 91,
|
||||
"Error creating backup file: %s": 53,
|
||||
"Error encoding config.toml: %s": 49,
|
||||
"Error expanding path: %s": 51,
|
||||
"Enabling Sector Indexing in the database.": 51,
|
||||
"Enter %s address": 85,
|
||||
"Enter the Yugabyte database %s": 116,
|
||||
"Enter the Yugabyte database host(s)": 114,
|
||||
"Enter the info to connect to your Yugabyte database installation (https://download.yugabyte.com/)": 106,
|
||||
"Enter the info to create a new miner": 74,
|
||||
"Enter the owner address": 82,
|
||||
"Enter the path to the configuration directory used by %s": 66,
|
||||
"Enter the sector size": 86,
|
||||
"Error closing backup file: %s": 59,
|
||||
"Error connecting to Yugabyte database: %s": 117,
|
||||
"Error connecting to full node API: %s": 94,
|
||||
"Error creating backup file: %s": 56,
|
||||
"Error encoding config.toml: %s": 52,
|
||||
"Error expanding path: %s": 54,
|
||||
"Error getting API: %s": 15,
|
||||
"Error getting miner info: %s": 27,
|
||||
"Error getting miner power: %s": 25,
|
||||
"Error getting miner info: %s": 31,
|
||||
"Error getting miner power: %s": 29,
|
||||
"Error getting token: %s": 17,
|
||||
"Error interpreting miner ID: %s: ID: %s": 40,
|
||||
"Error marshalling message: %s": 26,
|
||||
"Error reading config.toml: %s": 54,
|
||||
"Error reading filemode of config.toml: %s": 52,
|
||||
"Error saving config to layer: %s. Aborting Migration": 18,
|
||||
"Error sending message: %s": 29,
|
||||
"Error sending message: Status %s, Message: ": 30,
|
||||
"Error signing message: %s": 28,
|
||||
"Error verifying sectors: %s": 41,
|
||||
"Error writing backup file: %s": 55,
|
||||
"Error writing config.toml: %s": 57,
|
||||
"Failed to create the miner actor: %s": 88,
|
||||
"Failed to generate default config: %s": 97,
|
||||
"Failed to generate random bytes for secret: %s": 93,
|
||||
"Failed to get API info for FullNode: %w": 95,
|
||||
"Failed to insert 'base' config layer in database: %s": 98,
|
||||
"Failed to load base config from database: %s": 100,
|
||||
"Failed to parse base config: %s": 101,
|
||||
"Failed to parse confidence: %s": 87,
|
||||
"Failed to parse sector size: %s": 85,
|
||||
"Failed to parse the address: %s": 81,
|
||||
"Failed to regenerate base config: %s": 102,
|
||||
"Failed to verify the auth token from daemon node: %s": 96,
|
||||
"Filecoin %s channels: %s and %s": 35,
|
||||
"Hint: I am someone running Curio on whichever chain.": 23,
|
||||
"Host: %s": 104,
|
||||
"Error interpreting miner ID: %s: ID: %s": 44,
|
||||
"Error marshalling message: %s": 30,
|
||||
"Error reading config.toml: %s": 57,
|
||||
"Error reading filemode of config.toml: %s": 55,
|
||||
"Error saving config to layer: %s. Aborting Migration": 22,
|
||||
"Error sending message: %s": 33,
|
||||
"Error sending message: Status %s, Message: ": 34,
|
||||
"Error signing message: %s": 32,
|
||||
"Error verifying sectors: %s": 45,
|
||||
"Error writing backup file: %s": 58,
|
||||
"Error writing config.toml: %s": 60,
|
||||
"Failed to create the miner actor: %s": 91,
|
||||
"Failed to generate default config: %s": 100,
|
||||
"Failed to generate random bytes for secret: %s": 96,
|
||||
"Failed to get API info for FullNode: %w": 98,
|
||||
"Failed to insert 'base' config layer in database: %s": 101,
|
||||
"Failed to load base config from database: %s": 103,
|
||||
"Failed to parse base config: %s": 104,
|
||||
"Failed to parse confidence: %s": 90,
|
||||
"Failed to parse sector size: %s": 88,
|
||||
"Failed to parse the address: %s": 84,
|
||||
"Failed to regenerate base config: %s": 105,
|
||||
"Failed to verify the auth token from daemon node: %s": 99,
|
||||
"Filecoin %s channels: %s and %s": 39,
|
||||
"Hint: I am someone running Curio on whichever chain.": 27,
|
||||
"Host: %s": 107,
|
||||
"I want to:": 6,
|
||||
"Increase reliability using redundancy: start multiple machines with at-least the post layer: 'curio run --layers=post'": 36,
|
||||
"Individual Data: Miner ID, Curio version, chain (%s or %s). Signed.": 21,
|
||||
"Initializing a new miner actor.": 70,
|
||||
"Layer %s created. ": 118,
|
||||
"Increase reliability using redundancy: start multiple machines with at-least the post layer: 'curio run --layers=post'": 40,
|
||||
"Individual Data: Miner ID, Curio version, chain (%s or %s). Signed.": 25,
|
||||
"Initializing a new miner actor.": 73,
|
||||
"Layer %s created. ": 122,
|
||||
"Lotus-Miner to Curio Migration.": 10,
|
||||
"Message sent.": 31,
|
||||
"Message sent.": 35,
|
||||
"Migrate from existing Lotus-Miner": 7,
|
||||
"Migrating lotus-miner config.toml to Curio in-database configuration.": 14,
|
||||
"Miner %s created successfully": 89,
|
||||
"Miner creation error occurred: %s ": 78,
|
||||
"Migrating metadata for %d sectors.": 118,
|
||||
"Miner %s created successfully": 92,
|
||||
"Miner creation error occurred: %s ": 81,
|
||||
"New Miner initialization complete.": 13,
|
||||
"No address provided": 80,
|
||||
"No host provided": 112,
|
||||
"No path provided, abandoning migration ": 64,
|
||||
"No value provided": 84,
|
||||
"Nothing.": 24,
|
||||
"Now shut down lotus-miner and lotus-worker and use run %s instead.": 43,
|
||||
"One database can serve multiple miner IDs: Run a migration for each lotus-miner.": 37,
|
||||
"Other": 62,
|
||||
"Owner Address: %s": 72,
|
||||
"Password: %s": 107,
|
||||
"Please do not run guided-setup again as miner creation is not idempotent. You need to run 'curio config new-cluster %s' to finish the configuration": 94,
|
||||
"Please start (or restart) %s now that database credentials are in %s.": 38,
|
||||
"Port: %s": 105,
|
||||
"Pre-initialization steps complete": 92,
|
||||
"Press return to continue": 44,
|
||||
"Press return to update %s with Yugabyte info. A Backup file will be written to that folder before changes are made.": 50,
|
||||
"Read Miner Config": 68,
|
||||
"Restart Lotus Miner. ": 58,
|
||||
"Sector Size: %d": 75,
|
||||
"Sectors verified. %d sector locations found.": 46,
|
||||
"Select the location of your lotus-miner config directory?": 61,
|
||||
"Select what you want to share with the Curio team.": 20,
|
||||
"Sender Address: %s": 74,
|
||||
"Step Complete: %s\n": 69,
|
||||
"The '%s' layer stores common configuration. All curio instances can include it in their %s argument.": 33,
|
||||
"The Curio team wants to improve the software you use. Tell the team you're using `%s`.": 19,
|
||||
"The sectors are in the database. The database is ready for %s.": 42,
|
||||
"No address provided": 83,
|
||||
"No host provided": 115,
|
||||
"No path provided, abandoning migration ": 67,
|
||||
"No value provided": 87,
|
||||
"No, abort": 20,
|
||||
"Nothing.": 28,
|
||||
"Now shut down lotus-miner and lotus-worker and use run %s instead.": 47,
|
||||
"One database can serve multiple miner IDs: Run a migration for each lotus-miner.": 41,
|
||||
"Other": 65,
|
||||
"Owner Address: %s": 75,
|
||||
"Password: %s": 110,
|
||||
"Please do not run guided-setup again as miner creation is not idempotent. You need to run 'curio config new-cluster %s' to finish the configuration": 97,
|
||||
"Please start (or restart) %s now that database credentials are in %s.": 42,
|
||||
"Port: %s": 108,
|
||||
"Pre-initialization steps complete": 95,
|
||||
"Press return to continue": 48,
|
||||
"Press return to update %s with Yugabyte info. A Backup file will be written to that folder before changes are made.": 53,
|
||||
"Read Miner Config": 71,
|
||||
"Restart Lotus Miner. ": 61,
|
||||
"Sector Size: %d": 78,
|
||||
"Sectors verified. %d sector locations found.": 49,
|
||||
"Select the location of your lotus-miner config directory?": 64,
|
||||
"Select what you want to share with the Curio team.": 24,
|
||||
"Sender Address: %s": 77,
|
||||
"Step Complete: %s\n": 72,
|
||||
"The '%s' layer stores common configuration. All curio instances can include it in their %s argument.": 37,
|
||||
"The Curio team wants to improve the software you use. Tell the team you're using `%s`.": 23,
|
||||
"The sectors are in the database. The database is ready for %s.": 46,
|
||||
"This interactive tool creates a new miner actor and creates the basic configuration layer for it.": 1,
|
||||
"This interactive tool migrates lotus-miner to Curio in 5 minutes.": 3,
|
||||
"This process is partially idempotent. Once a new miner actor has been created and subsequent steps fail, the user need to run 'curio config new-cluster < miner ID >' to finish the configuration.": 2,
|
||||
"To run Curio: With machine or cgroup isolation, use the command (with example layer selection):": 120,
|
||||
"To start, ensure your sealing pipeline is drained and shut-down lotus-miner.": 60,
|
||||
"To work with the config: ": 119,
|
||||
"To run Curio: With machine or cgroup isolation, use the command (with example layer selection):": 124,
|
||||
"To start, ensure your sealing pipeline is drained and shut-down lotus-miner.": 63,
|
||||
"To work with the config: ": 123,
|
||||
"Try the web interface with %s for further guided improvements.": 11,
|
||||
"Unmigratable sectors found. Do you want to continue?": 18,
|
||||
"Use the arrow keys to navigate: ↓ ↑ → ← ": 0,
|
||||
"Username: %s": 106,
|
||||
"Waiting for %s to write sectors into Yugabyte.": 39,
|
||||
"Worker Address: %s": 73,
|
||||
"You can add other layers for per-machine configuration changes.": 34,
|
||||
"Username: %s": 109,
|
||||
"Waiting for %s to write sectors into Yugabyte.": 43,
|
||||
"Worker Address: %s": 76,
|
||||
"Yes, continue": 19,
|
||||
"You can add other layers for per-machine configuration changes.": 38,
|
||||
"You can now migrate your market node (%s), if applicable.": 12,
|
||||
"could not get API info for FullNode: %w": 16,
|
||||
}
|
||||
|
||||
var enIndex = []uint32{ // 122 elements
|
||||
var enIndex = []uint32{ // 126 elements
|
||||
// Entry 0 - 1F
|
||||
0x00000000, 0x00000035, 0x00000097, 0x0000015a,
|
||||
0x0000019c, 0x000001f5, 0x00000210, 0x0000021b,
|
||||
0x0000023d, 0x00000250, 0x0000026a, 0x0000028a,
|
||||
0x000002cc, 0x00000309, 0x0000032c, 0x00000372,
|
||||
0x0000038b, 0x000003b6, 0x000003d1, 0x00000409,
|
||||
0x00000463, 0x00000496, 0x000004e0, 0x00000521,
|
||||
0x00000556, 0x0000055f, 0x00000580, 0x000005a1,
|
||||
0x000005c1, 0x000005de, 0x000005fb, 0x0000062e,
|
||||
0x0000038b, 0x000003b6, 0x000003d1, 0x00000406,
|
||||
0x00000414, 0x0000041e, 0x00000432, 0x0000046a,
|
||||
0x000004c4, 0x000004f7, 0x00000541, 0x00000582,
|
||||
0x000005b7, 0x000005c0, 0x000005e1, 0x00000602,
|
||||
// Entry 20 - 3F
|
||||
0x0000063c, 0x00000650, 0x000006bb, 0x000006fb,
|
||||
0x00000724, 0x0000079b, 0x000007ec, 0x00000838,
|
||||
0x0000086a, 0x00000898, 0x000008b7, 0x000008f9,
|
||||
0x0000093f, 0x00000958, 0x0000096c, 0x0000099c,
|
||||
0x000009c6, 0x000009f0, 0x00000a12, 0x00000a89,
|
||||
0x00000aa5, 0x00000ad2, 0x00000af4, 0x00000b15,
|
||||
0x00000b36, 0x00000b57, 0x00000b78, 0x00000b92,
|
||||
0x00000ba8, 0x00000bf5, 0x00000c2f, 0x00000c35,
|
||||
0x00000622, 0x0000063f, 0x0000065c, 0x0000068f,
|
||||
0x0000069d, 0x000006b1, 0x0000071c, 0x0000075c,
|
||||
0x00000785, 0x000007fc, 0x0000084d, 0x00000899,
|
||||
0x000008cb, 0x000008f9, 0x00000918, 0x0000095a,
|
||||
0x000009a0, 0x000009b9, 0x000009e9, 0x00000a13,
|
||||
0x00000a3d, 0x00000a5f, 0x00000ad6, 0x00000af2,
|
||||
0x00000b1f, 0x00000b41, 0x00000b62, 0x00000b83,
|
||||
0x00000ba4, 0x00000bc5, 0x00000bdf, 0x00000bf5,
|
||||
// Entry 40 - 5F
|
||||
0x00000c71, 0x00000c9d, 0x00000ce6, 0x00000d26,
|
||||
0x00000d77, 0x00000d89, 0x00000da3, 0x00000dc3,
|
||||
0x00000de8, 0x00000dfd, 0x00000e13, 0x00000e29,
|
||||
0x00000e3c, 0x00000e55, 0x00000e94, 0x00000ebe,
|
||||
0x00000ed6, 0x00000eea, 0x00000f0d, 0x00000f21,
|
||||
0x00000f37, 0x00000f49, 0x00000f6c, 0x00000f7e,
|
||||
0x00000fa0, 0x00000fc8, 0x00000fe9, 0x00001004,
|
||||
0x0000102d, 0x0000104f, 0x00001081, 0x00001118,
|
||||
0x00000c42, 0x00000c7c, 0x00000c82, 0x00000cbe,
|
||||
0x00000cea, 0x00000d33, 0x00000d73, 0x00000dc4,
|
||||
0x00000dd6, 0x00000df0, 0x00000e10, 0x00000e35,
|
||||
0x00000e4a, 0x00000e60, 0x00000e76, 0x00000e89,
|
||||
0x00000ea2, 0x00000ee1, 0x00000f0b, 0x00000f23,
|
||||
0x00000f37, 0x00000f5a, 0x00000f6e, 0x00000f84,
|
||||
0x00000f96, 0x00000fb9, 0x00000fcb, 0x00000fed,
|
||||
0x00001015, 0x00001036, 0x00001051, 0x0000107a,
|
||||
// Entry 60 - 7F
|
||||
0x00001143, 0x0000117b, 0x000011a4, 0x000011dc,
|
||||
0x0000121d, 0x0000124d, 0x00001270, 0x00001298,
|
||||
0x000012fa, 0x00001306, 0x00001312, 0x00001322,
|
||||
0x00001332, 0x00001342, 0x00001369, 0x000013aa,
|
||||
0x000013ce, 0x000013df, 0x00001401, 0x0000142e,
|
||||
0x0000148d, 0x0000152a, 0x00001578, 0x00001592,
|
||||
0x000015b0, 0x00001610,
|
||||
} // Size: 512 bytes
|
||||
0x0000109c, 0x000010ce, 0x00001165, 0x00001190,
|
||||
0x000011c8, 0x000011f1, 0x00001229, 0x0000126a,
|
||||
0x0000129a, 0x000012bd, 0x000012e5, 0x00001347,
|
||||
0x00001353, 0x0000135f, 0x0000136f, 0x0000137f,
|
||||
0x0000138f, 0x000013b6, 0x000013f7, 0x0000141b,
|
||||
0x0000142c, 0x0000144e, 0x0000147b, 0x000014a1,
|
||||
0x00001500, 0x0000159d, 0x000015eb, 0x00001605,
|
||||
0x00001623, 0x00001683,
|
||||
} // Size: 528 bytes
|
||||
|
||||
const enData string = "" + // Size: 5648 bytes
|
||||
const enData string = "" + // Size: 5763 bytes
|
||||
"\x04\x00\x01 0\x02Use the arrow keys to navigate: ↓ ↑ → ←\x02This intera" +
|
||||
"ctive tool creates a new miner actor and creates the basic configuration" +
|
||||
" layer for it.\x02This process is partially idempotent. Once a new miner" +
|
||||
@ -216,118 +221,120 @@ const enData string = "" + // Size: 5648 bytes
|
||||
"e (%[1]s), if applicable.\x02New Miner initialization complete.\x02Migra" +
|
||||
"ting lotus-miner config.toml to Curio in-database configuration.\x02Erro" +
|
||||
"r getting API: %[1]s\x02could not get API info for FullNode: %[1]w\x02Er" +
|
||||
"ror getting token: %[1]s\x02Error saving config to layer: %[1]s. Abortin" +
|
||||
"g Migration\x02The Curio team wants to improve the software you use. Tel" +
|
||||
"l the team you're using `%[1]s`.\x02Select what you want to share with t" +
|
||||
"he Curio team.\x02Individual Data: Miner ID, Curio version, chain (%[1]s" +
|
||||
" or %[2]s). Signed.\x02Aggregate-Anonymous: version, chain, and Miner po" +
|
||||
"wer (bucketed).\x02Hint: I am someone running Curio on whichever chain." +
|
||||
"\x02Nothing.\x02Error getting miner power: %[1]s\x02Error marshalling me" +
|
||||
"ssage: %[1]s\x02Error getting miner info: %[1]s\x02Error signing message" +
|
||||
": %[1]s\x02Error sending message: %[1]s\x04\x00\x01 .\x02Error sending m" +
|
||||
"essage: Status %[1]s, Message:\x02Message sent.\x04\x00\x01 \x0f\x02Docu" +
|
||||
"mentation:\x02The '%[1]s' layer stores common configuration. All curio i" +
|
||||
"nstances can include it in their %[2]s argument.\x02You can add other la" +
|
||||
"yers for per-machine configuration changes.\x02Filecoin %[1]s channels: " +
|
||||
"%[2]s and %[3]s\x02Increase reliability using redundancy: start multiple" +
|
||||
" machines with at-least the post layer: 'curio run --layers=post'\x02One" +
|
||||
" database can serve multiple miner IDs: Run a migration for each lotus-m" +
|
||||
"iner.\x02Please start (or restart) %[1]s now that database credentials a" +
|
||||
"re in %[2]s.\x02Waiting for %[1]s to write sectors into Yugabyte.\x02Err" +
|
||||
"or interpreting miner ID: %[1]s: ID: %[2]s\x02Error verifying sectors: %" +
|
||||
"[1]s\x02The sectors are in the database. The database is ready for %[1]s" +
|
||||
".\x02Now shut down lotus-miner and lotus-worker and use run %[1]s instea" +
|
||||
"d.\x02Press return to continue\x02Aborting migration.\x02Sectors verifie" +
|
||||
"d. %[1]d sector locations found.\x02Connected to Yugabyte. Schema is cur" +
|
||||
"rent.\x02Enabling Sector Indexing in the database.\x02Error encoding con" +
|
||||
"fig.toml: %[1]s\x02Press return to update %[1]s with Yugabyte info. A Ba" +
|
||||
"ckup file will be written to that folder before changes are made.\x02Err" +
|
||||
"or expanding path: %[1]s\x02Error reading filemode of config.toml: %[1]s" +
|
||||
"\x02Error creating backup file: %[1]s\x02Error reading config.toml: %[1]" +
|
||||
"s\x02Error writing backup file: %[1]s\x02Error closing backup file: %[1]" +
|
||||
"s\x02Error writing config.toml: %[1]s\x04\x00\x01 \x15\x02Restart Lotus " +
|
||||
"Miner.\x02Connected to Yugabyte\x02To start, ensure your sealing pipelin" +
|
||||
"e is drained and shut-down lotus-miner.\x02Select the location of your l" +
|
||||
"otus-miner config directory?\x02Other\x02Enter the path to the configura" +
|
||||
"tion directory used by %[1]s\x04\x00\x01 '\x02No path provided, abandoni" +
|
||||
"ng migration\x02Cannot read the config.toml file in the provided directo" +
|
||||
"ry, Error: %[1]s\x02Could not create repo from directory: %[1]s. Abortin" +
|
||||
"g migration\x02Could not lock miner repo. Your miner must be stopped: %[" +
|
||||
"1]s\x0a Aborting migration\x02Read Miner Config\x04\x00\x01\x0a\x15\x02S" +
|
||||
"tep Complete: %[1]s\x02Initializing a new miner actor.\x02Enter the info" +
|
||||
" to create a new miner\x02Owner Address: %[1]s\x02Worker Address: %[1]s" +
|
||||
"\x02Sender Address: %[1]s\x02Sector Size: %[1]d\x02Confidence epochs: %[" +
|
||||
"1]d\x02Continue to verify the addresses and create a new miner actor." +
|
||||
"\x04\x00\x01 %\x02Miner creation error occurred: %[1]s\x02Enter the owne" +
|
||||
"r address\x02No address provided\x02Failed to parse the address: %[1]s" +
|
||||
"\x02Enter %[1]s address\x02Enter the sector size\x02No value provided" +
|
||||
"\x02Failed to parse sector size: %[1]s\x02Confidence epochs\x02Failed to" +
|
||||
" parse confidence: %[1]s\x02Failed to create the miner actor: %[1]s\x02M" +
|
||||
"iner %[1]s created successfully\x02Cannot reach the DB: %[1]s\x02Error c" +
|
||||
"onnecting to full node API: %[1]s\x02Pre-initialization steps complete" +
|
||||
"\x02Failed to generate random bytes for secret: %[1]s\x02Please do not r" +
|
||||
"un guided-setup again as miner creation is not idempotent. You need to r" +
|
||||
"un 'curio config new-cluster %[1]s' to finish the configuration\x02Faile" +
|
||||
"d to get API info for FullNode: %[1]w\x02Failed to verify the auth token" +
|
||||
" from daemon node: %[1]s\x02Failed to generate default config: %[1]s\x02" +
|
||||
"Failed to insert 'base' config layer in database: %[1]s\x02Configuration" +
|
||||
" 'base' was updated to include this miner's address\x02Failed to load ba" +
|
||||
"se config from database: %[1]s\x02Failed to parse base config: %[1]s\x02" +
|
||||
"Failed to regenerate base config: %[1]s\x02Enter the info to connect to " +
|
||||
"your Yugabyte database installation (https://download.yugabyte.com/)\x02" +
|
||||
"Host: %[1]s\x02Port: %[1]s\x02Username: %[1]s\x02Password: %[1]s\x02Data" +
|
||||
"base: %[1]s\x02Continue to connect and update schema.\x04\x00\x01 <\x02D" +
|
||||
"atabase config error occurred, abandoning migration: %[1]s\x02Enter the " +
|
||||
"Yugabyte database host(s)\x02No host provided\x02Enter the Yugabyte data" +
|
||||
"base %[1]s\x02Error connecting to Yugabyte database: %[1]s\x02Configurat" +
|
||||
"ion 'base' was updated to include this miner's address (%[1]s) and its w" +
|
||||
"allet setup.\x02Compare the configurations %[1]s to %[2]s. Changes betwe" +
|
||||
"en the miner IDs other than wallet addreses should be a new, minimal lay" +
|
||||
"er for runners that need it.\x02Configuration 'base' was created to rese" +
|
||||
"mble this lotus-miner's config.toml .\x04\x00\x01 \x15\x02Layer %[1]s cr" +
|
||||
"eated.\x04\x00\x01 \x19\x02To work with the config:\x02To run Curio: Wit" +
|
||||
"h machine or cgroup isolation, use the command (with example layer selec" +
|
||||
"tion):"
|
||||
"ror getting token: %[1]s\x02Unmigratable sectors found. Do you want to c" +
|
||||
"ontinue?\x02Yes, continue\x02No, abort\x02Aborting migration.\x02Error s" +
|
||||
"aving config to layer: %[1]s. Aborting Migration\x02The Curio team wants" +
|
||||
" to improve the software you use. Tell the team you're using `%[1]s`." +
|
||||
"\x02Select what you want to share with the Curio team.\x02Individual Dat" +
|
||||
"a: Miner ID, Curio version, chain (%[1]s or %[2]s). Signed.\x02Aggregate" +
|
||||
"-Anonymous: version, chain, and Miner power (bucketed).\x02Hint: I am so" +
|
||||
"meone running Curio on whichever chain.\x02Nothing.\x02Error getting min" +
|
||||
"er power: %[1]s\x02Error marshalling message: %[1]s\x02Error getting min" +
|
||||
"er info: %[1]s\x02Error signing message: %[1]s\x02Error sending message:" +
|
||||
" %[1]s\x04\x00\x01 .\x02Error sending message: Status %[1]s, Message:" +
|
||||
"\x02Message sent.\x04\x00\x01 \x0f\x02Documentation:\x02The '%[1]s' laye" +
|
||||
"r stores common configuration. All curio instances can include it in the" +
|
||||
"ir %[2]s argument.\x02You can add other layers for per-machine configura" +
|
||||
"tion changes.\x02Filecoin %[1]s channels: %[2]s and %[3]s\x02Increase re" +
|
||||
"liability using redundancy: start multiple machines with at-least the po" +
|
||||
"st layer: 'curio run --layers=post'\x02One database can serve multiple m" +
|
||||
"iner IDs: Run a migration for each lotus-miner.\x02Please start (or rest" +
|
||||
"art) %[1]s now that database credentials are in %[2]s.\x02Waiting for %[" +
|
||||
"1]s to write sectors into Yugabyte.\x02Error interpreting miner ID: %[1]" +
|
||||
"s: ID: %[2]s\x02Error verifying sectors: %[1]s\x02The sectors are in the" +
|
||||
" database. The database is ready for %[1]s.\x02Now shut down lotus-miner" +
|
||||
" and lotus-worker and use run %[1]s instead.\x02Press return to continue" +
|
||||
"\x02Sectors verified. %[1]d sector locations found.\x02Connected to Yuga" +
|
||||
"byte. Schema is current.\x02Enabling Sector Indexing in the database." +
|
||||
"\x02Error encoding config.toml: %[1]s\x02Press return to update %[1]s wi" +
|
||||
"th Yugabyte info. A Backup file will be written to that folder before ch" +
|
||||
"anges are made.\x02Error expanding path: %[1]s\x02Error reading filemode" +
|
||||
" of config.toml: %[1]s\x02Error creating backup file: %[1]s\x02Error rea" +
|
||||
"ding config.toml: %[1]s\x02Error writing backup file: %[1]s\x02Error clo" +
|
||||
"sing backup file: %[1]s\x02Error writing config.toml: %[1]s\x04\x00\x01 " +
|
||||
"\x15\x02Restart Lotus Miner.\x02Connected to Yugabyte\x02To start, ensur" +
|
||||
"e your sealing pipeline is drained and shut-down lotus-miner.\x02Select " +
|
||||
"the location of your lotus-miner config directory?\x02Other\x02Enter the" +
|
||||
" path to the configuration directory used by %[1]s\x04\x00\x01 '\x02No p" +
|
||||
"ath provided, abandoning migration\x02Cannot read the config.toml file i" +
|
||||
"n the provided directory, Error: %[1]s\x02Could not create repo from dir" +
|
||||
"ectory: %[1]s. Aborting migration\x02Could not lock miner repo. Your min" +
|
||||
"er must be stopped: %[1]s\x0a Aborting migration\x02Read Miner Config" +
|
||||
"\x04\x00\x01\x0a\x15\x02Step Complete: %[1]s\x02Initializing a new miner" +
|
||||
" actor.\x02Enter the info to create a new miner\x02Owner Address: %[1]s" +
|
||||
"\x02Worker Address: %[1]s\x02Sender Address: %[1]s\x02Sector Size: %[1]d" +
|
||||
"\x02Confidence epochs: %[1]d\x02Continue to verify the addresses and cre" +
|
||||
"ate a new miner actor.\x04\x00\x01 %\x02Miner creation error occurred: %" +
|
||||
"[1]s\x02Enter the owner address\x02No address provided\x02Failed to pars" +
|
||||
"e the address: %[1]s\x02Enter %[1]s address\x02Enter the sector size\x02" +
|
||||
"No value provided\x02Failed to parse sector size: %[1]s\x02Confidence ep" +
|
||||
"ochs\x02Failed to parse confidence: %[1]s\x02Failed to create the miner " +
|
||||
"actor: %[1]s\x02Miner %[1]s created successfully\x02Cannot reach the DB:" +
|
||||
" %[1]s\x02Error connecting to full node API: %[1]s\x02Pre-initialization" +
|
||||
" steps complete\x02Failed to generate random bytes for secret: %[1]s\x02" +
|
||||
"Please do not run guided-setup again as miner creation is not idempotent" +
|
||||
". You need to run 'curio config new-cluster %[1]s' to finish the configu" +
|
||||
"ration\x02Failed to get API info for FullNode: %[1]w\x02Failed to verify" +
|
||||
" the auth token from daemon node: %[1]s\x02Failed to generate default co" +
|
||||
"nfig: %[1]s\x02Failed to insert 'base' config layer in database: %[1]s" +
|
||||
"\x02Configuration 'base' was updated to include this miner's address\x02" +
|
||||
"Failed to load base config from database: %[1]s\x02Failed to parse base " +
|
||||
"config: %[1]s\x02Failed to regenerate base config: %[1]s\x02Enter the in" +
|
||||
"fo to connect to your Yugabyte database installation (https://download.y" +
|
||||
"ugabyte.com/)\x02Host: %[1]s\x02Port: %[1]s\x02Username: %[1]s\x02Passwo" +
|
||||
"rd: %[1]s\x02Database: %[1]s\x02Continue to connect and update schema." +
|
||||
"\x04\x00\x01 <\x02Database config error occurred, abandoning migration: " +
|
||||
"%[1]s\x02Enter the Yugabyte database host(s)\x02No host provided\x02Ente" +
|
||||
"r the Yugabyte database %[1]s\x02Error connecting to Yugabyte database: " +
|
||||
"%[1]s\x02Migrating metadata for %[1]d sectors.\x02Configuration 'base' w" +
|
||||
"as updated to include this miner's address (%[1]s) and its wallet setup." +
|
||||
"\x02Compare the configurations %[1]s to %[2]s. Changes between the miner" +
|
||||
" IDs other than wallet addreses should be a new, minimal layer for runne" +
|
||||
"rs that need it.\x02Configuration 'base' was created to resemble this lo" +
|
||||
"tus-miner's config.toml .\x04\x00\x01 \x15\x02Layer %[1]s created.\x04" +
|
||||
"\x00\x01 \x19\x02To work with the config:\x02To run Curio: With machine " +
|
||||
"or cgroup isolation, use the command (with example layer selection):"
|
||||
|
||||
var koIndex = []uint32{ // 122 elements
|
||||
var koIndex = []uint32{ // 126 elements
|
||||
// Entry 0 - 1F
|
||||
0x00000000, 0x00000044, 0x000000c1, 0x000001c1,
|
||||
0x0000020e, 0x00000289, 0x000002aa, 0x000002bc,
|
||||
0x000002e5, 0x00000300, 0x00000325, 0x00000348,
|
||||
0x000003b2, 0x00000402, 0x00000428, 0x00000481,
|
||||
0x000004a0, 0x000004dc, 0x0000050c, 0x00000564,
|
||||
0x000005f0, 0x00000629, 0x0000067f, 0x000006bd,
|
||||
0x0000070b, 0x00000726, 0x00000760, 0x00000793,
|
||||
0x000007cd, 0x000007f7, 0x00000821, 0x00000863,
|
||||
0x000004a0, 0x000004dc, 0x0000050c, 0x0000055c,
|
||||
0x00000568, 0x0000057a, 0x00000595, 0x000005ed,
|
||||
0x00000679, 0x000006b2, 0x00000708, 0x00000746,
|
||||
0x00000794, 0x000007af, 0x000007e9, 0x0000081c,
|
||||
// Entry 20 - 3F
|
||||
0x00000887, 0x00000894, 0x0000091a, 0x0000096c,
|
||||
0x00000993, 0x00000a2f, 0x00000ac1, 0x00000b3c,
|
||||
0x00000b80, 0x00000bbe, 0x00000be5, 0x00000c50,
|
||||
0x00000c9d, 0x00000cc4, 0x00000cdf, 0x00000d2e,
|
||||
0x00000d6f, 0x00000daf, 0x00000df6, 0x00000e9c,
|
||||
0x00000ecc, 0x00000f1b, 0x00000f3e, 0x00000f5f,
|
||||
0x00000f82, 0x00000fa5, 0x00000fe3, 0x00001007,
|
||||
0x0000101d, 0x00001088, 0x000010d7, 0x000010de,
|
||||
0x00000856, 0x00000880, 0x000008aa, 0x000008ec,
|
||||
0x00000910, 0x0000091d, 0x000009a3, 0x000009f5,
|
||||
0x00000a1c, 0x00000ab8, 0x00000b4a, 0x00000bc5,
|
||||
0x00000c09, 0x00000c47, 0x00000c6e, 0x00000cd9,
|
||||
0x00000d26, 0x00000d4d, 0x00000d9c, 0x00000ddd,
|
||||
0x00000e1d, 0x00000e64, 0x00000f0a, 0x00000f3a,
|
||||
0x00000f89, 0x00000fac, 0x00000fcd, 0x00000ff0,
|
||||
0x00001013, 0x00001051, 0x00001075, 0x0000108b,
|
||||
// Entry 40 - 5F
|
||||
0x00001126, 0x00001178, 0x000011d2, 0x0000123c,
|
||||
0x000012cd, 0x000012e5, 0x000012ff, 0x00001323,
|
||||
0x00001356, 0x0000136e, 0x00001386, 0x0000139e,
|
||||
0x000013b3, 0x000013cb, 0x00001422, 0x0000144d,
|
||||
0x00001465, 0x0000148c, 0x000014af, 0x000014c3,
|
||||
0x000014d8, 0x000014fc, 0x00001526, 0x00001537,
|
||||
0x0000155d, 0x00001583, 0x000015bc, 0x000015f4,
|
||||
0x0000162c, 0x0000164b, 0x00001697, 0x00001755,
|
||||
0x000010f6, 0x00001145, 0x0000114c, 0x00001194,
|
||||
0x000011e6, 0x00001240, 0x000012aa, 0x0000133b,
|
||||
0x00001353, 0x0000136d, 0x00001391, 0x000013c4,
|
||||
0x000013dc, 0x000013f4, 0x0000140c, 0x00001421,
|
||||
0x00001439, 0x00001490, 0x000014bb, 0x000014d3,
|
||||
0x000014fa, 0x0000151d, 0x00001531, 0x00001546,
|
||||
0x0000156a, 0x00001594, 0x000015a5, 0x000015cb,
|
||||
0x000015f1, 0x0000162a, 0x00001662, 0x0000169a,
|
||||
// Entry 60 - 7F
|
||||
0x000017a1, 0x000017ef, 0x00001812, 0x0000186e,
|
||||
0x000018be, 0x00001913, 0x00001956, 0x00001995,
|
||||
0x00001a03, 0x00001a14, 0x00001a22, 0x00001a3a,
|
||||
0x00001a4e, 0x00001a68, 0x00001a92, 0x00001af5,
|
||||
0x00001b31, 0x00001b5b, 0x00001b93, 0x00001be7,
|
||||
0x00001c60, 0x00001d1a, 0x00001d71, 0x00001da0,
|
||||
0x00001dc7, 0x00001e53,
|
||||
} // Size: 512 bytes
|
||||
0x000016b9, 0x00001705, 0x000017c3, 0x0000180f,
|
||||
0x0000185d, 0x00001880, 0x000018dc, 0x0000192c,
|
||||
0x00001981, 0x000019c4, 0x00001a03, 0x00001a71,
|
||||
0x00001a82, 0x00001a90, 0x00001aa8, 0x00001abc,
|
||||
0x00001ad6, 0x00001b00, 0x00001b63, 0x00001b9f,
|
||||
0x00001bc9, 0x00001c01, 0x00001c55, 0x00001c8d,
|
||||
0x00001d06, 0x00001dc0, 0x00001e17, 0x00001e46,
|
||||
0x00001e6d, 0x00001ef9,
|
||||
} // Size: 528 bytes
|
||||
|
||||
const koData string = "" + // Size: 7763 bytes
|
||||
const koData string = "" + // Size: 7929 bytes
|
||||
"\x04\x00\x01 ?\x02화살표 키를 사용하여 이동하세요: ↓ ↑ → ←\x02이 대화형 도구는 새로운 채굴자 액터를 생성" +
|
||||
"하고 그에 대한 기본 구성 레이어를 생성합니다.\x02이 프로세스는 부분적으로 항등원적입니다. 새로운 채굴자 액터가 생성되었고" +
|
||||
" 후속 단계가 실패하는 경우 사용자는 구성을 완료하기 위해 'curio config new-cluster < 채굴자 ID >'를 " +
|
||||
@ -337,98 +344,100 @@ const koData string = "" + // Size: 7763 bytes
|
||||
"s-Miner에서 Curio로 이주.\x02%[1]s를 사용하여 웹 인터페이스를 시도하고 더 나은 안내된 개선을 진행하세요." +
|
||||
"\x02해당하는 경우 이제 시장 노드를 이주할 수 있습니다 (%[1]s).\x02새로운 채굴자 초기화 완료.\x02lotus-mi" +
|
||||
"ner config.toml을 Curio의 데이터베이스 구성으로 이전 중입니다.\x02API 가져오기 오류: %[1]s\x02Fu" +
|
||||
"llNode의 API 정보를 가져올 수 없습니다: %[1]w\x02토큰을 가져오는 중 오류 발생: %[1]s\x02레이어에 구성을" +
|
||||
" 저장하는 중 오류 발생: %[1]s. 마이그레이션 중단\x02Curio 팀은 당신이 사용하는 소프트웨어를 개선하고자 합니다. 팀" +
|
||||
"에게 `%[1]s`를 사용 중이라고 알려주세요.\x02Curio 팀과 공유하고 싶은 것을 선택하세요.\x02개별 데이터: 채굴" +
|
||||
"자 ID, Curio 버전, 체인 (%[1]s 또는 %[2]s). 서명됨.\x02집계-익명: 버전, 체인, 및 채굴자 파워 (" +
|
||||
"버킷).\x02힌트: 나는 어떤 체인에서든 Curio를 실행 중인 사람입니다.\x02아무것도 없습니다.\x02마이너 파워를 가" +
|
||||
"져오는 중 오류 발생: %[1]s\x02메시지를 마샬하는 중 오류 발생: %[1]s\x02마이너 정보를 가져오는 중 오류 발생" +
|
||||
": %[1]s\x02메시지 서명 중 오류 발생: %[1]s\x02메시지 전송 중 오류 발생: %[1]s\x04\x00\x01 =" +
|
||||
"\x02메시지 전송 중 오류 발생: 상태 %[1]s, 메시지:\x02메시지가 전송되었습니다.\x04\x00\x01 \x08\x02" +
|
||||
"문서:\x02'%[1]s' 레이어에는 공통 구성이 저장됩니다. 모든 Curio 인스턴스는 %[2]s 인수에 포함시킬 수 있습니" +
|
||||
"다.\x02기계별 구성 변경을 위해 다른 레이어를 추가할 수 있습니다.\x02Filecoin %[1]s 채널: %[2]s 및 " +
|
||||
"%[3]s\x02신뢰성 향상을 위한 중복성 사용: 적어도 post 레이어를 사용하여 여러 대의 기계를 시작하십시오: 'curio " +
|
||||
"run --layers=post'\x02한 개의 데이터베이스는 여러 광부 ID를 제공할 수 있습니다: 각 lotus-miner에 " +
|
||||
"대해 마이그레이션을 실행하세요.\x02데이터베이스 자격 증명이 %[2]s에 입력되었으므로 지금 %[1]s을 시작하거나 다시 시" +
|
||||
"작하세요.\x02%[1]s가 Yugabyte에 섹터를 기록하도록 대기 중입니다.\x02광부 ID를 해석하는 중 오류 발생: %" +
|
||||
"[1]s: ID: %[2]s\x02섹터 확인 중 오류 발생: %[1]s\x02섹터가 데이터베이스에 있습니다. 데이터베이스가 %[1" +
|
||||
"]s를 위해 준비되었습니다.\x02이제 lotus-miner와 lotus-worker를 종료하고 %[1]s을 실행하세요.\x02계" +
|
||||
"속하려면 리턴을 누르세요\x02마이그레이션 중단.\x02섹터가 확인되었습니다. %[1]d개의 섹터 위치를 찾았습니다.\x02Y" +
|
||||
"ugabyte에 연결되었습니다. 스키마가 현재입니다.\x02데이터베이스에서 Sector Indexing을 활성화합니다.\x02co" +
|
||||
"nfig.toml을 인코딩하는 중 오류가 발생했습니다: %[1]s\x02%[1]s을 Yugabyte 정보로 업데이트하려면 리턴 키" +
|
||||
"를 누르세요. 변경 사항을 적용하기 전에 해당 폴더에 백업 파일이 작성됩니다.\x02경로를 확장하는 중 오류 발생: %[1]s" +
|
||||
"\x02config.toml의 파일 모드를 읽는 중 오류가 발생했습니다: %[1]s\x02백업 파일 생성 오류: %[1]s\x02" +
|
||||
"config.toml 읽기 오류: %[1]s\x02백업 파일 쓰기 오류: %[1]s\x02백업 파일 닫기 오류: %[1]s\x02" +
|
||||
"config.toml을 쓰는 중 오류가 발생했습니다: %[1]s\x04\x00\x01 \x1f\x02로터스 마이너 재시작.\x02" +
|
||||
"Yugabyte에 연결됨\x02시작하려면 밀봉 파이프라인이 비어 있고 lotus-miner가 종료되었는지 확인하세요.\x02로터스" +
|
||||
" 마이너 구성 디렉토리의 위치를 선택하시겠습니까?\x02기타\x02%[1]s에서 사용하는 구성 디렉터리 경로를 입력하세요.\x04" +
|
||||
"\x00\x01 M\x02경로가 제공되지 않았으므로 마이그레이션을 포기합니다\x02제공된 디렉토리에서 config.toml 파일을" +
|
||||
" 읽을 수 없습니다. 오류: %[1]s\x02디렉토리에서 저장소를 생성할 수 없습니다: %[1]s. 마이그레이션을 중단합니다." +
|
||||
"\x02광부 저장소를 잠금 해제할 수 없습니다. 귀하의 광부를 중지해야 합니다: %[1]s\x0a 마이그레이션을 중단합니다." +
|
||||
"\x02마이너 구성 읽기\x04\x00\x01\x0a\x15\x02단계 완료: %[1]s\x02새 채굴자 액터 초기화 중.\x02" +
|
||||
"새 채굴자를 생성하기 위한 정보 입력\x02소유자 주소: %[1]s\x02작업자 주소: %[1]s\x02송신자 주소: %[1]" +
|
||||
"s\x02섹터 크기: %[1]d\x02신뢰 에포크: %[1]d\x02주소를 확인하고 새 채굴자 액터를 생성하려면 계속 진행하세요." +
|
||||
"\x04\x00\x01 &\x02채굴자 생성 오류 발생: %[1]s\x02소유자 주소 입력\x02주소가 제공되지 않았습니다\x02" +
|
||||
"주소 구문 분석 실패: %[1]s\x02%[1]s 주소 입력\x02섹터 크기 입력\x02값이 제공되지 않았습니다\x02섹터 크" +
|
||||
"기 구문 분석 실패: %[1]s\x02신뢰 에포크\x02신뢰도 구문 분석 실패: %[1]s\x02채굴자 액터 생성 실패: %[" +
|
||||
"1]s\x02%[1]s 채굴자가 성공적으로 생성되었습니다\x02데이터베이스에 연결할 수 없습니다: %[1]s\x02풀 노드 API" +
|
||||
"에 연결하는 중 오류 발생: %[1]s\x02사전 초기화 단계 완료\x02비밀번호를 위한 랜덤 바이트 생성에 실패했습니다: %" +
|
||||
"[1]s\x02마이너 생성은 idempotent하지 않으므로 가이드 설정을 다시 실행하지 마십시오. 구성을 완료하려면 'curio" +
|
||||
" config new-cluster %[1]s'를 실행해야 합니다.\x02FullNode에 대한 API 정보를 가져오는 데 실패했" +
|
||||
"습니다: %[1]w\x02데몬 노드로부터 인증 토큰을 확인하는 중 오류 발생: %[1]s\x02기본 구성 생성 실패: %[1]" +
|
||||
"s\x02데이터베이스에 'base' 구성 레이어를 삽입하는 데 실패했습니다: %[1]s\x02이 마이너 주소를 포함한 구성 'ba" +
|
||||
"se'가 업데이트되었습니다.\x02데이터베이스에서 기본 구성을 로드하는 데 실패했습니다: %[1]s\x02기본 구성을 구문 분석하" +
|
||||
"는 데 실패했습니다: %[1]s\x02기본 구성을 재생성하는 데 실패했습니다: %[1]s\x02Yugabyte 데이터베이스 설" +
|
||||
"치에 연결할 정보를 입력하십시오 (https://download.yugabyte.com/)\x02호스트: %[1]s\x02포트" +
|
||||
": %[1]s\x02사용자 이름: %[1]s\x02비밀번호: %[1]s\x02데이터베이스: %[1]s\x02계속 연결 및 스키마 " +
|
||||
"업데이트.\x04\x00\x01 ^\x02데이터베이스 구성 오류가 발생하여 마이그레이션을 포기합니다: %[1]s\x02Yuga" +
|
||||
"byte 데이터베이스 호스트를 입력하십시오\x02호스트가 제공되지 않았습니다\x02Yugabyte 데이터베이스 %[1]s을 입력하" +
|
||||
"십시오\x02Yugabyte 데이터베이스에 연결하는 중 오류가 발생했습니다: %[1]s\x02기본 설정 'base'가 이 마이" +
|
||||
"너의 주소(%[1]s) 및 지갑 설정을 포함하도록 업데이트되었습니다.\x02구성 %[1]s를 %[2]s과 비교하세요. 지갑 주" +
|
||||
"소 이외의 마이너 ID 사이의 변경 사항은 필요한 실행자를 위한 새로운 최소한의 레이어여야 합니다.\x02'base' 설정이 " +
|
||||
"이 lotus-miner의 config.toml과 유사하게 만들어졌습니다.\x04\x00\x01 *\x02레이어 %[1]s가 " +
|
||||
"생성되었습니다.\x04\x00\x01 \x22\x02구성 파일을 사용하려면:\x02Curio를 실행하려면: 기계 또는 cgro" +
|
||||
"up 격리를 사용하여 다음 명령을 사용하세요 (예제 레이어 선택과 함께):"
|
||||
"llNode의 API 정보를 가져올 수 없습니다: %[1]w\x02토큰을 가져오는 중 오류 발생: %[1]s\x02이동할 수 없는" +
|
||||
" 섹터가 발견되었습니다. 계속하시겠습니까?\x02예, 계속\x02아니오, 중단\x02마이그레이션 중단.\x02레이어에 구성을 저장" +
|
||||
"하는 중 오류 발생: %[1]s. 마이그레이션 중단\x02Curio 팀은 당신이 사용하는 소프트웨어를 개선하고자 합니다. 팀에" +
|
||||
"게 `%[1]s`를 사용 중이라고 알려주세요.\x02Curio 팀과 공유하고 싶은 것을 선택하세요.\x02개별 데이터: 채굴자" +
|
||||
" ID, Curio 버전, 체인 (%[1]s 또는 %[2]s). 서명됨.\x02집계-익명: 버전, 체인, 및 채굴자 파워 (버킷)" +
|
||||
".\x02힌트: 나는 어떤 체인에서든 Curio를 실행 중인 사람입니다.\x02아무것도 없습니다.\x02마이너 파워를 가져오는 중" +
|
||||
" 오류 발생: %[1]s\x02메시지를 마샬하는 중 오류 발생: %[1]s\x02마이너 정보를 가져오는 중 오류 발생: %[1]s" +
|
||||
"\x02메시지 서명 중 오류 발생: %[1]s\x02메시지 전송 중 오류 발생: %[1]s\x04\x00\x01 =\x02메시지 " +
|
||||
"전송 중 오류 발생: 상태 %[1]s, 메시지:\x02메시지가 전송되었습니다.\x04\x00\x01 \x08\x02문서:" +
|
||||
"\x02'%[1]s' 레이어에는 공통 구성이 저장됩니다. 모든 Curio 인스턴스는 %[2]s 인수에 포함시킬 수 있습니다." +
|
||||
"\x02기계별 구성 변경을 위해 다른 레이어를 추가할 수 있습니다.\x02Filecoin %[1]s 채널: %[2]s 및 %[3]" +
|
||||
"s\x02신뢰성 향상을 위한 중복성 사용: 적어도 post 레이어를 사용하여 여러 대의 기계를 시작하십시오: 'curio run " +
|
||||
"--layers=post'\x02한 개의 데이터베이스는 여러 광부 ID를 제공할 수 있습니다: 각 lotus-miner에 대해 마" +
|
||||
"이그레이션을 실행하세요.\x02데이터베이스 자격 증명이 %[2]s에 입력되었으므로 지금 %[1]s을 시작하거나 다시 시작하세요" +
|
||||
".\x02%[1]s가 Yugabyte에 섹터를 기록하도록 대기 중입니다.\x02광부 ID를 해석하는 중 오류 발생: %[1]s: " +
|
||||
"ID: %[2]s\x02섹터 확인 중 오류 발생: %[1]s\x02섹터가 데이터베이스에 있습니다. 데이터베이스가 %[1]s를 위해" +
|
||||
" 준비되었습니다.\x02이제 lotus-miner와 lotus-worker를 종료하고 %[1]s을 실행하세요.\x02계속하려면 리" +
|
||||
"턴을 누르세요\x02섹터가 확인되었습니다. %[1]d개의 섹터 위치를 찾았습니다.\x02Yugabyte에 연결되었습니다. 스키" +
|
||||
"마가 현재입니다.\x02데이터베이스에서 Sector Indexing을 활성화합니다.\x02config.toml을 인코딩하는 중" +
|
||||
" 오류가 발생했습니다: %[1]s\x02%[1]s을 Yugabyte 정보로 업데이트하려면 리턴 키를 누르세요. 변경 사항을 적용하" +
|
||||
"기 전에 해당 폴더에 백업 파일이 작성됩니다.\x02경로를 확장하는 중 오류 발생: %[1]s\x02config.toml의 파" +
|
||||
"일 모드를 읽는 중 오류가 발생했습니다: %[1]s\x02백업 파일 생성 오류: %[1]s\x02config.toml 읽기 오" +
|
||||
"류: %[1]s\x02백업 파일 쓰기 오류: %[1]s\x02백업 파일 닫기 오류: %[1]s\x02config.toml을 쓰" +
|
||||
"는 중 오류가 발생했습니다: %[1]s\x04\x00\x01 \x1f\x02로터스 마이너 재시작.\x02Yugabyte에 연결" +
|
||||
"됨\x02시작하려면 밀봉 파이프라인이 비어 있고 lotus-miner가 종료되었는지 확인하세요.\x02로터스 마이너 구성 디렉" +
|
||||
"토리의 위치를 선택하시겠습니까?\x02기타\x02%[1]s에서 사용하는 구성 디렉터리 경로를 입력하세요.\x04\x00\x01" +
|
||||
" M\x02경로가 제공되지 않았으므로 마이그레이션을 포기합니다\x02제공된 디렉토리에서 config.toml 파일을 읽을 수 없습" +
|
||||
"니다. 오류: %[1]s\x02디렉토리에서 저장소를 생성할 수 없습니다: %[1]s. 마이그레이션을 중단합니다.\x02광부 저" +
|
||||
"장소를 잠금 해제할 수 없습니다. 귀하의 광부를 중지해야 합니다: %[1]s\x0a 마이그레이션을 중단합니다.\x02마이너 구" +
|
||||
"성 읽기\x04\x00\x01\x0a\x15\x02단계 완료: %[1]s\x02새 채굴자 액터 초기화 중.\x02새 채굴자를 " +
|
||||
"생성하기 위한 정보 입력\x02소유자 주소: %[1]s\x02작업자 주소: %[1]s\x02송신자 주소: %[1]s\x02섹터" +
|
||||
" 크기: %[1]d\x02신뢰 에포크: %[1]d\x02주소를 확인하고 새 채굴자 액터를 생성하려면 계속 진행하세요.\x04" +
|
||||
"\x00\x01 &\x02채굴자 생성 오류 발생: %[1]s\x02소유자 주소 입력\x02주소가 제공되지 않았습니다\x02주소 구" +
|
||||
"문 분석 실패: %[1]s\x02%[1]s 주소 입력\x02섹터 크기 입력\x02값이 제공되지 않았습니다\x02섹터 크기 구문" +
|
||||
" 분석 실패: %[1]s\x02신뢰 에포크\x02신뢰도 구문 분석 실패: %[1]s\x02채굴자 액터 생성 실패: %[1]s" +
|
||||
"\x02%[1]s 채굴자가 성공적으로 생성되었습니다\x02데이터베이스에 연결할 수 없습니다: %[1]s\x02풀 노드 API에 연" +
|
||||
"결하는 중 오류 발생: %[1]s\x02사전 초기화 단계 완료\x02비밀번호를 위한 랜덤 바이트 생성에 실패했습니다: %[1]" +
|
||||
"s\x02마이너 생성은 idempotent하지 않으므로 가이드 설정을 다시 실행하지 마십시오. 구성을 완료하려면 'curio co" +
|
||||
"nfig new-cluster %[1]s'를 실행해야 합니다.\x02FullNode에 대한 API 정보를 가져오는 데 실패했습니다" +
|
||||
": %[1]w\x02데몬 노드로부터 인증 토큰을 확인하는 중 오류 발생: %[1]s\x02기본 구성 생성 실패: %[1]s\x02" +
|
||||
"데이터베이스에 'base' 구성 레이어를 삽입하는 데 실패했습니다: %[1]s\x02이 마이너 주소를 포함한 구성 'base'" +
|
||||
"가 업데이트되었습니다.\x02데이터베이스에서 기본 구성을 로드하는 데 실패했습니다: %[1]s\x02기본 구성을 구문 분석하는" +
|
||||
" 데 실패했습니다: %[1]s\x02기본 구성을 재생성하는 데 실패했습니다: %[1]s\x02Yugabyte 데이터베이스 설치에 " +
|
||||
"연결할 정보를 입력하십시오 (https://download.yugabyte.com/)\x02호스트: %[1]s\x02포트: %" +
|
||||
"[1]s\x02사용자 이름: %[1]s\x02비밀번호: %[1]s\x02데이터베이스: %[1]s\x02계속 연결 및 스키마 업데이" +
|
||||
"트.\x04\x00\x01 ^\x02데이터베이스 구성 오류가 발생하여 마이그레이션을 포기합니다: %[1]s\x02Yugabyt" +
|
||||
"e 데이터베이스 호스트를 입력하십시오\x02호스트가 제공되지 않았습니다\x02Yugabyte 데이터베이스 %[1]s을 입력하십시오" +
|
||||
"\x02Yugabyte 데이터베이스에 연결하는 중 오류가 발생했습니다: %[1]s\x02%[1]d 섹터의 메타데이터를 이동 중입니" +
|
||||
"다.\x02기본 설정 'base'가 이 마이너의 주소(%[1]s) 및 지갑 설정을 포함하도록 업데이트되었습니다.\x02구성 %" +
|
||||
"[1]s를 %[2]s과 비교하세요. 지갑 주소 이외의 마이너 ID 사이의 변경 사항은 필요한 실행자를 위한 새로운 최소한의 레이어" +
|
||||
"여야 합니다.\x02'base' 설정이 이 lotus-miner의 config.toml과 유사하게 만들어졌습니다.\x04" +
|
||||
"\x00\x01 *\x02레이어 %[1]s가 생성되었습니다.\x04\x00\x01 \x22\x02구성 파일을 사용하려면:\x02C" +
|
||||
"urio를 실행하려면: 기계 또는 cgroup 격리를 사용하여 다음 명령을 사용하세요 (예제 레이어 선택과 함께):"
|
||||
|
||||
var zhIndex = []uint32{ // 122 elements
|
||||
var zhIndex = []uint32{ // 126 elements
|
||||
// Entry 0 - 1F
|
||||
0x00000000, 0x00000033, 0x0000008b, 0x00000134,
|
||||
0x0000017c, 0x000001cb, 0x000001e4, 0x000001f1,
|
||||
0x00000211, 0x0000022a, 0x00000240, 0x0000025d,
|
||||
0x000002a5, 0x000002e6, 0x00000302, 0x00000347,
|
||||
0x00000364, 0x0000038d, 0x000003ab, 0x000003e4,
|
||||
0x00000438, 0x00000465, 0x000004b4, 0x000004ef,
|
||||
0x00000524, 0x0000052e, 0x00000552, 0x00000570,
|
||||
0x00000594, 0x000005b2, 0x000005d0, 0x00000605,
|
||||
0x00000364, 0x0000038d, 0x000003ab, 0x000003df,
|
||||
0x000003ef, 0x000003fc, 0x0000040c, 0x00000445,
|
||||
0x00000499, 0x000004c6, 0x00000515, 0x00000550,
|
||||
0x00000585, 0x0000058f, 0x000005b3, 0x000005d1,
|
||||
// Entry 20 - 3F
|
||||
0x00000618, 0x00000627, 0x00000681, 0x000006be,
|
||||
0x000006e6, 0x00000745, 0x00000795, 0x000007e8,
|
||||
0x0000080e, 0x0000083b, 0x00000859, 0x00000895,
|
||||
0x000008d9, 0x000008e9, 0x000008f9, 0x0000092c,
|
||||
0x00000959, 0x0000097e, 0x000009a1, 0x00000a19,
|
||||
0x00000a37, 0x00000a66, 0x00000a8a, 0x00000aaf,
|
||||
0x00000ad3, 0x00000af7, 0x00000b1a, 0x00000b3a,
|
||||
0x00000b4f, 0x00000b9a, 0x00000bca, 0x00000bd1,
|
||||
0x000005f5, 0x00000613, 0x00000631, 0x00000666,
|
||||
0x00000679, 0x00000688, 0x000006e2, 0x0000071f,
|
||||
0x00000747, 0x000007a6, 0x000007f6, 0x00000849,
|
||||
0x0000086f, 0x0000089c, 0x000008ba, 0x000008f6,
|
||||
0x0000093a, 0x0000094a, 0x0000097d, 0x000009aa,
|
||||
0x000009cf, 0x000009f2, 0x00000a6a, 0x00000a88,
|
||||
0x00000ab7, 0x00000adb, 0x00000b00, 0x00000b24,
|
||||
0x00000b48, 0x00000b6b, 0x00000b8b, 0x00000ba0,
|
||||
// Entry 40 - 5F
|
||||
0x00000bfb, 0x00000c1f, 0x00000c63, 0x00000c95,
|
||||
0x00000cde, 0x00000cf1, 0x00000d0b, 0x00000d2a,
|
||||
0x00000d4f, 0x00000d67, 0x00000d7c, 0x00000d94,
|
||||
0x00000da8, 0x00000dbf, 0x00000df0, 0x00000e15,
|
||||
0x00000e2b, 0x00000e3b, 0x00000e55, 0x00000e69,
|
||||
0x00000e7c, 0x00000e89, 0x00000ea9, 0x00000eb9,
|
||||
0x00000ed6, 0x00000ef6, 0x00000f10, 0x00000f2d,
|
||||
0x00000f5e, 0x00000f77, 0x00000fa0, 0x0000102d,
|
||||
0x00000beb, 0x00000c1b, 0x00000c22, 0x00000c4c,
|
||||
0x00000c70, 0x00000cb4, 0x00000ce6, 0x00000d2f,
|
||||
0x00000d42, 0x00000d5c, 0x00000d7b, 0x00000da0,
|
||||
0x00000db8, 0x00000dcd, 0x00000de5, 0x00000df9,
|
||||
0x00000e10, 0x00000e41, 0x00000e66, 0x00000e7c,
|
||||
0x00000e8c, 0x00000ea6, 0x00000eba, 0x00000ecd,
|
||||
0x00000eda, 0x00000efa, 0x00000f0a, 0x00000f27,
|
||||
0x00000f47, 0x00000f61, 0x00000f7e, 0x00000faf,
|
||||
// Entry 60 - 7F
|
||||
0x00001059, 0x00001094, 0x000010b4, 0x000010e5,
|
||||
0x00001118, 0x00001145, 0x00001166, 0x0000118c,
|
||||
0x000011e6, 0x000011f5, 0x00001204, 0x00001216,
|
||||
0x00001225, 0x00001237, 0x00001256, 0x0000128e,
|
||||
0x000012b3, 0x000012c3, 0x000012e1, 0x0000130d,
|
||||
0x0000135e, 0x000013e0, 0x00001427, 0x00001441,
|
||||
0x00001459, 0x000014b0,
|
||||
} // Size: 512 bytes
|
||||
0x00000fc8, 0x00000ff1, 0x0000107e, 0x000010aa,
|
||||
0x000010e5, 0x00001105, 0x00001136, 0x00001169,
|
||||
0x00001196, 0x000011b7, 0x000011dd, 0x00001237,
|
||||
0x00001246, 0x00001255, 0x00001267, 0x00001276,
|
||||
0x00001288, 0x000012a7, 0x000012df, 0x00001304,
|
||||
0x00001314, 0x00001332, 0x0000135e, 0x00001388,
|
||||
0x000013d9, 0x0000145b, 0x000014a2, 0x000014bc,
|
||||
0x000014d4, 0x0000152b,
|
||||
} // Size: 528 bytes
|
||||
|
||||
const zhData string = "" + // Size: 5296 bytes
|
||||
const zhData string = "" + // Size: 5419 bytes
|
||||
"\x04\x00\x01 .\x02使用箭头键进行导航:↓ ↑ → ←\x02此交互式工具将创建一个新的矿工角色,并为其创建基本配置层。\x02" +
|
||||
"该过程部分幂等。一旦创建了新的矿工角色,并且随后的步骤失败,用户需要运行 'curio config new-cluster < 矿工 ID" +
|
||||
" >' 来完成配置。\x02这个交互式工具可以在5分钟内将lotus-miner迁移到Curio。\x02每一步都需要您的确认,并且可以撤销。随" +
|
||||
@ -436,41 +445,42 @@ const zhData string = "" + // Size: 5296 bytes
|
||||
"\x02中止剩余步骤。\x02Lotus-Miner到Curio迁移。\x02尝试使用%[1]s的网络界面进行更进一步的指导性改进。\x02如果" +
|
||||
"适用,您现在可以迁移您的市场节点(%[1]s)。\x02新矿工初始化完成。\x02将 lotus-miner config.toml 迁移到" +
|
||||
" Curio 的数据库配置中。\x02获取 API 时出错:%[1]s\x02无法获取FullNode的API信息:%[1]w\x02获取令牌时" +
|
||||
"出错:%[1]s\x02保存配置到层时出错:%[1]s。正在中止迁移\x02Curio 团队希望改进您使用的软件。告诉团队您正在使用 `%[" +
|
||||
"1]s`。\x02选择您想与Curio团队分享的内容。\x02个人数据:矿工 ID,Curio 版本,链(%[1]s 或 %[2]s)。签名。" +
|
||||
"\x02聚合-匿名:版本,链和矿工算力(分桶)。\x02提示:我是在任何链上运行 Curio 的人。\x02没有。\x02获取矿工功率时出错:%" +
|
||||
"[1]s\x02整理消息时出错:%[1]s\x02获取矿工信息时出错:%[1]s\x02签署消息时出错:%[1]s\x02发送消息时出错:%[1" +
|
||||
"]s\x04\x00\x01 0\x02发送消息时出错:状态%[1]s,消息:\x02消息已发送。\x04\x00\x01 \x0a\x02文档" +
|
||||
":\x02'%[1]s'层存储通用配置。所有Curio实例都可以在其%[2]s参数中包含它。\x02您可以添加其他层进行每台机器的配置更改。" +
|
||||
"\x02Filecoin %[1]s 频道:%[2]s 和 %[3]s\x02通过冗余增加可靠性:使用至少后层启动多台机器:'curio run" +
|
||||
" --layers=post'\x02一个数据库可以服务多个矿工ID:为每个lotus-miner运行迁移。\x02请立即启动(或重新启动)%[" +
|
||||
"1]s,因为数据库凭据已在%[2]s中。\x02等待%[1]s将扇区写入Yugabyte。\x02解释矿工ID时出错:%[1]s:ID:%[2]" +
|
||||
"s\x02验证扇区时出错:%[1]s\x02扇区在数据库中。数据库已准备好用于%[1]s。\x02现在关闭lotus-miner和lotus-w" +
|
||||
"orker,改为使用%[1]s运行。\x02按回车继续\x02中止迁移。\x02扇区已验证。发现了%[1]d个扇区位置。\x02已连接到Yuga" +
|
||||
"byte。模式是当前的。\x02在数据库中启用扇区索引。\x02编码config.toml时出错:%[1]s\x02按回车键更新 %[1]s 以" +
|
||||
"包含 Yugabyte 信息。在进行更改之前,将在该文件夹中写入备份文件。\x02扩展路径时出错:%[1]s\x02读取config.tom" +
|
||||
"l文件模式时出错:%[1]s\x02创建备份文件时出错:%[1]s\x02读取 config.toml 时出错:%[1]s\x02写入备份文件时" +
|
||||
"出错:%[1]s\x02关闭备份文件时出错:%[1]s\x02写入config.toml时出错:%[1]s\x04\x00\x01 \x1b" +
|
||||
"\x02重新启动Lotus Miner。\x02已连接到Yugabyte\x02开始之前,请确保您的密封管道已排空并关闭lotus-miner。" +
|
||||
"\x02选择您的lotus-miner配置目录的位置?\x02其他\x02输入%[1]s使用的配置目录的路径\x04\x00\x01 \x1f" +
|
||||
"\x02未提供路径,放弃迁移\x02无法读取提供的目录中的config.toml文件,错误:%[1]s\x02无法从目录创建repo:%[1]s" +
|
||||
"。 中止迁移\x02无法锁定矿工repo。 您的矿工必须停止:%[1]s\x0a 中止迁移\x02读取矿工配置\x04\x00\x01" +
|
||||
"\x0a\x15\x02步骤完成:%[1]s\x02初始化新的矿工角色。\x02输入创建新矿工所需的信息\x02所有者地址:%[1]s\x02工" +
|
||||
"作地址:%[1]s\x02发送者地址:%[1]s\x02扇区大小: %[1]d\x02置信度时期: %[1]d\x02继续验证地址并创建新的" +
|
||||
"矿工角色。\x04\x00\x01 \x02矿工创建错误发生: %[1]s\x02输入所有者地址\x02未提供地址\x02解析地址失败: " +
|
||||
"%[1]s\x02输入 %[1]s 地址\x02输入扇区大小\x02未提供值\x02解析扇区大小失败: %[1]s\x02置信度时期\x02解析" +
|
||||
"置信度失败: %[1]s\x02创建矿工角色失败: %[1]s\x02矿工 %[1]s 创建成功\x02无法访问数据库: %[1]s\x02" +
|
||||
"连接到完整节点 API 时发生错误: %[1]s\x02预初始化步骤完成\x02生成密码的随机字节失败: %[1]s\x02请不要再次运行引" +
|
||||
"导设置,因为矿工创建不是幂等的。 您需要运行 'curio config new-cluster %[1]s' 来完成配置。\x02无法获取" +
|
||||
" FullNode 的 API 信息: %[1]w\x02无法验证来自守护进程节点的授权令牌: %[1]s\x02无法生成默认配置: %[1]s" +
|
||||
"\x02无法将 'base' 配置层插入数据库: %[1]s\x02配置 'base' 已更新以包含此矿工的地址\x02从数据库加载基本配置失败" +
|
||||
":%[1]s\x02解析基本配置失败:%[1]s\x02重新生成基本配置失败: %[1]s\x02输入连接到您的Yugabyte数据库安装的" +
|
||||
"信息(https://download.yugabyte.com/)\x02主机:%[1]s\x02端口:%[1]s\x02用户名:%[1]" +
|
||||
"s\x02密码:%[1]s\x02数据库:%[1]s\x02继续连接和更新架构。\x04\x00\x01 3\x02发生数据库配置错误,放弃迁移" +
|
||||
":%[1]s\x02输入Yugabyte数据库主机(S)\x02未提供主机\x02输入Yugabyte数据库 %[1]s\x02连接到Yug" +
|
||||
"abyte数据库时出错:%[1]s\x02'base'配置已更新,包括该矿工的地址(%[1]s)及其钱包设置。\x02比较配置%[1]s和%[2" +
|
||||
"]s。矿工ID之间除了钱包地址的变化应该是需要的运行者的一个新的、最小的层。\x02'base'配置已创建,以类似于这个lotus-miner的" +
|
||||
"config.toml。\x04\x00\x01 \x15\x02层%[1]s已创建。\x04\x00\x01 \x13\x02要使用配置:" +
|
||||
"\x02运行Curio:使用机器或cgroup隔离,使用命令(附带示例层选择):"
|
||||
"出错:%[1]s\x02发现无法迁移的扇区。您想要继续吗?\x02是的,继续\x02不,中止\x02中止迁移。\x02保存配置到层时出错:%" +
|
||||
"[1]s。正在中止迁移\x02Curio 团队希望改进您使用的软件。告诉团队您正在使用 `%[1]s`。\x02选择您想与Curio团队分享的内" +
|
||||
"容。\x02个人数据:矿工 ID,Curio 版本,链(%[1]s 或 %[2]s)。签名。\x02聚合-匿名:版本,链和矿工算力(分桶)。" +
|
||||
"\x02提示:我是在任何链上运行 Curio 的人。\x02没有。\x02获取矿工功率时出错:%[1]s\x02整理消息时出错:%[1]s" +
|
||||
"\x02获取矿工信息时出错:%[1]s\x02签署消息时出错:%[1]s\x02发送消息时出错:%[1]s\x04\x00\x01 0\x02发" +
|
||||
"送消息时出错:状态%[1]s,消息:\x02消息已发送。\x04\x00\x01 \x0a\x02文档:\x02'%[1]s'层存储通用配置" +
|
||||
"。所有Curio实例都可以在其%[2]s参数中包含它。\x02您可以添加其他层进行每台机器的配置更改。\x02Filecoin %[1]s " +
|
||||
"频道:%[2]s 和 %[3]s\x02通过冗余增加可靠性:使用至少后层启动多台机器:'curio run --layers=post'" +
|
||||
"\x02一个数据库可以服务多个矿工ID:为每个lotus-miner运行迁移。\x02请立即启动(或重新启动)%[1]s,因为数据库凭据已在%[" +
|
||||
"2]s中。\x02等待%[1]s将扇区写入Yugabyte。\x02解释矿工ID时出错:%[1]s:ID:%[2]s\x02验证扇区时出错:%[" +
|
||||
"1]s\x02扇区在数据库中。数据库已准备好用于%[1]s。\x02现在关闭lotus-miner和lotus-worker,改为使用%[1]s" +
|
||||
"运行。\x02按回车继续\x02扇区已验证。发现了%[1]d个扇区位置。\x02已连接到Yugabyte。模式是当前的。\x02在数据库中启" +
|
||||
"用扇区索引。\x02编码config.toml时出错:%[1]s\x02按回车键更新 %[1]s 以包含 Yugabyte 信息。在进行更改" +
|
||||
"之前,将在该文件夹中写入备份文件。\x02扩展路径时出错:%[1]s\x02读取config.toml文件模式时出错:%[1]s\x02创建" +
|
||||
"备份文件时出错:%[1]s\x02读取 config.toml 时出错:%[1]s\x02写入备份文件时出错:%[1]s\x02关闭备份文件" +
|
||||
"时出错:%[1]s\x02写入config.toml时出错:%[1]s\x04\x00\x01 \x1b\x02重新启动Lotus Mine" +
|
||||
"r。\x02已连接到Yugabyte\x02开始之前,请确保您的密封管道已排空并关闭lotus-miner。\x02选择您的lotus-mine" +
|
||||
"r配置目录的位置?\x02其他\x02输入%[1]s使用的配置目录的路径\x04\x00\x01 \x1f\x02未提供路径,放弃迁移\x02无" +
|
||||
"法读取提供的目录中的config.toml文件,错误:%[1]s\x02无法从目录创建repo:%[1]s。 中止迁移\x02无法锁定矿工r" +
|
||||
"epo。 您的矿工必须停止:%[1]s\x0a 中止迁移\x02读取矿工配置\x04\x00\x01\x0a\x15\x02步骤完成:%[1]s" +
|
||||
"\x02初始化新的矿工角色。\x02输入创建新矿工所需的信息\x02所有者地址:%[1]s\x02工作地址:%[1]s\x02发送者地址:%[1" +
|
||||
"]s\x02扇区大小: %[1]d\x02置信度时期: %[1]d\x02继续验证地址并创建新的矿工角色。\x04\x00\x01 \x02矿" +
|
||||
"工创建错误发生: %[1]s\x02输入所有者地址\x02未提供地址\x02解析地址失败: %[1]s\x02输入 %[1]s 地址\x02" +
|
||||
"输入扇区大小\x02未提供值\x02解析扇区大小失败: %[1]s\x02置信度时期\x02解析置信度失败: %[1]s\x02创建矿工角色" +
|
||||
"失败: %[1]s\x02矿工 %[1]s 创建成功\x02无法访问数据库: %[1]s\x02连接到完整节点 API 时发生错误: %[1" +
|
||||
"]s\x02预初始化步骤完成\x02生成密码的随机字节失败: %[1]s\x02请不要再次运行引导设置,因为矿工创建不是幂等的。 您需要运行 '" +
|
||||
"curio config new-cluster %[1]s' 来完成配置。\x02无法获取 FullNode 的 API 信息: %[1]w" +
|
||||
"\x02无法验证来自守护进程节点的授权令牌: %[1]s\x02无法生成默认配置: %[1]s\x02无法将 'base' 配置层插入数据库: " +
|
||||
"%[1]s\x02配置 'base' 已更新以包含此矿工的地址\x02从数据库加载基本配置失败:%[1]s\x02解析基本配置失败:%[1]s" +
|
||||
"\x02重新生成基本配置失败: %[1]s\x02输入连接到您的Yugabyte数据库安装的信息(https://download.yugaby" +
|
||||
"te.com/)\x02主机:%[1]s\x02端口:%[1]s\x02用户名:%[1]s\x02密码:%[1]s\x02数据库:%[1]s" +
|
||||
"\x02继续连接和更新架构。\x04\x00\x01 3\x02发生数据库配置错误,放弃迁移:%[1]s\x02输入Yugabyte数据库主机(" +
|
||||
"S)\x02未提供主机\x02输入Yugabyte数据库 %[1]s\x02连接到Yugabyte数据库时出错:%[1]s\x02正在迁移%[1" +
|
||||
"]d个扇区的元数据。\x02'base'配置已更新,包括该矿工的地址(%[1]s)及其钱包设置。\x02比较配置%[1]s和%[2]s。矿工ID" +
|
||||
"之间除了钱包地址的变化应该是需要的运行者的一个新的、最小的层。\x02'base'配置已创建,以类似于这个lotus-miner的confi" +
|
||||
"g.toml。\x04\x00\x01 \x15\x02层%[1]s已创建。\x04\x00\x01 \x13\x02要使用配置:\x02运行C" +
|
||||
"urio:使用机器或cgroup隔离,使用命令(附带示例层选择):"
|
||||
|
||||
// Total table size 20243 bytes (19KiB); checksum: AB52E150
|
||||
// Total table size 20695 bytes (20KiB); checksum: BB5CCE20
|
||||
|
@ -187,6 +187,44 @@
|
||||
],
|
||||
"fuzzy": true
|
||||
},
|
||||
{
|
||||
"id": "Unmigratable sectors found. Do you want to continue?",
|
||||
"message": "Unmigratable sectors found. Do you want to continue?",
|
||||
"translation": "Unmigratable sectors found. Do you want to continue?",
|
||||
"translatorComment": "Copied from source.",
|
||||
"fuzzy": true
|
||||
},
|
||||
{
|
||||
"id": "Yes, continue",
|
||||
"message": "Yes, continue",
|
||||
"translation": "Yes, continue",
|
||||
"translatorComment": "Copied from source.",
|
||||
"fuzzy": true
|
||||
},
|
||||
{
|
||||
"id": "No, abort",
|
||||
"message": "No, abort",
|
||||
"translation": "No, abort",
|
||||
"translatorComment": "Copied from source.",
|
||||
"fuzzy": true
|
||||
},
|
||||
{
|
||||
"id": "Aborting migration.",
|
||||
"message": "Aborting migration.",
|
||||
"translation": "Aborting migration.",
|
||||
"translatorComment": "Copied from source.",
|
||||
"placeholders": [
|
||||
{
|
||||
"id": "Error",
|
||||
"string": "%[1]v",
|
||||
"type": "string",
|
||||
"underlyingType": "string",
|
||||
"argNum": 1,
|
||||
"expr": "err.Error()"
|
||||
}
|
||||
],
|
||||
"fuzzy": true
|
||||
},
|
||||
{
|
||||
"id": "Error saving config to layer: {Error}. Aborting Migration",
|
||||
"message": "Error saving config to layer: {Error}. Aborting Migration",
|
||||
@ -602,13 +640,6 @@
|
||||
"translatorComment": "Copied from source.",
|
||||
"fuzzy": true
|
||||
},
|
||||
{
|
||||
"id": "Aborting migration.",
|
||||
"message": "Aborting migration.",
|
||||
"translation": "Aborting migration.",
|
||||
"translatorComment": "Copied from source.",
|
||||
"fuzzy": true
|
||||
},
|
||||
{
|
||||
"id": "Sectors verified. {I} sector locations found.",
|
||||
"message": "Sectors verified. {I} sector locations found.",
|
||||
@ -1552,6 +1583,23 @@
|
||||
],
|
||||
"fuzzy": true
|
||||
},
|
||||
{
|
||||
"id": "Migrating metadata for {NSectors} sectors.",
|
||||
"message": "Migrating metadata for {NSectors} sectors.",
|
||||
"translation": "Migrating metadata for {NSectors} sectors.",
|
||||
"translatorComment": "Copied from source.",
|
||||
"placeholders": [
|
||||
{
|
||||
"id": "NSectors",
|
||||
"string": "%[1]d",
|
||||
"type": "int",
|
||||
"underlyingType": "int",
|
||||
"argNum": 1,
|
||||
"expr": "nSectors"
|
||||
}
|
||||
],
|
||||
"fuzzy": true
|
||||
},
|
||||
{
|
||||
"id": "Configuration 'base' was updated to include this miner's address ({MinerAddress}) and its wallet setup.",
|
||||
"message": "Configuration 'base' was updated to include this miner's address ({MinerAddress}) and its wallet setup.",
|
||||
|
@ -1101,6 +1101,30 @@
|
||||
"translation": "'base' 설정이 이 lotus-miner의 config.toml과 유사하게 만들어졌습니다.",
|
||||
"message": "Configuration 'base' was created to resemble this lotus-miner's config.toml .",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Unmigratable sectors found. Do you want to continue?",
|
||||
"translation": "이동할 수 없는 섹터가 발견되었습니다. 계속하시겠습니까?",
|
||||
"message": "Unmigratable sectors found. Do you want to continue?",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Yes, continue",
|
||||
"translation": "예, 계속",
|
||||
"message": "Yes, continue",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "No, abort",
|
||||
"translation": "아니오, 중단",
|
||||
"message": "No, abort",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Migrating metadata for {NSectors} sectors.",
|
||||
"translation": "{NSectors} 섹터의 메타데이터를 이동 중입니다.",
|
||||
"message": "Migrating metadata for {NSectors} sectors.",
|
||||
"placeholder": null
|
||||
}
|
||||
]
|
||||
}
|
@ -1071,6 +1071,30 @@
|
||||
"translation": "'base'配置已创建,以类似于这个lotus-miner的config.toml。",
|
||||
"message": "Configuration 'base' was created to resemble this lotus-miner's config.toml .",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Unmigratable sectors found. Do you want to continue?",
|
||||
"translation": "发现无法迁移的扇区。您想要继续吗?",
|
||||
"message": "Unmigratable sectors found. Do you want to continue?",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Yes, continue",
|
||||
"translation": "是的,继续",
|
||||
"message": "Yes, continue",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "No, abort",
|
||||
"translation": "不,中止",
|
||||
"message": "No, abort",
|
||||
"placeholder": null
|
||||
},
|
||||
{
|
||||
"id": "Migrating metadata for {NSectors} sectors.",
|
||||
"translation": "正在迁移{NSectors}个扇区的元数据。",
|
||||
"message": "Migrating metadata for {NSectors} sectors.",
|
||||
"placeholder": null
|
||||
}
|
||||
]
|
||||
}
|
@ -16,6 +16,7 @@ import (
|
||||
|
||||
"github.com/filecoin-project/lotus/cmd/curio/deps"
|
||||
curio "github.com/filecoin-project/lotus/curiosrc"
|
||||
"github.com/filecoin-project/lotus/curiosrc/alertmanager"
|
||||
"github.com/filecoin-project/lotus/curiosrc/chainsched"
|
||||
"github.com/filecoin-project/lotus/curiosrc/ffi"
|
||||
"github.com/filecoin-project/lotus/curiosrc/gc"
|
||||
@ -144,6 +145,9 @@ func StartTasks(ctx context.Context, dependencies *deps.Deps) (*harmonytask.Task
|
||||
activeTasks = append(activeTasks, storageEndpointGcTask)
|
||||
}
|
||||
|
||||
amTask := alertmanager.NewAlertTask(full, db, cfg.Alerting)
|
||||
activeTasks = append(activeTasks, amTask)
|
||||
|
||||
if needProofParams {
|
||||
for spt := range dependencies.ProofTypes {
|
||||
if err := modules.GetParams(true)(spt); err != nil {
|
||||
|
332
curiosrc/alertmanager/alerts.go
Normal file
332
curiosrc/alertmanager/alerts.go
Normal file
@ -0,0 +1,332 @@
|
||||
package alertmanager
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/BurntSushi/toml"
|
||||
"github.com/dustin/go-humanize"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
"github.com/filecoin-project/go-state-types/big"
|
||||
|
||||
"github.com/filecoin-project/lotus/node/config"
|
||||
)
|
||||
|
||||
// balanceCheck retrieves the machine details from the database and performs balance checks on unique addresses.
|
||||
// It populates the alert map with any errors encountered during the process and with any alerts related to low wallet balance and missing wallets.
|
||||
// The alert map key is "Balance Check".
|
||||
// It queries the database for the configuration of each layer and decodes it using the toml.Decode function.
|
||||
// It then iterates over the addresses in the configuration and curates a list of unique addresses.
|
||||
// If an address is not found in the chain node, it adds an alert to the alert map.
|
||||
// If the balance of an address is below MinimumWalletBalance, it adds an alert to the alert map.
|
||||
// If there are any errors encountered during the process, the err field of the alert map is populated.
|
||||
func balanceCheck(al *alerts) {
|
||||
Name := "Balance Check"
|
||||
al.alertMap[Name] = &alertOut{}
|
||||
|
||||
var ret string
|
||||
|
||||
uniqueAddrs, _, err := al.getAddresses()
|
||||
if err != nil {
|
||||
al.alertMap[Name].err = err
|
||||
return
|
||||
}
|
||||
|
||||
for _, addrStr := range uniqueAddrs {
|
||||
addr, err := address.NewFromString(addrStr)
|
||||
if err != nil {
|
||||
al.alertMap[Name].err = xerrors.Errorf("failed to parse address: %w", err)
|
||||
return
|
||||
}
|
||||
|
||||
has, err := al.api.WalletHas(al.ctx, addr)
|
||||
if err != nil {
|
||||
al.alertMap[Name].err = err
|
||||
return
|
||||
}
|
||||
|
||||
if !has {
|
||||
ret += fmt.Sprintf("Wallet %s was not found in chain node. ", addrStr)
|
||||
}
|
||||
|
||||
balance, err := al.api.WalletBalance(al.ctx, addr)
|
||||
if err != nil {
|
||||
al.alertMap[Name].err = err
|
||||
}
|
||||
|
||||
if abi.TokenAmount(al.cfg.MinimumWalletBalance).GreaterThanEqual(balance) {
|
||||
ret += fmt.Sprintf("Balance for wallet %s is below 5 Fil. ", addrStr)
|
||||
}
|
||||
}
|
||||
if ret != "" {
|
||||
al.alertMap[Name].alertString = ret
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// taskFailureCheck retrieves the task failure counts from the database for a specific time period.
|
||||
// It then checks for specific sealing tasks and tasks with more than 5 failures to generate alerts.
|
||||
func taskFailureCheck(al *alerts) {
|
||||
Name := "TaskFailures"
|
||||
al.alertMap[Name] = &alertOut{}
|
||||
|
||||
type taskFailure struct {
|
||||
Machine string `db:"completed_by_host_and_port"`
|
||||
Name string `db:"name"`
|
||||
Failures int `db:"failed_tasks_count"`
|
||||
}
|
||||
|
||||
var taskFailures []taskFailure
|
||||
|
||||
err := al.db.Select(al.ctx, &taskFailures, `
|
||||
SELECT completed_by_host_and_port, name, COUNT(*) AS failed_count
|
||||
FROM harmony_task_history
|
||||
WHERE result = FALSE
|
||||
AND work_end >= NOW() - $1::interval
|
||||
GROUP BY completed_by_host_and_port, name
|
||||
ORDER BY completed_by_host_and_port, name;`, fmt.Sprintf("%f Minutes", AlertMangerInterval.Minutes()))
|
||||
if err != nil {
|
||||
al.alertMap[Name].err = xerrors.Errorf("getting failed task count: %w", err)
|
||||
return
|
||||
}
|
||||
|
||||
mmap := make(map[string]int)
|
||||
tmap := make(map[string]int)
|
||||
|
||||
if len(taskFailures) > 0 {
|
||||
for _, tf := range taskFailures {
|
||||
_, ok := tmap[tf.Name]
|
||||
if !ok {
|
||||
tmap[tf.Name] = tf.Failures
|
||||
} else {
|
||||
tmap[tf.Name] += tf.Failures
|
||||
}
|
||||
_, ok = mmap[tf.Machine]
|
||||
if !ok {
|
||||
mmap[tf.Machine] = tf.Failures
|
||||
} else {
|
||||
mmap[tf.Machine] += tf.Failures
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sealingTasks := []string{"SDR", "TreeD", "TreeRC", "PreCommitSubmit", "PoRep", "Finalize", "MoveStorage", "CommitSubmit", "WdPost", "ParkPiece"}
|
||||
contains := func(s []string, e string) bool {
|
||||
for _, a := range s {
|
||||
if a == e {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Alerts for any sealing pipeline failures. Other tasks should have at least 5 failures for an alert
|
||||
for name, count := range tmap {
|
||||
if contains(sealingTasks, name) {
|
||||
al.alertMap[Name].alertString += fmt.Sprintf("Task: %s, Failures: %d. ", name, count)
|
||||
}
|
||||
if count > 5 {
|
||||
al.alertMap[Name].alertString += fmt.Sprintf("Task: %s, Failures: %d. ", name, count)
|
||||
}
|
||||
}
|
||||
|
||||
// Alert if a machine failed more than 5 tasks
|
||||
for name, count := range tmap {
|
||||
if count > 5 {
|
||||
al.alertMap[Name].alertString += fmt.Sprintf("Machine: %s, Failures: %d. ", name, count)
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// permanentStorageCheck retrieves the storage details from the database and checks if there is sufficient space for sealing sectors.
|
||||
// It queries the database for the available storage for all storage paths that can store data.
|
||||
// It queries the database for sectors being sealed that have not been finalized yet.
|
||||
// For each sector, it calculates the required space for sealing based on the sector size.
|
||||
// It checks if there is enough available storage for each sector and updates the sectorMap accordingly.
|
||||
// If any sectors are unaccounted for, it calculates the total missing space and adds an alert to the alert map.
|
||||
func permanentStorageCheck(al *alerts) {
|
||||
Name := "PermanentStorageSpace"
|
||||
// Get all storage path for permanent storages
|
||||
type storage struct {
|
||||
ID string `db:"storage_id"`
|
||||
Available int64 `db:"available"`
|
||||
}
|
||||
|
||||
var storages []storage
|
||||
|
||||
err := al.db.Select(al.ctx, &storages, `
|
||||
SELECT storage_id, available
|
||||
FROM storage_path
|
||||
WHERE can_store = TRUE;`)
|
||||
if err != nil {
|
||||
al.alertMap[Name].err = xerrors.Errorf("getting storage details: %w", err)
|
||||
return
|
||||
}
|
||||
|
||||
type sector struct {
|
||||
Miner abi.ActorID `db:"sp_id"`
|
||||
Number abi.SectorNumber `db:"sector_number"`
|
||||
Proof abi.RegisteredSealProof `db:"reg_seal_proof"`
|
||||
}
|
||||
|
||||
var sectors []sector
|
||||
|
||||
err = al.db.Select(al.ctx, §ors, `
|
||||
SELECT sp_id, sector_number, reg_seal_proof
|
||||
FROM sectors_sdr_pipeline
|
||||
WHERE after_move_storage = FALSE;`)
|
||||
if err != nil {
|
||||
al.alertMap[Name].err = xerrors.Errorf("getting sectors being sealed: %w", err)
|
||||
return
|
||||
}
|
||||
|
||||
type sm struct {
|
||||
s sector
|
||||
size int64
|
||||
}
|
||||
|
||||
sectorMap := make(map[sm]bool)
|
||||
|
||||
for _, sec := range sectors {
|
||||
space := int64(0)
|
||||
sec := sec
|
||||
sectorSize, err := sec.Proof.SectorSize()
|
||||
if err != nil {
|
||||
space = int64(64<<30)*2 + int64(200<<20) // Assume 64 GiB sector
|
||||
} else {
|
||||
space = int64(sectorSize)*2 + int64(200<<20) // sealed + unsealed + cache
|
||||
}
|
||||
|
||||
key := sm{s: sec, size: space}
|
||||
|
||||
sectorMap[key] = false
|
||||
|
||||
for _, strg := range storages {
|
||||
if space > strg.Available {
|
||||
strg.Available -= space
|
||||
sectorMap[key] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
missingSpace := big.NewInt(0)
|
||||
for sec, accounted := range sectorMap {
|
||||
if !accounted {
|
||||
big.Add(missingSpace, big.NewInt(sec.size))
|
||||
}
|
||||
}
|
||||
|
||||
if missingSpace.GreaterThan(big.NewInt(0)) {
|
||||
al.alertMap[Name].alertString = fmt.Sprintf("Insufficient storage space for sealing sectors. Additional %s required.", humanize.Bytes(missingSpace.Uint64()))
|
||||
}
|
||||
}
|
||||
|
||||
// getAddresses retrieves machine details from the database, stores them in an array and compares layers for uniqueness.
|
||||
// It employs addrMap to handle unique addresses, and generated slices for configuration fields and MinerAddresses.
|
||||
// The function iterates over layers, storing decoded configuration and verifying address existence in addrMap.
|
||||
// It ends by returning unique addresses and miner slices.
|
||||
func (al *alerts) getAddresses() ([]string, []string, error) {
|
||||
// MachineDetails represents the structure of data received from the SQL query.
|
||||
type machineDetail struct {
|
||||
ID int
|
||||
HostAndPort string
|
||||
Layers string
|
||||
}
|
||||
var machineDetails []machineDetail
|
||||
|
||||
// Get all layers in use
|
||||
err := al.db.Select(al.ctx, &machineDetails, `
|
||||
SELECT m.id, m.host_and_port, d.layers
|
||||
FROM harmony_machines m
|
||||
LEFT JOIN harmony_machine_details d ON m.id = d.machine_id;`)
|
||||
if err != nil {
|
||||
return nil, nil, xerrors.Errorf("getting config layers for all machines: %w", err)
|
||||
}
|
||||
|
||||
// UniqueLayers takes an array of MachineDetails and returns a slice of unique layers.
|
||||
|
||||
layerMap := make(map[string]bool)
|
||||
var uniqueLayers []string
|
||||
|
||||
// Get unique layers in use
|
||||
for _, machine := range machineDetails {
|
||||
machine := machine
|
||||
// Split the Layers field into individual layers
|
||||
layers := strings.Split(machine.Layers, ",")
|
||||
for _, layer := range layers {
|
||||
layer = strings.TrimSpace(layer)
|
||||
if _, exists := layerMap[layer]; !exists && layer != "" {
|
||||
layerMap[layer] = true
|
||||
uniqueLayers = append(uniqueLayers, layer)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
addrMap := make(map[string]bool)
|
||||
var uniqueAddrs []string
|
||||
var miners []string
|
||||
|
||||
// Get all unique addresses
|
||||
for _, layer := range uniqueLayers {
|
||||
text := ""
|
||||
cfg := config.DefaultCurioConfig()
|
||||
err := al.db.QueryRow(al.ctx, `SELECT config FROM harmony_config WHERE title=$1`, layer).Scan(&text)
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), sql.ErrNoRows.Error()) {
|
||||
return nil, nil, xerrors.Errorf("missing layer '%s' ", layer)
|
||||
}
|
||||
return nil, nil, fmt.Errorf("could not read layer '%s': %w", layer, err)
|
||||
}
|
||||
|
||||
_, err = toml.Decode(text, cfg)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("could not read layer, bad toml %s: %w", layer, err)
|
||||
}
|
||||
|
||||
for i := range cfg.Addresses {
|
||||
prec := cfg.Addresses[i].PreCommitControl
|
||||
com := cfg.Addresses[i].CommitControl
|
||||
term := cfg.Addresses[i].TerminateControl
|
||||
miner := cfg.Addresses[i].MinerAddresses
|
||||
if prec != nil {
|
||||
for j := range prec {
|
||||
if _, ok := addrMap[prec[j]]; !ok && prec[j] != "" {
|
||||
addrMap[prec[j]] = true
|
||||
uniqueAddrs = append(uniqueAddrs, prec[j])
|
||||
}
|
||||
}
|
||||
}
|
||||
if com != nil {
|
||||
for j := range com {
|
||||
if _, ok := addrMap[com[j]]; !ok && com[j] != "" {
|
||||
addrMap[com[j]] = true
|
||||
uniqueAddrs = append(uniqueAddrs, com[j])
|
||||
}
|
||||
}
|
||||
}
|
||||
if term != nil {
|
||||
for j := range term {
|
||||
if _, ok := addrMap[term[j]]; !ok && term[j] != "" {
|
||||
addrMap[term[j]] = true
|
||||
uniqueAddrs = append(uniqueAddrs, term[j])
|
||||
}
|
||||
}
|
||||
}
|
||||
if miner != nil {
|
||||
for j := range miner {
|
||||
if _, ok := addrMap[miner[j]]; !ok && miner[j] != "" {
|
||||
addrMap[miner[j]] = true
|
||||
miners = append(miners, miner[j])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return uniqueAddrs, miners, nil
|
||||
}
|
227
curiosrc/alertmanager/task_alert.go
Normal file
227
curiosrc/alertmanager/task_alert.go
Normal file
@ -0,0 +1,227 @@
|
||||
// Nobody associated with this software's development has any business relationship to pagerduty.
|
||||
// This is provided as a convenient trampoline to SP's alert system of choice.
|
||||
|
||||
package alertmanager
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
logging "github.com/ipfs/go-log/v2"
|
||||
"golang.org/x/xerrors"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/lib/harmony/harmonydb"
|
||||
"github.com/filecoin-project/lotus/lib/harmony/harmonytask"
|
||||
"github.com/filecoin-project/lotus/lib/harmony/resources"
|
||||
"github.com/filecoin-project/lotus/node/config"
|
||||
"github.com/filecoin-project/lotus/storage/ctladdr"
|
||||
)
|
||||
|
||||
const AlertMangerInterval = time.Hour
|
||||
|
||||
var log = logging.Logger("curio/alertmanager")
|
||||
|
||||
type AlertAPI interface {
|
||||
ctladdr.NodeApi
|
||||
StateMinerInfo(ctx context.Context, actor address.Address, tsk types.TipSetKey) (api.MinerInfo, error)
|
||||
}
|
||||
|
||||
type AlertTask struct {
|
||||
api AlertAPI
|
||||
cfg config.CurioAlerting
|
||||
db *harmonydb.DB
|
||||
}
|
||||
|
||||
type alertOut struct {
|
||||
err error
|
||||
alertString string
|
||||
}
|
||||
|
||||
type alerts struct {
|
||||
ctx context.Context
|
||||
api AlertAPI
|
||||
db *harmonydb.DB
|
||||
cfg config.CurioAlerting
|
||||
alertMap map[string]*alertOut
|
||||
}
|
||||
|
||||
type pdPayload struct {
|
||||
Summary string `json:"summary"`
|
||||
Severity string `json:"severity"`
|
||||
Source string `json:"source"`
|
||||
Component string `json:"component,omitempty"`
|
||||
Group string `json:"group,omitempty"`
|
||||
Class string `json:"class,omitempty"`
|
||||
CustomDetails interface{} `json:"custom_details,omitempty"`
|
||||
}
|
||||
|
||||
type alertFunc func(al *alerts)
|
||||
|
||||
var alertFuncs = []alertFunc{
|
||||
balanceCheck,
|
||||
taskFailureCheck,
|
||||
permanentStorageCheck,
|
||||
}
|
||||
|
||||
func NewAlertTask(api AlertAPI, db *harmonydb.DB, alertingCfg config.CurioAlerting) *AlertTask {
|
||||
return &AlertTask{
|
||||
api: api,
|
||||
db: db,
|
||||
cfg: alertingCfg,
|
||||
}
|
||||
}
|
||||
|
||||
func (a *AlertTask) Do(taskID harmonytask.TaskID, stillOwned func() bool) (done bool, err error) {
|
||||
if a.cfg.PageDutyIntegrationKey == "" {
|
||||
log.Warnf("PageDutyIntegrationKey is empty, not sending an alert")
|
||||
return true, nil
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
alMap := make(map[string]*alertOut)
|
||||
|
||||
altrs := &alerts{
|
||||
ctx: ctx,
|
||||
api: a.api,
|
||||
db: a.db,
|
||||
cfg: a.cfg,
|
||||
alertMap: alMap,
|
||||
}
|
||||
|
||||
for _, al := range alertFuncs {
|
||||
al(altrs)
|
||||
}
|
||||
|
||||
details := make(map[string]interface{})
|
||||
|
||||
for k, v := range altrs.alertMap {
|
||||
if v != nil {
|
||||
if v.err != nil {
|
||||
details[k] = v.err.Error()
|
||||
continue
|
||||
}
|
||||
if v.alertString != "" {
|
||||
details[k] = v.alertString
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Alert only if required
|
||||
if len(details) > 0 {
|
||||
payloadData := &pdPayload{
|
||||
Summary: "Curio Alert",
|
||||
Severity: "critical",
|
||||
CustomDetails: details,
|
||||
Source: "Curio Cluster",
|
||||
}
|
||||
|
||||
err = a.sendAlert(payloadData)
|
||||
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
}
|
||||
|
||||
return true, nil
|
||||
|
||||
}
|
||||
|
||||
func (a *AlertTask) CanAccept(ids []harmonytask.TaskID, engine *harmonytask.TaskEngine) (*harmonytask.TaskID, error) {
|
||||
id := ids[0]
|
||||
return &id, nil
|
||||
}
|
||||
|
||||
func (a *AlertTask) TypeDetails() harmonytask.TaskTypeDetails {
|
||||
return harmonytask.TaskTypeDetails{
|
||||
Max: 1,
|
||||
Name: "AlertManager",
|
||||
Cost: resources.Resources{
|
||||
Cpu: 1,
|
||||
Ram: 64 << 20,
|
||||
Gpu: 0,
|
||||
},
|
||||
IAmBored: harmonytask.SingletonTaskAdder(AlertMangerInterval, a),
|
||||
}
|
||||
}
|
||||
|
||||
func (a *AlertTask) Adder(taskFunc harmonytask.AddTaskFunc) {
|
||||
return
|
||||
}
|
||||
|
||||
var _ harmonytask.TaskInterface = &AlertTask{}
|
||||
|
||||
// sendAlert sends an alert to PagerDuty with the provided payload data.
|
||||
// It creates a PDData struct with the provided routing key, event action and payload.
|
||||
// It creates an HTTP POST request with the PagerDuty event URL as the endpoint and the marshaled JSON data as the request body.
|
||||
// It sends the request using an HTTP client with a maximum of 5 retries for network errors with exponential backoff before each retry.
|
||||
// It handles different HTTP response status codes and returns an error based on the status code().
|
||||
// If all retries fail, it returns an error indicating the last network error encountered.
|
||||
func (a *AlertTask) sendAlert(data *pdPayload) error {
|
||||
|
||||
type pdData struct {
|
||||
RoutingKey string `json:"routing_key"`
|
||||
EventAction string `json:"event_action"`
|
||||
Payload *pdPayload `json:"payload"`
|
||||
}
|
||||
|
||||
payload := &pdData{
|
||||
RoutingKey: a.cfg.PageDutyIntegrationKey,
|
||||
EventAction: "trigger",
|
||||
Payload: data,
|
||||
}
|
||||
|
||||
jsonData, err := json.Marshal(payload)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error marshaling JSON: %w", err)
|
||||
}
|
||||
|
||||
req, err := http.NewRequest("POST", a.cfg.PagerDutyEventURL, bytes.NewBuffer(jsonData))
|
||||
if err != nil {
|
||||
return fmt.Errorf("error creating request: %w", err)
|
||||
}
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
|
||||
client := &http.Client{}
|
||||
var resp *http.Response
|
||||
|
||||
for i := 0; i < 5; i++ { // Maximum of 5 retries
|
||||
resp, err = client.Do(req)
|
||||
if err != nil {
|
||||
time.Sleep(time.Duration(2*i) * time.Second) // Exponential backoff
|
||||
continue
|
||||
}
|
||||
defer func() { _ = resp.Body.Close() }()
|
||||
|
||||
switch resp.StatusCode {
|
||||
case 202:
|
||||
log.Debug("Accepted: The event has been accepted by PagerDuty.")
|
||||
return nil
|
||||
case 400:
|
||||
bd, rerr := io.ReadAll(resp.Body)
|
||||
if rerr != nil {
|
||||
return xerrors.Errorf("Bad request: payload JSON is invalid. Failed to read the body: %w", err)
|
||||
}
|
||||
return xerrors.Errorf("Bad request: payload JSON is invalid %s", string(bd))
|
||||
case 429:
|
||||
log.Debug("Too many API calls, retrying after backoff...")
|
||||
time.Sleep(time.Duration(5*i) * time.Second) // Exponential backoff
|
||||
case 500, 501, 502, 503, 504:
|
||||
log.Debug("Server error, retrying after backoff...")
|
||||
time.Sleep(time.Duration(5*i) * time.Second) // Exponential backoff
|
||||
default:
|
||||
log.Errorw("Response status:", resp.Status)
|
||||
return xerrors.Errorf("Unexpected HTTP response: %s", resp.Status)
|
||||
}
|
||||
}
|
||||
return fmt.Errorf("after retries, last error: %w", err)
|
||||
}
|
@ -364,3 +364,24 @@
|
||||
# type: string
|
||||
#StorageRPCSecret = ""
|
||||
|
||||
|
||||
[Alerting]
|
||||
# PagerDutyEventURL is URL for PagerDuty.com Events API v2 URL. Events sent to this API URL are ultimately
|
||||
# routed to a PagerDuty.com service and processed.
|
||||
# The default is sufficient for integration with the stock commercial PagerDuty.com company's service.
|
||||
#
|
||||
# type: string
|
||||
#PagerDutyEventURL = "https://events.pagerduty.com/v2/enqueue"
|
||||
|
||||
# PageDutyIntegrationKey is the integration key for a PagerDuty.com service. You can find this unique service
|
||||
# identifier in the integration page for the service.
|
||||
#
|
||||
# type: string
|
||||
#PageDutyIntegrationKey = ""
|
||||
|
||||
# MinimumWalletBalance is the minimum balance all active wallets. If the balance is below this value, an
|
||||
# alerts will be triggered for the wallet
|
||||
#
|
||||
# type: types.FIL
|
||||
#MinimumWalletBalance = "5 FIL"
|
||||
|
||||
|
@ -368,5 +368,10 @@ func DefaultCurioConfig() *CurioConfig {
|
||||
MaxQueueTrees: 0, // default don't use this limit
|
||||
MaxQueuePoRep: 0, // default don't use this limit
|
||||
},
|
||||
Alerting: CurioAlerting{
|
||||
PagerDutyEventURL: "https://events.pagerduty.com/v2/enqueue",
|
||||
PageDutyIntegrationKey: "",
|
||||
MinimumWalletBalance: types.MustParseFIL("5"),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -183,6 +183,30 @@ over the worker address if this flag is set.`,
|
||||
Comment: `MinerAddresses are the addresses of the miner actors to use for sending messages`,
|
||||
},
|
||||
},
|
||||
"CurioAlerting": {
|
||||
{
|
||||
Name: "PagerDutyEventURL",
|
||||
Type: "string",
|
||||
|
||||
Comment: `PagerDutyEventURL is URL for PagerDuty.com Events API v2 URL. Events sent to this API URL are ultimately
|
||||
routed to a PagerDuty.com service and processed.
|
||||
The default is sufficient for integration with the stock commercial PagerDuty.com company's service.`,
|
||||
},
|
||||
{
|
||||
Name: "PageDutyIntegrationKey",
|
||||
Type: "string",
|
||||
|
||||
Comment: `PageDutyIntegrationKey is the integration key for a PagerDuty.com service. You can find this unique service
|
||||
identifier in the integration page for the service.`,
|
||||
},
|
||||
{
|
||||
Name: "MinimumWalletBalance",
|
||||
Type: "types.FIL",
|
||||
|
||||
Comment: `MinimumWalletBalance is the minimum balance all active wallets. If the balance is below this value, an
|
||||
alerts will be triggered for the wallet`,
|
||||
},
|
||||
},
|
||||
"CurioConfig": {
|
||||
{
|
||||
Name: "Subsystems",
|
||||
@ -224,6 +248,12 @@ over the worker address if this flag is set.`,
|
||||
Name: "Apis",
|
||||
Type: "ApisConfig",
|
||||
|
||||
Comment: ``,
|
||||
},
|
||||
{
|
||||
Name: "Alerting",
|
||||
Type: "CurioAlerting",
|
||||
|
||||
Comment: ``,
|
||||
},
|
||||
},
|
||||
|
@ -77,6 +77,7 @@ type CurioConfig struct {
|
||||
Ingest CurioIngestConfig
|
||||
Journal JournalConfig
|
||||
Apis ApisConfig
|
||||
Alerting CurioAlerting
|
||||
}
|
||||
|
||||
type ApisConfig struct {
|
||||
@ -1109,3 +1110,18 @@ type FaultReporterConfig struct {
|
||||
// rewards. This address should have adequate funds to cover gas fees.
|
||||
ConsensusFaultReporterAddress string
|
||||
}
|
||||
|
||||
type CurioAlerting struct {
|
||||
// PagerDutyEventURL is URL for PagerDuty.com Events API v2 URL. Events sent to this API URL are ultimately
|
||||
// routed to a PagerDuty.com service and processed.
|
||||
// The default is sufficient for integration with the stock commercial PagerDuty.com company's service.
|
||||
PagerDutyEventURL string
|
||||
|
||||
// PageDutyIntegrationKey is the integration key for a PagerDuty.com service. You can find this unique service
|
||||
// identifier in the integration page for the service.
|
||||
PageDutyIntegrationKey string
|
||||
|
||||
// MinimumWalletBalance is the minimum balance all active wallets. If the balance is below this value, an
|
||||
// alerts will be triggered for the wallet
|
||||
MinimumWalletBalance types.FIL
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user