### Asynchronous Method: Start VM Instance Source: https://github.com/mathematrix/zstack/blob/master/docs/modules/core/pages/scalability_secrets_part_1_asynchronous_architecture.adoc Shows an example of an asynchronous method call within a service, using a Completion callback to handle the success of starting a VM instance and then proceeding to the next task in a chain. This pattern is used for internal service-to-service communication that needs to be non-blocking. ```java protected void startVm(final APIStartVmInstanceMsg msg, final SyncTaskChain taskChain) { startVm(msg, new Completion(taskChain) { @Override public void success() { VmInstanceInventory inv = VmInstanceInventory.valueOf(self); APIStartVmInstanceEvent evt = new APIStartVmInstanceEvent(msg.getId()); evt.setInventory(inv); bus.publish(evt); taskChain.next(); } }); } ``` -------------------------------- ### Interactive Program Startup Notice (GPL) Source: https://github.com/mathematrix/zstack/blob/master/conf/tools/flyway-6.3.1/licenses/LICENSES-THIRD-PARTY.txt Display this notice when a program starts in interactive mode to inform users about its version, warranty, and redistribution conditions. ```text Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type 'show w'. This is free software, and you are welcome to redistribute it under certain conditions; type 'show c' for details. ``` -------------------------------- ### ZStack Service Queue Registration Example Source: https://github.com/mathematrix/zstack/blob/master/docs/modules/core/pages/stateless_services.adoc This example shows how management nodes register service queues on the message bus, identified by a management node UUID. All queues for a specific node share the same UUID suffix. ```text zstack.message.ansible.3694776ab31a45709259254a018913ca zstack.message.api.portal zstack.message.applianceVm.3694776ab31a45709259254a018913ca zstack.message.cloudbus.3694776ab31a45709259254a018913ca zstack.message.cluster.3694776ab31a45709259254a018913ca zstack.message.configuration.3694776ab31a45709259254a018913ca zstack.message.console.3694776ab31a45709259254a018913ca zstack.message.eip.3694776ab31a45709259254a018913ca zstack.message.globalConfig.3694776ab31a45709259254a018913ca zstack.message.host.3694776ab31a45709259254a018913ca zstack.message.host.allocator.3694776ab31a45709259254a018913ca zstack.message.identity.3694776ab31a45709259254a018913ca zstack.message.image.3694776ab31a45709259254a018913ca zstack.message.managementNode.3694776ab31a45709259254a018913ca zstack.message.network.l2.3694776ab31a45709259254a018913ca zstack.message.network.l2.vlan.3694776ab31a45709259254a018913ca zstack.message.network.l3.3694776ab31a45709259254a018913ca zstack.message.network.service.3694776ab31a45709259254a018913ca zstack.message.portForwarding.3694776ab31a45709259254a018913ca zstack.message.query.3694776ab31a45709259254a018913ca zstack.message.securityGroup.3694776ab31a45709259254a018913ca zstack.message.snapshot.volume.3694776ab31a45709259254a018913ca zstack.message.storage.backup.3694776ab31a45709259254a018913ca ``` -------------------------------- ### Clone ZStack Repository and Set Up Local Environment Source: https://github.com/mathematrix/zstack/blob/master/CONTRIBUTING.md Clone your forked ZStack repository and configure local Git remotes to track the upstream repository. This is the initial setup for contributing. ```bash $ git clone https://github.com/YOUR_ACCOUNT/zstack.git (you can find the URL on the page of the forked repository) $ cd zstack $ git remote add upstream https://github.com/zstackorg/zstack.git $ git checkout master $ git fetch upstream $ git rebase upstream/master ``` -------------------------------- ### Query Network Service Provider Source: https://github.com/mathematrix/zstack/blob/master/docs/modules/network/pages/networkService/flatDhcp.adoc Example command to query details about a network service provider, which can be used to identify DHCP providers. ```bash admin >>>QueryNetworkServiceProvider uuid=cb69890a791348009e1ec61d91de8ec3 { "inventories": [ { "attachedL2NetworkUuids": [ "6c84e4ebdf4e4d1bb119c46488a7cc90", "ba7a2ac0f45d4d6a9a8da7c311ded9bb", "2131fa08cc4e43d7b82899f64f788749", "bbe2b8b0775246b0a6a7f52c6ee35cd6", ``` -------------------------------- ### Example Test Function with Function Name as Comment Source: https://github.com/mathematrix/zstack/blob/master/docs/modules/test/pages/integration-test/usages/write-test-case.adoc This example demonstrates how to structure a test logic within a function, using the function name as a clear comment for the test's purpose. It shows how to retrieve an IP range specification and assert the number of free IPs. ```groovy void useIpRangeUuidWithStartBeyondTheEndIp() { IpRangeSpec ipr = env.specByName("ipr") List freeIps = getFreeIpOfIpRange { ipRangeUuid = ipr.inventory.uuid start = "10.223.110.21" } assert freeIps.size() = 0 } ``` -------------------------------- ### Query L3 Network Configuration Source: https://github.com/mathematrix/zstack/blob/master/docs/modules/network/pages/networkService/flatDhcp.adoc Example command to query L3 network details, including IP ranges and associated network services like DHCP. ```bash admin >>>QueryL3Network uuid='e82f9446c3e34111b8b74cfcf70f4562' { "inventories": [ { "category": "Private", "createDate": "Aug 23, 2022 4:31:36 PM", "hostRoute": [], "ipRanges": [ { "createDate": "Aug 23, 2022 4:31:36 PM", "endIp": "192.168.1.254", "gateway": "192.168.1.1", "ipVersion": 4, "l3NetworkUuid": "e82f9446c3e34111b8b74cfcf70f4562", "lastOpDate": "Aug 23, 2022 4:31:36 PM", "name": "192.168.1.0/24", "netmask": "255.255.255.0", "networkCidr": "192.168.1.0/24", "prefixLen": 24, "startIp": "192.168.1.2", "uuid": "114691a225164a10904e8ac176cbdec1" } ], "ipVersion": 4, "l2NetworkUuid": "8fe67ed8517845b98b7715e31828710d", "lastOpDate": "Aug 23, 2022 4:31:36 PM", "name": "vx-2", "networkServices": [ { "l3NetworkUuid": "e82f9446c3e34111b8b74cfcf70f4562", "networkServiceProviderUuid": "a09b3ad773b24b34b7ac81a01a04df9b", "networkServiceType": "LoadBalancer" }, { "l3NetworkUuid": "e82f9446c3e34111b8b74cfcf70f4562", "networkServiceProviderUuid": "a09b3ad773b24b34b7ac81a01a04df9b", "networkServiceType": "CentralizedDNS" }, { "l3NetworkUuid": "e82f9446c3e34111b8b74cfcf70f4562", "networkServiceProviderUuid": "cb69890a791348009e1ec61d91de8ec3", "networkServiceType": "DHCP" }, { "l3NetworkUuid": "e82f9446c3e34111b8b74cfcf70f4562", "networkServiceProviderUuid": "a09b3ad773b24b34b7ac81a01a04df9b", "networkServiceType": "Eip" }, { "l3NetworkUuid": "e82f9446c3e34111b8b74cfcf70f4562", "networkServiceProviderUuid": "cb69890a791348009e1ec61d91de8ec3", "networkServiceType": "Userdata" }, { "l3Networkত্বUuid": "e82f9446c3e34111b8b74cfcf70f4562", "networkServiceProviderUuid": "a09b3ad773b24b34b7ac81a01a04df9b", "networkServiceType": "PortForwarding" }, { "l3NetworkUuid": "e82f9446c3e34111b8b74cfcf70f4562", "networkServiceProviderUuid": "a09b3ad773b24b34b7ac81a01a04df9b", "networkServiceType": "SNAT" }, { "l3NetworkUuid": "e82f9446c3e34111b8b74cfcf70f4562", "networkServiceProviderUuid": "a09b3ad773b24b34b7ac81a01a04df9b", "networkServiceType": "IPsec" }, { "l3NetworkUuid": "e82f9446c3e34111b8b74cfcf70f4562", "networkServiceProviderUuid": "a09b3ad773b24b34b7ac81a01a04df9b", "networkServiceType": "VRouterRoute" }, { "l3NetworkUuid": "e82f9446c3e34111b8b74cfcf70f4562", "networkServiceProviderUuid": "a09b3ad773b24b34b7ac81a01a04df9b", "networkServiceType": "VipQos" }, { "l3NetworkUuid": "e82f9446c3e34111b8b74cfcf70f4562", "networkServiceProviderUuid": "67bcc5c436a148a6a8d156aa7b1821eb", "networkServiceType": "SecurityGroup" } ], "state": "Enabled", "system": false, "type": "L3VpcNetwork", "uuid": "e82f9446c3e34111b8b74cfcf70f4562", "zoneUuid": "f3b1d4ee02b5497ab1bff0deb3764bca" } ], "success": true } ``` -------------------------------- ### TaskDaemon for VM Migration Cancellation (Python) Source: https://github.com/mathematrix/zstack/blob/master/docs/modules/longjob/pages/index.adoc A Python example demonstrating the implementation of a `TaskDaemon` for managing long-running tasks like VM migration. It shows how to define `_cancel` to abort the job and how the `TaskDaemon` context manager handles API ID registration and task lifecycle. ```python class MigrateDaemon(plugin.TaskDaemon): def __init__(self, domain): super(MigrateDaemon, self).__init__(cmd, 'MigrateVm', timeout) self.domain = domain def _get_percent(self): // omitted. def _cancel(self): logger.debug('cancelling vm[uuid:%s] migration' % cmd.vmUuid) self.domain.abortJob() def __exit__(self, exc_type, exc_val, exc_tb): // omitted. # to do VM migration: with MigrateDaemon(self.domain): self.domain.migrateToURI2(...) ``` -------------------------------- ### Query VM Instance by IP and Zone Source: https://github.com/mathematrix/zstack/blob/master/README.md Use this query to find a VM instance based on its Elastic IP and the zone it belongs to. This is an example of ZStack's comprehensive query APIs. ```bash QueryVmInstance vmNics.eip.guestIp=16.16.16.16 zone.name=west-coast ``` -------------------------------- ### Cancel VM Migration Implementation Source: https://github.com/mathematrix/zstack/blob/master/docs/modules/longjob/pages/index.adoc Provides an example of implementing the `cancel` method for a long-running job, specifically for canceling VM migration. It sends a `CancelMigrateVmMsg` to the bus for asynchronous processing. ```java @Override public void cancel(LongJobVO job, ReturnValueCompletion completion) { MigrateVmInnerMsg msg = JSONObjectUtil.toObject(job.getJobData(), MigrateVmInnerMsg.class); CancelMigrateVmMsg cmsg = new CancelMigrateVmMsg(); cmsg.setCancellationApiId(job.getApiId()); cmsg.setUuid(msg.getVmInstanceUuid()); bus.makeTargetServiceIdByResourceUuid(cmsg, VmInstanceConstant.SERVICE_ID, cmsg.getVmInstanceUuid()); bus.send(cmsg, new CloudBusCallBack(completion) { @Override public void run(MessageReply reply) { if (reply.isSuccess()) { completion.success(false); } else { completion.fail(reply.getError()); } } }); } ``` -------------------------------- ### Standard GPL Notice for Source Files Source: https://github.com/mathematrix/zstack/blob/master/conf/tools/flyway-6.3.1/licenses/LICENSES-THIRD-PARTY.txt Include this notice at the beginning of each source file to effectively convey the exclusion of warranty and specify redistribution terms under the GPL. ```text One line to give the program's name and a brief idea of what it does. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ``` -------------------------------- ### Configure Remote JVM Debug in IDEA Source: https://github.com/mathematrix/zstack/blob/master/docs/modules/test/pages/integration-test/usages/cookbook.adoc Set up a remote JVM debug configuration in IntelliJ IDEA. This allows you to connect the IDE debugger to a process started with debugging enabled. ```xml ``` -------------------------------- ### Query Host with Specific Fields and Conditions Source: https://github.com/mathematrix/zstack/blob/master/README.md This snippet demonstrates querying host information, including name and management IP, with filters for hypervisor type, volume size, VM state, and pagination. It showcases the flexibility of ZStack's query APIs. ```bash QueryHost fields=name,uuid,managementIp hypervisorType=KVM vmInstance.allVolumes.size>=549755813888000 vmInstance.state=Running start=0 limit=10 ``` -------------------------------- ### Execute Multiple Test Scenarios Sequentially Source: https://github.com/mathematrix/zstack/blob/master/docs/modules/test/pages/integration-test/usages/write-test-case.adoc Structure multiple test scenarios within a single `env.create()` closure to ensure they are executed in the defined order. ```groovy @Override void test() { env.create { testStopVm() ``` -------------------------------- ### LongJob Interface Definition Source: https://github.com/mathematrix/zstack/blob/master/docs/modules/longjob/pages/index.adoc Defines the core interface for long-running jobs, including methods for starting, canceling, resuming, and cleaning up jobs. The `cancel`, `resume`, and `clean` methods have default implementations. ```java public interface LongJob { void start(LongJobVO job, ReturnValueCompletion completion); default void cancel(LongJobVO job, ReturnValueCompletion completion) {} default void resume(LongJobVO job, ReturnValueCompletion completion) {} default void clean(LongJobVO job, NoErrorCompletion completion) {} default Class getAuditType() { return null; } default String getAuditResourceUuid() { return null; } } ``` -------------------------------- ### In-Memory Sync Queue Task Source: https://github.com/mathematrix/zstack/blob/master/docs/modules/core/pages/lock-free.adoc An example of a synchronous task submitted to an in-memory work queue. The task completes when the call() method returns. This is suitable for tasks that need to be executed sequentially on a specific resource. ```java thdf.syncSubmit(new SyncTask() { @Override public String getSyncSignature() { return "api.worker"; } @Override public int getSyncLevel() { return apiWorkerNum; } @Override public String getName() { return "api.worker"; } @Override public Object call() throws Exception { if (msg.getClass() == APIIsReadyToGoMsg.class) { handle((APIIsReadyToGoMsg) msg); } else { try { dispatchMessage((APIMessage) msg); } catch (Throwable t) { bus.logExceptionWithMessageDump(msg, t); bus.replyErrorByMessageType(msg, errf.throwableToInternalError(t)); } } /* When method call() returns, the next task will be proceeded immediately */ return null; } }); ``` -------------------------------- ### Classpath Exception Clarification for GPLv2 Source: https://github.com/mathematrix/zstack/blob/master/conf/tools/flyway-6.3.1/licenses/LICENSES-THIRD-PARTY.txt This clarification allows linking independent modules with a library under the GPLv2, regardless of the independent modules' license terms. ```text As a special exception, the copyright holders of this library give you permission to link this library with independent modules to produce an executable, regardless of the license terms of these independent modules, and to copy and distribute the resulting executable under terms of your choice, provided that you also meet, for each linked independent module, the terms and conditions of the license of that module. An independent module is a module which is not derived from or based on this library. If you modify this library, you may extend this exception to your version of the library, but you are not obligated to do so. If you do not wish to do so, delete this exception statement from your version. ``` -------------------------------- ### In-Memory Async Queue Task Source: https://github.com/mathematrix/zstack/blob/master/docs/modules/core/pages/lock-free.adoc An example of an asynchronous task submitted to an in-memory work queue. The task is considered complete when chain.next() is called. This allows the worker thread to return to the pool while the task may still be performing asynchronous operations. ```java thdf.chainSubmit(new ChainTask(msg) { @Override public String getName() { return String.format("start-vm-%s", self.getUuid()); } @Override public String getSyncSignature() { return syncThreadName; } @Override public void run(SyncTaskChain chain) { startVm(msg, chain); /* the next task will be proceeded only after startVm() method calls chain.next() */ } }); ``` -------------------------------- ### Implement LongJob Cancel Interface Source: https://github.com/mathematrix/zstack/blob/master/docs/modules/longjob/pages/cancel.adoc Implement the `cancel` interface for LongJob to handle cancellation requests. This example shows cancellation for migrating a VM. It returns `false` if cancellation is not yet complete and the original process needs to roll back, or `true` if cancellation and rollback are fully completed. ```java @Override public void cancel(LongJobVO job, ReturnValueCompletion completion) { MigrateVmInnerMsg msg = JSONObjectUtil.toObject(job.getJobData(), MigrateVmInnerMsg.class); CancelMigrateVmMsg cmsg = new CancelMigrateVmMsg(); cmsg.setCancellationApiId(job.getApiId()); cmsg.setUuid(msg.getVmInstanceUuid()); bus.makeTargetServiceIdByResourceUuid(cmsg, VmInstanceConstant.SERVICE_ID, cmsg.getVmInstanceUuid()); bus.send(cmsg, new CloudBusCallBack(completion) { @Override public void run(MessageReply reply) { if (reply.isSuccess()) { completion.success(false); } else { completion.fail(reply.getError()); } } }); } ``` -------------------------------- ### Create a New Branch and Commit Changes Source: https://github.com/mathematrix/zstack/blob/master/CONTRIBUTING.md Create a new branch for your feature or bugfix, make your code modifications, and commit them with a descriptive message. Always work on a separate branch. ```bash $ git checkout -b feature_x (make your changes) $ git status $ git add . $ git commit -a -m "descriptive commit message for your changes" ``` -------------------------------- ### Workflow Pre-Check for Cancellation Source: https://github.com/mathematrix/zstack/blob/master/docs/modules/longjob/pages/index.adoc Demonstrates how to implement a `preCheck` method within a workflow chain to detect if a cancellation has been requested. If canceled, it triggers an error and rollback. ```java FlowChain chain = FlowChainBuilder.newShareFlowChain(); chain.setName("awesome workflow"); chain.preCheck(data -> buildErrIfCanceled()); ``` -------------------------------- ### Push Changes and Create Pull Request Source: https://github.com/mathematrix/zstack/blob/master/CONTRIBUTING.md Push your local feature branch to your fork on GitHub and then initiate a pull request from your fork to the main ZStack repository. Ensure your branch is up-to-date before pushing. ```bash $ git push origin master $ git push origin feature_x ``` -------------------------------- ### Asynchronous Message: Attach NIC to VM Source: https://github.com/mathematrix/zstack/blob/master/docs/modules/core/pages/scalability_secrets_part_1_asynchronous_architecture.adoc Demonstrates sending an asynchronous message to attach a NIC to a VM on a hypervisor and handling the reply with a callback. This is used when a service needs to delegate a task to another service and be notified upon completion. ```java AttachNicToVmOnHypervisorMsg amsg = new AttachNicToVmOnHypervisorMsg(); amsg.setVmUuid(self.getUuid()); amsg.setHostUuid(self.getHostUuid()); amsg.setNics(msg.getNics()); bus.makeTargetServiceIdByResourceUuid(amsg, HostConstant.SERVICE_ID, self.getHostUuid()); bus.send(amsg, new CloudBusCallBack(msg) { @Override public void run(MessageReply reply) { AttachNicToVmReply r = new AttachNicToVmReply(); if (!reply.isSuccess()) { r.setError(errf.instantiateErrorCode(VmErrors.ATTACH_NETWORK_ERROR, r.getError())); } bus.reply(msg, r); } }); ```