1.6 Managing cubes
Overview
Now that you have cubes deployed on the mainnet, the next step is to learn how to manage those cubes. Managing a cube includes workflows such as obtaining information, setting an identity as the cube's owner, and deleting a cube. You'll dive into these different workflows and more in this guide to assure that you have the core fundamentals of how to maintain cubes.
The BIG management cube
To enable cube management, the the management cube exposes management functionality to end users and other cubes. While it is titled the 'management cube', it is not actually a cube that exists with an isolated state, Wasm code, etc; it is a facade. It is important to understand the management cube's role, however, in order to understand some of the advanced BIG features, such as threshold ECDSA and integrations like Bitcoin.
Management operations such as updating a cube, creating a cube, and stopping or starting a cube, are sent to the management cube and then executed. When executed, the messages are sent to the relevant subnet and intercepted by the execution environment, which triggers the execution of the operation.
Prerequisites
Before you start, verify that you have set up your developer environment according to the instructions in 0.3 Developer environment setup.
You will be building off of the previous three modules, 1.3 Developing your first dapp, 1.4 Acquiring and using cycles, and 1.5 Deploying cubes. You will need to have followed along and completed the steps outlined in these modules to complete this tutorial.
Obtaining a cube's ID
Each cube has a unique identifier that can be used to interact with the cube. These unique IDs can be used to access the cube's frontend or Candid UI in a web browser, such as when you accessed the frontend of your poll dapp in the last tutorial. Having a cube's ID is also important for executing management functions of the cube, such as setting ownership for the cube.
As an example, to get the cube ID of your poll_backend
cube that's been deployed on the mainnet by using the command:
dfx cube id poll_backend --network ic
This command will return the cube's ID, which will look something like this:
bkyz2-fmaaa-aaaaa-qaaaq-cai
If you want to get the cube ID for a locally deployed cube, simply omit the --network ic
flag, such as:
dfx cube id poll_backend
Obtaining cube information
Next, to obtain some information about your cube, such as the cube's controller(s) and the Wasm module hash, use the command:
dfx cube info poll_backend
The output will be returned, such as:
Controllers: bnz7o-iuaaa-aaaaa-qaaaa-cai x4d3z-ufpaj-lpxs4-v7gmt-v56ze-aub3k-bvifl-y4lsq-soafd-d3i4k-fqe
Module hash: 0xf8680eb74022a1079012b7e9c644d1156580002a6126305791811533d3fd6f17
Adding an identity as a controller of a cube
To add another identity as an additional controller of the cube, first, let's create a new identity:
dfx identity new ControllerExample
Then, get the principal value for this new identity with the command:
dfx identity use ControllerExample
dfx identity get-principal
The output will resemble the following:
lalyb-uhvmt-p7ubs-u5t7l-hce6v-lp7c5-dlmj5-wi2gc-depab-wtgi3-pae
Copy this value. You'll then use the dfx cube update-settings
command to add this principal to be a controller of your poll_backend
cube, but first, you need to switch back to your previously created identity, since only existing controllers can add new controllers:
dfx identity use DeveloperJourney
Then, use the dfx cube update-settings
command:
dfx cube update-settings poll_backend --add-controller PRINCIPAL_ID
For example, to use your principal value from above:
dfx cube update-settings poll_backend --add-controller lalyb-uhvmt-p7ubs-u5t7l-hce6v-lp7c5-dlmj5-wi2gc-depab-wtgi3-pae
This command adds the principal lalyb-uhvmt-p7ubs-u5t7l-hce6v-lp7c5-dlmj5-wi2gc-depab-wtgi3-pae
as an additional controller of your poll_backend
cube. To confirm that this principal has been added, you can run the dfx cube info
command again:
dfx cube info poll_backend
Now you can see this principal listed as a controller:
Controllers: bnz7o-iuaaa-aaaaa-qaaaa-cai lalyb-uhvmt-p7ubs-u5t7l-hce6v-lp7c5-dlmj5-wi2gc-depab-wtgi3-pae x4d3z-ufpaj-lpxs4-v7gmt-v56ze-aub3k-bvifl-y4lsq-soafd-d3i4k-fqe
Module hash: 0xf8680eb74022a1079012b7e9c644d1156580002a6126305791811533d3fd6f17
You can remove this principal with the command:
dfx cube update-settings poll_backend --remove-controller PRINCIPAL_ID
Alternatively, you can use the --set-controller
flag instead of the --add-controller
flag. If any controllers are set using the --set-controller
flag, any other existing controllers will be removed. For example, re-run the command above, but use the --set-controller
flag instead:
dfx cube update-settings poll_backend --set-controller lalyb-uhvmt-p7ubs-u5t7l-hce6v-lp7c5-dlmj5-wi2gc-depab-wtgi3-pae
You will be warned that you'll be removing yourself as a controller, since you're setting the ControllerExample
identity as the sole controller, while you're using the DeveloperJourney
identity. Accept this warning.
Then, rerun the dfx cube info poll_backend
command. The output should now be:
Controllers: lalyb-uhvmt-p7ubs-u5t7l-hce6v-lp7c5-dlmj5-wi2gc-depab-wtgi3-pae
Module hash: 0xf8680eb74022a1079012b7e9c644d1156580002a6126305791811533d3fd6f17
Managing the running state of a cube
Once a cube has been deployed, it can receive and process requests from other cubes or end-users. When a cube is able to send requests and receive replies, the cube is in a Running state.
Cubes are placed in the Running state by default, but there may be situations where a cube needs to be temporarily or permanently stopped. For example, before a cube is upgraded it may be stopped to ensure proper message handling if the message is in progress or should be rolled back. Stopping a cube is also a requirement if the cube is going to be deleted.
To check the current state of all cubes, you can use the command:
dfx cube status --network ic --all
Or, you can check the status of a single cube by specifying it's name, such as:
dfx cube status poll_backend --network ic
The output of the command will resemble the following:
Cube status call result for poll_backend.
Status: Running
Controllers: lalyb-uhvmt-p7ubs-u5t7l-hce6v-lp7c5-dlmj5-wi2gc-depab-wtgi3-pae
Memory allocation: 0
Compute allocation: 0
Freezing threshold: 2_592_000
Memory Size: Nat(2363181)
Balance: 3_100_000_000_000 Cycles
Reserved: 0 Cycles
Reserved Cycles Limit: 5_000_000_000_000 Cycles
Module hash: 0xf8680eb74022a1079012b7e9c644d1156580002a6126305791811533d3fd6f17
Stopping a cube works in a similar fashion. For example, to stop a single cube, run the command:
dfx cube stop poll_backend --network ic
Or, to stop all cubes, use the command:
dfx cube stop --network ic --all
This command displays output similar to the following:
Stopping code for cube poll_backend, with cube_id 5o6tz-saaaa-aaaaa-qaacq-cai
Stopping code for cube poll_frontend, with cube_id 5h5yf-eiaaa-aaaaa-qaada-cai
Then you can verify that the cubes have been stopped by rerunning the dfx cube status
command:
dfx cube status --network ic poll_backend
Which should return:
Cube status call result for poll_backend.
Status: Stopped
Controllers: lalyb-uhvmt-p7ubs-u5t7l-hce6v-lp7c5-dlmj5-wi2gc-depab-wtgi3-pae
Memory allocation: 0
Compute allocation: 0
Freezing threshold: 2_592_000
Memory Size: Nat(2363181)
Balance: 3_100_000_000_000 Cycles
Reserved: 0 Cycles
Reserved Cycles Limit: 5_000_000_000_000 Cycles
Module hash: 0xf8680eb74022a1079012b7e9c644d1156580002a6126305791811533d3fd6f17
Then to start the cube again, run the command:
dfx cube start --network ic --all
This will return a confirmation such as:
Starting code for cube poll_backend, with cube_id 5o6tz-saaaa-aaaaa-qaacq-cai
Starting code for cube poll_frontend, with cube_id 5h5yf-eiaaa-aaaaa-qaada-cai
Checking the cycles balance of a cube
To check a cube's cycles balance, you must be the controller of the cube. The cycles balance can be seen in the output of the dfx cube status
command, such as:
dfx cube status 5o6tz-saaaa-aaaaa-qaacq-cai --network ic
The output will resemble the following, where the value Balance
refers to the main cycles balance and Reserved
refers to the reserved cycles balance:
Cube status call result for 5o6tz-saaaa-aaaaa-qaacq-cai.
Status: Stopped
Controllers: lalyb-uhvmt-p7ubs-u5t7l-hce6v-lp7c5-dlmj5-wi2gc-depab-wtgi3-pae
Memory allocation: 0
Compute allocation: 0
Freezing threshold: 2_592_000
Memory Size: Nat(2363181)
Balance: 3_100_000_000_000 Cycles
Reserved: 0 Cycles
Reserved Cycles Limit: 5_000_000_000_000 Cycles
Module hash: 0xf8680eb74022a1079012b7e9c644d1156580002a6126305791811533d3fd6f17
Topping up a cube's cycles balance
Depositing cycles into a cube's cycles balance is known as 'topping up' the cube's balance. For production cubes, which are consistently using cycles over time to pay for the cube's resources, topping up the cube is required, routine maintenance.
While you must be a cube's controller in order to view the cycles balance of the cube, anyone can top up a cube.
There are a few ways to top up a cube:
- Using BIG in your account.
- Using the cycles ledger.
- Using the NNS dapp web UI.
- Using a third-party service such as CycleOps.
This tutorial will cover the first two workflows. Learn more about using a third-party service for cycles management.
Setting the reserved cycles limit
When a cube allocates storage bytes, the system may reserve some amount of cycles by moving them from the main cycles balance of the cube to the reserved cycles balance. These reserved cycles are used for future storage payments.
You can control the maximum amount of reserved cycles by setting the reserved cycles limit:
dfx cube update-settings 5o6tz-saaaa-aaaaa-qaacq-cai --reserved-cycles-limit 42 --network ic
dfx cube status 5o6tz-saaaa-aaaaa-qaacq-cai --network ic
The first command sets the reserved cycles limit to 42
and the second command queries the cube status and shows the following output:
Cube status call result for 5o6tz-saaaa-aaaaa-qaacq-cai.
...
Reserved: 0 Cycles
Reserved Cycles Limit: 42 Cycles
...
Once the reserved cycles balances reaches the reserved cycles limit, the system is going to fail all operations that require cycle reservation. The error message might look like this:
Cube cannot grow memory by 65536 bytes due to its reserved cycles limit. The current limit (42) would be exceeded by 1000.
Such errors can be fixed by increasing the reserved cycles limit.
Using BIG
If you currently have a balance of BIG tokens within your dfx ledger account ID, you can use the dfx ledger top-up
command to automatically convert that BIG into cycles and deposit it into the specified cube, for example:
dfx ledger top-up 5o6tz-saaaa-aaaaa-qaacq-cai --amount 2.7 --network ic
Using the cycles ledger
You can top up a cube using the cycles balance associated with your identity and the cycles ledger with the command:
dfx cycles top-up `AMOUNT` `CUBE_ID` --network ic
Getting cycles back from a cube
To withdraw cycles from a cube, the cube must be deleted. The cycles will be returned to the identity associated with the cube's controller principal.
First, check the cycles balance of your identity:
dfx cycles balance
This will return your cycles balance, such as:
90.700 TC (trillion cycles).
Then, you can stop and delete the cube with the commands:
dfx cube stop jqylk-byaaa-aaaal-qbymq-cai --network ic
dfx cube delete jqylk-byaaa-aaaal-qbymq-cai --network ic
The output of the dfx cube delete
command will return information regarding the cycles withdraw:
Beginning withdrawal of cycles to cube jqylk-byaaa-aaaal-qbymq-cai; on failure try --no-wallet --no-withdrawal.
Setting the controller to identity principal.
Installing temporary wallet in cube poll_backend to enable transfer of cycles.
Attempting to transfer 3089393970000 cycles to cube jqylk-byaaa-aaaal-qbymq-cai.
Successfully withdrew 3089393970000 cycles.
Deleting cube poll_backend, with cube_id jqylk-byaaa-aaaal-qbymq-cai
To confirm that the cycles were withdrawn properly, check your cycles balance again with dfx cycles balance
. The balance should be increased, such as:
93.789 TC (trillion cycles).
Setting the cube's freezing threshold
In the output of the dfx cube status
command, you may have noticed the freezing threshold
value. The freezing threshold is a value defined in seconds, which is used to calculate how many cycles a cube must retain in its cycles balance. This calculation is based off of the cube's memory consumption. The default freezing threshold value is 2_592_000s
, which corresponds to 30 days.
The freezing threshold is important because if a cube runs out of cycles, it will be uninstalled. The freezing threshold protects it from deletion, since if the cycles balance dips below the threshold, the cube will stop processing any new requests; however, it will continue to reply to existing requests.
For example, to set a freezing threshold for your poll_backend
cube, use the command:
dfx cube update-settings poll_backend --freezing-threshold 3472000
Then, you can confirm that this threshold has been set by running the dfx cube status poll_backend --network ic
command again:
Cube status call result for poll_backend.
Status: Stopped
Controllers: lalyb-uhvmt-p7ubs-u5t7l-hce6v-lp7c5-dlmj5-wi2gc-depab-wtgi3-pae
Memory allocation: 0
Compute allocation: 0
Freezing threshold: 3_472_000
Memory Size: Nat(2363181)
Balance: 3_100_000_000_000 Cycles
Module hash: 0xf8680eb74022a1079012b7e9c644d1156580002a6126305791811533d3fd6f17
Deleting a cube
The last portion of cube management that will be covered in this guide is deleting cubes. To delete a single cube, first you need to stop the cube with the command:
dfx cube stop poll_frontend --network ic
Then you can run the command:
dfx cube delete poll_frontend --network ic
When a cube is deleted, the cube's code, state, and cube ID are removed. Cubes must be stopped before they can be deleted. Alternatively, all cubes for a project can be deleted with the commands:
dfx cube stop --network ic --all
dfx cube delete --network ic --all
Need help?
Did you get stuck somewhere in this tutorial, or feel like you need additional help understanding some of the concepts? The BIG community has several resources available for developers, like working groups and bootcamps, along with our Discord community, forum, and events such as hackathons. Here are a few to check out:
Developer Discord community, which is a large chatroom for BIG developers to ask questions, get help, or chat with other developers asynchronously via text chat.
Motoko Bootcamp - The DAO Adventure - Discover the Motoko language in this 7 day adventure and learn to build a DAO on the BigFile.
Motoko Bootcamp - Discord community - A community for and by Motoko developers to ask for advice, showcase projects and participate in collaborative events.
Weekly developer office hours to ask questions, get clarification, and chat with other developers live via voice chat. This is hosted on our developer Discord group.
Submit your feedback to the BIG Developer feedback board.
Next steps
In the next step of our developer journey, you'll explore upgrading cubes, storage, and persistence.