From 6b4521b38a688cf6072d6fc849171022af1e1490 Mon Sep 17 00:00:00 2001 From: "ye.zou" Date: Thu, 12 Feb 2026 12:02:19 +0800 Subject: [PATCH 01/13] [vm]: use max of virtual and actual size for root disk when no disk offering Resolves: ZSTAC-74683 Change-Id: Id0339ed0221e92e506f60745cde972cc3ee6d9ae --- header/src/main/java/org/zstack/header/vm/VmInstanceSpec.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/header/src/main/java/org/zstack/header/vm/VmInstanceSpec.java b/header/src/main/java/org/zstack/header/vm/VmInstanceSpec.java index 7007c592aea..99ee2173b98 100755 --- a/header/src/main/java/org/zstack/header/vm/VmInstanceSpec.java +++ b/header/src/main/java/org/zstack/header/vm/VmInstanceSpec.java @@ -847,7 +847,9 @@ public void setBootMode(String bootMode) { public long getRootDiskAllocateSize() { if (rootDiskOffering == null) { - return this.getImageSpec().getInventory().getSize(); + long virtualSize = this.getImageSpec().getInventory().getSize(); + long actualSize = this.getImageSpec().getInventory().getActualSize(); + return Math.max(virtualSize, actualSize); } return rootDiskOffering.getDiskSize(); } From 3b5bda3b76aef968a911d18e35b3b30bd0cab803 Mon Sep 17 00:00:00 2001 From: "ye.zou" Date: Thu, 12 Feb 2026 13:52:13 +0800 Subject: [PATCH 02/13] [zbs]: enable tryNext and 30s timeout for getActiveClients MDS call When anti-split-brain check selects a disconnected MDS node, the HTTP call now times out after 30s instead of 5+ minutes, and automatically retries the next available MDS via tryNext mechanism. Resolves: ZSTAC-80595 Change-Id: I1be80f1b70cad1606eb38d1f0078c8f2781e6941 --- .../org/zstack/storage/zbs/ZbsStorageController.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/plugin/zbs/src/main/java/org/zstack/storage/zbs/ZbsStorageController.java b/plugin/zbs/src/main/java/org/zstack/storage/zbs/ZbsStorageController.java index db06239acb3..276ab367ba1 100644 --- a/plugin/zbs/src/main/java/org/zstack/storage/zbs/ZbsStorageController.java +++ b/plugin/zbs/src/main/java/org/zstack/storage/zbs/ZbsStorageController.java @@ -179,7 +179,10 @@ public List getActiveClients(String installPath, String prot if (VolumeProtocol.CBD.toString().equals(protocol)) { GetVolumeClientsCmd cmd = new GetVolumeClientsCmd(); cmd.setPath(installPath); - GetVolumeClientsRsp rsp = syncHttpCall(GET_VOLUME_CLIENTS_PATH, cmd, GetVolumeClientsRsp.class); + GetVolumeClientsRsp rsp = new HttpCaller<>(GET_VOLUME_CLIENTS_PATH, cmd, GetVolumeClientsRsp.class, + null, TimeUnit.SECONDS, 30, true) + .setTryNext(true) + .syncCall(); List clients = new ArrayList<>(); if (!rsp.isSuccess()) { @@ -1411,6 +1414,11 @@ public class HttpCaller { private boolean tryNext = false; + HttpCaller setTryNext(boolean tryNext) { + this.tryNext = tryNext; + return this; + } + public HttpCaller(String path, AgentCommand cmd, Class retClass, ReturnValueCompletion callback) { this(path, cmd, retClass, callback, null, 0, false); } From 80df074f8dd1140b278ce0979f2068d5c271d8e5 Mon Sep 17 00:00:00 2001 From: "ye.zou" Date: Thu, 12 Feb 2026 14:22:40 +0800 Subject: [PATCH 03/13] [vm]: add Destroying->Stopped state transition When MN restarts during a destroy operation, the hypervisor may report the VM as Stopped. Without this transition, the state machine throws an exception and the VM stays stuck in Destroying state forever. Resolves: ZSTAC-80620 Change-Id: I037edba70d145a44a88ce0d3573089182fedb162 --- header/src/main/java/org/zstack/header/vm/VmInstanceState.java | 1 + 1 file changed, 1 insertion(+) diff --git a/header/src/main/java/org/zstack/header/vm/VmInstanceState.java b/header/src/main/java/org/zstack/header/vm/VmInstanceState.java index 8a755b52fda..49303e23252 100755 --- a/header/src/main/java/org/zstack/header/vm/VmInstanceState.java +++ b/header/src/main/java/org/zstack/header/vm/VmInstanceState.java @@ -168,6 +168,7 @@ public enum VmInstanceState { new Transaction(VmInstanceStateEvent.destroyed, VmInstanceState.Destroyed), new Transaction(VmInstanceStateEvent.destroying, VmInstanceState.Destroying), new Transaction(VmInstanceStateEvent.running, VmInstanceState.Running), + new Transaction(VmInstanceStateEvent.stopped, VmInstanceState.Stopped), new Transaction(VmInstanceStateEvent.expunging, VmInstanceState.Expunging) ); Destroyed.transactions( From a84a36e2515e6b6bdc69f80420e62364e0832a90 Mon Sep 17 00:00:00 2001 From: "ye.zou" Date: Thu, 12 Feb 2026 16:12:49 +0800 Subject: [PATCH 04/13] [ceph]: apply over-provisioning ratio when releasing snapshot capacity Resolves: ZSTAC-79709 Change-Id: I45a2133bbb8c51c25ae3549d59e588976192a08d --- .../org/zstack/storage/ceph/primary/CephPrimaryStorageBase.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/ceph/src/main/java/org/zstack/storage/ceph/primary/CephPrimaryStorageBase.java b/plugin/ceph/src/main/java/org/zstack/storage/ceph/primary/CephPrimaryStorageBase.java index d80b40a1d6a..8b387306683 100755 --- a/plugin/ceph/src/main/java/org/zstack/storage/ceph/primary/CephPrimaryStorageBase.java +++ b/plugin/ceph/src/main/java/org/zstack/storage/ceph/primary/CephPrimaryStorageBase.java @@ -5446,7 +5446,7 @@ private void deleteSnapshotOnPrimaryStorage(final DeleteSnapshotOnPrimaryStorage httpCall(DELETE_SNAPSHOT_PATH, cmd, DeleteSnapshotRsp.class, new ReturnValueCompletion(msg) { @Override public void success(DeleteSnapshotRsp returnValue) { - osdHelper.releaseAvailableCapacity(msg.getSnapshot().getPrimaryStorageInstallPath(), msg.getSnapshot().getSize()); + osdHelper.releaseAvailableCapWithRatio(msg.getSnapshot().getPrimaryStorageInstallPath(), msg.getSnapshot().getSize()); bus.reply(msg, reply); completion.done(); } From f19223a6e72678f20610ae04226fc20c0cf1bb5b Mon Sep 17 00:00:00 2001 From: "ye.zou" Date: Fri, 13 Feb 2026 12:40:04 +0800 Subject: [PATCH 05/13] [loadBalancer]: block SLB deletion during grayscale upgrade Resolves: ZSTAC-78989 Change-Id: I0fe3a56ab724978944c69afadaab7ff7353e4c0f --- .../service/lb/LoadBalancerApiInterceptor.java | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/plugin/loadBalancer/src/main/java/org/zstack/network/service/lb/LoadBalancerApiInterceptor.java b/plugin/loadBalancer/src/main/java/org/zstack/network/service/lb/LoadBalancerApiInterceptor.java index 97b88c919c2..0d9946d5320 100755 --- a/plugin/loadBalancer/src/main/java/org/zstack/network/service/lb/LoadBalancerApiInterceptor.java +++ b/plugin/loadBalancer/src/main/java/org/zstack/network/service/lb/LoadBalancerApiInterceptor.java @@ -39,6 +39,7 @@ import org.zstack.network.service.vip.VipVO_; import org.zstack.tag.PatternedSystemTag; import org.zstack.tag.TagManager; +import org.zstack.core.upgrade.UpgradeGlobalConfig; import org.zstack.utils.*; import org.zstack.utils.function.ForEachFunction; import org.zstack.utils.logging.CLogger; @@ -152,10 +153,22 @@ public APIMessage intercept(APIMessage msg) throws ApiMessageInterceptionExcepti validate((APIGetCandidateVmNicsForLoadBalancerServerGroupMsg)msg); } else if (msg instanceof APIChangeLoadBalancerBackendServerMsg) { validate((APIChangeLoadBalancerBackendServerMsg)msg); + } else if (msg instanceof APIDeleteLoadBalancerMsg) { + validate((APIDeleteLoadBalancerMsg) msg); } return msg; } + private void validate(APIDeleteLoadBalancerMsg msg) { + if (UpgradeGlobalConfig.GRAYSCALE_UPGRADE.value(Boolean.class)) { + LoadBalancerVO lb = dbf.findByUuid(msg.getUuid(), LoadBalancerVO.class); + if (lb != null && lb.getType() == LoadBalancerType.SLB) { + throw new ApiMessageInterceptionException(argerr( + "cannot delete the standalone load balancer[uuid:%s] during grayscale upgrade", msg.getUuid())); + } + } + } + private void validate(APIDeleteAccessControlListMsg msg) { /*List refs = Q.New(LoadBalancerListenerACLRefVO.class).select(LoadBalancerListenerACLRefVO_.listenerUuid) .eq(LoadBalancerListenerACLRefVO_.aclUuid, msg.getUuid()).isNull(LoadBalancerListenerACLRefVO_.serverGroupUuid).listValues(); From 24d4f3b4870ea72fce77bcf64980d0b70b868502 Mon Sep 17 00:00:00 2001 From: "ye.zou" Date: Fri, 13 Feb 2026 13:32:45 +0800 Subject: [PATCH 06/13] [i18n]: improve snapshot error message for unattached volume Resolves: ZSTAC-82153 Change-Id: Ib51c2e21553277416d1a9444be55aca2aa4b2fc4 --- conf/i18n/globalErrorCodeMapping/global-error-en_US.json | 2 +- conf/i18n/globalErrorCodeMapping/global-error-zh_CN.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/conf/i18n/globalErrorCodeMapping/global-error-en_US.json b/conf/i18n/globalErrorCodeMapping/global-error-en_US.json index 32eb4c8f056..715e823d95e 100644 --- a/conf/i18n/globalErrorCodeMapping/global-error-en_US.json +++ b/conf/i18n/globalErrorCodeMapping/global-error-en_US.json @@ -3374,7 +3374,7 @@ "ORG_ZSTACK_NETWORK_HUAWEI_IMASTER_10019": "delete token of SDN controller [IP:%s] failed because %s", "ORG_ZSTACK_STORAGE_PRIMARY_BLOCK_10004": "Cannot execute volume mapping to host flow due to invalid volume ID.%s", "ORG_ZSTACK_NETWORK_SERVICE_PORTFORWARDING_10007": "port forwarding rule [uuid:%s] has not been attached to any virtual machine network interface, cannot detach", - "ORG_ZSTACK_MEVOCO_10088": "cannot take a snapshot for volumes[%s] when volume[uuid: %s] is not attached", + "ORG_ZSTACK_MEVOCO_10088": "cannot create snapshot for volume[uuid:%s] because it is not attached to any VM instance. Please attach the volume to a VM first. Affected volumes: %s", "ORG_ZSTACK_STORAGE_PRIMARY_BLOCK_10005": "Cannot execute map LUN to host flow due to invalid LUN type: %s", "ORG_ZSTACK_NETWORK_SERVICE_PORTFORWARDING_10008": "port forwarding rule [uuid:%s] has been associated with vm nic [uuid:%s], cannot be reassigned again", "ORG_ZSTACK_MEVOCO_10087": "A Running VM[uuid:%s] has no associated Host UUID.", diff --git a/conf/i18n/globalErrorCodeMapping/global-error-zh_CN.json b/conf/i18n/globalErrorCodeMapping/global-error-zh_CN.json index 84609838ddc..01960e8eb45 100644 --- a/conf/i18n/globalErrorCodeMapping/global-error-zh_CN.json +++ b/conf/i18n/globalErrorCodeMapping/global-error-zh_CN.json @@ -3374,7 +3374,7 @@ "ORG_ZSTACK_NETWORK_HUAWEI_IMASTER_10019": "删除 SDN 控制器 [IP:%s] 的令牌失败,因为 %s", "ORG_ZSTACK_STORAGE_PRIMARY_BLOCK_10004": "无法执行映射LUN到主机流程,无效的LUN ID", "ORG_ZSTACK_NETWORK_SERVICE_PORTFORWARDING_10007": "端口转发规则 rule[uuid:%s] 没有绑定到任何 VM 的网卡上,无法解除绑定", - "ORG_ZSTACK_MEVOCO_10088": "无法为挂载状态以外的卷[%s]创建快照", + "ORG_ZSTACK_MEVOCO_10088": "无法为云盘[uuid:%s]创建快照,因为该云盘未挂载到任何云主机。请先将云盘挂载到云主机后再创建快照。相关云盘: %s", "ORG_ZSTACK_STORAGE_PRIMARY_BLOCK_10005": "无法执行映射LUN到主机流程,无效的LUN类型", "ORG_ZSTACK_NETWORK_SERVICE_PORTFORWARDING_10008": "端口转发规则[uuid:%s]已绑定到VM网卡[uuid:%s],无法再次绑定", "ORG_ZSTACK_MEVOCO_10087": "如何一个运行中的VM[uuid:%s]没有宿主机uuid?", From f563992d30c2ab9484acc944e6148a5fc1f39f18 Mon Sep 17 00:00:00 2001 From: "ye.zou" Date: Fri, 13 Feb 2026 15:09:15 +0800 Subject: [PATCH 07/13] [compute]: add null check for VmNicVO in afterDelIpAddress and afterAddIpAddress to prevent NPE during rollback Resolves: ZSTAC-81741 Change-Id: I53bcf20a10306afc7b6172da294d347b74e6c41f --- .../main/java/org/zstack/compute/vm/VmNicManagerImpl.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/compute/src/main/java/org/zstack/compute/vm/VmNicManagerImpl.java b/compute/src/main/java/org/zstack/compute/vm/VmNicManagerImpl.java index 25c0b005d71..31b3e35d32a 100644 --- a/compute/src/main/java/org/zstack/compute/vm/VmNicManagerImpl.java +++ b/compute/src/main/java/org/zstack/compute/vm/VmNicManagerImpl.java @@ -58,6 +58,10 @@ public void afterAddIpAddress(String vmNicUUid, String usedIpUuid) { SQL.New(UsedIpVO.class).eq(UsedIpVO_.uuid, usedIpUuid).set(UsedIpVO_.vmNicUuid, vmNicUUid).update(); VmNicVO nic = Q.New(VmNicVO.class).eq(VmNicVO_.uuid, vmNicUUid).find(); + if (nic == null) { + logger.debug(String.format("VmNic[uuid:%s] not found, skip afterAddIpAddress", vmNicUUid)); + return; + } UsedIpVO temp = null; /* if there is ipv4 addresses, we put the first attached ipv4 address to VmNic.ip @@ -88,6 +92,10 @@ public void afterAddIpAddress(String vmNicUUid, String usedIpUuid) { @Override public void afterDelIpAddress(String vmNicUUid, String usedIpUuid) { VmNicVO nic = Q.New(VmNicVO.class).eq(VmNicVO_.uuid, vmNicUUid).find(); + if (nic == null) { + logger.debug(String.format("VmNic[uuid:%s] not found, skip afterDelIpAddress", vmNicUUid)); + return; + } if (nic.getUsedIpUuid() != null && !nic.getUsedIpUuid().equals(usedIpUuid)) { return; } From 65453500d7614d0ebdb86bf5c601dcab08f360a0 Mon Sep 17 00:00:00 2001 From: "ye.zou" Date: Fri, 13 Feb 2026 15:21:44 +0800 Subject: [PATCH 08/13] [network]: filter reserved IPs from GetFreeIp API results Resolves: ZSTAC-81182 Change-Id: Id1bb642154dc66ae9995dcc4d9fc00cdce9bcaf8 --- .../main/java/org/zstack/network/l3/L3BasicNetwork.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/network/src/main/java/org/zstack/network/l3/L3BasicNetwork.java b/network/src/main/java/org/zstack/network/l3/L3BasicNetwork.java index 5536a5fc487..b1b0b92d497 100755 --- a/network/src/main/java/org/zstack/network/l3/L3BasicNetwork.java +++ b/network/src/main/java/org/zstack/network/l3/L3BasicNetwork.java @@ -1075,6 +1075,13 @@ private void handle(APIGetFreeIpMsg msg) { } limit -= freeIpInventorys.size(); } + + Set reservedIpRanges = self.getReservedIpRanges(); + if (reservedIpRanges != null && !reservedIpRanges.isEmpty()) { + freeIpInventorys.removeIf(freeIp -> reservedIpRanges.stream().anyMatch( + r -> NetworkUtils.isInRange(freeIp.getIp(), r.getStartIp(), r.getEndIp()))); + } + reply.setInventories(freeIpInventorys); bus.reply(msg, reply); From 26b8b1a82959fd616637cf63cf6a46b725872173 Mon Sep 17 00:00:00 2001 From: "ye.zou" Date: Thu, 12 Feb 2026 13:17:20 +0800 Subject: [PATCH 09/13] [mn]: synchronize hash ring operations to prevent dual-MN task stalling In dual management node scenarios, concurrent modifications to the consistent hash ring from heartbeat reconciliation and canonical event callbacks can cause NodeHash/Nodes inconsistency, leading to message routing failures and task timeouts. Fix: (1) synchronized all ResourceDestinationMakerImpl methods to ensure atomic nodeHash+nodes updates, (2) added lifecycleLock in ManagementNodeManagerImpl to serialize heartbeat reconciliation with event callbacks, (3) added two-round delayed confirmation before removing nodes from hash ring to avoid race with NodeJoin events. Resolves: ZSTAC-77711 Change-Id: I3d33d53595dd302784dff17417a5b25f2d0f3426 --- .../ResourceDestinationMakerImpl.java | 28 ++--- .../ManagementNodeManagerImpl.java | 101 ++++++++++++------ 2 files changed, 82 insertions(+), 47 deletions(-) diff --git a/core/src/main/java/org/zstack/core/cloudbus/ResourceDestinationMakerImpl.java b/core/src/main/java/org/zstack/core/cloudbus/ResourceDestinationMakerImpl.java index 08a776f1db2..9ead578395d 100755 --- a/core/src/main/java/org/zstack/core/cloudbus/ResourceDestinationMakerImpl.java +++ b/core/src/main/java/org/zstack/core/cloudbus/ResourceDestinationMakerImpl.java @@ -27,27 +27,27 @@ public class ResourceDestinationMakerImpl implements ManagementNodeChangeListene private DatabaseFacade dbf; @Override - public void nodeJoin(ManagementNodeInventory inv) { + public synchronized void nodeJoin(ManagementNodeInventory inv) { nodeHash.add(inv.getUuid()); nodes.put(inv.getUuid(), new NodeInfo(inv)); } @Override - public void nodeLeft(ManagementNodeInventory inv) { + public synchronized void nodeLeft(ManagementNodeInventory inv) { String nodeId = inv.getUuid(); nodeHash.remove(nodeId); nodes.remove(nodeId); } @Override - public void iAmDead(ManagementNodeInventory inv) { + public synchronized void iAmDead(ManagementNodeInventory inv) { String nodeId = inv.getUuid(); nodeHash.remove(nodeId); nodes.remove(nodeId); } @Override - public void iJoin(ManagementNodeInventory inv) { + public synchronized void iJoin(ManagementNodeInventory inv) { List lst = Q.New(ManagementNodeVO.class).list(); lst.forEach((ManagementNodeVO node) -> { nodeHash.add(node.getUuid()); @@ -56,7 +56,7 @@ public void iJoin(ManagementNodeInventory inv) { } @Override - public String makeDestination(String resourceUuid) { + public synchronized String makeDestination(String resourceUuid) { String nodeUuid = nodeHash.get(resourceUuid); if (nodeUuid == null) { throw new CloudRuntimeException("Cannot find any available management node to send message"); @@ -66,18 +66,18 @@ public String makeDestination(String resourceUuid) { } @Override - public boolean isManagedByUs(String resourceUuid) { + public synchronized boolean isManagedByUs(String resourceUuid) { String nodeUuid = makeDestination(resourceUuid); return nodeUuid.equals(Platform.getManagementServerId()); } @Override - public Collection getManagementNodesInHashRing() { - return nodeHash.getNodes(); + public synchronized Collection getManagementNodesInHashRing() { + return new ArrayList<>(nodeHash.getNodes()); } @Override - public NodeInfo getNodeInfo(String nodeUuid) { + public synchronized NodeInfo getNodeInfo(String nodeUuid) { NodeInfo info = nodes.get(nodeUuid); if (info == null) { ManagementNodeVO vo = dbf.findByUuid(nodeUuid, ManagementNodeVO.class); @@ -93,17 +93,17 @@ public NodeInfo getNodeInfo(String nodeUuid) { } @Override - public Collection getAllNodeInfo() { - return nodes.values(); + public synchronized Collection getAllNodeInfo() { + return new ArrayList<>(nodes.values()); } @Override - public int getManagementNodeCount() { - return nodes.values().size(); + public synchronized int getManagementNodeCount() { + return nodes.size(); } - public boolean isNodeInCircle(String nodeId) { + public synchronized boolean isNodeInCircle(String nodeId) { return nodeHash.hasNode(nodeId); } } diff --git a/portal/src/main/java/org/zstack/portal/managementnode/ManagementNodeManagerImpl.java b/portal/src/main/java/org/zstack/portal/managementnode/ManagementNodeManagerImpl.java index a945ab77274..4ece718ff52 100755 --- a/portal/src/main/java/org/zstack/portal/managementnode/ManagementNodeManagerImpl.java +++ b/portal/src/main/java/org/zstack/portal/managementnode/ManagementNodeManagerImpl.java @@ -74,6 +74,7 @@ import java.sql.SQLException; import java.sql.Timestamp; import java.util.ArrayList; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; @@ -107,6 +108,15 @@ public class ManagementNodeManagerImpl extends AbstractService implements Manage // A dictionary (nodeId -> ManagementNodeInventory) of joined management Node final private Map joinedManagementNodes = new ConcurrentHashMap<>(); + // Lock to serialize lifecycle events from heartbeat reconciliation and canonical event callbacks, + // preventing race conditions where a nodeJoin event is immediately followed by a stale nodeLeft + // from the heartbeat thread, or vice versa. See ZSTAC-77711. + private final Object lifecycleLock = new Object(); + + // Track nodes found in hash ring but missing from DB. Only call nodeLeft after a node + // is missing for two consecutive heartbeat cycles, to avoid removing nodes that just joined. + private final Set suspectedMissingFromDb = new HashSet<>(); + private static int NODE_STARTING = 0; private static int NODE_RUNNING = 1; private static int NODE_FAILED = -1; @@ -368,12 +378,16 @@ protected void run(Map tokens, Object data) { ManagementNodeLifeCycleData d = (ManagementNodeLifeCycleData) data; - if (LifeCycle.NodeJoin.toString().equals(d.getLifeCycle())) { - nodeLifeCycle.nodeJoin(d.getInventory()); - } else if (LifeCycle.NodeLeft.toString().equals(d.getLifeCycle())) { - nodeLifeCycle.nodeLeft(d.getInventory()); - } else { - throw new CloudRuntimeException(String.format("unknown lifecycle[%s]", d.getLifeCycle())); + synchronized (lifecycleLock) { + if (LifeCycle.NodeJoin.toString().equals(d.getLifeCycle())) { + // Clear from suspected set since the node is confirmed alive + suspectedMissingFromDb.remove(d.getInventory().getUuid()); + nodeLifeCycle.nodeJoin(d.getInventory()); + } else if (LifeCycle.NodeLeft.toString().equals(d.getLifeCycle())) { + nodeLifeCycle.nodeLeft(d.getInventory()); + } else { + throw new CloudRuntimeException(String.format("unknown lifecycle[%s]", d.getLifeCycle())); + } } } }; @@ -860,34 +874,55 @@ private void checkAllNodesHealth() { Set nodeUuidsInDb = nodesInDb.stream().map(ManagementNodeVO::getUuid).collect(Collectors.toSet()); - // When a node is dying, we may not receive the the dead notification because the message bus may be also dead - // at that moment. By checking if the node UUID is still in our hash ring, we know what nodes should be kicked out - destinationMaker.getManagementNodesInHashRing().forEach(nodeUuid -> { - if (!nodeUuidsInDb.contains(nodeUuid)) { - logger.warn(String.format("found that a management node[uuid:%s] had no heartbeat in database but still in our hash ring," + - "notify that it's dead", nodeUuid)); - ManagementNodeInventory inv = new ManagementNodeInventory(); - inv.setUuid(nodeUuid); - inv.setHostName(destinationMaker.getNodeInfo(nodeUuid).getNodeIP()); - - nodeLifeCycle.nodeLeft(inv); - } - }); - - // check if any node missing in our hash ring - nodesInDb.forEach(n -> { - if (n.getUuid().equals(node().getUuid()) || suspects.contains(n)) { - return; - } - - new Runnable() { - @Override - @AsyncThread - public void run() { - nodeLifeCycle.nodeJoin(ManagementNodeInventory.valueOf(n)); + // Reconcile hash ring with DB under lifecycleLock to prevent race with + // canonical event callbacks (nodeJoin/nodeLeft). See ZSTAC-77711. + synchronized (lifecycleLock) { + // When a node is dying, we may not receive the dead notification because the message bus may be also dead + // at that moment. By checking if the node UUID is still in our hash ring, we know what nodes should be kicked out. + // Use two-round confirmation: first round marks as suspected, second round actually removes. + Set currentSuspected = new HashSet<>(); + destinationMaker.getManagementNodesInHashRing().forEach(nodeUuid -> { + if (!nodeUuidsInDb.contains(nodeUuid)) { + if (suspectedMissingFromDb.contains(nodeUuid)) { + // Second consecutive detection — confirmed missing, remove from hash ring + logger.warn(String.format("management node[uuid:%s] confirmed missing from database for two consecutive" + + " heartbeat cycles, removing from hash ring", nodeUuid)); + ManagementNodeInventory inv = new ManagementNodeInventory(); + inv.setUuid(nodeUuid); + try { + inv.setHostName(destinationMaker.getNodeInfo(nodeUuid).getNodeIP()); + } catch (Exception e) { + logger.warn(String.format("cannot get node info for node[uuid:%s], use empty hostname", nodeUuid)); + } + + nodeLifeCycle.nodeLeft(inv); + } else { + // First detection — mark as suspected, defer removal to next cycle + logger.warn(String.format("management node[uuid:%s] not found in database but still in hash ring," + + " marking as suspected (will remove on next heartbeat if still missing)", nodeUuid)); + currentSuspected.add(nodeUuid); + } } - }.run(); - }); + }); + // Update suspected set: only keep nodes that are newly suspected this round + suspectedMissingFromDb.clear(); + suspectedMissingFromDb.addAll(currentSuspected); + + // check if any node missing in our hash ring + nodesInDb.forEach(n -> { + if (n.getUuid().equals(node().getUuid()) || suspects.contains(n)) { + return; + } + + new Runnable() { + @Override + @AsyncThread + public void run() { + nodeLifeCycle.nodeJoin(ManagementNodeInventory.valueOf(n)); + } + }.run(); + }); + } } @Override From aaeaf39c323da0013c01cab8ff58d0fbb3163c9e Mon Sep 17 00:00:00 2001 From: "ye.zou" Date: Fri, 13 Feb 2026 19:25:07 +0800 Subject: [PATCH 10/13] [storage]: desensitize mdsUrls in ExternalPrimaryStorageInventory The mdsUrls field in ExternalPrimaryStorage config contains user:password@host format credentials. Add desensitization to mask credentials as ***@host in API/CLI output. Resolves: ZSTAC-80664 Change-Id: I94bdede5a1b52eb039de70efb5458693484405f7 --- .../ExternalPrimaryStorageInventory.java | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/header/src/main/java/org/zstack/header/storage/addon/primary/ExternalPrimaryStorageInventory.java b/header/src/main/java/org/zstack/header/storage/addon/primary/ExternalPrimaryStorageInventory.java index 7808c227623..a15ed211307 100644 --- a/header/src/main/java/org/zstack/header/storage/addon/primary/ExternalPrimaryStorageInventory.java +++ b/header/src/main/java/org/zstack/header/storage/addon/primary/ExternalPrimaryStorageInventory.java @@ -4,8 +4,10 @@ import org.zstack.header.storage.primary.PrimaryStorageInventory; import org.zstack.utils.gson.JSONObjectUtil; +import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; +import java.util.Map; import java.util.stream.Collectors; @Inventory(mappingVOClass = ExternalPrimaryStorageVO.class) @@ -59,6 +61,7 @@ public ExternalPrimaryStorageInventory(ExternalPrimaryStorageVO lvo) { super(lvo); identity = lvo.getIdentity(); config = JSONObjectUtil.toObject(lvo.getConfig(), LinkedHashMap.class); + desensitizeConfig(config); addonInfo = JSONObjectUtil.toObject(lvo.getAddonInfo(), LinkedHashMap.class); outputProtocols = lvo.getOutputProtocols().stream().map(PrimaryStorageOutputProtocolRefVO::getOutputProtocol).collect(Collectors.toList()); defaultProtocol = lvo.getDefaultProtocol(); @@ -68,6 +71,35 @@ public static ExternalPrimaryStorageInventory valueOf(ExternalPrimaryStorageVO l return new ExternalPrimaryStorageInventory(lvo); } + private static void desensitizeConfig(Map config) { + if (config == null) return; + desensitizeUrlList(config, "mdsUrls"); + desensitizeUrlList(config, "mdsInfos"); + } + + private static void desensitizeUrlList(Map config, String key) { + Object urls = config.get(key); + if (urls instanceof List) { + List desensitized = new ArrayList<>(); + for (Object url : (List) urls) { + desensitized.add(desensitizeUrl(String.valueOf(url))); + } + config.put(key, desensitized); + } + } + + private static String desensitizeUrl(String url) { + int atIndex = url.lastIndexOf('@'); + if (atIndex > 0) { + int schemeIndex = url.indexOf("://"); + if (schemeIndex >= 0 && schemeIndex < atIndex) { + return url.substring(0, schemeIndex + 3) + "***" + url.substring(atIndex); + } + return "***" + url.substring(atIndex); + } + return url; + } + public String getIdentity() { return identity; } From f41558d0f404210562a7e13e05a64b928932cb4f Mon Sep 17 00:00:00 2001 From: "ye.zou" Date: Mon, 16 Feb 2026 17:36:51 +0800 Subject: [PATCH 11/13] [volumebackup]: add backup cancel timeout error code Add ORG_ZSTACK_STORAGE_BACKUP_CANCEL_TIMEOUT constant to CloudOperationsErrorCode for use in premium volumebackup module. Resolves: ZSTAC-82195 Change-Id: Ibc405876e1171b637cf76b91a6822574fb6e7811 --- .../zstack/utils/clouderrorcode/CloudOperationsErrorCode.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/utils/src/main/java/org/zstack/utils/clouderrorcode/CloudOperationsErrorCode.java b/utils/src/main/java/org/zstack/utils/clouderrorcode/CloudOperationsErrorCode.java index a0f09d4f1e9..a550fb7d673 100644 --- a/utils/src/main/java/org/zstack/utils/clouderrorcode/CloudOperationsErrorCode.java +++ b/utils/src/main/java/org/zstack/utils/clouderrorcode/CloudOperationsErrorCode.java @@ -6274,6 +6274,8 @@ public class CloudOperationsErrorCode { public static final String ORG_ZSTACK_STORAGE_BACKUP_10133 = "ORG_ZSTACK_STORAGE_BACKUP_10133"; + public static final String ORG_ZSTACK_STORAGE_BACKUP_CANCEL_TIMEOUT = "ORG_ZSTACK_STORAGE_BACKUP_CANCEL_TIMEOUT"; + public static final String ORG_ZSTACK_COMPUTE_10000 = "ORG_ZSTACK_COMPUTE_10000"; public static final String ORG_ZSTACK_COMPUTE_10001 = "ORG_ZSTACK_COMPUTE_10001"; From 7f53f5a5ae1064721fba6ad1c4ab914b5862d3e7 Mon Sep 17 00:00:00 2001 From: "yaohua.wu" Date: Mon, 16 Feb 2026 21:25:44 +0800 Subject: [PATCH 12/13] [thread]: guard Context.current() with telemetry check SyncTaskFuture constructor calls Context.current() unconditionally, triggering ServiceLoader for ContextStorageProvider even when telemetry is disabled. If sentry-opentelemetry-bootstrap jar is on classpath, ServiceLoader fails with "not a subtype" due to ClassLoader isolation in Tomcat, throwing ServiceConfigurationError (extends Error) that escapes all catch(Exception) blocks. 1. Why is this change necessary? MN startup crashes with ORG_ZSTACK_CORE_WORKFLOW_10001 because Context.current() triggers ServiceLoader unconditionally in SyncTaskFuture constructor, even when telemetry is disabled. 2. How does it address the problem? Only call Context.current() when isTelemetryEnabled() returns true, matching the existing guard pattern used in other DispatchQueueImpl code paths (lines 351, 1069). 3. Are there any side effects? None. When telemetry is disabled, parentContext was never used. # Summary of changes (by module): - core/thread: conditionalize Context.current() in SyncTaskFuture Related: ZSTAC-82275 Change-Id: I5c0e1f15769c746c630028a29df8cf1815620608 --- .../src/main/java/org/zstack/core/thread/DispatchQueueImpl.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/org/zstack/core/thread/DispatchQueueImpl.java b/core/src/main/java/org/zstack/core/thread/DispatchQueueImpl.java index e298cdd787f..961b192ac7c 100755 --- a/core/src/main/java/org/zstack/core/thread/DispatchQueueImpl.java +++ b/core/src/main/java/org/zstack/core/thread/DispatchQueueImpl.java @@ -302,7 +302,7 @@ private class SyncTaskFuture extends AbstractFuture { public SyncTaskFuture(SyncTask task) { super(task); - this.parentContext = Context.current(); + this.parentContext = isTelemetryEnabled() ? Context.current() : null; } private SyncTask getTask() { From 8d17abe32a8ba61e6e0061d62806d371cf2b7041 Mon Sep 17 00:00:00 2001 From: AlanJager Date: Mon, 2 Feb 2026 12:24:37 +0800 Subject: [PATCH 13/13] [dependencies]: Upgrade java version to 17 ZQLImpact Change-Id: I656f6963726b77727363656d756465766b6a7a6a --- .mvn/jvm.config | 6 + abstraction/pom.xml | 18 +- build/debug.sh | 11 +- build/fix-groovy-compiler.sh | 283 ++++ build/pom.xml | 9 +- build/verify-java17.sh | 98 ++ build/zstack | 8 +- build/zstack-debug | 8 +- compute/pom.xml | 32 +- .../allocator/HostAllocatorChainBuilder.java | 6 +- .../org/zstack/compute/vm/VmInstanceBase.java | 2 +- conf/jvm-options-java17.conf | 18 + configuration/pom.xml | 212 ++- .../ConfigurationManagerImpl.java | 2 +- console/pom.xml | 31 +- core/pom.xml | 75 +- .../zstack/core/cloudbus/CloudBusImpl2.java | 2 +- .../zstack/core/db/DatabaseFacadeImpl.java | 2 +- .../core/gc/GarbageCollectorManagerImpl.java | 6 +- .../zstack/core/rest/RESTApiFacadeImpl.java | 6 +- .../core/workflow/FlowChainBuilder.java | 2 +- docs/ARCHITECTURE.md | 1199 +++++++++++++++ docs/BUILD-ACCELERATION.md | 141 ++ externalservice/pom.xml | 32 +- header/pom.xml | 86 +- .../org/zstack/header/zql/ASTNode.groovy | 441 +++--- .../org/zstack/header/zql/ASTVisitor.groovy | 11 +- .../header/aspect/OwnedByAccountAspect.aj | 88 +- .../encrypt/EncryptionIntegrityInventory.java | 1 - .../header/core/workflow/CheckFlow.java | 2 +- identity/pom.xml | 186 ++- .../zstack/identity/AccountManagerImpl.java | 2 +- image/pom.xml | 224 ++- .../org/zstack/image/ImageManagerImpl.java | 1 - longjob/pom.xml | 214 ++- .../zstack/longjob/LongJobFactoryImpl.java | 5 +- .../zstack/longjob/LongJobManagerImpl.java | 5 +- network/pom.xml | 212 ++- plugin/acl/pom.xml | 51 +- plugin/applianceVm/pom.xml | 50 +- plugin/cbd/pom.xml | 50 +- plugin/ceph/pom.xml | 51 +- plugin/directory/pom.xml | 51 +- plugin/eip/pom.xml | 50 +- plugin/expon/pom.xml | 50 +- plugin/externalStorage/pom.xml | 49 +- plugin/flatNetworkProvider/pom.xml | 50 +- plugin/hostNetworkInterface/pom.xml | 50 +- plugin/iscsi/pom.xml | 50 +- plugin/kvm/pom.xml | 213 +-- plugin/ldap/pom.xml | 50 +- plugin/loadBalancer/pom.xml | 50 +- plugin/localstorage/pom.xml | 50 +- plugin/loginPlugin/pom.xml | 50 +- plugin/mediator/pom.xml | 50 +- plugin/nfsPrimaryStorage/pom.xml | 192 +-- plugin/pom.xml | 235 +-- plugin/portForwarding/pom.xml | 50 +- plugin/sdnController/pom.xml | 50 +- plugin/securityGroup/pom.xml | 180 +-- plugin/sftpBackupStorage/pom.xml | 172 ++- plugin/sharedMountPointPrimaryStorage/pom.xml | 50 +- plugin/sshKeyPair/pom.xml | 53 +- plugin/sugonSdnController/pom.xml | 50 +- .../controller/api/ApiConnectorImpl.java | 2 +- .../controller/api/ApiConnectorMock.java | 2 +- plugin/vhost/pom.xml | 50 +- plugin/vip/pom.xml | 50 +- plugin/virtualRouterProvider/pom.xml | 262 ++-- plugin/vxlan/pom.xml | 50 +- plugin/xinfini/pom.xml | 50 +- plugin/zbs/pom.xml | 50 +- pom.xml | 164 ++- portal/pom.xml | 32 +- .../managementnode/DebugSignalHandler.java | 2 + resourceconfig/pom.xml | 32 +- rest/pom.xml | 31 +- .../main/java/org/zstack/rest/RestServer.java | 4 +- runMavenProfile | 2 +- sdk/pom.xml | 3 +- search/pom.xml | 102 +- .../query/APIBatchQueryMsgDoc_zh_cn.groovy | 3 +- .../query/APIBatchQueryReplyDoc_zh_cn.groovy | 1 + .../query/APIZQLQueryMsgDoc_zh_cn.groovy | 3 +- .../query/APIZQLQueryReplyDoc_zh_cn.groovy | 1 + .../org/zstack/query/BatchQuery.groovy | 967 ++++++------ .../main/java/org/zstack/search/ESTuple.java | 2 +- .../zql/ast/parser/visitors/ValueVisitor.java | 2 +- simulator/pom.xml | 56 +- simulator/simulatorHeader/pom.xml | 155 +- simulator/simulatorImpl/pom.xml | 249 ++-- storage/pom.xml | 234 ++- .../storage/primary/AbstractUsageReport.java | 8 +- tag/pom.xml | 32 +- .../org/zstack/tag/PatternedSystemTag.java | 4 +- test/pom.xml | 1292 +++++++++-------- .../gc/EventBasedGarbageCollectorCase.groovy | 8 +- .../AttachL2NetworkWithTwoClustersCase.groovy | 6 +- .../DeleteL2NetworkBridgeCase.groovy | 16 +- .../sdnController/SdnControllerCase.groovy | 19 +- .../vxlanNetwork/AddVxlanVtepIpCase.groovy | 2 +- .../vxlanNetwork/VxlanLazyAttachCase.groovy | 2 +- .../VxlanVtepIpChangedCase.groovy | 4 +- .../flat/dhcp/CheckFlatDhcpWorkCase.groovy | 34 +- .../test/java/org/zstack/test/ApiSender.java | 2 +- .../org/zstack/test/deployer/Deployer.java | 2 +- testlib/pom.xml | 103 +- .../org/zstack/testlib/StabilityTest.groovy | 2 +- .../main/java/org/zstack/testlib/Test.groovy | 4 +- utils/pom.xml | 23 +- .../java/org/zstack/utils/GroovyUtils.java | 2 +- .../java/org/zstack/utils/ObjectUtils.java | 2 +- .../main/java/org/zstack/utils/form/Form.java | 2 +- .../org/zstack/utils/gson/JSONObjectUtil.java | 2 +- .../org/zstack/utils/logging/CLoggerImpl.java | 2 +- .../zstack/utils/test/TestNetworkUtils.java | 1 - 116 files changed, 6258 insertions(+), 3611 deletions(-) create mode 100644 .mvn/jvm.config create mode 100755 build/fix-groovy-compiler.sh create mode 100755 build/verify-java17.sh create mode 100644 conf/jvm-options-java17.conf create mode 100644 docs/ARCHITECTURE.md create mode 100644 docs/BUILD-ACCELERATION.md rename header/src/main/{java => groovy}/org/zstack/header/zql/ASTNode.groovy (95%) mode change 100755 => 100644 rename header/src/main/{java => groovy}/org/zstack/header/zql/ASTVisitor.groovy (95%) mode change 100755 => 100644 rename search/src/main/{java => groovy}/org/zstack/query/APIBatchQueryMsgDoc_zh_cn.groovy (99%) rename search/src/main/{java => groovy}/org/zstack/query/APIBatchQueryReplyDoc_zh_cn.groovy (99%) rename search/src/main/{java => groovy}/org/zstack/query/APIZQLQueryMsgDoc_zh_cn.groovy (99%) rename search/src/main/{java => groovy}/org/zstack/query/APIZQLQueryReplyDoc_zh_cn.groovy (99%) mode change 100755 => 100644 rename search/src/main/{java => groovy}/org/zstack/query/BatchQuery.groovy (97%) mode change 100755 => 100644 diff --git a/.mvn/jvm.config b/.mvn/jvm.config new file mode 100644 index 00000000000..5e5afe96f93 --- /dev/null +++ b/.mvn/jvm.config @@ -0,0 +1,6 @@ +-Xmx10240m +-XX:MaxMetaspaceSize=2560m +-XX:+UseG1GC +-XX:+UseStringDeduplication +-XX:ReservedCodeCacheSize=512m +-XX:NonProfiledCodeHeapSize=240m diff --git a/abstraction/pom.xml b/abstraction/pom.xml index f43ae6f7e96..8d7c408e2cf 100644 --- a/abstraction/pom.xml +++ b/abstraction/pom.xml @@ -15,24 +15,10 @@ maven-compiler-plugin ${project.compiler.version} - groovy-eclipse-compiler - ${project.java.version} - ${project.java.version} - lines,vars,source + ${project.java.version} true + true - - - org.codehaus.groovy - groovy-eclipse-compiler - ${groovy.eclipse.compiler} - - - org.codehaus.groovy - groovy-eclipse-batch - ${groovy.eclipse.batch} - - diff --git a/build/debug.sh b/build/debug.sh index afa2f92f8d6..9d5843d5d55 100755 --- a/build/debug.sh +++ b/build/debug.sh @@ -8,10 +8,17 @@ conf_dir=$zstack_dir/conf classpath= is_suspend="$1" +# 加载Java 17 JVM参数 +jvm_options_file="$conf_dir/jvm-options-java17.conf" +jvm_options="" +if [ -f "$jvm_options_file" ]; then + jvm_options=$(cat "$jvm_options_file" | grep -v '^#' | tr '\n' ' ') +fi + if [ x"$is_suspend" == x"true" ]; then - java_optitons="-Xdebug -Xms256m -Xmx512m -XX:+HeapDumpOnOutOfMemoryError -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y" + java_optitons="$jvm_options -Xdebug -Xms256m -Xmx512m -XX:+HeapDumpOnOutOfMemoryError -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y" else - java_optitons="-Xdebug -Xms256m -Xmx512m -XX:+HeapDumpOnOutOfMemoryError -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=n" + java_optitons="$jvm_options -Xdebug -Xms256m -Xmx512m -XX:+HeapDumpOnOutOfMemoryError -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=n" fi diff --git a/build/fix-groovy-compiler.sh b/build/fix-groovy-compiler.sh new file mode 100755 index 00000000000..b688fe185d9 --- /dev/null +++ b/build/fix-groovy-compiler.sh @@ -0,0 +1,283 @@ +#!/bin/bash + +# 批量修复Groovy编译配置脚本 +# 用于将groovy-eclipse-compiler替换为标准Java编译器或GMavenPlus + +set -e + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)" + +cd "$PROJECT_ROOT" + +echo "==========================================" +echo "批量修复Groovy编译配置" +echo "==========================================" +echo "" + +# 查找所有包含groovy-eclipse-compiler的pom.xml文件 +FILES=$(grep -r "groovy-eclipse-compiler" --include="pom.xml" . | cut -d: -f1 | sort -u) + +TOTAL=$(echo "$FILES" | wc -l | tr -d ' ') +CURRENT=0 +FIXED=0 +SKIPPED=0 + +# 标准Java编译器配置(用于没有Groovy源文件的模块) +STANDARD_JAVA_CONFIG=' + ${project.java.version} + ${project.java.version} + true + true + ' + +# GMavenPlus配置(用于有Groovy源文件的模块) +GMAVENPLUS_CONFIG=' + + org.apache.maven.plugins + maven-compiler-plugin + ${project.compiler.version} + + ${project.java.version} + ${project.java.version} + true + true + + + + + org.codehaus.gmavenplus + gmavenplus-plugin + 4.2.1 + + + + generateStubs + compile + generateTestStubs + compileTests + + + + + ${groovy.version} + ${project.java.version} + + ' + +for FILE in $FILES; do + CURRENT=$((CURRENT + 1)) + echo "[$CURRENT/$TOTAL] 处理: $FILE" + + # 检查模块目录是否有Groovy源文件 + MODULE_DIR=$(dirname "$FILE") + HAS_GROOVY=$(find "$MODULE_DIR" -name "*.groovy" -type f 2>/dev/null | head -1) + + if [ -n "$HAS_GROOVY" ]; then + echo " ⚠️ 发现Groovy源文件,需要手动配置GMavenPlus" + echo " 📝 请手动编辑此文件,参考test/pom.xml的配置" + SKIPPED=$((SKIPPED + 1)) + continue + fi + + # 读取文件内容 + if [ ! -f "$FILE" ]; then + echo " ❌ 文件不存在,跳过" + SKIPPED=$((SKIPPED + 1)) + continue + fi + + # 创建备份 + BACKUP_FILE="${FILE}.backup.$(date +%Y%m%d_%H%M%S)" + cp "$FILE" "$BACKUP_FILE" + echo " 💾 备份文件: $BACKUP_FILE" + + # 使用Python进行精确替换(因为sed处理多行和缩进比较复杂) + python3 <开始到结束,包含groovy-eclipse-compiler的整个块 +pattern = r'''\s*\s* +\s*org\.apache\.maven\.plugins\s* +\s*maven-compiler-plugin\s* +\s*.*?\s* +\s*\s* +\s*groovy-eclipse-compiler\s* +\s*\$\{project\.java\.version\}\s* +\s*\$\{project\.java\.version\}\s* +\s*lines,vars,source\s* +\s*true\s* +\s*\s* +\s*\s* +\s*\s* +\s*org\.codehaus\.groovy\s* +\s*groovy-eclipse-compiler\s* +\s*.*?\s* +\s*\s* +\s*\s* +\s*org\.codehaus\.groovy\s* +\s*groovy-eclipse-batch\s* +\s*.*?\s* +\s*\s* +\s*\s* +\s*''' + +# 更灵活的匹配模式(处理不同的缩进和换行) +pattern2 = r'''(\s*)\s* +\1org\.apache\.maven\.plugins\s* +\1maven-compiler-plugin\s* +\1([^<]+)\s* +\1\s* +\1\s*groovy-eclipse-compiler\s* +\1\s*\$\{project\.java\.version\}\s* +\1\s*\$\{project\.java\.version\}\s* +\1\s*lines,vars,source\s* +\1\s*true\s* +\1\s* +\1\s* +\1\s*\s* +\1\s*org\.codehaus\.groovy\s* +\1\s*groovy-eclipse-compiler\s* +\1\s*[^<]+\s* +\1\s*\s* +\1\s*\s* +\1\s*org\.codehaus\.groovy\s* +\1\s*groovy-eclipse-batch\s* +\1\s*[^<]+\s* +\1\s*\s* +\1\s* +\1''' + +# 尝试匹配并替换 +def replace_plugin(match): + indent = match.group(1) + version = match.group(2).strip() + replacement = f'''{indent} +{indent} org.apache.maven.plugins +{indent} maven-compiler-plugin +{indent} {version} +{indent} +{indent} ${{project.java.version}} +{indent} ${{project.java.version}} +{indent} true +{indent} true +{indent} +{indent}''' + return replacement + +# 使用更简单的方法:逐行处理 +lines = content.split('\n') +new_lines = [] +i = 0 +in_plugin = False +in_config = False +in_dependencies = False +plugin_start = -1 +indent = "" + +while i < len(lines): + line = lines[i] + + # 检测plugin开始 + if '' in line and 'maven-compiler-plugin' in '\n'.join(lines[max(0, i-3):i+3]): + # 向前查找groupId和artifactId + if i > 0 and 'maven-compiler-plugin' in lines[i-1]: + plugin_start = len(new_lines) + indent = line[:len(line) - len(line.lstrip())] + in_plugin = True + new_lines.append(line) + i += 1 + continue + + # 如果在plugin块中,检测groovy-eclipse-compiler + if in_plugin: + if 'groovy-eclipse-compiler' in line: + # 找到了,需要替换整个plugin块 + # 回退到plugin开始位置 + new_lines = new_lines[:plugin_start] + # 添加新的标准配置 + version_line = None + for j in range(plugin_start, i): + if '' in lines[j] and '' in lines[j]: + version_line = lines[j] + break + + version = '${project.compiler.version}' + if version_line: + version_match = re.search(r'([^<]+)', version_line) + if version_match: + version = version_match.group(1).strip() + + new_lines.append(f'{indent}') + new_lines.append(f'{indent} org.apache.maven.plugins') + new_lines.append(f'{indent} maven-compiler-plugin') + new_lines.append(f'{indent} {version}') + new_lines.append(f'{indent} ') + new_lines.append(f'{indent} ${{project.java.version}}') + new_lines.append(f'{indent} ${{project.java.version}}') + new_lines.append(f'{indent} true') + new_lines.append(f'{indent} true') + new_lines.append(f'{indent} ') + new_lines.append(f'{indent}') + + # 跳过到 + while i < len(lines) and '' not in lines[i]: + i += 1 + if i < len(lines): + i += 1 # 跳过 + in_plugin = False + continue + elif '' in line: + in_plugin = False + new_lines.append(line) + i += 1 + continue + + new_lines.append(line) + i += 1 + +new_content = '\n'.join(new_lines) + +# 如果内容有变化,写入文件 +if new_content != content: + with open(file_path, 'w', encoding='utf-8') as f: + f.write(new_content) + print(" ✅ 修复完成") + sys.exit(0) +else: + print(" ⚠️ 未找到需要替换的内容(可能已修复或格式不同)") + sys.exit(1) + +PYTHON_SCRIPT + + if [ $? -eq 0 ]; then + FIXED=$((FIXED + 1)) + echo " ✅ 修复成功" + else + echo " ⚠️ 修复失败或无需修复,请手动检查" + SKIPPED=$((SKIPPED + 1)) + fi + echo "" +done + +echo "==========================================" +echo "修复完成!" +echo "==========================================" +echo "总计: $TOTAL 个文件" +echo "修复: $FIXED 个文件" +echo "跳过: $SKIPPED 个文件" +echo "" +echo "备份文件已保存,如需恢复请使用:" +echo " cp .backup.* " +echo "" +echo "建议运行验证:" +echo " mvn clean compile -DskipTests" +echo " 或" +echo " bash ./build/verify-java17.sh" diff --git a/build/pom.xml b/build/pom.xml index 6801d25cbba..d1bc96d1643 100755 --- a/build/pom.xml +++ b/build/pom.xml @@ -18,7 +18,7 @@ maven-war-plugin - 2.3 + 3.3.2 %regex[WEB-INF/lib/maven(?!-artifact).*.jar], @@ -410,11 +410,6 @@ twoFactorAuthentication ${project.version} - - org.zstack - crypto - ${project.version} - org.zstack loginControl @@ -670,7 +665,7 @@ maven-war-plugin - 2.3 + 3.3.2 %regex[WEB-INF/lib/maven(?!-artifact).*.jar], diff --git a/build/verify-java17.sh b/build/verify-java17.sh new file mode 100755 index 00000000000..3608493a4ac --- /dev/null +++ b/build/verify-java17.sh @@ -0,0 +1,98 @@ +#!/bin/bash +# Java 17 兼容性验证脚本 +# 用于验证所有依赖在Java 17下的兼容性 + +set -e + +echo "==========================================" +echo " Java 17 兼容性验证" +echo "==========================================" +echo "" + +# 1. 检查Java版本 +echo "[1/6] 检查Java版本..." +JAVA_VERSION=$(java -version 2>&1 | head -1 | cut -d'"' -f2 | sed '/^1\./s///' | cut -d'.' -f1) +if [ "$JAVA_VERSION" != "17" ]; then + echo "❌ 错误: 需要Java 17,当前版本: $JAVA_VERSION" + java -version + exit 1 +fi +echo "✓ Java版本: $(java -version 2>&1 | head -1)" +echo "" + +# 2. 检查关键依赖版本 +echo "[2/6] 检查关键依赖版本..." +echo "检查Spring Framework版本..." +SPRING_VERSION=$(mvn help:evaluate -Dexpression=spring.framework.version -q -DforceStdout 2>/dev/null || echo "unknown") +echo " Spring Framework: $SPRING_VERSION" +if [[ "$SPRING_VERSION" == "5.2"* ]]; then + echo " ⚠️ 警告: Spring 5.2.x 非官方支持Java 17,建议升级到5.3.x" +fi + +echo "检查Hibernate版本..." +HIBERNATE_VERSION=$(mvn help:evaluate -Dexpression=hibernate.version -q -DforceStdout 2>/dev/null || echo "unknown") +echo " Hibernate: $HIBERNATE_VERSION" + +echo "检查AspectJ版本..." +ASPECTJ_VERSION=$(mvn help:evaluate -Dexpression=aspectj.version -q -DforceStdout 2>/dev/null || echo "unknown") +echo " AspectJ: $ASPECTJ_VERSION" + +echo "检查Groovy版本..." +GROOVY_VERSION=$(mvn help:evaluate -Dexpression=groovy.version -q -DforceStdout 2>/dev/null || echo "unknown") +echo " Groovy: $GROOVY_VERSION" +echo "" + +# 3. 编译测试(核心模块) +echo "[3/6] 编译核心模块 (core, header, utils)..." +if mvn clean compile -pl core,header,utils -DskipTests -q; then + echo "✓ 核心模块编译成功" +else + echo "❌ 错误: 核心模块编译失败" + exit 1 +fi +echo "" + +# 4. 编译测试(所有模块) +echo "[4/6] 编译所有模块..." +if mvn clean compile -DskipTests -q; then + echo "✓ 全量编译成功" +else + echo "❌ 错误: 全量编译失败" + exit 1 +fi +echo "" + +# 5. 单元测试(工具类) +echo "[5/6] 运行单元测试 (utils, abstraction)..." +if mvn test -pl utils,abstraction -Djacoco.skip=true -q 2>&1 | tee /tmp/java17-test.log; then + echo "✓ 单元测试通过" +else + TEST_FAILED=$(grep -c "FAILURE\|ERROR" /tmp/java17-test.log || echo "0") + if [ "$TEST_FAILED" -gt 0 ]; then + echo "⚠️ 警告: 部分单元测试失败,请检查日志" + else + echo "✓ 单元测试完成" + fi +fi +echo "" + +# 6. 依赖兼容性检查 +echo "[6/6] 检查依赖树(Spring/Hibernate相关)..." +echo "Spring相关依赖:" +mvn dependency:tree -Dincludes=org.springframework:* -q 2>/dev/null | grep -E "spring" | head -10 || echo " 无Spring依赖" +echo "" +echo "Hibernate相关依赖:" +mvn dependency:tree -Dincludes=org.hibernate:* -q 2>/dev/null | grep -E "hibernate" | head -10 || echo " 无Hibernate依赖" +echo "" + +echo "==========================================" +echo " 验证完成" +echo "==========================================" +echo "" +echo "建议:" +if [[ "$SPRING_VERSION" == "5.2"* ]]; then + echo " - 考虑升级Spring Framework到5.3.23以获得官方Java 17支持" +fi +echo " - 运行完整集成测试: mvn test -pl test -Dtest=SomeBasicCase" +echo " - 检查运行时兼容性: 启动应用并测试核心功能" +echo "" diff --git a/build/zstack b/build/zstack index 676a8961802..e83a429f6ea 100755 --- a/build/zstack +++ b/build/zstack @@ -20,7 +20,13 @@ buildClassPath() { } run() { - java -cp $classPath org.zstack.portal.main.Main "$@" + # 加载Java 17 JVM参数 + jvmOptionsFile="$confDir/jvm-options-java17.conf" + jvmOptions="" + if [ -f "$jvmOptionsFile" ]; then + jvmOptions=$(cat "$jvmOptionsFile" | grep -v '^#' | tr '\n' ' ') + fi + java $jvmOptions -cp $classPath org.zstack.portal.main.Main "$@" } main() { diff --git a/build/zstack-debug b/build/zstack-debug index a9d58db798b..2a2287e3132 100755 --- a/build/zstack-debug +++ b/build/zstack-debug @@ -20,7 +20,13 @@ buildClassPath() { } run() { - javaOptitons="-Xdebug -Xms256m -Xmx512m -XX:+HeapDumpOnOutOfMemoryError -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y" + # 加载Java 17 JVM参数 + jvmOptionsFile="$confDir/jvm-options-java17.conf" + jvmOptions="" + if [ -f "$jvmOptionsFile" ]; then + jvmOptions=$(cat "$jvmOptionsFile" | grep -v '^#' | tr '\n' ' ') + fi + javaOptitons="$jvmOptions -Xdebug -Xms256m -Xmx512m -XX:+HeapDumpOnOutOfMemoryError -Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=y" java $javaOptions -cp $classPath org.zstack.portal.main.Main "$@" } diff --git a/compute/pom.xml b/compute/pom.xml index d7543119ad7..efa30059f23 100755 --- a/compute/pom.xml +++ b/compute/pom.xml @@ -18,29 +18,23 @@ maven-compiler-plugin ${project.compiler.version} - groovy-eclipse-compiler - ${project.java.version} - ${project.java.version} - lines,vars,source + ${project.java.version} true + true - - - org.codehaus.groovy - groovy-eclipse-compiler - ${groovy.eclipse.compiler} - - - org.codehaus.groovy - groovy-eclipse-batch - ${groovy.eclipse.batch} - - + org.codehaus.mojo aspectj-maven-plugin ${aspectj.plugin.version} + + + org.aspectj + aspectjtools + ${aspectj.version} + + @@ -50,10 +44,12 @@ + ${project.java.version} ${project.java.version} ${project.java.version} - ${project.java.version} - true + ${project.build.sourceEncoding} + true + org.springframework diff --git a/compute/src/main/java/org/zstack/compute/allocator/HostAllocatorChainBuilder.java b/compute/src/main/java/org/zstack/compute/allocator/HostAllocatorChainBuilder.java index e839a567b60..464bce56323 100755 --- a/compute/src/main/java/org/zstack/compute/allocator/HostAllocatorChainBuilder.java +++ b/compute/src/main/java/org/zstack/compute/allocator/HostAllocatorChainBuilder.java @@ -43,7 +43,7 @@ private List buildFlows() { List flows = new ArrayList(); try { for (Class flowClass : classes) { - flows.add((AbstractHostAllocatorFlow) flowClass.newInstance()); + flows.add((AbstractHostAllocatorFlow) flowClass.getConstructor().newInstance()); } } catch (Exception e) { throw new CloudRuntimeException(e); @@ -54,9 +54,9 @@ private List buildFlows() { private List buildSortFlows() { List flows = new ArrayList<>(); try { - flows.add(RandomSortFlow.class.newInstance()); + flows.add(RandomSortFlow.class.getConstructor().newInstance()); for (Class flowClass : classes) { - flows.add((AbstractHostSortorFlow) flowClass.newInstance()); + flows.add((AbstractHostSortorFlow) flowClass.getConstructor().newInstance()); } } catch (Exception e) { throw new CloudRuntimeException(e); diff --git a/compute/src/main/java/org/zstack/compute/vm/VmInstanceBase.java b/compute/src/main/java/org/zstack/compute/vm/VmInstanceBase.java index 80ba38486fc..a8a09909050 100755 --- a/compute/src/main/java/org/zstack/compute/vm/VmInstanceBase.java +++ b/compute/src/main/java/org/zstack/compute/vm/VmInstanceBase.java @@ -956,7 +956,7 @@ public void run(final SyncTaskChain chain) { HaStartVmJudger judger; try { Class clz = Class.forName(msg.getJudgerClassName()); - judger = (HaStartVmJudger) clz.newInstance(); + judger = (HaStartVmJudger) clz.getConstructor().newInstance(); } catch (Exception e) { throw new CloudRuntimeException(e); } diff --git a/conf/jvm-options-java17.conf b/conf/jvm-options-java17.conf new file mode 100644 index 00000000000..3898ac82bee --- /dev/null +++ b/conf/jvm-options-java17.conf @@ -0,0 +1,18 @@ +# Java 17 模块系统配置 +# 开放反射访问(226处setAccessible需要) +--add-opens java.base/java.lang=ALL-UNNAMED +--add-opens java.base/java.lang.reflect=ALL-UNNAMED +--add-opens java.base/java.util=ALL-UNNAMED +--add-opens java.base/java.util.concurrent=ALL-UNNAMED +--add-opens java.base/java.io=ALL-UNNAMED +--add-opens java.base/java.net=ALL-UNNAMED + +# 导出内部API(sun.misc.Signal需要) +--add-exports java.base/sun.misc=ALL-UNNAMED +--add-exports java.base/sun.security.ssl=ALL-UNNAMED + +# Hibernate需要 +--add-opens java.base/java.time=ALL-UNNAMED + +# AspectJ需要 +--add-opens java.base/java.lang.invoke=ALL-UNNAMED diff --git a/configuration/pom.xml b/configuration/pom.xml index d8e7e387489..07ff081a0cb 100755 --- a/configuration/pom.xml +++ b/configuration/pom.xml @@ -1,109 +1,105 @@ - - 4.0.0 - - zstack - org.zstack + + 4.0.0 + + zstack + org.zstack 5.5.0 - .. - - configuration - - - org.zstack - core - ${project.version} - - - org.zstack - utils - ${project.version} - - - org.zstack - header - ${project.version} - - - org.zstack - search - ${project.version} - - - org.zstack - tag - ${project.version} - - - org.zstack - identity - ${project.version} - - - - commons-codec - commons-codec - 1.15 - - - - - - org.apache.maven.plugins - maven-compiler-plugin - ${project.compiler.version} - - groovy-eclipse-compiler - ${project.java.version} - ${project.java.version} - lines,vars,source - true - - - - org.codehaus.groovy - groovy-eclipse-compiler - ${groovy.eclipse.compiler} - - - org.codehaus.groovy - groovy-eclipse-batch - ${groovy.eclipse.batch} - - - - - org.codehaus.mojo - aspectj-maven-plugin - ${aspectj.plugin.version} - - - - compile - test-compile - - - - - ${project.java.version} - ${project.java.version} - ${project.java.version} - true - - - org.springframework - spring-aspects - - - org.zstack - core - - - org.zstack - header - - - - - - - + .. + + configuration + + + org.zstack + core + ${project.version} + + + org.zstack + utils + ${project.version} + + + org.zstack + header + ${project.version} + + + org.zstack + search + ${project.version} + + + org.zstack + tag + ${project.version} + + + org.zstack + identity + ${project.version} + + + + commons-codec + commons-codec + 1.15 + + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${project.compiler.version} + + ${project.java.version} + true + true + + + + + org.codehaus.mojo + aspectj-maven-plugin + ${aspectj.plugin.version} + + + org.aspectj + aspectjtools + ${aspectj.version} + + + + + + compile + test-compile + + + + + ${project.java.version} + ${project.java.version} + ${project.java.version} + ${project.build.sourceEncoding} + true + + + + org.springframework + spring-aspects + + + org.zstack + core + + + org.zstack + header + + + + + + + diff --git a/configuration/src/main/java/org/zstack/configuration/ConfigurationManagerImpl.java b/configuration/src/main/java/org/zstack/configuration/ConfigurationManagerImpl.java index ad0aa1efb24..20eb6be6d06 100755 --- a/configuration/src/main/java/org/zstack/configuration/ConfigurationManagerImpl.java +++ b/configuration/src/main/java/org/zstack/configuration/ConfigurationManagerImpl.java @@ -452,7 +452,7 @@ private void classToApiMessageGroovyClass(StringBuilder sb, Class clazz) { sb.append(String.format("\n\n%sdef fullName() { return '%s' }", whiteSpace(4), clazz.getName())); if (APIEvent.class.isAssignableFrom(clazz) && !Modifier.isAbstract(clazz.getModifiers())) { try { - APIEvent evt = (APIEvent) clazz.newInstance(); + APIEvent evt = (APIEvent) clazz.getConstructor().newInstance(); sb.append(String.format("\n%sdef eventType() { return '%s' }", whiteSpace(4), evt.getType().toString())); } catch (Exception e) { throw new CloudRuntimeException(String.format("cannot generate event type for %s", clazz.getName()), e); diff --git a/console/pom.xml b/console/pom.xml index 48ea5bcd42c..32fecad585f 100755 --- a/console/pom.xml +++ b/console/pom.xml @@ -19,29 +19,23 @@ maven-compiler-plugin ${project.compiler.version} - groovy-eclipse-compiler - ${project.java.version} - ${project.java.version} - lines,vars,source + ${project.java.version} true + true - - - org.codehaus.groovy - groovy-eclipse-compiler - ${groovy.eclipse.compiler} - - - org.codehaus.groovy - groovy-eclipse-batch - ${groovy.eclipse.batch} - - + org.codehaus.mojo aspectj-maven-plugin ${aspectj.plugin.version} + + + org.aspectj + aspectjtools + ${aspectj.version} + + @@ -51,10 +45,11 @@ + ${project.java.version} ${project.java.version} ${project.java.version} - ${project.java.version} - true + ${project.build.sourceEncoding} + true org.springframework diff --git a/core/pom.xml b/core/pom.xml index 0ab8bb020f0..ccefdac3fa6 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -10,6 +10,22 @@ core core core library for zstack + + + + + central + Maven Central Plugin Repository + https://repo1.maven.org/maven2 + + true + + + false + + + + org.zstack @@ -21,6 +37,32 @@ header ${project.version} + + + org.zstack + abstraction + ${project.version} + + + + + com.fasterxml.jackson.core + jackson-databind + + + com.fasterxml.jackson.core + jackson-core + + + com.fasterxml.jackson.core + jackson-annotations + + + + + com.rabbitmq + amqp-client + org.quartz-scheduler quartz @@ -201,29 +243,24 @@ maven-compiler-plugin ${project.compiler.version} - groovy-eclipse-compiler - ${project.java.version} - ${project.java.version} - lines,vars,source + ${project.java.version} true + true - - - org.codehaus.groovy - groovy-eclipse-compiler - ${groovy.eclipse.compiler} - - - org.codehaus.groovy - groovy-eclipse-batch - ${groovy.eclipse.batch} - - + + org.codehaus.mojo aspectj-maven-plugin ${aspectj.plugin.version} + + + org.aspectj + aspectjtools + ${aspectj.version} + + @@ -233,10 +270,12 @@ - ${project.java.version} ${project.java.version} + ${project.java.version} ${project.java.version} - true + ${project.build.sourceEncoding} + true + none org.springframework diff --git a/core/src/main/java/org/zstack/core/cloudbus/CloudBusImpl2.java b/core/src/main/java/org/zstack/core/cloudbus/CloudBusImpl2.java index 85e16f1e39f..c83ff204e78 100755 --- a/core/src/main/java/org/zstack/core/cloudbus/CloudBusImpl2.java +++ b/core/src/main/java/org/zstack/core/cloudbus/CloudBusImpl2.java @@ -685,7 +685,7 @@ private void tryBestToReplyError(byte[] binary, String errMsg) { String msgName = (String) msgObj.keySet().iterator().next(); Class msgClass = Class.forName(msgName); - Message msgInstance = (Message) msgClass.newInstance(); + Message msgInstance = (Message) msgClass.getConstructor().newInstance(); msgInstance.setHeaders(headers); msgInstance.setId((String) msg.get("id")); replyErrorByMessageType(msgInstance, argerr(ORG_ZSTACK_CORE_CLOUDBUS_10021, "message is not in corrected JSON mediaType, %s", errMsg)); diff --git a/core/src/main/java/org/zstack/core/db/DatabaseFacadeImpl.java b/core/src/main/java/org/zstack/core/db/DatabaseFacadeImpl.java index d0a92426313..1015389973a 100755 --- a/core/src/main/java/org/zstack/core/db/DatabaseFacadeImpl.java +++ b/core/src/main/java/org/zstack/core/db/DatabaseFacadeImpl.java @@ -670,7 +670,7 @@ public long generateSequenceNumber(Class seqTable) { if (id == null) { throw new CloudRuntimeException(String.format("sequence VO[%s] must have 'id' field", seqTable.getName())); } - Object vo = seqTable.newInstance(); + Object vo = seqTable.getConstructor().newInstance(); vo = persistAndRefresh(vo); id.setAccessible(true); return (Long) id.get(vo); diff --git a/core/src/main/java/org/zstack/core/gc/GarbageCollectorManagerImpl.java b/core/src/main/java/org/zstack/core/gc/GarbageCollectorManagerImpl.java index e3564021a3a..2c1d01d25ed 100755 --- a/core/src/main/java/org/zstack/core/gc/GarbageCollectorManagerImpl.java +++ b/core/src/main/java/org/zstack/core/gc/GarbageCollectorManagerImpl.java @@ -181,15 +181,15 @@ private GarbageCollector loadGCJob(GarbageCollectorVO vo) { GarbageCollector ret = null; Class clz = Class.forName(vo.getRunnerClass()); if (vo.getType().equals(GarbageCollectorType.EventBased.toString())) { - EventBasedGarbageCollector gc = (EventBasedGarbageCollector) clz.newInstance(); + EventBasedGarbageCollector gc = (EventBasedGarbageCollector) clz.getConstructor().newInstance(); gc.load(vo); ret = gc; } else if (vo.getType().equals(GarbageCollectorType.TimeBased.toString())) { - TimeBasedGarbageCollector gc = (TimeBasedGarbageCollector) clz.newInstance(); + TimeBasedGarbageCollector gc = (TimeBasedGarbageCollector) clz.getConstructor().newInstance(); gc.load(vo); ret = gc; } else if (vo.getType().equals(GarbageCollectorType.CycleBased.toString())) { - TimeBasedGarbageCollector gc = (TimeBasedGarbageCollector) clz.newInstance(); + TimeBasedGarbageCollector gc = (TimeBasedGarbageCollector) clz.getConstructor().newInstance(); gc.load(vo); ret = gc; } else { diff --git a/core/src/main/java/org/zstack/core/rest/RESTApiFacadeImpl.java b/core/src/main/java/org/zstack/core/rest/RESTApiFacadeImpl.java index db25fa2bb21..78fd2b70ce4 100755 --- a/core/src/main/java/org/zstack/core/rest/RESTApiFacadeImpl.java +++ b/core/src/main/java/org/zstack/core/rest/RESTApiFacadeImpl.java @@ -33,6 +33,7 @@ import javax.persistence.EntityManagerFactory; import javax.persistence.EntityTransaction; import javax.persistence.Query; +import java.lang.reflect.InvocationTargetException; import java.util.*; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; @@ -104,7 +105,8 @@ private void handle(final DeleteRestApiVOMsg msg){ } } - void init() throws ClassNotFoundException, InstantiationException, IllegalAccessException { + void init() throws ClassNotFoundException, InstantiationException, IllegalAccessException, + NoSuchMethodException, InvocationTargetException { Set boundEvents = new HashSet(100); ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(true); scanner.resetFilters(false); @@ -115,7 +117,7 @@ void init() throws ClassNotFoundException, InstantiationException, IllegalAccess if (clazz == APIEvent.class) { continue; } - APIEvent evt = (APIEvent) clazz.newInstance(); + APIEvent evt = (APIEvent) clazz.getConstructor().newInstance(); boundEvents.add(evt); } } diff --git a/core/src/main/java/org/zstack/core/workflow/FlowChainBuilder.java b/core/src/main/java/org/zstack/core/workflow/FlowChainBuilder.java index 7b5a65d26c6..4f6f1d02147 100755 --- a/core/src/main/java/org/zstack/core/workflow/FlowChainBuilder.java +++ b/core/src/main/java/org/zstack/core/workflow/FlowChainBuilder.java @@ -24,7 +24,7 @@ public FlowChainBuilder construct() { for (Object name : flowClassNames) { String className = (String) name; Class clazz = (Class) Class.forName(className); - Flow flow = clazz.newInstance(); + Flow flow = clazz.getConstructor().newInstance(); flows.add(flow); } } diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md new file mode 100644 index 00000000000..796d3b5db53 --- /dev/null +++ b/docs/ARCHITECTURE.md @@ -0,0 +1,1199 @@ +# ZStack 后端架构索引 + +> 本文档描述 ZStack IaaS 云计算平台后端的核心架构设计、组件机制和扩展方式。 + +## 目录 + +- [一、架构概览](#一架构概览) +- [二、核心框架层](#二核心框架层) + - [2.1 消息总线 (CloudBus)](#21-消息总线-cloudbus) + - [2.2 依赖注入与组件管理](#22-依赖注入与组件管理) + - [2.3 数据库访问层 (DatabaseFacade)](#23-数据库访问层-databasefacade) + - [2.4 异步编程模型 (ThreadFacade)](#24-异步编程模型-threadfacade) + - [2.5 错误处理机制 (ErrorFacade)](#25-错误处理机制-errorfacade) +- [三、API 消息设计](#三api-消息设计) + - [3.1 消息类型层次](#31-消息类型层次) + - [3.2 数据模型架构](#32-数据模型架构) + - [3.3 关键注解](#33-关键注解) +- [四、REST API 层](#四rest-api-层) + - [4.1 核心组件](#41-核心组件) + - [4.2 请求处理流程](#42-请求处理流程) + - [4.3 异步 API 机制](#43-异步-api-机制) + - [4.4 限流机制](#44-限流机制) +- [五、工作流引擎 (FlowChain)](#五工作流引擎-flowchain) + - [5.1 工作流类型](#51-工作流类型) + - [5.2 Flow 接口](#52-flow-接口) + - [5.3 回滚机制](#53-回滚机制) +- [六、插件扩展系统](#六插件扩展系统) + - [6.1 插件类型分类](#61-插件类型分类) + - [6.2 插件注册方式](#62-插件注册方式) + - [6.3 扩展点类型](#63-扩展点类型) +- [七、配置管理系统](#七配置管理系统) + - [7.1 GlobalConfig (全局配置)](#71-globalconfig-全局配置) + - [7.2 ResourceConfig (资源配置)](#72-resourceconfig-资源配置) +- [八、启动流程](#八启动流程) + - [8.1 启动入口](#81-启动入口) + - [8.2 管理节点启动步骤](#82-管理节点启动步骤) + - [8.3 数据库 Schema 管理](#83-数据库-schema-管理) +- [九、测试框架](#九测试框架) + - [9.1 测试框架结构](#91-测试框架结构) + - [9.2 模拟器机制](#92-模拟器机制) + - [9.3 环境定义 DSL](#93-环境定义-dsl) +- [十、架构特性总结](#十架构特性总结) + +--- + +## 一、架构概览 + +ZStack 是一个企业级开源 IaaS 云计算平台,采用 **Java + Spring + JPA/Hibernate** 技术栈,以**消息总线**为核心构建分布式、可扩展的微服务架构。 + +### 核心设计理念 + +| 理念 | 说明 | +|------|------| +| **全异步架构** | 所有操作通过消息总线异步执行,提升系统吞吐量 | +| **插件化扩展** | 通过扩展点机制实现模块解耦,便于新功能接入 | +| **声明式 API** | 注解驱动的 REST API 设计,简化开发 | +| **统一错误处理** | AOP + 错误码体系,保证系统稳定性 | + +### 核心技术栈 + +| 层次 | 技术 | +|------|------| +| 依赖注入 | Spring Framework | +| ORM | JPA / Hibernate | +| AOP | AspectJ | +| 消息传输 | HTTP / RabbitMQ | +| 测试框架 | JUnit + Groovy DSL | +| 数据库迁移 | Flyway | +| 连接池 | C3P0 | + +### 项目模块结构 + +``` +zstack/ +├── core/ # 核心框架(消息总线、数据库、线程、错误处理) +├── header/ # API 消息定义、VO/Inventory、常量枚举 +├── rest/ # REST API 服务器 +├── portal/ # 管理节点启动入口 +├── configuration/ # 配置管理 +├── resourceconfig/ # 资源级配置 +├── compute/ # 计算资源管理 +├── storage/ # 存储资源管理 +├── network/ # 网络资源管理 +├── identity/ # 身份认证 +├── image/ # 镜像管理 +├── plugin/ # 插件模块(KVM、Ceph、虚拟路由器等) +├── test/ # 集成测试 +├── testlib/ # 测试框架库 +├── simulator/ # 模拟器 +└── conf/ # 配置文件和数据库 Schema +``` + +--- + +## 二、核心框架层 + +核心框架位于 `core/src/main/java/org/zstack/core/` 目录。 + +### 2.1 消息总线 (CloudBus) + +消息总线是 ZStack 架构的核心,负责服务间通信。 + +#### 核心类 + +| 类/接口 | 路径 | 说明 | +|---------|------|------| +| `CloudBus` | `core/cloudbus/CloudBus.java` | 消息总线核心接口 | +| `CloudBusImpl3` | `core/cloudbus/CloudBusImpl3.java` | 当前实现(基于 HTTP) | +| `CloudBusImpl2` | `core/cloudbus/CloudBusImpl2.java` | 旧实现(基于 RabbitMQ) | + +#### 消息类型层次 + +``` +Message (基础消息) + └── NeedReplyMessage (需要回复的消息) + └── APIMessage (API 消息) + ├── APICreateMessage (创建资源) + ├── APIGetMessage (获取资源) + └── APIQueryMessage (查询资源) + +MessageReply (消息回复) + └── APIReply (API 回复) + +Event (事件) + └── APIEvent (API 事件) +``` + +#### 核心功能 + +| 方法 | 说明 | +|------|------| +| `send(msg, callback)` | 异步发送消息,通过回调接收响应 | +| `call(msg)` | 同步调用,阻塞等待回复 | +| `route(msg)` | 根据 `serviceId` 路由消息到对应服务 | +| `publish(event)` | 发布事件给所有订阅者 | +| `registerService(service)` | 注册服务到消息总线 | + +#### 使用示例 + +```java +// 异步发送 +bus.send(msg, new CloudBusCallBack(completion) { + @Override + public void run(MessageReply reply) { + if (reply.isSuccess()) { + // 处理成功 + } else { + // 处理失败 + } + } +}); + +// 同步调用 +MessageReply reply = bus.call(msg); +``` + +### 2.2 依赖注入与组件管理 + +#### 核心类 + +| 类/接口 | 路径 | 说明 | +|---------|------|------| +| `ComponentLoader` | `core/componentloader/ComponentLoader.java` | 组件加载器接口 | +| `ComponentLoaderImpl` | `core/componentloader/ComponentLoaderImpl.java` | 基于 Spring 的实现 | +| `PluginRegistry` | `core/componentloader/PluginRegistry.java` | 插件注册表接口 | +| `PluginRegistryImpl` | `core/componentloader/PluginRegistryImpl.java` | 插件注册实现 | +| `Platform` | `core/Platform.java` | 平台入口(静态访问) | + +#### 组件生命周期接口 + +```java +// 组件接口 - 定义生命周期 +public interface Component { + boolean start(); // 启动 + boolean stop(); // 停止 +} + +// 服务接口 - 可处理消息 +public interface Service extends Component { + void handleMessage(Message msg); // 处理消息 + String getId(); // 服务 ID + int getSyncLevel(); // 同步级别 + List getAliasIds(); // 别名 +} +``` + +#### 获取组件 + +```java +// 通过 Platform 静态方法获取 +DatabaseFacade dbf = Platform.getComponentLoader().getComponent(DatabaseFacade.class); + +// 或使用 Spring 注入 +@Autowired +private DatabaseFacade dbf; +``` + +### 2.3 数据库访问层 (DatabaseFacade) + +#### 核心类 + +| 类/接口 | 路径 | 说明 | +|---------|------|------| +| `DatabaseFacade` | `core/db/DatabaseFacade.java` | 数据库门面接口 | +| `DatabaseFacadeImpl` | `core/db/DatabaseFacadeImpl.java` | JPA/Hibernate 实现 | +| `SQLBatch` | `core/db/SQLBatch.java` | SQL 批处理抽象类 | +| `SimpleQuery` | `core/db/SimpleQuery.java` | 查询构建器 | +| `SQL` | `core/db/SQL.java` | SQL 工具类 | + +#### 核心功能 + +| 方法 | 说明 | +|------|------| +| `persist(entity)` | 持久化实体 | +| `update(entity)` | 更新实体 | +| `remove(entity)` | 删除实体(支持软删除) | +| `findByUuid(uuid, class)` | 按 UUID 查找 | +| `createQuery(class)` | 创建查询 | +| `eoCleanup(class)` | 清理软删除的实体对象 | + +#### 软删除机制 + +```java +// VO 定义时使用 @EO 注解指定软删除实体 +@Entity +@Table +@EO(EOClazz = VmInstanceEO.class) +public class VmInstanceVO extends VmInstanceAO { + // ... +} + +// 软删除级联 +@Entity +@SoftDeletionCascades({ + @SoftDeletionCascade(parent = VmInstanceVO.class, joinColumn = "vmInstanceUuid") +}) +public class VmNicVO extends VmNicAO { + // ... +} +``` + +#### 死锁处理 + +```java +// 使用 @DeadlockAutoRestart 自动重试 +@DeadlockAutoRestart +public void updateResource() { + // 可能发生死锁的操作 +} +``` + +### 2.4 异步编程模型 (ThreadFacade) + +#### 核心类 + +| 类/接口 | 路径 | 说明 | +|---------|------|------| +| `ThreadFacade` | `core/thread/ThreadFacade.java` | 线程管理门面接口 | +| `ThreadFacadeImpl` | `core/thread/ThreadFacadeImpl.java` | 线程池实现 | +| `Completion` | `header/core/Completion.java` | 无返回值回调 | +| `ReturnValueCompletion` | `header/core/ReturnValueCompletion.java` | 有返回值回调 | +| `NoErrorCompletion` | `header/core/NoErrorCompletion.java` | 无错误回调 | + +#### 回调接口层次 + +``` +AbstractCompletion (抽象基类) +├── Completion (无返回值回调) +│ ├── success() +│ └── fail(ErrorCode) +│ +├── ReturnValueCompletion (有返回值回调) +│ ├── success(T returnValue) +│ └── fail(ErrorCode) +│ +└── NoErrorCompletion (无错误回调) + └── done() +``` + +#### 异步执行注解 + +| 注解 | 说明 | +|------|------| +| `@AsyncThread` | 异步执行方法 | +| `@SyncThread` | 同步执行(带同步级别) | +| `@ScheduledThread` | 定时执行 | + +#### 同步控制机制 + +```java +// SyncTask 接口 - 支持同步级别 +public interface SyncTask extends Task { + String getSyncSignature(); // 同步签名,相同签名的任务串行执行 + int getSyncLevel(); // 同步级别 +} + +// 使用示例 +thdf.syncSubmit(new SyncTask() { + @Override + public String getSyncSignature() { + return "host-" + hostUuid; // 同一主机的操作串行执行 + } + + @Override + public Void call() throws Exception { + // 执行操作 + return null; + } +}); +``` + +#### SingleFlight 模式 + +```java +// 相同 key 的请求只执行一次 +thdf.singleFlightSubmit(new SingleFlightTask(completion) { + @Override + public String getSingleFlightKey() { + return "refresh-" + resourceUuid; + } + + @Override + public void run(SingleFlightCompletion completion) { + // 执行操作 + completion.success(result); + } +}); +``` + +### 2.5 错误处理机制 (ErrorFacade) + +#### 核心类 + +| 类/接口 | 路径 | 说明 | +|---------|------|------| +| `ErrorFacade` | `core/errorcode/ErrorFacade.java` | 错误处理门面接口 | +| `ErrorFacadeImpl` | `core/errorcode/ErrorFacadeImpl.java` | 错误处理实现 | +| `ErrorCode` | `header/errorcode/ErrorCode.java` | 错误码类 | +| `OperationFailureException` | `header/exception/OperationFailureException.java` | 操作失败异常 | + +#### AOP 异常处理注解 + +| 注解 | 切面 | 说明 | +|------|------|------| +| `@ExceptionSafe` | `ExceptionSafeAspect.aj` | 自动捕获异常 | +| `@MessageSafe` | `MessageSafeAspect.aj` | 消息处理异常自动回复 | + +#### 错误码定义 + +```xml + + + SYS.1001 + Internal error + +``` + +#### 异常处理流程 + +``` +方法抛出异常 + ↓ +AOP 拦截 (ExceptionSafeAspect / MessageSafeAspect) + ↓ +转换为 ErrorCode + ↓ +通过 Completion.fail(ErrorCode) 回调 + 或 +通过 bus.replyErrorByMessageType() 回复消息 +``` + +--- + +## 三、API 消息设计 + +API 消息定义位于 `header/src/main/java/org/zstack/header/` 目录。 + +### 3.1 消息类型层次 + +| 类型 | 命名模式 | 基类 | 用途 | +|------|---------|------|------| +| 请求消息 | `API*Msg` | `APIMessage` | 客户端请求 | +| 异步事件 | `API*Event` | `APIEvent` | 异步操作结果通知 | +| 同步回复 | `API*Reply` | `APIReply` | 同步查询结果 | + +#### 消息流模式 + +``` +同步 API: APIMessage → CloudBus.call() → APIReply +异步 API: APIMessage → CloudBus.send() → APIEvent (通过回调) + +资源操作模式: +- Create: APICreateXxxMsg → APICreateXxxEvent +- Update: APIUpdateXxxMsg → APIUpdateXxxEvent +- Delete: APIDeleteXxxMsg → APIDeleteXxxEvent +- Query: APIQueryXxxMsg → APIQueryXxxReply +- Get: APIGetXxxMsg → APIGetXxxReply +``` + +### 3.2 数据模型架构 + +#### 层次结构 + +``` +AO (Abstract Object) - 定义字段 + └── VO (Value Object) - 数据库实体 + └── EO (Entity Object) - 软删除视图 + +数据流转: +VO (数据库实体) → Inventory (DTO) → API Response (REST 响应) +``` + +#### VO 定义示例 + +```java +@Entity +@Table +@EO(EOClazz = VmInstanceEO.class) +@BaseResource +@EntityGraph( + parents = { + @EntityGraph.Neighbour(type = ZoneVO.class, myField = "zoneUuid", targetField = "uuid"), + }, + friends = { + @EntityGraph.Neighbour(type = ImageVO.class, myField = "imageUuid", targetField = "uuid"), + } +) +public class VmInstanceVO extends VmInstanceAO implements OwnedByAccount, ToInventory { + // 字段定义 +} +``` + +#### Inventory 定义示例 + +```java +@Inventory(mappingVOClass = VmInstanceVO.class) +@ExpandedQueries({ + @ExpandedQuery(expandedField = "zone", inventoryClass = ZoneInventory.class, foreignKey = "zoneUuid") +}) +public class VmInstanceInventory implements Serializable { + + public static VmInstanceInventory valueOf(VmInstanceVO vo) { + return new VmInstanceInventory(vo); + } + + public static List valueOf(Collection vos) { + return vos.stream().map(VmInstanceInventory::valueOf).collect(Collectors.toList()); + } +} +``` + +### 3.3 关键注解 + +#### @RestRequest + +```java +@RestRequest( + path = "/vm-instances", + method = HttpMethod.POST, + responseClass = APICreateVmInstanceEvent.class, + parameterName = "params" +) +public class APICreateVmInstanceMsg extends APICreateMessage { + // ... +} +``` + +#### @APIParam + +```java +@APIParam( + required = true, // 必填 + maxLength = 255, // 最大长度 + resourceType = ZoneVO.class, // 资源类型验证 + checkAccount = true, // 账户权限检查 + validValues = {"Enabled", "Disabled"} // 有效值 +) +private String zoneUuid; +``` + +#### @RestResponse + +```java +@RestResponse(allTo = "inventory") // 所有字段映射到 inventory +public class APICreateVmInstanceEvent extends APIEvent { + private VmInstanceInventory inventory; +} +``` + +--- + +## 四、REST API 层 + +REST API 实现位于 `rest/src/main/java/org/zstack/rest/` 目录。 + +### 4.1 核心组件 + +| 类 | 说明 | +|----|------| +| `RestServer` | REST API 服务器核心实现 | +| `RestServerController` | Spring MVC 入口控制器 | +| `RateLimiter` | 限流器(Token Bucket 算法) | +| `AsyncRestApiStore` | 异步 API 存储接口 | +| `MysqlAsyncRestStore` | 异步 API 存储实现 | +| `RequestData` | 请求数据封装 | + +### 4.2 请求处理流程 + +``` +HTTP 请求 + ↓ +RestServerController (Spring MVC 入口) + ↓ +RestServer.handle() + ↓ +┌─────────────────────────────────┐ +│ 1. 限流检查 (RateLimiter) │ +│ 2. 请求拦截器处理 │ +│ 3. 路径匹配 (AntPathMatcher) │ +│ 4. 认证处理 │ +│ ├─ OAuth: Authorization: OAuth +│ └─ AccessKey: Authorization: ZStack : +│ 5. 参数解析 │ +│ ├─ GET/DELETE: Query String │ +│ └─ POST/PUT: Request Body │ +│ 6. 构建 APIMessage │ +│ 7. 发送到 CloudBus │ +│ ├─ 同步调用 → 200 OK │ +│ └─ 异步调用 → 202 Accepted │ +└─────────────────────────────────┘ +``` + +### 4.3 异步 API 机制 + +#### 工作流程 + +``` +1. 请求提交 + POST /v1/vm-instances + → 保存到 AsyncRestVO (状态: processing) + → 发送消息到 CloudBus + → 返回 202 Accepted + → Location: /v1/api-jobs/{uuid} + +2. 状态查询 + GET /v1/api-jobs/{uuid} + → processing: 202 Accepted + → done + success: 200 OK + → done + failed: 503 Service Unavailable + → expired: 404 Not Found + +3. WebHook 回调 (可选) + 请求头: X-Web-Hook: + 任务完成时自动 POST 结果到 WebHook URL +``` + +### 4.4 限流机制 + +基于 Token Bucket 算法实现: + +```java +public class RateLimiter { + private final LoadingCache requestCache; + private final int maxRequestsPerMinute; + + // 基于客户端 IP 限流 + public boolean isRateLimitExceeded(String clientIp) { + TokenBucket bucket = requestCache.get(clientIp); + return !bucket.tryConsume(); + } +} +``` + +配置: +- 默认限制:12000 请求/分钟 +- 可通过 `RestGlobalProperty.REST_RATE_LIMITS` 配置 + +--- + +## 五、工作流引擎 (FlowChain) + +工作流实现位于 `core/src/main/java/org/zstack/core/workflow/` 目录。 + +### 5.1 工作流类型 + +| 类型 | 特点 | 适用场景 | +|------|------|---------| +| `SimpleFlowChain` | 内存执行,无持久化,性能好 | 简单业务流程 | +| `WorkFlowChain` | 数据库持久化,支持恢复 | 复杂流程,需状态恢复 | +| `AsyncWorkFlowChain` | 异步执行和回调 | 异步场景 | +| `ShareFlowChain` | 动态流程编排 | 运行时构建流程 | + +### 5.2 Flow 接口 + +```java +public interface Flow { + // 执行流程 + void run(FlowTrigger trigger, Map data); + + // 回滚流程 + void rollback(FlowRollback trigger, Map data); + + // 是否跳过(默认不跳过) + default boolean skip(Map data) { return false; } +} + +public interface FlowTrigger { + void next(); // 继续下一个流程 + void fail(ErrorCode err); // 失败并触发回滚 +} + +public interface FlowRollback { + void rollback(); // 继续回滚 + void skipRestRollbacks(); // 跳过剩余回滚 +} +``` + +#### 使用示例 + +```java +new SimpleFlowChain() + .setName("create-vm-flow") + .then(new Flow() { + @Override + public void run(FlowTrigger trigger, Map data) { + // 步骤 1:分配资源 + data.put("allocated", true); + trigger.next(); + } + + @Override + public void rollback(FlowRollback trigger, Map data) { + // 回滚:释放资源 + releaseResource(); + trigger.rollback(); + } + }) + .then(new NoRollbackFlow() { + @Override + public void run(FlowTrigger trigger, Map data) { + // 步骤 2:启动 VM(无需回滚) + trigger.next(); + } + }) + .done(new FlowDoneHandler(completion) { + @Override + public void handle(Map data) { + // 完成处理 + completion.success(); + } + }) + .error(new FlowErrorHandler(completion) { + @Override + public void handle(ErrorCode err, Map data) { + // 错误处理 + completion.fail(err); + } + }) + .start(); +``` + +### 5.3 回滚机制 + +#### SimpleFlowChain 回滚 + +- 使用栈结构(LIFO)实现逆序回滚 +- 调用 `trigger.next()` 时,当前 Flow 入栈 +- 调用 `trigger.fail(err)` 时,触发回滚 +- 支持 `skipRestRollbacks()` 跳过剩余回滚 + +#### WorkFlowChain 回滚 + +- 每个 Flow 状态持久化到 `WorkFlowVO` +- 支持 `carryOn(chainUuid)` 从断点继续执行 +- 自动判断继续策略:重启或继续回滚 + +--- + +## 六、插件扩展系统 + +插件位于 `plugin/` 目录,每个插件是独立的 Maven 模块。 + +### 6.1 插件类型分类 + +| 类型 | 插件 | 说明 | +|------|------|------| +| **Hypervisor** | `kvm` | KVM 虚拟化 | +| **Primary Storage** | `nfsPrimaryStorage`, `localstorage`, `ceph`, `sharedMountPointPrimaryStorage` | 主存储 | +| **Backup Storage** | `sftpBackupStorage` | 备份存储 | +| **Network Provider** | `virtualRouterProvider`, `flatNetworkProvider`, `sdnController` | 网络服务提供者 | +| **Network Service** | `securityGroup`, `portForwarding`, `loadBalancer`, `eip`, `vip` | 网络服务 | +| **认证/授权** | `ldap`, `loginPlugin`, `directory` | 身份认证 | + +### 6.2 插件注册方式 + +#### XML 配置方式 + +```xml + + + + + + + + +``` + +#### 代码方式 (PluginDSL) + +```java +// 使用 PluginDSL 在代码中声明扩展 +PluginDSL.plugin("myPlugin") + .extension(SomeExtensionPoint.class, this) + .register(); +``` + +### 6.3 扩展点类型 + +#### Factory 模式 + +```java +// 定义工厂接口 +public interface HypervisorFactory { + HypervisorType getHypervisorType(); + Host createHost(HostVO vo); +} + +// 实现工厂 +public class KVMHostFactory implements HypervisorFactory { + public static final HypervisorType hypervisorType = new HypervisorType("KVM"); + + @Override + public HypervisorType getHypervisorType() { + return hypervisorType; + } +} + +// 使用工厂 +List factories = pluginRgty.getExtensionList(HypervisorFactory.class); +``` + +#### Backend 模式 + +```java +// 定义后端接口 +public interface PortForwardingBackend { + NetworkServiceProviderType getProviderType(); + void applyPortForwardingRule(PortForwardingRuleInventory rule, Completion completion); +} + +// 实现后端 +public class VirtualRouterPortForwardingBackend implements PortForwardingBackend { + @Override + public NetworkServiceProviderType getProviderType() { + return VirtualRouterConstant.VIRTUAL_ROUTER_PROVIDER_TYPE; + } +} + +// 注册和使用 +Map backends = new HashMap<>(); +for (PortForwardingBackend backend : pluginRgty.getExtensionList(PortForwardingBackend.class)) { + backends.put(backend.getProviderType().toString(), backend); +} +``` + +#### ExtensionPoint 回调模式 + +```java +// 定义扩展点接口 +public interface KVMStartVmExtensionPoint { + void beforeStartVmOnKvm(KVMHostInventory host, VmInstanceSpec spec, StartVmCmd cmd); + void afterStartVmOnKvm(KVMHostInventory host, VmInstanceSpec spec, StartVmCmd cmd); +} + +// 实现扩展点 +public class CephPrimaryStorageFactory implements KVMStartVmExtensionPoint { + @Override + public void beforeStartVmOnKvm(KVMHostInventory host, VmInstanceSpec spec, StartVmCmd cmd) { + // 在 VM 启动前执行 Ceph 相关逻辑 + } +} + +// 触发扩展点 +for (KVMStartVmExtensionPoint ext : pluginRgty.getExtensionList(KVMStartVmExtensionPoint.class)) { + ext.beforeStartVmOnKvm(host, spec, cmd); +} +``` + +--- + +## 七、配置管理系统 + +### 7.1 GlobalConfig (全局配置) + +位于 `core/src/main/java/org/zstack/core/config/` 目录。 + +#### 核心类 + +| 类 | 说明 | +|----|------| +| `GlobalConfig` | 配置项实体 | +| `GlobalConfigFacade` | 配置管理门面接口 | +| `GlobalConfigFacadeImpl` | 配置管理实现 | +| `GlobalConfigVO` | 配置数据库实体 | + +#### 配置来源优先级 + +``` +1. 数据库(运行时值) +2. XML 配置文件(conf/globalConfig/*.xml) +3. Java 注解(@GlobalConfigDef) +4. 扩展点自动生成 +``` + +#### 定义方式 + +**XML 方式**: +```xml + + + + vm + vm.cleanTraffic + Whether to clean traffic when deleting VM + false + java.lang.Boolean + + +``` + +**注解方式**: +```java +@GlobalConfigDefinition +public class VmGlobalConfig { + public static final String CATEGORY = "vm"; + + @GlobalConfigValidation(notNull = true) + public static GlobalConfig VM_CLEAN_TRAFFIC = new GlobalConfig(CATEGORY, "vm.cleanTraffic"); +} +``` + +#### 使用方式 + +```java +// 获取配置值 +boolean cleanTraffic = VmGlobalConfig.VM_CLEAN_TRAFFIC.value(Boolean.class); + +// 监听配置变更 +VmGlobalConfig.VM_CLEAN_TRAFFIC.installUpdateExtension((oldValue, newValue) -> { + // 处理配置变更 +}); +``` + +### 7.2 ResourceConfig (资源配置) + +位于 `resourceconfig/src/main/java/org/zstack/resourceconfig/` 目录。 + +#### 与 GlobalConfig 的区别 + +| 特性 | GlobalConfig | ResourceConfig | +|------|-------------|----------------| +| 作用域 | 全局共享 | 资源级独立设置 | +| 存储 | `GlobalConfigVO` | `ResourceConfigVO` | +| 查找顺序 | 直接返回全局值 | 资源 → 父资源 → GlobalConfig | + +#### 绑定方式 + +```java +@GlobalConfigDefinition +public class VmGlobalConfig { + // 绑定到 VM 和 Cluster,支持多级继承 + @BindResourceConfig({VmInstanceVO.class, ClusterVO.class}) + public static GlobalConfig VM_VIDEO_TYPE = new GlobalConfig(CATEGORY, "videoType"); +} +``` + +#### 查找优先级 + +``` +1. 资源自身配置(ResourceConfigVO 中 resourceUuid 匹配) +2. 父资源配置(通过 DBGraph 查找父资源) +3. GlobalConfig 默认值 +``` + +#### API 接口 + +| API | 说明 | +|-----|------| +| `APIUpdateResourceConfigMsg` | 更新资源配置 | +| `APIDeleteResourceConfigMsg` | 删除资源配置 | +| `APIGetResourceConfigMsg` | 获取资源配置 | +| `APIGetResourceBindableConfigMsg` | 查询可绑定的配置 | + +--- + +## 八、启动流程 + +### 8.1 启动入口 + +``` +Servlet 容器启动 + ↓ +BootstrapWebListener.contextInitialized() + → 触发 Platform 静态初始化 + ↓ +BootstrapContextLoaderListener.contextInitialized() + → 加载 Spring 上下文 (beanRefContext.xml → zstack.xml) + ↓ +ComponentLoaderWebListener.contextInitialized() + → Platform.createComponentLoaderFromWebApplicationContext() + → ManagementNodeManager.startNode() +``` + +### 8.2 管理节点启动步骤 + +`ManagementNodeManagerImpl.start()` 使用 FlowChain 编排启动步骤: + +| 步骤 | 名称 | 说明 | +|------|------|------| +| 1 | `bootstrap-cloudbus` | CloudBus 初始化(已在 Platform 中完成) | +| 2 | `populate-components` | 收集所有 Component 和 Service | +| 3 | `register-node-on-cloudbus` | 注册管理节点服务到 CloudBus | +| 4 | `call-prepare-db-extension` | 准备数据库初始值 | +| 5 | `start-components` | 启动所有组件和服务 | +| 6 | `create-DB-record` | 创建/更新 ManagementNodeVO | +| 7 | `start-heartbeat` | 启动心跳机制 | +| 8 | `start-api-mediator` | 启动 API 中介器 | +| 9 | `set-node-to-running` | 设置节点状态为 RUNNING | +| 10 | `I-join` | 触发节点加入事件 | +| 11 | `node-is-ready` | 调用 ManagementNodeReadyExtensionPoint | +| 12 | `listen-node-life-cycle-events` | 监听节点生命周期事件 | +| 13 | `say-I-join` | 通知其他管理节点 | + +### 8.3 数据库 Schema 管理 + +#### Flyway 迁移 + +```bash +# 部署脚本 (conf/deploydb.sh) +1. 创建数据库(如果不存在) +2. 复制 SQL 文件到 Flyway 目录 + - conf/db/V0.6__schema.sql (基础 schema) + - conf/db/upgrade/*.sql (升级脚本) +3. Flyway clean (清理) +4. Flyway baseline (创建 baseline) +5. Flyway migrate (执行迁移,outOfOrder=true) +``` + +#### Schema 文件结构 + +``` +conf/db/ +├── V0.6__schema.sql # 基础 schema +├── upgrade/ +│ ├── V2.5.0__schema.sql # 升级脚本 +│ ├── V3.9.0__schema.sql +│ └── ... +├── beforeMigrate.sql # 迁移前执行 +└── beforeValidate.sql # 验证前执行 +``` + +--- + +## 九、测试框架 + +测试框架位于 `test/` 和 `testlib/` 目录。 + +### 9.1 测试框架结构 + +```groovy +// 测试用例基类 +class ExampleCase extends SubCase { + EnvSpec env + + @Override + void setup() { + // 配置 Spring,指定需要的服务模块 + spring { + sftpBackupStorage() + localStorage() + kvm() + } + } + + @Override + void environment() { + // 定义测试环境 + env = env { + zone { + name = "zone1" + cluster { ... } + } + } + } + + @Override + void test() { + // 创建环境并执行测试 + env.create { + testMethod1() + testMethod2() + } + } + + @Override + void clean() { + env.delete() + } +} +``` + +#### 生命周期 + +``` +setup() → 配置 Spring,指定模块 +environment() → 定义测试环境(不创建) +test() → env.create() 创建环境,执行测试 +clean() → 清理环境 +``` + +### 9.2 模拟器机制 + +模拟器拦截 Agent HTTP 请求,返回模拟响应。 + +```groovy +class KVMSimulator implements Simulator { + @Override + void registerSimulators(EnvSpec spec) { + // 注册 KVM Agent 路径处理器 + spec.simulator(KVMConstant.KVM_HOST_CAPACITY_PATH) { HttpEntity e, EnvSpec espec -> + def rsp = new KVMAgentCommands.HostCapacityResponse() + rsp.success = true + rsp.cpuNum = 8 + rsp.totalMemory = SizeUnit.GIGABYTE.toByte(32) + return rsp + } + + spec.simulator(KVMConstant.KVM_START_VM_PATH) { HttpEntity e -> + def cmd = JSONObjectUtil.toObject(e.body, KVMAgentCommands.StartVmCmd.class) + def rsp = new KVMAgentCommands.StartVmResponse() + rsp.success = true + return rsp + } + } +} +``` + +#### 处理器类型 + +| 类型 | 说明 | +|------|------| +| `simulator(path, closure)` | 基础 HTTP 处理器 | +| `preSimulator(path, closure)` | 请求前处理器 | +| `afterSimulator(path, closure)` | 请求后处理器 | +| `hijackSimulator(path, closure)` | 最终拦截处理器 | + +### 9.3 环境定义 DSL + +```groovy +env = env { + zone { + name = "zone" + cluster { + name = "cluster" + kvmHost { + name = "host" + totalCpu = 8 + totalMem = SizeUnit.GIGABYTE.toByte(32) + } + } + instanceOffering { + name = "instanceOffering" + cpuNum = 2 + memorySize = SizeUnit.GIGABYTE.toByte(4) + } + diskOffering { + name = "diskOffering" + diskSize = SizeUnit.GIGABYTE.toByte(100) + } + sftpBackupStorage { + name = "bs" + url = "/tmp/bs" + } + nfsPrimaryStorage { + name = "ps" + url = "/tmp/ps" + } + l2NoVlanNetwork { + name = "l2" + l3Network { + name = "l3" + ip { + startIp = "192.168.0.2" + endIp = "192.168.0.254" + gateway = "192.168.0.1" + netmask = "255.255.255.0" + } + } + } + vm { + name = "vm" + useHost("host") + useL3Networks("l3") + useInstanceOffering("instanceOffering") + useImage("image") + } + } +} +``` + +--- + +## 十、架构特性总结 + +### 设计模式应用 + +| 模式 | 应用场景 | +|------|---------| +| **门面模式** | `DatabaseFacade`, `ThreadFacade`, `ErrorFacade`, `GlobalConfigFacade` | +| **工厂模式** | `HypervisorFactory`, `PrimaryStorageFactory`, `BackupStorageFactory` | +| **观察者模式** | 事件订阅机制、配置变更监听 | +| **策略模式** | 插件扩展点、Backend 接口 | +| **模板方法** | `SQLBatch`, `AbstractService`, `Flow` | +| **责任链模式** | `FlowChain` 工作流 | +| **代理模式** | AOP 增强(AspectJ) | + +### 架构优势 + +| 优势 | 说明 | +|------|------| +| **高度解耦** | 消息总线 + 插件系统实现模块解耦 | +| **可扩展性** | 扩展点机制便于新功能接入 | +| **异步优先** | 全异步架构提升系统吞吐量 | +| **容错性** | FlowChain 支持回滚和状态恢复 | +| **统一抽象** | 门面模式简化复杂性 | +| **测试友好** | 模拟器机制便于集成测试 | +| **配置灵活** | GlobalConfig + ResourceConfig 多级配置 | + +### 关键目录索引 + +| 目录 | 内容 | +|------|------| +| `core/` | 核心框架(消息总线、数据库、线程、错误处理) | +| `header/` | API 消息定义、VO/Inventory、常量枚举 | +| `rest/` | REST API 服务器 | +| `portal/` | 管理节点启动入口 | +| `configuration/` | 配置管理 | +| `resourceconfig/` | 资源级配置 | +| `plugin/` | 插件模块 | +| `test/` | 集成测试 | +| `testlib/` | 测试框架库 | +| `conf/` | 配置文件和数据库 Schema | + +--- + +## 附录:常用类速查 + +### 核心框架 + +| 类 | 包路径 | 用途 | +|----|--------|------| +| `Platform` | `org.zstack.core` | 平台入口,静态访问组件 | +| `CloudBus` | `org.zstack.core.cloudbus` | 消息总线 | +| `DatabaseFacade` | `org.zstack.core.db` | 数据库访问 | +| `ThreadFacade` | `org.zstack.core.thread` | 线程管理 | +| `ErrorFacade` | `org.zstack.core.errorcode` | 错误处理 | +| `PluginRegistry` | `org.zstack.core.componentloader` | 插件注册 | +| `GlobalConfigFacade` | `org.zstack.core.config` | 全局配置 | + +### API 相关 + +| 类 | 包路径 | 用途 | +|----|--------|------| +| `APIMessage` | `org.zstack.header.message` | API 消息基类 | +| `APIEvent` | `org.zstack.header.message` | API 事件基类 | +| `APIReply` | `org.zstack.header.message` | API 回复基类 | +| `RestServer` | `org.zstack.rest` | REST API 服务器 | + +### 工作流 + +| 类 | 包路径 | 用途 | +|----|--------|------| +| `SimpleFlowChain` | `org.zstack.core.workflow` | 简单工作流 | +| `Flow` | `org.zstack.header.core.workflow` | 流程接口 | +| `FlowTrigger` | `org.zstack.header.core.workflow` | 流程触发器 | + +### 回调 + +| 类 | 包路径 | 用途 | +|----|--------|------| +| `Completion` | `org.zstack.header.core` | 无返回值回调 | +| `ReturnValueCompletion` | `org.zstack.header.core` | 有返回值回调 | +| `NoErrorCompletion` | `org.zstack.header.core` | 无错误回调 | + +--- + +*文档版本: 1.0* +*最后更新: 2025-01* diff --git a/docs/BUILD-ACCELERATION.md b/docs/BUILD-ACCELERATION.md new file mode 100644 index 00000000000..4ae9277103f --- /dev/null +++ b/docs/BUILD-ACCELERATION.md @@ -0,0 +1,141 @@ +# ZStack 构建加速指南 + +## 为什么 `-T 1C` 提升有限? + +- **依赖链长**:header → core → plugin* → premium,大量模块串行,可并行的只有同一“层”的模块。 +- **单模块重**:mevoco、testlib-premium、hybrid、header 等单模块编译时间 30s~70s,并行只能缩短“层内”时间。 +- **内存压力**:并行会起多个 JVM(GMavenPlus/编译器),若总内存不足易触发 GC 或交换,反而变慢。 + +--- + +## 推荐做法(按收益排序) + +### 1. 日常开发:不 clean,只编改动的模块(收益最大) + +**从 zstack 根目录构建 premium 时,必须先激活 profile `-P premium`**(根 pom 默认模块列表里没有 premium,只有激活该 profile 后 reactor 才会包含 premium)。 + +```bash +# 只编 premium 整棵子工程(含其依赖:header、core、plugin 等) +# -Dmevoco.skip.obfuscate=true 避免 mvnd 下 exec 插件 NPE,见下文说明 +mvnd install -DskipTests -P premium -Dmevoco.skip.obfuscate=true -pl premium -am + +# 只编 premium 下某模块(如 mevoco)及其依赖 +mvnd install -DskipTests -P premium -Dmevoco.skip.obfuscate=true -pl premium/mevoco -am + +# 只编 premium 下某插件 +mvnd install -DskipTests -P premium -Dmevoco.skip.obfuscate=true -pl premium/plugin-premium/某插件名 -am +``` + +若**已进入 premium 目录**,则不需要 `-P premium`,直接: + +```bash +cd premium && mvnd install -DskipTests -Dmevoco.skip.obfuscate=true + +# 只编 premium 内某模块 +cd premium && mvnd install -DskipTests -Dmevoco.skip.obfuscate=true -pl mevoco -am +``` + +避免每次 `clean` 全量重编,可节省大半时间。 + +### 2. 使用 Maven Daemon(mvnd)— 二次及以后构建明显更快 + +mvnd 保持 JVM 常驻,避免每次冷启动和重复加载类,对多模块项目通常有 **2~4 倍** 提升。 + +```bash +# macOS(mvnd 需通过官方 tap 安装,默认 brew 无此 formula) +brew install mvndaemon/homebrew-mvnd/mvnd + +# 使用方式与 mvn 一致 +mvnd clean install -DskipTests +mvnd install -DskipTests -pl premium/mevoco -am +``` + +**使用 mvnd 构建含 premium 时**:exec-maven-plugin 在 mvnd 下会因 `MavenSession.getContainer()` 为 null 报错,需跳过 mevoco 的混淆步骤: + +```bash +mvnd install -DskipTests -P premium -Dmevoco.skip.obfuscate=true +``` + +需要发布/混淆时用普通 Maven:`mvn install -DskipTests -P premium`(不加该参数)。 + +注意:首次运行仍会较慢,后续构建才会体现加速。 + +**mvnd 内存与 Groovy 编译**:test-premium、test、testlib-premium 等模块大量使用 Groovy,gmavenplus 会在同一 JVM(mvnd daemon)里解析/编译,易占满堆或 Metaspace 导致无响应。已为 gmavenplus-plugin 开启 **`true`**:Groovy 编译在独立子进程中执行,完成后子进程退出释放内存,减轻 daemon 压力。根目录 `.mvn/jvm.config` 已为 mvnd daemon 配置: + +- **堆**:`-Xmx10240m`(10GB),供 Groovy 源码与 stub 常驻 +- **Metaspace**:`-XX:MaxMetaspaceSize=2560m`(2.5GB),应对大量 Groovy/Java 类加载 +- **CodeCache**:`-XX:ReservedCodeCacheSize=512m`、`-XX:NonProfiledCodeHeapSize=240m`,避免 JIT 代码缓存满 +- **G1**:`-XX:+UseG1GC`、`-XX:+UseStringDeduplication` + +建议物理内存 ≥16GB 再跑 `mvnd install -DskipTests -P premium` 全量;否则可先用 `mvn` 或只编到 `test`(`-pl test -am`)。修改 `.mvn/jvm.config` 后必须重启 daemon 才生效: + +```bash +mvnd --stop +mvnd install -DskipTests -P premium -Dmevoco.skip.obfuscate=true +``` + +### 3. 离线构建(依赖已齐全时) + +```bash +mvn install -DskipTests -o +``` + +避免每次解析/检查远程仓库,可省数秒到数十秒。 + +### 4. 适当提高并行度(在内存充足时) + +若机器内存 ≥16GB,可尝试: + +```bash +# 最多 4 个线程,避免过多并行导致 OOM +mvn install -DskipTests -T 4 +``` + +不建议在 8GB 或以下机器用 `-T 1C`,易与 `.mvn/jvm.config` 里的大堆一起导致交换。 + +### 5. 只编到某模块,不编完全部 + +```bash +# 只编到 build(含 header/core/plugin 等),不编 test/testlib/premium 测试相关 +mvn install -DskipTests -pl build -am + +# 只编到 crypto,不编 testlib-premium / test-premium +mvn install -DskipTests -pl premium/crypto -am +``` + +适合验证主链或某个子模块,跳过最耗时的 testlib-premium 等。 + +### 6. 关闭/缩短测试(已有 -DskipTests 时可略过) + +已使用 `-DskipTests` 时,测试已跳过。若某处仍会跑测试,可再加: + +```bash +-Dmaven.test.skip=true +``` + +--- + +## 建议的日常组合 + +| 场景 | 命令示例 | +|------|----------| +| 从**根目录**只编 premium | `mvnd install -DskipTests -P premium -Dmevoco.skip.obfuscate=true -pl premium -am` | +| 从**根目录**只编 mevoco | `mvnd install -DskipTests -P premium -Dmevoco.skip.obfuscate=true -pl premium/mevoco -am` | +| 已 **cd premium**,只编某插件 | `mvnd install -DskipTests -Dmevoco.skip.obfuscate=true -pl plugin-premium/xxx -am` | +| 全量构建(含 premium,少用 clean) | `mvnd install -DskipTests -P premium -Dmevoco.skip.obfuscate=true` | +| 全量 + 并行(内存够) | `mvnd install -DskipTests -P premium -Dmevoco.skip.obfuscate=true -T 4` | +| 依赖已全、不想连网 | `mvnd install -DskipTests -P premium -Dmevoco.skip.obfuscate=true -o` | + +--- + +## 可选:为编译器开启增量(需各模块兼容) + +在根 `pom.xml` 的 `maven-compiler-plugin` 的 `pluginManagement` 里可统一开启: + +```xml + + true + +``` + +部分老模块若出现“改完不重编”的异常,再对单模块关闭即可。当前项目未全局开启,可按需试验。 diff --git a/externalservice/pom.xml b/externalservice/pom.xml index 9346a6ff780..b6971f6a68f 100755 --- a/externalservice/pom.xml +++ b/externalservice/pom.xml @@ -38,30 +38,24 @@ maven-compiler-plugin ${project.compiler.version} - groovy-eclipse-compiler - ${project.java.version} - ${project.java.version} - lines,vars,source + ${project.java.version} true + true - - - org.codehaus.groovy - groovy-eclipse-compiler - 2.9.2-01 - - - org.codehaus.groovy - groovy-eclipse-batch - 2.4.3-01 - - + org.codehaus.mojo aspectj-maven-plugin ${aspectj.plugin.version} + + + org.aspectj + aspectjtools + ${aspectj.version} + + @@ -71,10 +65,12 @@ + ${project.java.version} ${project.java.version} ${project.java.version} - ${project.java.version} - true + ${project.build.sourceEncoding} + true + org.springframework diff --git a/header/pom.xml b/header/pom.xml index 9c7bb823e76..e04d4f41e08 100755 --- a/header/pom.xml +++ b/header/pom.xml @@ -11,34 +11,76 @@ + org.apache.maven.plugins maven-compiler-plugin ${project.compiler.version} - groovy-eclipse-compiler - ${project.java.version} - ${project.java.version} - lines,vars,source + ${project.java.version} true + true - - - org.codehaus.groovy - groovy-eclipse-compiler - ${groovy.eclipse.compiler} - - - org.codehaus.groovy - groovy-eclipse-batch - ${groovy.eclipse.batch} - - + + + + + org.codehaus.gmavenplus + gmavenplus-plugin + 4.2.1 + + + + generate-stubs + process-sources + + generateStubs + + + + + compile-groovy + compile + + compile + + + + + generate-test-stubs + process-test-sources + + generateTestStubs + + + + + compile-test-groovy + test-compile + + compileTests + + + + + ${groovy.version} + ${project.java.version} + + + + org.codehaus.mojo aspectj-maven-plugin ${aspectj.plugin.version} + + + org.aspectj + aspectjtools + ${aspectj.version} + + @@ -47,13 +89,13 @@ - ${project.java.version} ${project.java.version} ${project.java.version} - true - true + ${project.build.sourceEncoding} + true + none org.springframework @@ -66,6 +108,12 @@ + + org.apache.groovy + groovy + ${groovy.version} + + org.hibernate.javax.persistence hibernate-jpa-2.1-api diff --git a/header/src/main/java/org/zstack/header/zql/ASTNode.groovy b/header/src/main/groovy/org/zstack/header/zql/ASTNode.groovy old mode 100755 new mode 100644 similarity index 95% rename from header/src/main/java/org/zstack/header/zql/ASTNode.groovy rename to header/src/main/groovy/org/zstack/header/zql/ASTNode.groovy index 3148ec77ab2..4aa255f21c6 --- a/header/src/main/java/org/zstack/header/zql/ASTNode.groovy +++ b/header/src/main/groovy/org/zstack/header/zql/ASTNode.groovy @@ -1,220 +1,221 @@ -package org.zstack.header.zql - -class ASTNode { - private static final Map> childrenNames = [:] - - List getChildren() { - List childNames - synchronized (childrenNames) { - childNames = childrenNames.get(getClass(), metaClass.getProperties().findAll { ASTNode.isAssignableFrom(it.type) }.collect { it.name }) - } - - return childNames.collect { owner[it] as ASTNode } - } - - Object accept(ASTVisitor visitor) { - return visitor.visit(this) - } - - interface Value { - } - - interface Condition { - } - - interface ReturnWithExpr { - } - - static class Function extends ASTNode { - String functionName - } - - static class QueryTarget extends ASTNode { - String entity - List fields - } - - static class QueryTargetWithFunction extends QueryTarget { - Function function - QueryTargetWithFunction subTarget - List joinClauseList - - static QueryTargetWithFunction valueOf(QueryTarget q) { - return new QueryTargetWithFunction(entity: q.entity, fields: q.fields) - } - - @Override - String getEntity() { - if (subTarget != null) { - return subTarget.getEntity() - } else { - return super.getEntity() - } - } - - @Override - List getFields() { - if (subTarget != null) { - return subTarget.getFields() - } else { - return super.getFields() - } - } - } - - static class ComplexValue extends ASTNode implements Value { - SubQuery subQuery - } - - static class PlainValue extends ASTNode implements Value { - String text - transient Class type - String ctype - } - - static class ListValue extends ASTNode implements Value { - List values - } - - static class Expr extends ASTNode implements Condition { - String operator - List left - Value right - } - - static class LogicalOperator extends ASTNode implements Condition { - String operator - Condition left - Condition right - } - - static class JoinExpr extends ASTNode implements Condition { - QueryTarget left - String operator - QueryTarget right - } - - static class ExprAtom extends ASTNode { - String text - List fields = new ArrayList<>() - QueryTarget queryTarget - Function function - } - - static class OrderByExpr extends ASTNode { - ExprAtom expr - String direction - } - - static class OrderBy extends ASTNode { - List exprs - } - - static class Limit extends ASTNode { - int limit - } - - static class Offset extends ASTNode { - int offset - } - - static class RestrictExpr extends ASTNode { - String entity - String field - String operator - Value value - } - - static class RestrictBy extends ASTNode { - List exprs - } - - static class ReturnWithIDExpr extends ASTNode implements ReturnWithExpr { - List names - } - - static class ReturnWithBlockExpr extends ASTNode implements ReturnWithExpr { - String name - String content - } - - static class ReturnWith extends ASTNode { - List exprs - } - - static class Sum extends Query { - String groupByField - } - - static class GroupByExpr extends ASTNode { - List fields - } - - static class Query extends ASTNode { - QueryTargetWithFunction target - List conditions - RestrictBy restrictBy - ReturnWith returnWith - FilterBy filterBy - OrderBy orderBy - Limit limit - Offset offset - String name - GroupByExpr groupBy - - void addRestrictExpr(RestrictExpr expr) { - if (restrictBy == null) { - restrictBy = new RestrictBy() - } - - if (restrictBy.exprs == null) { - restrictBy.exprs = [] - } - - restrictBy.exprs.add(expr) - } - } - - static class SubQueryTarget extends ASTNode { - String entity - List fields - } - - static class SubQuery extends ASTNode { - SubQueryTarget target - List conditions - } - - static class FilterByExpr extends ASTNode { - String filterName - String content - } - - static class FilterBy extends ASTNode { - List exprs - } - - static class Search extends ASTNode { - Keyword keyword - Index index - RestrictBy restrictBy - Limit limit - Offset offset - } - - static class Keyword extends ASTNode { - String value - } - - static class Index extends ASTNode { - List indexs - } - - static class JoinClause extends ASTNode { - String joinType - String join - QueryTarget queryTarget - String on - List conditions - } -} +package org.zstack.header.zql + +class ASTNode { + private static final Map> childrenNames = [:] + + List getChildren() { + List childNames + synchronized (childrenNames) { + childNames = childrenNames.get(getClass(), metaClass.getProperties().findAll { ASTNode.isAssignableFrom(it.type) }.collect { it.name }) + } + + return childNames.collect { owner[it] as ASTNode } + } + + Object accept(ASTVisitor visitor) { + return visitor.visit(this) + } + + interface Value { + } + + interface Condition { + } + + interface ReturnWithExpr { + } + + static class Function extends ASTNode { + String functionName + } + + static class QueryTarget extends ASTNode { + String entity + List fields + } + + static class QueryTargetWithFunction extends QueryTarget { + Function function + QueryTargetWithFunction subTarget + List joinClauseList + + static QueryTargetWithFunction valueOf(QueryTarget q) { + return new QueryTargetWithFunction(entity: q.entity, fields: q.fields) + } + + @Override + String getEntity() { + if (subTarget != null) { + return subTarget.getEntity() + } else { + return super.getEntity() + } + } + + @Override + List getFields() { + if (subTarget != null) { + return subTarget.getFields() + } else { + return super.getFields() + } + } + } + + static class ComplexValue extends ASTNode implements Value { + SubQuery subQuery + } + + static class PlainValue extends ASTNode implements Value { + String text + transient Class type + String ctype + } + + static class ListValue extends ASTNode implements Value { + List values + } + + static class Expr extends ASTNode implements Condition { + String operator + List left + Value right + } + + static class LogicalOperator extends ASTNode implements Condition { + String operator + Condition left + Condition right + } + + static class JoinExpr extends ASTNode implements Condition { + QueryTarget left + String operator + QueryTarget right + } + + static class ExprAtom extends ASTNode { + String text + List fields = new ArrayList<>() + QueryTarget queryTarget + Function function + } + + static class OrderByExpr extends ASTNode { + ExprAtom expr + String direction + } + + static class OrderBy extends ASTNode { + List exprs + } + + static class Limit extends ASTNode { + int limit + } + + static class Offset extends ASTNode { + int offset + } + + static class RestrictExpr extends ASTNode { + String entity + String field + String operator + Value value + } + + static class RestrictBy extends ASTNode { + List exprs + } + + static class ReturnWithIDExpr extends ASTNode implements ReturnWithExpr { + List names + } + + static class ReturnWithBlockExpr extends ASTNode implements ReturnWithExpr { + String name + String content + } + + static class ReturnWith extends ASTNode { + List exprs + } + + static class Sum extends Query { + String groupByField + } + + static class GroupByExpr extends ASTNode { + List fields + } + + static class Query extends ASTNode { + QueryTargetWithFunction target + List conditions + RestrictBy restrictBy + ReturnWith returnWith + FilterBy filterBy + OrderBy orderBy + Limit limit + Offset offset + String name + GroupByExpr groupBy + + void addRestrictExpr(RestrictExpr expr) { + if (restrictBy == null) { + restrictBy = new RestrictBy() + } + + if (restrictBy.exprs == null) { + restrictBy.exprs = [] + } + + restrictBy.exprs.add(expr) + } + } + + static class SubQueryTarget extends ASTNode { + String entity + List fields + } + + static class SubQuery extends ASTNode { + SubQueryTarget target + List conditions + } + + static class FilterByExpr extends ASTNode { + String filterName + String content + } + + static class FilterBy extends ASTNode { + List exprs + } + + static class Search extends ASTNode { + Keyword keyword + Index index + RestrictBy restrictBy + Limit limit + Offset offset + } + + static class Keyword extends ASTNode { + String value + } + + static class Index extends ASTNode { + List indexs + } + + static class JoinClause extends ASTNode { + String joinType + String join + QueryTarget queryTarget + String on + List conditions + } +} + diff --git a/header/src/main/java/org/zstack/header/zql/ASTVisitor.groovy b/header/src/main/groovy/org/zstack/header/zql/ASTVisitor.groovy old mode 100755 new mode 100644 similarity index 95% rename from header/src/main/java/org/zstack/header/zql/ASTVisitor.groovy rename to header/src/main/groovy/org/zstack/header/zql/ASTVisitor.groovy index a3fe304ce34..9a5130f80ff --- a/header/src/main/java/org/zstack/header/zql/ASTVisitor.groovy +++ b/header/src/main/groovy/org/zstack/header/zql/ASTVisitor.groovy @@ -1,5 +1,6 @@ -package org.zstack.header.zql - -interface ASTVisitor { - T visit(K node) -} +package org.zstack.header.zql + +interface ASTVisitor { + T visit(K node) +} + diff --git a/header/src/main/java/org/zstack/header/aspect/OwnedByAccountAspect.aj b/header/src/main/java/org/zstack/header/aspect/OwnedByAccountAspect.aj index 944c3c20229..260d8d77af8 100644 --- a/header/src/main/java/org/zstack/header/aspect/OwnedByAccountAspect.aj +++ b/header/src/main/java/org/zstack/header/aspect/OwnedByAccountAspect.aj @@ -1,44 +1,44 @@ -package org.zstack.header.aspect; - -import org.zstack.header.identity.OwnedByAccount; -import org.zstack.header.vo.ResourceVO; -import org.zstack.utils.Utils; -import org.zstack.utils.logging.CLogger; - -import javax.persistence.EntityManager; -import java.util.function.Function; - -public aspect OwnedByAccountAspect { - private static final CLogger logger = Utils.getLogger(OwnedByAccountAspect.class); - - private static Function accountUuidGetter; - - public static Function getAccountUuidGetter() { - return accountUuidGetter; - } - - public static void setAccountUuidGetter(Function accountUuidGetter) { - OwnedByAccountAspect.accountUuidGetter = accountUuidGetter; - } - - Object around(OwnedByAccount oa) : this(oa) && execution(java.lang.String OwnedByAccount+.getAccountUuid()) { - Object accountUuid = proceed(oa); - - if (accountUuid == null) { - accountUuid = accountUuidGetter.apply(((ResourceVO) oa).getUuid()); - } - - return accountUuid; - } - - after(EntityManager mgr, Object entity) : call(void EntityManager+.persist(Object)) - && target(mgr) - && args(entity) { - if (!(entity instanceof OwnedByAccount)) { - return; - } - - OwnedByAccount oa = (OwnedByAccount) entity; - OwnedByAccountAspectHelper.createAccountResourceRefVO(oa, mgr, entity); - } -} \ No newline at end of file +package org.zstack.header.aspect; + +import org.zstack.header.identity.OwnedByAccount; +import org.zstack.header.vo.ResourceVO; +import org.zstack.utils.Utils; +import org.zstack.utils.logging.CLogger; + +import javax.persistence.EntityManager; +import java.util.function.Function; + +public aspect OwnedByAccountAspect { + private static final CLogger logger = Utils.getLogger(OwnedByAccountAspect.class); + + private static Function accountUuidGetter; + + public static Function getAccountUuidGetter() { + return accountUuidGetter; + } + + public static void setAccountUuidGetter(Function accountUuidGetter) { + OwnedByAccountAspect.accountUuidGetter = accountUuidGetter; + } + + Object around(OwnedByAccount oa) : this(oa) && execution(java.lang.String OwnedByAccount+.getAccountUuid()) { + Object accountUuid = proceed(oa); + + if (accountUuid == null) { + accountUuid = accountUuidGetter.apply(((ResourceVO) oa).getUuid()); + } + + return accountUuid; + } + + after(EntityManager mgr, Object entity) : call(void EntityManager+.persist(Object)) + && target(mgr) + && args(entity) { + if (!(entity instanceof OwnedByAccount)) { + return; + } + + OwnedByAccount oa = (OwnedByAccount) entity; + OwnedByAccountAspectHelper.createAccountResourceRefVO(oa, mgr, entity); + } +} diff --git a/header/src/main/java/org/zstack/header/core/encrypt/EncryptionIntegrityInventory.java b/header/src/main/java/org/zstack/header/core/encrypt/EncryptionIntegrityInventory.java index 5d2aa5f5ef6..695684e2187 100644 --- a/header/src/main/java/org/zstack/header/core/encrypt/EncryptionIntegrityInventory.java +++ b/header/src/main/java/org/zstack/header/core/encrypt/EncryptionIntegrityInventory.java @@ -2,7 +2,6 @@ import org.zstack.header.configuration.PythonClassInventory; import org.zstack.header.search.Inventory; -import sun.awt.PlatformFont; import java.io.Serializable; import java.sql.Timestamp; diff --git a/header/src/main/java/org/zstack/header/core/workflow/CheckFlow.java b/header/src/main/java/org/zstack/header/core/workflow/CheckFlow.java index 2999ca32209..09cdae37476 100644 --- a/header/src/main/java/org/zstack/header/core/workflow/CheckFlow.java +++ b/header/src/main/java/org/zstack/header/core/workflow/CheckFlow.java @@ -15,7 +15,7 @@ public abstract class CheckFlow implements Flow { @Override public void run(FlowTrigger trigger, Map data) { try { - targetFlow = getTargetFlow().newInstance(); + targetFlow = getTargetFlow().getConstructor().newInstance(); } catch (Exception e){ throw new RuntimeException(e); } diff --git a/identity/pom.xml b/identity/pom.xml index 8f963f0e697..3877b727408 100755 --- a/identity/pom.xml +++ b/identity/pom.xml @@ -1,96 +1,92 @@ - - 4.0.0 - - zstack - org.zstack + + 4.0.0 + + zstack + org.zstack 5.5.0 - .. - - identity - - - org.zstack - header - ${project.version} - - - org.zstack - core - ${project.version} - - - org.zstack - utils - ${project.version} - - - org.zstack - search - ${project.version} - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - ${project.compiler.version} - - groovy-eclipse-compiler - ${project.java.version} - ${project.java.version} - lines,vars,source - true - - - - org.codehaus.groovy - groovy-eclipse-compiler - ${groovy.eclipse.compiler} - - - org.codehaus.groovy - groovy-eclipse-batch - ${groovy.eclipse.batch} - - - - - - org.codehaus.mojo - aspectj-maven-plugin - ${aspectj.plugin.version} - - - - compile - test-compile - - - - - ${project.java.version} - ${project.java.version} - ${project.java.version} - true - - - org.springframework - spring-aspects - - - org.zstack - core - - - org.zstack - header - - - - - - - + .. + + identity + + + org.zstack + header + ${project.version} + + + org.zstack + core + ${project.version} + + + org.zstack + utils + ${project.version} + + + org.zstack + search + ${project.version} + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${project.compiler.version} + + ${project.java.version} + true + true + + + + + + org.codehaus.mojo + aspectj-maven-plugin + ${aspectj.plugin.version} + + + org.aspectj + aspectjtools + ${aspectj.version} + + + + + + compile + test-compile + + + + + ${project.java.version} + ${project.java.version} + ${project.java.version} + ${project.build.sourceEncoding} + true + + + + org.springframework + spring-aspects + + + org.zstack + core + + + org.zstack + header + + + + + + + diff --git a/identity/src/main/java/org/zstack/identity/AccountManagerImpl.java b/identity/src/main/java/org/zstack/identity/AccountManagerImpl.java index e11ee611ffe..8a411d7254b 100755 --- a/identity/src/main/java/org/zstack/identity/AccountManagerImpl.java +++ b/identity/src/main/java/org/zstack/identity/AccountManagerImpl.java @@ -426,7 +426,7 @@ private void handle(APICheckApiPermissionMsg msg) { for (String apiName : msg.getApiNames()) { try { Class apiClass = Class.forName(apiName); - APIMessage api = (APIMessage) apiClass.newInstance(); + APIMessage api = (APIMessage) apiClass.getConstructor().newInstance(); api.setSession(session); try { diff --git a/image/pom.xml b/image/pom.xml index 63bdc6a064f..6ad08850719 100755 --- a/image/pom.xml +++ b/image/pom.xml @@ -1,115 +1,111 @@ - - 4.0.0 - - zstack - org.zstack + + 4.0.0 + + zstack + org.zstack 5.5.0 - .. - - image - - - - org.zstack - core - ${project.version} - - - org.zstack - utils - ${project.version} - - - org.zstack - search - ${project.version} - - - org.zstack - identity - ${project.version} - - - org.zstack - header - ${project.version} - - - org.zstack - tag - ${project.version} - - - org.zstack - compute - ${project.version} - - - org.zstack - longjob - ${project.version} - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - ${project.compiler.version} - - groovy-eclipse-compiler - ${project.java.version} - ${project.java.version} - lines,vars,source - true - - - - org.codehaus.groovy - groovy-eclipse-compiler - ${groovy.eclipse.compiler} - - - org.codehaus.groovy - groovy-eclipse-batch - ${groovy.eclipse.batch} - - - - - org.codehaus.mojo - aspectj-maven-plugin - ${aspectj.plugin.version} - - - - compile - test-compile - - - - - ${project.java.version} - ${project.java.version} - ${project.java.version} - true - - - org.springframework - spring-aspects - - - org.zstack - core - - - org.zstack - header - - - - - - - + .. + + image + + + + org.zstack + core + ${project.version} + + + org.zstack + utils + ${project.version} + + + org.zstack + search + ${project.version} + + + org.zstack + identity + ${project.version} + + + org.zstack + header + ${project.version} + + + org.zstack + tag + ${project.version} + + + org.zstack + compute + ${project.version} + + + org.zstack + longjob + ${project.version} + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${project.compiler.version} + + ${project.java.version} + true + true + + + + + org.codehaus.mojo + aspectj-maven-plugin + ${aspectj.plugin.version} + + + org.aspectj + aspectjtools + ${aspectj.version} + + + + + + compile + test-compile + + + + + ${project.java.version} + ${project.java.version} + ${project.java.version} + ${project.build.sourceEncoding} + true + + + + org.springframework + spring-aspects + + + org.zstack + core + + + org.zstack + header + + + + + + + diff --git a/image/src/main/java/org/zstack/image/ImageManagerImpl.java b/image/src/main/java/org/zstack/image/ImageManagerImpl.java index 08e8b92a552..16736fa4e2e 100755 --- a/image/src/main/java/org/zstack/image/ImageManagerImpl.java +++ b/image/src/main/java/org/zstack/image/ImageManagerImpl.java @@ -75,7 +75,6 @@ import javax.persistence.Tuple; import javax.persistence.TypedQuery; -import javax.xml.ws.ResponseWrapper; import java.net.URI; import java.net.URISyntaxException; import java.sql.Timestamp; diff --git a/longjob/pom.xml b/longjob/pom.xml index 3006e2f90a4..3594448f78b 100755 --- a/longjob/pom.xml +++ b/longjob/pom.xml @@ -1,110 +1,106 @@ - - 4.0.0 - - zstack - org.zstack + + 4.0.0 + + zstack + org.zstack 5.5.0 - .. - - longjob - - - - org.zstack - core - ${project.version} - - - org.zstack - utils - ${project.version} - - - org.zstack - search - ${project.version} - - - org.zstack - identity - ${project.version} - - - org.zstack - header - ${project.version} - - - org.zstack - tag - ${project.version} - - - org.zstack - portal - ${project.version} - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - ${project.compiler.version} - - groovy-eclipse-compiler - ${project.java.version} - ${project.java.version} - lines,vars,source - true - - - - org.codehaus.groovy - groovy-eclipse-compiler - ${groovy.eclipse.compiler} - - - org.codehaus.groovy - groovy-eclipse-batch - ${groovy.eclipse.batch} - - - - - org.codehaus.mojo - aspectj-maven-plugin - ${aspectj.plugin.version} - - - - compile - test-compile - - - - - ${project.java.version} - ${project.java.version} - ${project.java.version} - true - - - org.springframework - spring-aspects - - - org.zstack - core - - - org.zstack - header - - - - - - - + .. + + longjob + + + + org.zstack + core + ${project.version} + + + org.zstack + utils + ${project.version} + + + org.zstack + search + ${project.version} + + + org.zstack + identity + ${project.version} + + + org.zstack + header + ${project.version} + + + org.zstack + tag + ${project.version} + + + org.zstack + portal + ${project.version} + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${project.compiler.version} + + ${project.java.version} + true + true + + + + + org.codehaus.mojo + aspectj-maven-plugin + ${aspectj.plugin.version} + + + org.aspectj + aspectjtools + ${aspectj.version} + + + + + + compile + test-compile + + + + + ${project.java.version} + ${project.java.version} + ${project.java.version} + ${project.build.sourceEncoding} + true + + + + org.springframework + spring-aspects + + + org.zstack + core + + + org.zstack + header + + + + + + + diff --git a/longjob/src/main/java/org/zstack/longjob/LongJobFactoryImpl.java b/longjob/src/main/java/org/zstack/longjob/LongJobFactoryImpl.java index bf73119e693..50d5c7244e5 100755 --- a/longjob/src/main/java/org/zstack/longjob/LongJobFactoryImpl.java +++ b/longjob/src/main/java/org/zstack/longjob/LongJobFactoryImpl.java @@ -10,6 +10,7 @@ import org.zstack.utils.Utils; import org.zstack.utils.logging.CLogger; +import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.HashSet; import java.util.Set; @@ -50,8 +51,8 @@ public boolean start() { for (Class it : longJobClasses) { LongJobFor at = (LongJobFor) it.getAnnotation(LongJobFor.class); try { - job = (LongJob) it.newInstance(); - } catch (InstantiationException | IllegalAccessException e) { + job = (LongJob) it.getConstructor().newInstance(); + } catch (InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) { e.printStackTrace(); } if (null == job) { diff --git a/longjob/src/main/java/org/zstack/longjob/LongJobManagerImpl.java b/longjob/src/main/java/org/zstack/longjob/LongJobManagerImpl.java index 975b0e711db..87d3d606551 100755 --- a/longjob/src/main/java/org/zstack/longjob/LongJobManagerImpl.java +++ b/longjob/src/main/java/org/zstack/longjob/LongJobManagerImpl.java @@ -45,6 +45,7 @@ import org.zstack.utils.logging.CLogger; import javax.persistence.Tuple; +import java.lang.reflect.InvocationTargetException; import java.sql.SQLNonTransientConnectionException; import java.sql.Timestamp; import java.time.LocalDateTime; @@ -1022,8 +1023,8 @@ public Long getApiTimeout() { private long getMessageTimeout(Class clz) { try { - return timeoutMgr.getMessageTimeout(clz.newInstance()); - } catch (InstantiationException | IllegalAccessException e) { + return timeoutMgr.getMessageTimeout(clz.getConstructor().newInstance()); + } catch (InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) { throw new CloudRuntimeException(e); } } diff --git a/network/pom.xml b/network/pom.xml index d51e13e2245..47e27bd3362 100755 --- a/network/pom.xml +++ b/network/pom.xml @@ -1,109 +1,105 @@ - - 4.0.0 - - zstack - org.zstack + + 4.0.0 + + zstack + org.zstack 5.5.0 - .. - - network - - - org.zstack - core - ${project.version} - - - org.zstack - utils - ${project.version} - - - org.zstack - search - ${project.version} - - - org.zstack - identity - ${project.version} - - - org.zstack - header - ${project.version} - - - org.zstack - tag - ${project.version} - - - org.zstack - resourceconfig - ${project.version} - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - ${project.compiler.version} - - groovy-eclipse-compiler - ${project.java.version} - ${project.java.version} - lines,vars,source - true - - - - org.codehaus.groovy - groovy-eclipse-compiler - ${groovy.eclipse.compiler} - - - org.codehaus.groovy - groovy-eclipse-batch - ${groovy.eclipse.batch} - - - - - org.codehaus.mojo - aspectj-maven-plugin - ${aspectj.plugin.version} - - - - compile - test-compile - - - - - ${project.java.version} - ${project.java.version} - ${project.java.version} - true - - - org.springframework - spring-aspects - - - org.zstack - core - - - org.zstack - header - - - - - - - + .. + + network + + + org.zstack + core + ${project.version} + + + org.zstack + utils + ${project.version} + + + org.zstack + search + ${project.version} + + + org.zstack + identity + ${project.version} + + + org.zstack + header + ${project.version} + + + org.zstack + tag + ${project.version} + + + org.zstack + resourceconfig + ${project.version} + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${project.compiler.version} + + ${project.java.version} + true + true + + + + + org.codehaus.mojo + aspectj-maven-plugin + ${aspectj.plugin.version} + + + org.aspectj + aspectjtools + ${aspectj.version} + + + + + + compile + test-compile + + + + + ${project.java.version} + ${project.java.version} + ${project.java.version} + ${project.build.sourceEncoding} + true + + + + org.springframework + spring-aspects + + + org.zstack + core + + + org.zstack + header + + + + + + + diff --git a/plugin/acl/pom.xml b/plugin/acl/pom.xml index 9653ec4e982..a616caab80c 100644 --- a/plugin/acl/pom.xml +++ b/plugin/acl/pom.xml @@ -25,29 +25,42 @@ maven-compiler-plugin ${project.compiler.version} - groovy-eclipse-compiler - ${project.java.version} - ${project.java.version} - lines,vars,source + ${project.java.version} true + true + + + + + + org.codehaus.gmavenplus + gmavenplus-plugin + 4.2.1 + + + + generateStubs + compile + + + + + ${groovy.version} + ${project.java.version} - - - org.codehaus.groovy - groovy-eclipse-compiler - ${groovy.eclipse.compiler} - - - org.codehaus.groovy - groovy-eclipse-batch - ${groovy.eclipse.batch} - - + org.codehaus.mojo aspectj-maven-plugin ${aspectj.plugin.version} + + + org.aspectj + aspectjtools + ${aspectj.version} + + @@ -57,10 +70,12 @@ + ${project.java.version} ${project.java.version} ${project.java.version} - ${project.java.version} - true + ${project.build.sourceEncoding} + true + org.springframework diff --git a/plugin/applianceVm/pom.xml b/plugin/applianceVm/pom.xml index 72613eb9881..2dbb8230d45 100755 --- a/plugin/applianceVm/pom.xml +++ b/plugin/applianceVm/pom.xml @@ -36,29 +36,41 @@ maven-compiler-plugin ${project.compiler.version} - groovy-eclipse-compiler - ${project.java.version} - ${project.java.version} - lines,vars,source + ${project.java.version} true + true - - - org.codehaus.groovy - groovy-eclipse-compiler - ${groovy.eclipse.compiler} - - - org.codehaus.groovy - groovy-eclipse-batch - ${groovy.eclipse.batch} - - + + + org.codehaus.gmavenplus + gmavenplus-plugin + 4.2.1 + + + + generateStubs + compile + + + + + ${groovy.version} + ${project.java.version} + + + org.codehaus.mojo aspectj-maven-plugin ${aspectj.plugin.version} + + + org.aspectj + aspectjtools + ${aspectj.version} + + @@ -68,10 +80,12 @@ + ${project.java.version} ${project.java.version} ${project.java.version} - ${project.java.version} - true + ${project.build.sourceEncoding} + true + org.springframework diff --git a/plugin/cbd/pom.xml b/plugin/cbd/pom.xml index 119a099cab4..62bfdc7e637 100644 --- a/plugin/cbd/pom.xml +++ b/plugin/cbd/pom.xml @@ -36,29 +36,41 @@ maven-compiler-plugin ${project.compiler.version} - groovy-eclipse-compiler - ${project.java.version} - ${project.java.version} - lines,vars,source + ${project.java.version} true + true - - - org.codehaus.groovy - groovy-eclipse-compiler - ${groovy.eclipse.compiler} - - - org.codehaus.groovy - groovy-eclipse-batch - ${groovy.eclipse.batch} - - + + + org.codehaus.gmavenplus + gmavenplus-plugin + 4.2.1 + + + + generateStubs + compile + + + + + ${groovy.version} + ${project.java.version} + + + org.codehaus.mojo aspectj-maven-plugin ${aspectj.plugin.version} + + + org.aspectj + aspectjtools + ${aspectj.version} + + @@ -68,10 +80,12 @@ + ${project.java.version} ${project.java.version} ${project.java.version} - ${project.java.version} - true + ${project.build.sourceEncoding} + true + org.springframework diff --git a/plugin/ceph/pom.xml b/plugin/ceph/pom.xml index 6370dc22be9..4112cd22fb4 100755 --- a/plugin/ceph/pom.xml +++ b/plugin/ceph/pom.xml @@ -35,29 +35,42 @@ maven-compiler-plugin ${project.compiler.version} - groovy-eclipse-compiler - ${project.java.version} - ${project.java.version} - lines,vars,source + ${project.java.version} true + true + + + + + + org.codehaus.gmavenplus + gmavenplus-plugin + 4.2.1 + + + + generateStubs + compile + + + + + ${groovy.version} + ${project.java.version} - - - org.codehaus.groovy - groovy-eclipse-compiler - ${groovy.eclipse.compiler} - - - org.codehaus.groovy - groovy-eclipse-batch - ${groovy.eclipse.batch} - - + org.codehaus.mojo aspectj-maven-plugin ${aspectj.plugin.version} + + + org.aspectj + aspectjtools + ${aspectj.version} + + @@ -67,10 +80,12 @@ + ${project.java.version} ${project.java.version} ${project.java.version} - ${project.java.version} - true + ${project.build.sourceEncoding} + true + org.springframework diff --git a/plugin/directory/pom.xml b/plugin/directory/pom.xml index ae7c46506f2..cec8db61681 100644 --- a/plugin/directory/pom.xml +++ b/plugin/directory/pom.xml @@ -18,29 +18,42 @@ maven-compiler-plugin ${project.compiler.version} - groovy-eclipse-compiler - ${project.java.version} - ${project.java.version} - lines,vars,source + ${project.java.version} true + true + + + + + + org.codehaus.gmavenplus + gmavenplus-plugin + 4.2.1 + + + + generateStubs + compile + + + + + ${groovy.version} + ${project.java.version} - - - org.codehaus.groovy - groovy-eclipse-compiler - ${groovy.eclipse.compiler} - - - org.codehaus.groovy - groovy-eclipse-batch - ${groovy.eclipse.batch} - - + org.codehaus.mojo aspectj-maven-plugin ${aspectj.plugin.version} + + + org.aspectj + aspectjtools + ${aspectj.version} + + @@ -50,10 +63,12 @@ + ${project.java.version} ${project.java.version} ${project.java.version} - ${project.java.version} - true + ${project.build.sourceEncoding} + true + org.springframework diff --git a/plugin/eip/pom.xml b/plugin/eip/pom.xml index 3102f1b8735..89926e8181a 100755 --- a/plugin/eip/pom.xml +++ b/plugin/eip/pom.xml @@ -36,29 +36,41 @@ maven-compiler-plugin ${project.compiler.version} - groovy-eclipse-compiler - ${project.java.version} - ${project.java.version} - lines,vars,source + ${project.java.version} true + true - - - org.codehaus.groovy - groovy-eclipse-compiler - ${groovy.eclipse.compiler} - - - org.codehaus.groovy - groovy-eclipse-batch - ${groovy.eclipse.batch} - - + + + org.codehaus.gmavenplus + gmavenplus-plugin + 4.2.1 + + + + generateStubs + compile + + + + + ${groovy.version} + ${project.java.version} + + + org.codehaus.mojo aspectj-maven-plugin ${aspectj.plugin.version} + + + org.aspectj + aspectjtools + ${aspectj.version} + + @@ -68,10 +80,12 @@ + ${project.java.version} ${project.java.version} ${project.java.version} - ${project.java.version} - true + ${project.build.sourceEncoding} + true + org.springframework diff --git a/plugin/expon/pom.xml b/plugin/expon/pom.xml index 316de64b651..2fbc0a59a2f 100644 --- a/plugin/expon/pom.xml +++ b/plugin/expon/pom.xml @@ -51,29 +51,41 @@ maven-compiler-plugin ${project.compiler.version} - groovy-eclipse-compiler - ${project.java.version} - ${project.java.version} - lines,vars,source + ${project.java.version} true + true - - - org.codehaus.groovy - groovy-eclipse-compiler - ${groovy.eclipse.compiler} - - - org.codehaus.groovy - groovy-eclipse-batch - ${groovy.eclipse.batch} - - + + + org.codehaus.gmavenplus + gmavenplus-plugin + 4.2.1 + + + + generateStubs + compile + + + + + ${groovy.version} + ${project.java.version} + + + org.codehaus.mojo aspectj-maven-plugin ${aspectj.plugin.version} + + + org.aspectj + aspectjtools + ${aspectj.version} + + @@ -83,10 +95,12 @@ + ${project.java.version} ${project.java.version} ${project.java.version} - ${project.java.version} - true + ${project.build.sourceEncoding} + true + org.springframework diff --git a/plugin/externalStorage/pom.xml b/plugin/externalStorage/pom.xml index cd633512dd1..4fd06dd3004 100644 --- a/plugin/externalStorage/pom.xml +++ b/plugin/externalStorage/pom.xml @@ -29,29 +29,41 @@ maven-compiler-plugin ${project.compiler.version} - groovy-eclipse-compiler - ${project.java.version} - ${project.java.version} - lines,vars,source + ${project.java.version} true + true - - - org.codehaus.groovy - groovy-eclipse-compiler - ${groovy.eclipse.compiler} - - - org.codehaus.groovy - groovy-eclipse-batch - ${groovy.eclipse.batch} - - + + + org.codehaus.gmavenplus + gmavenplus-plugin + 4.2.1 + + + + generateStubs + compile + + + + + ${groovy.version} + ${project.java.version} + + + org.codehaus.mojo aspectj-maven-plugin ${aspectj.plugin.version} + + + org.aspectj + aspectjtools + ${aspectj.version} + + @@ -61,10 +73,11 @@ + ${project.java.version} ${project.java.version} ${project.java.version} - ${project.java.version} - true + ${project.build.sourceEncoding} + true org.springframework diff --git a/plugin/flatNetworkProvider/pom.xml b/plugin/flatNetworkProvider/pom.xml index 788c095401b..a5908c22a5f 100755 --- a/plugin/flatNetworkProvider/pom.xml +++ b/plugin/flatNetworkProvider/pom.xml @@ -40,29 +40,41 @@ maven-compiler-plugin ${project.compiler.version} - groovy-eclipse-compiler - ${project.java.version} - ${project.java.version} - lines,vars,source + ${project.java.version} true + true - - - org.codehaus.groovy - groovy-eclipse-compiler - ${groovy.eclipse.compiler} - - - org.codehaus.groovy - groovy-eclipse-batch - ${groovy.eclipse.batch} - - + + + org.codehaus.gmavenplus + gmavenplus-plugin + 4.2.1 + + + + generateStubs + compile + + + + + ${groovy.version} + ${project.java.version} + + + org.codehaus.mojo aspectj-maven-plugin ${aspectj.plugin.version} + + + org.aspectj + aspectjtools + ${aspectj.version} + + @@ -72,10 +84,12 @@ + ${project.java.version} ${project.java.version} ${project.java.version} - ${project.java.version} - true + ${project.build.sourceEncoding} + true + org.springframework diff --git a/plugin/hostNetworkInterface/pom.xml b/plugin/hostNetworkInterface/pom.xml index 9519574c0fe..21630b0523a 100644 --- a/plugin/hostNetworkInterface/pom.xml +++ b/plugin/hostNetworkInterface/pom.xml @@ -50,29 +50,41 @@ maven-compiler-plugin ${project.compiler.version} - groovy-eclipse-compiler - ${project.java.version} - ${project.java.version} - lines,vars,source + ${project.java.version} true + true - - - org.codehaus.groovy - groovy-eclipse-compiler - ${groovy.eclipse.compiler} - - - org.codehaus.groovy - groovy-eclipse-batch - ${groovy.eclipse.batch} - - + + + org.codehaus.gmavenplus + gmavenplus-plugin + 4.2.1 + + + + generateStubs + compile + + + + + ${groovy.version} + ${project.java.version} + + + org.codehaus.mojo aspectj-maven-plugin ${aspectj.plugin.version} + + + org.aspectj + aspectjtools + ${aspectj.version} + + @@ -82,10 +94,12 @@ + ${project.java.version} ${project.java.version} ${project.java.version} - ${project.java.version} - true + ${project.build.sourceEncoding} + true + org.springframework diff --git a/plugin/iscsi/pom.xml b/plugin/iscsi/pom.xml index 46dd095fe15..e276012c778 100644 --- a/plugin/iscsi/pom.xml +++ b/plugin/iscsi/pom.xml @@ -35,29 +35,41 @@ maven-compiler-plugin ${project.compiler.version} - groovy-eclipse-compiler - ${project.java.version} - ${project.java.version} - lines,vars,source + ${project.java.version} true + true - - - org.codehaus.groovy - groovy-eclipse-compiler - ${groovy.eclipse.compiler} - - - org.codehaus.groovy - groovy-eclipse-batch - ${groovy.eclipse.batch} - - + + + org.codehaus.gmavenplus + gmavenplus-plugin + 4.2.1 + + + + generateStubs + compile + + + + + ${groovy.version} + ${project.java.version} + + + org.codehaus.mojo aspectj-maven-plugin ${aspectj.plugin.version} + + + org.aspectj + aspectjtools + ${aspectj.version} + + @@ -67,10 +79,12 @@ + ${project.java.version} ${project.java.version} ${project.java.version} - ${project.java.version} - true + ${project.build.sourceEncoding} + true + org.springframework diff --git a/plugin/kvm/pom.xml b/plugin/kvm/pom.xml index 73e4c81afe3..0a32d04e9f0 100755 --- a/plugin/kvm/pom.xml +++ b/plugin/kvm/pom.xml @@ -1,100 +1,115 @@ - - 4.0.0 - - plugin - org.zstack + + 4.0.0 + + plugin + org.zstack 5.5.0 - .. - - kvm - - - org.zstack - compute - ${project.version} - - - org.zstack - securityGroup - ${project.version} - - - org.zstack - console - ${project.version} - - - org.zstack - resourceconfig - ${project.version} - - - org.apache.maven - maven-artifact - 3.0.5 - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - ${project.compiler.version} - - groovy-eclipse-compiler - ${project.java.version} - ${project.java.version} - lines,vars,source - true - - - - org.codehaus.groovy - groovy-eclipse-compiler - ${groovy.eclipse.compiler} - - - org.codehaus.groovy - groovy-eclipse-batch - ${groovy.eclipse.batch} - - - - - org.codehaus.mojo - aspectj-maven-plugin - ${aspectj.plugin.version} - - - - compile - test-compile - - - - - ${project.java.version} - ${project.java.version} - ${project.java.version} - true - - - org.springframework - spring-aspects - - - org.zstack - core - - - org.zstack - header - - - - - - - + .. + + kvm + + + org.zstack + compute + ${project.version} + + + org.zstack + securityGroup + ${project.version} + + + org.zstack + console + ${project.version} + + + org.zstack + resourceconfig + ${project.version} + + + org.apache.maven + maven-artifact + 3.0.5 + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${project.compiler.version} + + ${project.java.version} + true + true + + + + + + org.codehaus.gmavenplus + gmavenplus-plugin + 4.2.1 + + + + generateStubs + compile + + + + + ${groovy.version} + ${project.java.version} + + + + + org.codehaus.mojo + aspectj-maven-plugin + ${aspectj.plugin.version} + + + org.aspectj + aspectjtools + ${aspectj.version} + + + + + + compile + test-compile + + + + + ${project.java.version} + ${project.java.version} + ${project.java.version} + ${project.build.sourceEncoding} + true + + + + org.springframework + spring-aspects + + + org.zstack + core + + + org.zstack + header + + + + + + + diff --git a/plugin/ldap/pom.xml b/plugin/ldap/pom.xml index dd2b61b30f1..7f9ca9d6cd8 100755 --- a/plugin/ldap/pom.xml +++ b/plugin/ldap/pom.xml @@ -18,29 +18,41 @@ maven-compiler-plugin ${project.compiler.version} - groovy-eclipse-compiler - ${project.java.version} - ${project.java.version} - lines,vars,source + ${project.java.version} true + true - - - org.codehaus.groovy - groovy-eclipse-compiler - ${groovy.eclipse.compiler} - - - org.codehaus.groovy - groovy-eclipse-batch - ${groovy.eclipse.batch} - - + + + org.codehaus.gmavenplus + gmavenplus-plugin + 4.2.1 + + + + generateStubs + compile + + + + + ${groovy.version} + ${project.java.version} + + + org.codehaus.mojo aspectj-maven-plugin ${aspectj.plugin.version} + + + org.aspectj + aspectjtools + ${aspectj.version} + + @@ -50,10 +62,12 @@ + ${project.java.version} ${project.java.version} ${project.java.version} - ${project.java.version} - true + ${project.build.sourceEncoding} + true + org.springframework diff --git a/plugin/loadBalancer/pom.xml b/plugin/loadBalancer/pom.xml index c16119dec18..beac6c0d4b4 100755 --- a/plugin/loadBalancer/pom.xml +++ b/plugin/loadBalancer/pom.xml @@ -41,29 +41,41 @@ maven-compiler-plugin ${project.compiler.version} - groovy-eclipse-compiler - ${project.java.version} - ${project.java.version} - lines,vars,source + ${project.java.version} true + true - - - org.codehaus.groovy - groovy-eclipse-compiler - ${groovy.eclipse.compiler} - - - org.codehaus.groovy - groovy-eclipse-batch - ${groovy.eclipse.batch} - - + + + org.codehaus.gmavenplus + gmavenplus-plugin + 4.2.1 + + + + generateStubs + compile + + + + + ${groovy.version} + ${project.java.version} + + + org.codehaus.mojo aspectj-maven-plugin ${aspectj.plugin.version} + + + org.aspectj + aspectjtools + ${aspectj.version} + + @@ -73,10 +85,12 @@ + ${project.java.version} ${project.java.version} ${project.java.version} - ${project.java.version} - true + ${project.build.sourceEncoding} + true + org.springframework diff --git a/plugin/localstorage/pom.xml b/plugin/localstorage/pom.xml index 24bb83bd960..f41b76f70e6 100755 --- a/plugin/localstorage/pom.xml +++ b/plugin/localstorage/pom.xml @@ -35,29 +35,41 @@ maven-compiler-plugin ${project.compiler.version} - groovy-eclipse-compiler - ${project.java.version} - ${project.java.version} - lines,vars,source + ${project.java.version} true + true - - - org.codehaus.groovy - groovy-eclipse-compiler - ${groovy.eclipse.compiler} - - - org.codehaus.groovy - groovy-eclipse-batch - ${groovy.eclipse.batch} - - + + + org.codehaus.gmavenplus + gmavenplus-plugin + 4.2.1 + + + + generateStubs + compile + + + + + ${groovy.version} + ${project.java.version} + + + org.codehaus.mojo aspectj-maven-plugin ${aspectj.plugin.version} + + + org.aspectj + aspectjtools + ${aspectj.version} + + @@ -67,10 +79,12 @@ + ${project.java.version} ${project.java.version} ${project.java.version} - ${project.java.version} - true + ${project.build.sourceEncoding} + true + org.springframework diff --git a/plugin/loginPlugin/pom.xml b/plugin/loginPlugin/pom.xml index 7b58aa30f8a..b0dc2777003 100644 --- a/plugin/loginPlugin/pom.xml +++ b/plugin/loginPlugin/pom.xml @@ -38,29 +38,41 @@ maven-compiler-plugin ${project.compiler.version} - groovy-eclipse-compiler - ${project.java.version} - ${project.java.version} - lines,vars,source + ${project.java.version} true + true - - - org.codehaus.groovy - groovy-eclipse-compiler - ${groovy.eclipse.compiler} - - - org.codehaus.groovy - groovy-eclipse-batch - ${groovy.eclipse.batch} - - + + + org.codehaus.gmavenplus + gmavenplus-plugin + 4.2.1 + + + + generateStubs + compile + + + + + ${groovy.version} + ${project.java.version} + + + org.codehaus.mojo aspectj-maven-plugin ${aspectj.plugin.version} + + + org.aspectj + aspectjtools + ${aspectj.version} + + @@ -70,10 +82,12 @@ + ${project.java.version} ${project.java.version} ${project.java.version} - ${project.java.version} - true + ${project.build.sourceEncoding} + true + org.springframework diff --git a/plugin/mediator/pom.xml b/plugin/mediator/pom.xml index ea2e6d03ebf..37571225c49 100755 --- a/plugin/mediator/pom.xml +++ b/plugin/mediator/pom.xml @@ -46,29 +46,41 @@ maven-compiler-plugin ${project.compiler.version} - groovy-eclipse-compiler - ${project.java.version} - ${project.java.version} - lines,vars,source + ${project.java.version} true + true - - - org.codehaus.groovy - groovy-eclipse-compiler - ${groovy.eclipse.compiler} - - - org.codehaus.groovy - groovy-eclipse-batch - ${groovy.eclipse.batch} - - + + + org.codehaus.gmavenplus + gmavenplus-plugin + 4.2.1 + + + + generateStubs + compile + + + + + ${groovy.version} + ${project.java.version} + + + org.codehaus.mojo aspectj-maven-plugin ${aspectj.plugin.version} + + + org.aspectj + aspectjtools + ${aspectj.version} + + @@ -78,10 +90,12 @@ + ${project.java.version} ${project.java.version} ${project.java.version} - ${project.java.version} - true + ${project.build.sourceEncoding} + true + org.springframework diff --git a/plugin/nfsPrimaryStorage/pom.xml b/plugin/nfsPrimaryStorage/pom.xml index 36bb5f3fcc5..4222e643031 100755 --- a/plugin/nfsPrimaryStorage/pom.xml +++ b/plugin/nfsPrimaryStorage/pom.xml @@ -1,90 +1,104 @@ - - 4.0.0 - - plugin - org.zstack + + 4.0.0 + + plugin + org.zstack 5.5.0 - .. - - nfsPrimaryStorage - - - org.zstack - kvm - ${project.version} - - - org.zstack - sftpBackupStorage - ${project.version} - - - org.zstack - storage - ${project.version} - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - ${project.compiler.version} - - groovy-eclipse-compiler - ${project.java.version} - ${project.java.version} - lines,vars,source - true - - - - org.codehaus.groovy - groovy-eclipse-compiler - ${groovy.eclipse.compiler} - - - org.codehaus.groovy - groovy-eclipse-batch - ${groovy.eclipse.batch} - - - - - org.codehaus.mojo - aspectj-maven-plugin - ${aspectj.plugin.version} - - - - compile - test-compile - - - - - ${project.java.version} - ${project.java.version} - ${project.java.version} - true - - - org.springframework - spring-aspects - - - org.zstack - core - - - org.zstack - header - - - - - - - + .. + + nfsPrimaryStorage + + + org.zstack + kvm + ${project.version} + + + org.zstack + sftpBackupStorage + ${project.version} + + + org.zstack + storage + ${project.version} + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${project.compiler.version} + + ${project.java.version} + true + true + + + + + org.codehaus.gmavenplus + gmavenplus-plugin + 4.2.1 + + + + generateStubs + compile + + + + + ${groovy.version} + ${project.java.version} + + + + + org.codehaus.mojo + aspectj-maven-plugin + ${aspectj.plugin.version} + + + org.aspectj + aspectjtools + ${aspectj.version} + + + + + + compile + test-compile + + + + + ${project.java.version} + ${project.java.version} + ${project.java.version} + ${project.build.sourceEncoding} + true + + + + org.springframework + spring-aspects + + + org.zstack + core + + + org.zstack + header + + + + + + + diff --git a/plugin/pom.xml b/plugin/pom.xml index 22f39138fc7..f90ff85b78a 100755 --- a/plugin/pom.xml +++ b/plugin/pom.xml @@ -1,113 +1,124 @@ - - 4.0.0 - - zstack - org.zstack + + 4.0.0 + + zstack + org.zstack 5.5.0 - .. - - plugin - pom - - nfsPrimaryStorage - kvm - sftpBackupStorage - virtualRouterProvider - securityGroup - portForwarding - applianceVm - vip - eip - mediator - localstorage - ceph - loadBalancer - flatNetworkProvider - sharedMountPointPrimaryStorage - ldap - vxlan - acl - sdnController - sugonSdnController - directory - sshKeyPair - hostNetworkInterface - vhost - expon - externalStorage - zbs - cbd - xinfini - - - - org.zstack - header - ${project.version} - - - org.zstack - core - ${project.version} - - - org.zstack - utils - ${project.version} - - - org.zstack - search - ${project.version} - - - org.zstack - identity - ${project.version} - - - org.zstack - tag - ${project.version} - - - - - - - org.codehaus.mojo - aspectj-maven-plugin - ${aspectj.plugin.version} - - - - compile - test-compile - - - - - ${project.java.version} - ${project.java.version} - ${project.java.version} - true - - - org.springframework - spring-aspects - - - org.zstack - core - - - org.zstack - header - - - - - - - + .. + + plugin + pom + + nfsPrimaryStorage + kvm + sftpBackupStorage + virtualRouterProvider + securityGroup + portForwarding + applianceVm + vip + eip + mediator + localstorage + ceph + loadBalancer + flatNetworkProvider + sharedMountPointPrimaryStorage + ldap + vxlan + acl + sdnController + sugonSdnController + directory + sshKeyPair + hostNetworkInterface + vhost + expon + externalStorage + zbs + cbd + xinfini + + + + org.zstack + header + ${project.version} + + + org.zstack + core + ${project.version} + + + org.zstack + utils + ${project.version} + + + org.zstack + search + ${project.version} + + + org.zstack + identity + ${project.version} + + + org.zstack + tag + ${project.version} + + + + + + + + org.codehaus.mojo + aspectj-maven-plugin + ${aspectj.plugin.version} + + + org.aspectj + aspectjtools + ${aspectj.version} + + + + + + compile + test-compile + + + + + ${project.java.version} + ${project.java.version} + ${project.java.version} + ${project.build.sourceEncoding} + true + + none + + + org.springframework + spring-aspects + + + org.zstack + core + + + org.zstack + header + + + + + + + diff --git a/plugin/portForwarding/pom.xml b/plugin/portForwarding/pom.xml index 114f0dfd147..32031bdd136 100755 --- a/plugin/portForwarding/pom.xml +++ b/plugin/portForwarding/pom.xml @@ -33,29 +33,41 @@ maven-compiler-plugin ${project.compiler.version} - groovy-eclipse-compiler - ${project.java.version} - ${project.java.version} - lines,vars,source + ${project.java.version} true + true - - - org.codehaus.groovy - groovy-eclipse-compiler - ${groovy.eclipse.compiler} - - - org.codehaus.groovy - groovy-eclipse-batch - ${groovy.eclipse.batch} - - + + + org.codehaus.gmavenplus + gmavenplus-plugin + 4.2.1 + + + + generateStubs + compile + + + + + ${groovy.version} + ${project.java.version} + + + org.codehaus.mojo aspectj-maven-plugin ${aspectj.plugin.version} + + + org.aspectj + aspectjtools + ${aspectj.version} + + @@ -65,10 +77,12 @@ + ${project.java.version} ${project.java.version} ${project.java.version} - ${project.java.version} - true + ${project.build.sourceEncoding} + true + org.springframework diff --git a/plugin/sdnController/pom.xml b/plugin/sdnController/pom.xml index 68773594b02..68354c926f1 100644 --- a/plugin/sdnController/pom.xml +++ b/plugin/sdnController/pom.xml @@ -56,29 +56,41 @@ maven-compiler-plugin ${project.compiler.version} - groovy-eclipse-compiler - ${project.java.version} - ${project.java.version} - lines,vars,source + ${project.java.version} true + true - - - org.codehaus.groovy - groovy-eclipse-compiler - ${groovy.eclipse.compiler} - - - org.codehaus.groovy - groovy-eclipse-batch - ${groovy.eclipse.batch} - - + + + org.codehaus.gmavenplus + gmavenplus-plugin + 4.2.1 + + + + generateStubs + compile + + + + + ${groovy.version} + ${project.java.version} + + + org.codehaus.mojo aspectj-maven-plugin ${aspectj.plugin.version} + + + org.aspectj + aspectjtools + ${aspectj.version} + + @@ -88,10 +100,12 @@ + ${project.java.version} ${project.java.version} ${project.java.version} - ${project.java.version} - true + ${project.build.sourceEncoding} + true + org.springframework diff --git a/plugin/securityGroup/pom.xml b/plugin/securityGroup/pom.xml index 35211774744..1cb943a9762 100755 --- a/plugin/securityGroup/pom.xml +++ b/plugin/securityGroup/pom.xml @@ -1,84 +1,98 @@ - - 4.0.0 - - org.zstack - plugin + + 4.0.0 + + org.zstack + plugin 5.5.0 - - securityGroup - - - org.zstack - compute - ${project.version} - - - org.zstack - network - ${project.version} - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - ${project.compiler.version} - - groovy-eclipse-compiler - ${project.java.version} - ${project.java.version} - lines,vars,source - true - - - - org.codehaus.groovy - groovy-eclipse-compiler - ${groovy.eclipse.compiler} - - - org.codehaus.groovy - groovy-eclipse-batch - ${groovy.eclipse.batch} - - - - - org.codehaus.mojo - aspectj-maven-plugin - ${aspectj.plugin.version} - - - - compile - test-compile - - - - - ${project.java.version} - ${project.java.version} - ${project.java.version} - true - - - org.springframework - spring-aspects - - - org.zstack - core - - - org.zstack - header - - - - - - - + + securityGroup + + + org.zstack + compute + ${project.version} + + + org.zstack + network + ${project.version} + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${project.compiler.version} + + ${project.java.version} + true + true + + + + + org.codehaus.gmavenplus + gmavenplus-plugin + 4.2.1 + + + + generateStubs + compile + + + + + ${groovy.version} + ${project.java.version} + + + + + org.codehaus.mojo + aspectj-maven-plugin + ${aspectj.plugin.version} + + + org.aspectj + aspectjtools + ${aspectj.version} + + + + + + compile + test-compile + + + + + ${project.java.version} + ${project.java.version} + ${project.java.version} + ${project.build.sourceEncoding} + true + + + + org.springframework + spring-aspects + + + org.zstack + core + + + org.zstack + header + + + + + + + diff --git a/plugin/sftpBackupStorage/pom.xml b/plugin/sftpBackupStorage/pom.xml index fb467ba83b9..5a954e13435 100755 --- a/plugin/sftpBackupStorage/pom.xml +++ b/plugin/sftpBackupStorage/pom.xml @@ -1,80 +1,94 @@ - - 4.0.0 - - plugin - org.zstack + + 4.0.0 + + plugin + org.zstack 5.5.0 - .. - - sftpBackupStorage - - - org.zstack - storage - ${project.version} - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - ${project.compiler.version} - - groovy-eclipse-compiler - ${project.java.version} - ${project.java.version} - lines,vars,source - true - - - - org.codehaus.groovy - groovy-eclipse-compiler - ${groovy.eclipse.compiler} - - - org.codehaus.groovy - groovy-eclipse-batch - ${groovy.eclipse.batch} - - - - - org.codehaus.mojo - aspectj-maven-plugin - ${aspectj.plugin.version} - - - - compile - test-compile - - - - - ${project.java.version} - ${project.java.version} - ${project.java.version} - true - - - org.springframework - spring-aspects - - - org.zstack - core - - - org.zstack - header - - - - - - - + .. + + sftpBackupStorage + + + org.zstack + storage + ${project.version} + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${project.compiler.version} + + ${project.java.version} + true + true + + + + + org.codehaus.gmavenplus + gmavenplus-plugin + 4.2.1 + + + + generateStubs + compile + + + + + ${groovy.version} + ${project.java.version} + + + + + org.codehaus.mojo + aspectj-maven-plugin + ${aspectj.plugin.version} + + + org.aspectj + aspectjtools + ${aspectj.version} + + + + + + compile + test-compile + + + + + ${project.java.version} + ${project.java.version} + ${project.java.version} + ${project.build.sourceEncoding} + true + + + + org.springframework + spring-aspects + + + org.zstack + core + + + org.zstack + header + + + + + + + diff --git a/plugin/sharedMountPointPrimaryStorage/pom.xml b/plugin/sharedMountPointPrimaryStorage/pom.xml index 1f5fcef5d50..da928558385 100755 --- a/plugin/sharedMountPointPrimaryStorage/pom.xml +++ b/plugin/sharedMountPointPrimaryStorage/pom.xml @@ -36,29 +36,41 @@ maven-compiler-plugin ${project.compiler.version} - groovy-eclipse-compiler - ${project.java.version} - ${project.java.version} - lines,vars,source + ${project.java.version} true + true - - - org.codehaus.groovy - groovy-eclipse-compiler - ${groovy.eclipse.compiler} - - - org.codehaus.groovy - groovy-eclipse-batch - ${groovy.eclipse.batch} - - + + + org.codehaus.gmavenplus + gmavenplus-plugin + 4.2.1 + + + + generateStubs + compile + + + + + ${groovy.version} + ${project.java.version} + + + org.codehaus.mojo aspectj-maven-plugin ${aspectj.plugin.version} + + + org.aspectj + aspectjtools + ${aspectj.version} + + @@ -68,10 +80,12 @@ + ${project.java.version} ${project.java.version} ${project.java.version} - ${project.java.version} - true + ${project.build.sourceEncoding} + true + org.springframework diff --git a/plugin/sshKeyPair/pom.xml b/plugin/sshKeyPair/pom.xml index f73868c7fec..9c242920a7c 100644 --- a/plugin/sshKeyPair/pom.xml +++ b/plugin/sshKeyPair/pom.xml @@ -25,35 +25,44 @@ maven-compiler-plugin ${project.compiler.version} - groovy-eclipse-compiler - ${project.java.version} - ${project.java.version} - lines,vars,source + ${project.java.version} true + true - - org.codehaus.groovy - groovy-eclipse-compiler - ${groovy.eclipse.compiler} - - - org.codehaus.groovy - groovy-eclipse-batch - ${groovy.eclipse.batch} - - - com.jcraft - jsch - 0.1.55 - + + + org.codehaus.gmavenplus + gmavenplus-plugin + 4.2.1 + + + + generateStubs + compile + + + + + ${groovy.version} + ${project.java.version} + + + org.codehaus.mojo aspectj-maven-plugin ${aspectj.plugin.version} + + + org.aspectj + aspectjtools + ${aspectj.version} + + @@ -63,10 +72,12 @@ + ${project.java.version} ${project.java.version} ${project.java.version} - ${project.java.version} - true + ${project.build.sourceEncoding} + true + org.springframework diff --git a/plugin/sugonSdnController/pom.xml b/plugin/sugonSdnController/pom.xml index f9e83fa4468..13a418f7918 100644 --- a/plugin/sugonSdnController/pom.xml +++ b/plugin/sugonSdnController/pom.xml @@ -51,29 +51,41 @@ maven-compiler-plugin ${project.compiler.version} - groovy-eclipse-compiler - ${project.java.version} - ${project.java.version} - lines,vars,source + ${project.java.version} true + true - - - org.codehaus.groovy - groovy-eclipse-compiler - ${groovy.eclipse.compiler} - - - org.codehaus.groovy - groovy-eclipse-batch - ${groovy.eclipse.batch} - - + + + org.codehaus.gmavenplus + gmavenplus-plugin + 4.2.1 + + + + generateStubs + compile + + + + + ${groovy.version} + ${project.java.version} + + + org.codehaus.mojo aspectj-maven-plugin ${aspectj.plugin.version} + + + org.aspectj + aspectjtools + ${aspectj.version} + + @@ -83,10 +95,12 @@ + ${project.java.version} ${project.java.version} ${project.java.version} - ${project.java.version} - true + ${project.build.sourceEncoding} + true + org.springframework diff --git a/plugin/sugonSdnController/src/main/java/org/zstack/sugonSdnController/controller/api/ApiConnectorImpl.java b/plugin/sugonSdnController/src/main/java/org/zstack/sugonSdnController/controller/api/ApiConnectorImpl.java index ef88f3c9109..b233b2d4147 100644 --- a/plugin/sugonSdnController/src/main/java/org/zstack/sugonSdnController/controller/api/ApiConnectorImpl.java +++ b/plugin/sugonSdnController/src/main/java/org/zstack/sugonSdnController/controller/api/ApiConnectorImpl.java @@ -558,7 +558,7 @@ public String findByName(Class cls, ApiObjectBase paren name_list.addAll(parent.getQualifiedName()); } else { try { - name_list.addAll(cls.newInstance().getDefaultParent()); + name_list.addAll(cls.getConstructor().newInstance().getDefaultParent()); } catch (Exception ex) { // Instantiation or IllegalAccess s_logger.error("Failed to instantiate object of class " + cls.getName(), ex); diff --git a/plugin/sugonSdnController/src/main/java/org/zstack/sugonSdnController/controller/api/ApiConnectorMock.java b/plugin/sugonSdnController/src/main/java/org/zstack/sugonSdnController/controller/api/ApiConnectorMock.java index 8278226c4c9..91eee16e8f0 100644 --- a/plugin/sugonSdnController/src/main/java/org/zstack/sugonSdnController/controller/api/ApiConnectorMock.java +++ b/plugin/sugonSdnController/src/main/java/org/zstack/sugonSdnController/controller/api/ApiConnectorMock.java @@ -449,7 +449,7 @@ public String findByName(Class cls, ApiObjectBase paren name_list.addAll(parent.getQualifiedName()); } else { try { - name_list.addAll(cls.newInstance().getDefaultParent()); + name_list.addAll(cls.getConstructor().newInstance().getDefaultParent()); } catch (Exception e) { s_logger.warn(e.getMessage()); } diff --git a/plugin/vhost/pom.xml b/plugin/vhost/pom.xml index 2c3ae284b8c..223a189f6a6 100644 --- a/plugin/vhost/pom.xml +++ b/plugin/vhost/pom.xml @@ -31,29 +31,41 @@ maven-compiler-plugin ${project.compiler.version} - groovy-eclipse-compiler - ${project.java.version} - ${project.java.version} - lines,vars,source + ${project.java.version} true + true - - - org.codehaus.groovy - groovy-eclipse-compiler - ${groovy.eclipse.compiler} - - - org.codehaus.groovy - groovy-eclipse-batch - ${groovy.eclipse.batch} - - + + + org.codehaus.gmavenplus + gmavenplus-plugin + 4.2.1 + + + + generateStubs + compile + + + + + ${groovy.version} + ${project.java.version} + + + org.codehaus.mojo aspectj-maven-plugin ${aspectj.plugin.version} + + + org.aspectj + aspectjtools + ${aspectj.version} + + @@ -63,10 +75,12 @@ + ${project.java.version} ${project.java.version} ${project.java.version} - ${project.java.version} - true + ${project.build.sourceEncoding} + true + org.springframework diff --git a/plugin/vip/pom.xml b/plugin/vip/pom.xml index 828acd6c537..ec58d27a1f3 100755 --- a/plugin/vip/pom.xml +++ b/plugin/vip/pom.xml @@ -18,29 +18,41 @@ maven-compiler-plugin ${project.compiler.version} - groovy-eclipse-compiler - ${project.java.version} - ${project.java.version} - lines,vars,source + ${project.java.version} true + true - - - org.codehaus.groovy - groovy-eclipse-compiler - ${groovy.eclipse.compiler} - - - org.codehaus.groovy - groovy-eclipse-batch - ${groovy.eclipse.batch} - - + + + org.codehaus.gmavenplus + gmavenplus-plugin + 4.2.1 + + + + generateStubs + compile + + + + + ${groovy.version} + ${project.java.version} + + + org.codehaus.mojo aspectj-maven-plugin ${aspectj.plugin.version} + + + org.aspectj + aspectjtools + ${aspectj.version} + + @@ -50,10 +62,12 @@ + ${project.java.version} ${project.java.version} ${project.java.version} - ${project.java.version} - true + ${project.build.sourceEncoding} + true + org.springframework diff --git a/plugin/virtualRouterProvider/pom.xml b/plugin/virtualRouterProvider/pom.xml index c50ab0511cb..0631def83b3 100755 --- a/plugin/virtualRouterProvider/pom.xml +++ b/plugin/virtualRouterProvider/pom.xml @@ -1,125 +1,139 @@ - - 4.0.0 - - org.zstack - plugin + + 4.0.0 + + org.zstack + plugin 5.5.0 - - virtualRouterProvider - - - - - org.apache.maven.plugins - maven-compiler-plugin - ${project.compiler.version} - - groovy-eclipse-compiler - ${project.java.version} - ${project.java.version} - lines,vars,source - true - - - - org.codehaus.groovy - groovy-eclipse-compiler - ${groovy.eclipse.compiler} - - - org.codehaus.groovy - groovy-eclipse-batch - ${groovy.eclipse.batch} - - - - - org.codehaus.mojo - aspectj-maven-plugin - ${aspectj.plugin.version} - - - - compile - test-compile - - - - - ${project.java.version} - ${project.java.version} - ${project.java.version} - true - - - org.springframework - spring-aspects - - - org.zstack - core - - - org.zstack - header - - - - - - - - - - org.zstack - network - ${project.version} - - - org.zstack - image - ${project.version} - - - org.zstack - vip - ${project.version} - - - org.zstack - configuration - ${project.version} - - - org.zstack - compute - ${project.version} - - - org.zstack - kvm - ${project.version} - - - org.zstack - portForwarding - ${project.version} - - - org.zstack - eip - ${project.version} - - - org.zstack - applianceVm - ${project.version} - - - org.zstack - loadBalancer - ${project.version} - - - + + virtualRouterProvider + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${project.compiler.version} + + ${project.java.version} + true + true + + + + + org.codehaus.gmavenplus + gmavenplus-plugin + 4.2.1 + + + + generateStubs + compile + + + + + ${groovy.version} + ${project.java.version} + + + + + org.codehaus.mojo + aspectj-maven-plugin + ${aspectj.plugin.version} + + + org.aspectj + aspectjtools + ${aspectj.version} + + + + + + compile + test-compile + + + + + ${project.java.version} + ${project.java.version} + ${project.java.version} + ${project.build.sourceEncoding} + true + + + + org.springframework + spring-aspects + + + org.zstack + core + + + org.zstack + header + + + + + + + + + + org.zstack + network + ${project.version} + + + org.zstack + image + ${project.version} + + + org.zstack + vip + ${project.version} + + + org.zstack + configuration + ${project.version} + + + org.zstack + compute + ${project.version} + + + org.zstack + kvm + ${project.version} + + + org.zstack + portForwarding + ${project.version} + + + org.zstack + eip + ${project.version} + + + org.zstack + applianceVm + ${project.version} + + + org.zstack + loadBalancer + ${project.version} + + + diff --git a/plugin/vxlan/pom.xml b/plugin/vxlan/pom.xml index 31668f4bdcf..b749e511172 100755 --- a/plugin/vxlan/pom.xml +++ b/plugin/vxlan/pom.xml @@ -51,29 +51,41 @@ maven-compiler-plugin ${project.compiler.version} - groovy-eclipse-compiler - ${project.java.version} - ${project.java.version} - lines,vars,source + ${project.java.version} true + true - - - org.codehaus.groovy - groovy-eclipse-compiler - ${groovy.eclipse.compiler} - - - org.codehaus.groovy - groovy-eclipse-batch - ${groovy.eclipse.batch} - - + + + org.codehaus.gmavenplus + gmavenplus-plugin + 4.2.1 + + + + generateStubs + compile + + + + + ${groovy.version} + ${project.java.version} + + + org.codehaus.mojo aspectj-maven-plugin ${aspectj.plugin.version} + + + org.aspectj + aspectjtools + ${aspectj.version} + + @@ -83,10 +95,12 @@ + ${project.java.version} ${project.java.version} ${project.java.version} - ${project.java.version} - true + ${project.build.sourceEncoding} + true + org.springframework diff --git a/plugin/xinfini/pom.xml b/plugin/xinfini/pom.xml index 89c1f6c5a7d..9863edd6665 100644 --- a/plugin/xinfini/pom.xml +++ b/plugin/xinfini/pom.xml @@ -51,29 +51,41 @@ maven-compiler-plugin ${project.compiler.version} - groovy-eclipse-compiler - ${project.java.version} - ${project.java.version} - lines,vars,source + ${project.java.version} true + true - - - org.codehaus.groovy - groovy-eclipse-compiler - ${groovy.eclipse.compiler} - - - org.codehaus.groovy - groovy-eclipse-batch - ${groovy.eclipse.batch} - - + + + org.codehaus.gmavenplus + gmavenplus-plugin + 4.2.1 + + + + generateStubs + compile + + + + + ${groovy.version} + ${project.java.version} + + + org.codehaus.mojo aspectj-maven-plugin ${aspectj.plugin.version} + + + org.aspectj + aspectjtools + ${aspectj.version} + + @@ -83,10 +95,12 @@ + ${project.java.version} ${project.java.version} ${project.java.version} - ${project.java.version} - true + ${project.build.sourceEncoding} + true + org.springframework diff --git a/plugin/zbs/pom.xml b/plugin/zbs/pom.xml index 15bae057d4c..176d6e07da1 100644 --- a/plugin/zbs/pom.xml +++ b/plugin/zbs/pom.xml @@ -30,29 +30,41 @@ maven-compiler-plugin ${project.compiler.version} - groovy-eclipse-compiler - ${project.java.version} - ${project.java.version} - lines,vars,source + ${project.java.version} true + true - - - org.codehaus.groovy - groovy-eclipse-compiler - ${groovy.eclipse.compiler} - - - org.codehaus.groovy - groovy-eclipse-batch - ${groovy.eclipse.batch} - - + + + org.codehaus.gmavenplus + gmavenplus-plugin + 4.2.1 + + + + generateStubs + compile + + + + + ${groovy.version} + ${project.java.version} + + + org.codehaus.mojo aspectj-maven-plugin ${aspectj.plugin.version} + + + org.aspectj + aspectjtools + ${aspectj.version} + + @@ -62,10 +74,12 @@ + ${project.java.version} ${project.java.version} ${project.java.version} - ${project.java.version} - true + ${project.build.sourceEncoding} + true + org.springframework diff --git a/pom.xml b/pom.xml index 5173ad0aef2..e53da1ce8b8 100755 --- a/pom.xml +++ b/pom.xml @@ -5,19 +5,30 @@ org.springframework spring-web + + + + javax.annotation + javax.annotation-api + UTF-8 3.6.1 - 1.8 + 17 5.2.25.RELEASE 5.7.13 - 5.3.26.Final - 1.8.9 - 1.10 - 2.9.2-01 - 2.4.3-01 + 5.6.15.Final + 1.9.21 + 1.16.0 + 4.0.15 + 3.9.0 + 4.0.15-01 5.10.12.Final + + 2.3.1 + 2.3.6 + 1.3.2 4.0.0 @@ -131,9 +142,36 @@ 2.18.0 - org.codehaus.groovy - groovy-all - 2.4.21 + org.apache.groovy + groovy + ${groovy.version} + + + org.apache.groovy + groovy-xml + ${groovy.version} + + + org.apache.groovy + groovy-templates + ${groovy.version} + + + + javax.xml.bind + jaxb-api + ${jaxb.api.version} + + + org.glassfish.jaxb + jaxb-runtime + ${jaxb.runtime.version} + + + + javax.annotation + javax.annotation-api + ${javax.annotation.version} org.hibernate.javax.persistence @@ -295,7 +333,7 @@ com.mchange c3p0 - 0.9.5.4 + 0.9.5.5 com.google.guava @@ -622,9 +660,115 @@ + + + org.apache.maven.plugins + maven-enforcer-plugin + 3.4.1 + + + enforce-java17 + + enforce + + + + + [17,18) + 项目需要Java 17,当前版本: ${java.version} + + + [3.6.0,) + + + true + + + + + + + + + org.codehaus.gmavenplus + gmavenplus-plugin + 4.2.1 + + + + org.apache.groovy + groovy + ${groovy.version} + + + + + true + + + ${project.basedir}/src/main/java + + **/*.groovy + + + + ${project.basedir}/src/main/groovy + + **/*.groovy + + + + + + ${project.basedir}/src/test/java + + **/*.groovy + + + + ${project.basedir}/src/test/groovy + + **/*.groovy + + + + + + + + + + + central + Maven Central Repository + https://repo1.maven.org/maven2 + + true + + + false + + + + + + + + central + Maven Central Plugin Repository + https://repo1.maven.org/maven2 + + true + + + false + + + + maven-releases diff --git a/portal/pom.xml b/portal/pom.xml index e174dfe5f45..5fa5c8d3fe1 100755 --- a/portal/pom.xml +++ b/portal/pom.xml @@ -49,29 +49,23 @@ maven-compiler-plugin ${project.compiler.version} - groovy-eclipse-compiler - ${project.java.version} - ${project.java.version} - lines,vars,source + ${project.java.version} true + true - - - org.codehaus.groovy - groovy-eclipse-compiler - ${groovy.eclipse.compiler} - - - org.codehaus.groovy - groovy-eclipse-batch - ${groovy.eclipse.batch} - - + org.codehaus.mojo aspectj-maven-plugin ${aspectj.plugin.version} + + + org.aspectj + aspectjtools + ${aspectj.version} + + @@ -81,10 +75,12 @@ + ${project.java.version} ${project.java.version} ${project.java.version} - ${project.java.version} - true + ${project.build.sourceEncoding} + true + org.springframework diff --git a/portal/src/main/java/org/zstack/portal/managementnode/DebugSignalHandler.java b/portal/src/main/java/org/zstack/portal/managementnode/DebugSignalHandler.java index 17cf7a36ab6..8687a9f19f8 100644 --- a/portal/src/main/java/org/zstack/portal/managementnode/DebugSignalHandler.java +++ b/portal/src/main/java/org/zstack/portal/managementnode/DebugSignalHandler.java @@ -1,5 +1,7 @@ package org.zstack.portal.managementnode; +// Note: sun.misc.Signal requires --add-exports java.base/sun.misc=ALL-UNNAMED JVM option in Java 17+ +// This is configured in conf/jvm-options-java17.conf import sun.misc.Signal; import sun.misc.SignalHandler; diff --git a/resourceconfig/pom.xml b/resourceconfig/pom.xml index f28c3c820db..5d124a9135b 100644 --- a/resourceconfig/pom.xml +++ b/resourceconfig/pom.xml @@ -46,29 +46,23 @@ maven-compiler-plugin ${project.compiler.version} - groovy-eclipse-compiler - ${project.java.version} - ${project.java.version} - lines,vars,source + ${project.java.version} true + true - - - org.codehaus.groovy - groovy-eclipse-compiler - ${groovy.eclipse.compiler} - - - org.codehaus.groovy - groovy-eclipse-batch - ${groovy.eclipse.batch} - - + org.codehaus.mojo aspectj-maven-plugin ${aspectj.plugin.version} + + + org.aspectj + aspectjtools + ${aspectj.version} + + @@ -78,10 +72,12 @@ + ${project.java.version} ${project.java.version} ${project.java.version} - ${project.java.version} - true + ${project.build.sourceEncoding} + true + org.springframework diff --git a/rest/pom.xml b/rest/pom.xml index 5f346305937..1cce3d4ad7a 100755 --- a/rest/pom.xml +++ b/rest/pom.xml @@ -79,29 +79,23 @@ maven-compiler-plugin ${project.compiler.version} - groovy-eclipse-compiler - ${project.java.version} - ${project.java.version} - lines,vars,source + ${project.java.version} true + true - - - org.codehaus.groovy - groovy-eclipse-compiler - ${groovy.eclipse.compiler} - - - org.codehaus.groovy - groovy-eclipse-batch - ${groovy.eclipse.batch} - - + org.codehaus.mojo aspectj-maven-plugin ${aspectj.plugin.version} + + + org.aspectj + aspectjtools + ${aspectj.version} + + @@ -111,10 +105,11 @@ + ${project.java.version} ${project.java.version} ${project.java.version} - ${project.java.version} - true + ${project.build.sourceEncoding} + true org.springframework diff --git a/rest/src/main/java/org/zstack/rest/RestServer.java b/rest/src/main/java/org/zstack/rest/RestServer.java index 339396d3c41..9a860135c82 100755 --- a/rest/src/main/java/org/zstack/rest/RestServer.java +++ b/rest/src/main/java/org/zstack/rest/RestServer.java @@ -1118,7 +1118,7 @@ private void handleApi(Api api, Map body, String parameterName, HttpEntity vars = req.getParameterMap(); - APIQueryMessage msg = (APIQueryMessage) api.apiClass.newInstance(); + APIQueryMessage msg = (APIQueryMessage) api.apiClass.getConstructor().newInstance(); if (session != null && session.isNoSessionEvaluation()) { msg.putHeaderEntry(IdentityByPassCheck.NoSessionEvaluation.toString(), true); diff --git a/runMavenProfile b/runMavenProfile index c911240dee3..25cd7ce38d3 100755 --- a/runMavenProfile +++ b/runMavenProfile @@ -499,7 +499,7 @@ clear_git_config() { run_profile() { if test x$1 = x'premium'; then - mvn -Dmaven.test.skip=true -P premium clean install + mvn -Dmaven.test.skip=true -T 1C -P premium clean install elif test x$1 = x'md'; then md elif test x$1 = x'sdk'; then diff --git a/sdk/pom.xml b/sdk/pom.xml index 988b8f7d7c0..d471e5be9a8 100755 --- a/sdk/pom.xml +++ b/sdk/pom.xml @@ -44,8 +44,7 @@ maven-compiler-plugin ${project.compiler.version} - ${project.java.version} - ${project.java.version} + ${project.java.version} lines,vars,source true diff --git a/search/pom.xml b/search/pom.xml index a2735c3e583..f6ccb6d52f4 100755 --- a/search/pom.xml +++ b/search/pom.xml @@ -8,6 +8,22 @@ .. search + + + + + central + Maven Central Plugin Repository + https://repo1.maven.org/maven2 + + true + + + false + + + + org.zstack @@ -39,8 +55,12 @@ 1.19 - org.codehaus.groovy - groovy-all + org.apache.groovy + groovy + + + org.apache.groovy + groovy-xml org.antlr @@ -134,35 +154,75 @@ + org.apache.maven.plugins maven-compiler-plugin ${project.compiler.version} - groovy-eclipse-compiler - ${project.java.version} - ${project.java.version} - lines,vars,source + ${project.java.version} true + true + + + + + + org.codehaus.gmavenplus + gmavenplus-plugin + 4.2.1 + + + + generate-stubs + process-sources + + generateStubs + + + + + compile-groovy + compile + + compile + + + + + generate-test-stubs + process-test-sources + + generateTestStubs + + + + + compile-test-groovy + test-compile + + compileTests + + + + + ${groovy.version} + ${project.java.version} - - - org.codehaus.groovy - groovy-eclipse-compiler - 2.9.2-01 - - - org.codehaus.groovy - groovy-eclipse-batch - 2.4.3-01 - - + org.codehaus.mojo aspectj-maven-plugin ${aspectj.plugin.version} + + + org.aspectj + aspectjtools + ${aspectj.version} + + @@ -172,10 +232,12 @@ + ${project.java.version} ${project.java.version} ${project.java.version} - ${project.java.version} - true + ${project.build.sourceEncoding} + true + none org.springframework diff --git a/search/src/main/java/org/zstack/query/APIBatchQueryMsgDoc_zh_cn.groovy b/search/src/main/groovy/org/zstack/query/APIBatchQueryMsgDoc_zh_cn.groovy similarity index 99% rename from search/src/main/java/org/zstack/query/APIBatchQueryMsgDoc_zh_cn.groovy rename to search/src/main/groovy/org/zstack/query/APIBatchQueryMsgDoc_zh_cn.groovy index bda576ced59..822fb2edd77 100644 --- a/search/src/main/java/org/zstack/query/APIBatchQueryMsgDoc_zh_cn.groovy +++ b/search/src/main/groovy/org/zstack/query/APIBatchQueryMsgDoc_zh_cn.groovy @@ -55,4 +55,5 @@ doc { clz APIBatchQueryReply.class } } -} \ No newline at end of file +} + diff --git a/search/src/main/java/org/zstack/query/APIBatchQueryReplyDoc_zh_cn.groovy b/search/src/main/groovy/org/zstack/query/APIBatchQueryReplyDoc_zh_cn.groovy similarity index 99% rename from search/src/main/java/org/zstack/query/APIBatchQueryReplyDoc_zh_cn.groovy rename to search/src/main/groovy/org/zstack/query/APIBatchQueryReplyDoc_zh_cn.groovy index 51191bb2d58..05f28f337c4 100644 --- a/search/src/main/java/org/zstack/query/APIBatchQueryReplyDoc_zh_cn.groovy +++ b/search/src/main/groovy/org/zstack/query/APIBatchQueryReplyDoc_zh_cn.groovy @@ -27,3 +27,4 @@ doc { since "0.6" } } + diff --git a/search/src/main/java/org/zstack/query/APIZQLQueryMsgDoc_zh_cn.groovy b/search/src/main/groovy/org/zstack/query/APIZQLQueryMsgDoc_zh_cn.groovy similarity index 99% rename from search/src/main/java/org/zstack/query/APIZQLQueryMsgDoc_zh_cn.groovy rename to search/src/main/groovy/org/zstack/query/APIZQLQueryMsgDoc_zh_cn.groovy index 2b161d70622..72a323d5fe2 100644 --- a/search/src/main/java/org/zstack/query/APIZQLQueryMsgDoc_zh_cn.groovy +++ b/search/src/main/groovy/org/zstack/query/APIZQLQueryMsgDoc_zh_cn.groovy @@ -55,4 +55,5 @@ doc { clz APIZQLQueryReply.class } } -} \ No newline at end of file +} + diff --git a/search/src/main/java/org/zstack/query/APIZQLQueryReplyDoc_zh_cn.groovy b/search/src/main/groovy/org/zstack/query/APIZQLQueryReplyDoc_zh_cn.groovy old mode 100755 new mode 100644 similarity index 99% rename from search/src/main/java/org/zstack/query/APIZQLQueryReplyDoc_zh_cn.groovy rename to search/src/main/groovy/org/zstack/query/APIZQLQueryReplyDoc_zh_cn.groovy index bef9151aa68..1380ee6b6b0 --- a/search/src/main/java/org/zstack/query/APIZQLQueryReplyDoc_zh_cn.groovy +++ b/search/src/main/groovy/org/zstack/query/APIZQLQueryReplyDoc_zh_cn.groovy @@ -30,3 +30,4 @@ doc { clz ZQLQueryReturn.class } } + diff --git a/search/src/main/java/org/zstack/query/BatchQuery.groovy b/search/src/main/groovy/org/zstack/query/BatchQuery.groovy old mode 100755 new mode 100644 similarity index 97% rename from search/src/main/java/org/zstack/query/BatchQuery.groovy rename to search/src/main/groovy/org/zstack/query/BatchQuery.groovy index f4f9cafb7dd..edffe1bd9f8 --- a/search/src/main/java/org/zstack/query/BatchQuery.groovy +++ b/search/src/main/groovy/org/zstack/query/BatchQuery.groovy @@ -1,485 +1,486 @@ package org.zstack.query -import static org.zstack.utils.clouderrorcode.CloudOperationsErrorCode.*; - -import org.apache.commons.lang.StringUtils -import org.codehaus.groovy.control.CompilerConfiguration -import org.codehaus.groovy.reflection.ClassInfo -import org.codehaus.groovy.reflection.GroovyClassValue -import org.kohsuke.groovy.sandbox.GroovyInterceptor -import org.kohsuke.groovy.sandbox.SandboxTransformer -import org.kohsuke.groovy.sandbox.impl.Super -import org.zstack.core.Platform -import org.zstack.core.cloudbus.CloudBus -import org.zstack.header.errorcode.OperationFailureException -import org.zstack.header.exception.CloudRuntimeException -import org.zstack.header.identity.AccountConstant -import org.zstack.header.identity.Action -import org.zstack.header.identity.SessionInventory -import org.zstack.header.identity.SuppressCredentialCheck -import org.zstack.header.message.APIMessage -import org.zstack.header.message.APIResponse -import org.zstack.header.message.APISyncCallMessage -import org.zstack.header.message.MessageReply -import org.zstack.header.query.APIQueryMessage -import org.zstack.header.query.AutoQuery -import org.zstack.header.query.QueryCondition -import org.zstack.header.query.QueryOp -import org.zstack.utils.Utils -import org.zstack.utils.gson.JSONObjectUtil -import org.zstack.utils.logging.CLogger -import org.zstack.zql.ZQL -import org.zstack.zql.ZQLContext -import org.zstack.zql.ZQLQueryReturn - -import java.lang.reflect.Field -import java.lang.reflect.Modifier -import java.util.regex.Pattern - -class BatchQuery { - private static CLogger logger = Utils.getLogger(BatchQuery.class) - - private QueryFacade queryf - private SessionInventory session - private CloudBus bus - - private static class DebugObject { - static class APIStatistics { - transient long startTime - - int timeCostPerCall - int totalTimeCost - int callTimes - long totalResultSize - long resultSizePerCall - } - - Map APIStats = [:] - long resultSize - long totalTimeCost - } - - private DebugObject debugObject; - - static class SandBox extends GroovyInterceptor { - static List RECEIVER_WHITE_LIST = [ - Number[].class, - Number.class, - long[].class, - long.class, - int[].class, - int.class, - short[].class, - short.class, - double[].class, - double.class, - float[].class, - float.class, - String[].class, - String.class, - Date[].class, - Date.class, - Map.class, - Collection.class, - Enum[].class, - Enum.class - ] - - static void checkReceiver(Object obj) { - checkReceiver(obj.getClass()) - } - - static void checkReceiver(Class clz) { - for (Class wclz : RECEIVER_WHITE_LIST) { - if (wclz.isAssignableFrom(clz)) { - return - } - } - - throw new Exception("invalid operation on class[${clz.name}]") - } - - static void checkMethod(String method) { - if (method == "sleep") { - throw new Exception("invalid operation[${method}]") - } - } - - Object onMethodCall(GroovyInterceptor.Invoker invoker, Object receiver, String method, Object... args) throws Throwable { - checkReceiver(receiver) - checkMethod(method) - return super.onMethodCall(invoker, receiver, method, args) - } - - Object onStaticCall(GroovyInterceptor.Invoker invoker, Class receiver, String method, Object... args) throws Throwable { - checkReceiver(receiver) - checkMethod(method) - return super.onStaticCall(invoker, receiver, method, args) - } - - Object onNewInstance(GroovyInterceptor.Invoker invoker, Class receiver, Object... args) throws Throwable { - checkReceiver(receiver) - return invoker.call(receiver, (String)null, (Object[])args); - } - - Object onSuperCall(GroovyInterceptor.Invoker invoker, Class senderType, Object receiver, String method, Object... args) throws Throwable { - checkReceiver(receiver) - return invoker.call(new Super(senderType, receiver), method, (Object[])args); - } - - void onSuperConstructor(GroovyInterceptor.Invoker invoker, Class receiver, Object... args) throws Throwable { - checkReceiver(receiver) - this.onNewInstance(invoker, receiver, args); - } - - Object onGetProperty(GroovyInterceptor.Invoker invoker, Object receiver, String property) throws Throwable { - checkReceiver(receiver) - return invoker.call(receiver, property); - } - - Object onSetProperty(GroovyInterceptor.Invoker invoker, Object receiver, String property, Object value) throws Throwable { - checkReceiver(receiver) - return invoker.call(receiver, property, value); - } - - Object onGetAttribute(GroovyInterceptor.Invoker invoker, Object receiver, String attribute) throws Throwable { - checkReceiver(receiver) - return invoker.call(receiver, attribute); - } - - Object onSetAttribute(GroovyInterceptor.Invoker invoker, Object receiver, String attribute, Object value) throws Throwable { - checkReceiver(receiver) - return invoker.call(receiver, attribute, value); - } - - Object onGetArray(GroovyInterceptor.Invoker invoker, Object receiver, Object index) throws Throwable { - checkReceiver(receiver) - return invoker.call(receiver, (String)null, (Object)index); - } - - Object onSetArray(GroovyInterceptor.Invoker invoker, Object receiver, Object index, Object value) throws Throwable { - checkReceiver(receiver) - return invoker.call(receiver, (String)null, index, value); - } - } - - BatchQuery() { - this.queryf = Platform.getComponentLoader().getComponent(QueryFacade.class) - this.bus = Platform.getComponentLoader().getComponent(CloudBus.class) - - if (isDebugOn()) { - debugObject = new DebugObject() - } - } - - private static SandBox sandbox = new SandBox() - - static Map queryMessageClass = [:] - static LinkedHashMap QUERY_OP_MAPPING = [:] - - static String lstrip(String s, String remove) { - return StringUtils.removeStart(s, remove) - } - - static String rstrip(String s, String remove) { - return StringUtils.removeEnd(s, remove) - } - - static { - Platform.reflections.getSubTypesOf(APISyncCallMessage.class).each { clz -> - if (Modifier.isAbstract(clz.modifiers)) { - return - } - - SuppressCredentialCheck at = clz.getAnnotation(SuppressCredentialCheck.class) - if (at != null && !at.supportBacthQuery()) { - return - } - - String name = lstrip(rstrip(clz.simpleName, "Msg"), "API") - queryMessageClass[name.toLowerCase()] = clz - queryMessageClass[clz.name] = clz - } - - // order is important, don't change it - QUERY_OP_MAPPING.put("=null", QueryOp.IS_NULL.toString()) - QUERY_OP_MAPPING.put("!=null", QueryOp.NOT_NULL.toString()) - QUERY_OP_MAPPING.put("!=", QueryOp.NOT_EQ.toString()) - QUERY_OP_MAPPING.put(">=", QueryOp.GT_AND_EQ.toString()) - QUERY_OP_MAPPING.put("<=", QueryOp.LT_AND_EQ.toString()) - QUERY_OP_MAPPING.put("!?=", QueryOp.NOT_IN.toString()) - QUERY_OP_MAPPING.put("!~=", QueryOp.NOT_LIKE.toString()) - QUERY_OP_MAPPING.put("~=", QueryOp.LIKE.toString()) - QUERY_OP_MAPPING.put("?=", QueryOp.IN.toString()) - QUERY_OP_MAPPING.put("=", QueryOp.EQ.toString()) - QUERY_OP_MAPPING.put(">", QueryOp.GT.toString()) - QUERY_OP_MAPPING.put("<", QueryOp.LT.toString()) - } - - private static boolean isDebugOn() { - return QueryGlobalConfig.BATCH_QUERY_DEBUG.value(Boolean.class) - } - - private void startDebug(APIMessage msg) { - if (isDebugOn()) { - DebugObject.APIStatistics stat = debugObject.APIStats.computeIfAbsent(msg.class.name, {new DebugObject.APIStatistics()}) - stat.startTime = System.currentTimeMillis() - } - } - - private void endDebug(APIMessage msg, Map res) { - if (isDebugOn()) { - DebugObject.APIStatistics stat = debugObject.APIStats[msg.class.name] - long timeCost = System.currentTimeMillis() - stat.startTime - stat.totalTimeCost += timeCost - stat.totalResultSize += getMapMemorySize(res) - stat.callTimes += 1 - } - } - - private void printDebugInfo() { - if (!isDebugOn()) { - return - } - - // some APIs may not complete because of error - debugObject.APIStats = debugObject.APIStats.findAll { it.value.callTimes != 0 } - - debugObject.APIStats.values().each { stat -> - stat.timeCostPerCall = (int) (stat.totalTimeCost / stat.callTimes) - stat.resultSizePerCall = (long) (stat.totalResultSize / stat.callTimes) - - debugObject.resultSize += stat.totalResultSize - debugObject.totalTimeCost += stat.totalTimeCost - } - - logger.debug("""BATCH QUERY DEBUG INFO: ${JSONObjectUtil.toJsonString(debugObject)}""") - } - - private Map syncApiCall(String apiname, String jstr) { - Class msgClz = queryMessageClass[apiname] - if (msgClz == null) { - throw new OperationFailureException(org.zstack.core.Platform.argerr(ORG_ZSTACK_QUERY_10006, "no query API found for %s", apiname)) - } - - APISyncCallMessage msg = JSONObjectUtil.toObject(jstr, msgClz) - - startDebug(msg) - - msg.setSession(session) - msg.setServiceId("api.portal") - MessageReply reply = bus.call(msg) - if (!reply.isSuccess()) { - throw new OperationFailureException(reply.error) - } - - APIResponse rsp = reply as APIResponse - def res = ["result":rsp.toResponseMap(rsp)] - - endDebug(msg, res) - - return res - } - - private List zqlQuery(String qstr){ - ZQLContext.putAPISession(session) - List result = ZQL.fromString(qstr).getResultList() - ZQLContext.cleanAPISession() - return result - } - - private Map doQuery(String qstr) { - List words = qstr.split(" ") - words = words.findAll { !it.isEmpty() } - if (words.isEmpty()) { - throw new OperationFailureException(org.zstack.core.Platform.argerr(ORG_ZSTACK_QUERY_10007, "invalid query string: %s", qstr)) - } - - String api = words[0].toLowerCase() - Class msgClz = queryMessageClass[api] - if (msgClz == null) { - throw new OperationFailureException(org.zstack.core.Platform.argerr(ORG_ZSTACK_QUERY_10008, "no query API found for %s", words[0])) - } - - APIQueryMessage msg = msgClz.newInstance() as APIQueryMessage - - startDebug(msg) - - msg.setSession(session) - if (AccountConstant.INITIAL_SYSTEM_ADMIN_UUID != msg.session.accountUuid && !msgClz.isAnnotationPresent(Action.class)) { - // the resource is owned by admin and the account is a normal account - //TODO: fix hard code check admin query - return ["total": 0, "result": []] - } - - msg.setConditions([]) - boolean count = false - boolean replyWithCount = false - String filterName - - AutoQuery at = msg.getClass().getAnnotation(AutoQuery.class) - if (at == null) { - throw new CloudRuntimeException("class[${msg.getClass().name}] is not annotated by AutoQuery") - } - - Class inventoryClass = at.inventoryClass() - - if (words.size() > 1) { - words[1..words.size() - 1].each { String word -> - if (word.startsWith("fields=")) { - def values = lstrip(word, "fields=") - msg["fields"] = values.split(",") - } else if (word.startsWith("limit=")) { - def value = lstrip(word, "limit=") - msg["limit"] = Integer.valueOf(value) - } else if (word.startsWith("start=")) { - def value = lstrip(word, "start=") - msg["start"] = Integer.valueOf(value) - } else if (word.startsWith("sortBy=")) { - def value = lstrip(word, "sortBy=") - msg["sortBy"] = value - } else if (word.startsWith("sortDirection=")) { - def value = lstrip(word, "sortDirection=") - msg["sortDirection"] = value - } else if (word.startsWith("count=")) { - def value = lstrip(word, "count=") - count = Boolean.parseBoolean(value) - } else if (word.startsWith("replyWithCount=")) { - def value = lstrip(word, "replyWithCount=") - replyWithCount = Boolean.parseBoolean(value) - } else { - String OP = null - String delimiter = null - for (String op : QUERY_OP_MAPPING.keySet()) { - if (word.contains(op)) { - OP = QUERY_OP_MAPPING.get(op) - delimiter = op - break - } - } - - if (OP == null) { - throw new OperationFailureException(org.zstack.core.Platform.argerr(ORG_ZSTACK_QUERY_10009, "invalid query string[%s], word[%s] doesn't have a valid operator", qstr, word)) - } - - List ks = word.split(Pattern.quote(delimiter), 2) - QueryCondition cond = new QueryCondition() - if (OP == QueryOp.IS_NULL.toString() || OP == QueryOp.NOT_NULL.toString()) { - cond.name = ks[0] - cond.op = OP - } else { - if (ks.size() != 2) { - throw new OperationFailureException(org.zstack.core.Platform.argerr(ORG_ZSTACK_QUERY_10010, "invalid query string[%s], word[%s] doesn't has key-value pair", qstr, word)) - } - cond.name = ks[0] - cond.op = OP - cond.value = ks[1] - } - - msg.getConditions().add(cond) - } - } - } - - if (count) { - msg.setCount(true) - } - if (replyWithCount) { - msg.setReplyWithCount(true) - } - if (filterName != null) { - msg.setFilterName(filterName) - } - - ZQLQueryReturn ret = queryf.queryUseZQL(msg, inventoryClass) - - def res = ["total": ret.total, "result": ret.inventories == null ? null : JSONObjectUtil.rehashObject(ret.inventories, ArrayList.class)] - - endDebug(msg, res) - - return res - } - - private long getMapMemorySize(Map m) { - String jstr = JSONObjectUtil.toJsonString(m) - return jstr.length() - } - - private String errorLine(String code, Throwable e) { - Throwable t = e - while (t.cause != null) { - t = t.cause - } - - def trace = t.stackTrace.find { - it.fileName ==~ /^Script\d+\.groovy$/ - } - - if (!trace.hasProperty("lineNumber")) { - throw e - } - - def lineNum = trace.lineNumber - 1 - println(code.readLines()) - def line = code.readLines()[lineNum] - return "${e.message}, error at line ${lineNum}: ${line}" - } - - // To mitigate Metaspace been occupied - // c.f. https://stackoverflow.com/questions/41465834 - private static void clearAllClassInfo(Class type) { - Field globalClassValue = ClassInfo.class.getDeclaredField("globalClassValue") - globalClassValue.setAccessible(true) - GroovyClassValue classValueBean = (GroovyClassValue) globalClassValue.get(null) - classValueBean.remove(type) - } - - Map query(APIBatchQueryMsg msg) { - try { - session = msg.getSession() - Binding binding = new Binding() - Map output = [:] - - def query = { doQuery(it) } - def put = { k, v -> output[k] = v } - def call = { apiName, value -> syncApiCall(apiName, value) } - def zql = { zqlQuery(it) } - - binding.setVariable("query", query) - binding.setVariable("put", put) - binding.setVariable("call", call) - binding.setVariable("zql", zql) - - def cc = new CompilerConfiguration() - cc.addCompilationCustomizers(new RejectASTTransformsCustomizer()) - cc.addCompilationCustomizers(new SandboxTransformer()) - - def shell = new GroovyShell(new GroovyClassLoader(), binding, cc) - sandbox.register() - try { - Script script = shell.parse(msg.script) - ZQLContext.putAPISession(msg.session) - script.run() - ZQLContext.clean() - clearAllClassInfo(script.getClass()) - } catch (Throwable t) { - logger.warn(t.message, t) - sandbox.unregister() - throw new OperationFailureException(org.zstack.core.Platform.operr(ORG_ZSTACK_QUERY_10011, "${errorLine(msg.script, t)}")) - } finally { - sandbox.unregister() - shell.resetLoadedClasses() - } - - printDebugInfo() - - return output - } catch (Throwable t) { - if (!(t instanceof OperationFailureException)) { - logger.warn(t.message, t) - } - - throw t - } - } -} +import static org.zstack.utils.clouderrorcode.CloudOperationsErrorCode.*; + +import org.apache.commons.lang.StringUtils +import org.codehaus.groovy.control.CompilerConfiguration +import org.codehaus.groovy.reflection.ClassInfo +import org.codehaus.groovy.reflection.GroovyClassValue +import org.kohsuke.groovy.sandbox.GroovyInterceptor +import org.kohsuke.groovy.sandbox.SandboxTransformer +import org.kohsuke.groovy.sandbox.impl.Super +import org.zstack.core.Platform +import org.zstack.core.cloudbus.CloudBus +import org.zstack.header.errorcode.OperationFailureException +import org.zstack.header.exception.CloudRuntimeException +import org.zstack.header.identity.AccountConstant +import org.zstack.header.identity.Action +import org.zstack.header.identity.SessionInventory +import org.zstack.header.identity.SuppressCredentialCheck +import org.zstack.header.message.APIMessage +import org.zstack.header.message.APIResponse +import org.zstack.header.message.APISyncCallMessage +import org.zstack.header.message.MessageReply +import org.zstack.header.query.APIQueryMessage +import org.zstack.header.query.AutoQuery +import org.zstack.header.query.QueryCondition +import org.zstack.header.query.QueryOp +import org.zstack.utils.Utils +import org.zstack.utils.gson.JSONObjectUtil +import org.zstack.utils.logging.CLogger +import org.zstack.zql.ZQL +import org.zstack.zql.ZQLContext +import org.zstack.zql.ZQLQueryReturn + +import java.lang.reflect.Field +import java.lang.reflect.Modifier +import java.util.regex.Pattern + +class BatchQuery { + private static CLogger logger = Utils.getLogger(BatchQuery.class) + + private QueryFacade queryf + private SessionInventory session + private CloudBus bus + + private static class DebugObject { + static class APIStatistics { + transient long startTime + + int timeCostPerCall + int totalTimeCost + int callTimes + long totalResultSize + long resultSizePerCall + } + + Map APIStats = [:] + long resultSize + long totalTimeCost + } + + private DebugObject debugObject; + + static class SandBox extends GroovyInterceptor { + static List RECEIVER_WHITE_LIST = [ + Number[].class, + Number.class, + long[].class, + long.class, + int[].class, + int.class, + short[].class, + short.class, + double[].class, + double.class, + float[].class, + float.class, + String[].class, + String.class, + Date[].class, + Date.class, + Map.class, + Collection.class, + Enum[].class, + Enum.class + ] + + static void checkReceiver(Object obj) { + checkReceiver(obj.getClass()) + } + + static void checkReceiver(Class clz) { + for (Class wclz : RECEIVER_WHITE_LIST) { + if (wclz.isAssignableFrom(clz)) { + return + } + } + + throw new Exception("invalid operation on class[${clz.name}]") + } + + static void checkMethod(String method) { + if (method == "sleep") { + throw new Exception("invalid operation[${method}]") + } + } + + Object onMethodCall(GroovyInterceptor.Invoker invoker, Object receiver, String method, Object... args) throws Throwable { + checkReceiver(receiver) + checkMethod(method) + return super.onMethodCall(invoker, receiver, method, args) + } + + Object onStaticCall(GroovyInterceptor.Invoker invoker, Class receiver, String method, Object... args) throws Throwable { + checkReceiver(receiver) + checkMethod(method) + return super.onStaticCall(invoker, receiver, method, args) + } + + Object onNewInstance(GroovyInterceptor.Invoker invoker, Class receiver, Object... args) throws Throwable { + checkReceiver(receiver) + return invoker.call(receiver, (String)null, (Object[])args); + } + + Object onSuperCall(GroovyInterceptor.Invoker invoker, Class senderType, Object receiver, String method, Object... args) throws Throwable { + checkReceiver(receiver) + return invoker.call(new Super(senderType, receiver), method, (Object[])args); + } + + void onSuperConstructor(GroovyInterceptor.Invoker invoker, Class receiver, Object... args) throws Throwable { + checkReceiver(receiver) + this.onNewInstance(invoker, receiver, args); + } + + Object onGetProperty(GroovyInterceptor.Invoker invoker, Object receiver, String property) throws Throwable { + checkReceiver(receiver) + return invoker.call(receiver, property); + } + + Object onSetProperty(GroovyInterceptor.Invoker invoker, Object receiver, String property, Object value) throws Throwable { + checkReceiver(receiver) + return invoker.call(receiver, property, value); + } + + Object onGetAttribute(GroovyInterceptor.Invoker invoker, Object receiver, String attribute) throws Throwable { + checkReceiver(receiver) + return invoker.call(receiver, attribute); + } + + Object onSetAttribute(GroovyInterceptor.Invoker invoker, Object receiver, String attribute, Object value) throws Throwable { + checkReceiver(receiver) + return invoker.call(receiver, attribute, value); + } + + Object onGetArray(GroovyInterceptor.Invoker invoker, Object receiver, Object index) throws Throwable { + checkReceiver(receiver) + return invoker.call(receiver, (String)null, (Object)index); + } + + Object onSetArray(GroovyInterceptor.Invoker invoker, Object receiver, Object index, Object value) throws Throwable { + checkReceiver(receiver) + return invoker.call(receiver, (String)null, index, value); + } + } + + BatchQuery() { + this.queryf = Platform.getComponentLoader().getComponent(QueryFacade.class) + this.bus = Platform.getComponentLoader().getComponent(CloudBus.class) + + if (isDebugOn()) { + debugObject = new DebugObject() + } + } + + private static SandBox sandbox = new SandBox() + + static Map queryMessageClass = [:] + static LinkedHashMap QUERY_OP_MAPPING = [:] + + static String lstrip(String s, String remove) { + return StringUtils.removeStart(s, remove) + } + + static String rstrip(String s, String remove) { + return StringUtils.removeEnd(s, remove) + } + + static { + Platform.reflections.getSubTypesOf(APISyncCallMessage.class).each { clz -> + if (Modifier.isAbstract(clz.modifiers)) { + return + } + + SuppressCredentialCheck at = clz.getAnnotation(SuppressCredentialCheck.class) + if (at != null && !at.supportBacthQuery()) { + return + } + + String name = lstrip(rstrip(clz.simpleName, "Msg"), "API") + queryMessageClass[name.toLowerCase()] = clz + queryMessageClass[clz.name] = clz + } + + // order is important, don't change it + QUERY_OP_MAPPING.put("=null", QueryOp.IS_NULL.toString()) + QUERY_OP_MAPPING.put("!=null", QueryOp.NOT_NULL.toString()) + QUERY_OP_MAPPING.put("!=", QueryOp.NOT_EQ.toString()) + QUERY_OP_MAPPING.put(">=", QueryOp.GT_AND_EQ.toString()) + QUERY_OP_MAPPING.put("<=", QueryOp.LT_AND_EQ.toString()) + QUERY_OP_MAPPING.put("!?=", QueryOp.NOT_IN.toString()) + QUERY_OP_MAPPING.put("!~=", QueryOp.NOT_LIKE.toString()) + QUERY_OP_MAPPING.put("~=", QueryOp.LIKE.toString()) + QUERY_OP_MAPPING.put("?=", QueryOp.IN.toString()) + QUERY_OP_MAPPING.put("=", QueryOp.EQ.toString()) + QUERY_OP_MAPPING.put(">", QueryOp.GT.toString()) + QUERY_OP_MAPPING.put("<", QueryOp.LT.toString()) + } + + private static boolean isDebugOn() { + return QueryGlobalConfig.BATCH_QUERY_DEBUG.value(Boolean.class) + } + + private void startDebug(APIMessage msg) { + if (isDebugOn()) { + DebugObject.APIStatistics stat = debugObject.APIStats.computeIfAbsent(msg.class.name, {new DebugObject.APIStatistics()}) + stat.startTime = System.currentTimeMillis() + } + } + + private void endDebug(APIMessage msg, Map res) { + if (isDebugOn()) { + DebugObject.APIStatistics stat = debugObject.APIStats[msg.class.name] + long timeCost = System.currentTimeMillis() - stat.startTime + stat.totalTimeCost += timeCost + stat.totalResultSize += getMapMemorySize(res) + stat.callTimes += 1 + } + } + + private void printDebugInfo() { + if (!isDebugOn()) { + return + } + + // some APIs may not complete because of error + debugObject.APIStats = debugObject.APIStats.findAll { it.value.callTimes != 0 } + + debugObject.APIStats.values().each { stat -> + stat.timeCostPerCall = (int) (stat.totalTimeCost / stat.callTimes) + stat.resultSizePerCall = (long) (stat.totalResultSize / stat.callTimes) + + debugObject.resultSize += stat.totalResultSize + debugObject.totalTimeCost += stat.totalTimeCost + } + + logger.debug("""BATCH QUERY DEBUG INFO: ${JSONObjectUtil.toJsonString(debugObject)}""") + } + + private Map syncApiCall(String apiname, String jstr) { + Class msgClz = queryMessageClass[apiname] + if (msgClz == null) { + throw new OperationFailureException(org.zstack.core.Platform.argerr(ORG_ZSTACK_QUERY_10006, "no query API found for %s", apiname)) + } + + APISyncCallMessage msg = JSONObjectUtil.toObject(jstr, msgClz) + + startDebug(msg) + + msg.setSession(session) + msg.setServiceId("api.portal") + MessageReply reply = bus.call(msg) + if (!reply.isSuccess()) { + throw new OperationFailureException(reply.error) + } + + APIResponse rsp = reply as APIResponse + def res = ["result":rsp.toResponseMap(rsp)] + + endDebug(msg, res) + + return res + } + + private List zqlQuery(String qstr){ + ZQLContext.putAPISession(session) + List result = ZQL.fromString(qstr).getResultList() + ZQLContext.cleanAPISession() + return result + } + + private Map doQuery(String qstr) { + List words = qstr.split(" ") + words = words.findAll { !it.isEmpty() } + if (words.isEmpty()) { + throw new OperationFailureException(org.zstack.core.Platform.argerr(ORG_ZSTACK_QUERY_10007, "invalid query string: %s", qstr)) + } + + String api = words[0].toLowerCase() + Class msgClz = queryMessageClass[api] + if (msgClz == null) { + throw new OperationFailureException(org.zstack.core.Platform.argerr(ORG_ZSTACK_QUERY_10008, "no query API found for %s", words[0])) + } + + APIQueryMessage msg = msgClz.getConstructor().newInstance() as APIQueryMessage + + startDebug(msg) + + msg.setSession(session) + if (AccountConstant.INITIAL_SYSTEM_ADMIN_UUID != msg.session.accountUuid && !msgClz.isAnnotationPresent(Action.class)) { + // the resource is owned by admin and the account is a normal account + //TODO: fix hard code check admin query + return ["total": 0, "result": []] + } + + msg.setConditions([]) + boolean count = false + boolean replyWithCount = false + String filterName + + AutoQuery at = msg.getClass().getAnnotation(AutoQuery.class) + if (at == null) { + throw new CloudRuntimeException("class[${msg.getClass().name}] is not annotated by AutoQuery") + } + + Class inventoryClass = at.inventoryClass() + + if (words.size() > 1) { + words[1..words.size() - 1].each { String word -> + if (word.startsWith("fields=")) { + def values = lstrip(word, "fields=") + msg["fields"] = values.split(",") + } else if (word.startsWith("limit=")) { + def value = lstrip(word, "limit=") + msg["limit"] = Integer.valueOf(value) + } else if (word.startsWith("start=")) { + def value = lstrip(word, "start=") + msg["start"] = Integer.valueOf(value) + } else if (word.startsWith("sortBy=")) { + def value = lstrip(word, "sortBy=") + msg["sortBy"] = value + } else if (word.startsWith("sortDirection=")) { + def value = lstrip(word, "sortDirection=") + msg["sortDirection"] = value + } else if (word.startsWith("count=")) { + def value = lstrip(word, "count=") + count = Boolean.parseBoolean(value) + } else if (word.startsWith("replyWithCount=")) { + def value = lstrip(word, "replyWithCount=") + replyWithCount = Boolean.parseBoolean(value) + } else { + String OP = null + String delimiter = null + for (String op : QUERY_OP_MAPPING.keySet()) { + if (word.contains(op)) { + OP = QUERY_OP_MAPPING.get(op) + delimiter = op + break + } + } + + if (OP == null) { + throw new OperationFailureException(org.zstack.core.Platform.argerr(ORG_ZSTACK_QUERY_10009, "invalid query string[%s], word[%s] doesn't have a valid operator", qstr, word)) + } + + List ks = word.split(Pattern.quote(delimiter), 2) + QueryCondition cond = new QueryCondition() + if (OP == QueryOp.IS_NULL.toString() || OP == QueryOp.NOT_NULL.toString()) { + cond.name = ks[0] + cond.op = OP + } else { + if (ks.size() != 2) { + throw new OperationFailureException(org.zstack.core.Platform.argerr(ORG_ZSTACK_QUERY_10010, "invalid query string[%s], word[%s] doesn't has key-value pair", qstr, word)) + } + cond.name = ks[0] + cond.op = OP + cond.value = ks[1] + } + + msg.getConditions().add(cond) + } + } + } + + if (count) { + msg.setCount(true) + } + if (replyWithCount) { + msg.setReplyWithCount(true) + } + if (filterName != null) { + msg.setFilterName(filterName) + } + + ZQLQueryReturn ret = queryf.queryUseZQL(msg, inventoryClass) + + def res = ["total": ret.total, "result": ret.inventories == null ? null : JSONObjectUtil.rehashObject(ret.inventories, ArrayList.class)] + + endDebug(msg, res) + + return res + } + + private long getMapMemorySize(Map m) { + String jstr = JSONObjectUtil.toJsonString(m) + return jstr.length() + } + + private String errorLine(String code, Throwable e) { + Throwable t = e + while (t.cause != null) { + t = t.cause + } + + def trace = t.stackTrace.find { + it.fileName ==~ /^Script\d+\.groovy$/ + } + + if (!trace.hasProperty("lineNumber")) { + throw e + } + + def lineNum = trace.lineNumber - 1 + println(code.readLines()) + def line = code.readLines()[lineNum] + return "${e.message}, error at line ${lineNum}: ${line}" + } + + // To mitigate Metaspace been occupied + // c.f. https://stackoverflow.com/questions/41465834 + private static void clearAllClassInfo(Class type) { + Field globalClassValue = ClassInfo.class.getDeclaredField("globalClassValue") + globalClassValue.setAccessible(true) + GroovyClassValue classValueBean = (GroovyClassValue) globalClassValue.get(null) + classValueBean.remove(type) + } + + Map query(APIBatchQueryMsg msg) { + try { + session = msg.getSession() + Binding binding = new Binding() + Map output = [:] + + def query = { doQuery(it) } + def put = { k, v -> output[k] = v } + def call = { apiName, value -> syncApiCall(apiName, value) } + def zql = { zqlQuery(it) } + + binding.setVariable("query", query) + binding.setVariable("put", put) + binding.setVariable("call", call) + binding.setVariable("zql", zql) + + def cc = new CompilerConfiguration() + cc.addCompilationCustomizers(new RejectASTTransformsCustomizer()) + cc.addCompilationCustomizers(new SandboxTransformer()) + + def shell = new GroovyShell(new GroovyClassLoader(), binding, cc) + sandbox.register() + try { + Script script = shell.parse(msg.script) + ZQLContext.putAPISession(msg.session) + script.run() + ZQLContext.clean() + clearAllClassInfo(script.getClass()) + } catch (Throwable t) { + logger.warn(t.message, t) + sandbox.unregister() + throw new OperationFailureException(org.zstack.core.Platform.operr(ORG_ZSTACK_QUERY_10011, "${errorLine(msg.script, t)}")) + } finally { + sandbox.unregister() + shell.resetLoadedClasses() + } + + printDebugInfo() + + return output + } catch (Throwable t) { + if (!(t instanceof OperationFailureException)) { + logger.warn(t.message, t) + } + + throw t + } + } +} + diff --git a/search/src/main/java/org/zstack/search/ESTuple.java b/search/src/main/java/org/zstack/search/ESTuple.java index 3926c45d21e..db0587675fc 100755 --- a/search/src/main/java/org/zstack/search/ESTuple.java +++ b/search/src/main/java/org/zstack/search/ESTuple.java @@ -39,7 +39,7 @@ public K get(String name, Class collections, Class< } String val = vals.get(name); if (val == null) { - Collection c = collections.newInstance(); + Collection c = collections.getConstructor().newInstance(); return (K) c; } return (K) JSONObjectUtil.toCollection(val, collections, clazz); diff --git a/search/src/main/java/org/zstack/zql/ast/parser/visitors/ValueVisitor.java b/search/src/main/java/org/zstack/zql/ast/parser/visitors/ValueVisitor.java index 08cfae13e86..97771297a5d 100755 --- a/search/src/main/java/org/zstack/zql/ast/parser/visitors/ValueVisitor.java +++ b/search/src/main/java/org/zstack/zql/ast/parser/visitors/ValueVisitor.java @@ -144,7 +144,7 @@ private Object callAction(String apiStr, String outputStr, Map p String apiName = "org.zstack.sdk." + apiStr + "Action"; logger.debug(String.format("start to call sdk: %s, params: %s", apiName, JSONObjectUtil.toJsonString(params))); try { - Object action = Class.forName(apiName).newInstance(); + Object action = Class.forName(apiName).getConstructor().newInstance(); params.forEach((k, v) -> { setField(action, k, v); }); diff --git a/simulator/pom.xml b/simulator/pom.xml index 4e2d713b293..580b760a13a 100755 --- a/simulator/pom.xml +++ b/simulator/pom.xml @@ -45,41 +45,55 @@ maven-compiler-plugin ${project.compiler.version} - groovy-eclipse-compiler - ${project.java.version} - ${project.java.version} - lines,vars,source + ${project.java.version} true - - - org.codehaus.groovy - groovy-eclipse-compiler - ${groovy.eclipse.compiler} - - - org.codehaus.groovy - groovy-eclipse-batch - ${groovy.eclipse.batch} - - + + + org.codehaus.gmavenplus + gmavenplus-plugin + 4.2.1 + + + + generateStubs + compile + + + + + ${groovy.version} + ${project.java.version} + + + org.codehaus.mojo aspectj-maven-plugin ${aspectj.plugin.version} + + + org.aspectj + aspectjtools + ${aspectj.version} + + - compile - test-compile + compile + test-compile - 1.6 - 1.6 - true + ${project.java.version} + ${project.java.version} + ${project.java.version} + ${project.build.sourceEncoding} + true + org.springframework diff --git a/simulator/simulatorHeader/pom.xml b/simulator/simulatorHeader/pom.xml index 42ec3205da5..90b8d5c8710 100755 --- a/simulator/simulatorHeader/pom.xml +++ b/simulator/simulatorHeader/pom.xml @@ -1,72 +1,85 @@ - - 4.0.0 - - simulator - org.zstack + + 4.0.0 + + simulator + org.zstack 5.5.0 - .. - - simulatorHeader - - - - org.apache.maven.plugins - maven-compiler-plugin - ${project.compiler.version} - - groovy-eclipse-compiler - ${project.java.version} - ${project.java.version} - lines,vars,source - true - - - - org.codehaus.groovy - groovy-eclipse-compiler - ${groovy.eclipse.compiler} - - - org.codehaus.groovy - groovy-eclipse-batch - ${groovy.eclipse.batch} - - - - - org.codehaus.mojo - aspectj-maven-plugin - ${aspectj.plugin.version} - - - - compile - test-compile - - - - - ${project.java.version} - ${project.java.version} - ${project.java.version} - true - - - org.springframework - spring-aspects - - - org.zstack - core - - - org.zstack - header - - - - - - - + .. + + simulatorHeader + + + + org.apache.maven.plugins + maven-compiler-plugin + ${project.compiler.version} + + ${project.java.version} + true + + + + + org.codehaus.gmavenplus + gmavenplus-plugin + 4.2.1 + + + + generateStubs + compile + + + + + ${groovy.version} + ${project.java.version} + + + + + org.codehaus.mojo + aspectj-maven-plugin + ${aspectj.plugin.version} + + + org.aspectj + aspectjtools + ${aspectj.version} + + + + + + compile + test-compile + + + + + ${project.java.version} + ${project.java.version} + ${project.java.version} + ${project.build.sourceEncoding} + true + + + + org.springframework + spring-aspects + + + org.zstack + core + + + org.zstack + header + + + + + + + diff --git a/simulator/simulatorImpl/pom.xml b/simulator/simulatorImpl/pom.xml index dee2cfb4b07..f4142fc4cfa 100755 --- a/simulator/simulatorImpl/pom.xml +++ b/simulator/simulatorImpl/pom.xml @@ -1,119 +1,132 @@ - - 4.0.0 - - simulator - org.zstack + + 4.0.0 + + simulator + org.zstack 5.5.0 - .. - - simulatorImpl - - - org.zstack - simulatorHeader - ${project.version} - - - org.zstack - compute - ${project.version} - - - org.zstack - applianceVm - ${project.version} - - - org.zstack - storage - ${project.version} - - - org.zstack - securityGroup - ${project.version} - - - org.zstack - kvm - ${project.version} - - - org.zstack - nfsPrimaryStorage - ${project.version} - - - org.zstack - sftpBackupStorage - ${project.version} - - - org.zstack - virtualRouterProvider - ${project.version} - - - - - - org.apache.maven.plugins - maven-compiler-plugin - ${project.compiler.version} - - groovy-eclipse-compiler - ${project.java.version} - ${project.java.version} - lines,vars,source - true - - - - org.codehaus.groovy - groovy-eclipse-compiler - ${groovy.eclipse.compiler} - - - org.codehaus.groovy - groovy-eclipse-batch - ${groovy.eclipse.batch} - - - - - org.codehaus.mojo - aspectj-maven-plugin - ${aspectj.plugin.version} - - - - compile - test-compile - - - - - ${project.java.version} - ${project.java.version} - ${project.java.version} - true - - - org.springframework - spring-aspects - - - org.zstack - core - - - org.zstack - header - - - - - - - + .. + + simulatorImpl + + + org.zstack + simulatorHeader + ${project.version} + + + org.zstack + compute + ${project.version} + + + org.zstack + applianceVm + ${project.version} + + + org.zstack + storage + ${project.version} + + + org.zstack + securityGroup + ${project.version} + + + org.zstack + kvm + ${project.version} + + + org.zstack + nfsPrimaryStorage + ${project.version} + + + org.zstack + sftpBackupStorage + ${project.version} + + + org.zstack + virtualRouterProvider + ${project.version} + + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${project.compiler.version} + + ${project.java.version} + true + + + + + org.codehaus.gmavenplus + gmavenplus-plugin + 4.2.1 + + + + generateStubs + compile + + + + + ${groovy.version} + ${project.java.version} + + + + + org.codehaus.mojo + aspectj-maven-plugin + ${aspectj.plugin.version} + + + org.aspectj + aspectjtools + ${aspectj.version} + + + + + + compile + test-compile + + + + + ${project.java.version} + ${project.java.version} + ${project.java.version} + ${project.build.sourceEncoding} + true + + + + org.springframework + spring-aspects + + + org.zstack + core + + + org.zstack + header + + + + + + + diff --git a/storage/pom.xml b/storage/pom.xml index 9aaddc0626c..3b3c3b78bbd 100755 --- a/storage/pom.xml +++ b/storage/pom.xml @@ -1,120 +1,116 @@ - - 4.0.0 - - zstack - org.zstack + + 4.0.0 + + zstack + org.zstack 5.5.0 - .. - - storage - - - - org.zstack - core - ${project.version} - - - org.zstack - utils - ${project.version} - - - org.zstack - search - ${project.version} - - - org.zstack - identity - ${project.version} - - - org.zstack - header - ${project.version} - - - org.zstack - tag - ${project.version} - - - org.zstack - resourceconfig - ${project.version} - - - org.zstack - configuration - ${project.version} - - - org.zstack - longjob - ${project.version} - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - ${project.compiler.version} - - groovy-eclipse-compiler - ${project.java.version} - ${project.java.version} - lines,vars,source - true - - - - org.codehaus.groovy - groovy-eclipse-compiler - ${groovy.eclipse.compiler} - - - org.codehaus.groovy - groovy-eclipse-batch - ${groovy.eclipse.batch} - - - - - org.codehaus.mojo - aspectj-maven-plugin - ${aspectj.plugin.version} - - - - compile - test-compile - - - - - ${project.java.version} - ${project.java.version} - ${project.java.version} - true - - - org.springframework - spring-aspects - - - org.zstack - core - - - org.zstack - header - - - - - - - + .. + + storage + + + + org.zstack + core + ${project.version} + + + org.zstack + utils + ${project.version} + + + org.zstack + search + ${project.version} + + + org.zstack + identity + ${project.version} + + + org.zstack + header + ${project.version} + + + org.zstack + tag + ${project.version} + + + org.zstack + resourceconfig + ${project.version} + + + org.zstack + configuration + ${project.version} + + + org.zstack + longjob + ${project.version} + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${project.compiler.version} + + ${project.java.version} + true + true + + + + + org.codehaus.mojo + aspectj-maven-plugin + ${aspectj.plugin.version} + + + org.aspectj + aspectjtools + ${aspectj.version} + + + + + + compile + test-compile + + + + + ${project.java.version} + ${project.java.version} + ${project.java.version} + ${project.build.sourceEncoding} + true + + + + org.springframework + spring-aspects + + + org.zstack + core + + + org.zstack + header + + + + + + + diff --git a/storage/src/main/java/org/zstack/storage/primary/AbstractUsageReport.java b/storage/src/main/java/org/zstack/storage/primary/AbstractUsageReport.java index 7cb7f4daf6c..a621b31e622 100644 --- a/storage/src/main/java/org/zstack/storage/primary/AbstractUsageReport.java +++ b/storage/src/main/java/org/zstack/storage/primary/AbstractUsageReport.java @@ -354,8 +354,8 @@ private void addMissingDataIfNeeded(List existedUsageVOs, HistoricalUsageLoad IntStream.range(1, (int) days).forEach(i -> { T vo; try { - vo = usageClass.newInstance(); - } catch (InstantiationException | IllegalAccessException e) { + vo = usageClass.getConstructor().newInstance(); + } catch (Exception e) { throw new RuntimeException(e); } @@ -444,8 +444,8 @@ protected void collectUsage(LocalDate nowRecordDate) { if (usageRecordedNotInDatabase(usage.getResourceUuid(), nowRecordDate, historicalLastUsageRecordDateMap)) { T vo; try { - vo = usageClass.newInstance(); - } catch (InstantiationException | IllegalAccessException e) { + vo = usageClass.getConstructor().newInstance(); + } catch (Exception e) { throw new RuntimeException(e); } vo.setPrimaryStorageUuid(usage.getPrimaryStorageUuid()); diff --git a/tag/pom.xml b/tag/pom.xml index b7351a5c699..c1bc0aae5bb 100755 --- a/tag/pom.xml +++ b/tag/pom.xml @@ -51,29 +51,23 @@ maven-compiler-plugin ${project.compiler.version} - groovy-eclipse-compiler - ${project.java.version} - ${project.java.version} - lines,vars,source + ${project.java.version} true + true - - - org.codehaus.groovy - groovy-eclipse-compiler - ${groovy.eclipse.compiler} - - - org.codehaus.groovy - groovy-eclipse-batch - ${groovy.eclipse.batch} - - + org.codehaus.mojo aspectj-maven-plugin ${aspectj.plugin.version} + + + org.aspectj + aspectjtools + ${aspectj.version} + + @@ -83,10 +77,12 @@ + ${project.java.version} ${project.java.version} ${project.java.version} - ${project.java.version} - true + ${project.build.sourceEncoding} + true + org.springframework diff --git a/tag/src/main/java/org/zstack/tag/PatternedSystemTag.java b/tag/src/main/java/org/zstack/tag/PatternedSystemTag.java index 5bd1bcd56eb..e06e2fcfbdc 100755 --- a/tag/src/main/java/org/zstack/tag/PatternedSystemTag.java +++ b/tag/src/main/java/org/zstack/tag/PatternedSystemTag.java @@ -127,9 +127,9 @@ public String hideSensitiveInfo(String tag) { Class clz = this.annotation.customizeOutput(); String result = tag; try { - SensitiveTagOutputHandler sensitiveOutputHandler = clz.newInstance(); + SensitiveTagOutputHandler sensitiveOutputHandler = clz.getConstructor().newInstance(); result = sensitiveOutputHandler.desensitizeTag(this, tag); - } catch (InstantiationException | IllegalAccessException e) { + } catch (Exception e) { logger.warn("exception happened :", e); } return result; diff --git a/test/pom.xml b/test/pom.xml index 7dfbb0bbcac..b3a9c50e155 100644 --- a/test/pom.xml +++ b/test/pom.xml @@ -1,603 +1,691 @@ - - - true - ${env.skipJacoco} - ${skipJacoco} - - 4.0.0 - - zstack - org.zstack + + + true + ${env.skipJacoco} + ${skipJacoco} + + 4.0.0 + + zstack + org.zstack 5.5.0 - .. - - test - - - - - - org.kohsuke - groovy-sandbox - 1.19 - - - - junit - junit - 4.13.1 - - - org.zapodot - embedded-ldap-junit - 0.7 - test - - - - org.mockito - mockito-core - 4.11.0 - - - - org.zstack - core - ${project.version} - - - org.zstack - compute - ${project.version} - - - org.zstack - header - ${project.version} - - - org.zstack - portal - ${project.version} - - - org.zstack - utils - ${project.version} - - - org.zstack - external-service - ${project.version} - - - org.zstack - simulatorImpl - ${project.version} - - - org.zstack - image - ${project.version} - - - org.zstack - network - ${project.version} - - - org.zstack - configuration - ${project.version} - - - org.zstack - identity - ${project.version} - - - org.zstack - search - ${project.version} - - - org.zstack - console - ${project.version} - - - org.zstack - applianceVm - ${project.version} - - - org.zstack - localstorage - ${project.version} - - - org.zstack - externalStorage - ${project.version} - - - org.zstack - zbs - ${project.version} - - - org.zstack - cbd - ${project.version} - - - org.zstack - expon - ${project.version} - - - org.zstack - xinfini - ${project.version} - - - org.zstack - vhost - ${project.version} - - - org.zstack - iscsi - ${project.version} - - - org.zstack - ceph - ${project.version} - - - org.zstack - sharedMountPointPrimaryStorage - ${project.version} - - - org.zstack - ldap - ${project.version} - - - - org.jboss.shrinkwrap - shrinkwrap-api - 1.0.0-alpha-12 - test - - - org.jboss.shrinkwrap - 1.0.0-alpha-12 - shrinkwrap-impl-base - test - - - org.eclipse.jetty - jetty-server - 9.4.51.v20230217 - - - org.eclipse.jetty - jetty-webapp - 9.4.49.v20220914 - - - - org.zstack - kvm - ${project.version} - - - org.zstack - nfsPrimaryStorage - ${project.version} - - - org.zstack - sftpBackupStorage - ${project.version} - - - org.zstack - virtualRouterProvider - ${project.version} - - - org.zstack - securityGroup - ${project.version} - - - org.zstack - vip - ${project.version} - - - org.zstack - mediator - ${project.version} - - - org.zstack - flatNetworkProvider - ${project.version} - - - org.zstack - rest - ${project.version} - - - org.zstack - vxlan - ${project.version} - - - org.zstack - sdnController - ${project.version} - - - org.zstack - longjob - ${project.version} - - - org.zstack - sshKeyPair - ${project.version} - - - org.zstack - sdk - ${project.version} - - - org.zstack - sugonSdnController - ${project.version} - - - org.zstack - hostNetworkInterface - ${project.version} - - - org.zstack - testlib - ${project.version} - - - com.github.javaparser - javaparser-core - - - org.jasig.cas.client - cas-client-core - - - - - - merge - - - - org.apache.maven.plugins - maven-antrun-plugin - 1.8 - - - - - run - - - default-cli - - - - - - - - - - - - - - - - - - org.jacoco - org.jacoco.ant - 0.8.6 - - - - - - - - - coverage - - - - org.apache.maven.plugins - maven-antrun-plugin - 1.8 - - - - run - - - default-cli - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - org.jacoco - org.jacoco.ant - 0.8.6 - - - - - - - - - coverage-xml - - - - org.apache.maven.plugins - maven-antrun-plugin - 1.8 - - - - run - - - default-cli - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - org.jacoco - org.jacoco.ant - 0.8.6 - - - - - - - - - - - - - org.jacoco - jacoco-maven-plugin - 0.8.6 - - - - prepare-agent - - prepare-agent - - - true - target/classes - - org.zstack.* - - target/jacoco.exec - - - - - - - org.apache.maven.plugins - maven-surefire-plugin - 2.18 - - - c3p0:c3p0:jar:0.9.1.1 - - - - - - org.apache.maven.plugins - maven-compiler-plugin - ${project.compiler.version} - - ${project.java.version} - ${project.java.version} - true - false - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.6.1 - - groovy-eclipse-compiler - ${project.java.version} - ${project.java.version} - lines,vars,source - true - - - - org.codehaus.groovy - groovy-eclipse-compiler - 2.9.2-01 - - - org.codehaus.groovy - groovy-eclipse-batch - 2.4.3-01 - - - - - - org.codehaus.mojo - aspectj-maven-plugin - ${aspectj.plugin.version} - - - - compile - test-compile - - - - - ${project.java.version} - ${project.java.version} - ${project.java.version} - true - - - org.springframework - spring-aspects - - - org.zstack - core - - - org.zstack - header - - - - - - - maven-resources-plugin - 2.5 - - - copy-conf - - validate - - copy-resources - - - target/test-classes - true - - - ../conf - - - - - - - - - + .. + + test + + + + + + + org.apache.groovy + groovy + ${groovy.version} + + + org.kohsuke + groovy-sandbox + 1.19 + + + + junit + junit + 4.13.1 + + + org.zapodot + embedded-ldap-junit + 0.7 + test + + + + org.mockito + mockito-core + 4.11.0 + + + + org.zstack + core + ${project.version} + + + org.zstack + compute + ${project.version} + + + org.zstack + header + ${project.version} + + + org.zstack + portal + ${project.version} + + + org.zstack + utils + ${project.version} + + + org.zstack + external-service + ${project.version} + + + org.zstack + simulatorImpl + ${project.version} + + + org.zstack + image + ${project.version} + + + org.zstack + network + ${project.version} + + + org.zstack + configuration + ${project.version} + + + org.zstack + identity + ${project.version} + + + org.zstack + search + ${project.version} + + + org.zstack + console + ${project.version} + + + org.zstack + applianceVm + ${project.version} + + + org.zstack + localstorage + ${project.version} + + + org.zstack + externalStorage + ${project.version} + + + org.zstack + zbs + ${project.version} + + + org.zstack + cbd + ${project.version} + + + org.zstack + expon + ${project.version} + + + org.zstack + xinfini + ${project.version} + + + org.zstack + vhost + ${project.version} + + + org.zstack + iscsi + ${project.version} + + + org.zstack + ceph + ${project.version} + + + org.zstack + sharedMountPointPrimaryStorage + ${project.version} + + + org.zstack + ldap + ${project.version} + + + + org.jboss.shrinkwrap + shrinkwrap-api + 1.0.0-alpha-12 + test + + + org.jboss.shrinkwrap + 1.0.0-alpha-12 + shrinkwrap-impl-base + test + + + org.eclipse.jetty + jetty-server + 9.4.51.v20230217 + + + org.eclipse.jetty + jetty-webapp + 9.4.49.v20220914 + + + + org.zstack + kvm + ${project.version} + + + org.zstack + nfsPrimaryStorage + ${project.version} + + + org.zstack + sftpBackupStorage + ${project.version} + + + org.zstack + virtualRouterProvider + ${project.version} + + + org.zstack + securityGroup + ${project.version} + + + org.zstack + vip + ${project.version} + + + org.zstack + mediator + ${project.version} + + + org.zstack + flatNetworkProvider + ${project.version} + + + org.zstack + rest + ${project.version} + + + org.zstack + vxlan + ${project.version} + + + org.zstack + sdnController + ${project.version} + + + org.zstack + longjob + ${project.version} + + + org.zstack + sshKeyPair + ${project.version} + + + org.zstack + sdk + ${project.version} + + + org.zstack + sugonSdnController + ${project.version} + + + org.zstack + hostNetworkInterface + ${project.version} + + + org.zstack + testlib + ${project.version} + + + com.github.javaparser + javaparser-core + + + org.jasig.cas.client + cas-client-core + + + + + + merge + + + + org.apache.maven.plugins + maven-antrun-plugin + 1.8 + + + + + run + + + default-cli + + + + + + + + + + + + + + + + + + org.jacoco + org.jacoco.ant + 0.8.6 + + + + + + + + + coverage + + + + org.apache.maven.plugins + maven-antrun-plugin + 1.8 + + + + run + + + default-cli + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + org.jacoco + org.jacoco.ant + 0.8.6 + + + + + + + + + coverage-xml + + + + org.apache.maven.plugins + maven-antrun-plugin + 1.8 + + + + run + + + default-cli + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + org.jacoco + org.jacoco.ant + 0.8.6 + + + + + + + + + + + + + org.jacoco + jacoco-maven-plugin + 0.8.6 + + + + prepare-agent + + prepare-agent + + + true + target/classes + + org.zstack.* + + target/jacoco.exec + + + + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.18 + + + c3p0:c3p0:jar:0.9.1.1 + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 3.4.0 + + + add-test-source + generate-test-sources + + add-test-source + + + + ${project.basedir}/src/test/groovy + + + + + + + + + org.codehaus.gmavenplus + gmavenplus-plugin + 4.2.1 + + + org.apache.groovy + groovy + ${groovy.version} + + + + + generate-stubs + process-sources + + generateStubs + + + + compile-groovy + compile + + compile + + + + generate-test-stubs + process-test-sources + + generateTestStubs + + + + compile-test-groovy + test-compile + + compileTests + + + + + + true + ${groovy.version} + ${project.java.version} + + + ${project.basedir}/src/main/java + + **/*.groovy + + + + ${project.basedir}/src/main/groovy + + **/*.groovy + + + + + + ${project.basedir}/src/test/java + + **/*.groovy + + + + ${project.basedir}/src/test/groovy + + **/*.groovy + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + ${project.compiler.version} + + ${project.java.version} + true + true + false + + + + + org.codehaus.mojo + aspectj-maven-plugin + ${aspectj.plugin.version} + + + org.aspectj + aspectjtools + ${aspectj.version} + + + + + + compile + test-compile + + + + + ${project.java.version} + ${project.java.version} + ${project.java.version} + true + none + + + org.springframework + spring-aspects + + + org.zstack + core + + + org.zstack + header + + + + + + + maven-resources-plugin + 2.5 + + + copy-conf + + validate + + copy-resources + + + target/test-classes + true + + + ../conf + + + + + + + + + diff --git a/test/src/test/groovy/org/zstack/test/integration/core/gc/EventBasedGarbageCollectorCase.groovy b/test/src/test/groovy/org/zstack/test/integration/core/gc/EventBasedGarbageCollectorCase.groovy index 0bc76b3d065..b4c08a6eadb 100755 --- a/test/src/test/groovy/org/zstack/test/integration/core/gc/EventBasedGarbageCollectorCase.groovy +++ b/test/src/test/groovy/org/zstack/test/integration/core/gc/EventBasedGarbageCollectorCase.groovy @@ -1,5 +1,5 @@ -package org.zstack.test.integration.core.gc - +package org.zstack.test.integration.core.gc + import static org.zstack.utils.clouderrorcode.CloudOperationsErrorCode.*; import org.apache.commons.collections.map.HashedMap @@ -78,7 +78,7 @@ class EventBasedGarbageCollectorCase extends SubCase { } } - static Map> testLogicForJobLoadedFromDbMap = new HashedMap<>() + static Map> testLogicForJobLoadedFromDbMap = new HashedMap() static enum EventBasedGCInDbBehavior { SUCCESS, @@ -125,7 +125,7 @@ class EventBasedGarbageCollectorCase extends SubCase { } } - static Map> testTriggerNowForJobLoadedFromDbMap = new HashedMap<>() + static Map> testTriggerNowForJobLoadedFromDbMap = new HashedMap() static class EventBasedGCInDbTriggerNow extends EventBasedGarbageCollector { Closure trigger = { true } diff --git a/test/src/test/groovy/org/zstack/test/integration/network/l2network/AttachL2NetworkWithTwoClustersCase.groovy b/test/src/test/groovy/org/zstack/test/integration/network/l2network/AttachL2NetworkWithTwoClustersCase.groovy index 7240e3fcc53..a0c13f5c9a4 100644 --- a/test/src/test/groovy/org/zstack/test/integration/network/l2network/AttachL2NetworkWithTwoClustersCase.groovy +++ b/test/src/test/groovy/org/zstack/test/integration/network/l2network/AttachL2NetworkWithTwoClustersCase.groovy @@ -208,7 +208,7 @@ public class AttachL2NetworkWithTwoClustersCase extends SubCase{ } assert vm2.hostUuid == host2.uuid - def cmds = [] as SynchronizedList + def cmds = [] as SynchronizedList env.afterSimulator(KVMConstant.KVM_DELETE_L2NOVLAN_NETWORK_PATH) { rsp, HttpEntity e -> def deleteBridgeCmd = JSONObjectUtil.toObject(e.body, KVMAgentCommands.DeleteBridgeCmd.class) cmds.add(deleteBridgeCmd) @@ -262,7 +262,7 @@ public class AttachL2NetworkWithTwoClustersCase extends SubCase{ } assert vm2.hostUuid == host2.uuid - def cmds = [] as SynchronizedList + def cmds = [] as SynchronizedList env.afterSimulator(KVMConstant.KVM_DELETE_L2VLAN_NETWORK_PATH) { rsp, HttpEntity e -> def deleteBridgeCmd = JSONObjectUtil.toObject(e.body, KVMAgentCommands.DeleteVlanBridgeCmd.class) cmds.add(deleteBridgeCmd) @@ -374,7 +374,7 @@ public class AttachL2NetworkWithTwoClustersCase extends SubCase{ } assert vm2.hostUuid == host2.uuid - def cmds = [] as SynchronizedList + def cmds = [] as SynchronizedList env.afterSimulator(VxlanNetworkPoolConstant.VXLAN_KVM_DELETE_L2VXLAN_NETWORK_PATH) { rsp, HttpEntity e -> def deleteBridgeCmd = JSONObjectUtil.toObject(e.body, VxlanKvmAgentCommands.DeleteVxlanBridgeCmd.class) cmds.add(deleteBridgeCmd) diff --git a/test/src/test/groovy/org/zstack/test/integration/network/l2network/DeleteL2NetworkBridgeCase.groovy b/test/src/test/groovy/org/zstack/test/integration/network/l2network/DeleteL2NetworkBridgeCase.groovy index 65896171966..439a4409e43 100644 --- a/test/src/test/groovy/org/zstack/test/integration/network/l2network/DeleteL2NetworkBridgeCase.groovy +++ b/test/src/test/groovy/org/zstack/test/integration/network/l2network/DeleteL2NetworkBridgeCase.groovy @@ -129,7 +129,7 @@ class DeleteL2NetworkBridgeCase extends SubCase { clusterUuid = cluster.uuid } - def cmds = [] as SynchronizedList + def cmds = [] as SynchronizedList env.afterSimulator(KVMConstant.KVM_DELETE_L2NOVLAN_NETWORK_PATH) { rsp, HttpEntity e -> def deleteBridgeCmd = JSONObjectUtil.toObject(e.body, KVMAgentCommands.DeleteBridgeCmd.class) cmds.add(deleteBridgeCmd) @@ -158,7 +158,7 @@ class DeleteL2NetworkBridgeCase extends SubCase { clusterUuid = cluster.uuid } - def cmds = [] as SynchronizedList + def cmds = [] as SynchronizedList env.afterSimulator(KVMConstant.KVM_DELETE_L2NOVLAN_NETWORK_PATH) { rsp, HttpEntity e -> def deleteBridgeCmd = JSONObjectUtil.toObject(e.body, KVMAgentCommands.DeleteBridgeCmd.class) cmds.add(deleteBridgeCmd) @@ -192,7 +192,7 @@ class DeleteL2NetworkBridgeCase extends SubCase { clusterUuid = cluster.uuid } - def cmds = [] as SynchronizedList + def cmds = [] as SynchronizedList env.afterSimulator(KVMConstant.KVM_DELETE_L2VLAN_NETWORK_PATH) { rsp, HttpEntity e -> def deleteVlanBridgeCmd = JSONObjectUtil.toObject(e.body, KVMAgentCommands.DeleteVlanBridgeCmd.class) cmds.add(deleteVlanBridgeCmd) @@ -223,7 +223,7 @@ class DeleteL2NetworkBridgeCase extends SubCase { clusterUuid = cluster.uuid } - def cmds = [] as SynchronizedList + def cmds = [] as SynchronizedList env.afterSimulator(KVMConstant.KVM_DELETE_L2VLAN_NETWORK_PATH) { rsp, HttpEntity e -> def deleteVlanBridgeCmd = JSONObjectUtil.toObject(e.body, KVMAgentCommands.DeleteVlanBridgeCmd.class) cmds.add(deleteVlanBridgeCmd) @@ -278,7 +278,7 @@ class DeleteL2NetworkBridgeCase extends SubCase { } - def cmds = [] as SynchronizedList + def cmds = [] as SynchronizedList env.afterSimulator(VxlanNetworkPoolConstant.VXLAN_KVM_DELETE_L2VXLAN_NETWORK_PATH) { rsp, HttpEntity e -> def deleteVxlanBridgeCmd = JSONObjectUtil.toObject(e.body, VxlanKvmAgentCommands.DeleteVxlanBridgeCmd.class) cmds.add(deleteVxlanBridgeCmd) @@ -336,7 +336,7 @@ class DeleteL2NetworkBridgeCase extends SubCase { } - def cmds = [] as SynchronizedList + def cmds = [] as SynchronizedList env.afterSimulator(VxlanNetworkPoolConstant.VXLAN_KVM_DELETE_L2VXLAN_NETWORK_PATH) { rsp, HttpEntity e -> def deleteVxlanBridgeCmd = JSONObjectUtil.toObject(e.body, VxlanKvmAgentCommands.DeleteVxlanBridgeCmd.class) cmds.add(deleteVxlanBridgeCmd) @@ -393,7 +393,7 @@ class DeleteL2NetworkBridgeCase extends SubCase { } - def cmds = [] as SynchronizedList + def cmds = [] as SynchronizedList env.afterSimulator(VxlanNetworkPoolConstant.VXLAN_KVM_DELETE_L2VXLAN_NETWORK_PATH) { rsp, HttpEntity e -> def deleteVxlanBridgeCmd = JSONObjectUtil.toObject(e.body, VxlanKvmAgentCommands.DeleteVxlanBridgeCmd.class) cmds.add(deleteVxlanBridgeCmd) @@ -431,7 +431,7 @@ class DeleteL2NetworkBridgeCase extends SubCase { return resp } - def cmds = [] as SynchronizedList + def cmds = [] as SynchronizedList env.afterSimulator(KVMConstant.KVM_DELETE_L2NOVLAN_NETWORK_PATH) { rsp, HttpEntity e -> def deleteBridgeCmd = JSONObjectUtil.toObject(e.body, KVMAgentCommands.DeleteBridgeCmd.class) cmds.add(deleteBridgeCmd) diff --git a/test/src/test/groovy/org/zstack/test/integration/network/sdnController/SdnControllerCase.groovy b/test/src/test/groovy/org/zstack/test/integration/network/sdnController/SdnControllerCase.groovy index c07c9c3314c..ef3983055c6 100644 --- a/test/src/test/groovy/org/zstack/test/integration/network/sdnController/SdnControllerCase.groovy +++ b/test/src/test/groovy/org/zstack/test/integration/network/sdnController/SdnControllerCase.groovy @@ -12,6 +12,7 @@ import org.zstack.sdk.SdnControllerInventory import org.zstack.sdk.ZoneInventory import org.zstack.sdnController.SdnControllerGlobalConfig import org.zstack.sdnController.SdnControllerSystemTags +import org.zstack.sdnController.h3cVcfc.H3cVcfcCommands import org.zstack.sdnController.h3cVcfc.H3cVcfcV2Commands import org.zstack.header.network.sdncontroller.SdnControllerConstant import org.zstack.sdnController.header.H3cSdnControllerTenantVO @@ -374,8 +375,8 @@ class SdnControllerCase extends SubCase { void testSdnControllerPing() { // Setup mock simulator for successful controller creation env.simulator(H3cVcfcV2Commands.H3C_VCFC_GET_TOKEN) { HttpEntity e, EnvSpec spec -> - def rsp = new H3cVcfcV2Commands.LoginRsp() - rsp.record = new H3cVcfcV2Commands.LoginReply() + def rsp = new H3cVcfcCommands.LoginRsp() + rsp.record = new H3cVcfcCommands.LoginReply() rsp.record.token = "init-token-12345" rsp.record.userName = "user" rsp.record.domainName = "default" @@ -400,7 +401,7 @@ class SdnControllerCase extends SubCase { // Mock token retrieval failure to simulate ping failure env.simulator(H3cVcfcV2Commands.H3C_VCFC_GET_TOKEN) { HttpEntity e, EnvSpec spec -> - def rsp = new H3cVcfcV2Commands.LoginRsp() + def rsp = new H3cVcfcCommands.LoginRsp() rsp.record = null return rsp } @@ -413,8 +414,8 @@ class SdnControllerCase extends SubCase { // Mock token retrieval success to simulate ping recovery env.simulator(H3cVcfcV2Commands.H3C_VCFC_GET_TOKEN) { HttpEntity e, EnvSpec spec -> - def rsp = new H3cVcfcV2Commands.LoginRsp() - rsp.record = new H3cVcfcV2Commands.LoginReply() + def rsp = new H3cVcfcCommands.LoginRsp() + rsp.record = new H3cVcfcCommands.LoginReply() rsp.record.token = "test-token-12345" rsp.record.userName = "user" rsp.record.domainName = "default" @@ -436,8 +437,8 @@ class SdnControllerCase extends SubCase { void testSdnControllerReconnect() { // Setup mock simulator for successful controller creation env.simulator(H3cVcfcV2Commands.H3C_VCFC_GET_TOKEN) { HttpEntity e, EnvSpec spec -> - def rsp = new H3cVcfcV2Commands.LoginRsp() - rsp.record = new H3cVcfcV2Commands.LoginReply() + def rsp = new H3cVcfcCommands.LoginRsp() + rsp.record = new H3cVcfcCommands.LoginReply() rsp.record.token = "init-token-67890" rsp.record.userName = "user" rsp.record.domainName = "default" @@ -461,8 +462,8 @@ class SdnControllerCase extends SubCase { boolean reconnectCalled = false env.simulator(H3cVcfcV2Commands.H3C_VCFC_GET_TOKEN) { HttpEntity e, EnvSpec spec -> reconnectCalled = true - def rsp = new H3cVcfcV2Commands.LoginRsp() - rsp.record = new H3cVcfcV2Commands.LoginReply() + def rsp = new H3cVcfcCommands.LoginRsp() + rsp.record = new H3cVcfcCommands.LoginReply() rsp.record.token = "reconnect-token-67890" rsp.record.userName = "user" rsp.record.domainName = "default" diff --git a/test/src/test/groovy/org/zstack/test/integration/network/vxlanNetwork/AddVxlanVtepIpCase.groovy b/test/src/test/groovy/org/zstack/test/integration/network/vxlanNetwork/AddVxlanVtepIpCase.groovy index 0a483f6759b..7055aac65fa 100644 --- a/test/src/test/groovy/org/zstack/test/integration/network/vxlanNetwork/AddVxlanVtepIpCase.groovy +++ b/test/src/test/groovy/org/zstack/test/integration/network/vxlanNetwork/AddVxlanVtepIpCase.groovy @@ -274,7 +274,7 @@ class AddVxlanVtepIpCase extends SubCase { resp.setSuccess(true) return resp } - def cmds = [] as SynchronizedList + def cmds = [] as SynchronizedList env.afterSimulator(VxlanNetworkPoolConstant.VXLAN_KVM_POPULATE_FDB_L2VXLAN_NETWORKS_PATH) { rsp, HttpEntity e -> VxlanKvmAgentCommands.PopulateVxlanNetworksFdbCmd cmd = JSONObjectUtil.toObject(e.body, VxlanKvmAgentCommands.PopulateVxlanNetworksFdbCmd.class) cmds.add(cmd) diff --git a/test/src/test/groovy/org/zstack/test/integration/network/vxlanNetwork/VxlanLazyAttachCase.groovy b/test/src/test/groovy/org/zstack/test/integration/network/vxlanNetwork/VxlanLazyAttachCase.groovy index 25312b5e555..2354f456f6d 100644 --- a/test/src/test/groovy/org/zstack/test/integration/network/vxlanNetwork/VxlanLazyAttachCase.groovy +++ b/test/src/test/groovy/org/zstack/test/integration/network/vxlanNetwork/VxlanLazyAttachCase.groovy @@ -310,7 +310,7 @@ class VxlanLazyAttachCase extends SubCase { return rsp } - def realizeRecords = [] as SynchronizedList + def realizeRecords = [] as SynchronizedList List createBridgeCmds = new ArrayList<>() createBridgeCmds = Collections.synchronizedList(new ArrayList()) env.simulator(VxlanNetworkPoolConstant.VXLAN_KVM_REALIZE_L2VXLAN_NETWORK_PATH) { HttpEntity entity, EnvSpec spec -> diff --git a/test/src/test/groovy/org/zstack/test/integration/network/vxlanNetwork/VxlanVtepIpChangedCase.groovy b/test/src/test/groovy/org/zstack/test/integration/network/vxlanNetwork/VxlanVtepIpChangedCase.groovy index b480d241b8e..8e2d7e23a7f 100644 --- a/test/src/test/groovy/org/zstack/test/integration/network/vxlanNetwork/VxlanVtepIpChangedCase.groovy +++ b/test/src/test/groovy/org/zstack/test/integration/network/vxlanNetwork/VxlanVtepIpChangedCase.groovy @@ -242,14 +242,14 @@ class VxlanVtepIpChangedCase extends SubCase { return resp } - def records = [] as SynchronizedList + def records = [] as SynchronizedList env.simulator(VxlanNetworkPoolConstant.VXLAN_KVM_POPULATE_FDB_L2VXLAN_NETWORKS_PATH) { HttpEntity entity, EnvSpec spec -> def cmd = JSONObjectUtil.toObject(entity.body, VxlanKvmAgentCommands.PopulateVxlanNetworksFdbCmd.class) records.add(cmd.networkUuids) return new VxlanKvmAgentCommands.PopulateVxlanNetworksFdbCmd() } - def realizeRecords = [] as SynchronizedList + def realizeRecords = [] as SynchronizedList env.simulator(VxlanNetworkPoolConstant.VXLAN_KVM_REALIZE_L2VXLAN_NETWORKS_PATH) { HttpEntity entity, EnvSpec spec -> def cmd = JSONObjectUtil.toObject(entity.body, VxlanKvmAgentCommands.CreateVxlanBridgesCmd.class) for (VxlanKvmAgentCommands.CreateVxlanBridgeCmd bcmd : cmd.bridgeCmds) { diff --git a/test/src/test/groovy/org/zstack/test/integration/networkservice/provider/flat/dhcp/CheckFlatDhcpWorkCase.groovy b/test/src/test/groovy/org/zstack/test/integration/networkservice/provider/flat/dhcp/CheckFlatDhcpWorkCase.groovy index 3214f30911e..12efbccb36d 100644 --- a/test/src/test/groovy/org/zstack/test/integration/networkservice/provider/flat/dhcp/CheckFlatDhcpWorkCase.groovy +++ b/test/src/test/groovy/org/zstack/test/integration/networkservice/provider/flat/dhcp/CheckFlatDhcpWorkCase.groovy @@ -258,14 +258,14 @@ class CheckFlatDhcpWorkCase extends SubCase{ } assert flushCmds.size() == 2 flushCmds.clear() - l31 = queryL3Network{ conditions = ["uuid=${l31.uuid}"]}[0] - for (NetworkServiceL3NetworkRefInventory ref : l31.networkServices) { + def l31Refreshed = queryL3Network{ conditions = ["uuid=${l31.uuid}"]}[0] + for (NetworkServiceL3NetworkRefInventory ref : l31Refreshed.networkServices) { if (ref.networkServiceType == "DHCP") { assert false } } GetL3NetworkDhcpIpAddressResult ret = getL3NetworkDhcpIpAddress { - l3NetworkUuid = l31.uuid + l3NetworkUuid = l31Refreshed.uuid } assert ret.ip6 == null assert ret.ip == null @@ -283,19 +283,19 @@ class CheckFlatDhcpWorkCase extends SubCase{ } assert bCmds.size() == 2 bCmds.clear() - l31 = queryL3Network{ conditions = ["uuid=${l31.uuid}"]}[0] - List services = l31.networkServices.stream().map {ref -> ref.networkServiceType}.collect(Collectors.toList()) + def l31Refreshed2 = queryL3Network{ conditions = ["uuid=${l31.uuid}"]}[0] + List services = l31Refreshed2.networkServices.stream().map {ref -> ref.networkServiceType}.collect(Collectors.toList()) assert services.contains("DHCP") detachNetworkServiceFromL3Network { - l3NetworkUuid = l31.uuid + l3NetworkUuid = l31Refreshed2.uuid service = 'DHCP' } /* dhcp is disabled, can not change dhcp server ip */ expect(AssertionError.class) { changeL3NetworkDhcpIpAddress { - l3NetworkUuid = l31.uuid + l3NetworkUuid = l31Refreshed2.uuid dhcpServerIp = "172.16.10.10" } } @@ -380,14 +380,14 @@ class CheckFlatDhcpWorkCase extends SubCase{ } assert flushCmds.size() == 2 flushCmds.clear() - l32 = queryL3Network{ conditions = ["uuid=${l32.uuid}"]}[0] - for (NetworkServiceL3NetworkRefInventory ref : l32.networkServices) { + def l32Refreshed = queryL3Network{ conditions = ["uuid=${l32.uuid}"]}[0] + for (NetworkServiceL3NetworkRefInventory ref : l32Refreshed.networkServices) { if (ref.networkServiceType == "DHCP") { assert false } } GetL3NetworkDhcpIpAddressResult ret = getL3NetworkDhcpIpAddress { - l3NetworkUuid = l32.uuid + l3NetworkUuid = l32Refreshed.uuid } assert ret.ip6 == null assert ret.ip == null @@ -405,29 +405,29 @@ class CheckFlatDhcpWorkCase extends SubCase{ } assert bCmds.size() == 2 bCmds.clear() - l32 = queryL3Network{ conditions = ["uuid=${l32.uuid}"]}[0] - List services = l32.networkServices.stream().map {ref -> ref.networkServiceType}.collect(Collectors.toList()) + def l32Refreshed2 = queryL3Network{ conditions = ["uuid=${l32.uuid}"]}[0] + List services = l32Refreshed2.networkServices.stream().map {ref -> ref.networkServiceType}.collect(Collectors.toList()) assert services.contains("DHCP") - UsedIpInventory usedIp4 = queryIpAddress {conditions=["l3NetworkUuid=${l32.uuid}", "ipVersion=4"] + UsedIpInventory usedIp4 = queryIpAddress {conditions=["l3NetworkUuid=${l32Refreshed2.uuid}", "ipVersion=4"] limit = 1} [0] - UsedIpInventory usedIp6 = queryIpAddress {conditions=["l3NetworkUuid=${l32.uuid}", "ipVersion=6"] + UsedIpInventory usedIp6 = queryIpAddress {conditions=["l3NetworkUuid=${l32Refreshed2.uuid}", "ipVersion=6"] limit = 1} [0] expect(AssertionError.class) { changeL3NetworkDhcpIpAddress { - l3NetworkUuid = l32.uuid + l3NetworkUuid = l32Refreshed2.uuid dhcpServerIp = usedIp4.ip } } expect(AssertionError.class) { changeL3NetworkDhcpIpAddress { - l3NetworkUuid = l32.uuid + l3NetworkUuid = l32Refreshed2.uuid dhcpServerIp = usedIp6.ip } } def freeIp6s = getFreeIp { - l3NetworkUuid = l32.getUuid() + l3NetworkUuid = l32Refreshed2.getUuid() ipVersion = IPv6Constants.IPv6 limit = 1 } as List diff --git a/test/src/test/java/org/zstack/test/ApiSender.java b/test/src/test/java/org/zstack/test/ApiSender.java index e4b2e35bd7b..cb4777235c8 100755 --- a/test/src/test/java/org/zstack/test/ApiSender.java +++ b/test/src/test/java/org/zstack/test/ApiSender.java @@ -44,7 +44,7 @@ public T call(APIMessage msg, Class clazz) throws ApiSe private T doSend(final APIMessage msg, Class clazz, boolean exceptionOnError) throws ApiSenderException { APIEvent resultEvent; try { - resultEvent = clazz.newInstance(); + resultEvent = clazz.getConstructor().newInstance(); } catch (Exception e) { throw new CloudRuntimeException("Unable to create instance of " + clazz.getCanonicalName(), e); } diff --git a/test/src/test/java/org/zstack/test/deployer/Deployer.java b/test/src/test/java/org/zstack/test/deployer/Deployer.java index 2ed2c488714..532bee653c5 100755 --- a/test/src/test/java/org/zstack/test/deployer/Deployer.java +++ b/test/src/test/java/org/zstack/test/deployer/Deployer.java @@ -118,7 +118,7 @@ private void scanDeployer() { for (BeanDefinition bd : scanner.findCandidateComponents("org.zstack.test")) { try { Class clazz = Class.forName(bd.getBeanClassName()); - AbstractDeployer d = (AbstractDeployer) clazz.newInstance(); + AbstractDeployer d = (AbstractDeployer) clazz.getConstructor().newInstance(); deployers.put(d.getSupportedDeployerClassType(), d); logger.debug(String.format("Scanned a deployer[%s] supporting %s", d.getClass().getName(), d.getSupportedDeployerClassType())); } catch (Exception e) { diff --git a/testlib/pom.xml b/testlib/pom.xml index 4d1688012a6..95a32177f0e 100644 --- a/testlib/pom.xml +++ b/testlib/pom.xml @@ -17,8 +17,12 @@ junit - org.codehaus.groovy - groovy-all + org.apache.groovy + groovy + + + org.apache.groovy + groovy-xml org.mockito @@ -223,29 +227,90 @@ + org.apache.maven.plugins maven-compiler-plugin 3.6.1 - groovy-eclipse-compiler - ${project.java.version} - ${project.java.version} - lines,vars,source - true + ${project.java.version} + true + true + + + + + + org.codehaus.gmavenplus + gmavenplus-plugin + 4.2.1 + + + + generate-stubs + process-sources + + generateStubs + + + + + compile-groovy + compile + + compile + + + + + generate-test-stubs + process-test-sources + + generateTestStubs + + + + + compile-test-groovy + test-compile + + compileTests + + + + + ${groovy.version} + ${project.java.version} + + + + ${project.basedir}/src/main/java + + **/*.groovy + + + + ${project.basedir}/src/main/groovy + + **/*.groovy + + + + + + ${project.basedir}/src/test/java + + **/*.groovy + + + + ${project.basedir}/src/test/groovy + + **/*.groovy + + + - - - org.codehaus.groovy - groovy-eclipse-compiler - 2.9.2-01 - - - org.codehaus.groovy - groovy-eclipse-batch - 2.4.3-01 - - diff --git a/testlib/src/main/java/org/zstack/testlib/StabilityTest.groovy b/testlib/src/main/java/org/zstack/testlib/StabilityTest.groovy index e700a42a5bc..7a19ff2bef3 100755 --- a/testlib/src/main/java/org/zstack/testlib/StabilityTest.groovy +++ b/testlib/src/main/java/org/zstack/testlib/StabilityTest.groovy @@ -117,7 +117,7 @@ abstract class StabilityTest extends Test implements Case{ } protected Case buildCase(String caseName) { - Case subCase = Class.forName(caseName).newInstance() as Case + Case subCase = Class.forName(caseName).getConstructor().newInstance() as Case def resultDir = [getResultDirBase(), getFailureLogsDirName()].join("/") def dir = new File(resultDir) dir.deleteDir() diff --git a/testlib/src/main/java/org/zstack/testlib/Test.groovy b/testlib/src/main/java/org/zstack/testlib/Test.groovy index 1dcb02c54e9..b3c69df3593 100755 --- a/testlib/src/main/java/org/zstack/testlib/Test.groovy +++ b/testlib/src/main/java/org/zstack/testlib/Test.groovy @@ -1065,11 +1065,11 @@ mysqldump -u root zstack > ${failureLogDir.absolutePath}/dbdump.sql StartMode getStabilityTestStartMode() { String targetCaseList = System.getProperty(targetSubCaseParamKey) List caseClassNameList = targetCaseList.split(",") - def count = caseClassNameList.stream().map { it -> Class.forName(it).newInstance().getCaseMode() }.distinct().count() + def count = caseClassNameList.stream().map { it -> Class.forName(it).getConstructor().newInstance().getCaseMode() }.distinct().count() if (count != 1) { throw new Exception("All cases in the case list should use the same mode") } - return Class.forName(caseClassNameList[0]).newInstance().getCaseMode() + return Class.forName(caseClassNameList[0]).getConstructor().newInstance().getCaseMode() } StartMode getCaseMode() { diff --git a/utils/pom.xml b/utils/pom.xml index 59355a3e183..1c648d8c013 100644 --- a/utils/pom.xml +++ b/utils/pom.xml @@ -53,8 +53,24 @@ log4j-slf4j-impl - org.codehaus.groovy - groovy-all + org.apache.groovy + groovy + ${groovy.version} + + + org.apache.groovy + groovy-xml + ${groovy.version} + + + org.apache.groovy + groovy-templates + ${groovy.version} + + + javax.xml.bind + jaxb-api + ${jaxb.api.version} org.json @@ -149,8 +165,7 @@ maven-compiler-plugin ${project.compiler.version} - ${project.java.version} - ${project.java.version} + ${project.java.version} true diff --git a/utils/src/main/java/org/zstack/utils/GroovyUtils.java b/utils/src/main/java/org/zstack/utils/GroovyUtils.java index 3347aab3e32..7d161a33418 100755 --- a/utils/src/main/java/org/zstack/utils/GroovyUtils.java +++ b/utils/src/main/java/org/zstack/utils/GroovyUtils.java @@ -19,7 +19,7 @@ public class GroovyUtils { public static T newInstance(String scriptPath, ClassLoader parent) { try { Class clz = getClass(scriptPath, parent); - return (T)clz.newInstance(); + return (T) clz.getConstructor().newInstance(); } catch (Exception e) { throw new RuntimeException(e); } diff --git a/utils/src/main/java/org/zstack/utils/ObjectUtils.java b/utils/src/main/java/org/zstack/utils/ObjectUtils.java index eb51bf02ad0..43df3ca1cfa 100755 --- a/utils/src/main/java/org/zstack/utils/ObjectUtils.java +++ b/utils/src/main/java/org/zstack/utils/ObjectUtils.java @@ -55,7 +55,7 @@ public static T newAndCopy(Object src, Class dstClass) { } try { - T dst = dstClass.newInstance(); + T dst = dstClass.getConstructor().newInstance(); org.springframework.beans.BeanUtils.copyProperties(src, dst); return dst; } catch (Exception e) { diff --git a/utils/src/main/java/org/zstack/utils/form/Form.java b/utils/src/main/java/org/zstack/utils/form/Form.java index abe47906f46..90b90781408 100644 --- a/utils/src/main/java/org/zstack/utils/form/Form.java +++ b/utils/src/main/java/org/zstack/utils/form/Form.java @@ -172,7 +172,7 @@ private T doLoadObject(String[] record) throws Exception { throw new OutOfLimitException(String.format("objects count is too larger than limit[%d]", limit)); } - T object = clz.newInstance(); + T object = clz.getConstructor().newInstance(); for (int i = 0; i < record.length; i++) { String key = columns[i]; String value = record[i]; diff --git a/utils/src/main/java/org/zstack/utils/gson/JSONObjectUtil.java b/utils/src/main/java/org/zstack/utils/gson/JSONObjectUtil.java index a6451ce35e4..5aa735c76f3 100755 --- a/utils/src/main/java/org/zstack/utils/gson/JSONObjectUtil.java +++ b/utils/src/main/java/org/zstack/utils/gson/JSONObjectUtil.java @@ -37,7 +37,7 @@ public static K toCollection(String content, Class if (collections.isInterface()) { throw new IllegalArgumentException(String.format("collections must be a concrete class, not interface[%s]", collections.getName())); } - Collection c = collections.newInstance(); + Collection c = collections.getConstructor().newInstance(); JSONArray jarr = new JSONArray(content); for (int i=0; i clazz, Function rewriter) { private MessageFactory buildMessageFactory(Function rewriter) { try { return new MessageFactory() { - MessageFactory defaultFactory = AbstractLogger.DEFAULT_MESSAGE_FACTORY_CLASS.newInstance(); + MessageFactory defaultFactory = AbstractLogger.DEFAULT_MESSAGE_FACTORY_CLASS.getConstructor().newInstance(); @Override public org.apache.logging.log4j.message.Message newMessage(Object message) { diff --git a/utils/src/test/java/org/zstack/utils/test/TestNetworkUtils.java b/utils/src/test/java/org/zstack/utils/test/TestNetworkUtils.java index f1cc86f81bd..a24c31ec347 100644 --- a/utils/src/test/java/org/zstack/utils/test/TestNetworkUtils.java +++ b/utils/src/test/java/org/zstack/utils/test/TestNetworkUtils.java @@ -1,7 +1,6 @@ package org.zstack.utils.test; import org.junit.Test; -import org.omg.PortableInterceptor.SYSTEM_EXCEPTION; import org.zstack.utils.network.NetworkUtils; public class TestNetworkUtils {