diff --git a/VERSION b/VERSION index aa87198d370..4c23f212761 100755 --- a/VERSION +++ b/VERSION @@ -1,3 +1,3 @@ MAJOR=5 MINOR=5 -UPDATE=22 +UPDATE=28 diff --git a/abstraction/src/main/java/org/zstack/abstraction/sso/OAuth2PluginConstants.java b/abstraction/src/main/java/org/zstack/abstraction/sso/OAuth2PluginConstants.java index 087bbd5129e..1c89436ae41 100644 --- a/abstraction/src/main/java/org/zstack/abstraction/sso/OAuth2PluginConstants.java +++ b/abstraction/src/main/java/org/zstack/abstraction/sso/OAuth2PluginConstants.java @@ -46,4 +46,7 @@ public interface OAuth2PluginConstants { String ZF_PROVIDER_NAME = "zf"; String ALI_PROVIDER_NAME = "ali_idaas_private"; String MAX_KEY_PROVIDER_NAME = "max_key"; + String ZIAM_PROVIDER_NAME = "ziam"; + String LOGIN_TYPE_IAM2_ROPC = "iam2_ropc"; + String ZIAM_DEFAULT_SCOPE = "openid profile email"; } diff --git a/build/pom.xml b/build/pom.xml index a1ea6a47ca7..5a097bb382a 100755 --- a/build/pom.xml +++ b/build/pom.xml @@ -636,6 +636,11 @@ ovn ${project.version} + + org.zstack + zns + ${project.version} + org.zstack observabilityServer diff --git a/compute/src/main/java/org/zstack/compute/allocator/HostAllocatorManagerImpl.java b/compute/src/main/java/org/zstack/compute/allocator/HostAllocatorManagerImpl.java index a6598082004..2f59c6fb49f 100755 --- a/compute/src/main/java/org/zstack/compute/allocator/HostAllocatorManagerImpl.java +++ b/compute/src/main/java/org/zstack/compute/allocator/HostAllocatorManagerImpl.java @@ -237,11 +237,15 @@ public String call(HostUsedCpuMem arg) { } }); - hostUuids.stream().filter(huuid -> !hostHasVms.contains(huuid)).forEach(huuid -> { + for (String huuid : hostUuids) { + if (hostHasVms.contains(huuid)) { + continue; + } + HostUsedCpuMem s = new HostUsedCpuMem(); s.hostUuid = huuid; hostUsedCpuMemList.add(s); - }); + } for (final HostUsedCpuMem s : hostUsedCpuMemList) { new HostCapacityUpdater(s.hostUuid).run(new HostCapacityUpdaterRunnable() { diff --git a/compute/src/main/java/org/zstack/compute/host/HostTrackImpl.java b/compute/src/main/java/org/zstack/compute/host/HostTrackImpl.java index 48ed6a7dc48..19a5e56a752 100755 --- a/compute/src/main/java/org/zstack/compute/host/HostTrackImpl.java +++ b/compute/src/main/java/org/zstack/compute/host/HostTrackImpl.java @@ -36,6 +36,7 @@ public class HostTrackImpl implements HostTracker, ManagementNodeChangeListener, private final static CLogger logger = Utils.getLogger(HostTrackImpl.class); private Map trackers = new ConcurrentHashMap<>(); + private volatile boolean stopped; private static boolean alwaysStartRightNow = false; private static final Cache skippedPingHostDeadline = CacheBuilder.newBuilder().expireAfterWrite(1, TimeUnit.HOURS).build(); @@ -251,6 +252,11 @@ public void cancel() { public void trackHost(String hostUuid) { + if (stopped) { + logger.debug(String.format("skip tracking host[uuid:%s], host tracker is stopped", hostUuid)); + return; + } + if (!destMaker.isManagedByUs(hostUuid)) { logger.debug(String.format("skip tracking host[uuid:%s], not managed by us", hostUuid)); return; @@ -285,6 +291,11 @@ public void untrackHost(String huuid) { @Override public void trackHost(Collection huuids) { + if (stopped) { + logger.debug(String.format("skip tracking hosts%s, host tracker is stopped", huuids)); + return; + } + huuids.forEach(this::trackHost); } @@ -353,6 +364,7 @@ private HostReconnectTaskFactory getHostReconnectTaskFactory(String hvType) { @Override public boolean start() { + stopped = false; populateExtensions(); onHostStatusChange(); onHostPingSkip(); @@ -421,6 +433,9 @@ protected void run(Map tokens, Object data) { @Override public boolean stop() { + stopped = true; + new HashSet<>(trackers.values()).forEach(Tracker::cancel); + trackers.clear(); return true; } } diff --git a/compute/src/main/java/org/zstack/compute/vm/StopVmGC.java b/compute/src/main/java/org/zstack/compute/vm/StopVmGC.java index a55de8878cf..1c79a9035f0 100755 --- a/compute/src/main/java/org/zstack/compute/vm/StopVmGC.java +++ b/compute/src/main/java/org/zstack/compute/vm/StopVmGC.java @@ -51,6 +51,7 @@ protected void triggerNow(GCCompletion completion) { public void run(FlowTrigger trigger, Map data) { StopVmOnHypervisorMsg msg = new StopVmOnHypervisorMsg(); msg.setVmInventory(inventory); + msg.setIgnoreNotFoundError(true); bus.makeTargetServiceIdByResourceUuid(msg, HostConstant.SERVICE_ID, hostUuid); bus.send(msg, new CloudBusCallBack(trigger) { @Override @@ -66,6 +67,16 @@ public void run(MessageReply reply) { }).then(new NoRollbackFlow() { @Override public void run(FlowTrigger trigger, Map data) { + String vmHostUuid = Q.New(VmInstanceVO.class).select(VmInstanceVO_.hostUuid) + .eq(VmInstanceVO_.uuid, inventory.getUuid()).findValue(); + if (!hostUuid.equals(vmHostUuid)) { + logger.debug(String.format("skip changing vm[uuid:%s] state to stopped after StopVmGC, " + + "current host[uuid:%s] is not gc host[uuid:%s]", inventory.getUuid(), + vmHostUuid, hostUuid)); + trigger.next(); + return; + } + ChangeVmStateMsg cmsg = new ChangeVmStateMsg(); cmsg.setVmInstanceUuid(inventory.getUuid()); cmsg.setStateEvent(VmInstanceStateEvent.stopped.toString()); diff --git a/compute/src/main/java/org/zstack/compute/vm/VmAllocateHostFlow.java b/compute/src/main/java/org/zstack/compute/vm/VmAllocateHostFlow.java index ee542fe36ee..3059e9dfc19 100755 --- a/compute/src/main/java/org/zstack/compute/vm/VmAllocateHostFlow.java +++ b/compute/src/main/java/org/zstack/compute/vm/VmAllocateHostFlow.java @@ -21,6 +21,7 @@ import org.zstack.header.host.HostVO; import org.zstack.header.image.ImageConstant.ImageMediaType; import org.zstack.header.image.ImageInventory; +import org.zstack.header.message.APIMessage; import org.zstack.header.message.MessageReply; import org.zstack.header.network.l3.L3NetworkInventory; import org.zstack.header.storage.primary.PrimaryStorageClusterRefVO; @@ -95,6 +96,9 @@ public String call(L3NetworkInventory arg) { })); msg.setImage(image); msg.setVmOperation(spec.getCurrentVmOperation().toString()); + if (spec.getMessage() instanceof APIMessage && ((APIMessage) spec.getMessage()).getSystemTags() != null) { + msg.setSystemTags(new ArrayList<>(((APIMessage) spec.getMessage()).getSystemTags())); + } if (spec.getVmInventory().getZoneUuid() != null) { msg.setZoneUuid(spec.getVmInventory().getZoneUuid()); diff --git a/compute/src/main/java/org/zstack/compute/vm/VmAllocateNicFlow.java b/compute/src/main/java/org/zstack/compute/vm/VmAllocateNicFlow.java index db5da3e3ce8..0e307a30b5c 100755 --- a/compute/src/main/java/org/zstack/compute/vm/VmAllocateNicFlow.java +++ b/compute/src/main/java/org/zstack/compute/vm/VmAllocateNicFlow.java @@ -11,6 +11,7 @@ import org.zstack.core.db.DatabaseFacade; import org.zstack.core.db.SQLBatch; import org.zstack.core.errorcode.ErrorFacade; +import org.zstack.header.core.Completion; import org.zstack.header.core.WhileDoneCompletion; import org.zstack.header.core.workflow.Flow; import org.zstack.header.core.workflow.FlowRollback; @@ -18,6 +19,7 @@ import org.zstack.header.errorcode.ErrorCode; import org.zstack.header.errorcode.ErrorCodeList; import org.zstack.header.image.ImagePlatform; +import org.zstack.header.message.APIMessage; import org.zstack.header.network.l3.*; import org.zstack.header.vm.*; import org.zstack.network.l3.L3NetworkManager; @@ -91,113 +93,68 @@ public void run(final FlowTrigger trigger, final Map data) { List nics = new ArrayList<>(); data.put(VmInstanceConstant.Params.VmAllocateNicFlow_nics.toString(), nics); List errs = new ArrayList<>(); + List vmSystemTags = spec.getMessage() instanceof APIMessage ? ((APIMessage) spec.getMessage()).getSystemTags() : null; new While<>(VmNicSpec.getFirstL3NetworkInventoryOfSpec(spec.getL3Networks())).each((nicSpec, wcomp) -> { L3NetworkInventory nw = nicSpec.getL3Invs().get(0); int deviceId = deviceIdBitmap.nextClearBit(0); deviceIdBitmap.set(deviceId); MacOperator mo = new MacOperator(); - String customMac = mo.getMac(spec.getVmInventory().getUuid(), nw.getUuid()); - if (customMac != null){ - mo.deleteCustomMacSystemTag(spec.getVmInventory().getUuid(), nw.getUuid(), customMac); - customMac = customMac.toLowerCase(); - } else { - customMac = MacOperator.generateMacWithDeviceId((short) deviceId); - } - final String mac = customMac; + final String customMac = mo.getMac(spec.getVmInventory().getUuid(), nw.getUuid()); + final String mac = allocateMac(customMac, deviceId); CustomNicOperator nicOperator = new CustomNicOperator(spec.getVmInventory().getUuid(),nw.getUuid()); final String customNicUuid = nicOperator.getCustomNicId(); // choose vnic factory based on enableSRIOV system tag & enableVhostUser globalConfig - VmNicType type = nicManager.getVmNicType(spec.getVmInventory().getUuid(), nw); + VmNicType type = nicManager.getVmNicType(spec.getVmInventory().getUuid(), nw, vmSystemTags); if (type == null) { errs.add(Platform.operr(ORG_ZSTACK_COMPUTE_VM_10068, "there is no available nicType on L3 network [%s]", nw.getUuid())); wcomp.allDone(); + return; } VmInstanceNicFactory vnicFactory = vmMgr.getVmInstanceNicFactory(type); - - VmNicInventory nic = new VmNicInventory(); - if (customNicUuid != null) { - nic.setUuid(customNicUuid); - } else { - nic.setUuid(Platform.getUuid()); - } - /* the first ip is ipv4 address for dual stack nic */ - nic.setVmInstanceUuid(spec.getVmInventory().getUuid()); - nic.setL3NetworkUuid(nw.getUuid()); - nic.setMac(mac); - nic.setHypervisorType(spec.getDestHost() == null ? - spec.getVmInventory().getHypervisorType() : spec.getDestHost().getHypervisorType()); + VmNicInventory nic = buildNicInventory(spec, nicSpec, nw, mac, customNicUuid, deviceId, disableL3Networks); if (mo.checkDuplicateMac(nic.getHypervisorType(), nic.getL3NetworkUuid(), nic.getMac())) { - trigger.fail(operr(ORG_ZSTACK_COMPUTE_VM_10069, "Duplicate mac address [%s]", nic.getMac())); + errs.add(operr(ORG_ZSTACK_COMPUTE_VM_10069, "Duplicate mac address [%s]", nic.getMac())); + wcomp.allDone(); return; } - if (!StringUtils.isEmpty(nicSpec.getNicDriverType())) { - nic.setDriverType(nicSpec.getNicDriverType()); - } else { - boolean vmImageHasVirtio = VmSystemTags.VIRTIO.hasTag(spec.getVmInventory().getUuid()); - nicManager.setNicDriverType(nic, vmImageHasVirtio, - ImagePlatform.valueOf(spec.getVmInventory().getPlatform()).isParaVirtualization(), - spec.getVmInventory()); - } + // Persist VmNicVO first so that ResourceVO entry exists before extensions + // (e.g. SDN controllers) attempt to create SystemTags referencing the NIC UUID. + VmNicVO nicVO = vnicFactory.createVmNic(nic, spec); - nic.setDeviceId(deviceId); - nic.setInternalName(VmNicVO.generateNicInternalName(spec.getVmInventory().getInternalId(), nic.getDeviceId())); - nic.setState(disableL3Networks.contains(nic.getL3NetworkUuid()) ? VmNicState.disable.toString() : VmNicState.enable.toString()); - new SQLBatch() { + callBeforeAllocateVmNicExtensions(nic, spec, new Completion(wcomp) { @Override - protected void scripts() { - VmNicVO nicVO = vnicFactory.createVmNic(nic, spec); - if (!nw.enableIpAddressAllocation() && nicNetworkInfoMap != null - && nicNetworkInfoMap.containsKey(nw.getUuid()) - && spec.getVmInventory().getType().equals(VmInstanceConstant.USER_VM_TYPE)) { - NicIpAddressInfo nicNicIpAddressInfo = nicNetworkInfoMap.get(nic.getL3NetworkUuid()); - if (!nicNicIpAddressInfo.ipv6Address.isEmpty()) { - UsedIpVO vo = new UsedIpVO(); - vo.setUuid(Platform.getUuid()); - vo.setIp(IPv6NetworkUtils.getIpv6AddressCanonicalString(nicNicIpAddressInfo.ipv6Address)); - vo.setNetmask(IPv6NetworkUtils.getFormalNetmaskOfNetworkCidr(nicNicIpAddressInfo.ipv6Address+"/"+ nicNicIpAddressInfo.ipv6Prefix)); - vo.setGateway(nicNicIpAddressInfo.ipv6Gateway.isEmpty() ? "" : IPv6NetworkUtils.getIpv6AddressCanonicalString(nicNicIpAddressInfo.ipv6Gateway)); - vo.setIpVersion(IPv6Constants.IPv6); - vo.setVmNicUuid(nic.getUuid()); - vo.setL3NetworkUuid(nic.getL3NetworkUuid()); - vo.setIpInBinary(NetworkUtils.ipStringToBytes(vo.getIp())); - vo.setIpRangeUuid(new StaticIpOperator().getIpRangeUuid(nic.getL3NetworkUuid(), vo.getIp())); - nic.setUsedIpUuid(vo.getUuid()); - nicVO.setUsedIpUuid(vo.getUuid()); - nicVO.setIp(vo.getIp()); - nicVO.setNetmask(vo.getNetmask()); - nicVO.setGateway(vo.getGateway()); - dbf.persist(vo); - } - if (!nicNicIpAddressInfo.ipv4Address.isEmpty()) { - UsedIpVO vo = new UsedIpVO(); - vo.setUuid(Platform.getUuid()); - vo.setIp(nicNicIpAddressInfo.ipv4Address); - vo.setGateway(nicNicIpAddressInfo.ipv4Gateway); - vo.setNetmask(nicNicIpAddressInfo.ipv4Netmask); - vo.setIpVersion(IPv6Constants.IPv4); - vo.setVmNicUuid(nic.getUuid()); - vo.setL3NetworkUuid(nic.getL3NetworkUuid()); - vo.setIpInLong(NetworkUtils.ipv4StringToLong(vo.getIp())); - vo.setIpInBinary(NetworkUtils.ipStringToBytes(vo.getIp())); - vo.setIpRangeUuid(new StaticIpOperator().getIpRangeUuid(nic.getL3NetworkUuid(), vo.getIp())); - nic.setUsedIpUuid(vo.getUuid()); - nicVO.setUsedIpUuid(vo.getUuid()); - nicVO.setIp(vo.getIp()); - nicVO.setNetmask(vo.getNetmask()); - nicVO.setGateway(vo.getGateway()); - dbf.persist(vo); + public void success() { + new SQLBatch() { + @Override + protected void scripts() { + persistStaticIpIfNeeded(nic, nicVO, nw, nicNetworkInfoMap, spec); + nics.add(nic); + VmNicVO updated = dbf.updateAndRefresh(nicVO); + addVmNicConfig(updated, spec, nicSpec); } + }.execute(); + if (customMac != null) { + mo.deleteCustomMacSystemTag(spec.getVmInventory().getUuid(), nw.getUuid(), customMac); + } + wcomp.done(); + } + + @Override + public void fail(ErrorCode errorCode) { + try { + dbf.removeByPrimaryKey(nicVO.getUuid(), VmNicVO.class); + } catch (Throwable t) { + logger.warn(String.format("failed to remove VmNicVO[uuid:%s] after before allocate extension failure", + nicVO.getUuid()), t); } - nics.add(nic); - nicVO = dbf.updateAndRefresh(nicVO); - addVmNicConfig(nicVO, spec, nicSpec); + errs.add(errorCode); + wcomp.allDone(); } - }.execute(); - wcomp.done(); + }); }).run(new WhileDoneCompletion(trigger) { @Override @@ -211,6 +168,89 @@ public void done(ErrorCodeList errorCodeList) { }); } + private String allocateMac(String customMac, int deviceId) { + if (customMac != null) { + return customMac.toLowerCase(); + } + return MacOperator.generateMacWithDeviceId((short) deviceId); + } + + private VmNicInventory buildNicInventory(VmInstanceSpec spec, VmNicSpec nicSpec, + L3NetworkInventory nw, String mac, String customNicUuid, + int deviceId, List disableL3Networks) { + VmNicInventory nic = new VmNicInventory(); + nic.setUuid(customNicUuid != null ? customNicUuid : Platform.getUuid()); + /* the first ip is ipv4 address for dual stack nic */ + nic.setVmInstanceUuid(spec.getVmInventory().getUuid()); + nic.setL3NetworkUuid(nw.getUuid()); + nic.setMac(mac); + nic.setHypervisorType(spec.getDestHost() == null ? + spec.getVmInventory().getHypervisorType() : spec.getDestHost().getHypervisorType()); + + if (!StringUtils.isEmpty(nicSpec.getNicDriverType())) { + nic.setDriverType(nicSpec.getNicDriverType()); + } else { + boolean vmImageHasVirtio = VmSystemTags.VIRTIO.hasTag(spec.getVmInventory().getUuid()); + nicManager.setNicDriverType(nic, vmImageHasVirtio, + ImagePlatform.valueOf(spec.getVmInventory().getPlatform()).isParaVirtualization(), + spec.getVmInventory()); + } + + nic.setDeviceId(deviceId); + nic.setInternalName(VmNicVO.generateNicInternalName(spec.getVmInventory().getInternalId(), nic.getDeviceId())); + nic.setState(disableL3Networks.contains(nic.getL3NetworkUuid()) ? VmNicState.disable.toString() : VmNicState.enable.toString()); + return nic; + } + + private void persistStaticIpIfNeeded(VmNicInventory nic, VmNicVO nicVO, + L3NetworkInventory nw, Map nicNetworkInfoMap, + VmInstanceSpec spec) { + if (nw.enableIpAddressAllocation() || nicNetworkInfoMap == null + || !nicNetworkInfoMap.containsKey(nw.getUuid()) + || !spec.getVmInventory().getType().equals(VmInstanceConstant.USER_VM_TYPE)) { + return; + } + + NicIpAddressInfo nicIpAddressInfo = nicNetworkInfoMap.get(nic.getL3NetworkUuid()); + if (!nicIpAddressInfo.ipv6Address.isEmpty()) { + UsedIpVO vo = new UsedIpVO(); + vo.setUuid(Platform.getUuid()); + vo.setIp(IPv6NetworkUtils.getIpv6AddressCanonicalString(nicIpAddressInfo.ipv6Address)); + vo.setNetmask(IPv6NetworkUtils.getFormalNetmaskOfNetworkCidr(nicIpAddressInfo.ipv6Address + "/" + nicIpAddressInfo.ipv6Prefix)); + vo.setGateway(nicIpAddressInfo.ipv6Gateway.isEmpty() ? "" : IPv6NetworkUtils.getIpv6AddressCanonicalString(nicIpAddressInfo.ipv6Gateway)); + vo.setIpVersion(IPv6Constants.IPv6); + vo.setVmNicUuid(nic.getUuid()); + vo.setL3NetworkUuid(nic.getL3NetworkUuid()); + vo.setIpInBinary(NetworkUtils.ipStringToBytes(vo.getIp())); + vo.setIpRangeUuid(new StaticIpOperator().getIpRangeUuid(nic.getL3NetworkUuid(), vo.getIp())); + nic.setUsedIpUuid(vo.getUuid()); + nicVO.setUsedIpUuid(vo.getUuid()); + nicVO.setIp(vo.getIp()); + nicVO.setNetmask(vo.getNetmask()); + nicVO.setGateway(vo.getGateway()); + dbf.persist(vo); + } + if (!nicIpAddressInfo.ipv4Address.isEmpty()) { + UsedIpVO vo = new UsedIpVO(); + vo.setUuid(Platform.getUuid()); + vo.setIp(nicIpAddressInfo.ipv4Address); + vo.setGateway(nicIpAddressInfo.ipv4Gateway); + vo.setNetmask(nicIpAddressInfo.ipv4Netmask); + vo.setIpVersion(IPv6Constants.IPv4); + vo.setVmNicUuid(nic.getUuid()); + vo.setL3NetworkUuid(nic.getL3NetworkUuid()); + vo.setIpInLong(NetworkUtils.ipv4StringToLong(vo.getIp())); + vo.setIpInBinary(NetworkUtils.ipStringToBytes(vo.getIp())); + vo.setIpRangeUuid(new StaticIpOperator().getIpRangeUuid(nic.getL3NetworkUuid(), vo.getIp())); + nic.setUsedIpUuid(vo.getUuid()); + nicVO.setUsedIpUuid(vo.getUuid()); + nicVO.setIp(vo.getIp()); + nicVO.setNetmask(vo.getNetmask()); + nicVO.setGateway(vo.getGateway()); + dbf.persist(vo); + } + } + private void addVmNicConfig(VmNicVO vmNicVO, VmInstanceSpec vmSpec, VmNicSpec nicSpec) { if (nicSpec == null) { return; @@ -237,6 +277,38 @@ private void addVmNicConfig(VmNicVO vmNicVO, VmInstanceSpec vmSpec, VmNicSpec ni } } + private void callBeforeAllocateVmNicExtensions(VmNicInventory nic, VmInstanceSpec spec, Completion completion) { + List exts = pluginRgty.getExtensionList(BeforeAllocateVmNicExtensionPoint.class); + if (exts.isEmpty()) { + completion.success(); + return; + } + + new While<>(exts).each((ext, wcomp) -> { + ext.beforeAllocateVmNic(nic, spec, new Completion(wcomp) { + @Override + public void success() { + wcomp.done(); + } + + @Override + public void fail(ErrorCode errorCode) { + wcomp.addError(errorCode); + wcomp.allDone(); + } + }); + }).run(new WhileDoneCompletion(completion) { + @Override + public void done(ErrorCodeList errorCodeList) { + if (errorCodeList.getCauses().isEmpty()) { + completion.success(); + } else { + completion.fail(errorCodeList.getCauses().get(0)); + } + } + }); + } + @Override public void rollback(final FlowRollback chain, Map data) { final VmInstanceSpec spec = (VmInstanceSpec) data.get(VmInstanceConstant.Params.VmInstanceSpec.toString()); @@ -256,7 +328,7 @@ public void rollback(final FlowRollback chain, Map data) { vnicFactory.releaseVmNic(vmNic); } dbf.removeByPrimaryKeys(destNics.stream().map(VmNicInventory::getUuid).collect(Collectors.toList()), VmNicVO.class); + chain.rollback(); - return; } } diff --git a/compute/src/main/java/org/zstack/compute/vm/VmAllocateSdnNicFlow.java b/compute/src/main/java/org/zstack/compute/vm/VmAllocateSdnNicFlow.java new file mode 100644 index 00000000000..19d2d75c228 --- /dev/null +++ b/compute/src/main/java/org/zstack/compute/vm/VmAllocateSdnNicFlow.java @@ -0,0 +1,131 @@ +package org.zstack.compute.vm; + +import org.springframework.beans.factory.annotation.Autowire; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Configurable; +import org.zstack.core.asyncbatch.While; +import org.zstack.core.componentloader.PluginRegistry; +import org.zstack.header.core.Completion; +import org.zstack.header.core.WhileDoneCompletion; +import org.zstack.header.core.workflow.Flow; +import org.zstack.header.core.workflow.FlowRollback; +import org.zstack.header.core.workflow.FlowTrigger; +import org.zstack.header.errorcode.ErrorCode; +import org.zstack.header.errorcode.ErrorCodeList; +import org.zstack.header.network.l3.UsedIpInventory; +import org.zstack.header.network.sdncontroller.SdnControllerConstant; +import org.zstack.header.vm.*; +import org.zstack.utils.Utils; +import org.zstack.utils.logging.CLogger; + +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import static org.zstack.core.progress.ProgressReportService.taskProgress; + +/** + * Placed after VmAllocateNicIpFlow in the flow chain. + * + * For each NIC belonging to an SDN-managed L2 network, this flow delegates + * to the registered {@link AfterAllocateSdnNicExtensionPoint} implementations + * (typically {@code SdnControllerManagerImpl}) which: + * + * - OVN: calls addLogicalPorts() with already-allocated IPs + * - ZNS: calls createSegmentPort(), receives IP back from ZNS, writes to DB + * - H3C/Sugon: default no-op + * + * Non-SDN NICs are skipped by the extension implementation internally. + */ +@Configurable(preConstruction = true, autowire = Autowire.BY_TYPE) +public class VmAllocateSdnNicFlow implements Flow { + private static final CLogger logger = Utils.getLogger(VmAllocateSdnNicFlow.class); + + @Autowired + private PluginRegistry pluginRgty; + + @Override + public void run(final FlowTrigger trigger, final Map data) { + taskProgress("create SDN ports for nics"); + + final VmInstanceSpec spec = (VmInstanceSpec) data.get(VmInstanceConstant.Params.VmInstanceSpec.toString()); + final List nics = spec.getDestNics(); + List allocatedIpsOnStart = (List) data.get(VmAllocateNicForStartingVmFlow.class); + if (allocatedIpsOnStart != null) { + spec.putExtensionData(SdnControllerConstant.ALLOCATED_IPS_ON_START, allocatedIpsOnStart.stream() + .map(UsedIpInventory::getVmNicUuid) + .collect(Collectors.toList())); + } + + if (nics == null || nics.isEmpty()) { + trigger.next(); + return; + } + + List exts = + pluginRgty.getExtensionList(AfterAllocateSdnNicExtensionPoint.class); + if (exts.isEmpty()) { + trigger.next(); + return; + } + + new While<>(exts).each((ext, wcomp) -> { + ext.afterAllocateSdnNic(spec, nics, new Completion(wcomp) { + @Override + public void success() { + wcomp.done(); + } + + @Override + public void fail(ErrorCode errorCode) { + wcomp.addError(errorCode); + wcomp.allDone(); + } + }); + }).run(new WhileDoneCompletion(trigger) { + @Override + public void done(ErrorCodeList errorCodeList) { + if (!errorCodeList.getCauses().isEmpty()) { + trigger.fail(errorCodeList.getCauses().get(0)); + } else { + trigger.next(); + } + } + }); + } + + @Override + public void rollback(final FlowRollback chain, Map data) { + final VmInstanceSpec spec = (VmInstanceSpec) data.get(VmInstanceConstant.Params.VmInstanceSpec.toString()); + final List nics = spec.getDestNics(); + + List exts = + pluginRgty.getExtensionList(AfterAllocateSdnNicExtensionPoint.class); + + if (exts.isEmpty() || nics == null || nics.isEmpty()) { + chain.rollback(); + return; + } + + new While<>(exts).each((ext, wcomp) -> { + ext.rollbackSdnNic(spec, nics, new Completion(wcomp) { + @Override + public void success() { + wcomp.done(); + } + + @Override + public void fail(ErrorCode errorCode) { + // best-effort: log and continue + logger.warn(String.format("failed to rollback SDN nic: %s", errorCode)); + wcomp.done(); + } + }); + }).run(new WhileDoneCompletion(chain) { + @Override + public void done(ErrorCodeList errorCodeList) { + chain.rollback(); + } + }); + } +} diff --git a/compute/src/main/java/org/zstack/compute/vm/VmCascadeExtension.java b/compute/src/main/java/org/zstack/compute/vm/VmCascadeExtension.java index 9bd98bd9511..07247d60b91 100755 --- a/compute/src/main/java/org/zstack/compute/vm/VmCascadeExtension.java +++ b/compute/src/main/java/org/zstack/compute/vm/VmCascadeExtension.java @@ -325,6 +325,7 @@ protected List handleDeletionForIpRange(List(nic.getUsedIps()).all((ip, comp) -> { ReturnIpMsg msg = new ReturnIpMsg(); msg.setUsedIpUuid(ip.getUuid()); @@ -82,9 +98,51 @@ public void run(MessageReply reply) { }).run(new WhileDoneCompletion(trigger){ @Override public void done(ErrorCodeList errorCodeList) { - dbf.removeByPrimaryKey(nic.getUuid(), VmNicVO.class); - trigger.next(); + callReleaseSdnNics(java.util.Collections.singletonList(nic), new Completion(trigger) { + @Override + public void success() { + dbf.removeByPrimaryKey(nic.getUuid(), VmNicVO.class); + trigger.next(); + } + + @Override + public void fail(ErrorCode errorCode) { + logger.warn(String.format("releaseSdnNics failed for nic[uuid:%s]: %s, continue", + nic.getUuid(), errorCode)); + dbf.removeByPrimaryKey(nic.getUuid(), VmNicVO.class); + trigger.next(); + } + }); + } + }); + } + + private void callReleaseSdnNics(List nics, Completion completion) { + List exts = pluginRgty.getExtensionList(AfterAllocateSdnNicExtensionPoint.class); + if (exts.isEmpty()) { + completion.success(); + return; + } + + new While<>(exts).each((ext, wcomp) -> { + ext.releaseSdnNics(nics, new Completion(wcomp) { + @Override + public void success() { + wcomp.done(); + } + + @Override + public void fail(ErrorCode errorCode) { + logger.warn(String.format("releaseSdnNics extension failed: %s, continue", errorCode)); + wcomp.done(); + } + }); + }).run(new WhileDoneCompletion(completion) { + @Override + public void done(ErrorCodeList errorCodeList) { + completion.success(); } }); } + } diff --git a/compute/src/main/java/org/zstack/compute/vm/VmExpungeSdnNicFlow.java b/compute/src/main/java/org/zstack/compute/vm/VmExpungeSdnNicFlow.java new file mode 100644 index 00000000000..654d7cc213f --- /dev/null +++ b/compute/src/main/java/org/zstack/compute/vm/VmExpungeSdnNicFlow.java @@ -0,0 +1,84 @@ +package org.zstack.compute.vm; + +import org.springframework.beans.factory.annotation.Autowire; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Configurable; +import org.zstack.core.asyncbatch.While; +import org.zstack.core.componentloader.PluginRegistry; +import org.zstack.header.core.Completion; +import org.zstack.header.core.WhileDoneCompletion; +import org.zstack.header.core.workflow.FlowTrigger; +import org.zstack.header.core.workflow.NoRollbackFlow; +import org.zstack.header.errorcode.ErrorCode; +import org.zstack.header.errorcode.ErrorCodeList; +import org.zstack.header.vm.AfterAllocateSdnNicExtensionPoint; +import org.zstack.header.vm.VmInstanceConstant; +import org.zstack.header.vm.VmInstanceSpec; +import org.zstack.header.vm.VmNicInventory; +import org.zstack.utils.Utils; +import org.zstack.utils.logging.CLogger; + +import java.util.List; +import java.util.Map; + +@Configurable(preConstruction = true, autowire = Autowire.BY_TYPE) +public class VmExpungeSdnNicFlow extends NoRollbackFlow { + private static final CLogger logger = Utils.getLogger(VmExpungeSdnNicFlow.class); + + @Autowired + private PluginRegistry pluginRgty; + + @Override + public void run(FlowTrigger trigger, Map data) { + VmInstanceSpec spec = (VmInstanceSpec) data.get(VmInstanceConstant.Params.VmInstanceSpec.toString()); + List nics = spec.getVmInventory().getVmNics(); + if (nics == null || nics.isEmpty()) { + trigger.next(); + return; + } + + expungeSdnNics(nics, new Completion(trigger) { + @Override + public void success() { + trigger.next(); + } + + @Override + public void fail(ErrorCode errorCode) { + logger.warn(String.format("expungeSdnNics failed during vm expunge: %s", errorCode)); + trigger.fail(errorCode); + } + }); + } + + private void expungeSdnNics(List nics, Completion completion) { + List exts = pluginRgty.getExtensionList(AfterAllocateSdnNicExtensionPoint.class); + if (exts.isEmpty()) { + completion.success(); + return; + } + + new While<>(exts).each((ext, wcomp) -> ext.expungeSdnNics(nics, new Completion(wcomp) { + @Override + public void success() { + wcomp.done(); + } + + @Override + public void fail(ErrorCode errorCode) { + logger.warn(String.format("expungeSdnNics extension failed during vm expunge: %s", errorCode)); + wcomp.addError(errorCode); + wcomp.done(); + } + })).run(new WhileDoneCompletion(completion) { + @Override + public void done(ErrorCodeList errorCodeList) { + if (errorCodeList.getCauses().isEmpty()) { + completion.success(); + } else { + completion.fail(errorCodeList.getCauses().get(0)); + } + } + }); + } +} diff --git a/compute/src/main/java/org/zstack/compute/vm/VmInstanceApiInterceptor.java b/compute/src/main/java/org/zstack/compute/vm/VmInstanceApiInterceptor.java index 06d175a8d13..0e42d53cc71 100755 --- a/compute/src/main/java/org/zstack/compute/vm/VmInstanceApiInterceptor.java +++ b/compute/src/main/java/org/zstack/compute/vm/VmInstanceApiInterceptor.java @@ -1536,4 +1536,4 @@ private void validate(APIFstrimVmMsg msg) { } msg.setHostUuid(t.get(1, String.class)); } -} \ No newline at end of file +} 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 a52c9010bc7..332314056b9 100755 --- a/compute/src/main/java/org/zstack/compute/vm/VmInstanceBase.java +++ b/compute/src/main/java/org/zstack/compute/vm/VmInstanceBase.java @@ -44,8 +44,14 @@ import org.zstack.header.image.*; import org.zstack.header.image.ImageConstant.ImageMediaType; import org.zstack.header.message.*; +import org.zstack.header.network.l2.L2NetworkVO; import org.zstack.header.network.l3.*; +import org.zstack.header.network.sdncontroller.SdnControllerVO; +import org.zstack.header.network.sdncontroller.SdnControllerVO_; import org.zstack.header.storage.primary.*; +import org.zstack.header.tag.SystemTagInventory; +import org.zstack.header.tag.SystemTagVO; +import org.zstack.header.tag.SystemTagVO_; import org.zstack.header.vm.*; import org.zstack.header.vm.ChangeVmMetaDataMsg.AtomicHostUuid; import org.zstack.header.vm.ChangeVmMetaDataMsg.AtomicVmState; @@ -63,6 +69,7 @@ import org.zstack.header.volume.*; import org.zstack.identity.Account; import org.zstack.identity.AccountManager; +import org.zstack.network.l2.L2NetworkSystemTags; import org.zstack.network.l3.IpRangeHelper; import org.zstack.network.l3.L3NetworkManager; import org.zstack.resourceconfig.ResourceConfig; @@ -84,6 +91,7 @@ import org.zstack.utils.network.NetworkUtils; import javax.persistence.PersistenceException; +import javax.persistence.Tuple; import javax.persistence.TypedQuery; import java.sql.Timestamp; import java.time.LocalDateTime; @@ -98,6 +106,8 @@ public class VmInstanceBase extends AbstractVmInstance { protected static final CLogger logger = Utils.getLogger(VmInstanceBase.class); + private static final String ATTACH_CREATED_VM_SYSTEM_TAG_UUIDS = "AttachCreatedVmSystemTagUuids"; + private static final String UNRESOLVED_SDN_VENDOR = "__UNRESOLVED_SDN_VENDOR__"; @Autowired protected CloudBus bus; @@ -1011,16 +1021,38 @@ public void done(ErrorCodeList errorCodeList) { logger.debug(String.format("HaStartVmJudger[%s] says the VM[uuid:%s, name:%s] is qualified for HA start, now we are starting it", judger.getClass(), self.getUuid(), self.getName())); + String hostUuid = self.getHostUuid(); + String suspectHostUuid = StringUtils.trimToNull(hostUuid); + String peerHostUuid = StringUtils.trimToNull(msg.getAccessiblePeerHostUuid()); UpdateQuery sql = SQL.New(VmInstanceVO.class) .eq(VmInstanceVO_.uuid, self.getUuid()) .set(VmInstanceVO_.state, VmInstanceState.Stopped) .set(VmInstanceVO_.hostUuid, null); - if (self.getHostUuid() != null) { - sql.set(VmInstanceVO_.lastHostUuid, self.getHostUuid()); + if (hostUuid != null) { + sql.set(VmInstanceVO_.lastHostUuid, hostUuid); } sql.update(); + refreshVO(); + if (suspectHostUuid == null) { + logger.debug(String.format("HA-start vm[%s]: skip creating pre-fence tag because suspect host is absent", + self.getUuid())); + } else if (peerHostUuid == null) { + logger.debug(String.format("HA-start vm[%s]: skip creating pre-fence tag because peer host is absent", + self.getUuid())); + } else { + Map tokens = new HashMap<>(); + tokens.put(VmSystemTags.HA_PRE_FENCE_SUSPECT_HOST_UUID_TOKEN, suspectHostUuid); + tokens.put(VmSystemTags.HA_PRE_FENCE_ACCESSIBLE_PEER_HOST_UUID_TOKEN, peerHostUuid); + + SystemTagCreator creator = VmSystemTags.HA_PRE_FENCE_PENDING.newSystemTagCreator(self.getUuid()); + creator.inherent = true; + creator.recreate = true; + creator.ignoreIfExisting = true; + creator.setTagByTokens(tokens); + creator.create(); + } startVm(msg, new Completion(msg, chain) { @Override @@ -1269,15 +1301,7 @@ public void done(ErrorCodeList errorCodeList) { @Override public void run(FlowTrigger trigger, Map data) { - final VmInstanceInventory vm = getSelfInventory(); - final VmNicInventory nic = VmNicInventory.valueOf(targetNic); - CollectionUtils.safeForEach(pluginRgty.getExtensionList(VmIpChangedExtensionPoint.class), - new ForEachFunction() { - @Override - public void run(VmIpChangedExtensionPoint ext) { - ext.vmIpChanged(vm, nic, oldIpMap, newIpMap); - } - }); + notifyVmIpChanged(targetNic.getUuid(), oldIpMap, newIpMap); trigger.next(); } }); @@ -1303,6 +1327,39 @@ public void handle(ErrorCode errCode, Map data) { }).start(); } + private void notifyVmIpChanged(String vmNicUuid, Map oldIpMap, Map newIpMap) { + VmInstanceVO latestVm = dbf.findByUuid(self.getUuid(), VmInstanceVO.class); + if (latestVm == null) { + return; + } + self = latestVm; + final VmInstanceInventory vm = VmInstanceInventory.valueOf(latestVm); + VmNicVO latestNic = dbf.findByUuid(vmNicUuid, VmNicVO.class); + if (latestNic == null) { + return; + } + + final VmNicInventory nic = VmNicInventory.valueOf(latestNic); + CollectionUtils.safeForEach(pluginRgty.getExtensionList(VmIpChangedExtensionPoint.class), + new ForEachFunction() { + @Override + public void run(VmIpChangedExtensionPoint ext) { + ext.vmIpChanged(vm, nic, oldIpMap, newIpMap); + } + }); + } + + private UsedIpInventory toUsedIpInventory(UsedIpVO ipvo) { + UsedIpInventory ip = new UsedIpInventory(); + ip.setIp(ipvo.getIp()); + ip.setGateway(ipvo.getGateway()); + ip.setNetmask(ipvo.getNetmask()); + ip.setL3NetworkUuid(ipvo.getL3NetworkUuid()); + ip.setUuid(ipvo.getUuid()); + ip.setIpVersion(ipvo.getIpVersion()); + return ip; + } + private void handle(final ExpungeVmMsg msg) { final ExpungeVmReply reply = new ExpungeVmReply(); thdf.chainSubmit(new ChainTask(msg) { @@ -2171,7 +2228,8 @@ public String getName() { @Deferred @SuppressWarnings({"rawtypes", "unchecked"}) - private void attachNic(final Message msg, final List l3Uuids, final ReturnValueCompletion completion) { + private void attachNic(final Message msg, final List l3Uuids, final Map outerFlowData, + final ReturnValueCompletion completion) { refreshVO(); ErrorCode allowed = validateOperationByState(msg, self.getState(), SysErrors.OPERATION_ERROR); if (allowed != null) { @@ -2239,25 +2297,40 @@ void rollback() { } } - class SetL3SecurityGroupSystemTag { - private boolean isSet = false; + class SetVmSystemTags { + private List createdTags = new ArrayList<>(); void set () { if (msg instanceof APIAttachL3NetworkToVmMsg) { APIAttachL3NetworkToVmMsg amsg = (APIAttachL3NetworkToVmMsg) msg; + if (amsg.getSystemTags() == null || amsg.getSystemTags().isEmpty()) { + return; + } - if (amsg.hasSystemTag(VmSystemTags.L3_NETWORK_SECURITY_GROUP_UUIDS_REF::isMatch)) { - tagMgr.createNonInherentSystemTags(amsg.getSystemTags(), self.getUuid(), VmInstanceVO.class.getSimpleName()); - isSet = true; + List vmSystemTags = tagMgr.filterSystemTags( + amsg.getSystemTags(), VmInstanceVO.class.getSimpleName()); + + for (String tag : vmSystemTags) { + SystemTagInventory created = tagMgr.createNonInherentSystemTag( + self.getUuid(), tag, VmInstanceVO.class.getSimpleName()); + if (created != null) { + createdTags.add(created); + } } } } void rollback() { - if (isSet) { - VmSystemTags.L3_NETWORK_SECURITY_GROUP_UUIDS_REF.delete(self.getUuid()); + for (SystemTagInventory tag : createdTags) { + tagMgr.deleteSystemTag(tag.getUuid()); } } + + List getCreatedTagUuids() { + return createdTags.stream() + .map(SystemTagInventory::getUuid) + .collect(Collectors.toList()); + } } class SetCustomMacSystemTag { @@ -2289,7 +2362,7 @@ void rollback() { setStaticIp.set(); Defer.guard(setStaticIp::rollback); - final SetL3SecurityGroupSystemTag setSystemTag = new SetL3SecurityGroupSystemTag(); + final SetVmSystemTags setSystemTag = new SetVmSystemTags(); setSystemTag.set(); Defer.guard(setSystemTag::rollback); @@ -2298,6 +2371,7 @@ void rollback() { Defer.guard(setCustomMacSystemTag::rollback); final VmInstanceSpec spec = buildSpecFromInventory(getSelfInventory(), VmOperation.AttachNic); + spec.setMessage(msg); final VmInstanceInventory vm = spec.getVmInventory(); List l3s = new ArrayList<>(); for (String l3Uuid : l3Uuids) { @@ -2340,6 +2414,7 @@ void rollback() { flowChain.then(new VmAllocateNicFlow()); flowChain.then(new VmAllocateNicIpFlow()); + flowChain.then(new VmAllocateSdnNicFlow()); flowChain.then(new VmSetDefaultL3NetworkOnAttachingFlow()); setAdditionalFlow(flowChain, spec); if (self.getState() == VmInstanceState.Running) { @@ -2353,6 +2428,9 @@ public void handle(Map data) { CollectionUtils.safeForEach(pluginRgty.getExtensionList(VmAfterAttachL3NetworkExtensionPoint.class), arg -> l3s.forEach(l3 -> arg.vmAfterAttachL3Network(vm, l3))); VmNicInventory nic = spec.getDestNics().get(0); + if (outerFlowData != null && !setSystemTag.getCreatedTagUuids().isEmpty()) { + outerFlowData.put(ATTACH_CREATED_VM_SYSTEM_TAG_UUIDS, setSystemTag.getCreatedTagUuids()); + } completion.success(nic); } }).error(new FlowErrorHandler(completion) { @@ -2363,11 +2441,27 @@ public void handle(final ErrorCode errCode, Map data) { setDefaultL3Network.rollback(); setStaticIp.rollback(); setSystemTag.rollback(); + if (outerFlowData != null) { + outerFlowData.remove(ATTACH_CREATED_VM_SYSTEM_TAG_UUIDS); + } completion.fail(errCode); } }).start(); } + @SuppressWarnings("unchecked") + private void rollbackAttachCreatedVmSystemTags(Map data) { + Object tagUuids = data.get(ATTACH_CREATED_VM_SYSTEM_TAG_UUIDS); + if (!(tagUuids instanceof List)) { + return; + } + + for (String tagUuid : (List) tagUuids) { + tagMgr.deleteSystemTag(tagUuid); + } + data.remove(ATTACH_CREATED_VM_SYSTEM_TAG_UUIDS); + } + private void attachNic(final APIAttachVmNicToVmMsg msg, final ReturnValueCompletion completion) { thdf.chainSubmit(new ChainTask(completion) { @Override @@ -2457,6 +2551,14 @@ public void run(FlowTrigger trigger, Map data) { int deviceId = deviceIdBitmap.nextClearBit(0); deviceIdBitmap.set(deviceId); String internalName = VmNicVO.generateNicInternalName(spec.getVmInventory().getInternalId(), deviceId); + String driverType = vmNicVO.getDriverType(); + if (StringUtils.isEmpty(driverType)) { + VmNicInventory nicInv = VmNicInventory.valueOf(vmNicVO); + nicManager.setNicDriverType(nicInv, VmSystemTags.VIRTIO.hasTag(self.getUuid()), + ImagePlatform.valueOf(spec.getVmInventory().getPlatform()).isParaVirtualization(), + spec.getVmInventory()); + driverType = nicInv.getDriverType(); + } UpdateQuery.New(VmNicVO.class) .eq(VmNicVO_.uuid, vmNicUuid) @@ -2464,14 +2566,14 @@ public void run(FlowTrigger trigger, Map data) { .set(VmNicVO_.deviceId, deviceId) .set(VmNicVO_.internalName, internalName) .set(VmNicVO_.hypervisorType, spec.getVmInventory().getHypervisorType()) + .set(VmNicVO_.driverType, driverType) .update(); vmNicVO.setVmInstanceUuid(self.getUuid()); vmNicVO.setDeviceId(deviceId); vmNicVO.setInternalName(internalName); vmNicVO.setHypervisorType(spec.getVmInventory().getHypervisorType()); - vmNicVO.setDriverType(VmSystemTags.VIRTIO.hasTag(self.getUuid()) ? - nicManager.getDefaultPVNicDriver() : nicManager.getDefaultNicDriver()); + vmNicVO.setDriverType(driverType); spec.getDestNics().add(0, VmNicInventory.valueOf(vmNicVO)); trigger.next(); @@ -2552,7 +2654,7 @@ public void run(final SyncTaskChain chain) { public void run(FlowTrigger trigger, Map data) { List l3Uuids = new ArrayList<>(); l3Uuids.add(l3Uuid); - attachNic((Message) msg, l3Uuids, new ReturnValueCompletion(trigger) { + attachNic((Message) msg, l3Uuids, data, new ReturnValueCompletion(trigger) { @Override public void success(VmNicInventory returnValue) { data.put(vmNicInvKey, returnValue); @@ -2578,11 +2680,13 @@ public void rollback(FlowRollback trigger, Map data) { doDetachNic(nic, true, true, new Completion(trigger) { @Override public void success() { + rollbackAttachCreatedVmSystemTags(data); trigger.rollback(); } @Override public void fail(ErrorCode errorCode) { + rollbackAttachCreatedVmSystemTags(data); trigger.rollback(); } }); @@ -2626,6 +2730,7 @@ public void handle(Map data) { }).error(new FlowErrorHandler(completion) { @Override public void handle(ErrorCode errCode, Map data) { + rollbackAttachCreatedVmSystemTags(data); completion.fail(errCode); chain.next(); } @@ -3641,6 +3746,8 @@ public void run(FlowTrigger trigger, Map data) { // in dual stack l3 , keep the old ip which not set in msg List voRemoveList = new ArrayList<>(); List voOldList = Q.New(UsedIpVO.class).eq(UsedIpVO_.vmNicUuid, nicVO.getUuid()).list(); + Map oldIpMap = new HashMap<>(); + Map newIpMap = new HashMap<>(); if (msg.getIp() == null && msg.getIp6() == null) { voRemoveList.addAll(voOldList); nicVO.setUsedIpUuid(null); @@ -3702,9 +3809,16 @@ public void run(FlowTrigger trigger, Map data) { voRemoveList.addAll(voOldList.stream().filter(voOld -> voOld.getIpVersion() == IPv6Constants.IPv6).collect(Collectors.toList())); } } + for (UsedIpVO vo : voRemoveList) { + oldIpMap.put(vo.getIpVersion(), toUsedIpInventory(vo)); + } + for (UsedIpVO vo : voNewList) { + newIpMap.put(vo.getIpVersion(), toUsedIpInventory(vo)); + } dbf.persistCollection(voNewList); dbf.update(nicVO); dbf.removeCollection(voRemoveList, UsedIpVO.class); + notifyVmIpChanged(nicVO.getUuid(), oldIpMap, newIpMap); trigger.next(); } }); @@ -4765,12 +4879,7 @@ public String getName() { } private void detachIso(final String isoUuid, final Completion completion) { - if (!IsoOperator.isIsoAttachedToVm(self.getUuid())) { - completion.success(); - return; - } - - if (!IsoOperator.getIsoUuidByVmUuid(self.getUuid()).contains(isoUuid)) { + if (isoUuid == null) { completion.success(); return; } @@ -4779,7 +4888,11 @@ private void detachIso(final String isoUuid, final Completion completion) { .eq(VmCdRomVO_.vmInstanceUuid, self.getUuid()) .eq(VmCdRomVO_.isoUuid, isoUuid) .find(); - assert targetVmCdRomVO != null; + if (targetVmCdRomVO == null) { + new IsoOperator().syncVmIsoSystemTag(self.getUuid()); + completion.success(); + return; + } if (self.getState() == VmInstanceState.Stopped || self.getState() == VmInstanceState.Destroyed) { targetVmCdRomVO.setIsoUuid(null); @@ -4791,7 +4904,7 @@ private void detachIso(final String isoUuid, final Completion completion) { } VmInstanceSpec spec = buildSpecFromInventory(getSelfInventory(), VmOperation.DetachIso); - boolean isoNotExist = spec.getDestIsoList().stream().noneMatch(isoSpec -> isoSpec.getImageUuid().equals(isoUuid)); + boolean isoNotExist = spec.getDestIsoList().stream().noneMatch(isoSpec -> isoUuid.equals(isoSpec.getImageUuid())); if (isoNotExist) { // the image ISO has been deleted from backup storage // try to detach it from the VM anyway @@ -4995,10 +5108,7 @@ private void handle(APIGetVmAttachableL3NetworkMsg msg) { APIGetVmAttachableL3NetworkReply reply = new APIGetVmAttachableL3NetworkReply(); List l3Invs = getAttachableL3Network(msg.getSession().getAccountUuid()); - List ret = new ArrayList<>(l3Invs); - for (FilterAttachableL3NetworkExtensionPoint ext : pluginRgty.getExtensionList(FilterAttachableL3NetworkExtensionPoint.class)) { - ret = ext.filterAttachableL3Network(VmInstanceInventory.valueOf(self), ret); - } + List ret = filterAttachableL3Network(VmInstanceInventory.valueOf(self), l3Invs); reply.setInventories(ret); bus.reply(msg, reply); @@ -5008,10 +5118,7 @@ private void handle(APIGetCandidateL3NetworksForChangeVmNicNetworkMsg msg) { APIGetVmAttachableL3NetworkReply reply = new APIGetVmAttachableL3NetworkReply(); List l3Invs = getAttachableL3Network(msg.getSession().getAccountUuid()); - List ret = new ArrayList<>(l3Invs); - for (FilterAttachableL3NetworkExtensionPoint ext : pluginRgty.getExtensionList(FilterAttachableL3NetworkExtensionPoint.class)) { - ret = ext.filterAttachableL3Network(VmInstanceInventory.valueOf(self), ret); - } + List ret = filterAttachableL3Network(VmInstanceInventory.valueOf(self), l3Invs); VmNicVO nicVO= Q.New(VmNicVO.class).eq(VmNicVO_.uuid, msg.getVmNicUuid()).find(); for (FilterVmNicChangeableL3NetworkExtensionPoint ext : pluginRgty.getExtensionList(FilterVmNicChangeableL3NetworkExtensionPoint.class)) { @@ -5022,6 +5129,142 @@ private void handle(APIGetCandidateL3NetworksForChangeVmNicNetworkMsg msg) { bus.reply(msg, reply); } + private List filterAttachableL3Network(VmInstanceInventory vm, List l3Invs) { + List ret = filterAttachableL3NetworkByDomain(vm, l3Invs); + for (FilterAttachableL3NetworkExtensionPoint ext : pluginRgty.getExtensionList(FilterAttachableL3NetworkExtensionPoint.class)) { + if (ext instanceof VmAttachableL3NetworkDomainFilterExtensionPoint) { + continue; + } + ret = ext.filterAttachableL3Network(vm, ret); + } + return ret; + } + + private List filterAttachableL3NetworkByDomain(VmInstanceInventory vm, List l3Invs) { + Set domainFilters = new LinkedHashSet<>( + pluginRgty.getExtensionList(VmAttachableL3NetworkDomainFilterExtensionPoint.class)); + pluginRgty.getExtensionList(FilterAttachableL3NetworkExtensionPoint.class).stream() + .filter(VmAttachableL3NetworkDomainFilterExtensionPoint.class::isInstance) + .map(VmAttachableL3NetworkDomainFilterExtensionPoint.class::cast) + .forEach(domainFilters::add); + if (domainFilters.isEmpty()) { + return new ArrayList<>(l3Invs); + } + + Map> filtersByVendor = new HashMap<>(); + List defaultFilters = new ArrayList<>(); + for (VmAttachableL3NetworkDomainFilterExtensionPoint filter : domainFilters) { + String vendorType = filter.getSdnControllerVendorType(); + if (vendorType == null) { + defaultFilters.add(filter); + } else { + filtersByVendor.computeIfAbsent(vendorType, k -> new ArrayList<>()).add(filter); + } + } + Map vendorTypeByL3Uuid = getSdnControllerVendorTypeByL3Uuid(l3Invs); + Map> l3sByVendor = new LinkedHashMap<>(); + for (L3NetworkInventory l3 : l3Invs) { + String vendorType = vendorTypeByL3Uuid.get(l3.getUuid()); + l3sByVendor.computeIfAbsent(vendorType, k -> new ArrayList<>()).add(l3); + } + + List ret = new ArrayList<>(); + for (Map.Entry> e : l3sByVendor.entrySet()) { + List filters; + if (e.getKey() == null) { + filters = defaultFilters; + } else if (UNRESOLVED_SDN_VENDOR.equals(e.getKey())) { + filters = Collections.emptyList(); + } else { + filters = filtersByVendor.getOrDefault(e.getKey(), Collections.emptyList()); + } + if (filters.isEmpty()) { + ret.addAll(e.getValue()); + continue; + } + + List filtered = new ArrayList<>(e.getValue()); + for (VmAttachableL3NetworkDomainFilterExtensionPoint filter : filters) { + filtered = filter.filterAttachableL3NetworkInDomain(vm, filtered); + } + ret.addAll(filtered); + } + return ret; + } + + private Map getSdnControllerVendorTypeByL3Uuid(List l3Invs) { + if (l3Invs.isEmpty()) { + return Collections.emptyMap(); + } + + List l3Uuids = l3Invs.stream() + .map(L3NetworkInventory::getUuid) + .collect(Collectors.toList()); + List l3L2Tuples = Q.New(L3NetworkVO.class) + .select(L3NetworkVO_.uuid, L3NetworkVO_.l2NetworkUuid) + .in(L3NetworkVO_.uuid, l3Uuids) + .listTuple(); + + Map l3ToL2Uuid = new HashMap<>(); + Set l2Uuids = new HashSet<>(); + for (Tuple t : l3L2Tuples) { + String l3Uuid = t.get(0, String.class); + String l2Uuid = t.get(1, String.class); + l3ToL2Uuid.put(l3Uuid, l2Uuid); + if (l2Uuid != null) { + l2Uuids.add(l2Uuid); + } + } + + if (l2Uuids.isEmpty()) { + return Collections.emptyMap(); + } + + List controllerTagTuples = Q.New(SystemTagVO.class) + .select(SystemTagVO_.resourceUuid, SystemTagVO_.tag) + .in(SystemTagVO_.resourceUuid, l2Uuids) + .eq(SystemTagVO_.resourceType, L2NetworkVO.class.getSimpleName()) + .like(SystemTagVO_.tag, L2NetworkSystemTags.L2_NETWORK_SDN_CONTROLLER_UUID_TOKEN + "::%") + .listTuple(); + Map l2ToControllerUuid = new HashMap<>(); + Set controllerUuids = new HashSet<>(); + for (Tuple t : controllerTagTuples) { + String l2Uuid = t.get(0, String.class); + String tag = t.get(1, String.class); + String controllerUuid = L2NetworkSystemTags.L2_NETWORK_SDN_CONTROLLER_UUID.getTokenByTag( + tag, L2NetworkSystemTags.L2_NETWORK_SDN_CONTROLLER_UUID_TOKEN); + if (controllerUuid != null) { + l2ToControllerUuid.put(l2Uuid, controllerUuid); + controllerUuids.add(controllerUuid); + } + } + + if (controllerUuids.isEmpty()) { + return Collections.emptyMap(); + } + + List controllerVOS = Q.New(SdnControllerVO.class) + .in(SdnControllerVO_.uuid, controllerUuids) + .list(); + Map controllerUuidToVendorType = new HashMap<>(); + for (SdnControllerVO vo : controllerVOS) { + controllerUuidToVendorType.put(vo.getUuid(), vo.getVendorType()); + } + + Map vendorTypeByL3Uuid = new HashMap<>(); + for (Map.Entry e : l3ToL2Uuid.entrySet()) { + String controllerUuid = l2ToControllerUuid.get(e.getValue()); + if (controllerUuid == null) { + continue; + } + + String vendorType = controllerUuidToVendorType.get(controllerUuid); + vendorTypeByL3Uuid.put(e.getKey(), + StringUtils.isBlank(vendorType) ? UNRESOLVED_SDN_VENDOR : vendorType); + } + return vendorTypeByL3Uuid; + } + private void handle(final AttachIsoToVmInstanceMsg msg) { thdf.chainSubmit(new ChainTask(msg) { @Override @@ -5335,6 +5578,7 @@ private void handle(final APIChangeVmNicStateMsg msg) { SQL.New(VmNicVO.class).eq(VmNicVO_.uuid, msg.getVmNicUuid()).set(VmNicVO_.state, VmNicState.disable).update(); } self = dbf.reload(self); + extEmitter.afterChangeVmNicState(msg.getVmNicUuid(), msg.getState()); evt.setInventory(VmInstanceInventory.valueOf(self)); bus.publish(evt); return; @@ -9273,4 +9517,3 @@ public void run(MessageReply reply) { }); } } - diff --git a/compute/src/main/java/org/zstack/compute/vm/VmInstanceExtensionPointEmitter.java b/compute/src/main/java/org/zstack/compute/vm/VmInstanceExtensionPointEmitter.java index b4e66919d1d..78be6365828 100755 --- a/compute/src/main/java/org/zstack/compute/vm/VmInstanceExtensionPointEmitter.java +++ b/compute/src/main/java/org/zstack/compute/vm/VmInstanceExtensionPointEmitter.java @@ -51,6 +51,7 @@ public class VmInstanceExtensionPointEmitter implements Component { private List cleanUpAfterVmChangeImageExtensionPoints; private List vmNicChangeStateExtensionPoints; private List sshKeyPairAssociateExtensionPoints; + private List afterUpdateVmNicMacExtensionPoints; public List handleSystemTag(String vmUuid, List tags){ List errorCodes = new ArrayList<>(); @@ -581,6 +582,10 @@ public void afterChangeVmNicState(final String vmNic, final String state) { CollectionUtils.safeForEach(vmNicChangeStateExtensionPoints, arg -> arg.afterChangeVmNicState(vmNic, state)); } + public void afterUpdateVmNicMac(final VmNicInventory nic, final String oldMac, final String newMac) { + CollectionUtils.safeForEach(afterUpdateVmNicMacExtensionPoints, arg -> arg.afterUpdateVmNicMac(nic, oldMac, newMac)); + } + public List associateSshKeyPair(String vmUuid, List sshKeyUuids) { List errorCodes = new ArrayList<>(); CollectionUtils.safeForEach(sshKeyPairAssociateExtensionPoints, extension -> { @@ -626,6 +631,7 @@ private void populateExtensions() { cleanUpAfterVmChangeImageExtensionPoints = pluginRgty.getExtensionList(CleanUpAfterVmChangeImageExtensionPoint.class); vmNicChangeStateExtensionPoints = pluginRgty.getExtensionList(VmNicChangeStateExtensionPoint.class); sshKeyPairAssociateExtensionPoints = pluginRgty.getExtensionList(SshKeyPairAssociateExtensionPoint.class); + afterUpdateVmNicMacExtensionPoints = pluginRgty.getExtensionList(AfterUpdateVmNicMacExtensionPoint.class); } @Override diff --git a/compute/src/main/java/org/zstack/compute/vm/VmNicLifecycleGlobalConfig.java b/compute/src/main/java/org/zstack/compute/vm/VmNicLifecycleGlobalConfig.java new file mode 100644 index 00000000000..a1ca2001303 --- /dev/null +++ b/compute/src/main/java/org/zstack/compute/vm/VmNicLifecycleGlobalConfig.java @@ -0,0 +1,14 @@ +package org.zstack.compute.vm; + +import org.zstack.core.config.GlobalConfig; +import org.zstack.core.config.GlobalConfigDefinition; +import org.zstack.core.config.GlobalConfigValidation; + +@GlobalConfigDefinition +public class VmNicLifecycleGlobalConfig { + public static final String CATEGORY = "vmNicLifecycle"; + + @GlobalConfigValidation(numberGreaterThan = 0) + public static GlobalConfig RECONCILE_TIMEOUT = + new GlobalConfig(CATEGORY, "reconcileOnHost.timeout"); +} diff --git a/compute/src/main/java/org/zstack/compute/vm/VmNicLifecycleManager.java b/compute/src/main/java/org/zstack/compute/vm/VmNicLifecycleManager.java new file mode 100644 index 00000000000..2a7348c416e --- /dev/null +++ b/compute/src/main/java/org/zstack/compute/vm/VmNicLifecycleManager.java @@ -0,0 +1,487 @@ +package org.zstack.compute.vm; + +import org.springframework.beans.factory.annotation.Autowired; +import org.zstack.core.Platform; +import org.zstack.core.componentloader.PluginRegistry; +import org.zstack.core.workflow.FlowChainBuilder; +import org.zstack.header.core.Completion; +import org.zstack.header.core.NoErrorCompletion; +import org.zstack.header.core.workflow.*; +import org.zstack.header.errorcode.ErrorCode; +import org.zstack.header.errorcode.SysErrors; +import org.zstack.header.network.l3.L3NetworkInventory; +import org.zstack.header.vm.*; +import org.zstack.utils.Utils; +import org.zstack.utils.logging.CLogger; + +import java.util.*; +import java.util.stream.Collectors; + +public class VmNicLifecycleManager implements + PreVmInstantiateResourceExtensionPoint, + VmReleaseResourceExtensionPoint, + VmInstanceMigrateExtensionPoint, + InstantiateResourceOnAttachingNicExtensionPoint, + ReleaseNetworkServiceOnDetachingNicExtensionPoint { + + private static final CLogger logger = Utils.getLogger(VmNicLifecycleManager.class); + + @Autowired + private PluginRegistry pluginRgty; + + private List getExtensions() { + return pluginRgty.getExtensionList(VmNicLifecycleExtensionPoint.class); + } + + // ===================== NIC filtering ===================== + + private List filterNics(VmNicLifecycleExtensionPoint ext, + List allNics) { + List matched = new ArrayList<>(); + for (VmNicInventory nic : allNics) { + try { + if (ext.isApplicable(nic)) { + matched.add(nic); + } + } catch (Exception e) { + logger.error(String.format("[VmNicLifecycle] %s.isApplicable(nic=%s) threw exception", + ext.getClass().getSimpleName(), nic.getUuid()), e); + throw new RuntimeException(String.format("%s.isApplicable failed for nic[uuid:%s]", + ext.getClass().getSimpleName(), nic.getUuid()), e); + } + } + return matched; + } + + // ===================== fail-fast serial runner (setup / preMigrate) ===================== + + private void runSetup(VmNicLifecycleContext context, Iterator it, + String hostUuid, List allNics, + Completion completion) { + if (!it.hasNext()) { + completion.success(); + return; + } + + VmNicLifecycleExtensionPoint ext = it.next(); + List nics; + try { + nics = filterNics(ext, allNics); + } catch (RuntimeException e) { + completion.fail(Platform.err(SysErrors.OPERATION_ERROR.toString(), SysErrors.OPERATION_ERROR, "%s", e.getMessage())); + return; + } + if (nics.isEmpty()) { + runSetup(context, it, hostUuid, allNics, completion); + return; + } + + long start = System.currentTimeMillis(); + try { + ext.setupOnHost(context, hostUuid, nics, new Completion(completion) { + @Override + public void success() { + logger.debug(String.format("[VmNicLifecycle] %s.setupOnHost(host=%s, nics=%d) " + + "completed in %dms", ext.getClass().getSimpleName(), hostUuid, + nics.size(), System.currentTimeMillis() - start)); + runSetup(context, it, hostUuid, allNics, completion); + } + + @Override + public void fail(ErrorCode errorCode) { + logger.warn(String.format("[VmNicLifecycle] %s.setupOnHost(host=%s) failed: %s", + ext.getClass().getSimpleName(), hostUuid, errorCode)); + completion.fail(errorCode); + } + }); + } catch (Throwable t) { + completion.fail(Platform.err(SysErrors.OPERATION_ERROR.toString(), SysErrors.OPERATION_ERROR, + "%s.setupOnHost(host=%s) threw exception: %s", + ext.getClass().getSimpleName(), hostUuid, t.getMessage())); + } + } + + private void runPreMigrate(Iterator it, + String srcHostUuid, String destHostUuid, + List allNics, Completion completion) { + if (!it.hasNext()) { + completion.success(); + return; + } + + VmNicLifecycleExtensionPoint ext = it.next(); + List nics; + try { + nics = filterNics(ext, allNics); + } catch (RuntimeException e) { + completion.fail(Platform.err(SysErrors.OPERATION_ERROR.toString(), SysErrors.OPERATION_ERROR, "%s", e.getMessage())); + return; + } + if (nics.isEmpty()) { + runPreMigrate(it, srcHostUuid, destHostUuid, allNics, completion); + return; + } + + long start = System.currentTimeMillis(); + try { + ext.preMigrate(srcHostUuid, destHostUuid, nics, new Completion(completion) { + @Override + public void success() { + logger.debug(String.format("[VmNicLifecycle] %s.preMigrate(src=%s, dest=%s, nics=%d) " + + "completed in %dms", ext.getClass().getSimpleName(), + srcHostUuid, destHostUuid, nics.size(), System.currentTimeMillis() - start)); + runPreMigrate(it, srcHostUuid, destHostUuid, allNics, completion); + } + + @Override + public void fail(ErrorCode errorCode) { + logger.warn(String.format("[VmNicLifecycle] %s.preMigrate(src=%s, dest=%s) failed: %s", + ext.getClass().getSimpleName(), srcHostUuid, destHostUuid, errorCode)); + completion.fail(errorCode); + } + }); + } catch (Throwable t) { + completion.fail(Platform.err(SysErrors.OPERATION_ERROR.toString(), SysErrors.OPERATION_ERROR, + "%s.preMigrate(src=%s, dest=%s) threw exception: %s", + ext.getClass().getSimpleName(), srcHostUuid, destHostUuid, t.getMessage())); + } + } + + // ===================== fail-logged serial runner (cleanup / postMigrate / failedMigrate) ===================== + + @FunctionalInterface + private interface CleanupAction { + void execute(VmNicLifecycleExtensionPoint ext, List nics, + NoErrorCompletion completion); + } + + private void runFailLogged(Iterator it, + List allNics, + String methodName, CleanupAction action, + NoErrorCompletion completion) { + if (!it.hasNext()) { + completion.done(); + return; + } + + VmNicLifecycleExtensionPoint ext = it.next(); + List nics; + try { + nics = filterNics(ext, allNics); + } catch (RuntimeException e) { + logger.warn(String.format("[VmNicLifecycle] %s.isApplicable threw exception during %s", + ext.getClass().getSimpleName(), methodName), e); + runFailLogged(it, allNics, methodName, action, completion); + return; + } + if (nics.isEmpty()) { + runFailLogged(it, allNics, methodName, action, completion); + return; + } + + try { + action.execute(ext, nics, new NoErrorCompletion() { + @Override + public void done() { + runFailLogged(it, allNics, methodName, action, completion); + } + }); + } catch (Throwable t) { + logger.warn(String.format("[VmNicLifecycle] %s.%s threw exception", + ext.getClass().getSimpleName(), methodName), t); + runFailLogged(it, allNics, methodName, action, completion); + } + } + + private void runCleanup(Iterator it, + String hostUuid, List allNics, + NoErrorCompletion completion) { + runFailLogged(it, allNics, "cleanupFromHost", + (ext, nics, done) -> ext.cleanupFromHost(hostUuid, nics, done), completion); + } + + private void runCleanupStale(Iterator it, + String lastHostUuid, List allNics, + NoErrorCompletion completion) { + runFailLogged(it, allNics, "cleanupStaleResource", + (ext, nics, done) -> ext.cleanupStaleResource(lastHostUuid, nics, done), completion); + } + + private void runPostMigrate(Iterator it, + String srcHostUuid, String destHostUuid, + List allNics, NoErrorCompletion completion) { + runFailLogged(it, allNics, "postMigrate", + (ext, nics, done) -> ext.postMigrate(srcHostUuid, destHostUuid, nics, done), + completion); + } + + private void runFailedMigrate(Iterator it, + String srcHostUuid, String destHostUuid, + List allNics, NoErrorCompletion completion) { + runFailLogged(it, allNics, "failedMigrate", + (ext, nics, done) -> ext.failedMigrate(srcHostUuid, destHostUuid, nics, done), + completion); + } + + // ===================== PreVmInstantiateResourceExtensionPoint ===================== + + @Override + public void preBeforeInstantiateVmResource(VmInstanceSpec spec) + throws VmInstantiateResourceException { + // sync hook — no resource operations + } + + private VmNicLifecycleContext buildContext(VmInstanceSpec spec, String destHostUuid) { + VmNicLifecycleContext ctx = new VmNicLifecycleContext(); + ctx.setOperation(spec.getCurrentVmOperation()); + ctx.setDestHostUuid(destHostUuid); + if (spec.getVmInventory() != null) { + ctx.setVmUuid(spec.getVmInventory().getUuid()); + ctx.setSrcHostUuid(spec.getVmInventory().getHostUuid()); + ctx.setLastHostUuid(spec.getVmInventory().getLastHostUuid()); + } + return ctx; + } + + @Override + public void preInstantiateVmResource(VmInstanceSpec spec, Completion completion) { + List allNics = spec.getDestNics(); + if (allNics == null || allNics.isEmpty() || getExtensions().isEmpty()) { + completion.success(); + return; + } + + if (spec.getDestHost() == null) { + completion.success(); + return; + } + String destHostUuid = spec.getDestHost().getUuid(); + String lastHostUuid = spec.getVmInventory().getLastHostUuid(); + VmInstanceConstant.VmOperation op = spec.getCurrentVmOperation(); + VmNicLifecycleContext ctx = buildContext(spec, destHostUuid); + + FlowChain chain = FlowChainBuilder.newSimpleFlowChain(); + chain.setName("vmnic-lifecycle-pre-instantiate-" + spec.getVmInventory().getUuid()); + + if (lastHostUuid != null && !lastHostUuid.equals(destHostUuid) + && op == VmInstanceConstant.VmOperation.Start) { + chain.then(new NoRollbackFlow() { + String __name__ = "cleanup-stale-resource-from-last-host"; + + @Override + public void run(FlowTrigger trigger, Map data) { + runCleanupStale(getExtensions().iterator(), lastHostUuid, allNics, + new NoErrorCompletion() { + @Override + public void done() { + trigger.next(); + } + }); + } + }); + } + + chain.then(new NoRollbackFlow() { + String __name__ = "setup-on-dest-host"; + + @Override + public void run(FlowTrigger trigger, Map data) { + runSetup(ctx, getExtensions().iterator(), destHostUuid, allNics, new Completion(trigger) { + @Override + public void success() { + trigger.next(); + } + + @Override + public void fail(ErrorCode errorCode) { + trigger.fail(errorCode); + } + }); + } + }); + + chain.done(new FlowDoneHandler(completion) { + @Override + public void handle(Map data) { + completion.success(); + } + }).error(new FlowErrorHandler(completion) { + @Override + public void handle(ErrorCode errCode, Map data) { + completion.fail(errCode); + } + }).start(); + } + + @Override + public void preReleaseVmResource(VmInstanceSpec spec, Completion completion) { + doCleanup(spec, new NoErrorCompletion(completion) { + @Override + public void done() { + completion.success(); + } + }); + } + + // ===================== VmReleaseResourceExtensionPoint ===================== + + @Override + public void releaseVmResource(VmInstanceSpec spec, Completion completion) { + if (spec.getCurrentVmOperation() == VmInstanceConstant.VmOperation.Reboot) { + completion.success(); + return; + } + doCleanup(spec, new NoErrorCompletion(completion) { + @Override + public void done() { + completion.success(); + } + }); + } + + private void doCleanup(VmInstanceSpec spec, NoErrorCompletion completion) { + List allNics = spec.getDestNics(); + if (allNics == null || allNics.isEmpty() || getExtensions().isEmpty()) { + completion.done(); + return; + } + if (spec.getDestHost() == null) { + completion.done(); + return; + } + String hostUuid = spec.getDestHost().getUuid(); + runCleanup(getExtensions().iterator(), hostUuid, allNics, completion); + } + + // ===================== VmInstanceMigrateExtensionPoint ===================== + + @Override + public void beforeMigrateVm(VmInstanceInventory inv, String destHostUuid) { + // no-op — sync validation hook + } + + @Override + public void preMigrateVm(VmInstanceInventory inv, String destHostUuid, + Completion completion) { + if (getExtensions().isEmpty()) { + completion.success(); + return; + } + String srcHostUuid = inv.getHostUuid(); + List allNics = inv.getVmNics(); + if (allNics == null || allNics.isEmpty()) { + completion.success(); + return; + } + runPreMigrate(getExtensions().iterator(), srcHostUuid, destHostUuid, allNics, completion); + } + + @Override + public void postMigrateVm(VmInstanceInventory inv, String destHostUuid, + Completion completion) { + if (getExtensions().isEmpty()) { + completion.success(); + return; + } + String srcHostUuid = inv.getHostUuid(); + List allNics = inv.getVmNics(); + if (allNics == null || allNics.isEmpty()) { + completion.success(); + return; + } + runPostMigrate(getExtensions().iterator(), srcHostUuid, destHostUuid, allNics, + new NoErrorCompletion(completion) { + @Override + public void done() { + completion.success(); + } + }); + } + + @Override + public void afterMigrateVm(VmInstanceInventory inv, String srcHostUuid, + NoErrorCompletion completion) { + completion.done(); + } + + @Override + public void failedToMigrateVm(VmInstanceInventory inv, String destHostUuid, + ErrorCode reason, NoErrorCompletion completion) { + if (getExtensions().isEmpty()) { + completion.done(); + return; + } + String srcHostUuid = inv.getHostUuid(); + List allNics = inv.getVmNics(); + if (allNics == null || allNics.isEmpty()) { + completion.done(); + return; + } + runFailedMigrate(getExtensions().iterator(), srcHostUuid, destHostUuid, allNics, completion); + } + + // ===================== InstantiateResourceOnAttachingNicExtensionPoint ===================== + + @Override + public void instantiateResourceOnAttachingNic(VmInstanceSpec spec, + L3NetworkInventory l3, Completion completion) { + VmInstanceInventory vm = spec.getVmInventory(); + if (!VmInstanceState.Running.toString().equals(vm.getState()) || getExtensions().isEmpty()) { + completion.success(); + return; + } + + List newNics = spec.getDestNics().stream() + .filter(nic -> nic.getL3NetworkUuid().equals(l3.getUuid())) + .collect(Collectors.toList()); + if (newNics.isEmpty()) { + completion.success(); + return; + } + + String hostUuid = vm.getHostUuid(); + VmNicLifecycleContext ctx = buildContext(spec, hostUuid); + ctx.setOperation(VmInstanceConstant.VmOperation.AttachNic); + runSetup(ctx, getExtensions().iterator(), hostUuid, newNics, completion); + } + + @Override + public void releaseResourceOnAttachingNic(VmInstanceSpec spec, + L3NetworkInventory l3, NoErrorCompletion completion) { + doCleanupForNic(spec, l3, completion); + } + + private void doCleanupForNic(VmInstanceSpec spec, L3NetworkInventory l3, + NoErrorCompletion completion) { + if (getExtensions().isEmpty()) { + completion.done(); + return; + } + String hostUuid = spec.getVmInventory().getHostUuid(); + if (hostUuid == null) { + completion.done(); + return; + } + List nics = spec.getDestNics().stream() + .filter(nic -> nic.getL3NetworkUuid().equals(l3.getUuid())) + .collect(Collectors.toList()); + runCleanup(getExtensions().iterator(), hostUuid, nics, completion); + } + + // ===================== ReleaseNetworkServiceOnDetachingNicExtensionPoint ===================== + + @Override + public void releaseResourceOnDetachingNic(VmInstanceSpec spec, + VmNicInventory nic, NoErrorCompletion completion) { + if (getExtensions().isEmpty()) { + completion.done(); + return; + } + String hostUuid = spec.getVmInventory().getHostUuid(); + if (hostUuid == null) { + completion.done(); + return; + } + runCleanup(getExtensions().iterator(), hostUuid, Collections.singletonList(nic), completion); + } +} diff --git a/compute/src/main/java/org/zstack/compute/vm/VmNicManager.java b/compute/src/main/java/org/zstack/compute/vm/VmNicManager.java index ab6cc8d749d..f703b8d4d43 100644 --- a/compute/src/main/java/org/zstack/compute/vm/VmNicManager.java +++ b/compute/src/main/java/org/zstack/compute/vm/VmNicManager.java @@ -20,4 +20,6 @@ public interface VmNicManager { void setNicDriverType(VmNicInventory nic, boolean isImageSupportVirtIo, boolean isParaVirtualization, VmInstanceInventory vm); VmNicType getVmNicType(String vmUuid, L3NetworkInventory l3nw); + + VmNicType getVmNicType(String vmUuid, L3NetworkInventory l3nw, List vmSystemTags); } 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 31b3e35d32a..b977c85adca 100644 --- a/compute/src/main/java/org/zstack/compute/vm/VmNicManagerImpl.java +++ b/compute/src/main/java/org/zstack/compute/vm/VmNicManagerImpl.java @@ -1,6 +1,5 @@ package org.zstack.compute.vm; -import com.google.common.collect.Maps; import org.apache.commons.collections.CollectionUtils; import org.springframework.beans.factory.annotation.Autowire; import org.springframework.beans.factory.annotation.Autowired; @@ -128,39 +127,40 @@ public void afterDelIpAddress(String vmNicUUid, String usedIpUuid) { @Override public void prepareDbInitialValue() { - List nics = Q.New(VmNicVO.class).notNull(VmNicVO_.vmInstanceUuid).list(); - List ns = nics.stream() - .filter(v -> v.getDriverType() == null - && v.getType().equals(VmInstanceConstant.VIRTUAL_NIC_TYPE) - && v.getVmInstanceUuid() != null) - .collect(Collectors.toList()); + List nics = Q.New(VmNicVO.class) + .isNull(VmNicVO_.driverType) + .eq(VmNicVO_.type, VmInstanceConstant.VIRTUAL_NIC_TYPE) + .notNull(VmNicVO_.vmInstanceUuid) + .list(); - if (CollectionUtils.isEmpty(ns)) { + if (CollectionUtils.isEmpty(nics)) { return; } - List vmUuids = ns.stream() + List vmUuids = nics.stream() .map(VmNicVO::getVmInstanceUuid) + .distinct() .collect(Collectors.toList()); + Set virtioVmUuids = new HashSet<>(VmSystemTags.VIRTIO.filterResourceHasTag(vmUuids)); List tupleList = Q.New(VmInstanceVO.class) .select(VmInstanceVO_.uuid, VmInstanceVO_.platform) .in(VmInstanceVO_.uuid, vmUuids) .listTuple(); - Map vmPlatforms = Maps.newHashMap(); + Map vmDrivers = new HashMap<>(); for (Tuple vmTuple : tupleList) { String vmUuid = vmTuple.get(0, String.class); String vmPlatform = vmTuple.get(1, String.class); - vmPlatforms.put(vmUuid, ImagePlatform.valueOf(vmPlatform).isParaVirtualization() ? + vmDrivers.put(vmUuid, virtioVmUuids.contains(vmUuid) || ImagePlatform.valueOf(vmPlatform).isParaVirtualization() ? defaultPVNicDriver : defaultNicDriver); } Map> nicGroups = nics.stream() - .filter(v -> vmPlatforms.containsKey(v.getVmInstanceUuid())) + .filter(v -> vmDrivers.containsKey(v.getVmInstanceUuid())) .collect( Collectors.groupingBy( - v -> vmPlatforms.get(v.getVmInstanceUuid()).equals(defaultPVNicDriver), + v -> vmDrivers.get(v.getVmInstanceUuid()).equals(defaultPVNicDriver), Collectors.mapping(VmNicVO::getUuid, Collectors.toList())) ); @@ -284,6 +284,53 @@ public void setNicDriverType(VmNicInventory nic, boolean isImageSupportVirtIo, b @Override public VmNicType getVmNicType(String vmUuid, L3NetworkInventory l3nw) { + return getVmNicType(vmUuid, l3nw, null); + } + + @Override + public VmNicType getVmNicType(String vmUuid, L3NetworkInventory l3nw, List vmSystemTags) { + L2NetworkVO l2nw = dbf.findByUuid(l3nw.getL2NetworkUuid(), L2NetworkVO.class); + VSwitchType vSwitchType = VSwitchType.valueOf(l2nw.getvSwitchType()); + + if (L2NetworkConstant.VSWITCH_TYPE_ZNS.equals(l2nw.getvSwitchType())) { + List znsNicModes = new ArrayList<>(); + if (vmSystemTags != null) { + znsNicModes.addAll(vmSystemTags.stream() + .filter(Objects::nonNull) + .map(String::trim) + .filter(VmSystemTags.ZNS_NIC_MODE::isMatch) + .map(tag -> VmSystemTags.ZNS_NIC_MODE.getTokenByTag(tag, VmSystemTags.ZNS_NIC_MODE_TOKEN)) + .collect(Collectors.toList())); + } + znsNicModes.addAll(VmSystemTags.ZNS_NIC_MODE.getTags(vmUuid).stream() + .map(tag -> VmSystemTags.ZNS_NIC_MODE.getTokenByTag(tag, VmSystemTags.ZNS_NIC_MODE_TOKEN)) + .collect(Collectors.toList())); + + List normalizedModes = znsNicModes.stream() + .filter(Objects::nonNull) + .map(String::trim) + .distinct() + .collect(Collectors.toList()); + + for (String mode : normalizedModes) { + if (!VmInstanceConstant.ZNS_NIC_MODE_DPDK.equals(mode) && !VmInstanceConstant.ZNS_NIC_MODE_KERNEL.equals(mode)) { + throw new OperationFailureException(argerr(ORG_ZSTACK_COMPUTE_VM_10257, + "invalid znsNicMode[%s], valid values are [%s, %s]", + mode, VmInstanceConstant.ZNS_NIC_MODE_DPDK, VmInstanceConstant.ZNS_NIC_MODE_KERNEL)); + } + } + + if (normalizedModes.size() > 1) { + throw new OperationFailureException(argerr(ORG_ZSTACK_COMPUTE_VM_10257, + "conflicting znsNicMode tags %s, only one mode is allowed", normalizedModes)); + } + + boolean enableZnsDpdk = normalizedModes.contains(VmInstanceConstant.ZNS_NIC_MODE_DPDK); + logger.debug(String.format("create %s on zns l3 network[uuid:%s] inside VmAllocateNicFlow", + enableZnsDpdk ? "dpdk vhostuser nic" : "vnic", l3nw.getUuid())); + return vSwitchType.getVmNicType(enableZnsDpdk ? VmNicType.VmNicSubType.VHOSTUSER : VmNicType.VmNicSubType.NONE); + } + List tags = new ArrayList<>(); tags.add(String.format("enableSRIOV::%s", l3nw.getUuid())); tags.add(String.format("enableVFHA::%s", l3nw.getUuid())); @@ -295,14 +342,19 @@ public VmNicType getVmNicType(String vmUuid, L3NetworkInventory l3nw) { logger.debug(String.format("create %s on l3 network[uuid:%s] inside VmAllocateNicFlow", enableSriov ? "vf nic" : "vnic", l3nw.getUuid())); boolean enableVhostUser = NetworkServiceGlobalConfig.ENABLE_VHOSTUSER.value(Boolean.class); + + boolean enableDpdkVhostuser = Q.New(SystemTagVO.class) + .eq(SystemTagVO_.resourceType, VmInstanceVO.class.getSimpleName()) + .eq(SystemTagVO_.resourceUuid, vmUuid) + .eq(SystemTagVO_.tag, String.format("enableDpdkVhostuser::%s", l3nw.getUuid())) + .isExists(); + VmNicType.VmNicSubType subType = VmNicType.VmNicSubType.NONE; if (enableSriov) { subType = VmNicType.VmNicSubType.SRIOV; - } else if (enableVhostUser) { + } else if (enableVhostUser || enableDpdkVhostuser) { subType = VmNicType.VmNicSubType.VHOSTUSER; } - L2NetworkVO l2nw = dbf.findByUuid(l3nw.getL2NetworkUuid(), L2NetworkVO.class); - VSwitchType vSwitchType = VSwitchType.valueOf(l2nw.getvSwitchType()); return vSwitchType.getVmNicType(subType); } diff --git a/compute/src/main/java/org/zstack/compute/vm/VmReturnReleaseNicFlow.java b/compute/src/main/java/org/zstack/compute/vm/VmReturnReleaseNicFlow.java index 0fd0e2aa068..7279d7e8af5 100755 --- a/compute/src/main/java/org/zstack/compute/vm/VmReturnReleaseNicFlow.java +++ b/compute/src/main/java/org/zstack/compute/vm/VmReturnReleaseNicFlow.java @@ -6,10 +6,13 @@ import org.zstack.core.asyncbatch.While; import org.zstack.core.cloudbus.CloudBus; import org.zstack.core.cloudbus.CloudBusCallBack; +import org.zstack.core.componentloader.PluginRegistry; import org.zstack.core.db.DatabaseFacade; +import org.zstack.header.core.Completion; import org.zstack.header.core.WhileDoneCompletion; import org.zstack.header.core.workflow.FlowTrigger; import org.zstack.header.core.workflow.NoRollbackFlow; +import org.zstack.header.errorcode.ErrorCode; import org.zstack.header.errorcode.ErrorCodeList; import org.zstack.header.message.MessageReply; import org.zstack.header.network.l3.L3NetworkConstant; @@ -34,6 +37,10 @@ public class VmReturnReleaseNicFlow extends NoRollbackFlow { protected CloudBus bus; @Autowired protected VmInstanceDeletionPolicyManager deletionPolicyMgr; + @Autowired + protected VmInstanceManager vmMgr; + @Autowired + protected PluginRegistry pluginRgty; @Override public void run(FlowTrigger chain, Map data) { @@ -43,6 +50,11 @@ public void run(FlowTrigger chain, Map data) { return; } + returnIpsAndReleaseNics(spec, data, chain); + } + + + private void returnIpsAndReleaseNics(VmInstanceSpec spec, Map data, FlowTrigger chain) { List msgs = new ArrayList<>(spec.getVmInventory().getVmNics().size()); for (VmNicInventory nic : spec.getVmInventory().getVmNics()) { for (UsedIpInventory ip : nic.getUsedIps()) { @@ -54,6 +66,11 @@ public void run(FlowTrigger chain, Map data) { } } + VmInstanceDeletionPolicy deletionPolicy = + VmInstanceConstant.USER_VM_TYPE.equals(spec.getVmInventory().getType()) + ? getDeletionPolicy(spec, data) + : VmInstanceDeletionPolicy.Direct; + new While<>(msgs).each((returnIpMsg, completion) -> bus.send(returnIpMsg, new CloudBusCallBack(completion) { @Override public void run(MessageReply reply) { @@ -66,12 +83,13 @@ public void run(MessageReply reply) { })).run(new WhileDoneCompletion(chain) { @Override public void done(ErrorCodeList errorCodeList) { + List releasedNics = new ArrayList<>(); + List nicsToDelete = new ArrayList<>(); for (VmNicInventory nic : spec.getVmInventory().getVmNics()) { VmNicVO vo = dbf.findByUuid(nic.getUuid(), VmNicVO.class); if (VmInstanceConstant.USER_VM_TYPE.equals(spec.getVmInventory().getType())) { - VmInstanceDeletionPolicy deletionPolicy = getDeletionPolicy(spec, data); if (deletionPolicy == VmInstanceDeletionPolicy.Direct) { - dbf.remove(vo); + nicsToDelete.add(vo); } else { vo.setUsedIpUuid(null); vo.setIp(null); @@ -80,10 +98,92 @@ public void done(ErrorCodeList errorCodeList) { dbf.update(vo); } } else { - dbf.remove(vo); + nicsToDelete.add(vo); } + releasedNics.add(nic); + } + + Completion releaseDone = new Completion(chain) { + @Override + public void success() { + nicsToDelete.forEach(dbf::remove); + chain.next(); + } + + @Override + public void fail(ErrorCode errorCode) { + logger.warn(String.format("releaseSdnNics failed: %s, continue anyway", errorCode)); + nicsToDelete.forEach(dbf::remove); + chain.next(); + } + }; + + if (shouldReleaseSdnNicIps(deletionPolicy)) { + callReleaseSdnNicIps(releasedNics, releaseDone); + } else { + callReleaseSdnNics(releasedNics, releaseDone); + } + } + }); + } + + private boolean shouldReleaseSdnNicIps(VmInstanceDeletionPolicy deletionPolicy) { + return deletionPolicy == VmInstanceDeletionPolicy.Delay + || deletionPolicy == VmInstanceDeletionPolicy.Never; + } + + private void callReleaseSdnNicIps(List nics, Completion completion) { + List exts = pluginRgty.getExtensionList(AfterAllocateSdnNicExtensionPoint.class); + if (exts.isEmpty() || nics.isEmpty()) { + completion.success(); + return; + } + + new While<>(exts).each((ext, wcomp) -> { + ext.releaseNicIps(nics, new Completion(wcomp) { + @Override + public void success() { + wcomp.done(); + } + + @Override + public void fail(ErrorCode errorCode) { + logger.warn(String.format("releaseNicIps extension failed: %s, continue", errorCode)); + wcomp.done(); } - chain.next(); + }); + }).run(new WhileDoneCompletion(completion) { + @Override + public void done(ErrorCodeList errorCodeList) { + completion.success(); + } + }); + } + + private void callReleaseSdnNics(List nics, Completion completion) { + List exts = pluginRgty.getExtensionList(AfterAllocateSdnNicExtensionPoint.class); + if (exts.isEmpty() || nics.isEmpty()) { + completion.success(); + return; + } + + new While<>(exts).each((ext, wcomp) -> { + ext.releaseSdnNics(nics, new Completion(wcomp) { + @Override + public void success() { + wcomp.done(); + } + + @Override + public void fail(ErrorCode errorCode) { + logger.warn(String.format("releaseSdnNics extension failed: %s, continue", errorCode)); + wcomp.done(); + } + }); + }).run(new WhileDoneCompletion(completion) { + @Override + public void done(ErrorCodeList errorCodeList) { + completion.success(); } }); } diff --git a/compute/src/main/java/org/zstack/compute/vm/VmStartOnHypervisorFlow.java b/compute/src/main/java/org/zstack/compute/vm/VmStartOnHypervisorFlow.java index 20965f61655..bf44adeb836 100755 --- a/compute/src/main/java/org/zstack/compute/vm/VmStartOnHypervisorFlow.java +++ b/compute/src/main/java/org/zstack/compute/vm/VmStartOnHypervisorFlow.java @@ -5,17 +5,26 @@ import org.springframework.beans.factory.annotation.Configurable; import org.zstack.core.cloudbus.CloudBus; import org.zstack.core.cloudbus.CloudBusCallBack; +import org.zstack.core.asyncbatch.While; import org.zstack.core.componentloader.PluginRegistry; +import org.zstack.core.workflow.FlowChainBuilder; +import org.zstack.header.core.Completion; +import org.zstack.header.core.WhileDoneCompletion; import org.zstack.header.core.workflow.Flow; +import org.zstack.header.core.workflow.FlowChain; +import org.zstack.header.core.workflow.FlowDoneHandler; +import org.zstack.header.core.workflow.FlowErrorHandler; import org.zstack.header.core.workflow.FlowRollback; import org.zstack.header.core.workflow.FlowTrigger; +import org.zstack.header.core.workflow.NoRollbackFlow; +import org.zstack.header.errorcode.ErrorCode; +import org.zstack.header.errorcode.ErrorCodeList; import org.zstack.header.host.HostConstant; import org.zstack.header.message.MessageReply; import org.zstack.header.vm.*; import org.zstack.utils.Utils; import org.zstack.utils.logging.CLogger; -import java.util.List; import java.util.Map; @Configurable(preConstruction = true, autowire = Autowire.BY_TYPE) public class VmStartOnHypervisorFlow implements Flow { @@ -26,34 +35,68 @@ public class VmStartOnHypervisorFlow implements Flow { @Autowired private PluginRegistry pluginRgty; - private final List exts = pluginRgty.getExtensionList(VmBeforeStartOnHypervisorExtensionPoint.class);; - - private void fireExtensions(VmInstanceSpec spec) { - for (VmBeforeStartOnHypervisorExtensionPoint ext : exts) { - ext.beforeStartVmOnHypervisor(spec); - } - } - @Override public void run(final FlowTrigger chain, final Map data) { final VmInstanceSpec spec = (VmInstanceSpec) data.get(VmInstanceConstant.Params.VmInstanceSpec.toString()); + FlowChain fchain = FlowChainBuilder.newSimpleFlowChain(); + fchain.setName(String.format("vm-start-on-hypervisor-vm-%s", spec.getVmInventory().getUuid())); + fchain.then(new NoRollbackFlow() { + @Override + public void run(FlowTrigger trigger, Map d) { + new While<>(pluginRgty.getExtensionList(VmBeforeStartOnHypervisorExtensionPoint.class)) + .each((ext, comp) -> ext.beforeStartVmOnHypervisor(spec, new Completion(comp) { + @Override + public void success() { + comp.done(); + } - fireExtensions(spec); - - StartVmOnHypervisorMsg msg = new StartVmOnHypervisorMsg(); - msg.setVmSpec(spec); - bus.makeTargetServiceIdByResourceUuid(msg, HostConstant.SERVICE_ID, spec.getDestHost().getUuid()); - bus.send(msg, new CloudBusCallBack(chain) { + @Override + public void fail(ErrorCode errorCode) { + comp.addError(errorCode); + comp.done(); + } + })).run(new WhileDoneCompletion(trigger) { + @Override + public void done(ErrorCodeList errorCodeList) { + if (errorCodeList.getCauses().size() > 0) { + trigger.fail(errorCodeList.getCauses().get(0)); + } else { + trigger.next(); + } + } + }); + } + }); + fchain.then(new NoRollbackFlow() { @Override - public void run(MessageReply reply) { - if (reply.isSuccess()) { - data.put(VmStartOnHypervisorFlow.class.getName(), true); - chain.next(); - } else { - chain.fail(reply.getError()); - } + public void run(FlowTrigger trigger, Map d) { + StartVmOnHypervisorMsg msg = new StartVmOnHypervisorMsg(); + msg.setVmSpec(spec); + bus.makeTargetServiceIdByResourceUuid(msg, HostConstant.SERVICE_ID, spec.getDestHost().getUuid()); + bus.send(msg, new CloudBusCallBack(trigger) { + @Override + public void run(MessageReply reply) { + if (reply.isSuccess()) { + data.put(VmStartOnHypervisorFlow.class.getName(), true); + trigger.next(); + } else { + trigger.fail(reply.getError()); + } + } + }); } }); + fchain.done(new FlowDoneHandler(chain) { + @Override + public void handle(Map d) { + chain.next(); + } + }).error(new FlowErrorHandler(chain) { + @Override + public void handle(ErrorCode errCode, Map d) { + chain.fail(errCode); + } + }).start(); } @Override diff --git a/compute/src/main/java/org/zstack/compute/vm/VmSystemTags.java b/compute/src/main/java/org/zstack/compute/vm/VmSystemTags.java index df0c9fdd9e8..606462ac9ba 100755 --- a/compute/src/main/java/org/zstack/compute/vm/VmSystemTags.java +++ b/compute/src/main/java/org/zstack/compute/vm/VmSystemTags.java @@ -5,6 +5,7 @@ import org.zstack.header.tag.AdminOnlyTag; import org.zstack.header.tag.TagDefinition; import org.zstack.header.vm.VmInstanceVO; +import org.zstack.header.vm.VmNicVO; import org.zstack.tag.PatternedSystemTag; import org.zstack.tag.SensitiveTagOutputHandler; import org.zstack.tag.SensitiveTag; @@ -318,5 +319,20 @@ public String desensitizeTag(SystemTag systemTag, String tag) { public static PatternedSystemTag VM_STATE_PAUSED_AFTER_MIGRATE = new PatternedSystemTag(("vmPausedAfterMigrate"), VmInstanceVO.class); + public static String HA_PRE_FENCE_SUSPECT_HOST_UUID_TOKEN = "suspectHostUuid"; + public static String HA_PRE_FENCE_ACCESSIBLE_PEER_HOST_UUID_TOKEN = "accessiblePeerHostUuid"; + public static PatternedSystemTag HA_PRE_FENCE_PENDING = + new PatternedSystemTag(String.format("haPreFencePending::{%s}::{%s}", + HA_PRE_FENCE_SUSPECT_HOST_UUID_TOKEN, + HA_PRE_FENCE_ACCESSIBLE_PEER_HOST_UUID_TOKEN), VmInstanceVO.class); + public static PatternedSystemTag VM_MEMORY_ACCESS_MODE_SHARED = new PatternedSystemTag(("vmMemoryAccessModeShared"), VmInstanceVO.class); + + public static String ZNS_NIC_MODE_TOKEN = "znsNicMode"; + public static PatternedSystemTag ZNS_NIC_MODE = new PatternedSystemTag( + String.format("%s::{%s}", ZNS_NIC_MODE_TOKEN, ZNS_NIC_MODE_TOKEN), VmInstanceVO.class); + + public static String IFACE_ID_TOKEN = "ifaceId"; + public static PatternedSystemTag IFACE_ID = new PatternedSystemTag( + String.format("ifaceId::{%s}", IFACE_ID_TOKEN), VmNicVO.class); } diff --git a/conf/db/upgrade/V5.5.22__schema.sql b/conf/db/upgrade/V5.5.22__schema.sql index 94b14f06535..49f2c5f86ca 100644 --- a/conf/db/upgrade/V5.5.22__schema.sql +++ b/conf/db/upgrade/V5.5.22__schema.sql @@ -1,6 +1,9 @@ -- ZSTAC-84025: Add pipelineTag to ModelVO for inference template auto-matching CALL ADD_COLUMN('ModelVO', 'pipelineTag', 'VARCHAR(64)', 1, NULL); +-- ZSTAC-84246: Persist virtiofs restore success epoch for VmModelMountVO. +CALL ADD_COLUMN('VmModelMountVO', 'lastAttachedEpoch', 'BIGINT', 1, NULL); + -- ZSTAC-84025: Add isDefault to ModelServiceRefVO to mark the default inference template per model ALTER TABLE `zstack`.`ModelServiceRefVO` ADD COLUMN `isDefault` TINYINT(1) NOT NULL DEFAULT 0; @@ -29,3 +32,211 @@ DROP PROCEDURE IF EXISTS backfill_model_service_ref_create_date; -- in DEFAULT or ON UPDATE. lastOpDate already uses it, so keep createDate non-zero -- and let ModelServiceRefVO.@PrePersist populate the real creation time for new rows. ALTER TABLE `zstack`.`ModelServiceRefVO` MODIFY COLUMN `createDate` TIMESTAMP NOT NULL DEFAULT '2000-01-01 00:00:00'; + +CREATE TABLE IF NOT EXISTS `zstack`.`HaNetworkGroupVO` ( + `uuid` VARCHAR(32) NOT NULL UNIQUE COMMENT 'uuid', + `name` VARCHAR(255) NOT NULL, + `description` VARCHAR(2048) DEFAULT NULL, + `type` VARCHAR(128) NOT NULL, + `minAvailableCount` INT(10) NOT NULL DEFAULT 1, + `state` VARCHAR(32) NOT NULL DEFAULT 'Enabled', + `lastOpDate` TIMESTAMP NOT NULL DEFAULT '2000-01-01 00:00:00' ON UPDATE CURRENT_TIMESTAMP, + `createDate` TIMESTAMP NOT NULL DEFAULT '2000-01-01 00:00:00', + PRIMARY KEY (`uuid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE IF NOT EXISTS `zstack`.`HaNetworkGroupL3NetworkRefVO` ( + `uuid` VARCHAR(32) NOT NULL UNIQUE COMMENT 'uuid', + `haNetworkGroupUuid` VARCHAR(32) NOT NULL, + `l3NetworkUuid` VARCHAR(32) NOT NULL, + `lastOpDate` TIMESTAMP NOT NULL DEFAULT '2000-01-01 00:00:00' ON UPDATE CURRENT_TIMESTAMP, + `createDate` TIMESTAMP NOT NULL DEFAULT '2000-01-01 00:00:00', + PRIMARY KEY (`uuid`), + INDEX `idxHaNetworkGroupL3NetworkRefVOhaNetworkGroupUuid` (`haNetworkGroupUuid`), + UNIQUE INDEX `ukHaNetworkGroupL3NetworkRefVOl3NetworkUuid` (`l3NetworkUuid`), + CONSTRAINT `fkHaNetworkGroupL3NetworkRefVOHaNetworkGroupVO` FOREIGN KEY (`haNetworkGroupUuid`) REFERENCES `zstack`.`HaNetworkGroupVO` (`uuid`) ON DELETE CASCADE, + CONSTRAINT `fkHaNetworkGroupL3NetworkRefVOL3NetworkEO` FOREIGN KEY (`l3NetworkUuid`) REFERENCES `zstack`.`L3NetworkEO` (`uuid`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE IF NOT EXISTS `zstack`.`HostHaNetworkGroupStatusVO` ( + `uuid` VARCHAR(32) NOT NULL UNIQUE COMMENT 'uuid', + `hostUuid` VARCHAR(32) NOT NULL, + `networkGroupUuid` VARCHAR(32) NOT NULL, + `status` VARCHAR(32) NOT NULL DEFAULT 'Unknown', + `lastOpDate` TIMESTAMP NOT NULL DEFAULT '2000-01-01 00:00:00' ON UPDATE CURRENT_TIMESTAMP, + `createDate` TIMESTAMP NOT NULL DEFAULT '2000-01-01 00:00:00', + PRIMARY KEY (`uuid`), + UNIQUE INDEX `ukHostHaNetworkGroupStatusVOHostUuidNetworkGroupUuid` (`hostUuid`, `networkGroupUuid`), + INDEX `idxHostHaNetworkGroupStatusVOhostUuid` (`hostUuid`), + INDEX `idxHostHaNetworkGroupStatusVOnetworkGroupUuid` (`networkGroupUuid`), + CONSTRAINT `fkHostHaNetworkGroupStatusVOHostEO` FOREIGN KEY (`hostUuid`) REFERENCES `zstack`.`HostEO` (`uuid`) ON DELETE CASCADE, + CONSTRAINT `fkHostHaNetworkGroupStatusVOHaNetworkGroupVO` FOREIGN KEY (`networkGroupUuid`) REFERENCES `zstack`.`HaNetworkGroupVO` (`uuid`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE IF NOT EXISTS `zstack`.`HaNetworkGroupGlobalConfigVersionVO` ( + `name` VARCHAR(64) NOT NULL, + `version` BIGINT UNSIGNED NOT NULL DEFAULT 0, + PRIMARY KEY (`name`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +INSERT IGNORE INTO `zstack`.`HaNetworkGroupGlobalConfigVersionVO` (`name`, `version`) +VALUES ('ha-network-group', 0); + +-- ZNS SDN Controller support + +CREATE TABLE IF NOT EXISTS `ZnsControllerVO` ( + `uuid` varchar(32) NOT NULL, + PRIMARY KEY (`uuid`), + CONSTRAINT `fkZnsControllerVOSdnControllerVO` FOREIGN KEY (`uuid`) REFERENCES `SdnControllerVO` (`uuid`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE IF NOT EXISTS `L2GeneveNetworkVO` ( + `uuid` varchar(32) NOT NULL, + `geneveId` int(10) unsigned NOT NULL, + PRIMARY KEY (`uuid`), + CONSTRAINT `fkL2GeneveNetworkVOL2NetworkEO` FOREIGN KEY (`uuid`) REFERENCES `L2NetworkEO` (`uuid`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE IF NOT EXISTS `ZnsTransportZoneVO` ( + `uuid` varchar(32) NOT NULL, + `znsResourceUuid` varchar(64) NOT NULL, + `name` varchar(255) DEFAULT NULL, + `description` text DEFAULT NULL, + `type` varchar(64) DEFAULT NULL, + `physicalNetwork` varchar(255) DEFAULT NULL, + `status` varchar(64) DEFAULT NULL, + `isDefault` tinyint(1) NOT NULL DEFAULT 0, + `tags` text DEFAULT NULL, + `znsSdnControllerUuid` varchar(32) NOT NULL, + `createDate` timestamp NOT NULL DEFAULT '2000-01-01 00:00:00', + `lastOpDate` timestamp NOT NULL DEFAULT '2000-01-01 00:00:00' ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`uuid`), + UNIQUE KEY `uk_zns_tz_resource` (`znsSdnControllerUuid`, `znsResourceUuid`), + CONSTRAINT `fkZnsTransportZoneVOSdnControllerVO` FOREIGN KEY (`znsSdnControllerUuid`) REFERENCES `SdnControllerVO` (`uuid`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + + +-- ZNS Wave 2: Tenant/TenantRouter resource modeling (ZCF-2133) + +CREATE TABLE IF NOT EXISTS `ZnsTenantVO` ( + `uuid` VARCHAR(32) NOT NULL, + `sdnControllerUuid` VARCHAR(32) NOT NULL, + `znsResourceUuid` VARCHAR(64) NOT NULL, + `name` VARCHAR(255) NOT NULL, + `description` TEXT DEFAULT NULL, + `lastOpDate` timestamp NOT NULL DEFAULT '2000-01-01 00:00:00' ON UPDATE CURRENT_TIMESTAMP, + `createDate` timestamp NOT NULL DEFAULT '2000-01-01 00:00:00', + PRIMARY KEY (`uuid`), + UNIQUE KEY `uk_zns_tenant_resource` (`sdnControllerUuid`, `znsResourceUuid`), + CONSTRAINT `fk_zns_tenant_sdn` FOREIGN KEY (`sdnControllerUuid`) REFERENCES `SdnControllerVO` (`uuid`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE IF NOT EXISTS `ZnsTenantRouterVO` ( + `uuid` VARCHAR(32) NOT NULL, + `sdnControllerUuid` VARCHAR(32) NOT NULL, + `tenantUuid` VARCHAR(32) DEFAULT NULL, + `znsResourceUuid` VARCHAR(64) NOT NULL, + `name` VARCHAR(255) NOT NULL, + `description` TEXT DEFAULT NULL, + `state` VARCHAR(32) DEFAULT NULL COMMENT 'Active / Inactive', + `lastOpDate` timestamp NOT NULL DEFAULT '2000-01-01 00:00:00' ON UPDATE CURRENT_TIMESTAMP, + `createDate` timestamp NOT NULL DEFAULT '2000-01-01 00:00:00', + PRIMARY KEY (`uuid`), + UNIQUE KEY `uk_zns_tr_resource` (`sdnControllerUuid`, `znsResourceUuid`), + KEY `idx_zns_tr_tenant` (`tenantUuid`), + CONSTRAINT `fk_zns_tr_tenant` FOREIGN KEY (`tenantUuid`) REFERENCES `ZnsTenantVO` (`uuid`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CALL ADD_COLUMN('ModelServiceVO', 'hasNewVersion', 'tinyint(1)', 1, NULL); +CALL ADD_COLUMN('ModelCenterCapacityVO', 'availableCapacity', 'bigint', 0, '0'); +CALL ADD_COLUMN('ModelCenterCapacityVO', 'totalCapacity', 'bigint', 0, '0'); +UPDATE `zstack`.`ModelCenterCapacityVO` SET `availableCapacity` = 0 WHERE `availableCapacity` IS NULL; +UPDATE `zstack`.`ModelCenterCapacityVO` SET `totalCapacity` = 0 WHERE `totalCapacity` IS NULL; +ALTER TABLE `zstack`.`ModelCenterCapacityVO` MODIFY COLUMN `availableCapacity` bigint NOT NULL DEFAULT 0; +ALTER TABLE `zstack`.`ModelCenterCapacityVO` MODIFY COLUMN `totalCapacity` bigint NOT NULL DEFAULT 0; + +CREATE TABLE IF NOT EXISTS `zstack`.`CdnModelServiceTemplateVO` ( + `uuid` varchar(32) NOT NULL, + `name` varchar(255) NOT NULL, + `version` varchar(255) DEFAULT NULL, + `platform` varchar(255) DEFAULT NULL, + `framework` varchar(255) DEFAULT NULL, + `gpuVendor` varchar(255) DEFAULT NULL, + `size` bigint DEFAULT NULL, + `projectId` varchar(255) DEFAULT NULL, + `projectName` varchar(255) DEFAULT NULL, + `downloadUrl` varchar(2048) DEFAULT NULL, + `installed` tinyint(1) NOT NULL DEFAULT 0, + `modelServiceUuid` varchar(32) DEFAULT NULL, + `usingServiceCount` bigint NOT NULL DEFAULT 0, + `createDate` timestamp NOT NULL DEFAULT '2000-01-01 00:00:00', + `lastOpDate` timestamp ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`uuid`), + UNIQUE KEY `ukCdnModelServiceTemplateVOName` (`name`), + KEY `idxCdnModelServiceTemplateVOModelServiceUuid` (`modelServiceUuid`), + CONSTRAINT `fkCdnModelServiceTemplateVOModelServiceVO` FOREIGN KEY (`modelServiceUuid`) + REFERENCES `zstack`.`ModelServiceVO` (`uuid`) ON DELETE SET NULL +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +CALL ADD_COLUMN('CdnModelServiceTemplateVO', 'framework', 'varchar(255)', 1, NULL); +CALL ADD_COLUMN('CdnModelServiceTemplateVO', 'gpuVendor', 'varchar(255)', 1, NULL); + +-- dGPU billing support tables + +CREATE TABLE IF NOT EXISTS `zstack`.`PriceDGpuGpuSpecRefVO` ( + `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, + `priceUuid` VARCHAR(32) NOT NULL, + `gpuSpecUuid` VARCHAR(32) NOT NULL, + `createDate` TIMESTAMP NULL DEFAULT NULL, + `lastOpDate` TIMESTAMP NULL DEFAULT NULL, + PRIMARY KEY (`id`), + CONSTRAINT `fk_price_dgpu_spec_price` + FOREIGN KEY (`priceUuid`) REFERENCES `zstack`.`PriceVO`(`uuid`) ON DELETE CASCADE, + CONSTRAINT `fk_price_dgpu_spec_gpu_spec` + FOREIGN KEY (`gpuSpecUuid`) REFERENCES `zstack`.`GpuDeviceSpecVO`(`uuid`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE IF NOT EXISTS `zstack`.`DGpuUsageVO` ( + `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, + `dgpuDeviceUuid` VARCHAR(32) NOT NULL, + `gpuSpecUuid` VARCHAR(32) NOT NULL, + `allocatedMemory` BIGINT UNSIGNED NOT NULL, + `dgpuName` VARCHAR(255) DEFAULT NULL, + `vmUuid` VARCHAR(32) DEFAULT NULL, + `vmName` VARCHAR(255) DEFAULT NULL, + `status` VARCHAR(64) NOT NULL, + `accountUuid` VARCHAR(32) NOT NULL, + `dateInLong` BIGINT UNSIGNED NOT NULL, + `inventory` TEXT DEFAULT NULL, + `createDate` TIMESTAMP NULL DEFAULT NULL, + `lastOpDate` TIMESTAMP NULL DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `idx_dgpu_usage_account_date` (`accountUuid`, `dateInLong`), + KEY `idx_dgpu_usage_device` (`accountUuid`, `dateInLong`, `dgpuDeviceUuid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE IF NOT EXISTS `zstack`.`DGpuUsageHistoryVO` ( + `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, + `dgpuDeviceUuid` VARCHAR(32) NOT NULL, + `gpuSpecUuid` VARCHAR(32) NOT NULL, + `allocatedMemory` BIGINT UNSIGNED NOT NULL, + `dgpuName` VARCHAR(255) DEFAULT NULL, + `vmUuid` VARCHAR(32) DEFAULT NULL, + `vmName` VARCHAR(255) DEFAULT NULL, + `status` VARCHAR(64) NOT NULL, + `accountUuid` VARCHAR(32) NOT NULL, + `dateInLong` BIGINT UNSIGNED NOT NULL, + `inventory` TEXT DEFAULT NULL, + `createDate` TIMESTAMP NULL DEFAULT NULL, + `lastOpDate` TIMESTAMP NULL DEFAULT NULL, + PRIMARY KEY (`id`), + KEY `idx_dgpu_usage_history_account_date` (`accountUuid`, `dateInLong`), + KEY `idx_dgpu_usage_history_device` (`accountUuid`, `dateInLong`, `dgpuDeviceUuid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE IF NOT EXISTS `zstack`.`DGpuBillingVO` ( + `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT, + `vmName` VARCHAR(255) DEFAULT NULL, + `allocatedMemory` BIGINT UNSIGNED DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `id` (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; diff --git a/conf/db/upgrade/V5.5.28__schema.sql b/conf/db/upgrade/V5.5.28__schema.sql new file mode 100644 index 00000000000..6d129a749fe --- /dev/null +++ b/conf/db/upgrade/V5.5.28__schema.sql @@ -0,0 +1,236 @@ +-- ZSTAC-75429: scope AI ModelCenter-derived resources by zone. +CALL ADD_COLUMN('ModelVO', 'zoneUuid', 'VARCHAR(32)', 1, NULL); +CALL ADD_COLUMN('ModelServiceVO', 'zoneUuid', 'VARCHAR(32)', 1, NULL); +CALL ADD_COLUMN('DatasetVO', 'zoneUuid', 'VARCHAR(32)', 1, NULL); +CALL ADD_COLUMN('ModelServiceInstanceGroupVO', 'zoneUuid', 'VARCHAR(32)', 1, NULL); +CALL ADD_COLUMN('ModelServiceInstanceVO', 'launchCommand', 'MEDIUMTEXT', 1, NULL); +CALL ADD_COLUMN('ZdfsVO', 'metaServerPort', 'INT', 0, 6379); + +UPDATE `zstack`.`ModelCenterVO` mc +INNER JOIN ( + SELECT ms.`modelCenterUuid`, MIN(vm.`zoneUuid`) AS `zoneUuid`, COUNT(DISTINCT vm.`zoneUuid`) AS `zoneCount` + FROM `zstack`.`ModelServiceVO` ms + INNER JOIN `zstack`.`ModelServiceInstanceGroupVO` g ON g.`modelServiceUuid` = ms.`uuid` + INNER JOIN `zstack`.`ModelServiceInstanceVO` i ON i.`modelServiceGroupUuid` = g.`uuid` + INNER JOIN `zstack`.`VmInstanceVO` vm ON vm.`uuid` = i.`vmInstanceUuid` + WHERE vm.`zoneUuid` IS NOT NULL + AND ms.`modelCenterUuid` IS NOT NULL + GROUP BY ms.`modelCenterUuid` +) inferred ON inferred.`modelCenterUuid` = mc.`uuid` +SET mc.`zoneUuid` = inferred.`zoneUuid` +WHERE mc.`zoneUuid` IS NULL + AND inferred.`zoneCount` = 1; + +UPDATE `zstack`.`ModelVO` m +INNER JOIN `zstack`.`ModelCenterVO` mc ON m.`modelCenterUuid` = mc.`uuid` +SET m.`zoneUuid` = mc.`zoneUuid` +WHERE m.`zoneUuid` IS NULL; + +UPDATE `zstack`.`ModelServiceVO` ms +INNER JOIN `zstack`.`ModelCenterVO` mc ON ms.`modelCenterUuid` = mc.`uuid` +SET ms.`zoneUuid` = mc.`zoneUuid` +WHERE ms.`zoneUuid` IS NULL; + +UPDATE `zstack`.`DatasetVO` d +INNER JOIN `zstack`.`ModelCenterVO` mc ON d.`modelCenterUuid` = mc.`uuid` +SET d.`zoneUuid` = mc.`zoneUuid` +WHERE d.`zoneUuid` IS NULL; + +UPDATE `zstack`.`ModelServiceVO` ms +INNER JOIN ( + SELECT g.`modelServiceUuid`, MIN(vm.`zoneUuid`) AS `zoneUuid`, COUNT(DISTINCT vm.`zoneUuid`) AS `zoneCount` + FROM `zstack`.`ModelServiceInstanceGroupVO` g + INNER JOIN `zstack`.`ModelServiceInstanceVO` i ON i.`modelServiceGroupUuid` = g.`uuid` + INNER JOIN `zstack`.`VmInstanceVO` vm ON vm.`uuid` = i.`vmInstanceUuid` + WHERE vm.`zoneUuid` IS NOT NULL + AND g.`modelServiceUuid` IS NOT NULL + GROUP BY g.`modelServiceUuid` +) inferred ON inferred.`modelServiceUuid` = ms.`uuid` +SET ms.`zoneUuid` = inferred.`zoneUuid` +WHERE ms.`zoneUuid` IS NULL + AND inferred.`zoneCount` = 1; + +UPDATE `zstack`.`ModelVO` m +INNER JOIN ( + SELECT g.`modelUuid`, MIN(vm.`zoneUuid`) AS `zoneUuid`, COUNT(DISTINCT vm.`zoneUuid`) AS `zoneCount` + FROM `zstack`.`ModelServiceInstanceGroupVO` g + INNER JOIN `zstack`.`ModelServiceInstanceVO` i ON i.`modelServiceGroupUuid` = g.`uuid` + INNER JOIN `zstack`.`VmInstanceVO` vm ON vm.`uuid` = i.`vmInstanceUuid` + WHERE vm.`zoneUuid` IS NOT NULL + AND g.`modelUuid` IS NOT NULL + GROUP BY g.`modelUuid` +) inferred ON inferred.`modelUuid` = m.`uuid` +SET m.`zoneUuid` = inferred.`zoneUuid` +WHERE m.`zoneUuid` IS NULL + AND inferred.`zoneCount` = 1; + +UPDATE `zstack`.`ModelServiceInstanceGroupVO` g +LEFT JOIN `zstack`.`ModelServiceVO` ms ON g.`modelServiceUuid` = ms.`uuid` +LEFT JOIN `zstack`.`ModelVO` m ON g.`modelUuid` = m.`uuid` +SET g.`zoneUuid` = COALESCE(ms.`zoneUuid`, m.`zoneUuid`) +WHERE g.`zoneUuid` IS NULL; + +UPDATE `zstack`.`ModelServiceInstanceGroupVO` g +INNER JOIN ( + SELECT i.`modelServiceGroupUuid`, MIN(vm.`zoneUuid`) AS `zoneUuid`, COUNT(DISTINCT vm.`zoneUuid`) AS `zoneCount` + FROM `zstack`.`ModelServiceInstanceVO` i + INNER JOIN `zstack`.`VmInstanceVO` vm ON vm.`uuid` = i.`vmInstanceUuid` + WHERE vm.`zoneUuid` IS NOT NULL + GROUP BY i.`modelServiceGroupUuid` +) inferred ON inferred.`modelServiceGroupUuid` = g.`uuid` +SET g.`zoneUuid` = inferred.`zoneUuid` +WHERE g.`zoneUuid` IS NULL + AND inferred.`zoneCount` = 1; + +CALL ADD_CONSTRAINT('ModelVO', 'fkModelVOZoneVO', 'zoneUuid', 'ZoneEO', 'uuid', 'RESTRICT'); +CALL ADD_CONSTRAINT('ModelServiceVO', 'fkModelServiceVOZoneVO', 'zoneUuid', 'ZoneEO', 'uuid', 'RESTRICT'); +CALL ADD_CONSTRAINT('DatasetVO', 'fkDatasetVOZoneVO', 'zoneUuid', 'ZoneEO', 'uuid', 'RESTRICT'); +CALL ADD_CONSTRAINT('ModelServiceInstanceGroupVO', 'fkModelServiceInstanceGroupVOZoneVO', 'zoneUuid', 'ZoneEO', 'uuid', 'RESTRICT'); + +-- ZSTAC-84111: Persist Zaku health state on NativeClusterVO for query and manual recovery. +CALL ADD_COLUMN('NativeClusterVO', 'zakuHealthStatus', 'VARCHAR(32)', 1, 'Unknown'); +UPDATE `zstack`.`NativeClusterVO` SET `zakuHealthStatus` = 'Unknown' WHERE `zakuHealthStatus` IS NULL; + +-- ZSTAC-82189: distinguish AI inference image variants beyond CPU architecture. +CALL ADD_COLUMN('ModelServiceTemplateVO', 'name', 'VARCHAR(255)', 1, NULL); +CALL ADD_COLUMN('ModelServiceTemplateVO', 'acceleratorType', 'VARCHAR(255)', 1, NULL); +CALL ADD_COLUMN('ModelServiceTemplateVO', 'imageNamePattern', 'VARCHAR(2048)', 1, NULL); +CALL CREATE_INDEX('ModelServiceTemplateVO', 'idxModelServiceTemplateModelServiceUuid', 'modelServiceUuid'); +CALL DELETE_INDEX('ModelServiceTemplateVO', 'ukModelServiceCpuArch'); + +-- Host Model Cache control-plane state for VM/cloud-host model service deployments. +CREATE TABLE IF NOT EXISTS `zstack`.`AiHostModelCacheVO` ( + `uuid` VARCHAR(32) NOT NULL, + `hostUuid` VARCHAR(32) NOT NULL, + `modelCenterUuid` VARCHAR(32) DEFAULT NULL, + `modelUuid` VARCHAR(32) DEFAULT NULL, + `sourceRoot` VARCHAR(2048) DEFAULT NULL, + `sourcePath` VARCHAR(2048) DEFAULT NULL, + `sizeBytes` BIGINT DEFAULT NULL, + `sourceMtime` BIGINT DEFAULT NULL, + `checksum` VARCHAR(255) DEFAULT NULL, + `contentVersion` VARCHAR(255) DEFAULT NULL, + `identityHash` VARCHAR(255) NOT NULL, + `status` VARCHAR(32) NOT NULL, + `desiredRefCount` BIGINT NOT NULL DEFAULT 0, + `runningRefCount` BIGINT NOT NULL DEFAULT 0, + `reservationUuid` VARCHAR(32) DEFAULT NULL, + `waiterCount` INT DEFAULT NULL, + `lastAccessDate` TIMESTAMP NULL DEFAULT NULL, + `lastSyncDate` TIMESTAMP NULL DEFAULT NULL, + `failurePhase` VARCHAR(64) DEFAULT NULL, + `failureCode` VARCHAR(64) DEFAULT NULL, + `failureMessage` MEDIUMTEXT DEFAULT NULL, + `createDate` TIMESTAMP NOT NULL DEFAULT '2000-01-01 00:00:00', + `lastOpDate` TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`uuid`), + UNIQUE KEY `ukAiHostModelCacheVOHostIdentity` (`hostUuid`, `identityHash`), + KEY `idxAiHostModelCacheVOHostRoot` (`hostUuid`, `sourceRoot`(255)), + KEY `idxAiHostModelCacheVOModel` (`modelUuid`), + KEY `idxAiHostModelCacheVOStatus` (`status`), + CONSTRAINT `fkAiHostModelCacheVOHostEO` + FOREIGN KEY (`hostUuid`) REFERENCES `zstack`.`HostEO` (`uuid`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE IF NOT EXISTS `zstack`.`AiHostCacheStorageVO` ( + `uuid` VARCHAR(32) NOT NULL, + `hostUuid` VARCHAR(32) NOT NULL, + `sourceRoot` VARCHAR(2048) NOT NULL, + `sourceRootIdentity` VARCHAR(64) NOT NULL, + `physicalTotalBytes` BIGINT DEFAULT NULL, + `physicalAvailableBytes` BIGINT DEFAULT NULL, + `policyUsedBytes` BIGINT DEFAULT NULL, + `unmanagedUsedBytesEstimate` BIGINT DEFAULT NULL, + `policyReservedBytes` BIGINT DEFAULT NULL, + `policyMaxSizeBytes` BIGINT DEFAULT NULL, + `effectiveAvailableBytes` BIGINT DEFAULT NULL, + `highWatermarkBytes` BIGINT DEFAULT NULL, + `lowWatermarkBytes` BIGINT DEFAULT NULL, + `status` VARCHAR(32) DEFAULT NULL, + `statusReason` VARCHAR(1024) DEFAULT NULL, + `lastSyncDate` TIMESTAMP NULL DEFAULT NULL, + `createDate` TIMESTAMP NOT NULL DEFAULT '2000-01-01 00:00:00', + `lastOpDate` TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`uuid`), + UNIQUE KEY `ukAiHostCacheStorageVOHostRootIdentity` (`hostUuid`, `sourceRootIdentity`), + KEY `idxAiHostCacheStorageVOStatus` (`status`), + CONSTRAINT `fkAiHostCacheStorageVOHostEO` + FOREIGN KEY (`hostUuid`) REFERENCES `zstack`.`HostEO` (`uuid`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CALL ADD_COLUMN('AiHostCacheStorageVO', 'sourceRootIdentity', 'VARCHAR(64)', 1, NULL); +UPDATE `zstack`.`AiHostCacheStorageVO` +SET `sourceRootIdentity` = SHA2(IFNULL(`sourceRoot`, ''), 256) +WHERE `sourceRootIdentity` IS NULL OR `sourceRootIdentity` = ''; +ALTER TABLE `zstack`.`AiHostCacheStorageVO` MODIFY COLUMN `sourceRootIdentity` VARCHAR(64) NOT NULL; +SET @index_exists = (SELECT COUNT(*) FROM information_schema.statistics + WHERE table_schema = 'zstack' + AND table_name = 'AiHostCacheStorageVO' + AND index_name = 'ukAiHostCacheStorageVOHostRootIdentity'); +SET @sql = IF(@index_exists = 0, + 'ALTER TABLE `zstack`.`AiHostCacheStorageVO` ADD UNIQUE KEY `ukAiHostCacheStorageVOHostRootIdentity` (`hostUuid`, `sourceRootIdentity`)', + 'SELECT 1'); +PREPARE stmt FROM @sql; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; +CALL DELETE_INDEX('AiHostCacheStorageVO', 'ukAiHostCacheStorageVOHostRoot'); + +CREATE TABLE IF NOT EXISTS `zstack`.`AiHostModelCachePolicyVO` ( + `uuid` VARCHAR(32) NOT NULL, + `hostUuid` VARCHAR(32) NOT NULL, + `sourceRoot` VARCHAR(2048) NOT NULL, + `sourceRootIdentity` VARCHAR(64) NOT NULL, + `enabled` TINYINT(1) DEFAULT NULL, + `maxSizeBytes` BIGINT DEFAULT NULL, + `highWatermarkPercent` INT DEFAULT NULL, + `lowWatermarkPercent` INT DEFAULT NULL, + `disabledReason` VARCHAR(1024) DEFAULT NULL, + `createDate` TIMESTAMP NOT NULL DEFAULT '2000-01-01 00:00:00', + `lastOpDate` TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`uuid`), + UNIQUE KEY `ukAiHostModelCachePolicyVOHostRootIdentity` (`hostUuid`, `sourceRootIdentity`), + CONSTRAINT `fkAiHostModelCachePolicyVOHostEO` + FOREIGN KEY (`hostUuid`) REFERENCES `zstack`.`HostEO` (`uuid`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CALL ADD_COLUMN('AiHostModelCachePolicyVO', 'sourceRootIdentity', 'VARCHAR(64)', 1, NULL); +UPDATE `zstack`.`AiHostModelCachePolicyVO` +SET `sourceRootIdentity` = SHA2(IFNULL(`sourceRoot`, ''), 256) +WHERE `sourceRootIdentity` IS NULL OR `sourceRootIdentity` = ''; +ALTER TABLE `zstack`.`AiHostModelCachePolicyVO` MODIFY COLUMN `sourceRootIdentity` VARCHAR(64) NOT NULL; +CALL DELETE_INDEX('AiHostModelCachePolicyVO', 'ukAiHostModelCachePolicyVOHostRoot'); +SET @index_exists = (SELECT COUNT(*) FROM information_schema.statistics + WHERE table_schema = 'zstack' + AND table_name = 'AiHostModelCachePolicyVO' + AND index_name = 'ukAiHostModelCachePolicyVOHostRootIdentity'); +SET @sql = IF(@index_exists = 0, + 'ALTER TABLE `zstack`.`AiHostModelCachePolicyVO` ADD UNIQUE KEY `ukAiHostModelCachePolicyVOHostRootIdentity` (`hostUuid`, `sourceRootIdentity`)', + 'SELECT 1'); +PREPARE stmt FROM @sql; +EXECUTE stmt; +DEALLOCATE PREPARE stmt; + +CREATE TABLE IF NOT EXISTS `zstack`.`AiHostModelCacheReservationVO` ( + `uuid` VARCHAR(32) NOT NULL, + `hostUuid` VARCHAR(32) NOT NULL, + `sourceRoot` VARCHAR(2048) DEFAULT NULL, + `modelUuid` VARCHAR(32) DEFAULT NULL, + `modelCenterUuid` VARCHAR(32) DEFAULT NULL, + `ownerType` VARCHAR(32) NOT NULL, + `ownerResourceUuid` VARCHAR(32) NOT NULL, + `reservedBytes` BIGINT NOT NULL, + `status` VARCHAR(32) NOT NULL, + `expiredDate` TIMESTAMP NULL DEFAULT NULL, + `createDate` TIMESTAMP NOT NULL DEFAULT '2000-01-01 00:00:00', + `lastOpDate` TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`uuid`), + KEY `idxAiHostModelCacheReservationVOHostRoot` (`hostUuid`, `sourceRoot`(255)), + KEY `idxAiHostModelCacheReservationVOOwner` (`ownerType`, `ownerResourceUuid`), + KEY `idxAiHostModelCacheReservationVOStatus` (`status`), + CONSTRAINT `fkAiHostModelCacheReservationVOHostEO` + FOREIGN KEY (`hostUuid`) REFERENCES `zstack`.`HostEO` (`uuid`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CALL ADD_COLUMN('VmModelMountVO', 'cacheUuid', 'VARCHAR(32)', 1, NULL); +CALL CREATE_INDEX('VmModelMountVO', 'idxVmModelMountVOCacheUuid', 'cacheUuid'); +CALL ADD_CONSTRAINT('VmModelMountVO', 'fkVmModelMountVOAiHostModelCacheVO', 'cacheUuid', 'AiHostModelCacheVO', 'uuid', 'SET NULL'); diff --git a/conf/globalConfig/vmNicLifecycle.xml b/conf/globalConfig/vmNicLifecycle.xml new file mode 100644 index 00000000000..7e2e9c927db --- /dev/null +++ b/conf/globalConfig/vmNicLifecycle.xml @@ -0,0 +1,10 @@ + + + + reconcileOnHost.timeout + Timeout in seconds for each VmNicLifecycleExtensionPoint implementation's reconcileOnHost call during host heartbeat reconciliation + vmNicLifecycle + 30 + java.lang.Long + + diff --git a/conf/i18n/globalErrorCodeMapping/global-error-en_US.json b/conf/i18n/globalErrorCodeMapping/global-error-en_US.json index df3c4c42bdf..5c54d1fd80f 100644 --- a/conf/i18n/globalErrorCodeMapping/global-error-en_US.json +++ b/conf/i18n/globalErrorCodeMapping/global-error-en_US.json @@ -4178,6 +4178,7 @@ "ORG_ZSTACK_POLICYROUTE_10013": "operation failure, IP format only supports IPv4/IP range/CIDR, but found %s", "ORG_ZSTACK_POLICYROUTE_10010": "NextHopIp must be in IPv4 format but found [%s]", "ORG_ZSTACK_CORE_REST_10012": "unable to retrieve %s within %sms", + "ORG_ZSTACK_CORE_REST_10013": "kvmagent on host[uuid:%s] restarted at %s, pending HTTP call sent before %s aborted", "ORG_ZSTACK_QUERY_10021": "field[%s] is not a primitive of the inventory %s; you cannot specify it in the parameter \u0027fields\u0027; valid fields are %s", "ORG_ZSTACK_NETWORK_SERVICE_FLAT_10034": "DHCP server IP [%s] already exists within L3 network [%s]", "ORG_ZSTACK_QUERY_10020": "entity metadata class[%s] lacks field[%s]", @@ -4722,6 +4723,7 @@ "ORG_ZSTACK_DGPU_10010": "Available License not found, please apply addon license for product dGPU.", "ORG_ZSTACK_DGPU_10011": "Addon license for product dGPU has expired, please renew it.", "ORG_ZSTACK_DGPU_10012": "Insufficient dGPU GPU number licensed. Your license permits %d GPU, there are %d GPU used, shared: %d, need: %d.", + "ORG_ZSTACK_DGPU_10013": "dGPU AddOn License is available, but no GPU number quota is granted. Please update the dGPU AddOn License, or request dGPU GPU number capacity from License Server for the current node.", "ORG_ZSTACK_AI_10159": "Model service instance[UUID: %s] failed to start within %s seconds. Reason: %s", "ORG_ZSTACK_AI_10138": "Requested CPU count[%s] exceeds the CPU limit[%s]", "ORG_ZSTACK_AI_10139": "Requested memory size[%s] exceeds the memory limit[%s]", @@ -4734,5 +4736,11 @@ "ORG_ZSTACK_AI_10162": "VM[name:%s, uuid:%s] must be running to mount/unmount model. Current state: %s", "ORG_ZSTACK_AI_10163": "VM[name:%s, uuid:%s] is not running on any host", "ORG_ZSTACK_AI_10164": "Model[name:%s, uuid:%s] is not shared to the account that owns this VM (or to public). Mount requires the model to be accessible under the same sharing rules as the VM.", - "ORG_ZSTACK_AI_10165": "ModelCenter[uuid:%s] not found for Model[name:%s, uuid:%s]" + "ORG_ZSTACK_AI_10165": "ModelCenter[uuid:%s] not found for Model[name:%s, uuid:%s]", + "ORG_ZSTACK_NETWORK_ZNS_10043": "failed to allocate DHCPv4 server IP for ZNS L3[uuid:%s]", + "ORG_ZSTACK_NETWORK_ZNS_10044": "cannot enable DHCP: L3[uuid:%s] has no eligible IpRange (SLAAC excluded)", + "ORG_ZSTACK_NETWORK_ZNS_10045": "cannot enable DHCP: L3[uuid:%s] has no Cloud-reserved DHCPv4 server IP", + "ORG_ZSTACK_NETWORK_ZNS_10046": "DHCP service already exists on segment[uuid:%s] but GET returned empty", + "ORG_ZSTACK_NETWORK_ZNS_10047": "cannot update DHCP: L3[uuid:%s] has no Cloud-reserved DHCPv4 server IP", + "ORG_ZSTACK_NETWORK_ZNS_10048": "failed to allocate DHCPv4 server IP for ZNS L3[uuid:%s]" } diff --git a/conf/i18n/globalErrorCodeMapping/global-error-ja-JP.json b/conf/i18n/globalErrorCodeMapping/global-error-ja-JP.json index a1ede2a0151..7f8132b76de 100644 --- a/conf/i18n/globalErrorCodeMapping/global-error-ja-JP.json +++ b/conf/i18n/globalErrorCodeMapping/global-error-ja-JP.json @@ -2844,7 +2844,7 @@ "ORG_ZSTACK_AI_CONTAINER_10018": "デプロイメント%sにはインスタンス情報がありません", "ORG_ZSTACK_TAG2_10005": "タグUUIDs %sが無効です。タグタイプはシンプルタイプでなければなりません", "ORG_ZSTACK_AI_CONTAINER_10017": "デプロイメント%sは存在しません", - "ORG_ZSTACK_IDENTITY_10070": "アカウント[uuid: %s]のQuota[name: %s]が見つかりません", + "ORG_ZSTACK_IDENTITY_10070": "Quota[name: %s]がアカウント[uuid: %s]で見つかりません", "ORG_ZSTACK_TAG2_10002": "クラウドリソースメタデータのシンプルタグパターン形式を更新できません", "ORG_ZSTACK_TAG2_10003": "重複するリソース名が見つかりました。確認して解決してください。", "ORG_ZSTACK_SNS_PLATFORM_WECOM_10000": "WeComへのメッセージ送信に失敗しました。ステータス: %s、本文: %s", diff --git a/conf/i18n/globalErrorCodeMapping/global-error-ko-KR.json b/conf/i18n/globalErrorCodeMapping/global-error-ko-KR.json index 7ad24c14f1c..b8188ee11b5 100644 --- a/conf/i18n/globalErrorCodeMapping/global-error-ko-KR.json +++ b/conf/i18n/globalErrorCodeMapping/global-error-ko-KR.json @@ -2784,7 +2784,7 @@ "ORG_ZSTACK_AI_CONTAINER_10018": "배포 %s에 인스턴스 정보가 없습니다.", "ORG_ZSTACK_TAG2_10005": "잘못된 태그 UUID %s, 태그 유형은 단순 유형이어야 합니다.", "ORG_ZSTACK_AI_CONTAINER_10017": "배포 %s이(가) 존재하지 않습니다.", - "ORG_ZSTACK_IDENTITY_10070": "계정[uuid: %s]에 대한 Quota[name: %s]를 찾을 수 없습니다.", + "ORG_ZSTACK_IDENTITY_10070": "Quota[name: %s]를 계정[uuid: %s]에서 찾을 수 없습니다.", "ORG_ZSTACK_TAG2_10002": "클라우드 리소스 메타데이터의 단순 태그 패턴 형식을 업데이트할 수 없습니다.", "ORG_ZSTACK_TAG2_10003": "중복된 리소스 이름이 발견되었습니다. 확인하고 해결하세요.", "ORG_ZSTACK_SNS_PLATFORM_WECOM_10000": "WeCom으로 메시지를 보내지 못했습니다. 상태: %s, 본문: %s", diff --git a/conf/i18n/globalErrorCodeMapping/global-error-zh_CN.json b/conf/i18n/globalErrorCodeMapping/global-error-zh_CN.json index 1400aefd860..481cd268b83 100644 --- a/conf/i18n/globalErrorCodeMapping/global-error-zh_CN.json +++ b/conf/i18n/globalErrorCodeMapping/global-error-zh_CN.json @@ -2875,7 +2875,7 @@ "ORG_ZSTACK_AI_CONTAINER_10018": "部署 %s 没有副本信息", "ORG_ZSTACK_TAG2_10005": "非法标签UUIDs %s,标签类型必须是简单型,)", "ORG_ZSTACK_AI_CONTAINER_10017": "部署 %s 未找到", - "ORG_ZSTACK_IDENTITY_10070": "无法找到账号[uuid: %s]的配额[name: %s]", + "ORG_ZSTACK_IDENTITY_10070": "无法找到配额[name: %s],账号[uuid: %s]", "ORG_ZSTACK_TAG2_10002": "无法更新简单标签模式格式", "ORG_ZSTACK_TAG2_10003": "重复名称", "ORG_ZSTACK_SNS_PLATFORM_WECOM_10000": "失败向企业微信发送消息。状态:%s,正文:%s", @@ -4178,6 +4178,7 @@ "ORG_ZSTACK_POLICYROUTE_10013": "操作失败,IP格式仅支持ipv4/iprange/cidr,但发现%s", "ORG_ZSTACK_POLICYROUTE_10010": "下一跳IP必须是ipv4格式,但发现[%s]", "ORG_ZSTACK_CORE_REST_10012": "无法在 %sms 内回显 %s", + "ORG_ZSTACK_CORE_REST_10013": "物理机[uuid:%s]上的 kvmagent 于 %s 重启,丢弃发出于 %s 之前的待处理 HTTP 请求", "ORG_ZSTACK_QUERY_10021": "字段[%s]不是库存%s中的原始类型;你无法在参数\u0027fields\u0027中指定它;有效的字段是%s", "ORG_ZSTACK_NETWORK_SERVICE_FLAT_10034": "DHCP服务器IP [%s] 已存在于L3网络 [%s] 中", "ORG_ZSTACK_QUERY_10020": "实体元类[%s]不存在字段[%s]", @@ -4722,6 +4723,7 @@ "ORG_ZSTACK_DGPU_10010": "未找到可用的 dGPU AddOn License,请为 dGPU 产品申请并上传对应授权。", "ORG_ZSTACK_DGPU_10011": "dGPU 产品的 AddOn License 已过期,请及时续期。", "ORG_ZSTACK_DGPU_10012": "dGPU 授权 GPU 数量不足。License 允许 %d 个 GPU,当前已使用 %d 个,其他节点共享使用 %d 个,本次还需要 %d 个。", + "ORG_ZSTACK_DGPU_10013": "dGPU AddOn License 已存在,但未授予 GPU 数量授权。请更新 dGPU AddOn License,或从 License Server 为当前节点申请 dGPU GPU 数量授权。", "ORG_ZSTACK_AI_10138": "请求 CPU 数量[%s]超过 CPU 上限[%s]", "ORG_ZSTACK_AI_10139": "请求内存大小[%s]超过内存上限[%s]", "ORG_ZSTACK_AI_10140": "请求 CPU 数量[%s] 不能低于最小保证值,配置最小值: %s,实际最小值: %s(max(cpuNum × 20%%, 配置最小值))", @@ -4741,5 +4743,11 @@ "ORG_ZSTACK_AI_10162": "虚拟机「%s」(UUID: %s) 必须处于运行状态才能挂载/卸载模型,当前状态: %s", "ORG_ZSTACK_AI_10163": "虚拟机「%s」(UUID: %s) 未运行在任何主机上", "ORG_ZSTACK_AI_10164": "模型「%s」(UUID: %s) 与该虚拟机所属账户的共享规则不匹配,无法挂载。\n请确认模型已共享给该账户或设为公开。", - "ORG_ZSTACK_AI_10165": "模型中心 (UUID: %s) 未找到(关联模型: 「%s」UUID: %s)。\n请检查模型中心是否已被删除。" + "ORG_ZSTACK_AI_10165": "模型中心 (UUID: %s) 未找到(关联模型: 「%s」UUID: %s)。\n请检查模型中心是否已被删除。", + "ORG_ZSTACK_NETWORK_ZNS_10043": "为 ZNS 三层网络[uuid:%s]分配 DHCPv4 服务 IP 失败", + "ORG_ZSTACK_NETWORK_ZNS_10044": "无法启用 DHCP:三层网络[uuid:%s]没有可用的 IP 范围(不包含 SLAAC)", + "ORG_ZSTACK_NETWORK_ZNS_10045": "无法启用 DHCP:三层网络[uuid:%s]没有云端预留的 DHCPv4 服务 IP", + "ORG_ZSTACK_NETWORK_ZNS_10046": "网段[uuid:%s]上已存在 DHCP 服务,但 GET 返回为空", + "ORG_ZSTACK_NETWORK_ZNS_10047": "无法更新 DHCP:三层网络[uuid:%s]没有云端预留的 DHCPv4 服务 IP", + "ORG_ZSTACK_NETWORK_ZNS_10048": "为 ZNS 三层网络[uuid:%s]分配 DHCPv4 服务 IP 失败" } diff --git a/conf/i18n/globalErrorCodeMapping/global-error-zh_TW.json b/conf/i18n/globalErrorCodeMapping/global-error-zh_TW.json index e4519a55611..714160303db 100644 --- a/conf/i18n/globalErrorCodeMapping/global-error-zh_TW.json +++ b/conf/i18n/globalErrorCodeMapping/global-error-zh_TW.json @@ -2874,7 +2874,7 @@ "ORG_ZSTACK_AI_CONTAINER_10018": "部署 %s 没有副本信息", "ORG_ZSTACK_TAG2_10005": "非法標签UUIDs %s,標签類型必須是简单型,)", "ORG_ZSTACK_AI_CONTAINER_10017": "部署 %s 未找到", - "ORG_ZSTACK_IDENTITY_10070": "無法找到帳號[uuid: %s]的配額[name: %s]", + "ORG_ZSTACK_IDENTITY_10070": "無法找到配額[name: %s],帳號[uuid: %s]", "ORG_ZSTACK_TAG2_10002": "無法更新简单標签模式格式", "ORG_ZSTACK_TAG2_10003": "重复名称", "ORG_ZSTACK_SNS_PLATFORM_WECOM_10000": "失敗向企业微信發送消息。状态:%s,正文:%s", diff --git a/conf/install/zstack-server b/conf/install/zstack-server index dbfd89047ab..5c17ff816f8 100755 --- a/conf/install/zstack-server +++ b/conf/install/zstack-server @@ -17,6 +17,9 @@ pidfile='/var/run/zstack/zstack-server.pid' TOMCAT_PATH="/usr/local/zstack/root/apache-tomcat" zstack_app=${ZSTACK_HOME-"$TOMCAT_PATH/webapps/zstack"} +MARIADB_SERVICE=${ZSTACK_MARIADB_SERVICE:-mariadb} +MARIADB_SOCKET=${ZSTACK_MARIADB_SOCKET:-/var/lib/mysql/mysql.sock} +ZSTACK_SERVER_LOG_DIR=${ZSTACK_SERVER_LOG_DIR:-/var/log/zstack} which zstack-ctl &>/dev/null if [ $? -ne 0 ]; then @@ -32,7 +35,92 @@ stop_zstack(){ ZSTACK_HOME=$zstack_app HOME=`echo ~root` zstack-ctl stop } +log_zstack_server() { + mkdir -p "$ZSTACK_SERVER_LOG_DIR" 2>/dev/null + if [ -d "$ZSTACK_SERVER_LOG_DIR" ]; then + echo "$@" >> "$ZSTACK_SERVER_LOG_DIR/zstack-server.log" + else + echo "$@" + fi +} + +mariadb_service_exists() { + if command -v systemctl >/dev/null 2>&1; then + systemctl list-unit-files "$MARIADB_SERVICE.service" 2>/dev/null | grep -q "$MARIADB_SERVICE.service" && return 0 + fi + + if command -v service >/dev/null 2>&1; then + service "$MARIADB_SERVICE" status >/dev/null 2>&1 && return 0 + fi + + [ -x "/etc/init.d/$MARIADB_SERVICE" ] && return 0 + + return 1 +} + +mariadb_is_active() { + if command -v systemctl >/dev/null 2>&1; then + systemctl is-active --quiet "$MARIADB_SERVICE" >/dev/null 2>&1 && return 0 + fi + + if command -v service >/dev/null 2>&1; then + service "$MARIADB_SERVICE" status >/dev/null 2>&1 && return 0 + fi + + if [ -x "/etc/init.d/$MARIADB_SERVICE" ]; then + "/etc/init.d/$MARIADB_SERVICE" status >/dev/null 2>&1 && return 0 + fi + + return 1 +} + +socket_is_used() { + has_probe=false + + if command -v lsof >/dev/null 2>&1; then + has_probe=true + lsof -t -- "$MARIADB_SOCKET" >/dev/null 2>&1 && return 0 + fi + + if command -v fuser >/dev/null 2>&1; then + has_probe=true + fuser "$MARIADB_SOCKET" >/dev/null 2>&1 && return 0 + fi + + [ "$has_probe" = "true" ] || return 2 + + return 1 +} + +start_mariadb_service() { + if command -v systemctl >/dev/null 2>&1; then + systemctl reset-failed "$MARIADB_SERVICE" >/dev/null 2>&1 + systemctl start "$MARIADB_SERVICE" + return $? + fi + + service "$MARIADB_SERVICE" start +} + +recover_mariadb_stale_socket() { + [ "$ZSTACK_RECOVER_MARIADB_SOCKET" = "false" ] && return 0 + [ -e "$MARIADB_SOCKET" ] || return 0 + mariadb_service_exists || return 0 + mariadb_is_active && return 0 + socket_is_used + socket_status=$? + [ "$socket_status" -eq 0 ] && return 0 + [ "$socket_status" -eq 2 ] && return 0 + + log_zstack_server "removing stale MariaDB socket $MARIADB_SOCKET before zstack start" + rm -f "$MARIADB_SOCKET" || return 1 + + log_zstack_server "starting $MARIADB_SERVICE service before zstack start" + start_mariadb_service +} + start_zstack(){ + recover_mariadb_stale_socket || return $? ZSTACK_HOME=$zstack_app HOME=`echo ~root` zstack-ctl start } diff --git a/conf/serviceConfig/sdnController.xml b/conf/serviceConfig/sdnController.xml index 41521e0803c..2ae849eb987 100644 --- a/conf/serviceConfig/sdnController.xml +++ b/conf/serviceConfig/sdnController.xml @@ -49,4 +49,4 @@ org.zstack.network.hostNetworkInterface.APIQueryPhysicalSwitchMsg query - \ No newline at end of file + diff --git a/conf/serviceConfig/volume.xml b/conf/serviceConfig/volume.xml index 03fcb26b8de..bd0a010273f 100755 --- a/conf/serviceConfig/volume.xml +++ b/conf/serviceConfig/volume.xml @@ -93,4 +93,8 @@ org.zstack.header.volume.APIUndoSnapshotCreationMsg + + + org.zstack.header.volume.APIReInitDataVolumeMsg + diff --git a/conf/springConfigXml/Kvm.xml b/conf/springConfigXml/Kvm.xml index 580169b641a..cdb2f667c15 100755 --- a/conf/springConfigXml/Kvm.xml +++ b/conf/springConfigXml/Kvm.xml @@ -96,6 +96,12 @@ + + + + + + @@ -107,9 +113,9 @@ - - - + + + diff --git a/conf/springConfigXml/VmInstanceManager.xml b/conf/springConfigXml/VmInstanceManager.xml index ef3d5a7cc9e..09a9cb8d0e5 100755 --- a/conf/springConfigXml/VmInstanceManager.xml +++ b/conf/springConfigXml/VmInstanceManager.xml @@ -37,6 +37,7 @@ org.zstack.compute.vm.VmAllocateVolumeFlow org.zstack.compute.vm.VmAllocateNicFlow org.zstack.compute.vm.VmAllocateNicIpFlow + org.zstack.compute.vm.VmAllocateSdnNicFlow org.zstack.compute.vm.VmAllocateCdRomFlow org.zstack.compute.vm.VmInstantiateResourcePreFlow org.zstack.compute.vm.VmCreateOnHypervisorFlow @@ -68,6 +69,7 @@ org.zstack.compute.vm.VmAllocateHostForStoppedVmFlow org.zstack.compute.vm.VmImageSelectBackupStorageFlow org.zstack.compute.vm.VmAllocateNicForStartingVmFlow + org.zstack.compute.vm.VmAllocateSdnNicFlow org.zstack.compute.vm.VmInstantiateResourcePreFlow org.zstack.compute.vm.VmStartOnHypervisorFlow org.zstack.compute.vm.VmInstantiateResourcePostFlow @@ -115,6 +117,7 @@ + org.zstack.compute.vm.VmExpungeSdnNicFlow org.zstack.compute.vm.VmExpungeRootVolumeFlow org.zstack.compute.vm.VmExpungeMemoryVolumeFlow org.zstack.compute.vm.VmExpungeCacheVolumeFlow @@ -260,4 +263,14 @@ + + + + + + + + + + diff --git a/conf/springConfigXml/flatNetworkProvider.xml b/conf/springConfigXml/flatNetworkProvider.xml index b05ce499cfc..4dde49c4d62 100755 --- a/conf/springConfigXml/flatNetworkProvider.xml +++ b/conf/springConfigXml/flatNetworkProvider.xml @@ -51,6 +51,7 @@ + diff --git a/conf/springConfigXml/sdnController.xml b/conf/springConfigXml/sdnController.xml index a9be9ec8795..e76be084ac6 100644 --- a/conf/springConfigXml/sdnController.xml +++ b/conf/springConfigXml/sdnController.xml @@ -26,14 +26,11 @@ - - - - + diff --git a/conf/springConfigXml/sugonSdnController.xml b/conf/springConfigXml/sugonSdnController.xml index f0ff6ad0033..c55e6da4903 100644 --- a/conf/springConfigXml/sugonSdnController.xml +++ b/conf/springConfigXml/sugonSdnController.xml @@ -67,11 +67,7 @@ - - - - - + diff --git a/conf/springConfigXml/volumeSnapshot.xml b/conf/springConfigXml/volumeSnapshot.xml index 09022186cb2..d26ca551061 100755 --- a/conf/springConfigXml/volumeSnapshot.xml +++ b/conf/springConfigXml/volumeSnapshot.xml @@ -26,6 +26,7 @@ + diff --git a/conf/tools/install.sh b/conf/tools/install.sh index 8a759869850..1fe2f2642a0 100755 --- a/conf/tools/install.sh +++ b/conf/tools/install.sh @@ -8,6 +8,7 @@ else fi pypi_path=file://$cwd/../../../static/pypi/simple +zstack_build_tmpdir=/usr/local/zstack/ usage() { echo "usage:$0 [zstack-cli|zstack-ctl|zstack-dashboard|zstack-ui|zstack-sys]" @@ -25,6 +26,124 @@ install_pip() { pip3.11 --version | grep 22.3.1 >/dev/null || yum install -y python3.11-pip } +zstack_local_repo_args() { + grep -R "^\[zstack-local\]" /etc/yum.repos.d/*.repo >/dev/null 2>&1 && echo "--disablerepo=* --enablerepo=zstack-local" +} + +yum_install_packages() { + local repo_args=`zstack_local_repo_args` + yum -y $repo_args install $@ +} + +yum_reinstall_packages() { + local repo_args=`zstack_local_repo_args` + yum -y $repo_args reinstall $@ || yum -y $repo_args install $@ +} + +ensure_rpm_packages_installed() { + local missing_list=`LANG=en_US.UTF-8 rpm -q $@ 2>/dev/null | grep 'not installed' | awk 'BEGIN{ORS=" "}{ print $2 }'` + [ -z "$missing_list" ] && return 0 + + echo "Installing zstack-ctl build dependencies: $missing_list" + yum_install_packages $missing_list +} + +verify_rpm_packages() { + local broken_list="" + local pkg + + for pkg in $@; do + rpm -q $pkg >/dev/null 2>&1 || continue + rpm -V $pkg >/dev/null 2>&1 || broken_list="$broken_list $pkg" + done + + [ -z "$broken_list" ] && return 0 + + echo "Reinstalling broken zstack-ctl build dependencies:$broken_list" + yum_reinstall_packages $broken_list +} + +python_cflags_need_annobin() { + $1 - <<'PY' 2>/dev/null | grep -q 'annobin' +import sysconfig +print(sysconfig.get_config_var("CFLAGS") or "") +PY +} + +python_cflags_need_redhat_rpm_config() { + $1 - <<'PY' 2>/dev/null | grep -qE 'redhat|^-specs=| -specs=' +import sysconfig +print(sysconfig.get_config_var("CFLAGS") or "") +PY +} + +verify_python_c_extension_build() { + local python_bin=$1 + local tmp_c=`TMPDIR="$zstack_build_tmpdir" mktemp zstackctl-build-check.XXXXXX.c` + [ -z "$tmp_c" ] && return 1 + local tmp_o=${tmp_c%.c}.o + local py_cflags=`$python_bin - <<'PY' +import sysconfig +print(sysconfig.get_config_var("CFLAGS") or "") +PY +` + local py_include=`$python_bin - <<'PY' +import sysconfig +include_dir = sysconfig.get_config_var("INCLUDEPY") or "" +print("-I%s" % include_dir if include_dir else "") +PY +` + + cat > "$tmp_c" <<'EOF' +#include +#include +#include +int main(void) { return 0; } +EOF + + gcc $py_cflags $py_include -c "$tmp_c" -o "$tmp_o" + local ret=$? + rm -f "$tmp_c" "$tmp_o" + + if [ $ret -ne 0 ]; then + echo "Failed to compile a minimal Python C extension. Please check gcc, python3.11-devel, libffi-devel, openssl-devel, redhat-rpm-config and annobin." + return 1 + fi + + return 0 +} + +ensure_zstack_ctl_build_deps() { + command -v rpm >/dev/null 2>&1 || return 0 + command -v yum >/dev/null 2>&1 || return 0 + + local python_bin=python3.11 + local base_deps="$python_bin ${python_bin}-devel ${python_bin}-pip gcc libffi-devel openssl-devel" + ensure_rpm_packages_installed $base_deps || return 1 + verify_rpm_packages $base_deps || return 1 + local need_redhat_rpm_config=false + local need_annobin=false + + if python_cflags_need_redhat_rpm_config $python_bin; then + need_redhat_rpm_config=true + ensure_rpm_packages_installed redhat-rpm-config || return 1 + fi + + if python_cflags_need_annobin $python_bin; then + need_annobin=true + ensure_rpm_packages_installed annobin || return 1 + fi + + if $need_redhat_rpm_config; then + verify_rpm_packages redhat-rpm-config || return 1 + fi + if $need_annobin; then + verify_rpm_packages annobin || return 1 + fi + + verify_python_c_extension_build $python_bin +} + # Ensure the virtualenv at $1 is a Python 3.11 venv. # If it does not exist or is a legacy Python 2 venv, recreate it. ensure_python3_venv() { @@ -47,6 +166,10 @@ ensure_python3_venv() { cd $cwd +if [ $tool = 'zstack-ctl' ]; then + ensure_zstack_ctl_build_deps || exit 1 +fi + install_pip cd /tmp @@ -87,8 +210,8 @@ elif [ $tool = 'zstack-ctl' ]; then ensure_python3_venv "$CTL_VIRENV_PATH" . $CTL_VIRENV_PATH/bin/activate cd $cwd - TMPDIR=/usr/local/zstack/ pip install -i $pypi_path --trusted-host localhost --ignore-installed zstackctl-*.tar.gz || exit 1 - TMPDIR=/usr/local/zstack/ pip install -i $pypi_path --trusted-host localhost --ignore-installed pycryptodome || exit 1 + TMPDIR="$zstack_build_tmpdir" pip install -i $pypi_path --trusted-host localhost --ignore-installed zstackctl-*.tar.gz || exit 1 + TMPDIR="$zstack_build_tmpdir" pip install -i $pypi_path --trusted-host localhost --ignore-installed pycryptodome || exit 1 [ -f $CTL_VIRENV_PATH/bin/zstack-ctl ] && cp $CTL_VIRENV_PATH/bin/zstack-ctl /usr/bin/zstack-ctl chmod +x /usr/bin/zstack-ctl python $CTL_VIRENV_PATH/lib/python3.11/site-packages/zstackctl/generate_zstackctl_bash_completion.py @@ -102,7 +225,7 @@ elif [ $tool = 'zstack-sys' ]; then . $SYS_VIRENV_PATH/bin/activate cd $cwd #TMPDIR=/usr/local/zstack/ pip install -i $pypi_path --trusted-host localhost --ignore-installed setuptools==65.5.1 || exit 1 - TMPDIR=/usr/local/zstack/ pip install -i $pypi_path --trusted-host localhost --ignore-installed ansible==9.13.0 || exit 1 + TMPDIR="$zstack_build_tmpdir" pip install -i $pypi_path --trusted-host localhost --ignore-installed ansible==9.13.0 || exit 1 cat > /usr/bin/ansible << EOF #! /bin/sh @@ -219,4 +342,3 @@ elif [ x"$tool" = x"zstack-ui" ]; then else usage fi - diff --git a/core/src/main/java/org/zstack/core/rest/RESTFacadeImpl.java b/core/src/main/java/org/zstack/core/rest/RESTFacadeImpl.java index 516fd500ef6..c803af97498 100755 --- a/core/src/main/java/org/zstack/core/rest/RESTFacadeImpl.java +++ b/core/src/main/java/org/zstack/core/rest/RESTFacadeImpl.java @@ -93,6 +93,10 @@ private interface AsyncHttpWrapper { void fail(ErrorCode err); void success(HttpEntity responseEntity); + + String getResourceUuid(); + + long getSentAtMillis(); } private interface HttpCallHandlerWrapper { @@ -446,6 +450,9 @@ public void asyncJson(final String url, final String body, Map h HttpEntity req = new HttpEntity(body, requestHeaders); + final long sentAtMillis = System.currentTimeMillis(); + final String resourceUuid = (headers == null) ? null : headers.get(Constants.AGENT_HTTP_HEADER_RESOURCE_UUID); + AsyncHttpWrapper wrapper = new AsyncHttpWrapper() { final AtomicBoolean called = new AtomicBoolean(false); @@ -565,6 +572,16 @@ public void fail(ErrorCode err) { public void success(HttpEntity responseEntity) { completion.success(responseEntity); } + + @Override + public String getResourceUuid() { + return resourceUuid; + } + + @Override + public long getSentAtMillis() { + return sentAtMillis; + } }; try { @@ -600,6 +617,29 @@ public void asyncJsonPost(String url, String body, AsyncRESTCallback callback) { asyncJsonPost(url, body, callback, TimeUnit.MILLISECONDS, timeout); } + @Override + public int failPendingCallsForResourceBefore(String resourceUuid, long cutoffMillis, ErrorCode err) { + if (resourceUuid == null) { + return 0; + } + int drained = 0; + for (AsyncHttpWrapper w : wrappers.values()) { + if (!resourceUuid.equals(w.getResourceUuid())) { + continue; + } + if (w.getSentAtMillis() >= cutoffMillis) { + continue; + } + try { + w.fail(err); + drained++; + } catch (Throwable t) { + logger.warn(String.format("fail injection threw for resource[uuid:%s]: %s", resourceUuid, t.getMessage()), t); + } + } + return drained; + } + @Override public HttpEntity httpServletRequestToHttpEntity(HttpServletRequest req) { try { diff --git a/core/src/main/java/org/zstack/core/rest/webhook/WebhookCallbackClient.java b/core/src/main/java/org/zstack/core/rest/webhook/WebhookCallbackClient.java new file mode 100644 index 00000000000..0559312b6d2 --- /dev/null +++ b/core/src/main/java/org/zstack/core/rest/webhook/WebhookCallbackClient.java @@ -0,0 +1,188 @@ +package org.zstack.core.rest.webhook; + +import org.zstack.core.Platform; +import org.zstack.core.thread.ThreadFacade; +import org.zstack.core.thread.ThreadFacadeImpl; +import org.zstack.header.core.ReturnValueCompletion; +import org.zstack.header.errorcode.ErrorCode; +import org.zstack.header.rest.RESTFacade; +import org.zstack.utils.Utils; +import org.zstack.utils.logging.CLogger; + +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.TimeUnit; + +import static org.zstack.core.Platform.operr; + +/** + * Generic async callback client for external systems that use a webhook pattern: + *
    + *
  1. Send an HTTP request to the external system
  2. + *
  3. External system returns immediately (e.g. 202 Accepted)
  4. + *
  5. External system later POSTs back the result to a callback URL
  6. + *
  7. This client matches the callback to the original request and completes it
  8. + *
+ * + *

Callback flow:

+ *
+ * External Controller
+ *     │  POST /asyncrest/sendcommand  (commandpath header → callbackPath)
+ *     ▼
+ * AsyncRESTCallController.sendCommand()
+ *     ▼
+ * RESTFacadeImpl.sendCommand()  →  httpCallhandlers.get(callbackPath)
+ *     ▼
+ * WebhookCallbackClient.onCallback(T cmd)
+ *     ├─ protocol.extractTaskId(cmd)
+ *     ├─ pendingCalls.remove(taskId)  ← CAS point (atomic, prevents double invocation)
+ *     ├─ cancel timeout
+ *     └─ protocol.isSuccess(cmd) ? completion.success(cmd) : completion.fail(error)
+ * 
+ * + *

This class is a plain POJO — not a Spring bean. It is created and owned by the + * plugin-specific API client (e.g. ZnsApiClient) which passes in its dependencies.

+ * + *

Thread safety: {@code ConcurrentHashMap.remove()} serves as the CAS point. + * Among callback arrival, timeout, and send-failure, only one can successfully remove + * and thus complete a pending call.

+ * + * @param the callback body type + */ +public class WebhookCallbackClient { + private static final CLogger logger = Utils.getLogger(WebhookCallbackClient.class); + + private final WebhookProtocol protocol; + private final RESTFacade restf; + private final ThreadFacade thdf; + private final ConcurrentHashMap> pendingCalls = new ConcurrentHashMap<>(); + private String callbackUrl; + + private static class PendingEntry { + final ReturnValueCompletion completion; + final ThreadFacadeImpl.TimeoutTaskReceipt timeoutReceipt; + + PendingEntry(ReturnValueCompletion completion, + ThreadFacadeImpl.TimeoutTaskReceipt timeoutReceipt) { + this.completion = completion; + this.timeoutReceipt = timeoutReceipt; + } + } + + public WebhookCallbackClient(WebhookProtocol protocol, RESTFacade restf, ThreadFacade thdf) { + this.protocol = protocol; + this.restf = restf; + this.thdf = thdf; + } + + /** + * Register the callback handler on the sendCommand channel. + * Must be called once during the owning component's start() lifecycle. + */ + public void start() { + this.callbackUrl = restf.getSendCommandUrl(); + restf.registerSyncHttpCallHandler( + protocol.getCallbackPath(), + protocol.getCallbackClass(), + this::onCallback); + } + + /** + * Register a pending call and return its task identifier. + * + *

The caller should use the returned taskId to decorate the outgoing request + * headers via {@link WebhookProtocol#decorateRequest}, then send the HTTP request. + * If the send fails, the caller must invoke {@link #fail} to clean up.

+ * + * @param completion the completion to invoke when the callback arrives (or on timeout) + * @param unit timeout time unit + * @param timeout timeout value + * @return the generated taskId + */ + public String submit(ReturnValueCompletion completion, TimeUnit unit, long timeout) { + String taskId = Platform.getUuid(); + + ThreadFacadeImpl.TimeoutTaskReceipt timeoutReceipt = thdf.submitTimeoutTask(() -> { + fail(taskId, operr("[Webhook Timeout] callback timed out for taskId[%s], path[%s]", + taskId, protocol.getCallbackPath())); + }, unit, timeout); + + pendingCalls.put(taskId, new PendingEntry<>(completion, timeoutReceipt)); + return taskId; + } + + /** + * Actively fail a pending call (e.g. when the HTTP send fails). + * + *

{@code ConcurrentHashMap.remove()} is atomic — only one of + * (callback / timeout / send-failure) can win, preventing double invocation.

+ */ + public void fail(String taskId, ErrorCode error) { + PendingEntry entry = pendingCalls.remove(taskId); + if (entry != null) { + entry.timeoutReceipt.cancel(); + entry.completion.fail(error); + } + } + + /** + * @return the callback URL that the external system should POST results to + */ + public String getCallbackUrl() { + return callbackUrl; + } + + /** + * Override the callback URL. Use this when the callback is handled by a + * dedicated HTTP endpoint (e.g. a Spring Controller) rather than the + * sendCommand channel. + */ + public void setCallbackUrl(String callbackUrl) { + this.callbackUrl = callbackUrl; + } + + /** + * @return the protocol adapter + */ + public WebhookProtocol getProtocol() { + return protocol; + } + + /** + * Deliver a callback that was received outside the sendCommand channel + * (e.g. from a dedicated Spring Controller endpoint for external systems). + */ + public void deliverCallback(T cmd) { + onCallback(cmd); + } + + /** + * Callback handler invoked by the RESTFacade sendCommand channel. + */ + private String onCallback(T cmd) { + String taskId = protocol.extractTaskId(cmd); + if (taskId == null) { + logger.warn(String.format("received webhook callback without taskId on path[%s], ignoring", + protocol.getCallbackPath())); + return null; + } + + PendingEntry entry = pendingCalls.remove(taskId); + if (entry == null) { + logger.warn(String.format("received webhook callback for unknown taskId[%s] on path[%s], ignoring", + taskId, protocol.getCallbackPath())); + return null; + } + + entry.timeoutReceipt.cancel(); + + if (protocol.isSuccess(cmd)) { + entry.completion.success(cmd); + } else { + String error = protocol.extractError(cmd); + entry.completion.fail(operr("webhook callback failed for taskId[%s], path[%s], error: %s", + taskId, protocol.getCallbackPath(), error != null ? error : "unknown")); + } + + return null; + } +} diff --git a/core/src/main/java/org/zstack/core/rest/webhook/WebhookProtocol.java b/core/src/main/java/org/zstack/core/rest/webhook/WebhookProtocol.java new file mode 100644 index 00000000000..693a4add2a5 --- /dev/null +++ b/core/src/main/java/org/zstack/core/rest/webhook/WebhookProtocol.java @@ -0,0 +1,54 @@ +package org.zstack.core.rest.webhook; + +import java.util.Map; + +/** + * Defines the protocol adaptation for an external system's webhook callback mechanism. + * + *

Different external controllers (e.g., SDN controllers) use different header conventions, + * callback body formats, and success/failure semantics. This interface abstracts those + * differences so that {@link WebhookCallbackClient} can handle the common async lifecycle + * (pending call registration, timeout, CAS-guarded callback dispatch) generically.

+ * + * @param the callback body type that the external system POSTs back + */ +public interface WebhookProtocol { + + /** + * The path to register on the sendCommand channel (e.g. "/zns/callback"). + * This will be passed to {@code RESTFacade.registerSyncHttpCallHandler}. + */ + String getCallbackPath(); + + /** + * The class used to deserialize the callback JSON body. + */ + Class getCallbackClass(); + + /** + * Extract the task identifier from the callback body. + * This must match the taskId returned by {@link WebhookCallbackClient#submit}. + */ + String extractTaskId(T callback); + + /** + * Determine whether the callback indicates a successful operation. + */ + boolean isSuccess(T callback); + + /** + * Extract a human-readable error description from the callback body. + * Called only when {@link #isSuccess} returns false. + */ + String extractError(T callback); + + /** + * Decorate the outgoing HTTP request headers with the task identifier and callback URL, + * following the conventions of the external system. + * + * @param headers mutable map to add headers to + * @param taskId the unique task identifier for this async call + * @param callbackUrl the URL the external system should POST the result to + */ + void decorateRequest(Map headers, String taskId, String callbackUrl); +} diff --git a/core/src/main/java/org/zstack/core/trash/TrashType.java b/core/src/main/java/org/zstack/core/trash/TrashType.java index a3ec4d62ea6..93de5ceecb7 100644 --- a/core/src/main/java/org/zstack/core/trash/TrashType.java +++ b/core/src/main/java/org/zstack/core/trash/TrashType.java @@ -10,4 +10,5 @@ public enum TrashType { RevertVolume, VolumeSnapshot, ReimageVolume, + ReInitDataVolume, } diff --git a/core/src/main/java/org/zstack/core/upgrade/UpgradeChecker.java b/core/src/main/java/org/zstack/core/upgrade/UpgradeChecker.java index 90639caf24c..b2e90613b20 100644 --- a/core/src/main/java/org/zstack/core/upgrade/UpgradeChecker.java +++ b/core/src/main/java/org/zstack/core/upgrade/UpgradeChecker.java @@ -327,24 +327,25 @@ public void updateAgentVersion(String agentUuid, String agentType, String expect return; } - if (Objects.equals(agentVersionVO.getExpectVersion(), agentVersionVO.getCurrentVersion())) { + if (Objects.equals(agentVersionVO.getExpectVersion(), expectVersion) + && Objects.equals(agentVersionVO.getCurrentVersion(), currentVersion)) { logger.trace(String.format("Agent[uuid: %s] version expected version: %s, current version: %s, not changed", agentUuid, agentVersionVO.getExpectVersion(), agentVersionVO.getCurrentVersion())); return; } - if (!Objects.equals(agentVersionVO.getCurrentVersion(), currentVersion)) { - String originCurrentVersion = agentVersionVO.getCurrentVersion(); - agentVersionVO.setCurrentVersion(currentVersion); - logger.trace(String.format("Update agent[uuid: %s] version\n" + - "From:\n" + - "expected version: %s, current version: %s\n" + - "To:\n" + - "expected version: %s, current version: %s\n", - agentUuid, - agentVersionVO.getExpectVersion(), originCurrentVersion, - agentVersionVO.getExpectVersion(), agentVersionVO.getCurrentVersion())); - dbf.update(agentVersionVO); - } + String originExpectVersion = agentVersionVO.getExpectVersion(); + String originCurrentVersion = agentVersionVO.getCurrentVersion(); + agentVersionVO.setExpectVersion(expectVersion); + agentVersionVO.setCurrentVersion(currentVersion); + logger.trace(String.format("Update agent[uuid: %s] version\n" + + "From:\n" + + "expected version: %s, current version: %s\n" + + "To:\n" + + "expected version: %s, current version: %s\n", + agentUuid, + originExpectVersion, originCurrentVersion, + agentVersionVO.getExpectVersion(), agentVersionVO.getCurrentVersion())); + dbf.update(agentVersionVO); } /** diff --git a/docs/design/zns-pivot/ZCF-2133-p3-review-gpt55.md b/docs/design/zns-pivot/ZCF-2133-p3-review-gpt55.md new file mode 100644 index 00000000000..c3e34ed008e --- /dev/null +++ b/docs/design/zns-pivot/ZCF-2133-p3-review-gpt55.md @@ -0,0 +1,224 @@ +# P3 详细设计 Review 报告 + +**文档**:ZCF-2133-zns-pivot-detailed-design.md v1.0.0 +**评审日期**:2025-07 +**评审人**:Senior Java/Cloud Platform Architect + +--- + +## 总评 + +设计整体思路清晰,SoT 拆分逻辑合理,SystemTag 迁移方案保留了向后兼容窗口。但存在 4 个 P0 阻塞问题,其中两个(HTTP 机制选型错误、缺失依赖注入字段)将导致运行时 NPE 或 404,必须在进入 P4 实现前全部修复。 + +**总体结论:NEEDS REWORK** + +--- + +## 统计 + +| 级别 | 数量 | +|------|------| +| P0 (阻塞) | 4 | +| P1 (重要) | 4 | +| P2 (次要) | 4 | + +--- + +## P0 问题(阻塞,必须修复) + +### P0-1:`registerSyncHttpCallHandler` 对外部 ZNS 系统不可用 + +**位置**:§4.1.2 `ZnsReverseNotificationFacade.start()` + +**问题**:设计对 4 个 ZNS 通知端点全部使用 `RESTFacade.registerSyncHttpCallHandler`。该机制属于 ZStack 内部 Agent 协议——要求调用方在 HTTP 请求中携带 `commandpath` 头以完成路由分发。ZNS 是外部系统,其 POST 请求不携带任何 `commandpath` 头(参见现有 `ZnsCallbackController.java` 的注释:"ZNS is an external system that simply POSTs a JSON body to the webhook URL without extra routing headers")。使用此机制后 ZNS 推送的请求将全部被 RESTFacade dispatch 忽略或返回 404,通知通道完全失效。 + +**建议**:与现有 `ZnsCallbackController.java` 保持一致,新建或扩展一个 Spring `@Controller`(如 `ZnsNotificationController`),对每个端点使用 `@RequestMapping` 注册处理方法,接收 `@RequestBody` 后分发给各 Handler。不需要 `registerSyncHttpCallHandler`。 + +--- + +### P0-2:`ZnsReverseNotificationFacade` 缺失 `evtf` 和 `znsApiClient` 依赖注入 + +**位置**:§4.1.2 外部类声明;§4.2.2 `AddComputeManagerHandler` step 5;§4.10.2 `SyncResourceHandler.handleTenantRouterEvent` + +**问题**:外部类 `ZnsReverseNotificationFacade` 的 `@Autowired` 字段只声明了 `restf`、`dbf`、`bus`、`thdf` 四个。但内部 Handler 类访问了两个未声明的字段: + +1. `AddComputeManagerHandler` 第 5 步调用 `evtf.fire(SdnControllerCanonicalEvents.SDN_CONTROLLER_ADDED, ...)` ——`evtf`(EventFacade)未注入,运行时 NPE。 +2. `SyncResourceHandler.handleTenantRouterEvent` 调用 `znsApiClient.getTenantRouter(...)` 和 `znsApiClient.listSegments(...)` ——`znsApiClient` 未注入,运行时 NPE。 + +**建议**:在 `ZnsReverseNotificationFacade` 类中补充: + +```java +@Autowired +private EventFacade evtf; +@Autowired +private ZnsApiClient znsApiClient; +``` + +--- + +### P0-3:`AddComputeManagerHandler` 无事务边界,多步 persist 存在数据完整性风险 + +**位置**:§4.2.2,步骤 2-4 + +**问题**:连续执行 `dbf.persist(sdnVo)` → `dbf.persist(znsVo)` → `createInherentTag(...)` 三步,中间任意一步失败(如 `ZnsControllerVO` 主键冲突或 SystemTag 写入异常)将导致 `SdnControllerVO` 孤岛记录残留在数据库中,且无回滚。重复执行通知时因 name 已存在而直接返回错误,但孤岛记录仍无法清除,数据库状态被污染。 + +另外,名称重复检查(check-then-act)与 persist 之间没有事务保护,并发场景下两个相同通知可能同时通过检查、同时 persist,违反业务唯一性约束。 + +**建议**:将步骤 2-4 包裹在同一个 `@Transactional` 方法或使用 `new SQLBatch()` 块中;同时对 `SdnControllerVO` 的 `computerManagerUuid`(通过唯一索引或 DB 约束)进行唯一性保障,而非仅凭 name 检查。 + +--- + +### P0-4:`VmNicVO.type` 赋值时机与 `KVMRealizeL2GeneveNetworkBackend.realize()` 的先后顺序未验证 + +**位置**:§4.7.2 `computeVmNicType`;§4.8.3 `realize()` 方法 + +**问题**:`realize()` 中 DPDK 分支判断依赖 `nic.getType()`: + +```java +if (VmNicType.VHOSTUSER.toString().equals(nic.getType())) { + prepareDpdkNic(hostUuid, nic, completion); +} +``` + +`nic.getType()` 的值来自 `VmNicManagerImpl.computeVmNicType()`。设计未说明该方法的计算结果何时被持久化到 `VmNicVO.type`,也未确认 `VmNicVO` 在进入 `KVMRealizeL2GeneveNetworkBackend.realize()` 之前 `type` 字段是否已被正确写入。若 `VmNicVO.type` 在 `realize()` 执行时仍为 `null` 或 `NONE`,DPDK socket 永远不会被创建,但 VM 会以错误配置启动,且没有任何报错。 + +**建议**:设计必须明确以下两点: +1. `computeVmNicType()` 在哪个执行阶段被调用并将结果写入 `VmNicVO.type`(应早于 `KVMRealizeL2GeneveNetworkBackend.realize()` 调用链); +2. 在 `realize()` 入口加断言或日志,记录 `nic.getType()` 的当前值,以便在集成测试中可观测。 + +--- + +## P1 问题(重要,应修复) + +### P1-1:Handler 内抛出 `ApiMessageInterceptionException` 语义错误 + +**位置**:§4.3.2 `WizardInitSyncHandler`;§4.10.1 `SyncFabricHandler`;§4.10.2 `SyncResourceHandler` + +**问题**:三个 Handler 在找不到对应控制器时均抛出 `ApiMessageInterceptionException`。该异常专用于 `ApiMessageInterceptor` 的拦截阶段,在 HTTP 请求处理上下文中抛出此异常的行为未定义——可能被 Spring 全局异常处理器捕获为 500,也可能导致非预期响应,与 `NotificationResponse` 格式不一致,ZNS 无法正常解析错误。 + +**建议**:将错误场景改为返回 `NotificationResponse{success:false, error:"..."}` 的 JSON 字符串,或统一抛出一个约定的业务 `RuntimeException`(需配套 Spring `@ExceptionHandler` 处理)。 + +--- + +### P1-2:并发推送通知时 reconcile 操作缺乏串行化保护 + +**位置**:§4.10.1 `SyncFabricHandler`;§4.10.2 `SyncResourceHandler` + +**问题**:两个 Handler 均以 `Completion(null)` 触发异步 reconcile 后立即返回。若 ZNS 短时间内连续推送多条通知(网络抖动重试或批量事件),同一 controller 的 `syncDeviceResourcesFromZns` / `reconcileSegmentsCloudAsSoT` 将并行执行,导致: + +- 并发 upsert 同一 `ZnsTenantRouterVO`/`ZnsTransportZoneVO`:主键冲突或数据覆盖; +- 并发孤儿删除:一个线程正在使用的记录被另一个线程删除,引发 `DataIntegrityViolationException`。 + +**建议**:在两个 Handler 的异步触发点加入 per-controller `GlobalLock` 或使用 `ZStack ThreadFacade.syncSubmit` 排队执行,保证同一 controllerUuid 的 reconcile 操作串行化。 + +--- + +### P1-3:`needsSegmentUpdate` 对 L2 对象使用了不存在的 gateway 方法 + +**位置**:§4.12.2 `needsSegmentUpdate` + +**问题**: + +```java +private boolean needsSegmentUpdate(ZnsApiCommands.SegmentData znsSegment, + L2NetworkInventory cloudL2) { + if (!Objects.equals(znsSegment.gateway_address, cloudL2.getGatewayV4())) return true; + if (!Objects.equals(znsSegment.gateway6_address, cloudL2.getGatewayV6())) return true; + if (znsSegment.mtu != cloudL2.getMtu()) return true; + ... +} +``` + +`L2NetworkInventory` 不存在 `getGatewayV4()`、`getGatewayV6()`、`getMtu()` 方法——网关是 L3/IpRange 层概念,MTU 也通常存储在 L3 或独立配置,而非 L2 Inventory。此代码无法通过编译。即便手动扩展 L2Inventory,将 L3 信息下推到 L2 层也是架构倒置。 + +**建议**:`needsSegmentUpdate` 应接受 `L3NetworkInventory`(或 `IpRangeInventory` 列表),从 L3/IpRange 层获取 gateway 和 MTU 信息进行比较。方法签名应改为: + +```java +private boolean needsSegmentUpdate(ZnsApiCommands.SegmentData znsSegment, + L3NetworkInventory cloudL3) +``` + +--- + +### P1-4:`AddComputeManagerHandler` 重复检查仅基于 name,遗漏 computerManagerUuid 唯一性 + +**位置**:§4.2.2,步骤 1 + +**问题**:当前重复判断逻辑: + +```java +boolean nameExists = Q.New(SdnControllerVO.class) + .eq(SdnControllerVO_.name, cmd.name) + .isExists(); +``` + +只检查名称是否重复。若 ZNS 因网络超时重试推送相同通知(`computerManagerUuid` 相同、`name` 相同),第二次请求仍会被视为"重复而拒绝"。但若用户后续重命名控制器,再次推送原始通知将绕过检查创建重复记录。真正的业务唯一键是 `computerManagerUuid`。 + +**建议**:将重复检查改为基于 `computerManagerUuid` 的 SystemTag 查询(调用 `findControllerByComputerManagerUuid(cmd.computerManagerUuid)`),若已存在则直接返回现有 UUID(幂等语义),而非报错: + +```java +SdnControllerVO existing = findControllerByComputerManagerUuid(cmd.computerManagerUuid); +if (existing != null) { + return JSONObjectUtil.toJsonString(result(true, existing.getUuid(), null)); // 幂等 +} +``` + +--- + +## P2 问题(次要) + +### P2-1:`AddComputeManagerNotification` 携带明文密码 + +**位置**:§4.1.3 `ZnsNotificationCommands.AddComputeManagerNotification` + +**问题**:通知 DTO 中包含 `password` 字段明文传输。虽文档注明 Phase 1 依赖网络隔离,但在设计层面未提及任何传输加密或证书验证措施,调试日志若打印完整 body(`ZnsCallbackController.java` 现有模式为 `logger.debug(body)`)将导致密码泄露到日志文件。 + +**建议**:在 `ZnsReverseNotificationFacade` 的日志打印位置对 `password` 字段做脱敏处理;并在设计中明确 Phase 2 的 HMAC/TLS 升级路径。 + +--- + +### P2-2:`cleanupOrphanSegments` 未过滤 computerManagerUuid,存在跨控制器误删风险 + +**位置**:§4.3.3 + +**问题**:`cleanupOrphanSegments` 调用 `znsApiClient.listSegments(znsIp, ...)` 获取段列表,若参数中未携带 `cms_uuid`(computerManagerUuid)过滤条件,将拉取该 ZNS 实例下所有 Segment,包括属于其他 computerManager 的 Segment。这些 Segment 在 Cloud 中没有 L2 对应(因为它们属于别的 CM),会被误判为孤儿并强制删除。 + +**建议**:在 `cleanupOrphanSegments` 中显式传递 `computerManagerUuid` 过滤参数,与 `initSdnController` Flow 5 中的 `segParams.put("cms_uuid", ...)` 保持一致。 + +--- + +### P2-3:`SyncFabricNotification.scope` 值集合暴露 ZNS 内部拓扑术语 + +**位置**:§4.1.3 `SyncFabricNotification`;§4.9.2 `shouldSync` + +**问题**:`scope` 取值 `TZ | TN | HOSTSWITCH` 直接映射 ZNS 内部实体概念(TransportZone、TransportNode、HostSwitch),违反 NA-3 精神(API 参数不应暴露实现层细节)。同时 `shouldSync` 对 Tenant/TenantRouter 只响应 `"ALL"` scope,无法做精细粒度触发——若 ZNS 未来需要仅触发 Tenant 同步,现有枚举集合无法支持且需改代码。 + +**建议**:将 scope 值抽象为 Cloud 视角语义:`ALL | FABRIC | TENANT`;`FABRIC` 对应 TZ+TN+HOSTSWITCH,`TENANT` 对应 Tenant+TenantRouter 同步。在 `shouldSync` 中映射: + +```java +private boolean shouldSync(String scope, String category) { + if ("ALL".equalsIgnoreCase(scope)) return true; + return category.equalsIgnoreCase(scope); +} +``` + +--- + +### P2-4:`WizardInitSyncHandler` 异步触发后立即返回 `success:true`,ZNS 无法感知同步失败 + +**位置**:§4.3.2 末尾返回逻辑 + +**问题**:FlowChain 以 `.start()` 异步启动,`handleSyncHttpCall` 立即返回 `{success:true}`,ZNS 收到成功响应但实际同步可能几秒后失败(TenantRouter 拉取失败、DB 写入失败等)。ZNS 侧无重试机制,同步静默失败后 Cloud 状态可能不完整(如缺少 TenantRouter 记录)。 + +**建议**:在设计文档中明确说明此为"请求已受理(202 Accepted)"语义,ZNS 应在后续操作时(如创建 VPC L3)通过 Cloud 查询 API 验证同步状态,或依赖 `reconnectSdnController` 的周期性 reconcile 作为补偿机制。 + +--- + +## 亮点(做得好的地方) + +- **SoT 分组清晰**:将 `reconnectSdnController` 拆分为 Group A(ZNS-as-SoT 设备资源)和 Group B(Cloud-as-SoT Segment)逻辑分明,职责边界明确,比原来的单一 FlowChain 更易维护。 +- **SystemTag 迁移有兼容窗口**:`ENABLE_DPDK_VHOSTUSER` 改为 `ZNS_NIC_MODE` 时,`resolveZnsNicMode()` 提供了 v4 fallback 读取链,避免了升级时的强制迁移。 +- **孤儿 TenantRouter 告警而非静默删除**:当 ZNS 删除了 Cloud 中还有 L3 引用的 TenantRouter 时,设计选择触发 `EVT_ZNS_TENANT_ROUTER_ORPHAN_IN_CLOUD` 事件而非强删,符合 Cloud-as-SoT 的安全语义。 +- **FlowChain `NoRollbackFlow` 使用合理**:在 Reconcile 类 Flow 中(幂等 upsert 操作),均使用 `NoRollbackFlow`,避免了 rollback 时重复删除或状态不一致的问题。 +- **错误码体系完整**:6 个新错误码均有 i18n 映射,区分 argerr/operr 类型,与现有编码规范一致。 +- **实现顺序 Wave 划分合理**:Wave 1 先建数据模型、Wave 3 建通道、Wave 4 建流程的依赖拓扑排序正确,降低了并行开发的集成风险。 diff --git a/docs/design/zns-pivot/ZCF-2133-zns-pivot-detailed-design.md b/docs/design/zns-pivot/ZCF-2133-zns-pivot-detailed-design.md new file mode 100644 index 00000000000..e6b6a26a834 --- /dev/null +++ b/docs/design/zns-pivot/ZCF-2133-zns-pivot-detailed-design.md @@ -0,0 +1,2006 @@ +# ZCF-2133 ZNS 集成改造 P3 详细设计文档 + +## 1. 文档信息 + +| 字段 | 内容 | +|------|------| +| 文档编号 | ZCF-2133-P3-DD | +| 版本 | 1.1.0 | +| 状态 | 草稿 | +| 所属阶段 | P3 详细设计(瀑布模型第三阶段) | +| 关联 Func Spec | ZCF-2133 Func Spec v2.2.2 | +| 编写日期 | 2025-07 | +| 最后更新 | 2025-07 | + +### 修改历史 + +| 版本 | 日期 | 作者 | 说明 | +|------|------|------|------| +| 1.1.0 | 2026-04 | — | Review 修订:P0-1 HTTP 机制改 Spring @Controller;P0-2 补全 evtf/znsApiClient 注入;P0-3 AddComputeManager 增加事务边界+幂等语义;P0-4 补充 VmNicVO.type 赋值时机说明;P1-1/P1-3 Handler 错误响应修正;P1-2 并发序列化保护;P1-4 幂等检查改 computerManagerUuid;P2-2 cleanupOrphanSegments 增加 CM 过滤;P2-3 scope 值抽象化 | +| 1.0.0 | 2025-07 | — | 初稿,覆盖 14 个设计点 | + +--- + +## 2. 设计目标与范围 + +### 2.1 目标 + +将 ZNS 插件从"Cloud 主动拉取/注册"模式改造为"ZNS 主动推送通知"模式(pivot),实现: + +1. **反向通知通道**:ZNS → Cloud 的 HTTP 推送,替代现有纯拉取模型 +2. **Add-CM 流程重写**:ZNS wizard 完成后主动调用 Cloud,Cloud 被动建档 +3. **初次同步(Wizard Init Sync)**:ZNS wizard 完成 T1 创建后触发全量拉取 +4. **租户资源建模**:新增 `ZnsTenantVO` / `ZnsTenantRouterVO` 及完整生命周期 +5. **SystemTag 迁移**:`enableDpdkVhostuser`(L3 维度)→ `znsNicMode`(VM 维度) +6. **VPC L3 支持**:ZnsApiInterceptor 放开对 `L3VpcNetwork` 的拦截,要求关联租户路由器 Tag +7. **DPDK NIC 生命周期**:最小化路径实现 DPDK vhostuser socket 的创建/释放 +8. **Reconcile SoT 拆分**:设备资源(ZNS-as-SoT)与网络资源(Cloud-as-SoT)分组 + +### 2.2 范围 + +本文档覆盖 ZNS 插件目录: +```text +zstack/premium/plugin-premium/zns/src/main/java/org/zstack/network/zns/ +``` +以及关联的 KVM 插件改动(DPDK NIC 命令)和 VM NIC 类型计算改动。 + +### 2.3 不在范围内 + +- ZNS 侧 API 实现(由 ZNS 团队负责) +- KVM agent(Python)侧 dpdk socket 实现 +- UI/前端改动 +- 性能测试与压测 + +--- + +## 3. 设计变更概览 + +| 编号 | 变更点 | 变更类型 | 涉及类 | +|------|--------|----------|--------| +| 3.1 | 新增反向通知通道 | 新增 | `ZnsNotificationController`, `ZnsNotificationCommands` | +| 3.2 | Add-CM 流程重写 | 修改+新增 | `ZnsNotificationController.AddComputeManagerHandler`, `ZnsSdnController` | +| 3.3 | 移除 Flow 5 `create-l2-l3-from-segments` | **删除** | `ZnsSdnController.initSdnController` | +| 3.4 | 首次同步(Wizard Init Sync) | 新增 | `ZnsNotificationController.WizardInitSyncHandler` | +| 3.5 | 租户资源建模 | 新增 | `ZnsTenantVO`, `ZnsTenantRouterVO`, `ZnsTenantInventory`, `ZnsTenantRouterInventory` | +| 3.6 | SystemTag 变更 | 修改 | `ZnsSdnControllerSystemTags` | +| 3.7 | ZnsApiInterceptor VPC 支持 | 修改 | `ZnsApiInterceptor` | +| 3.8 | VM NIC 类型计算 | 修改 | `VmNicManagerImpl.computeVmNicType` | +| 3.9 | DPDK NIC 生命周期 | 新增 | `KVMRealizeL2GeneveNetworkBackend`, `KVMAgentCommands` | +| 3.10 | Reconcile SoT 拆分 | 重构 | `ZnsSdnController.reconnectSdnController` | +| 3.11 | 运行时推送通知处理 | 新增 | `SyncFabricHandler`, `SyncResourceHandler` | +| 3.12 | DHCP/DNS/MTU 完整性 | 验证+小修 | `ZnsSdnControllerDhcp` | +| 3.13 | 双栈 IpRange | 验证 | `ZnsSdnControllerL3` | +| 3.14 | 新增错误码 | 新增 | `ZnsErrors` | + +--- + +## 4. 详细设计 + +### 4.1 反向通知通道 + +#### 4.1.1 设计说明 + +当前 ZNS 插件只有 `/zns/callback` 处理异步任务回调。新增业务事件推送通道,支持 ZNS → Cloud 的主动通知,实现推送模型替代拉取模型。 + +**HTTP 机制选型**:ZNS 是外部系统,HTTP 请求不携带 ZStack 内部 `commandpath` 路由头,因此**不能**使用 `RESTFacade.registerSyncHttpCallHandler`(该机制仅适用于 ZStack 内部 Agent 协议)。改用 Spring `@Controller` + `@RequestMapping`,与现有 `ZnsCallbackController` 保持一致。 + +所有端点不做鉴权(Phase 1 依赖网络隔离),预留鉴权钩子供后续版本升级(Phase 2 计划 HMAC 签名验证)。 + +#### 4.1.2 新增类:`ZnsNotificationController` + +**包路径**:`org.zstack.network.zns` + +```java +@Controller +@Component +public class ZnsNotificationController { + + @Autowired + private DatabaseFacade dbf; + @Autowired + private EventFacade evtf; // P0-2: 必需,AddComputeManagerHandler 触发规范事件 + @Autowired + private ZnsApiClient znsApiClient; // P0-2: 必需,SyncResourceHandler 拉取资源详情 + @Autowired + private CloudBus bus; + @Autowired + private ThreadFacade thdf; + + @RequestMapping( + value = ZnsConstant.ZNS_NOTIFY_ADD_COMPUTE_MANAGER_PATH, + method = RequestMethod.POST, + produces = MediaType.APPLICATION_JSON_VALUE) + @ResponseBody + public String handleAddComputeManager( + @RequestBody ZnsNotificationCommands.AddComputeManagerNotification cmd) { + return new AddComputeManagerHandler().handle(cmd); + } + + @RequestMapping( + value = ZnsConstant.ZNS_NOTIFY_WIZARD_INIT_SYNC_PATH, + method = RequestMethod.POST, + produces = MediaType.APPLICATION_JSON_VALUE) + @ResponseBody + public String handleWizardInitSync( + @RequestBody ZnsNotificationCommands.WizardInitSyncNotification cmd) { + return new WizardInitSyncHandler().handle(cmd); + } + + @RequestMapping( + value = ZnsConstant.ZNS_NOTIFY_SYNC_FABRIC_PATH, + method = RequestMethod.POST, + produces = MediaType.APPLICATION_JSON_VALUE) + @ResponseBody + public String handleSyncFabric( + @RequestBody ZnsNotificationCommands.SyncFabricNotification cmd) { + return new SyncFabricHandler().handle(cmd); + } + + @RequestMapping( + value = ZnsConstant.ZNS_NOTIFY_SYNC_RESOURCE_PATH, + method = RequestMethod.POST, + produces = MediaType.APPLICATION_JSON_VALUE) + @ResponseBody + public String handleSyncResource( + @RequestBody ZnsNotificationCommands.SyncResourceNotification cmd) { + return new SyncResourceHandler().handle(cmd); + } + + /** 鉴权预留钩子,Phase 1 直接返回,Phase 2 验证 HMAC 签名 */ + private void validateRequest(HttpServletRequest req, String controllerUuid) { + // reserved: no-op in phase 1 + } + + /** 根据 computerManagerUuid 系统标签查找 SdnControllerVO */ + private SdnControllerVO findControllerByComputerManagerUuid(String computerManagerUuid) { + String tagPattern = ZnsSdnControllerSystemTags.COMPUTER_MANAGER_UUID + .instantiateTag(map(e( + ZnsSdnControllerSystemTags.COMPUTER_MANAGER_UUID_TOKEN, computerManagerUuid + ))); + List controllerUuids = Q.New(SystemTagVO.class) + .select(SystemTagVO_.resourceUuid) + .eq(SystemTagVO_.tag, tagPattern) + .eq(SystemTagVO_.resourceType, SdnControllerVO.class.getSimpleName()) + .listValues(); + if (controllerUuids.isEmpty()) { + return null; + } + return dbf.findByUuid(controllerUuids.get(0), SdnControllerVO.class); + } + + /** 在事务内完成 SdnControllerVO + ZnsControllerVO + SystemTag 的原子创建,返回 controllerUuid */ + @Transactional + private String persistNewController(ZnsNotificationCommands.AddComputeManagerNotification cmd) { + SdnControllerVO sdnVo = new SdnControllerVO(); + sdnVo.setUuid(Platform.getUuid()); + sdnVo.setName(cmd.name); + sdnVo.setDescription(cmd.description); + sdnVo.setIp(cmd.vip); + sdnVo.setUsername(cmd.account); + sdnVo.setPassword(cmd.password); + sdnVo.setVendorType(ZnsSdnControllerFactory.ZNS_TYPE); + sdnVo.setStatus(SdnControllerStatus.Connected); + dbf.getEntityManager().persist(sdnVo); + + ZnsControllerVO znsVo = new ZnsControllerVO(); + znsVo.setUuid(sdnVo.getUuid()); + dbf.getEntityManager().persist(znsVo); + + ZnsSdnControllerSystemTags.COMPUTER_MANAGER_UUID.createInherentTag( + sdnVo.getUuid(), + map(e(ZnsSdnControllerSystemTags.COMPUTER_MANAGER_UUID_TOKEN, cmd.computerManagerUuid)) + ); + + return sdnVo.getUuid(); + } + + // 内部 Handler 类见 §4.2 ~ §4.4 / §4.10 + class AddComputeManagerHandler { ... } + class WizardInitSyncHandler { ... } + class SyncFabricHandler { ... } + class SyncResourceHandler { ... } +} +``` + +**新增常量**(`ZnsConstant.java`): + +```java +public static final String ZNS_NOTIFY_ADD_COMPUTE_MANAGER_PATH = "/zns/notify/add-compute-manager"; +public static final String ZNS_NOTIFY_WIZARD_INIT_SYNC_PATH = "/zns/notify/wizard-init-sync"; +public static final String ZNS_NOTIFY_SYNC_FABRIC_PATH = "/zns/notify/sync-fabric"; +public static final String ZNS_NOTIFY_SYNC_RESOURCE_PATH = "/zns/notify/sync-resource"; +``` + +#### 4.1.3 新增类:`ZnsNotificationCommands` + +**包路径**:`org.zstack.network.zns` + +```java +public class ZnsNotificationCommands { + + /** ZNS wizard 完成 addComputeManager 后推送给 Cloud */ + public static class AddComputeManagerNotification { + /** ZNS VIP,后续 API 调用使用 */ + public String vip; + /** ZNS 管理员账号 */ + public String account; + /** ZNS 管理员密码 */ + public String password; + /** ZNS 侧 computerManager UUID */ + public String computerManagerUuid; + /** 人类可读名称 */ + public String name; + public String description; + } + + /** ZNS wizard 创建第一个 T1(租户路由器)后推送给 Cloud */ + public static class WizardInitSyncNotification { + public String computerManagerUuid; + } + + /** 传输区域/节点/Host-Switch 配置变更时推送 */ + public static class SyncFabricNotification { + public String computerManagerUuid; + /** + * 同步范围:ALL | FABRIC | TENANT,默认 ALL + * ALL - 全量同步设备资源(TZ+TN+Tenant+TenantRouter) + * FABRIC - 仅同步传输层资源(TransportZone + TransportNode + HostSwitch) + * TENANT - 仅同步租户资源(Tenant + TenantRouter) + * + * 注:不直接暴露 ZNS 内部术语(TZ/TN/HOSTSWITCH),使用 Cloud 视角抽象值。 + */ + public String scope; + } + + /** Segment 或 TenantRouter 创建/更新/删除时推送 */ + public static class SyncResourceNotification { + public String computerManagerUuid; + /** SEGMENT | TENANT_ROUTER */ + public String resourceType; + /** CREATE | UPDATE | DELETE */ + public String action; + /** ZNS 侧资源 UUID(dashed 格式) */ + public String resourceUuid; + } + + /** 通用响应 */ + public static class NotificationResponse { + public boolean success; + public String uuid; + public String error; + } +} +``` + +--- + +### 4.2 Add-CM 流程重写 + +#### 4.2.1 设计说明 + +**旧流程**(主动模式):Cloud 调用 `preInitSdnController` → 向 ZNS 发起 `verifyComputeManager` → 拉取集群信息 → 建档。 + +**新流程**(被动模式):ZNS wizard 完成后调用 `POST /zns/notify/add-compute-manager` → Cloud 接收通知 → 直接建档 → 返回 controller UUID 给 ZNS。 + +**向后兼容**:保留现有 `APIAddSdnControllerMsg` + `preInitSdnController` 作为手动补录通道,在常量中记录废弃说明。 + +#### 4.2.2 `AddComputeManagerHandler.handle` + +```java +class AddComputeManagerHandler { + + public String handle(ZnsNotificationCommands.AddComputeManagerNotification cmd) { + + // 1. 幂等检查:同 computerManagerUuid 已存在则直接返回现有 UUID(幂等语义,而非报错) + // 真正的业务唯一键是 computerManagerUuid,name 可能变化,不作唯一性依据。 + SdnControllerVO existing = findControllerByComputerManagerUuid(cmd.computerManagerUuid); + if (existing != null) { + return JSONObjectUtil.toJsonString(result(true, existing.getUuid(), null)); + } + + // 2-4. 在同一事务内原子创建 SdnControllerVO + ZnsControllerVO + SystemTag + // 避免部分写入导致的孤岛记录。 + String controllerUuid = persistNewController(cmd); + + // 5. 发送规范事件 SDN_CONTROLLER_ADDED(evtf 已在外部类注入) + SdnControllerVO created = dbf.findByUuid(controllerUuid, SdnControllerVO.class); + SdnControllerCanonicalEvents.SdnControllerAddedData evtData = + new SdnControllerCanonicalEvents.SdnControllerAddedData(); + evtData.setControllerUuid(controllerUuid); + evtData.setInventory(SdnControllerInventory.valueOf(created)); + evtf.fire(SdnControllerCanonicalEvents.SDN_CONTROLLER_ADDED, evtData); + + // 注:password 字段在日志打印时必须脱敏,不得原文输出到 debug log。 + logger.debug(String.format("[add-compute-manager] SDN controller[uuid:%s] created " + + "for computerManagerUuid[%s]", controllerUuid, cmd.computerManagerUuid)); + + // 6. 返回 controller UUID + return JSONObjectUtil.toJsonString(result(true, controllerUuid, null)); + } + + private ZnsNotificationCommands.NotificationResponse result( + boolean success, String uuid, String error) { + ZnsNotificationCommands.NotificationResponse r = + new ZnsNotificationCommands.NotificationResponse(); + r.success = success; + r.uuid = uuid; + r.error = error; + return r; + } +} +``` + +> **事务边界**:步骤 2-4 由外部类的 `persistNewController(@Transactional)` 方法完成,三步 persist 在同一事务内。若任意一步失败则全部回滚,无孤岛记录残留。 + +#### 4.2.3 `initSdnController` 清理(移除 Flow 5) + +在 `ZnsSdnController.initSdnController` 中,删除 Flow 5 `create-l2-l3-from-segments`。 + +**变更前**(5 个 Flow): +```text +Flow 1: sync-compute-collections +Flow 2: fetch-discovered-nodes +Flow 3: derive-vswitch-and-create-host-refs +Flow 4: persist-transport-zones +Flow 5: create-l2-l3-from-segments ← 删除此 Flow +``` + +**变更后**(4 个 Flow): +```text +Flow 1: sync-compute-collections +Flow 2: fetch-discovered-nodes +Flow 3: derive-vswitch-and-create-host-refs +Flow 4: persist-transport-zones +``` + +`initSdnController` 职责明确为**设备同步**,不再做 L2/L3 反向导入。 + +**向后兼容常量**(`ZnsSdnControllerConstant.java`): + +```java +/** + * 手动添加 SdnController 的 API 路径已废弃,保留以支持遗留脚本。 + * 新流程:ZNS wizard 完成后调用 POST /zns/notify/add-compute-manager 自动建档。 + * 将在 ZStack v5.1 移除手动路径。 + */ +@Deprecated +public static final String MANUAL_ADD_DEPRECATION_NOTE = + "APIAddSdnControllerMsg for ZNS is deprecated since v5.0; " + + "use ZNS wizard push-notification flow instead."; +``` + +--- + +### 4.3 首次同步(Wizard Init Sync) + +#### 4.3.1 设计说明 + +ZNS wizard 创建第一个 T1(租户路由器)后,调用 `POST /zns/notify/wizard-init-sync`。Cloud 触发全量 ZNS 数据拉取,同时对"Cloud 无对应 L2 的 ZNS 孤儿 Segment"执行强制删除(Cloud-as-SoT 语义)。 + +#### 4.3.2 `WizardInitSyncHandler.handle` + +```java +class WizardInitSyncHandler { + + public String handle(ZnsNotificationCommands.WizardInitSyncNotification cmd) { + + SdnControllerVO controller = findControllerByComputerManagerUuid(cmd.computerManagerUuid); + if (controller == null) { + // P1-1: 返回结构化错误响应,不抛异常(ZNS 需能解析响应体) + ZnsNotificationCommands.NotificationResponse resp = + new ZnsNotificationCommands.NotificationResponse(); + resp.success = false; + resp.error = String.format( + "no SDN controller found for computerManagerUuid[%s]", + cmd.computerManagerUuid); + return JSONObjectUtil.toJsonString(resp); + } + + String controllerUuid = controller.getUuid(); + String znsIp = controller.getIp(); + + FlowChain chain = FlowChainBuilder.newSimpleFlowChain(); + chain.setName(String.format("zns-wizard-init-sync-%s", controllerUuid)); + chain.allowEmptyFlow(); + + // Flow 1: 从 ZNS 同步 TransportZone(ZNS-as-SoT) + chain.then(new NoRollbackFlow() { + String __name__ = "sync-transport-zones-zns-as-sot"; + @Override + public void run(FlowTrigger trigger, Map data) { + syncTransportZonesFromZns(znsIp, controllerUuid, new Completion(trigger) { + @Override public void success() { trigger.next(); } + @Override public void fail(ErrorCode err) { trigger.fail(err); } + }); + } + }); + + // Flow 2: 从 ZNS 同步 TransportNode / Host Refs(ZNS-as-SoT) + chain.then(new NoRollbackFlow() { + String __name__ = "sync-transport-nodes-zns-as-sot"; + @Override + public void run(FlowTrigger trigger, Map data) { + syncTransportNodesFromZns(znsIp, controllerUuid, new Completion(trigger) { + @Override public void success() { trigger.next(); } + @Override public void fail(ErrorCode err) { trigger.fail(err); } + }); + } + }); + + // Flow 3: 从 ZNS 同步 Tenant(ZNS-as-SoT,若 ZNS 暂无租户 API 则 skip) + chain.then(new NoRollbackFlow() { + String __name__ = "sync-tenants-zns-as-sot"; + @Override + public void run(FlowTrigger trigger, Map data) { + syncTenantsFromZns(znsIp, controllerUuid, new Completion(trigger) { + @Override public void success() { trigger.next(); } + @Override public void fail(ErrorCode err) { + // 租户 API 缺失时降级跳过,记录 warning 日志 + logger.warn(String.format( + "[zns-wizard-init-sync] tenant API not available " + + "for controller[uuid:%s], skipping", controllerUuid)); + trigger.next(); + } + }); + } + }); + + // Flow 4: 从 ZNS 同步 TenantRouter(ZNS-as-SoT) + chain.then(new NoRollbackFlow() { + String __name__ = "sync-tenant-routers-zns-as-sot"; + @Override + public void run(FlowTrigger trigger, Map data) { + syncTenantRoutersFromZns(znsIp, controllerUuid, new Completion(trigger) { + @Override public void success() { trigger.next(); } + @Override public void fail(ErrorCode err) { trigger.fail(err); } + }); + } + }); + + // Flow 5: 清理孤儿 Segment(Cloud-as-SoT) + chain.then(new NoRollbackFlow() { + String __name__ = "cleanup-orphan-segments"; + @Override + public void run(FlowTrigger trigger, Map data) { + cleanupOrphanSegments(znsIp, controllerUuid, new Completion(trigger) { + @Override public void success() { trigger.next(); } + @Override public void fail(ErrorCode err) { + // 孤儿清理失败不阻断主流程,记录 warning + logger.warn(String.format( + "[zns-wizard-init-sync] orphan segment cleanup failed " + + "for controller[uuid:%s]: %s", controllerUuid, err.getDetails())); + trigger.next(); + } + }); + } + }); + + chain.done(new FlowDoneHandler(null) { + @Override public void handle(Map data) { + logger.info(String.format( + "[zns-wizard-init-sync] completed for controller[uuid:%s]", controllerUuid)); + } + }).error(new FlowErrorHandler(null) { + @Override public void handle(ErrorCode err, Map data) { + logger.error(String.format( + "[zns-wizard-init-sync] failed for controller[uuid:%s]: %s", + controllerUuid, err.getDetails())); + } + }).start(); + + // 202 Accepted 语义:FlowChain 异步执行,立即返回"已受理"。 + // ZNS 不应假设 Cloud 同步已完成;若需确认同步结果,可在后续操作前 + // 查询 Cloud 的 TenantRouter 列表,或等待 reconnectSdnController 周期补偿。 + ZnsNotificationCommands.NotificationResponse resp = + new ZnsNotificationCommands.NotificationResponse(); + resp.success = true; + return JSONObjectUtil.toJsonString(resp); + } +} +``` + +#### 4.3.3 孤儿 Segment 清理逻辑 + +```java +private void cleanupOrphanSegments(String znsIp, String controllerUuid, + Completion completion) { + // 1. 从 ZNS 拉取该 computerManager 下的所有 Segment 列表 + // 必须携带 computerManagerUuid 过滤参数,避免拉取其他 CM 下的 Segment 导致误删。 + String computerManagerUuid = ZnsSdnControllerSystemTags.COMPUTER_MANAGER_UUID + .getTokenByResourceUuid(controllerUuid, + ZnsSdnControllerSystemTags.COMPUTER_MANAGER_UUID_TOKEN); + znsApiClient.listSegments(znsIp, computerManagerUuid, + new ReturnValueCompletion>(completion) { + @Override + public void success(List znsSegments) { + // 2. 对每个 ZNS Segment:检查 Cloud 是否有对应的 L2 + // 判据:systemTag znsSegmentUuid::{segmentUuid} 存在于 L2NetworkVO + List orphanExternalUuids = new ArrayList<>(); + for (ZnsApiCommands.SegmentData seg : znsSegments) { + String tagValue = ZnsSdnControllerSystemTags.ZNS_SEGMENT_UUID + .instantiateTag(map(e( + ZnsSdnControllerSystemTags.ZNS_SEGMENT_UUID_TOKEN, seg.uuid + ))); + boolean cloudHasL2 = Q.New(SystemTagVO.class) + .eq(SystemTagVO_.tag, tagValue) + .eq(SystemTagVO_.resourceType, L2NetworkVO.class.getSimpleName()) + .isExists(); + if (!cloudHasL2) { + orphanExternalUuids.add(seg.uuid); + } + } + + // 3. 批量删除孤儿 Segment(force=true 忽略 ZNS 侧依赖) + new While<>(orphanExternalUuids).each((segUuid, whileCompletion) -> { + znsApiClient.deleteSegment(znsIp, segUuid, true, + new Completion(whileCompletion) { + @Override public void success() { whileCompletion.done(); } + @Override public void fail(ErrorCode err) { + logger.warn(String.format( + "[cleanup-orphan-segments] failed to delete ZNS segment[uuid:%s]: %s", + segUuid, err.getDetails())); + whileCompletion.done(); // 单条失败不阻断 + } + }); + }).run(new NoErrorCompletion(completion) { + @Override public void done() { completion.success(); } + }); + } + + @Override + public void fail(ErrorCode err) { completion.fail(err); } + }); +} +``` + +--- + +### 4.4 租户资源建模 + +#### 4.4.1 `ZnsTenantVO` + +**包路径**:`org.zstack.network.zns` + +```java +@Entity +@Table(name = "ZnsTenantVO") +public class ZnsTenantVO extends ResourceVO { + + @Column(nullable = false) + private String sdnControllerUuid; + + @Column(nullable = false, length = 64) + private String externalUuid; // ZNS 侧 tenant UUID(dashed 格式) + + @Column(nullable = false) + private String name; + + @Column(length = 2048) + private String description; + + @Temporal(TemporalType.TIMESTAMP) + @Column(nullable = false) + private Timestamp createDate; + + @Temporal(TemporalType.TIMESTAMP) + @Column(nullable = false) + private Timestamp lastOpDate; + + // getter/setter 省略(使用 Lombok @Data 或手写均可) +} +``` + +**Flyway DDL**(文件名:`V5.0.x__ZnsTenantVO.sql`): + +```sql +CREATE TABLE IF NOT EXISTS `ZnsTenantVO` ( + `uuid` CHAR(32) NOT NULL, + `sdnControllerUuid` CHAR(32) NOT NULL, + `externalUuid` VARCHAR(64) NOT NULL COMMENT 'ZNS tenant UUID (dashed format)', + `name` VARCHAR(255) NOT NULL, + `description` VARCHAR(2048) DEFAULT NULL, + `createDate` DATETIME NOT NULL, + `lastOpDate` DATETIME NOT NULL, + PRIMARY KEY (`uuid`), + UNIQUE KEY `uidx_externalUuid` (`externalUuid`), + KEY `idx_sdnControllerUuid` (`sdnControllerUuid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; +``` + +**Inventory 类**:`ZnsTenantInventory` + +```java +@InventoryDoc( + spec = @InventoryDocSpec( + inventory = "ZnsTenantInventory", + tableNames = {"ZnsTenantVO"} + ) +) +public class ZnsTenantInventory { + public String uuid; + public String sdnControllerUuid; + public String externalUuid; + public String name; + public String description; + public Timestamp createDate; + public Timestamp lastOpDate; + + public static ZnsTenantInventory valueOf(ZnsTenantVO vo) { + ZnsTenantInventory inv = new ZnsTenantInventory(); + inv.uuid = vo.getUuid(); + inv.sdnControllerUuid = vo.getSdnControllerUuid(); + inv.externalUuid = vo.getExternalUuid(); + inv.name = vo.getName(); + inv.description = vo.getDescription(); + inv.createDate = vo.getCreateDate(); + inv.lastOpDate = vo.getLastOpDate(); + return inv; + } +} +``` + +**ZNS API 响应 DTO**(添加到 `ZnsApiCommands.java`): + +```java +public static class TenantData { + public String uuid; // ZNS dashed UUID + public String name; + public String description; +} +``` + +#### 4.4.2 `ZnsTenantRouterVO` + +```java +@Entity +@Table(name = "ZnsTenantRouterVO") +public class ZnsTenantRouterVO extends ResourceVO { + + @Column(nullable = false) + private String sdnControllerUuid; + + @Column(nullable = false, length = 64) + private String externalUuid; // ZNS 侧 tenant router UUID(dashed 格式) + + @Column + private String tenantUuid; // 可选 FK → ZnsTenantVO.uuid + + @Column(nullable = false) + private String name; + + @Column(length = 2048) + private String description; + + @Temporal(TemporalType.TIMESTAMP) + @Column(nullable = false) + private Timestamp createDate; + + @Temporal(TemporalType.TIMESTAMP) + @Column(nullable = false) + private Timestamp lastOpDate; +} +``` + +**Flyway DDL**(文件名:`V5.0.x__ZnsTenantRouterVO.sql`): + +```sql +CREATE TABLE IF NOT EXISTS `ZnsTenantRouterVO` ( + `uuid` CHAR(32) NOT NULL, + `sdnControllerUuid` CHAR(32) NOT NULL, + `externalUuid` VARCHAR(64) NOT NULL COMMENT 'ZNS tenant router UUID (dashed format)', + `tenantUuid` CHAR(32) DEFAULT NULL COMMENT 'FK to ZnsTenantVO, nullable', + `name` VARCHAR(255) NOT NULL, + `description` VARCHAR(2048) DEFAULT NULL, + `createDate` DATETIME NOT NULL, + `lastOpDate` DATETIME NOT NULL, + PRIMARY KEY (`uuid`), + UNIQUE KEY `uidx_externalUuid` (`externalUuid`), + KEY `idx_sdnControllerUuid` (`sdnControllerUuid`), + KEY `idx_tenantUuid` (`tenantUuid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; +``` + +**Inventory 类**:`ZnsTenantRouterInventory` + +```java +@InventoryDoc( + spec = @InventoryDocSpec( + inventory = "ZnsTenantRouterInventory", + tableNames = {"ZnsTenantRouterVO"} + ) +) +public class ZnsTenantRouterInventory { + public String uuid; + public String sdnControllerUuid; + public String externalUuid; + public String tenantUuid; + public String name; + public String description; + public Timestamp createDate; + public Timestamp lastOpDate; + + public static ZnsTenantRouterInventory valueOf(ZnsTenantRouterVO vo) { + ZnsTenantRouterInventory inv = new ZnsTenantRouterInventory(); + inv.uuid = vo.getUuid(); + inv.sdnControllerUuid = vo.getSdnControllerUuid(); + inv.externalUuid = vo.getExternalUuid(); + inv.tenantUuid = vo.getTenantUuid(); + inv.name = vo.getName(); + inv.description = vo.getDescription(); + inv.createDate = vo.getCreateDate(); + inv.lastOpDate = vo.getLastOpDate(); + return inv; + } +} +``` + +**Query API**: + +```java +// APIQueryZnsTenantRouterMsg.java +@Action(category = SdnControllerConstant.ACTION_CATEGORY, names = {"read"}) +public class APIQueryZnsTenantRouterMsg + extends APIQueryMessage implements APISyncCallMessage { + + public static List __example__() { + return list("uuid=" + uuid()); + } +} + +// APIQueryZnsTenantRouterReply.java +public class APIQueryZnsTenantRouterReply + extends APIQueryReply { + public List inventories; +} +``` + +**ZNS API 响应 DTO**(添加到 `ZnsApiCommands.java`): + +```java +public static class TenantRouterData { + public String uuid; // ZNS dashed UUID + public String name; + public String tenant_uuid; // ZNS 侧 tenant UUID(dashed 格式) + public String description; +} +``` + +**ZNS API Client 新增方法**(`ZnsApiClient.java`): + +```java +/** + * 列出指定 ZNS 控制器下所有 TenantRouter + */ +void listTenantRouters( + String znsIp, + ReturnValueCompletion> completion +); + +/** + * 获取单个 TenantRouter 详情 + */ +void getTenantRouter( + String znsIp, + String externalUuid, + ReturnValueCompletion> completion +); +``` + +#### 4.4.3 限制删除租户路由器 + +在 `ZnsApiInterceptor` 中拦截 `APIDeleteZnsTenantRouterMsg`: + +```java +private void validate(APIDeleteZnsTenantRouterMsg msg) { + // 检查是否有 L3 通过 systemTag 引用此 TenantRouter + String tagPattern = ZnsSdnControllerSystemTags.ZNS_TENANT_ROUTER_UUID + .instantiateTag(map(e( + ZnsSdnControllerSystemTags.ZNS_TENANT_ROUTER_UUID_TOKEN, msg.getUuid() + ))); + List l3Uuids = Q.New(SystemTagVO.class) + .select(SystemTagVO_.resourceUuid) + .eq(SystemTagVO_.tag, tagPattern) + .eq(SystemTagVO_.resourceType, L3NetworkVO.class.getSimpleName()) + .listValues(); + if (!l3Uuids.isEmpty()) { + throw new ApiMessageInterceptionException( + ZnsErrors.operr(ZnsErrors.ZNS_TENANT_ROUTER_IN_USE, + "cannot delete tenant router[uuid:%s], L3 networks [%s] are still using it", + msg.getUuid(), String.join(", ", l3Uuids)) + ); + } +} +``` + +--- + +### 4.5 SystemTag 变更 + +#### 4.5.1 设计说明 + +`ENABLE_DPDK_VHOSTUSER` 是 L3 维度的 SystemTag,与业务语义不符(dpdk 是 VM 级别的 NIC 模式选择,而非网络属性)。新 Tag `znsNicMode` 改为 VM 维度,值为 `dpdk` 或 `kernel`。 + +此 Tag 是**新特性 Tag**,无历史数据,可直接重命名。保留旧 Tag 一个版本作为 fallback 读取。 + +#### 4.5.2 `ZnsSdnControllerSystemTags` 变更 + +```java +public class ZnsSdnControllerSystemTags { + + // ===== 已有 Tag(保持不变)===== + + /** computerManagerUuid 关联标签,挂在 SdnControllerVO 上 */ + public static final String COMPUTER_MANAGER_UUID_TOKEN = "computerManagerUuid"; + public static final PatternedSystemTag COMPUTER_MANAGER_UUID = new PatternedSystemTag( + String.format("computerManagerUuid::{%s}", COMPUTER_MANAGER_UUID_TOKEN), + SdnControllerVO.class + ); + + /** ZNS Segment UUID,挂在 L2NetworkVO 上 */ + public static final String ZNS_SEGMENT_UUID_TOKEN = "znsSegmentUuid"; + public static final PatternedSystemTag ZNS_SEGMENT_UUID = new PatternedSystemTag( + String.format("znsSegmentUuid::{%s}", ZNS_SEGMENT_UUID_TOKEN), + L2NetworkVO.class + ); + + // ===== 废弃(Deprecated)===== + + /** + * @deprecated 自 v5.0 起废弃,改为 VM 维度的 {@link #ZNS_NIC_MODE}。 + * 将在 v5.1 删除。仅作为读取 fallback,不再写入。 + */ + @Deprecated + public static final String ENABLE_DPDK_VHOSTUSER_TOKEN = "enableDpdkVhostuser"; + @Deprecated + public static final PatternedSystemTag ENABLE_DPDK_VHOSTUSER = new PatternedSystemTag( + String.format("enableDpdkVhostuser::{%s}", ENABLE_DPDK_VHOSTUSER_TOKEN), + L3NetworkVO.class + ); + + // ===== 新增 ===== + + /** + * VM 级别 NIC 模式标签,挂在 VmInstanceVO 上。 + * 取值:dpdk | kernel(缺省值为 kernel) + */ + public static final String ZNS_NIC_MODE_TOKEN = "mode"; + public static final PatternedSystemTag ZNS_NIC_MODE = new PatternedSystemTag( + String.format("znsNicMode::{%s}", ZNS_NIC_MODE_TOKEN), + VmInstanceVO.class + ); + + /** + * L3 VPC 网络关联的 TenantRouter UUID,挂在 L3NetworkVO 上。 + * 创建 VPC L3 时必须携带此 Tag。 + */ + public static final String ZNS_TENANT_ROUTER_UUID_TOKEN = "tenantRouterUuid"; + public static final PatternedSystemTag ZNS_TENANT_ROUTER_UUID = new PatternedSystemTag( + String.format("znsTenantRouterUuid::{%s}", ZNS_TENANT_ROUTER_UUID_TOKEN), + L3NetworkVO.class + ); +} +``` + +#### 4.5.3 NIC 模式读取兼容逻辑 + +```java +/** + * 读取 VM 的 ZNS NIC 模式,优先读新 Tag,fallback 读旧 L3 Tag。 + * @return "dpdk" | "kernel" + */ +public static String resolveZnsNicMode(String vmUuid, String l3Uuid) { + // 1. 优先读 VM 维度新 Tag + String newTag = ZnsSdnControllerSystemTags.ZNS_NIC_MODE + .getTokenByResourceUuid(vmUuid, ZnsSdnControllerSystemTags.ZNS_NIC_MODE_TOKEN); + if (newTag != null) { + return newTag; + } + + // 2. Fallback: 读旧 L3 维度 Tag(deprecated,v5.1 删除此分支) + String oldTag = ZnsSdnControllerSystemTags.ENABLE_DPDK_VHOSTUSER + .getTokenByResourceUuid(l3Uuid, + ZnsSdnControllerSystemTags.ENABLE_DPDK_VHOSTUSER_TOKEN); + if ("true".equalsIgnoreCase(oldTag)) { + return "dpdk"; + } + + // 3. 默认 kernel 模式 + return "kernel"; +} +``` + +--- + +### 4.6 ZnsApiInterceptor 更新 + +#### 4.6.1 VPC L3 支持 + +**文件**:`ZnsApiInterceptor.java` + +```java +private void validate(APICreateL3NetworkMsg msg) { + // 前置:获取 L2 上的 ZNS 控制器,非 ZNS L2 则直接放行 + if (!isZnsL2(msg.getL2NetworkUuid())) { + return; + } + + String type = msg.getType(); + + if (L3NetworkConstant.L3_BASIC_NETWORK_TYPE.equals(type)) { + // Flat 网络:无需额外要求 + + } else if (L3NetworkConstant.L3_VPC_NETWORK_TYPE.equals(type)) { + // VPC 网络:必须携带 znsTenantRouterUuid SystemTag + String tenantRouterUuid = extractTenantRouterUuidFromSystemTags(msg.getSystemTags()); + if (tenantRouterUuid == null) { + throw new ApiMessageInterceptionException( + ZnsErrors.argerr(ZnsErrors.ZNS_VPC_REQUIRES_TENANT_ROUTER_TAG, + "creating VPC L3Network on ZNS L2 requires systemTag " + + "znsTenantRouterUuid::{uuid}") + ); + } + // 验证 TenantRouter 存在 + boolean exists = Q.New(ZnsTenantRouterVO.class) + .eq(ZnsTenantRouterVO_.uuid, tenantRouterUuid) + .isExists(); + if (!exists) { + throw new ApiMessageInterceptionException( + ZnsErrors.argerr(ZnsErrors.ZNS_TENANT_ROUTER_NOT_FOUND, + "tenant router[uuid:%s] not found", tenantRouterUuid) + ); + } + + } else { + throw new ApiMessageInterceptionException( + ZnsErrors.argerr(ZnsErrors.ZNS_L3_TYPE_NOT_SUPPORTED, + "ZNS L2 only supports L3BasicNetwork or L3VpcNetwork, got type[%s]", type) + ); + } + + // Category 限制:拒绝 Public / System 类别 + if (msg.getCategory() != null) { + L3NetworkCategory cat = L3NetworkCategory.valueOf(msg.getCategory()); + if (cat == L3NetworkCategory.Public || cat == L3NetworkCategory.System) { + throw new ApiMessageInterceptionException( + ZnsErrors.argerr(ZnsErrors.ZNS_L3_CATEGORY_NOT_SUPPORTED, + "ZNS L2 does not support L3 category[%s]", cat) + ); + } + } +} + +/** 从 SystemTag 列表中提取 znsTenantRouterUuid 的值 */ +private String extractTenantRouterUuidFromSystemTags(List systemTags) { + if (systemTags == null) return null; + for (String tag : systemTags) { + if (ZnsSdnControllerSystemTags.ZNS_TENANT_ROUTER_UUID.isMatch(tag)) { + return ZnsSdnControllerSystemTags.ZNS_TENANT_ROUTER_UUID + .getTokenByTag(tag, ZnsSdnControllerSystemTags.ZNS_TENANT_ROUTER_UUID_TOKEN); + } + } + return null; +} +``` + +#### 4.6.2 新增 VM 创建拦截(ZNS NIC 模式校验) + +```java +private void validate(APICreateVmInstanceMsg msg) { + for (String l3Uuid : msg.getL3NetworkUuids()) { + if (!isZnsL3(l3Uuid)) { + continue; + } + + // 检查 VM systemTag 中的 znsNicMode + String nicMode = extractZnsNicModeFromSystemTags(msg.getSystemTags()); + if (nicMode != null && !"dpdk".equalsIgnoreCase(nicMode) + && !"kernel".equalsIgnoreCase(nicMode)) { + throw new ApiMessageInterceptionException( + ZnsErrors.argerr(ZnsErrors.ZNS_INVALID_NIC_MODE, + "invalid znsNicMode[%s], allowed values: dpdk | kernel", nicMode) + ); + } + + // DPDK 模式:尽力检查候选主机是否有 ZNS dpdk 能力 + if ("dpdk".equalsIgnoreCase(nicMode)) { + String controllerUuid = getZnsControllerUuidByL3(l3Uuid); + if (controllerUuid != null) { + boolean hasDpdkHost = Q.New(SdnControllerHostRefVO.class) + .eq(SdnControllerHostRefVO_.sdnControllerUuid, controllerUuid) + .isExists(); + if (!hasDpdkHost) { + throw new ApiMessageInterceptionException( + ZnsErrors.argerr(ZnsErrors.ZNS_DPDK_NO_CAPABLE_HOST, + "DPDK NIC requires at least one host managed by ZNS controller[uuid:%s]", + controllerUuid) + ); + } + } + } + } +} + +private String extractZnsNicModeFromSystemTags(List systemTags) { + if (systemTags == null) return null; + for (String tag : systemTags) { + if (ZnsSdnControllerSystemTags.ZNS_NIC_MODE.isMatch(tag)) { + return ZnsSdnControllerSystemTags.ZNS_NIC_MODE + .getTokenByTag(tag, ZnsSdnControllerSystemTags.ZNS_NIC_MODE_TOKEN); + } + } + return null; +} +``` + +--- + +### 4.7 VM NIC 类型计算 + +#### 4.7.1 设计说明 + +**文件**:`VmNicManagerImpl.java`(位于 network-service 或 vm 插件) + +方法 `computeVmNicType` 当前读取 L3 维度的 `ENABLE_DPDK_VHOSTUSER`,需改为读取 VM 维度的 `ZNS_NIC_MODE`,并保留旧 Tag fallback 读取逻辑(一个版本兼容窗口)。 + +#### 4.7.2 `computeVmNicType` 修改 + +> **赋值时机(P0-4)**:`computeVmNicType` 在 `VmNicManagerImpl.allocateNicForVm`(VM 创建流程的 NIC 分配步骤)中调用,结果写入 `VmNicVO.type` 并在同一事务内持久化。该步骤早于 `KVMRealizeL2GeneveNetworkBackend.realize()` 执行(realize 在后续 KVM 实现步骤中触发),因此 `nic.getType()` 在 `realize()` 入口处已有正确值。 +> +> 实现时须在 `realize()` 入口添加断言日志:`logger.debug("realize nic[uuid:{}] type={}", nic.getUuid(), nic.getType())`,以便集成测试可观测 NIC 类型是否正确传递。 + +```java +/** + * 计算 VM NIC 类型。 + * 对于 ZNS L2:优先读 VM 级别 znsNicMode Tag,fallback 到旧 L3 级别 enableDpdkVhostuser Tag。 + * + * @param vmUuid VM UUID + * @param l2Network L2 网络 Inventory + * @param l3Uuid L3 网络 UUID + * @return VmNicType + */ +public VmNicType computeVmNicType(String vmUuid, + L2NetworkInventory l2Network, + String l3Uuid) { + // 非 ZNS L2 走原有逻辑 + if (!ZnsSdnControllerFactory.ZNS_TYPE.equals(l2Network.getvSwitchType())) { + return defaultVmNicType(l2Network); + } + + // ZNS L2:读取 NIC 模式 + String nicMode = ZnsSdnControllerSystemTags.resolveZnsNicMode(vmUuid, l3Uuid); + + if ("dpdk".equalsIgnoreCase(nicMode)) { + // DPDK vhostuser 模式 + return VmNicType.valueOf(L2NetworkConstant.ACCEL_TYPE_VHOST_USER_SPACE); + } else { + // kernel 模式(默认) + return VmNicType.valueOf(VmInstanceConstant.VIRTUAL_NIC_TYPE); + } +} +``` + +--- + +### 4.8 DPDK NIC 生命周期 + +#### 4.8.1 设计说明 + +最小化路径:不引入新的 `VmNicLifecycle` 抽象框架,直接在 `KVMRealizeL2GeneveNetworkBackend` 中扩展,分支到 DPDK 路径。 + +Socket 路径约定:`/var/run/dpdk/vhost-{nicUuid}`(host 侧固定约定,避免传递配置)。 + +#### 4.8.2 新增 KVM Agent 命令(`KVMAgentCommands.java`) + +```java +// 准备 DPDK vhostuser socket +public static class PrepareDpdkNicCmd extends AgentCommand { + /** VM NIC UUID */ + public String vmNicUuid; + /** host 侧 socket 路径,约定为 /var/run/dpdk/vhost-{nicUuid} */ + public String socketPath; +} + +public static class PrepareDpdkNicResponse extends AgentResponse { + // 无额外字段,通用 success/error 通过 AgentResponse 携带 +} + +// 释放 DPDK vhostuser socket +public static class ReleaseDpdkNicCmd extends AgentCommand { + public String vmNicUuid; + public String socketPath; +} + +public static class ReleaseDpdkNicResponse extends AgentResponse {} +``` + +**KVM Agent 路径常量**(`KVMConstant.java`): + +```java +public static final String KVM_PREPARE_DPDK_NIC_PATH = "/prepareDpdkNic"; +public static final String KVM_RELEASE_DPDK_NIC_PATH = "/releaseDpdkNic"; +``` + +#### 4.8.3 `KVMRealizeL2GeneveNetworkBackend` 扩展 + +**`realize` 方法(VM 创建/启动时)**: + +```java +@Override +public void realize(L2NetworkInventory l2Network, String hostUuid, + VmNicInventory nic, Completion completion) { + // 1. 原有 ZNS port 同步逻辑(createSegmentPort/updateSegmentPort)保持不变 + doZnsPortSync(l2Network, hostUuid, nic, new Completion(completion) { + @Override + public void success() { + // P0-4: 断言日志,确认 NIC 类型在 realize() 前已正确写入 + logger.debug(String.format("realize nic[uuid:%s] type=%s", + nic.getUuid(), nic.getType())); + // 2. 根据 NIC 类型分支 + if (VmNicType.VHOSTUSER.toString().equals(nic.getType())) { + prepareDpdkNic(hostUuid, nic, completion); + } else { + // kernel 模式:libvirt 默认路径,无需额外操作 + completion.success(); + } + } + @Override + public void fail(ErrorCode err) { completion.fail(err); } + }); +} + +private void prepareDpdkNic(String hostUuid, VmNicInventory nic, + Completion completion) { + KVMAgentCommands.PrepareDpdkNicCmd cmd = new KVMAgentCommands.PrepareDpdkNicCmd(); + cmd.vmNicUuid = nic.getUuid(); + cmd.socketPath = String.format("/var/run/dpdk/vhost-%s", nic.getUuid()); + + kvmHostFactory.getConnector().sendCommand(hostUuid, + KVMConstant.KVM_PREPARE_DPDK_NIC_PATH, cmd, + KVMAgentCommands.PrepareDpdkNicResponse.class, + new ReturnValueCompletion(completion) { + @Override + public void success(KVMAgentCommands.PrepareDpdkNicResponse resp) { + if (!resp.isSuccess()) { + completion.fail(ZnsErrors.operr( + "failed to prepare DPDK NIC[uuid:%s] on host[uuid:%s]: %s", + nic.getUuid(), hostUuid, resp.getError())); + return; + } + completion.success(); + } + @Override + public void fail(ErrorCode err) { completion.fail(err); } + }); +} +``` + +**`releaseOnVmDestroy` 方法扩展(VM 销毁时)**: + +```java +@Override +public void releaseOnVmDestroy(L2NetworkInventory l2Network, VmInstanceInventory vm, + VmNicInventory nic, NoErrorCompletion completion) { + // 原有清理逻辑(deleteSegmentPort 等)保持不变 + doZnsPortRelease(l2Network, vm.getHostUuid(), nic, new NoErrorCompletion(completion) { + @Override + public void done() { + // DPDK 模式需要额外释放 socket + if (VmNicType.VHOSTUSER.toString().equals(nic.getType())) { + releaseDpdkNic(vm.getHostUuid(), nic, completion); + } else { + completion.done(); + } + } + }); +} + +private void releaseDpdkNic(String hostUuid, VmNicInventory nic, + NoErrorCompletion completion) { + KVMAgentCommands.ReleaseDpdkNicCmd cmd = new KVMAgentCommands.ReleaseDpdkNicCmd(); + cmd.vmNicUuid = nic.getUuid(); + cmd.socketPath = String.format("/var/run/dpdk/vhost-%s", nic.getUuid()); + + kvmHostFactory.getConnector().sendCommand(hostUuid, + KVMConstant.KVM_RELEASE_DPDK_NIC_PATH, cmd, + KVMAgentCommands.ReleaseDpdkNicResponse.class, + new ReturnValueCompletion(completion) { + @Override + public void success(KVMAgentCommands.ReleaseDpdkNicResponse resp) { + if (!resp.isSuccess()) { + // release 失败记录 warning,不阻断 VM 删除流程 + logger.warn(String.format( + "[release-dpdk-nic] failed to release DPDK NIC[uuid:%s] " + + "on host[uuid:%s]: %s", nic.getUuid(), hostUuid, resp.getError())); + } + completion.done(); // 无论成功失败都继续 + } + @Override + public void fail(ErrorCode err) { + logger.warn(String.format( + "[release-dpdk-nic] error releasing DPDK NIC[uuid:%s]: %s", + nic.getUuid(), err.getDetails())); + completion.done(); + } + }); +} +``` + +#### 4.8.4 OVS Kernel 路径验证要点 + +- `KVMRealizeL2GeneveNetworkBackend.realize` 中,当 `nic.getType()` 为 `NONE`(kernel)时,不应调用任何 dpdk 相关方法 +- 验证方式:单元测试 mock `VmNicVO.type = NONE`,断言 `PrepareDpdkNicCmd` 未被发送 +- **预期结论**:无代码改动,仅添加验证测试 + +--- + +### 4.9 Reconcile SoT 拆分 + +#### 4.9.1 设计说明 + +`reconnectSdnController` 原来是单一 FlowChain,将其重构为两个逻辑组: +- **Group A**(ZNS-as-SoT):设备资源(TZ、TN、Tenant、TenantRouter)从 ZNS 全量同步到 Cloud +- **Group B**(Cloud-as-SoT):Segment(L2/L3 对应的 ZNS Segment)由 Cloud 主导三路对比 + +#### 4.9.2 `syncDeviceResourcesFromZns` + +```java +/** + * Group A: ZNS-as-SoT 设备资源同步。 + * 执行顺序:TZ → TN → Tenant → TenantRouter + * 每一步:从 ZNS 拉取全量 → Upsert 到 DB → 删除 DB 中 ZNS 不存在的孤儿记录 + */ +private void syncDeviceResourcesFromZns(String controllerUuid, String znsIp, + String scope, Completion completion) { + FlowChain chain = FlowChainBuilder.newSimpleFlowChain(); + chain.setName(String.format("sync-device-resources-from-zns-%s", controllerUuid)); + chain.allowEmptyFlow(); + + if (shouldSync(scope, "TZ", "ALL")) { + chain.then(new NoRollbackFlow() { + String __name__ = "sync-transport-zones-zns-as-sot"; + @Override + public void run(FlowTrigger trigger, Map data) { + syncTransportZonesFromZns(znsIp, controllerUuid, new Completion(trigger) { + @Override public void success() { trigger.next(); } + @Override public void fail(ErrorCode err) { trigger.fail(err); } + }); + } + }); + } + + if (shouldSync(scope, "TN", "ALL")) { + chain.then(new NoRollbackFlow() { + String __name__ = "sync-transport-nodes-zns-as-sot"; + @Override + public void run(FlowTrigger trigger, Map data) { + syncTransportNodesFromZns(znsIp, controllerUuid, new Completion(trigger) { + @Override public void success() { trigger.next(); } + @Override public void fail(ErrorCode err) { trigger.fail(err); } + }); + } + }); + } + + if (shouldSync(scope, "ALL")) { + chain.then(new NoRollbackFlow() { + String __name__ = "sync-tenants-zns-as-sot"; + @Override + public void run(FlowTrigger trigger, Map data) { + syncTenantsFromZns(znsIp, controllerUuid, new Completion(trigger) { + @Override public void success() { trigger.next(); } + @Override public void fail(ErrorCode err) { + logger.warn("tenant API unavailable, skipping: " + err.getDetails()); + trigger.next(); + } + }); + } + }); + + chain.then(new NoRollbackFlow() { + String __name__ = "sync-tenant-routers-zns-as-sot"; + @Override + public void run(FlowTrigger trigger, Map data) { + syncTenantRoutersFromZns(znsIp, controllerUuid, new Completion(trigger) { + @Override public void success() { trigger.next(); } + @Override public void fail(ErrorCode err) { trigger.fail(err); } + }); + } + }); + } + + chain.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(); +} + +private boolean shouldSync(String scope, String... targets) { + if (scope == null || "ALL".equalsIgnoreCase(scope)) return true; + for (String t : targets) { + if (t.equalsIgnoreCase(scope)) return true; + } + return false; +} +``` + +> **scope 值映射**:`FABRIC` → TZ+TN;`TENANT` → Tenant+TenantRouter。 +> `shouldSync(scope, "TZ", "FABRIC")` 对 scope=FABRIC 返回 true,对 scope=TENANT 返回 false。 +``` + +#### 4.9.3 新 `reconnectSdnController` + +```java +@Override +public void reconnectSdnController(ReconnectSdnControllerMsg msg, NoErrorCompletion completion) { + SdnControllerVO controller = dbf.findByUuid(msg.getSdnControllerUuid(), SdnControllerVO.class); + String znsIp = controller.getIp(); + + FlowChain chain = FlowChainBuilder.newSimpleFlowChain(); + chain.setName(String.format("reconnect-zns-controller-%s", controller.getUuid())); + + // Group A: ZNS-as-SoT 设备资源 + chain.then(new NoRollbackFlow() { + String __name__ = "group-a-sync-device-resources"; + @Override + public void run(FlowTrigger trigger, Map data) { + syncDeviceResourcesFromZns(controller.getUuid(), znsIp, "ALL", + new Completion(trigger) { + @Override public void success() { trigger.next(); } + @Override public void fail(ErrorCode err) { + // Group A 失败记录日志但不阻断 Group B + logger.warn("[reconnect] Group A sync failed: " + err.getDetails()); + trigger.next(); + } + }); + } + }); + + // Group B: Cloud-as-SoT Segment 三路对比 + chain.then(new NoRollbackFlow() { + String __name__ = "group-b-reconcile-segments-cloud-as-sot"; + @Override + public void run(FlowTrigger trigger, Map data) { + reconcileSegmentsCloudAsSoT(controller.getUuid(), znsIp, + new Completion(trigger) { + @Override public void success() { trigger.next(); } + @Override public void fail(ErrorCode err) { trigger.fail(err); } + }); + } + }); + + chain.done(new FlowDoneHandler(null) { + @Override public void handle(Map data) { completion.done(); } + }).error(new FlowErrorHandler(null) { + @Override public void handle(ErrorCode err, Map data) { + logger.error("[reconnect] FlowChain failed: " + err.getDetails()); + completion.done(); + } + }).start(); +} +``` + +#### 4.9.4 TenantRouter 同步中的边界处理 + +`syncTenantRoutersFromZns` 内部的孤儿处理逻辑: + +```java +private void syncTenantRoutersFromZns(String znsIp, String controllerUuid, + Completion completion) { + znsApiClient.listTenantRouters(znsIp, + new ReturnValueCompletion>(completion) { + @Override + public void success(ListResponse resp) { + List znsRouters = resp.getResults(); + + // Upsert:ZNS 有 → 写入或更新 Cloud DB + Set znsExternalUuids = new HashSet<>(); + for (ZnsApiCommands.TenantRouterData rd : znsRouters) { + znsExternalUuids.add(rd.uuid); + upsertTenantRouter(controllerUuid, rd); + } + + // 孤儿处理:Cloud 有但 ZNS 无 + List cloudRouters = Q.New(ZnsTenantRouterVO.class) + .eq(ZnsTenantRouterVO_.sdnControllerUuid, controllerUuid) + .list(); + for (ZnsTenantRouterVO cloudRouter : cloudRouters) { + if (!znsExternalUuids.contains(cloudRouter.getExternalUuid())) { + handleOrphanTenantRouter(cloudRouter); + } + } + completion.success(); + } + @Override + public void fail(ErrorCode err) { completion.fail(err); } + }); +} + +private void handleOrphanTenantRouter(ZnsTenantRouterVO orphan) { + String tagPattern = ZnsSdnControllerSystemTags.ZNS_TENANT_ROUTER_UUID + .instantiateTag(map(e( + ZnsSdnControllerSystemTags.ZNS_TENANT_ROUTER_UUID_TOKEN, orphan.getUuid() + ))); + boolean l3InUse = Q.New(SystemTagVO.class) + .eq(SystemTagVO_.tag, tagPattern) + .eq(SystemTagVO_.resourceType, L3NetworkVO.class.getSimpleName()) + .isExists(); + + if (l3InUse) { + // 有 L3 引用:触发告警,不删除 + evtf.fire(ZnsCanonicalEvents.EVT_ZNS_TENANT_ROUTER_ORPHAN_IN_CLOUD, + new ZnsCanonicalEvents.TenantRouterOrphanData( + orphan.getUuid(), + String.format( + "ZNS deleted tenant router[uuid:%s] but Cloud VPC L3 networks " + + "still reference it. Please delete the L3 networks first.", + orphan.getUuid()) + )); + } else { + // 无引用:静默删除 + dbf.remove(orphan); + } +} +``` + +--- + +### 4.10 运行时推送通知处理 + +#### 4.10.1 `SyncFabricHandler` + +```java +class SyncFabricHandler { + + public String handle(ZnsNotificationCommands.SyncFabricNotification cmd) { + + SdnControllerVO controller = findControllerByComputerManagerUuid(cmd.computerManagerUuid); + if (controller == null) { + // P1-1: 返回结构化错误响应,不抛异常 + ZnsNotificationCommands.NotificationResponse errResp = + new ZnsNotificationCommands.NotificationResponse(); + errResp.success = false; + errResp.error = String.format( + "no SDN controller found for computerManagerUuid[%s]", + cmd.computerManagerUuid); + return JSONObjectUtil.toJsonString(errResp); + } + + String scope = cmd.scope != null ? cmd.scope : "ALL"; + final String controllerUuid = controller.getUuid(); + final String znsIp = controller.getIp(); + + // P1-2: 使用 per-controller 异步串行化队列,防止并发推送时 reconcile 竞争。 + // 同一 controllerUuid 的请求排队执行,不并发。 + thdf.chainSubmit(new ChainTask(null) { + @Override public String getSyncSignature() { + return String.format("zns-sync-fabric-%s", controllerUuid); + } + @Override public void run(SyncTaskChain chain) { + syncDeviceResourcesFromZns(controllerUuid, znsIp, scope, + new Completion(null) { + @Override public void success() { + logger.info(String.format("[sync-fabric] completed for " + + "controller[uuid:%s] scope[%s]", controllerUuid, scope)); + chain.next(); + } + @Override public void fail(ErrorCode err) { + logger.error(String.format("[sync-fabric] failed for " + + "controller[uuid:%s]: %s", controllerUuid, err.getDetails())); + chain.next(); + } + }); + } + @Override public String getName() { return getSyncSignature(); } + }); + + // 202 Accepted:已受理,异步执行 + ZnsNotificationCommands.NotificationResponse resp = + new ZnsNotificationCommands.NotificationResponse(); + resp.success = true; + return JSONObjectUtil.toJsonString(resp); + } +} +``` + +#### 4.10.2 `SyncResourceHandler` + +```java +class SyncResourceHandler { + + public String handle(ZnsNotificationCommands.SyncResourceNotification cmd) { + + SdnControllerVO controller = findControllerByComputerManagerUuid(cmd.computerManagerUuid); + if (controller == null) { + // P1-1: 结构化错误响应 + ZnsNotificationCommands.NotificationResponse errResp = + new ZnsNotificationCommands.NotificationResponse(); + errResp.success = false; + errResp.error = String.format( + "no SDN controller found for computerManagerUuid[%s]", + cmd.computerManagerUuid); + return JSONObjectUtil.toJsonString(errResp); + } + + final SdnControllerVO ctrl = controller; + + // P1-2: per-controller 串行化 + thdf.chainSubmit(new ChainTask(null) { + @Override public String getSyncSignature() { + return String.format("zns-sync-resource-%s", ctrl.getUuid()); + } + @Override public void run(SyncTaskChain chain) { + if ("TENANT_ROUTER".equalsIgnoreCase(cmd.resourceType)) { + handleTenantRouterEvent(ctrl, cmd, chain); + } else if ("SEGMENT".equalsIgnoreCase(cmd.resourceType)) { + handleSegmentEvent(ctrl, cmd, chain); + } else { + logger.warn(String.format("[sync-resource] unknown resourceType[%s], ignored", + cmd.resourceType)); + chain.next(); + } + } + @Override public String getName() { return getSyncSignature(); } + }); + + ZnsNotificationCommands.NotificationResponse resp = + new ZnsNotificationCommands.NotificationResponse(); + resp.success = true; + return JSONObjectUtil.toJsonString(resp); + } + + private void handleTenantRouterEvent(SdnControllerVO controller, + ZnsNotificationCommands.SyncResourceNotification cmd, + SyncTaskChain chain) { + if ("CREATE".equalsIgnoreCase(cmd.action) + || "UPDATE".equalsIgnoreCase(cmd.action)) { + znsApiClient.getTenantRouter(controller.getIp(), cmd.resourceUuid, + new ReturnValueCompletion>(null) { + @Override + public void success(GetResponse resp) { + upsertTenantRouter(controller.getUuid(), resp.getResult()); + chain.next(); + } + @Override + public void fail(ErrorCode err) { + logger.error(String.format( + "[sync-resource] failed to get tenant router[externalUuid:%s]: %s", + cmd.resourceUuid, err.getDetails())); + chain.next(); + } + }); + + } else if ("DELETE".equalsIgnoreCase(cmd.action)) { + ZnsTenantRouterVO vo = Q.New(ZnsTenantRouterVO.class) + .eq(ZnsTenantRouterVO_.externalUuid, cmd.resourceUuid) + .find(); + if (vo != null) { + handleOrphanTenantRouter(vo); + } + chain.next(); + } else { + chain.next(); + } + } + + private void handleSegmentEvent(SdnControllerVO controller, + ZnsNotificationCommands.SyncResourceNotification cmd, + SyncTaskChain chain) { + reconcileSegmentsCloudAsSoT(controller.getUuid(), controller.getIp(), + new Completion(null) { + @Override + public void success() { + logger.info(String.format("[sync-resource/segment] reconcile completed " + + "for controller[uuid:%s]", controller.getUuid())); + chain.next(); + } + @Override + public void fail(ErrorCode err) { + logger.error(String.format("[sync-resource/segment] reconcile failed " + + "for controller[uuid:%s]: %s", controller.getUuid(), err.getDetails())); + chain.next(); + } + }); + } +} +``` + +--- + +### 4.11 DHCP/DNS/MTU 完整性 + +#### 4.11.1 双栈 DHCP + +**文件**:`ZnsSdnControllerDhcp.java` + +**`enableDHCP` 验证要点**: + +```java +// 确认 buildDhcpConfig 同时处理 v4 和 v6 IpRange +private ZnsApiCommands.DhcpServiceConfig buildDhcpConfig( + String segmentUuid, L3NetworkInventory l3) { + + ZnsApiCommands.DhcpServiceConfig config = new ZnsApiCommands.DhcpServiceConfig(); + config.segmentUuid = segmentUuid; + + for (IpRangeInventory ipRange : l3.getIpRanges()) { + if (NetworkUtils.isIpv4Address(ipRange.getGateway())) { + // IPv4 配置 + config.gateway_address = ipRange.getGateway(); + config.subnet_mask = ipRange.getNetmask(); + // ... 其他 v4 字段 + } else { + // IPv6 配置 + config.gateway6_address = ipRange.getGateway(); + config.subnet6_prefix = ipRange.getPrefixLen(); + // ... 其他 v6 字段 + } + } + return config; +} +``` + +**边界场景:先启用 v4 DHCP,后添加 v6 IpRange**: + +在 `ZnsControllerManager.afterCreateIpRange` 中: + +```java +@Override +public void afterCreateIpRange(IpRangeInventory ipRange) { + // 若 L3 所在 L2 是 ZNS,且 DHCP 已启用,则触发 DHCP 服务更新 + L3NetworkVO l3 = dbf.findByUuid(ipRange.getL3NetworkUuid(), L3NetworkVO.class); + if (l3 == null || !isDhcpEnabled(l3.getUuid())) { + return; + } + if (!isZnsL3(l3.getUuid())) { + return; + } + SdnControllerUpdateDHCPMsg updateMsg = new SdnControllerUpdateDHCPMsg(); + updateMsg.setL3NetworkUuid(l3.getUuid()); + bus.makeLocalServiceId(updateMsg, SdnControllerConstant.SERVICE_ID); + bus.send(updateMsg); +} +``` + +#### 4.11.2 DNS 独立更新 + +`ZnsSdnControllerDhcp.updateDHCP` 在处理 DNS 变更时,只修改 `dns_servers` 字段: + +```java +private ZnsApiCommands.DhcpServicePatch buildDnsPatch(List dnsServers) { + ZnsApiCommands.DhcpServicePatch patch = new ZnsApiCommands.DhcpServicePatch(); + patch.dns_servers = dnsServers; + // 不包含 dhcp_configs(不改变 DHCP 启停状态) + return patch; +} +``` + +**验证要点**:`APIUpdateL3NetworkMsg` 变更 DNS → 调用 `SdnControllerUpdateDHCPMsg` → ZNS PATCH 只含 `dns_servers`,不触发 DHCP enable/disable。 + +#### 4.11.3 MTU 更新(已实现,验证) + +`ZnsControllerManager.afterSetL3NetworkMtu` → PATCH segment `{mtu: value}`。 + +验证:双栈 L3(同一 Segment)MTU 更新只需 PATCH 一次,两个 IpRange 共享同一 segmentUuid。 + +--- + +### 4.12 双栈 IpRange + +#### 4.12.1 设计说明 + +`ZnsSdnControllerL3.createIpRange` 已区分 v4/v6,分别设置 `gateway_address` / `gateway6_address`。需验证以下边界场景。 + +#### 4.12.2 验证矩阵 + +| 场景 | 预期行为 | 是否需要代码改动 | +|------|----------|-----------------| +| L3 仅有 v4 IpRange | PATCH segment 含 `gateway_address`,无 `gateway6_address` | 否 | +| L3 仅有 v6 IpRange | PATCH segment 含 `gateway6_address`,无 `gateway_address` | 否 | +| L3 同时有 v4 + v6 IpRange | PATCH segment 同时含两个字段,v4 不覆盖 v6 | 验证 | +| 添加 v6 后不覆盖 v4 | `createIpRange` 做 partial update(PATCH 非 PUT) | 验证 | +| 删除 v4,保留 v6 | v6 配置不受影响;若 DHCP 启用则拦截(ZnsApiInterceptor) | 验证 | + +**reconcile `needsSegmentUpdate` 需比较双栈字段**: + +```java +/** + * P1-3: gateway/MTU 是 L3/IpRange 层概念,不在 L2NetworkInventory 上。 + * 方法签名改为接受 L3NetworkInventory,从 IpRange 列表取 gateway 比较。 + */ +private boolean needsSegmentUpdate(ZnsApiCommands.SegmentData znsSegment, + L3NetworkInventory cloudL3) { + String gwV4 = null, gwV6 = null; + for (IpRangeInventory ipRange : cloudL3.getIpRanges()) { + if (NetworkUtils.isIpv4Address(ipRange.getGateway())) { + gwV4 = ipRange.getGateway(); + } else { + gwV6 = ipRange.getGateway(); + } + } + // 比较 v4 字段 + if (!Objects.equals(znsSegment.gateway_address, gwV4)) return true; + // 比较 v6 字段 + if (!Objects.equals(znsSegment.gateway6_address, gwV6)) return true; + // MTU 从 L3 的 systemTag 或 L2 基础属性取,ZStack 惯例通常存于 L3 层 tag + // 若 ZNS segment 携带 mtu 字段且 Cloud L3 有对应 tag,则比较 + return false; +} +``` + +--- + +### 4.13 告警事件(TenantRouter 孤儿) + +**新增规范事件常量**(`ZnsCanonicalEvents.java`): + +```java +public class ZnsCanonicalEvents { + + public static final String EVT_ZNS_TENANT_ROUTER_ORPHAN_IN_CLOUD = + "/zns/tenantRouter/orphanInCloud"; + + @EventDefinition + public static class TenantRouterOrphanData { + public String tenantRouterUuid; + public String message; + + public TenantRouterOrphanData(String uuid, String msg) { + this.tenantRouterUuid = uuid; + this.message = msg; + } + } +} +``` + +此事件可触发 Cloud 告警系统(AlarmManager)向运维人员发送通知。告警内容: + +> ZNS 侧已删除租户路由器 [uuid:%s],但 Cloud 中仍有 VPC L3 网络引用该路由器。请先删除对应的 L3 网络,再重新触发同步。 + +--- + +### 4.14 错误码 + +**文件**:`ZnsErrors.java`(或 `ZnsErrorCode.java`) + +```java +public interface ZnsErrors { + + // ===== 已有错误码(保持不变)===== + // ... + + // ===== 新增错误码 ===== + + /** VPC L3 在 ZNS L2 上必须携带 znsTenantRouterUuid systemTag */ + String ZNS_VPC_REQUIRES_TENANT_ROUTER_TAG = "ORG_ZSTACK_NETWORK_ZNS_10020"; + + /** 指定的租户路由器不存在 */ + String ZNS_TENANT_ROUTER_NOT_FOUND = "ORG_ZSTACK_NETWORK_ZNS_10021"; + + /** ZNS L2 不支持该 L3 类别(Public/System) */ + String ZNS_L3_CATEGORY_NOT_SUPPORTED = "ORG_ZSTACK_NETWORK_ZNS_10022"; + + /** 无法删除租户路由器,仍有 L3 网络引用 */ + String ZNS_TENANT_ROUTER_IN_USE = "ORG_ZSTACK_NETWORK_ZNS_10023"; + + /** 找不到对应 computerManagerUuid 的 SDN 控制器 */ + String ZNS_CONTROLLER_NOT_FOUND_FOR_CM_UUID = "ORG_ZSTACK_NETWORK_ZNS_10024"; + + /** DPDK NIC 需要有 ZNS dpdk 能力的主机 */ + String ZNS_DPDK_NO_CAPABLE_HOST = "ORG_ZSTACK_NETWORK_ZNS_10025"; + + /** L3 类型不被 ZNS L2 支持 */ + String ZNS_L3_TYPE_NOT_SUPPORTED = "ORG_ZSTACK_NETWORK_ZNS_10011"; + + // 工具方法(可直接调用) + static ErrorCode argerr(String code, String fmt, Object... args) { + return Platform.argerr(code, fmt, args); + } + + static ErrorCode operr(String code, String fmt, Object... args) { + return Platform.operr(code, fmt, args); + } +} +``` + +**错误码 i18n 文件**(`zns-errors.properties`): + +```properties +ORG_ZSTACK_NETWORK_ZNS_10020=在 ZNS L2 上创建 VPC 类型 L3 网络时,必须提供 systemTag [znsTenantRouterUuid::{uuid}] +ORG_ZSTACK_NETWORK_ZNS_10021=租户路由器 [uuid:{0}] 不存在 +ORG_ZSTACK_NETWORK_ZNS_10022=ZNS L2 不支持 L3 网络类别 [{0}],仅支持 Private +ORG_ZSTACK_NETWORK_ZNS_10023=无法删除租户路由器 [uuid:{0}],以下 L3 网络仍在引用:{1} +ORG_ZSTACK_NETWORK_ZNS_10024=找不到 computerManagerUuid [{0}] 对应的 SDN 控制器 +ORG_ZSTACK_NETWORK_ZNS_10025=DPDK NIC 模式需要至少一台由 ZNS 控制器 [uuid:{0}] 管理的主机 +``` + +--- + +## 5. 新增错误码清单 + +| 错误码 | 常量名 | 场景 | 类型 | +|--------|--------|------|------| +| `ORG_ZSTACK_NETWORK_ZNS_10020` | `ZNS_VPC_REQUIRES_TENANT_ROUTER_TAG` | 创建 VPC L3 未携带 TenantRouter Tag | argerr | +| `ORG_ZSTACK_NETWORK_ZNS_10021` | `ZNS_TENANT_ROUTER_NOT_FOUND` | 指定 TenantRouter 不存在 | argerr | +| `ORG_ZSTACK_NETWORK_ZNS_10022` | `ZNS_L3_CATEGORY_NOT_SUPPORTED` | L3 Category 不支持(Public/System) | argerr | +| `ORG_ZSTACK_NETWORK_ZNS_10023` | `ZNS_TENANT_ROUTER_IN_USE` | 删除 TenantRouter 时仍有 L3 引用 | operr | +| `ORG_ZSTACK_NETWORK_ZNS_10024` | `ZNS_CONTROLLER_NOT_FOUND_FOR_CM_UUID` | 反向通知时找不到控制器 | operr | +| `ORG_ZSTACK_NETWORK_ZNS_10025` | `ZNS_DPDK_NO_CAPABLE_HOST` | DPDK 模式无可用主机 | argerr | + +--- + +## 6. Flyway DDL 清单 + +| 文件名 | 内容 | 依赖 | +|--------|------|------| +| `V5.0.x__ZnsTenantVO.sql` | 创建 `ZnsTenantVO` 表 | 无 | +| `V5.0.x__ZnsTenantRouterVO.sql` | 创建 `ZnsTenantRouterVO` 表 | 无(tenantUuid 可为 NULL) | + +**注意事项**: +- Flyway 文件版本号 `5.0.x` 中的 `x` 需根据 ZStack 版本号规范确定具体序号 +- 两个表不设外键约束(ZStack 惯例,由应用层保证引用完整性) +- `externalUuid` 加 `UNIQUE KEY`,确保 ZNS 侧 UUID 不重复导入 + +--- + +## 7. SystemTag 变更清单 + +| 旧 Tag | 挂载维度 | 新 Tag | 挂载维度 | 变更类型 | 迁移说明 | +|--------|---------|--------|---------|---------|---------| +| `enableDpdkVhostuser::{enableDpdkVhostuser}` | `L3NetworkVO` | `znsNicMode::{mode}` | `VmInstanceVO` | 重命名 + 维度变更 | 新特性 Tag,无历史数据;旧 Tag 加 `@Deprecated`,保留一个 minor 版本作为 fallback 读取,v5.1 删除 | +| ——(新增)—— | —— | `znsTenantRouterUuid::{tenantRouterUuid}` | `L3NetworkVO` | 新增 | VPC L3 创建时必须携带 | + +--- + +## 8. 实现顺序建议 + +### Wave 1 — 基础数据模型(无业务依赖) + +| 任务 | 说明 | +|------|------| +| 创建 `ZnsTenantVO` + Flyway DDL | 基础 VO,不含业务逻辑 | +| 创建 `ZnsTenantRouterVO` + Flyway DDL | 基础 VO,不含业务逻辑 | +| `ZnsTenantInventory` / `ZnsTenantRouterInventory` | Inventory 类 | +| `APIQueryZnsTenantRouterMsg` / Reply | Query API | +| 更新 `ZnsSdnControllerSystemTags`(新增 `ZNS_NIC_MODE`, `ZNS_TENANT_ROUTER_UUID`,废弃旧 Tag) | 无运行时副作用 | +| 新增错误码(`ZnsErrors`) | 常量类,零依赖 | + +### Wave 2 — ZNS API Client 扩展 + +| 任务 | 说明 | +|------|------| +| `ZnsApiCommands.TenantData` / `TenantRouterData` DTO | 无业务逻辑 | +| `ZnsApiClient.listTenantRouters` | 新增接口方法 | +| `ZnsApiClient.getTenantRouter` | 新增接口方法 | + +### Wave 3 — 反向通知通道 + +| 任务 | 说明 | +|------|------| +| `ZnsNotificationCommands`(所有 Notification DTO) | 数据类 | +| `ZnsNotificationController`(Spring @Controller,4 个 @RequestMapping 端点) | 核心新增类 | +| `ZnsConstant` 新增 HTTP 路径常量 | 常量 | + +### Wave 4 — Add-CM / Wizard Init 流程 + +| 任务 | 说明 | +|------|------| +| `AddComputeManagerHandler` 实现 | 依赖 Wave 1/3 | +| `WizardInitSyncHandler` 实现(含 5 个 Flow) | 依赖 Wave 2/3 | +| `ZnsSdnController.initSdnController` 移除 Flow 5 | 手术式删除 | +| `ZnsSdnControllerConstant.MANUAL_ADD_DEPRECATION_NOTE` | 文档常量 | + +### Wave 5 — Reconcile 重构 + 运行时通知 + +| 任务 | 说明 | +|------|------| +| `syncDeviceResourcesFromZns`(提取为独立方法) | 依赖 Wave 2/4 | +| `syncTenantRoutersFromZns` + 孤儿处理逻辑 | 依赖 Wave 1 | +| `ZnsCanonicalEvents.EVT_ZNS_TENANT_ROUTER_ORPHAN_IN_CLOUD` | 事件常量 | +| 新 `reconnectSdnController`(Group A + Group B) | 重构现有方法 | +| `SyncFabricHandler` | 依赖 Wave 3/5 | +| `SyncResourceHandler` | 依赖 Wave 3/5 | + +### Wave 6 — API 拦截 + VM/NIC 层 + +| 任务 | 说明 | +|------|------| +| `ZnsApiInterceptor.validate(APICreateL3NetworkMsg)` — VPC 支持 | 依赖 Wave 1 | +| `ZnsApiInterceptor.validate(APIDeleteZnsTenantRouterMsg)` — 限制删除 | 依赖 Wave 1 | +| `ZnsApiInterceptor.validate(APICreateVmInstanceMsg)` — NIC 模式校验 | 依赖 Wave 1 | +| `VmNicManagerImpl.computeVmNicType` 改为读 VM 维度 Tag | 依赖 Wave 1 | +| `KVMAgentCommands` 新增 `PrepareDpdkNicCmd` / `ReleaseDpdkNicCmd` | 依赖无 | +| `KVMRealizeL2GeneveNetworkBackend` DPDK 分支 | 依赖 Wave 1/6 | +| DHCP/DNS/MTU 完整性验证 + `afterCreateIpRange` 修复 | 依赖 Wave 4 | +| 双栈 IpRange `needsSegmentUpdate` 双字段比较 | 回归验证 | + +--- + +## 附录 A:关键接口/类一览 + +| 类/接口 | 所在包 | 变更类型 | +|---------|--------|---------| +| `ZnsNotificationController` | `org.zstack.network.zns` | **新增** | +| `ZnsNotificationCommands` | `org.zstack.network.zns` | **新增** | +| `ZnsCanonicalEvents` | `org.zstack.network.zns` | **新增** | +| `ZnsTenantVO` | `org.zstack.network.zns` | **新增** | +| `ZnsTenantRouterVO` | `org.zstack.network.zns` | **新增** | +| `ZnsTenantInventory` | `org.zstack.network.zns` | **新增** | +| `ZnsTenantRouterInventory` | `org.zstack.network.zns` | **新增** | +| `APIQueryZnsTenantRouterMsg` | `org.zstack.network.zns` | **新增** | +| `ZnsErrors` | `org.zstack.network.zns` | **修改**(新增 6 个常量) | +| `ZnsSdnControllerSystemTags` | `org.zstack.network.zns` | **修改**(废弃 1 个,新增 2 个) | +| `ZnsApiInterceptor` | `org.zstack.network.zns` | **修改**(VPC 支持 + 新拦截) | +| `ZnsSdnController` | `org.zstack.network.zns` | **修改**(移除 Flow 5,重构 reconnect) | +| `ZnsApiCommands` | `org.zstack.network.zns` | **修改**(新增 DTO) | +| `ZnsApiClient` | `org.zstack.network.zns` | **修改**(新增 2 个方法) | +| `ZnsConstant` | `org.zstack.network.zns` | **修改**(新增 HTTP 路径常量) | +| `ZnsSdnControllerConstant` | `org.zstack.network.zns` | **修改**(新增废弃常量) | +| `VmNicManagerImpl` | `org.zstack.network.vm`(或 network-service) | **修改**(NIC 类型计算) | +| `KVMAgentCommands` | `org.zstack.kvm` | **修改**(新增 DPDK 命令) | +| `KVMRealizeL2GeneveNetworkBackend` | `org.zstack.kvm` | **修改**(DPDK 分支) | +| `KVMConstant` | `org.zstack.kvm` | **修改**(新增路径常量) | +| `ZnsSdnControllerDhcp` | `org.zstack.network.zns` | **验证**(DHCP 完整性) | +| `ZnsSdnControllerL3` | `org.zstack.network.zns` | **验证**(双栈 IpRange) | + +--- + +## 附录 B:数据流图 + +### B.1 新 Add-CM 流程 + +``` +ZNS Wizard + │ + │ POST /zns/notify/add-compute-manager + │ {vip, account, password, computerManagerUuid, name} + ▼ +ZnsNotificationController.AddComputeManagerHandler + │ + ├─ 幂等检查(computerManagerUuid) + ├─ persistNewController @Transactional + │ persist SdnControllerVO + │ persist ZnsControllerVO + │ create SystemTag computerManagerUuid::{uuid} + ├─ fire SDN_CONTROLLER_ADDED event + │ + └─ return {uuid, success:true} + │ + ▼ + ZNS 存储 Cloud 侧 controller UUID +``` + +### B.2 Wizard Init Sync 流程 + +``` +ZNS Wizard(T1 创建完成) + │ + │ POST /zns/notify/wizard-init-sync {computerManagerUuid} + ▼ +WizardInitSyncHandler + │ + ├─ Flow 1: sync-transport-zones-zns-as-sot + │ pull TZ from ZNS → upsert ZnsTransportZoneVO → delete orphans + ├─ Flow 2: sync-transport-nodes-zns-as-sot + │ pull TN → upsert SdnControllerHostRefVO → delete orphans + ├─ Flow 3: sync-tenants-zns-as-sot(optional) + │ pull Tenant → upsert ZnsTenantVO → delete orphans + ├─ Flow 4: sync-tenant-routers-zns-as-sot + │ pull TR → upsert ZnsTenantRouterVO → handle orphans + └─ Flow 5: cleanup-orphan-segments + list ZNS Segments → find no-Cloud-L2 counterpart → deleteSegment(force=true) +``` + +### B.3 Reconcile SoT 拆分 + +``` +reconnectSdnController + │ + ├─ [Group A: ZNS-as-SoT] syncDeviceResourcesFromZns + │ TZ sync → TN sync → Tenant sync → TenantRouter sync + │ 每步:pull all from ZNS → upsert → delete orphans + │ + └─ [Group B: Cloud-as-SoT] reconcileSegmentsCloudAsSoT + 3-way diff: Cloud L2 ↔ ZNS Segment ↔ cloud-basis + 原有逻辑不变 +``` diff --git a/docs/modules/network/nav.adoc b/docs/modules/network/nav.adoc index 19dbb6c06b1..0cee54bd193 100644 --- a/docs/modules/network/nav.adoc +++ b/docs/modules/network/nav.adoc @@ -4,4 +4,5 @@ *** xref:networkResource/L3Network.adoc[] *** xref:networkResource/l3Ipam.adoc[] *** xref:networkResource/VpcRouter.adoc[] + *** xref:networkResource/ZnsIntegration.adoc[] ** xref:networkService/networkService.adoc[] \ No newline at end of file diff --git a/docs/modules/network/pages/networkResource/ZStackL2NetworkType.adoc b/docs/modules/network/pages/networkResource/ZStackL2NetworkType.adoc new file mode 100644 index 00000000000..14c22fcda29 --- /dev/null +++ b/docs/modules/network/pages/networkResource/ZStackL2NetworkType.adoc @@ -0,0 +1,504 @@ += 网络类型体系:L2NetworkType / VSwitchType / VmNicType + +ZStack 的网络类型由三层模型组成,分别描述二层网络拓扑、虚拟交换机实现和虚拟机网卡类型。 + +== 三层类型模型 + +[cols="1,1,1"] +|=== +| L2NetworkType (网络拓扑类型) | VSwitchType (虚拟交换机类型) | VmNicType (网卡类型) + +| 定义二层网络的拓扑结构 +| 定义物理机上的虚拟交换机实现 +| 定义虚拟机网卡的驱动/接口类型 + +| 由 `L2NetworkFactory` 注册 +| 由 `VmInstanceNicFactory` 注册 +| 由 `VSwitchType.addVmNicType()` 绑定 + +| 存储在 `L2NetworkVO.type` +| 存储在 `L2NetworkVO.vSwitchType` +| 存储在 `VmNicVO.type` +|=== + +=== 关系 + +---- +L2NetworkType 1 ──── N VSwitchType 1 ──── N VmNicType + (一种L2可选多种vSwitch) (一种vSwitch可有多种NIC子类型) +---- + +例: + +---- +L2NoVlanNetwork ──┬── LinuxBridge ──── VIRTUAL_NIC (SubType=NONE) + └── OVN_DPDK ──┬── dpdkvhostuserclient (SubType=NONE) + └── VF (SubType=SRIOV) + +L2GeneveNetwork ──── ZNS ──┬── VIRTUAL_NIC (SubType=NONE, 默认) + └── dpdkvhostuserclient (SubType=VHOSTUSER, 需system tag指定) + +L2VlanNetwork ──── LinuxBridge ──── VIRTUAL_NIC (SubType=NONE) +---- + +== 注册机制 + +=== L2NetworkType + +在 `L2NetworkFactory.getType()` 中通过 `new L2NetworkType("xxx")` 自动注册到静态 Map。 + +[source,java] +---- +// L2NoVlanL2NetworkFactory.java +public L2NetworkType getType() { + return new L2NetworkType(L2NetworkConstant.L2_NO_VLAN_NETWORK_TYPE); +} +---- + +=== VSwitchType + +在 `VmInstanceNicFactory.getType()` 中通过 `new VSwitchType("xxx")` 自动注册到静态 Map。 + +[source,java] +---- +// ZnsVmNicFactory.java +static final VSwitchType vSwitchType = new VSwitchType("ZNS"); +---- + +=== VmNicType + +通过 `VSwitchType.addVmNicType(SubType, VmNicType)` 绑定到 VSwitchType。 + +[source,java] +---- +// ZnsVmNicFactory.java +vSwitchType.addVmNicType(VmNicType.VmNicSubType.NONE, type); +---- + +== 全部 L2NetworkType(10种) + +[cols="2,3,2"] +|=== +| L2NetworkType | 工厂类 | 模块 + +| L2NoVlanNetwork +| `L2NoVlanL2NetworkFactory` +| network/ + +| L2VlanNetwork +| `L2VlanNetworkFactory` +| network/ + +| VxlanNetwork +| `VxlanNetworkFactory` +| plugin/vxlan/ + +| VxlanNetworkPool +| `VxlanNetworkPoolFactory` +| plugin/vxlan/ + +| HardwareVxlanNetwork +| `HardwareVxlanNetworkFactory` +| plugin/sdnController/ + +| HardwareVxlanNetworkPool +| `HardwareVxlanNetworkPoolFactory` +| plugin/sdnController/ + +| L2GeneveNetwork +| `L2GeneveNetworkFactory` +| premium/zns/ + +| PortGroupNetwork +| `L2PortGroupNetworkFactory` +| premium/virtualSwitch/ + +| VirtualSwitchNetwork +| `L2VirtualSwitchNetworkFactory` +| premium/virtualSwitch/ + +| TfNetwork +| `TfL2NetworkFactory` +| plugin/sugonSdn/ +|=== + +== 全部 VSwitchType(7种) + +[cols="2,1,1,2"] +|=== +| VSwitchType | sdnControllerType | nicLifecycleManagedByFactory | NicFactory + +| LinuxBridge +| null +| false +| `VmNicFactory` + +| ZNS +| "ZNS" +| *true* +| `ZnsVmNicFactory` + +| MacVlan +| null +| false +| `VmMacVlanNicFactory` + +| OVN_DPDK +| null +| false +| `VmOvnVhostUserNicFactory` + +| OVS_DPDK +| null +| false +| `VmOvnVhostUserNicFactory` + +| TF +| null +| false +| `TfVmNicFactory` + +| OVS_DPDK(vDPA) +| null +| false +| `VmVdpaNicFactory` +|=== + +=== VSwitchType 关键属性 + +[cols="2,4,1"] +|=== +| 属性 | 作用 | ZNS 值 + +| `sdnControllerType` +| 关联的 SDN 控制器类型,null 表示无 SDN +| "ZNS" + +| `nicLifecycleManagedByFactory` +| NIC 生命周期由 NicFactory 管理 (true) 还是 SdnControllerManager 管理 (false) +| *true* + +| `attachToCluster` +| 是否需要手动挂载集群 +| false(ZNS 通过 TransportZone 自动挂载) + +| `useDpdk` +| 是否使用 DPDK +| false +|=== + +== L2NetworkType → VSwitchType 映射 + +L2NetworkVO 同时持有 `type`(L2NetworkType)和 `vSwitchType`(VSwitchType)。 +L2 创建时由用户或系统指定 vSwitchType。同一 L2NetworkType 可搭配不同 VSwitchType: + +[cols="2,2,3"] +|=== +| L2NetworkType | 可用 VSwitchType | 说明 + +| L2NoVlanNetwork +| LinuxBridge, OVN_DPDK, OVS_DPDK, ZNS +| 普通无 VLAN 二层网络 + +| L2VlanNetwork +| LinuxBridge, OVN_DPDK, OVS_DPDK, ZNS +| VLAN tagged 网络 + +| VxlanNetwork +| LinuxBridge +| 软件 VXLAN 覆盖网络 + +| HardwareVxlanNetwork +| (SDN 专用) +| 硬件 SDN VXLAN + +| L2GeneveNetwork +| ZNS +| ZNS Geneve 覆盖网络 + +| PortGroupNetwork +| (VirtualSwitch) +| VMware 端口组 + +| TfNetwork +| TF +| Tungsten Fabric +|=== + +== VSwitchType → VmNicType 映射(按 VmNicSubType) + +请求创建 NIC 时: + +. 检查 VM 是否有 SRIOV 系统标签 → SubType=SRIOV +. 检查全局配置是否启用 VHOSTUSER → SubType=VHOSTUSER +. 否则 → SubType=NONE + +`VSwitchType.getVmNicType(subType)` 从 nicTypes Map 中查找对应的 VmNicType。 + +[cols="2,1,1,1"] +|=== +| VSwitchType | SubType=NONE | SubType=SRIOV | SubType=VHOSTUSER + +| LinuxBridge +| VIRTUAL_NIC +| — +| — + +| ZNS +| VIRTUAL_NIC +| — +| dpdkvhostuserclient + +| MacVlan +| MACVLAN_NIC +| — +| — + +| OVN_DPDK +| OVN_VHOSTUSER +| OVN_VF +| — + +| OVS_DPDK +| — +| VDPA +| OVS_VHOSTUSER + +| TF +| TF_NIC +| — +| — +|=== + +== 创建 VM 时 NIC 组装完整流程 + +---- + VmAllocateNicFlow + │ + L3Network → L2Network → VSwitchType → VmNicType → VmInstanceNicFactory + │ + factory.createVmNic() + ┌───────────┴───────────┐ + │ │ + (持久化 VmNicVO) factory.afterCreateVmNic() + │ + ┌─────────────────────────┤ + │ │ + 普通 NIC (空操作) ZNS NIC: + createSegmentPort() + → 创建 UsedIpVO + → 回写 VmNicVO.ip/gateway + │ + VmInstantiateResourcePreFlow + │ + SdnControllerManagerImpl.preInstantiateVmResource() + │ + ┌──────────────┼──────────────┐ + │ │ │ + sdnControllerType nicLifecycle 其他 SDN: + == null? ManagedByFactory? controller.addVmNics() + → 跳过(普通) → 跳过(ZNS已处理) (OVN/HW-VXLAN 路径) + │ + KVMHost.completeNicInfo() + │ + KVMCompleteNicInformationExtensionPoint (按 L2Type 分发) + ┌──────┬──────┼──────┬──────┐ + │ │ │ │ │ + NoVlan Vlan VxLAN Geneve PortGroup + bridge bridge bridge bridge ... + 无VLAN +VLAN +VNI (ZNS管) + │ + StartVmCmd → KVM Agent +---- + +== L2 物理机配置(Realize)决策 + +[cols="2,3,3"] +|=== +| L2 Backend | realize() 行为 | 触发时机 + +| KVMRealizeL2NoVlan +| `CreateBridgeCmd` → 物理机创建网桥 +| Host 连接时 + NIC 挂载时 + +| KVMRealizeL2Vlan +| `CreateVlanBridgeCmd` → 创建 VLAN 子接口 + 网桥 +| Host 连接时 + NIC 挂载时 + +| KVMRealizeL2Vxlan +| `CreateVxlanBridgeCmd` → 创建 VXLAN 隧道 + 网桥 +| 按需(`InstantiateResourceOnAttachingNic`) + +| KVMRealizeL2Geneve +| *空操作* +| ZNS/OVS controller 自行管理网桥 +|=== + +== 全部 VmNicType(6种) + +[cols="2,2,2,3"] +|=== +| VmNicType | 类型名 | NicFactory | 说明 + +| VNIC +| `"VNIC"` +| `VmNicFactory` +| 标准 virtio 网卡,最常用的类型 + +| dpdkvhostuserclient +| `"dpdkvhostuserclient"` +| `VmOvnVhostUserNicFactory` +| DPDK vhost-user 网卡,使用 OVS 的 vhost-user socket 进行高性能数据传输 + +| VF +| `"VF"` +| `VmVfNicFactory` +| SR-IOV Virtual Function 网卡,直通物理网卡的虚拟功能 + +| vDPA +| `"vDPA"` +| `VmVdpaNicFactory` +| vDPA (virtio Data Path Acceleration) 网卡,硬件加速的 virtio 数据路径 + +| MACVLAN +| `"MACVLAN"` +| `VmMacVlanNicFactory` +| MacVLAN 网卡,基于 MAC 地址的虚拟 LAN + +| TFVNIC +| `"TFVNIC"` +| `TfVmNicFactory` +| Tungsten Fabric 网卡 +|=== + +=== 各 VmNicType 的使用条件 + +VmNicType 的选择由 `VmNicManagerImpl.getVmNicType()` 决定,依据三个因素: + +. L2 网络的 VSwitchType +. VM 是否有 SRIOV 系统标签(`enableSRIOV::{l3Uuid}`) +. 全局配置 `ENABLE_VHOSTUSER` 是否开启 + +选择优先级:SRIOV > VHOSTUSER > NONE,若 VSwitchType 不支持请求的 SubType,回退到 NONE。 + +[cols="2,2,2,2,2"] +|=== +| VmNicType | VSwitchType | L2NetworkType | VmNicSubType | 使用条件 + +| VNIC +| LinuxBridge +| L2NoVlanNetwork, L2VlanNetwork +| NONE +| 默认情况:未启用 SRIOV 且未启用 VHOSTUSER + +| dpdkvhostuserclient +| OVN_DPDK +| L2NoVlanNetwork +| NONE +| L2 使用 OVN_DPDK vSwitch,默认情况 + +| dpdkvhostuserclient +| OVS_DPDK +| L2NoVlanNetwork, L2VlanNetwork +| VHOSTUSER +| L2 使用 OVS_DPDK vSwitch 且全局配置 `ENABLE_VHOSTUSER=true` + +| dpdkvhostuserclient +| OVN_DPDK +| L2NoVlanNetwork +| SRIOV +| L2 使用 OVN_DPDK vSwitch 且 VM 有 `enableSRIOV` 标签(注册为 VF 类型) + +| VF +| LinuxBridge +| L2NoVlanNetwork, L2VlanNetwork +| SRIOV +| L2 使用 LinuxBridge 且 VM 有 `enableSRIOV` 标签 + +| vDPA +| OVS_DPDK +| L2NoVlanNetwork, L2VlanNetwork +| NONE, SRIOV +| L2 使用 OVS_DPDK vSwitch,默认或 SRIOV 模式 + +| MACVLAN +| MacVlan +| L2NoVlanNetwork, L2VlanNetwork +| NONE +| L2 使用 MacVlan vSwitch + +| VNIC +| ZNS +| L2NoVlanNetwork, L2VlanNetwork, L2GeneveNetwork +| NONE +| L2 使用 ZNS vSwitch,默认网卡类型 + +| dpdkvhostuserclient +| ZNS +| L2NoVlanNetwork, L2VlanNetwork, L2GeneveNetwork +| VHOSTUSER +| L2 使用 ZNS vSwitch,用户通过 system tag 指定使用 dpdkvhostuserclient + +| TFVNIC +| TF +| TfNetwork +| NONE +| L2 使用 TF (Tungsten Fabric) vSwitch +|=== + +=== NicTO 中 srcPath 设置规则 + +当 VSwitchType 为 OVN_DPDK 或 ZNS 时,`completeNicInformation()` 会设置 +`srcPath = "/var/run/openvswitch/" + nic.getInternalName()`,用于 DPDK vhost-user socket 连接。 + +[cols="2,2,2,1"] +|=== +| L2NetworkType | VSwitchType | 设置 srcPath? | Backend + +| L2NoVlanNetwork +| LinuxBridge +| 否 +| KVMRealizeL2NoVlanNetworkBackend + +| L2NoVlanNetwork +| OVN_DPDK / ZNS +| *是* +| KVMRealizeL2NoVlanNetworkBackend + +| L2VlanNetwork +| LinuxBridge +| 否 +| KVMRealizeL2VlanNetworkBackend + +| L2VlanNetwork +| OVN_DPDK / ZNS +| *是* +| KVMRealizeL2VlanNetworkBackend + +| L2GeneveNetwork +| ZNS +| 否(仅 OVN_DPDK 设置) +| KVMRealizeL2GeneveNetworkBackend + +| VxlanNetwork +| LinuxBridge +| 否 +| KVMRealizeL2VxlanNetworkBackend +|=== + +== SDN 两条路径对比 + +=== Path A: Factory 管理(ZNS) + +* `VSwitchType.nicLifecycleManagedByFactory = true` +* `SdnControllerManagerImpl.preInstantiateVmResource()` 跳过 +* `VmInstanceNicFactory`(ZnsVmNicFactory)在 `afterCreateVmNic()` 中直接调 ZNS API +* Port 在 VM stop/reboot 时持久化,不随 VM 生命周期反复创建/删除 + +=== Path B: SdnControllerManager 管理(OVN / Hardware VXLAN) + +* `VSwitchType.nicLifecycleManagedByFactory = false`,`sdnControllerType != null` +* `SdnControllerManagerImpl.preInstantiateVmResource()` 处理 +* 通过 `L2NetworkSystemTags.SdnControllerUuid` 找到控制器 UUID +* 调用 `SdnControllerL2.addVmNics()` 创建端口 +* Port 随 VM start/stop 反复创建/删除 diff --git a/docs/modules/network/pages/networkResource/ZnsIntegration.adoc b/docs/modules/network/pages/networkResource/ZnsIntegration.adoc new file mode 100644 index 00000000000..285af083f14 --- /dev/null +++ b/docs/modules/network/pages/networkResource/ZnsIntegration.adoc @@ -0,0 +1,975 @@ += 对接ZNS SDN控制器 + +== 总体描述 + +当前 ZNS 与 Cloud 的集成采用混合主权模型: + +* 设备资源(transport zone、transport node、host switch、tenant、tenant router)以 ZNS 为真相源 +* 业务资源(L2Network、L3Network、IpRange、segment、segment port、DHCP service)以 Cloud 为真相源 +* Cloud 不再把 ZNS 上已有的 segment 反向导入为 L2/L3;首次同步和定时对账发现孤儿 segment 时,直接在 ZNS 侧清理 +* ZNS 通过反向通知驱动 SDN Controller 建档、首次同步和运行期设备资源同步;Cloud 通过 API 主动维护业务资源 + +Cloud 与 ZNS 的核心映射关系如下: + +* ZNS transport zone / transport node / host switch → Cloud 侧设备资源视图与调度约束 +* ZNS tenant router → Cloud `ZnsTenantRouterVO` +* Cloud `L2Network` ↔ ZNS segment +* Cloud `VmNic` ↔ ZNS segment port +* Cloud `IpRange` / DHCP / DNS / MTU ↔ ZNS segment 配置 + +=== CMS +Cloud 资源和 ZNS 资源之间的映射仍然通过 CMS 元数据协助建立。 + +[source,go] +---- + type Cms struct { + CmsUuid string + Type string ### cloud/zsv/zaku/zns + IP string ### cloud mn vip + Role string ###owner, user + CmsResourceUuid string ###owner, user + } + +type Segment { + ... + CmsMetaDatas []Cms `json:"cms"` +} +---- + +* Cms::Type 定义 cms 类型:Cloud、ZSV、ZAKU、ZNS +* Cms::IP 定义 cms 的 IP 地址,该字段主要用于资源识别;cms 的唯一标识仍是 CmsUuid +* Cms::CmsUuid 定义 cmsUuid。对 Cloud 而言,该值对应 ZNS 的 `computerManagerUuid`,由 `add-compute-manager` 反向通知写入 `SdnController` systemTag +* Cms::CmsResourceUuid 定义该 cms 系统对应的资源 UUID,用于回写 Cloud 资源标识并在对账时建立映射 +* 对业务资源(segment、segment port、DHCP service)而言,Cloud 是 owner;ZNS 不主动创建这些资源,也不应主动发送 `resourceType=SEGMENT` 通知 +* 对设备资源(transport zone、transport node、host switch、tenant、tenant router)而言,ZNS 是 owner,Cloud 仅做同步展示和引用校验 + +=== ZNS API + +ZNS API 需要同时覆盖 Cloud 主调和 ZNS 反向通知两类场景: + +* Cloud → ZNS:创建/删除/更新 segment、segment port、tenant router 关联、DHCP、DNS、MTU、IpRange 等业务资源 +* ZNS → Cloud:通过反向通知完成 `add-compute-manager`、`wizard-init-sync`、`sync-fabric`、`sync-resource`,以及条件能力 `delete-compute-manager` +* 查询 API 需要支持按 `cmsUuid` 过滤资源 +* 面向大规模对账的查询 API 应逐步支持 `hash_fields` / `content_hash` 轻量比对;segment port 列表还需要支持按 `host_uuid` 过滤 + +[NOTE] +不是所有 API 都需要以上全部能力,但所有会进入对账链路的资源都必须支持稳定的跨系统映射。 + +=== ZNS 数据库对象 + +由 cms 创建的资源,或者需要按 cms 查询的资源,都需要保存 cms 信息。 +一个资源可能有多个 cms 信息,表示资源可在多个 cms 之间共享。 + +对账相关资源还需要满足以下要求: + +* segment / segment port 能够回写 Cloud 资源 UUID,支持孤儿资源清理 +* segment port 需要记录 `host_uuid`、`transport_node_uuid`,便于按主机维度对账 +* segment / segment port / DHCP service 在支持轻量对账时,可以根据 `hash_fields` 计算并返回 `content_hash` + +=== UUID 格式约定 + +ZNS 使用带连字符的 UUID 格式(`550e8400-e29b-41d4-a716-446655440000`),Cloud 使用不带连字符的紧凑 UUID 格式(`550e8400e29b41d4a716446655440000`)。 + +Cloud 在调用 ZNS API 时需要将 Cloud UUID 转换为 ZNS UUID 格式,在接收 ZNS 响应时需要将 ZNS UUID 转换回 Cloud 格式。 + +== Cloud 与 ZNS 通信协议 + +=== 传输层 + +Cloud 通过 HTTP REST API 与 ZNS 通信,ZNS 也通过 HTTP POST 反向通知 Cloud。所有请求/响应体均为 JSON 格式。 + +全局配置参数: + +[cols="2,2,2"] +|=== +|配置项 |默认值 |说明 + +|`zns.controller.scheme` +|`http` +|HTTP 或 HTTPS + +|`zns.controller.port` +|`7278` +|ZNS API 端口 + +|`zns.controller.timeout` +|`300000`(5分钟) +|请求超时时间(毫秒) + +|`zns.notifyDebounceMs` +|`1000` +|ZNS 反向通知防抖窗口(毫秒) + +|=== + +[NOTE] +反向通知 endpoint 仅绑定到管理网,v1 阶段依赖管理网隔离、`computerManagerUuid` 校验和资源归属校验,不引入 token / signing。 + +=== 异步回调模式 + +Cloud 调用 ZNS 的业务写操作(POST/PATCH/DELETE)采用异步回调模式: + +.... +Cloud ZNS + │ POST/PATCH/DELETE + headers │ + │ x-web-hook: │ + │ x-job-uuid: │ + │─────────────────────────────────────────►│ + │ ◄── 202 Accepted │ (ZNS 立即返回) + │ │ + │ (ZNS 异步处理完成后回调 Cloud) │ + │ ◄── POST │ + │ { taskUuid, success, status, data } │ + │ │ + │ Cloud 根据 taskUuid 匹配到 │ + │ 对应的等待中的调用并完成 │ +.... + +Cloud 的读操作(GET)为同步调用,直接返回 200 + JSON body。 +ZNS 的反向通知也是同步 POST:Cloud 负责快速返回 200 / 4xx,真正的资源同步可以在 Cloud 内部异步执行。 + +=== 反向通知 + +ZNS 通过以下入口反向通知 Cloud: + +[cols="2,2,3"] +|=== +|入口 |发送方 |用途 + +|`POST /zns/notify/add-compute-manager` +|ZNS +|创建或更新 `SdnController` 建档信息,不触发资源同步 + +|`POST /zns/notify/wizard-init-sync` +|ZNS Wizard +|首次同步设备资源,并清理 ZNS 侧孤儿 segment + +|`POST /zns/notify/sync-fabric` +|ZNS +|按 `scope` 触发设备资源重拉;支持 `ALL` 和 `TZ/TN/HOSTSWITCH/TENANT/TENANT_ROUTER` + +|`POST /zns/notify/sync-resource` +|ZNS +|单资源增删改通知,主要用于 tenant router / transport node 等;`SEGMENT` 通知直接拒绝 + +|`POST /zns/notify/delete-compute-manager` +|ZNS +|条件能力,仅在应用市场支持卸载前钩子时启用 + +|=== + +=== 请求串行化 + +对同一个 ZNS IP 的所有 API 调用通过任务链串行执行,避免并发操作导致的冲突。 + +对 ZNS 反向通知,Cloud 会对相同 `sdnControllerUuid + scope` 的 `sync-fabric` 进行防抖合并,避免通知风暴导致重复重拉。 + +== ZNS SDN控制器 + +ZStack 已经定义 `SdnControllerVO`,目前已有 `H3cVcfcSdnController`、`SugonSdnController`、`OvnController`、`HuaweiIMasterSdnController` 等实现。 + +新定义 `ZnsControllerVO`,继承 `SdnControllerVO`: + +* vendorType:ZNS +* vendorVersion:用于记录当前连接的 ZNS 版本(详见 <> 章节) +* transportZones:关联的 `ZnsTransportZoneVO` 列表(一对多) +* state:在 `Connecting`、`Connected`、`Syncing`、`Ready`、`Disconnected` 之间流转 +* lastError:记录通知或对账失败时的最近错误信息 + +[NOTE] +Cloud 通过 SystemTag 记录以下映射关系: + +* `computerManagerUuid::{uuid}` 在 `SdnControllerVO` 上 +* `znsSegmentUuid::{segmentUuid}` 在 `L2NetworkVO` 上 +* `znsSegmentPortUuid::{portUuid}` 在 `VmNicVO` 上 +* `znsTenantRouterUuid::{tenantRouterUuid}` 在 `L3VpcNetwork` 上 +* `znsDhcpServiceUuid::{serviceUuid}` 在开启 DHCP 的 `L3Network` 上 + +=== 创建SDN控制器 + +Cloud 侧接入 ZNS 的主路径不再是手工录入,而是由 ZNS 反向通知完成建档。 +原有 `APIAddSdnControllerMsg` 手工接入路径仍保留,作为反向通知失效时的兜底。 + +==== 1. 接收 add-compute-manager 反向通知 + +ZNS 在完成 `addComputerManager` 后,调用 `POST /zns/notify/add-compute-manager`,携带 vip、account、password、computerManagerUuid、name 等信息。 + +==== 2. 幂等建档或更新连接信息 + +Cloud 根据 `computerManagerUuid` 对 `SdnControllerVO` / `ZnsControllerVO` 做 insert 或 update: + +* 完全相同 payload:幂等成功,记录数不增加 +* `computerManagerUuid` 相同但 vip / account / password 变化:仅更新变化字段 +* 缺少关键字段:直接返回 400,不落库 + +==== 3. 仅建档,不触发资源同步 + +`add-compute-manager` 成功后,控制器进入 `Connecting` 状态,仅表示 Cloud 已知晓该 ZNS 控制器。 +在首次 `wizard-init-sync` 成功前,Cloud 不会同步任何设备资源,也不允许创建 ZNS L2。 + +=== 首次同步(Wizard 触发) + +首次同步由 ZNS Wizard 通过 `POST /zns/notify/wizard-init-sync` 触发,而不是在建档时自动执行。 + +==== 1. 进入 Syncing 状态 + +Cloud 收到 `wizard-init-sync` 后,将控制器从 `Connecting` / `Connected` 置为 `Syncing`,开始全量同步设备资源。 + +==== 2. 同步 Compute Collections、Discovered Nodes 和 Host Ref + +Cloud 调用 `GET /zns/api/v1/fabric/compute-collections`、`GET /zns/api/v1/fabric/discovered-nodes`,并继续追踪 host switch 相关信息,建立以下映射关系: + +* `HostData.managementIp`:匹配 Cloud `HostVO.managementIp` +* `HostData.clusterId`:匹配 Cloud `ClusterVO.uuid` +* `HostSwitchProfileData.type`:枚举值 `dpdk` 或 `kernel`,用于推导 `SdnControllerHostRefVO.vSwitchType` +* `HostSwitchProfileData.transportZoneIds`:建立 `transportZoneUuid → Set` 反向映射 + +`type` 与 `vSwitchType` 的映射规则如下: + +[cols="2,2"] +|=== +|ZNS HostSwitchProfileData.type |Cloud SdnControllerHostRefVO.vSwitchType + +|`dpdk` +|`OvsDpdk` + +|`kernel` +|`OvsKernel` + +|其它未知值,或者 profile 查询失败 +|`ZNS` + +|=== + +==== 3. 同步 Transport Zones、Tenant 和 Tenant Router + +Cloud 拉取 transport zone、tenant、tenant router 并持久化本地视图。`ZnsTransportZoneVO` 的主要字段如下: + +[cols="2,3,2"] +|=== +|字段 |来源 |说明 + +|`uuid` +|transport zone UUID(转换为 Cloud 格式) +|主键 + +|`name` +|transport zone 返回字段 +|transport zone 名称 + +|`description` +|transport zone 返回字段 +|描述信息 + +|`type` +|transport zone 返回字段 +|类型,典型值为 `vlan` 或 `overlay` + +|`physicalNetwork` +|transport zone 返回字段 +|物理网络标识 + +|`status` +|transport zone 返回字段 +|当前状态 + +|`tags` +|transport zone 返回字段 +|标签信息 + +|`znsSdnControllerUuid` +|当前 `ZnsSdnControllerVO.uuid` +|外键,关联到所属 ZNS SDN Controller + +|=== + +==== 4. 清理 ZNS 孤儿 segment + +首次同步不会根据 ZNS segment 在 Cloud 侧创建新的 L2/L3。 +如果 ZNS 上已经存在不属于任何 Cloud L2 的 segment,Cloud 会把它们视为孤儿资源并在 ZNS 侧删除。 + +==== 5. 完成首次同步 + +首次同步成功后,控制器进入 `Ready` 状态; +如果中途访问 ZNS 失败,则控制器进入 `Disconnected`,并记录 `lastError`,等待重试或手动 reconnect。 + +=== 运行期变更通知 + +ZNS 运行期资源变化后,通过反向通知驱动 Cloud 更新设备资源视图: + +* `sync-fabric`:按 `scope=ALL` 或具体类型重拉设备资源 +* `sync-resource`:处理 tenant router、transport node 等单资源级别的增删改 +* `resourceType=SEGMENT` 的通知直接拒绝,因为 segment 以 Cloud 为真相源 + +[NOTE] +如果通知触发的重拉过程因为网络抖动失败,Cloud 只记录错误并等待下一轮定时对账,不会立刻把控制器标记为 `Disconnected`。 + +=== 重连SDN控制器 + +重连(`APIReconnectSdnControllerMsg`)以 Cloud 数据库为基准,对设备资源和业务资源分别做收敛,不会根据 ZNS 当前状态在 Cloud 新建 L2/L3。 + +==== 1. 刷新 SdnControllerHostRefVO(upsert) + +重连仍需重新扫描 host(包括 compute collections → discovered nodes → host switch),以处理新加入的主机或 `vSwitchType` 发生变化的主机。 +映射关系与首次同步相同,写库操作改为 upsert: + +[cols="3,2"] +|=== +|情况 |操作 + +|`SdnControllerHostRefVO` 不存在(新主机) +|INSERT 新记录 + +|已存在但 `vSwitchType` 或 `vtepIp` 发生变化 +|UPDATE + +|已存在且字段未变 +|跳过 + +|=== + +==== 2. 刷新设备资源 + +调用 transport zone、tenant、tenant router 等设备资源查询 API,对本地视图做 upsert,并删除 ZNS 侧已不存在的旧记录。 + +==== 3. Segment 协调(以 Cloud 为基准) + +重连以 Cloud 数据库中所有 `vSwitchType = ZNS` 的 `L2NetworkVO` 为基准,与 ZNS 侧 segment 做三路对比: + +[cols="2,2,3"] +|=== +|Cloud 侧 L2NetworkVO |ZNS 侧 segment |操作 + +|不存在 +|存在 +|调用 `DELETE /zns/api/v1/segments/{uuid}` 删除孤儿 segment + +|存在 +|不存在 +|调用 `POST /zns/api/v1/segments` 在 ZNS 新建 segment + +|存在 +|存在但参数不一致(名称、描述、transport zone、VNI、CIDR、DHCP、DNS、MTU 等) +|调用 `PATCH /zns/api/v1/segments/{uuid}` 更新 + +|存在 +|存在且参数一致 +|无操作 + +|=== + +[NOTE] +重连不会根据 ZNS segment 在 Cloud 侧创建新的 L2Network / L3Network / IpRange。 + +==== 4. Segment Port 协调 + +完成 segment 协调后,对每个已与 Cloud L2 匹配的 segment,逐一协调其 port: + +[cols="2,2,3"] +|=== +|Cloud 侧 VmNicVO |ZNS 侧 segment port |操作 + +|存在 +|不存在 +|调用 `POST /zns/api/v1/segments/{uuid}/ports` 补建 port + +|不存在 +|存在 +|调用 `DELETE /zns/api/v1/segments/{uuid}/ports/{portUuid}` 删除孤儿 port + +|两侧均存在但参数有漂移 +|存在 +|按 Cloud 当前值补发更新或等待常规网卡变更流程收敛 + +|两侧均存在且参数一致 +|存在 +|无操作 + +|=== + +==== 5. Tenant Router 引用收敛 + +如果本地仍引用一个 ZNS 侧已不存在的 tenant router: + +* 若没有任何 `L3VpcNetwork` 引用它:删除本地 `ZnsTenantRouterVO` +* 若仍有 `L3VpcNetwork` 引用它:保留本地记录并告警,等待运维先清理 Cloud 引用 + +=== 心跳探活(Ping) + +Cloud 定期发送 `SdnControllerPingMsg`,通过调用 `GET /zns/api/v1/fabric/compute-managers/{uuid}` 验证 Computer Manager 连通性。 + +* 验证成功:控制器保持当前可用状态 +* 验证失败:控制器状态变为 `Disconnected` + +=== 定时同步对账 + +定时对账按照资源主权拆成两条链路: + +* 设备资源:以 ZNS 为真相源,Cloud 删除本地多余记录、补齐缺失记录 +* 业务资源:以 Cloud 为真相源,Cloud 修正 ZNS 侧的 segment / segment port / DHCP 漂移,并清理孤儿业务资源 + +对账时的核心规则: + +* ZNS 上存在、Cloud 不存在的 segment:直接删除,不反向导入 Cloud +* ZNS 上存在、Cloud 不存在的 segment port:按孤儿 port 清理 +* Cloud 上仍引用已删除 tenant router:保留本地记录并告警,不强制删除 +* 当 ZNS 提供 `hash_fields` / `content_hash` 能力后,可先做轻量比对,再决定是否拉全量数据 + +=== 删除SDN控制器 + +Cloud 主动删除 ZNS SDN Controller 时,默认走 cascade 路径: + +. 先级联删除 `VmNic`、`L3Network`、`L2Network` +. 删除过程中分别按 segment port、tenant router attach、segment 的各自语义与 ZNS 交互 +. 最后删除 `SdnControllerVO` 以及本地设备资源视图 + +`APIDeleteSdnControllerMsg` 支持两种行为: + +* 默认模式:允许 cascade,按资源依赖顺序清理 +* `deleteMode=Enforcing`:如果仍有 ZNS L2 / L3 / VmNic 引用,直接拒绝删除 + +[NOTE] +`delete-compute-manager` 反向通知是条件能力。只有应用市场支持卸载前钩子时,才允许 ZNS 反向通知 Cloud 做 restrict 删除;该路径不触发 cascade。 + +== L2Network + +=== 基础信息 + +`L2NetworkVO` 的重要字段: + +* `type`:L2NoVlanNetwork、L2VlanNetwork、L2GeneveNetwork +* `vSwitchType`:固定为 `ZNS` +* `virtualNetworkId`:vlanId 或 Geneve ID +* `physicalInterface`:固定为空字符串 + +ZNS L2Network 的定义如下: + +[cols="1,2"] +|=== +|属性 |值 + +|type +|L2NoVlanNetwork、L2VlanNetwork、L2GeneveNetwork + +|vSwitchType +|ZNS(固定值,不区分 kernel 和 dpdk) + +|physicalInterface +|空字符串 + +|virtualNetworkId +|Vlan Id 或 Geneve Id + +|transportZoneUuid +|创建时必须显式指定;`L2GeneveNetwork` 只能绑定 `overlay`,`L2VlanNetwork` / `L2NoVlanNetwork` 只能绑定 `vlan` + +|=== + +[NOTE] +`L2NetworkClusterRefVO` 仍由 transport zone 和 host sync 结果推导,用于表达 Cloud 侧可调度范围;ZNS 不负责 cluster 级网络隔离。 + +=== 创建 L2Network + +创建 ZNS 二层网络时,Cloud 不再自动选择默认 transport zone,而是要求创建请求显式指定 `transportZoneUuid`。 + +调用 `POST /zns/api/v1/segments` 创建 segment,请求体至少包含: + +* `name` +* `description` +* `transport_zone_uuid` +* `transport_type` +* `virtual_network_id` +* `dpdk_capable` +* cms 信息 + +创建成功后,将 ZNS 返回的 segment UUID 通过 systemTag 记录到 `L2NetworkVO` 上。 +如果 ZNS 创建失败,Cloud 不创建本地 `L2NetworkVO`。 + +[NOTE] +创建 `L2Network` 时,Cloud 会自动将 `vSwitchType` 设为 `ZNS`,`physicalInterface` 设为空字符串。这通过 `ZnsApiInterceptor` 在 `APICreateL2NetworkMsg` 处理前自动完成。 + +=== 删除 L2Network + +删除 ZNS 二层网络时,Cloud 先调用 `DELETE /zns/api/v1/segments/{uuid}`: + +* 删除成功:清理本地 L2 和 systemTag +* ZNS 返回 5xx:按 best-effort 继续删除本地 L2;残留 segment 留给定时对账清理 +* ZNS 返回"segment 仍被引用":中止本地删除,要求先清理引用关系 + +=== APIChangeL2NetworkVlanIdMsg + +* `L2GeneveNetwork` 类型不支持修改 VLAN ID,需要在 API 拦截器中拦截 +* `L2VlanNetwork`、`L2NoVlanNetwork` 类型允许按现有语义修改,但修改后的值必须继续以 Cloud 为真相源同步到 ZNS + +=== APIAttachL2NetworkToClusterMsg / APIDetachL2NetworkFromClusterMsg + +当前实现为空操作(no-op)。 +ZNS 通过 transport zone 管理底层网络覆盖范围,attach / detach cluster 仅影响 Cloud 侧的调度约束。 + +== L3Network + +=== 基础信息 + +`L3NetworkVO` 的重要字段: + +* `type`:`L3BasicNetwork`、`L3VpcNetwork` +* `category`:`Private` + +ZNS L3 的定义如下: + +[cols="1,2"] +|=== +|属性 |值/规则 + +|type +|`L3BasicNetwork` 或 `L3VpcNetwork` + +|category +|只能是 `Private` + +|`znsTenantRouterUuid` +|仅 `L3VpcNetwork` 需要,通过 systemTag 指定 + +|每个 ZNS L2 的 L3 数量 +|最多一个 + +|=== + +[NOTE] +ZNS 集成不再创建额外的“ZNS L3 对象”。Cloud 的 L3 只是 segment 上的三层配置和可选的 tenant router 绑定关系。 + +=== 创建 L3Network + +创建 `L3BasicNetwork` 时,Cloud 只创建本地 `L3NetworkVO`,不单独调用 ZNS 创建 L3 资源。 + +创建 `L3VpcNetwork` 时,除本地建档外,还必须: + +* 校验请求携带 `znsTenantRouterUuid::{uuid}` systemTag +* 校验该 tenant router 已同步到 Cloud +* 调用 ZNS 把当前 segment attach 到对应 tenant router + +如果 attach 失败,Cloud 回滚本地 `L3NetworkVO` 和 systemTag,不保留半成品数据。 + +=== 创建/删除 IpRange + +Cloud 为 ZNS L3 分配和维护 IpRange,ZNS 只保存 segment 上的三层配置。 + +* IPv4 IpRange:同步到 `cidr` / `gateway_address` +* IPv6 IpRange:同步到 `cidr6` / `gateway6_address` +* 同一个 L3 最多允许一条 IPv4 IpRange 和一条 IPv6 IpRange + +创建 IpRange 时,Cloud 先落本地数据,再调用 `PATCH /zns/api/v1/segments/{uuid}` 同步对应字段; +如果 PATCH 失败,Cloud 回滚本地 IpRange。 + +删除 IpRange 时: + +* 删除 IPv4 IpRange:只清空 IPv4 相关字段 +* 删除 IPv6 IpRange:只清空 IPv6 相关字段 +* 如果该 IP 版本的 DHCP 仍处于启用状态,则拒绝删除对应 IpRange + +[NOTE] +创建/删除 `L3Network` 本身不创建或删除 ZNS segment;只有 VPC attach / detach 和 IpRange / DHCP / DNS / MTU 变化才会调用 ZNS API。 + +=== DHCP / DNS 同步 + +ZNS L3 支持运行期开关 DHCP,并同步 DNS 配置: + +* 开启 DHCP:Cloud PATCH segment 的 `dhcp_configs`,并在本地记录 `znsDhcpServiceUuid` +* 关闭 DHCP:Cloud 仅把 `dhcp_configs.enabled` 置为 `false`,保留 `dns_servers`,便于后续再次开启时复用 +* 更新 DNS:Cloud 仅 PATCH `dhcp_configs.dns_servers` + +如果 DHCP / DNS PATCH 失败,Cloud 回滚本地状态,不保留不一致配置。 + +=== MTU 同步 + +当用户修改 L3Network MTU 时,如果该 L3 属于 ZNS 网络,Cloud 调用 `PATCH /zns/api/v1/segments/{uuid}` 将 `mtu` 字段同步到 ZNS segment。 +如果 PATCH 失败,Cloud 回滚本地 MTU。 + +== VmNic + +ZNS 网卡的模式选择不再直接暴露为“UI 选 VNIC 或 dpdkvhostuserclient”,而是由 VM systemTag `znsNicMode::{kernel|dpdk}` 决定。 +如果用户没有指定该 systemTag,则使用 `zns.defaultNicMode` 全局配置(默认 `kernel`)。 + +实际创建出的 `VmNicVO.type` 映射如下: + +* `znsNicMode::kernel` → `vnic` +* `znsNicMode::dpdk` → `dpdkvhostuserclient` + +=== 虚拟机的物理机分配 + +创建虚拟机选择了 ZNS 网络时: + +* `kernel` 模式只能调度到 `OvsKernel` 主机 +* `dpdk` 模式只能调度到 `OvsDpdk` 主机 +* 如果没有符合模式的主机,则调度失败 +* `dpdk` 虚拟机不允许迁移到 `kernel` 主机 + +=== 网卡创建过程 + +创建虚拟机或给虚拟机添加网卡时,会调用 `VmAllocateNicFlow` 创建网卡。 + +ZNS 网卡创建过程如下: + +. 按 Cloud 现有流程分配网卡 mac、internalId、internalName、driverType 和本地 `UsedIp` +. 调用 ZNS 创建 segment port API(`POST /zns/api/v1/segments/{uuid}/ports`),请求体包含:name、mac、ipv4、ipv6、vm_uuid、dpdk_mode、cms 信息 +. 在已知主机上下文时,可以额外携带 `host_uuid`、`transport_node_uuid`,便于后续按主机维度对账 +. 如果 ZNS 创建成功,则持久化 `VmNicVO` / `UsedIpVO`,并将 port UUID 通过 systemTag 记录到 `VmNicVO` 上 +. 如果 ZNS 创建失败,则回滚本地 `VmNicVO` / `UsedIpVO`,不中断 Cloud / ZNS 一致性 + +=== 网卡删除过程 + +* `VmReturnReleaseNicFlow`:在 `destroyVmWorkFlowElements` 中被调用,用于虚拟机销毁时释放网卡资源 +* `VmDetachNicFlow`:在云主机删除网卡时调用 + +两个 Flow 中都需要调用 ZNS 删除 segment port API(`DELETE /zns/api/v1/segments/{uuid}/ports/{portUuid}`)。 + +删除语义如下: + +* 删除成功:清理 systemTag,删除 `VmNicVO`、`UsedIpVO` +* 删除失败:按 best-effort 继续清理本地数据;残留 port 留给定时对账删除 + +=== IP 变更(VmIpChanged) + +当虚拟机 IP 发生变化时(`SetVmStaticIp`、`ChangeVmIp` 等操作),Cloud 调用 `PATCH /zns/api/v1/segments/{uuid}/ports/{portUuid}` 更新 ZNS 侧 port 的 IPv4 / IPv6 信息。 + +=== ChangeVmNicNetwork(换网操作) + +`APIChangeVmNicNetworkMsg` 涉及 detach 旧网络 + attach 新网络: + +* 不支持从 ZNS 变换成非 ZNS 网络,或从非 ZNS 变换成 ZNS 网络 +* 不支持在不同 ZNS 控制器之间换网 +* 从同一控制器下的 ZNS 网络换网时:先删除旧 segment port,再在新 segment 上创建新 port + +=== DPDK 网卡的特殊处理 + +由于 libvirt 不能自动创建 `dpdkvhostuserclient` 类型的网卡,Cloud 需要在虚拟机启动前,在物理机上预先创建对应的 DPDK 网卡。 +该逻辑只在 `znsNicMode::dpdk` 路径生效;`kernel` 路径继续依赖 libvirt 自动创建普通 vnic。 + +=== FilterAttachableL3NetworkExtensionPoint + +获取虚拟机可挂载的 L3 网络列表时,ZNS 网络有额外的过滤规则: + +* 如果虚拟机尚未挂载 ZNS 网络:ZNS 类型的 L3 仅当虚拟机所在物理机被该 ZNS 控制器管理时才可挂载 +* 如果虚拟机已挂载 ZNS 网络:只允许挂载同一 ZNS 控制器下的 L3,或挂载非 ZNS 的 L3 + +== API 拦截器 + +`ZnsApiInterceptor` 在以下场景进行拦截: + +* `APICreateL2NetworkMsg`:如果请求创建 ZNS L2,自动设置 `vSwitchType = ZNS`、`physicalInterface = ""`,并校验 `transportZoneUuid` 和 L2 类型匹配 +* `APICreateL3NetworkMsg`:ZNS L2 只允许创建 `Private` 类型 L3;同一 ZNS L2 只能有一个 L3;`L3VpcNetwork` 必须携带合法的 `znsTenantRouterUuid` +* `APIAddIpRangeMsg` / `APIDeleteIpRangeMsg`:每个 ipVersion 只允许一条 IpRange;IPv6 gateway 必须落在 CIDR 内;对应 DHCP 启用时禁止删除该 ipVersion 的 IpRange +* `APIChangeL2NetworkVlanIdMsg`:禁止修改 `L2GeneveNetwork` 的 VLAN ID +* `APIChangeVmNicNetworkMsg`:禁止 ZNS 与非 ZNS 网络之间换网,禁止不同 ZNS 控制器之间换网 +* `APIDeleteSdnControllerMsg`:在 `deleteMode=Enforcing` 时,如果仍有引用资源则拒绝删除 +* `APISdnControllerAddHostMsg` / `RemoveHostMsg` / `ChangeHostMsg`:禁止对 ZNS 控制器手动管理主机(由 ZNS 自动同步) + +[[api-version]] +== API 版本兼容性 + +=== 问题背景 + +Cloud 和 ZNS 是独立部署的两个组件,可能出现版本不一致: + +* **场景A**:Cloud 升级了,ZNS 没升级 — Cloud 发出 ZNS 不认识的 API 格式 +* **场景B**:ZNS 升级了,Cloud 没升级 — Cloud 用旧格式调新 API,参数缺失或语义变化 +* **场景C**:运行中 ZNS 被升级/降级 — Cloud 缓存的版本信息过期 + +=== 设计思路 + +.... +1. 每个 API 独立版本 + 不是给 ZNS 一个整体版本号,而是给每个 API 独立的版本号。 + ZNS 一年 2-3 个版本,但不是每个 API 都会变。 + +2. ZNS 是自己能力的真相源 + 每个 API 通过 HTTP OPTIONS 方法声明自己支持哪些版本。 + ZNS 各 API 各管各的版本,不集中到一个大接口里。 + +3. Cloud 通过 HTTP Header 声明自己发送的版本 + 每次请求带 X-Api-Version header,ZNS 可据此选择处理逻辑。 +.... + +=== 版本模型 + +==== 每个 API 有独立版本 + +.... +API 路径 + 方法 Cloud 发送的版本 ZNS 支持的版本 +────────────────────────────────────── ──────────────── ─────────────── +POST /zns/api/v1/segments 1.1 [1.0, 1.1] +PATCH /zns/api/v1/segments/{uuid} 1.1 [1.0, 1.1, 1.2] +DELETE /zns/api/v1/segments 1.0 [1.0] +GET /zns/api/v1/segments 1.1 [1.0, 1.1] +POST /zns/api/v1/segments/{id}/ports 1.0 [1.0, 1.1] +PATCH /zns/api/v1/segments/{id}/ports 1.1 [1.0, 1.1] +DELETE /zns/api/v1/segments/{id}/ports 1.0 [1.0] +.... + +* *Cloud 侧*:每个 API 有一个确定的版本,表示"我发出去的请求是什么格式" +* *ZNS 侧*:每个 API 支持一组版本,表示"我能理解哪些格式" +* *兼容条件*:Cloud 发送的版本 ∈ ZNS 支持的版本集合 + +==== API 版本变更举例 + +.... +ZNS v1.0 发布: + PATCH /segments 支持 [1.0] + POST /ports 支持 [1.0] + +ZNS v1.1 发布(PATCH segment 新增 mtu 字段): + PATCH /segments 支持 [1.0, 1.1] ← 新增 1.1,但仍兼容 1.0 + POST /ports 支持 [1.0] ← 没变 + +ZNS v1.2 发布(PATCH segment 删除了某个旧字段): + PATCH /segments 支持 [1.1, 1.2] ← 不再支持 1.0 + POST /ports 支持 [1.0, 1.1] ← 新增 1.1 +.... + +=== 版本查询:HTTP OPTIONS 方法 + +每个 API 路径通过标准的 HTTP OPTIONS 方法返回自己支持的版本。 + +.... +Cloud ZNS + │ │ + │ OPTIONS /zns/api/v1/segments │ + │───────────────────────────────────────────────────►│ + │ │ + │ ◄── 204 No Content │ + │ Headers: │ + │ Allow: GET, POST, DELETE │ ← 标准头 + │ X-Api-Versions: POST=1.0,1.1; │ ← 自定义头 + │ DELETE=1.0; │ + │ GET=1.0,1.1 │ + │ │ + │ OPTIONS /zns/api/v1/segments/{uuid} │ + │───────────────────────────────────────────────────►│ + │ │ + │ ◄── 204 No Content │ + │ Headers: │ + │ Allow: GET, PATCH │ + │ X-Api-Versions: PATCH=1.0,1.1,1.2; │ + │ GET=1.0,1.1 │ + │ │ +.... + +`X-Api-Versions` Header 格式: +.... +X-Api-Versions: {METHOD1}={ver1},{ver2};{METHOD2}={ver1},{ver2} + +示例:POST=1.0,1.1;DELETE=1.0;GET=1.0,1.1 +.... + +=== 版本声明:X-Api-Version 请求头 + +Cloud 每次发送 API 请求时,通过 Header 声明自己发送的是哪个版本的格式: + +.... +Cloud ZNS + │ │ + │ PATCH /zns/api/v1/segments/{uuid} │ + │ Headers: │ + │ X-Api-Version: 1.1 ← 声明版本 │ + │ Content-Type: application/json │ + │ x-web-hook: ... │ + │ x-job-uuid: ... │ + │ Body: │ + │ { "name": "...", "mtu": 9000 } ← 1.1 格式 │ + │───────────────────────────────────────────────────►│ + │ │ + │ ZNS 收到请求: │ + │ 1. 检查 X-Api-Version = 1.1 │ + │ 2. PATCH segments 支持 1.1? → 用 1.1 处理逻辑 │ + │ 不支持? → 返回 400 │ + │ │ +.... + +==== ZNS 处理不支持的版本 + +.... +ZNS 返回: + HTTP 400 Bad Request + { + "error": "unsupported_api_version", + "message": "PATCH /segments does not support version 1.3", + "supported_versions": ["1.0", "1.1", "1.2"] + } +.... + +==== ZNS 处理没有版本 Header 的请求(兼容旧版 Cloud) + +没有 `X-Api-Version` header 时,ZNS 按该 API 支持的最低版本处理,确保旧版 Cloud 仍能正常使用。 + +=== 版本检查时机 + +.... +核心原则: + 不在每次 API 调用前询问 ZNS(会导致每次操作延迟翻倍) + 而是在 3 个时机批量拉取版本信息,缓存在内存中 + + ZNS 版本一年才变 2-3 次,变版本必然有运维动作(升级), + 升级后通常会触发 reconnect。Ping 间隔内版本突然变化的概率极低。 +.... + +[cols="2,3,3"] +|=== +|时机 |触发条件 |行为 + +|添加控制器(preInit) +|用户首次添加 ZNS 控制器到 Cloud +|对每个 API 路径发 OPTIONS → 检查兼容性 → 缓存。不兼容则拒绝添加 + +|重连控制器(reconnect) +|管理员手动触发重连,或网络恢复后自动重连 +|清除旧缓存 → 重新发 OPTIONS → 检查 → 缓存。不兼容则重连失败 + +|心跳探活(ping) +|Cloud 定时 Ping ZNS +|对每个 API 路径发 OPTIONS → 与缓存对比。版本变化 → 刷新缓存 → 重新检查。不兼容 → Ping 失败 → 标记 Disconnected + +|=== + +=== 双层防御 + +版本兼容性在两个层面保证: + +.... +第 1 层: Cloud 提前检查(发请求之前) + Cloud 在 preInit/reconnect/ping 时通过 OPTIONS 拉取版本 + 缓存到内存,每次发请求前本地查缓存 + 不兼容 → 不发请求,直接报错或降级 + 作用: 避免发出注定失败的请求 + +第 2 层: ZNS 兜底校验(收到请求时) + ZNS 收到请求后检查 X-Api-Version header + 不支持 → 返回 400 + supported_versions + 作用: 即使 Cloud 缓存过期,ZNS 也能拒绝不兼容的请求 +.... + +=== 不兼容时的处理策略 + +不同 API 不兼容时,处理方式不同: + +[cols="3,1,3"] +|=== +|API (路径 + 方法) |重要性 |不兼容时行为 + +|POST /segments(创建网络) +|关键 +|阻断: 拒绝添加/重连控制器 + +|DELETE /segments(删除网络) +|关键 +|阻断 + +|POST /segments/{id}/ports(创建端口) +|关键 +|阻断 + +|DELETE /segments/{id}/ports(删除端口) +|关键 +|阻断 + +|GET /segments(列表,对账用) +|关键 +|阻断 + +|GET /segments/{id}/ports(列表,对账用) +|关键 +|阻断 + +|PATCH /segments/{uuid}(更新 mtu 等) +|非关键 +|降级: 跳过 + 打印告警日志 + +|PATCH /segments/{id}/ports/{id}(更新端口) +|非关键 +|降级: 跳过 + 打印告警日志 + +|=== + +=== 兼容旧版 + +==== Cloud 遇到旧版 ZNS(不支持 OPTIONS 版本响应) + +如果 OPTIONS 返回 404 或 204 但没有 `X-Api-Versions` header,Cloud 假设所有 API 只支持 `["1.0"]`。 + +==== ZNS 遇到旧版 Cloud(不带 X-Api-Version header) + +没有 `X-Api-Version` header 时,ZNS 按最低支持版本处理。 + +=== 错误信息设计 + +==== Cloud 新,ZNS 旧 + +.... +ZNS controller [192.168.1.10] does not support the following APIs +required by this Cloud version: + - PATCH /segments: Cloud sends v1.1, ZNS supports [1.0] + - POST /ports: Cloud sends v1.1, ZNS supports [1.0] +Please upgrade ZNS to a compatible version. +.... + +==== ZNS 新,Cloud 旧 + +.... +This Cloud version is not compatible with ZNS [192.168.1.10]: + - PATCH /segments: Cloud sends v1.0, ZNS supports [1.1, 1.2] (v1.0 dropped) +Please upgrade Cloud to a compatible version. +.... + +==== 非关键 API 降级 + +.... +WARN: ZNS [192.168.1.10] does not support PATCH /segments v1.1 +(ZNS supports [1.0]). MTU sync will be skipped. +This does not affect core network operations. Upgrade ZNS to enable MTU sync. +.... + +=== 版本维护规范 + +==== 什么时候需要升版本 + +需要升版本: + +* 请求体新增必填字段 +* 请求体删除字段 +* 字段类型变化(string → int) +* 字段语义变化(单位从 MB 变成 KB) +* 响应体结构变化(影响 Cloud 解析) + +不需要升版本: + +* 请求体新增可选字段(ZNS 忽略未知字段即可) +* 纯内部实现变化,接口不变 +* 性能优化,接口不变 + +==== ZNS 的向后兼容策略 + +建议每个 API 至少兼容前 2 个版本。 + +.... +示例: PATCH /segments + v1.2 发布时 → supported: [1.0, 1.1, 1.2] (兼容 3 个版本) + v1.3 发布时 → supported: [1.1, 1.2, 1.3] (下线 1.0) + +这样可以给 Cloud 升级留出足够的时间窗口。 +.... + +=== 双方职责总结 + +==== ZNS 侧 + +. 每个 API 路径实现 OPTIONS 方法,返回 `Allow` + `X-Api-Versions` header +. 收到请求时检查 `X-Api-Version` header:支持则用对应版本处理;不支持则返回 400;缺失则按最低版本处理 +. 每次 API 格式变化时在该 API 的 OPTIONS 响应中新增版本号,保留旧版本兼容 +. 新增 API 时实现 OPTIONS,初始版本为 `1.0` + +==== Cloud 侧 + +. 维护 `CLOUD_API_VERSIONS` 表,记录当前发出的每个 API 的格式版本 +. 在 preInit、reconnect、ping 三个时机通过 OPTIONS 拉取版本并缓存 +. 每次发请求带上 `X-Api-Version` header +. 每次修改 API 请求体格式时同步更新版本号 +. 标记每个 API 的重要性(关键/非关键),决定不兼容时是阻断还是降级 diff --git a/docs/modules/network/pages/networkResource/networkResource.adoc b/docs/modules/network/pages/networkResource/networkResource.adoc index 3b567e4eb66..382c3b4d733 100644 --- a/docs/modules/network/pages/networkResource/networkResource.adoc +++ b/docs/modules/network/pages/networkResource/networkResource.adoc @@ -3,4 +3,5 @@ * xref:networkResource/L2Network.adoc[] * xref:networkResource/L3Network.adoc[] * xref:networkResource/l3Ipam.adoc[] -* xref:networkResource/VpcRouter.adoc[] \ No newline at end of file +* xref:networkResource/VpcRouter.adoc[] +* xref:networkResource/ZnsIntegration.adoc[] diff --git a/header/src/main/java/org/zstack/header/host/HostCanonicalEvents.java b/header/src/main/java/org/zstack/header/host/HostCanonicalEvents.java index cca0e26567d..2e4998c964e 100755 --- a/header/src/main/java/org/zstack/header/host/HostCanonicalEvents.java +++ b/header/src/main/java/org/zstack/header/host/HostCanonicalEvents.java @@ -26,6 +26,7 @@ public class HostCanonicalEvents { public static final String HOST_PHYSICAL_POWER_SUPPLY_STATUS_ABNORMAL = "/host/physicalPowerSupply/status/abnormal"; public static final String HOST_PHYSICAL_GPU_REMOVE_TRIGGERED = "/host/physicalGpu/remove/triggered"; public static final String HOST_PHYSICAL_GPU_STATUS_ABNORMAL = "/host/physicalGpu/status/abnormal"; + public static final String HOST_PHYSICAL_GPU_XID_ERROR = "/host/physicalGpu/xid/error"; public static final String HOST_PHYSICAL_VGPU_STATUS_ABNORMAL = "/host/physicalVGpu/status/abnormal"; public static final String HOST_PHYSICAL_RAID_STATUS_ABNORMAL = "/host/physicalRaid/status/abnormal"; public static final String HOST_PHYSICAL_HBA_STATE_ABNORMAL = "/host/physicalHBA/state/abnormal"; @@ -178,6 +179,46 @@ public void setStatus(String status) { } } + @NeedJsonSchema + public static class HostPhysicalGpuXidErrorData { + private String hostUuid; + private String pcideviceAddress; + private String xidCode; + private String message; + + public String getHostUuid() { + return hostUuid; + } + + public void setHostUuid(String hostUuid) { + this.hostUuid = hostUuid; + } + + public String getPcideviceAddress() { + return pcideviceAddress; + } + + public void setPcideviceAddress(String pcideviceAddress) { + this.pcideviceAddress = pcideviceAddress; + } + + public String getXidCode() { + return xidCode; + } + + public void setXidCode(String xidCode) { + this.xidCode = xidCode; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + } + @NeedJsonSchema public static class HostPhysicalCpuStatusAbnormalData { private String hostUuid; diff --git a/header/src/main/java/org/zstack/header/host/HostHardware.java b/header/src/main/java/org/zstack/header/host/HostHardware.java index 7b5464eb26a..6043d777253 100644 --- a/header/src/main/java/org/zstack/header/host/HostHardware.java +++ b/header/src/main/java/org/zstack/header/host/HostHardware.java @@ -9,6 +9,7 @@ public enum HostHardware { MEMORY, DISK, GPU, + GPU_XID, POWERSUPPLY, FAN, RAID, diff --git a/header/src/main/java/org/zstack/header/network/l2/L2NetworkConstant.java b/header/src/main/java/org/zstack/header/network/l2/L2NetworkConstant.java index e72b0b91396..f0b2dd42194 100755 --- a/header/src/main/java/org/zstack/header/network/l2/L2NetworkConstant.java +++ b/header/src/main/java/org/zstack/header/network/l2/L2NetworkConstant.java @@ -22,6 +22,8 @@ public interface L2NetworkConstant { public static final String HARDWARE_VXLAN_NETWORK_TYPE = "HardwareVxlanNetwork"; public static final String L2_TF_NETWORK_TYPE = "TfL2Network"; @PythonClass + public static final String L2_GENEVE_NETWORK_TYPE = "L2GeneveNetwork"; + @PythonClass public static final String VXLAN_NETWORK_TYPE = "VxlanNetwork"; @PythonClass public static final String VXLAN_NETWORK_POOL_TYPE = "VxlanNetworkPool"; @@ -37,7 +39,11 @@ public interface L2NetworkConstant { @PythonClass public static final String VSWITCH_TYPE_OVN_DPDK = "OvnDpdk"; + @PythonClass + public static final String VSWITCH_TYPE_ZNS = "ZNS"; public static final String OVN_DPDK_VNIC_SRC_PATH = "/var/run/openvswitch/"; + public static final String ACCEL_TYPE_VDPA = "vDPA"; + public static final String ACCEL_TYPE_VHOST_USER_SPACE = "dpdkvhostuserclient"; public static final String DETACH_L2NETWORK_CODE = "l2Network.detach"; diff --git a/header/src/main/java/org/zstack/header/network/l3/AfterSetL3NetworkMtuExtensionPoint.java b/header/src/main/java/org/zstack/header/network/l3/AfterSetL3NetworkMtuExtensionPoint.java new file mode 100644 index 00000000000..c884c697b00 --- /dev/null +++ b/header/src/main/java/org/zstack/header/network/l3/AfterSetL3NetworkMtuExtensionPoint.java @@ -0,0 +1,7 @@ +package org.zstack.header.network.l3; + +import org.zstack.header.core.Completion; + +public interface AfterSetL3NetworkMtuExtensionPoint { + void afterSetL3NetworkMtu(L3NetworkInventory l3, int mtu, Completion completion); +} diff --git a/header/src/main/java/org/zstack/header/network/l3/AfterUpdateIpRangeExtensionPoint.java b/header/src/main/java/org/zstack/header/network/l3/AfterUpdateIpRangeExtensionPoint.java new file mode 100644 index 00000000000..d29e30ac614 --- /dev/null +++ b/header/src/main/java/org/zstack/header/network/l3/AfterUpdateIpRangeExtensionPoint.java @@ -0,0 +1,5 @@ +package org.zstack.header.network.l3; + +public interface AfterUpdateIpRangeExtensionPoint { + void afterUpdateIpRange(IpRangeInventory oldIpRange, IpRangeInventory newIpRange); +} diff --git a/header/src/main/java/org/zstack/header/network/l3/L3NetworkInventory.java b/header/src/main/java/org/zstack/header/network/l3/L3NetworkInventory.java index f1662f6421f..b40295ea289 100755 --- a/header/src/main/java/org/zstack/header/network/l3/L3NetworkInventory.java +++ b/header/src/main/java/org/zstack/header/network/l3/L3NetworkInventory.java @@ -423,6 +423,9 @@ public boolean enableIpAddressAllocation() { } if (!getType().equals(L3NetworkConstant.L3_BASIC_NETWORK_TYPE)) { + if (L3NetworkType.hasType(getType())) { + return L3NetworkType.valueOf(getType()).isIpAddressAllocationEnabled(); + } return true; } diff --git a/header/src/main/java/org/zstack/header/network/l3/L3NetworkType.java b/header/src/main/java/org/zstack/header/network/l3/L3NetworkType.java index b60fbb45969..e759a88b57c 100755 --- a/header/src/main/java/org/zstack/header/network/l3/L3NetworkType.java +++ b/header/src/main/java/org/zstack/header/network/l3/L3NetworkType.java @@ -6,6 +6,7 @@ public class L3NetworkType { private static Map types = Collections.synchronizedMap(new HashMap()); private final String typeName; private boolean exposed = true; + private boolean ipAddressAllocationEnabled = true; public L3NetworkType(String typeName) { this.typeName = typeName; @@ -25,6 +26,14 @@ public void setExposed(boolean exposed) { this.exposed = exposed; } + public boolean isIpAddressAllocationEnabled() { + return ipAddressAllocationEnabled; + } + + public void setIpAddressAllocationEnabled(boolean ipAddressAllocationEnabled) { + this.ipAddressAllocationEnabled = ipAddressAllocationEnabled; + } + public static boolean hasType(String typeName) { return types.containsKey(typeName); } diff --git a/header/src/main/java/org/zstack/header/network/l3/L3NetworkVO.java b/header/src/main/java/org/zstack/header/network/l3/L3NetworkVO.java index 0df379851dd..0ea342bd7a5 100755 --- a/header/src/main/java/org/zstack/header/network/l3/L3NetworkVO.java +++ b/header/src/main/java/org/zstack/header/network/l3/L3NetworkVO.java @@ -115,6 +115,9 @@ public boolean enableIpAddressAllocation() { } if (!getType().equals(L3NetworkConstant.L3_BASIC_NETWORK_TYPE)) { + if (L3NetworkType.hasType(getType())) { + return L3NetworkType.valueOf(getType()).isIpAddressAllocationEnabled(); + } return true; } diff --git a/header/src/main/java/org/zstack/header/network/sdncontroller/SdnControllerConstant.java b/header/src/main/java/org/zstack/header/network/sdncontroller/SdnControllerConstant.java index b6a6ddbe6ad..6077e352049 100644 --- a/header/src/main/java/org/zstack/header/network/sdncontroller/SdnControllerConstant.java +++ b/header/src/main/java/org/zstack/header/network/sdncontroller/SdnControllerConstant.java @@ -18,6 +18,8 @@ public class SdnControllerConstant { public static final String SERVICE_ID = "SdnController"; + public static final String ALLOCATED_IPS_ON_START = "allocatedIpsOnStart"; + public static final String H3C_VCFC_CONTROLLER = "H3C VCFC"; public static final String H3C_VCFC_VENDOR_VERSION_V1 = DEFAULT_VENDOR_VERSION; diff --git a/header/src/main/java/org/zstack/header/network/sdncontroller/SdnControllerInventory.java b/header/src/main/java/org/zstack/header/network/sdncontroller/SdnControllerInventory.java index 9f364f79136..760086a4fbd 100644 --- a/header/src/main/java/org/zstack/header/network/sdncontroller/SdnControllerInventory.java +++ b/header/src/main/java/org/zstack/header/network/sdncontroller/SdnControllerInventory.java @@ -1,7 +1,9 @@ package org.zstack.header.network.sdncontroller; import org.zstack.header.configuration.PythonClassInventory; +import org.zstack.header.log.NoLogging; import org.zstack.header.search.Inventory; +import org.zstack.header.search.TypeField; import java.io.Serializable; import java.sql.Timestamp; @@ -13,12 +15,14 @@ @PythonClassInventory public class SdnControllerInventory implements Serializable { private String uuid; + @TypeField private String vendorType; private String vendorVersion; private String name; private String description; private String ip; private String username; + @NoLogging private String password; private SdnControllerStatus status; private List hostRefs; @@ -34,7 +38,7 @@ public SdnControllerInventory(SdnControllerVO vo) { this.setVendorVersion(vo.getVendorVersion()); this.setDescription(vo.getDescription()); this.setName(vo.getName()); - this.setIp(vo.getIp()); + this.setIp(toHostAddress(vo.getIp())); this.setUsername(vo.getUsername()); this.setPassword(vo.getPassword()); this.setStatus(vo.getStatus()); @@ -55,6 +59,28 @@ public static List valueOf(Collection v return lst; } + private static String toHostAddress(String endpoint) { + if (endpoint == null) { + return null; + } + + String value = endpoint.trim(); + if (value.startsWith("[")) { + int rightBracket = value.indexOf(']'); + if (rightBracket > 1 && rightBracket + 1 < value.length() && value.charAt(rightBracket + 1) == ':') { + return value.substring(1, rightBracket); + } + } + + int firstColon = value.indexOf(':'); + int lastColon = value.lastIndexOf(':'); + if (firstColon > 0 && firstColon == lastColon) { + return value.substring(0, lastColon); + } + + return value; + } + public String getUuid() { return uuid; } diff --git a/header/src/main/java/org/zstack/header/network/sdncontroller/SdnControllerStatusEvent.java b/header/src/main/java/org/zstack/header/network/sdncontroller/SdnControllerStatusEvent.java new file mode 100644 index 00000000000..d9046427ec0 --- /dev/null +++ b/header/src/main/java/org/zstack/header/network/sdncontroller/SdnControllerStatusEvent.java @@ -0,0 +1,11 @@ +package org.zstack.header.network.sdncontroller; + +public enum SdnControllerStatusEvent { + RECONNECT_STARTED, + RECONNECT_SUCCESS, + RECONNECT_FAILED, + PING_FAILED, + INIT_SYNC_STARTED, + INIT_SYNC_SUCCESS, + INIT_SYNC_FAILED +} diff --git a/header/src/main/java/org/zstack/header/network/service/APIAttachNetworkServiceToL3NetworkMsg.java b/header/src/main/java/org/zstack/header/network/service/APIAttachNetworkServiceToL3NetworkMsg.java index c51ba7f5423..1753638d0d1 100755 --- a/header/src/main/java/org/zstack/header/network/service/APIAttachNetworkServiceToL3NetworkMsg.java +++ b/header/src/main/java/org/zstack/header/network/service/APIAttachNetworkServiceToL3NetworkMsg.java @@ -8,6 +8,7 @@ import org.zstack.header.network.l3.L3NetworkConstant; import org.zstack.header.network.l3.L3NetworkMessage; import org.zstack.header.network.l3.L3NetworkVO; +import org.zstack.header.rest.APINoSee; import org.zstack.header.rest.RestRequest; import java.util.*; @@ -66,6 +67,8 @@ public class APIAttachNetworkServiceToL3NetworkMsg extends APIMessage implements */ @APIParam private Map> networkServices; + @APINoSee + private transient boolean skipAttach; @Override public String getL3NetworkUuid() { @@ -83,6 +86,14 @@ public void setNetworkServices(Map> networkServices) { public void setL3NetworkUuid(String l3NetworkUuid) { this.l3NetworkUuid = l3NetworkUuid; } + + public boolean isSkipAttach() { + return skipAttach; + } + + public void setSkipAttach(boolean skipAttach) { + this.skipAttach = skipAttach; + } public static APIAttachNetworkServiceToL3NetworkMsg __example__() { APIAttachNetworkServiceToL3NetworkMsg msg = new APIAttachNetworkServiceToL3NetworkMsg(); diff --git a/header/src/main/java/org/zstack/header/network/service/NetworkServiceAttachExtensionPoint.java b/header/src/main/java/org/zstack/header/network/service/NetworkServiceAttachExtensionPoint.java new file mode 100644 index 00000000000..1b61aac5fad --- /dev/null +++ b/header/src/main/java/org/zstack/header/network/service/NetworkServiceAttachExtensionPoint.java @@ -0,0 +1,5 @@ +package org.zstack.header.network.service; + +public interface NetworkServiceAttachExtensionPoint { + boolean skipAttachNetworkService(APIAttachNetworkServiceToL3NetworkMsg msg); +} diff --git a/header/src/main/java/org/zstack/header/network/service/NetworkServiceProviderType.java b/header/src/main/java/org/zstack/header/network/service/NetworkServiceProviderType.java index 852bd09c401..a5ae83ce72f 100755 --- a/header/src/main/java/org/zstack/header/network/service/NetworkServiceProviderType.java +++ b/header/src/main/java/org/zstack/header/network/service/NetworkServiceProviderType.java @@ -10,6 +10,7 @@ public class NetworkServiceProviderType { private final String typeName; private boolean createDhcpNameSpace = true; private boolean allocateDhcpServerIp = true; + private boolean allocateDhcpv6ServerIp = true; public NetworkServiceProviderType(String typeName) { this.typeName = typeName; @@ -55,6 +56,14 @@ public void setAllocateDhcpServerIp(boolean allocateDhcpServerIp) { this.allocateDhcpServerIp = allocateDhcpServerIp; } + public boolean isAllocateDhcpv6ServerIp() { + return allocateDhcpv6ServerIp; + } + + public void setAllocateDhcpv6ServerIp(boolean allocateDhcpv6ServerIp) { + this.allocateDhcpv6ServerIp = allocateDhcpv6ServerIp; + } + @Override public int hashCode() { return typeName.hashCode(); diff --git a/header/src/main/java/org/zstack/header/rest/RESTFacade.java b/header/src/main/java/org/zstack/header/rest/RESTFacade.java index e9d3120f9d6..a70d5d7e337 100755 --- a/header/src/main/java/org/zstack/header/rest/RESTFacade.java +++ b/header/src/main/java/org/zstack/header/rest/RESTFacade.java @@ -11,6 +11,7 @@ import org.springframework.http.converter.StringHttpMessageConverter; import org.springframework.web.client.RestTemplate; import org.zstack.header.core.Completion; +import org.zstack.header.errorcode.ErrorCode; import javax.net.ssl.SSLContext; import javax.servlet.http.HttpServletRequest; @@ -38,6 +39,8 @@ public interface RESTFacade { void asyncJson(final String url, final String body, Map headers, HttpMethod method, final AsyncRESTCallback callback, final TimeUnit unit, final long timeout); + int failPendingCallsForResourceBefore(String resourceUuid, long cutoffMillis, ErrorCode err); + T syncJsonPost(String url, Object body, Class returnClass); T syncJsonPost(String url, Object body, Class returnClass, TimeUnit unit, long timeout); diff --git a/header/src/main/java/org/zstack/header/rest/SDKGeneric.java b/header/src/main/java/org/zstack/header/rest/SDKGeneric.java new file mode 100644 index 00000000000..d4d9373d8ad --- /dev/null +++ b/header/src/main/java/org/zstack/header/rest/SDKGeneric.java @@ -0,0 +1,11 @@ +package org.zstack.header.rest; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target({ElementType.FIELD}) +@Retention(RetentionPolicy.RUNTIME) +public @interface SDKGeneric { +} diff --git a/header/src/main/java/org/zstack/header/storage/addon/primary/PrimaryStorageNodeSvc.java b/header/src/main/java/org/zstack/header/storage/addon/primary/PrimaryStorageNodeSvc.java index d7a6207cbc8..79226ee2c9b 100644 --- a/header/src/main/java/org/zstack/header/storage/addon/primary/PrimaryStorageNodeSvc.java +++ b/header/src/main/java/org/zstack/header/storage/addon/primary/PrimaryStorageNodeSvc.java @@ -13,7 +13,7 @@ public interface PrimaryStorageNodeSvc { void deactivate(String installPath, String protocol, ActiveVolumeClient client, Completion comp); - void blacklist(String installPath, String protocol, HostInventory h, Completion comp); + void blacklist(String installPath, String protocol, HostInventory h); String getActivePath(BaseVolumeInfo v, HostInventory h, boolean shareable); BaseVolumeInfo getActiveVolumeInfo(String activePath, HostInventory h, boolean shareable); diff --git a/header/src/main/java/org/zstack/header/storage/primary/ReInitDataVolumeOnPrimaryStorageMsg.java b/header/src/main/java/org/zstack/header/storage/primary/ReInitDataVolumeOnPrimaryStorageMsg.java new file mode 100644 index 00000000000..0f4f289645c --- /dev/null +++ b/header/src/main/java/org/zstack/header/storage/primary/ReInitDataVolumeOnPrimaryStorageMsg.java @@ -0,0 +1,33 @@ +package org.zstack.header.storage.primary; + +import org.zstack.header.message.NeedReplyMessage; +import org.zstack.header.volume.VolumeInventory; + +public class ReInitDataVolumeOnPrimaryStorageMsg extends NeedReplyMessage implements PrimaryStorageMessage { + private VolumeInventory volume; + private String allocatedInstallUrl; + + @Override + public String getPrimaryStorageUuid() { + if (volume == null || volume.getPrimaryStorageUuid() == null) { + throw new IllegalArgumentException("volume and primaryStorageUuid must not be null"); + } + return volume.getPrimaryStorageUuid(); + } + + public VolumeInventory getVolume() { + return volume; + } + + public void setVolume(VolumeInventory volume) { + this.volume = volume; + } + + public String getAllocatedInstallUrl() { + return allocatedInstallUrl; + } + + public void setAllocatedInstallUrl(String allocatedInstallUrl) { + this.allocatedInstallUrl = allocatedInstallUrl; + } +} diff --git a/header/src/main/java/org/zstack/header/storage/primary/ReInitDataVolumeOnPrimaryStorageReply.java b/header/src/main/java/org/zstack/header/storage/primary/ReInitDataVolumeOnPrimaryStorageReply.java new file mode 100644 index 00000000000..2a02dd70f83 --- /dev/null +++ b/header/src/main/java/org/zstack/header/storage/primary/ReInitDataVolumeOnPrimaryStorageReply.java @@ -0,0 +1,15 @@ +package org.zstack.header.storage.primary; + +import org.zstack.header.message.MessageReply; + +public class ReInitDataVolumeOnPrimaryStorageReply extends MessageReply { + private String newVolumeInstallPath; + + public String getNewVolumeInstallPath() { + return newVolumeInstallPath; + } + + public void setNewVolumeInstallPath(String newVolumeInstallPath) { + this.newVolumeInstallPath = newVolumeInstallPath; + } +} diff --git a/header/src/main/java/org/zstack/header/storage/snapshot/MarkRootVolumeAsSnapshotMsg.java b/header/src/main/java/org/zstack/header/storage/snapshot/MarkVolumeAsSnapshotMsg.java similarity index 82% rename from header/src/main/java/org/zstack/header/storage/snapshot/MarkRootVolumeAsSnapshotMsg.java rename to header/src/main/java/org/zstack/header/storage/snapshot/MarkVolumeAsSnapshotMsg.java index 6f4de85abb5..24cbef36313 100644 --- a/header/src/main/java/org/zstack/header/storage/snapshot/MarkRootVolumeAsSnapshotMsg.java +++ b/header/src/main/java/org/zstack/header/storage/snapshot/MarkVolumeAsSnapshotMsg.java @@ -3,11 +3,7 @@ import org.zstack.header.message.NeedReplyMessage; import org.zstack.header.volume.VolumeInventory; -/** - * Created by liangbo.zhou on 17-6-23. - */ -public class MarkRootVolumeAsSnapshotMsg extends NeedReplyMessage{ - +public class MarkVolumeAsSnapshotMsg extends NeedReplyMessage { private VolumeInventory volume; private String accountUuid; diff --git a/header/src/main/java/org/zstack/header/storage/snapshot/MarkRootVolumeAsSnapshotReply.java b/header/src/main/java/org/zstack/header/storage/snapshot/MarkVolumeAsSnapshotReply.java similarity index 74% rename from header/src/main/java/org/zstack/header/storage/snapshot/MarkRootVolumeAsSnapshotReply.java rename to header/src/main/java/org/zstack/header/storage/snapshot/MarkVolumeAsSnapshotReply.java index b1bd5dcbbb9..162f7ae6ccb 100644 --- a/header/src/main/java/org/zstack/header/storage/snapshot/MarkRootVolumeAsSnapshotReply.java +++ b/header/src/main/java/org/zstack/header/storage/snapshot/MarkVolumeAsSnapshotReply.java @@ -2,10 +2,7 @@ import org.zstack.header.message.MessageReply; -/** - * Created by liangbo.zhou on 17-6-23. - */ -public class MarkRootVolumeAsSnapshotReply extends MessageReply { +public class MarkVolumeAsSnapshotReply extends MessageReply { private VolumeSnapshotInventory inventory; public VolumeSnapshotInventory getInventory() { diff --git a/header/src/main/java/org/zstack/header/storage/snapshot/VolumeSnapshotDBSyncExtensionPoint.java b/header/src/main/java/org/zstack/header/storage/snapshot/VolumeSnapshotDBSyncExtensionPoint.java new file mode 100644 index 00000000000..9a86d0f29cf --- /dev/null +++ b/header/src/main/java/org/zstack/header/storage/snapshot/VolumeSnapshotDBSyncExtensionPoint.java @@ -0,0 +1,9 @@ +package org.zstack.header.storage.snapshot; + +import org.zstack.header.volume.VolumeInventory; + +public interface VolumeSnapshotDBSyncExtensionPoint { + VolumeSnapshotInventory syncVolumeSnapshotDBAfterTakeSnapshot(VolumeInventory volume, + VolumeSnapshotInventory snapshot, + String volumeNewInstallPath); +} diff --git a/header/src/main/java/org/zstack/header/vm/AfterAllocateSdnNicExtensionPoint.java b/header/src/main/java/org/zstack/header/vm/AfterAllocateSdnNicExtensionPoint.java new file mode 100644 index 00000000000..fac3cddf27b --- /dev/null +++ b/header/src/main/java/org/zstack/header/vm/AfterAllocateSdnNicExtensionPoint.java @@ -0,0 +1,77 @@ +package org.zstack.header.vm; + +import org.zstack.header.core.Completion; + +import java.util.List; + +/** + * Extension point called after VmNicVO is persisted and non-SDN NIC IPs have + * been allocated (i.e. after VmAllocateNicIpFlow), but before the VM is + * instantiated on the hypervisor. + * + * Implementations should: + * 1. Filter NICs that belong to SDN-managed L2 networks (via VSwitchType). + * 2. Send REST API calls to the SDN controller to create ports (e.g. + * OVN logical switch ports, ZNS segment ports). + * 3. For controllers that return IP addresses (e.g. ZNS), write the + * returned IPs back into UsedIpVO and VmNicVO. + * + * If the implementation fails, VmAllocateSdnNicFlow will trigger a rollback + * via {@link #rollbackSdnNic}. + */ +public interface AfterAllocateSdnNicExtensionPoint { + /** + * Create SDN ports for the given NICs. + * + * @param spec the VM instance spec + * @param nics all NICs from spec.getDestNics() — implementation filters SDN NICs internally + * @param completion success/fail callback + */ + void afterAllocateSdnNic(VmInstanceSpec spec, List nics, Completion completion); + + /** + * Rollback: remove SDN ports and clean up any IPs allocated by the SDN controller. + * + * @param spec the VM instance spec + * @param nics all NICs from spec.getDestNics() + * @param completion success/fail callback (best-effort — failures should be logged but not block rollback) + */ + void rollbackSdnNic(VmInstanceSpec spec, List nics, Completion completion); + + /** + * Release SDN ports for NICs being detached or destroyed. + * Used by VmDetachNicFlow and VmReturnReleaseNicFlow. + * + * @param nics NICs to release (implementation filters SDN NICs internally) + * @param completion success/fail callback (best-effort) + */ + void releaseSdnNics(List nics, Completion completion); + + /** + * Expunge SDN ports for NICs whose VM is being permanently deleted. + * + * Unlike destroy/detach cleanup, expunge may fail the VM expunge workflow + * so the local VM/NIC records remain available for a later retry instead + * of leaving orphaned external SDN ports. + * + * @param nics NICs to expunge (implementation filters SDN NICs internally) + * @param completion success/fail callback + */ + default void expungeSdnNics(List nics, Completion completion) { + releaseSdnNics(nics, completion); + } + + /** + * Release IP only for NICs whose VM is being destroyed but NIC VO is retained (Recover policy). + * The segment port itself is kept; only the IP binding is released so the port can be + * re-assigned an IP when the VM starts again after recovery. + * + * Default is a no-op; only SDN controllers that manage IP allocation (e.g. ZNS) override this. + * + * @param nics NICs to release IP from (implementation filters SDN NICs internally) + * @param completion success/fail callback (best-effort) + */ + default void releaseNicIps(List nics, Completion completion) { + completion.success(); + } +} diff --git a/header/src/main/java/org/zstack/header/vm/AfterAllocateVmNicIpExtensionPoint.java b/header/src/main/java/org/zstack/header/vm/AfterAllocateVmNicIpExtensionPoint.java new file mode 100644 index 00000000000..7ff132bdc9c --- /dev/null +++ b/header/src/main/java/org/zstack/header/vm/AfterAllocateVmNicIpExtensionPoint.java @@ -0,0 +1,25 @@ +package org.zstack.header.vm; + +import org.zstack.header.core.Completion; + +/** + * Extension point called after IP address(es) have been successfully allocated + * and flushed to the database for VmNics in VmAllocateNicIpFlow. + * + * At the time this fires: + * - VmNicVO rows exist in the database (created by VmAllocateNicFlow) + * - UsedIpVO rows are committed (allocated by VmAllocateNicIpFlow) + * - spec.getDestNics() contains up-to-date NIC inventories with IP info + * + * If the implementation fails, the flow chain rolls back: + * VmAllocateNicIpFlow.rollback (returns IPs) → VmAllocateNicFlow.rollback (deletes NICs). + */ +public interface AfterAllocateVmNicIpExtensionPoint { + /** + * Runs after VM NIC IPs are allocated and persisted. + * + * @param spec VM allocation spec containing the latest destination NIC inventories + * @param completion must be completed by the implementation + */ + void afterAllocateVmNicIp(VmInstanceSpec spec, Completion completion); +} diff --git a/header/src/main/java/org/zstack/header/vm/AfterReleaseVmNicExtensionPoint.java b/header/src/main/java/org/zstack/header/vm/AfterReleaseVmNicExtensionPoint.java new file mode 100644 index 00000000000..8375f1df87e --- /dev/null +++ b/header/src/main/java/org/zstack/header/vm/AfterReleaseVmNicExtensionPoint.java @@ -0,0 +1,18 @@ +package org.zstack.header.vm; + +import org.zstack.header.core.Completion; + +/** + * Extension point called after a VmNic has been deleted from the database. + * Implementations perform post-deletion cleanup (e.g., deleting SDN segment ports). + * Cloud DB deletion must succeed before this extension point is invoked. + */ +public interface AfterReleaseVmNicExtensionPoint { + /** + * Runs after the VM NIC has been deleted from Cloud DB. + * + * @param nic inventory snapshot of the deleted NIC + * @param completion must be completed by the implementation + */ + void afterReleaseVmNic(VmNicInventory nic, Completion completion); +} diff --git a/header/src/main/java/org/zstack/header/vm/AfterUpdateVmNicMacExtensionPoint.java b/header/src/main/java/org/zstack/header/vm/AfterUpdateVmNicMacExtensionPoint.java new file mode 100644 index 00000000000..f07b9dcb8e6 --- /dev/null +++ b/header/src/main/java/org/zstack/header/vm/AfterUpdateVmNicMacExtensionPoint.java @@ -0,0 +1,5 @@ +package org.zstack.header.vm; + +public interface AfterUpdateVmNicMacExtensionPoint { + void afterUpdateVmNicMac(VmNicInventory nic, String oldMac, String newMac); +} diff --git a/header/src/main/java/org/zstack/header/vm/BeforeAllocateVmNicExtensionPoint.java b/header/src/main/java/org/zstack/header/vm/BeforeAllocateVmNicExtensionPoint.java new file mode 100644 index 00000000000..f354a9d2521 --- /dev/null +++ b/header/src/main/java/org/zstack/header/vm/BeforeAllocateVmNicExtensionPoint.java @@ -0,0 +1,14 @@ +package org.zstack.header.vm; + +import org.zstack.header.core.Completion; + +/** + * Extension point called after a VmNic is persisted but before it is fully configured + * in VmAllocateNicFlow. The VmNicVO (and its ResourceVO) already exists in the database, + * so implementations may safely create SystemTags referencing the NIC UUID. + * If the implementation fails, the NIC will be cleaned up during flow rollback. + * Use case: create SDN segment ports and save port-UUID system tags for the NIC. + */ +public interface BeforeAllocateVmNicExtensionPoint { + void beforeAllocateVmNic(VmNicInventory nic, VmInstanceSpec spec, Completion completion); +} diff --git a/header/src/main/java/org/zstack/header/vm/HaStartVmInstanceMsg.java b/header/src/main/java/org/zstack/header/vm/HaStartVmInstanceMsg.java index a358249cdf9..3ef49037137 100644 --- a/header/src/main/java/org/zstack/header/vm/HaStartVmInstanceMsg.java +++ b/header/src/main/java/org/zstack/header/vm/HaStartVmInstanceMsg.java @@ -12,6 +12,7 @@ public class HaStartVmInstanceMsg extends NeedReplyMessage implements VmInstance private String vmInstanceUuid; private String judgerClassName; private List softAvoidHostUuids; + private String accessiblePeerHostUuid; private String haReason; public String getJudgerClassName() { @@ -30,6 +31,14 @@ public void setSoftAvoidHostUuids(List softAvoidHostUuids) { this.softAvoidHostUuids = softAvoidHostUuids; } + public String getAccessiblePeerHostUuid() { + return accessiblePeerHostUuid; + } + + public void setAccessiblePeerHostUuid(String accessiblePeerHostUuid) { + this.accessiblePeerHostUuid = accessiblePeerHostUuid; + } + @Override public String getVmInstanceUuid() { return vmInstanceUuid; diff --git a/header/src/main/java/org/zstack/header/vm/StopVmOnHypervisorMsg.java b/header/src/main/java/org/zstack/header/vm/StopVmOnHypervisorMsg.java index bffd82dce1f..966928e74d4 100755 --- a/header/src/main/java/org/zstack/header/vm/StopVmOnHypervisorMsg.java +++ b/header/src/main/java/org/zstack/header/vm/StopVmOnHypervisorMsg.java @@ -7,6 +7,7 @@ public class StopVmOnHypervisorMsg extends NeedReplyMessage implements HostMessa private VmInstanceInventory vmInventory; private String type; private boolean debug; + private Boolean ignoreNotFoundError; public VmInstanceInventory getVmInventory() { return vmInventory; @@ -36,4 +37,12 @@ public boolean isDebug() { public void setDebug(boolean debug) { this.debug = debug; } + + public Boolean isIgnoreNotFoundError() { + return ignoreNotFoundError; + } + + public void setIgnoreNotFoundError(Boolean ignoreNotFoundError) { + this.ignoreNotFoundError = ignoreNotFoundError; + } } diff --git a/header/src/main/java/org/zstack/header/vm/VmAttachableL3NetworkDomainFilterExtensionPoint.java b/header/src/main/java/org/zstack/header/vm/VmAttachableL3NetworkDomainFilterExtensionPoint.java new file mode 100644 index 00000000000..f4e0a0b744c --- /dev/null +++ b/header/src/main/java/org/zstack/header/vm/VmAttachableL3NetworkDomainFilterExtensionPoint.java @@ -0,0 +1,23 @@ +package org.zstack.header.vm; + +import org.zstack.header.network.l3.L3NetworkInventory; + +import java.util.List; + +public interface VmAttachableL3NetworkDomainFilterExtensionPoint { + /** + * Returns the SDN controller vendor this domain filter handles. + * + * @return vendor type for SDN-backed L3 networks, or null for non-SDN/default L3 networks + */ + String getSdnControllerVendorType(); + + /** + * Keeps the L3 networks that are attachable to the VM within this filter's network domain. + * + * @param vm non-null VM inventory used as the attach target + * @param l3s non-null candidate L3 list; implementations must not modify the input list + * @return non-null filtered candidate list containing attachable L3 networks in this domain + */ + List filterAttachableL3NetworkInDomain(VmInstanceInventory vm, List l3s); +} diff --git a/header/src/main/java/org/zstack/header/vm/VmBeforeStartOnHypervisorExtensionPoint.java b/header/src/main/java/org/zstack/header/vm/VmBeforeStartOnHypervisorExtensionPoint.java index c56d99d38dd..1b3a393496f 100755 --- a/header/src/main/java/org/zstack/header/vm/VmBeforeStartOnHypervisorExtensionPoint.java +++ b/header/src/main/java/org/zstack/header/vm/VmBeforeStartOnHypervisorExtensionPoint.java @@ -1,7 +1,14 @@ package org.zstack.header.vm; +import org.zstack.header.core.Completion; + /** */ public interface VmBeforeStartOnHypervisorExtensionPoint { - void beforeStartVmOnHypervisor(VmInstanceSpec spec); + default void beforeStartVmOnHypervisor(VmInstanceSpec spec) {} + + default void beforeStartVmOnHypervisor(VmInstanceSpec spec, Completion completion) { + beforeStartVmOnHypervisor(spec); + completion.success(); + } } diff --git a/header/src/main/java/org/zstack/header/vm/VmCanonicalEvents.java b/header/src/main/java/org/zstack/header/vm/VmCanonicalEvents.java index e6fe6a92272..03b7758d4ea 100755 --- a/header/src/main/java/org/zstack/header/vm/VmCanonicalEvents.java +++ b/header/src/main/java/org/zstack/header/vm/VmCanonicalEvents.java @@ -20,6 +20,7 @@ public class VmCanonicalEvents { public static final String VM_NIC_INFO_DUPLICATE_PATH = "/vm/nicinfo/duplicate"; public static final String VM_NIC_INFO_IPRANGE_CONFLICT_PATH = "/vm/nicinfo/iprangeConflict"; public static final String VM_GPU_STATUS_ABNORMAL = "/vm/gpu/status/abnormal"; + public static final String VM_GPU_XID_ERROR = "/vm/gpu/xid/error"; @NeedJsonSchema public static class VmCrashReportData { @@ -349,4 +350,44 @@ public void setStatus(String status) { this.status = status; } } + + @NeedJsonSchema + public static class VmGpuXidErrorData { + private String vmUuid; + private String pciDeviceAddress; + private String xidCode; + private String message; + + public String getVmUuid() { + return vmUuid; + } + + public void setVmUuid(String vmUuid) { + this.vmUuid = vmUuid; + } + + public String getPciDeviceAddress() { + return pciDeviceAddress; + } + + public void setPciDeviceAddress(String pciDeviceAddress) { + this.pciDeviceAddress = pciDeviceAddress; + } + + public String getXidCode() { + return xidCode; + } + + public void setXidCode(String xidCode) { + this.xidCode = xidCode; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + } } diff --git a/header/src/main/java/org/zstack/header/vm/VmInstanceConstant.java b/header/src/main/java/org/zstack/header/vm/VmInstanceConstant.java index fec2e4f1b51..61cfe494fab 100755 --- a/header/src/main/java/org/zstack/header/vm/VmInstanceConstant.java +++ b/header/src/main/java/org/zstack/header/vm/VmInstanceConstant.java @@ -18,6 +18,8 @@ public interface VmInstanceConstant { String KVM_HYPERVISOR_TYPE = "KVM"; String VIRTUAL_NIC_TYPE = "VNIC"; + String ZNS_NIC_MODE_DPDK = "dpdk"; + String ZNS_NIC_MODE_KERNEL = "kernel"; String VM_SYNC_SIGNATURE_PREFIX = "Vm-"; diff --git a/header/src/main/java/org/zstack/header/vm/VmInstanceNicFactory.java b/header/src/main/java/org/zstack/header/vm/VmInstanceNicFactory.java index 44ce4a8831e..690c30cf46d 100755 --- a/header/src/main/java/org/zstack/header/vm/VmInstanceNicFactory.java +++ b/header/src/main/java/org/zstack/header/vm/VmInstanceNicFactory.java @@ -1,5 +1,6 @@ package org.zstack.header.vm; +import org.zstack.header.core.Completion; import org.zstack.header.network.l2.VSwitchType; import org.zstack.header.network.l3.UsedIpInventory; diff --git a/header/src/main/java/org/zstack/header/vm/VmNicInventory.java b/header/src/main/java/org/zstack/header/vm/VmNicInventory.java index 5ce7ef4a8eb..cacd1af1ac4 100755 --- a/header/src/main/java/org/zstack/header/vm/VmNicInventory.java +++ b/header/src/main/java/org/zstack/header/vm/VmNicInventory.java @@ -40,6 +40,8 @@ public class VmNicInventory implements Serializable { @Deprecated private Integer ipVersion; private String driverType; + @APINoSee + private String interfaceId; private List usedIps; private String internalName; private Integer deviceId; @@ -223,6 +225,14 @@ public void setDriverType(String driverType) { this.driverType = driverType; } + public String getInterfaceId() { + return interfaceId; + } + + public void setInterfaceId(String interfaceId) { + this.interfaceId = interfaceId; + } + public String getType() { return type; } diff --git a/header/src/main/java/org/zstack/header/vm/VmNicLifecycleContext.java b/header/src/main/java/org/zstack/header/vm/VmNicLifecycleContext.java new file mode 100644 index 00000000000..3300b17e33a --- /dev/null +++ b/header/src/main/java/org/zstack/header/vm/VmNicLifecycleContext.java @@ -0,0 +1,60 @@ +package org.zstack.header.vm; + +import org.zstack.header.vm.VmInstanceConstant.VmOperation; + +import java.util.Objects; + +public class VmNicLifecycleContext { + private VmOperation operation; + private String vmUuid; + private String srcHostUuid; + private String destHostUuid; + private String lastHostUuid; + + public VmOperation getOperation() { + return operation; + } + + public void setOperation(VmOperation operation) { + this.operation = operation; + } + + public String getVmUuid() { + return vmUuid; + } + + public void setVmUuid(String vmUuid) { + this.vmUuid = vmUuid; + } + + public String getSrcHostUuid() { + return srcHostUuid; + } + + public void setSrcHostUuid(String srcHostUuid) { + this.srcHostUuid = srcHostUuid; + } + + public String getDestHostUuid() { + return destHostUuid; + } + + public void setDestHostUuid(String destHostUuid) { + this.destHostUuid = destHostUuid; + } + + public String getLastHostUuid() { + return lastHostUuid; + } + + public void setLastHostUuid(String lastHostUuid) { + this.lastHostUuid = lastHostUuid; + } + + public boolean isStartWithChangedHost() { + return operation == VmOperation.Start + && lastHostUuid != null + && destHostUuid != null + && !Objects.equals(lastHostUuid, destHostUuid); + } +} diff --git a/header/src/main/java/org/zstack/header/vm/VmNicLifecycleExtensionPoint.java b/header/src/main/java/org/zstack/header/vm/VmNicLifecycleExtensionPoint.java new file mode 100644 index 00000000000..a90b790366d --- /dev/null +++ b/header/src/main/java/org/zstack/header/vm/VmNicLifecycleExtensionPoint.java @@ -0,0 +1,121 @@ +package org.zstack.header.vm; + +import org.zstack.header.core.Completion; +import org.zstack.header.core.NoErrorCompletion; + +import java.util.List; + +/** + * Extension point for managing the lifecycle of VM NICs on hosts. + * Implementations are invoked during VM start, stop, migration, NIC attach/detach, + * and periodic reconciliation driven by KVM heartbeat. + * + *

All async methods must invoke their completion callback exactly once, + * even on error paths. {@link Completion}-based methods may fail the operation; + * {@link NoErrorCompletion}-based methods must always succeed (log and absorb errors). + */ +public interface VmNicLifecycleExtensionPoint { + + /** + * Returns true if this extension should manage the given NIC. + * Called synchronously; must not block or throw checked exceptions. + * + * @param nic the NIC to evaluate + * @return true if this extension handles the NIC + */ + boolean isApplicable(VmNicInventory nic); + + /** + * Called when a VM starts or a NIC is attached to a running VM. + * Failure aborts the VM start / NIC attach operation. + * + * @param hostUuid UUID of the host where the VM is starting + * @param nics NICs filtered by {@link #isApplicable} + * @param completion call {@code success()} or {@code fail()} exactly once + */ + void setupOnHost(String hostUuid, List nics, Completion completion); + + default void setupOnHost(VmNicLifecycleContext context, String hostUuid, + List nics, Completion completion) { + setupOnHost(hostUuid, nics, completion); + } + + /** + * Called when a VM stops or a NIC is detached. Errors are logged but do not + * block the operation. + * + * @param hostUuid UUID of the host the VM is leaving + * @param nics NICs filtered by {@link #isApplicable} + * @param completion call {@code done()} exactly once + */ + void cleanupFromHost(String hostUuid, List nics, NoErrorCompletion completion); + + /** + * Called before live migration starts. Default: setup on destination host. + * Failure aborts the migration. + * Execution order: preMigrate → (live migration) → postMigrate or failedMigrate. + * + * @param srcHostUuid UUID of the source host + * @param destHostUuid UUID of the destination host + * @param nics NICs filtered by {@link #isApplicable} + * @param completion call {@code success()} or {@code fail()} exactly once + */ + default void preMigrate(String srcHostUuid, String destHostUuid, + List nics, Completion completion) { + setupOnHost(destHostUuid, nics, completion); + } + + /** + * Called after live migration succeeds. Errors are logged but do not block. + * + * @param srcHostUuid UUID of the source host + * @param destHostUuid UUID of the destination host + * @param nics NICs filtered by {@link #isApplicable} + * @param completion call {@code done()} exactly once + */ + default void postMigrate(String srcHostUuid, String destHostUuid, + List nics, NoErrorCompletion completion) { + cleanupFromHost(srcHostUuid, nics, completion); + } + + /** + * Called when live migration fails. Errors are logged but do not block. + * + * @param srcHostUuid UUID of the source host + * @param destHostUuid UUID of the destination host (where partial setup may exist) + * @param nics NICs filtered by {@link #isApplicable} + * @param completion call {@code done()} exactly once + */ + default void failedMigrate(String srcHostUuid, String destHostUuid, + List nics, NoErrorCompletion completion) { + cleanupFromHost(destHostUuid, nics, completion); + } + + /** + * Called on VM start when the VM's last known host differs from the destination host. + * Used to clean up state left on the previous host after an ungraceful shutdown. + * Errors are logged but do not block. + * + * @param lastHostUuid UUID of the host where the VM last ran + * @param nics NICs filtered by {@link #isApplicable} + * @param completion call {@code done()} exactly once + */ + default void cleanupStaleResource(String lastHostUuid, List nics, + NoErrorCompletion completion) { + cleanupFromHost(lastHostUuid, nics, completion); + } + + /** + * Called periodically on each successful KVM heartbeat to reconcile NIC state. + * Implementations should ensure remote systems match the expected state in {@code expectedNics}. + * Errors are logged but do not block the heartbeat. + * + * @param hostUuid UUID of the host being reconciled + * @param expectedNics all Running-VM NICs on this host, filtered by {@link #isApplicable} + * @param completion call {@code done()} exactly once + */ + default void reconcileOnHost(String hostUuid, List expectedNics, + NoErrorCompletion completion) { + completion.done(); + } +} diff --git a/header/src/main/java/org/zstack/header/vm/VmOvsNicConstant.java b/header/src/main/java/org/zstack/header/vm/VmOvsNicConstant.java deleted file mode 100644 index 964a41e8861..00000000000 --- a/header/src/main/java/org/zstack/header/vm/VmOvsNicConstant.java +++ /dev/null @@ -1,9 +0,0 @@ -package org.zstack.header.vm; - -import org.zstack.header.configuration.PythonClass; - -@PythonClass -public class VmOvsNicConstant { - public static final String ACCEL_TYPE_VDPA = "vDPA"; - public static final String ACCEL_TYPE_VHOST_USER_SPACE = "dpdkvhostuserclient"; -} diff --git a/header/src/main/java/org/zstack/header/volume/APIReInitDataVolumeEvent.java b/header/src/main/java/org/zstack/header/volume/APIReInitDataVolumeEvent.java new file mode 100644 index 00000000000..a5e1e57b908 --- /dev/null +++ b/header/src/main/java/org/zstack/header/volume/APIReInitDataVolumeEvent.java @@ -0,0 +1,53 @@ +package org.zstack.header.volume; + +import org.zstack.header.message.APIEvent; +import org.zstack.header.rest.RestResponse; +import org.zstack.utils.data.SizeUnit; + +import java.sql.Timestamp; + +@RestResponse(allTo = "inventory") +public class APIReInitDataVolumeEvent extends APIEvent { + private VolumeInventory inventory; + + public void setInventory(VolumeInventory inventory) { + this.inventory = inventory; + } + + public VolumeInventory getInventory() { + return inventory; + } + + public APIReInitDataVolumeEvent() { + super(); + } + + public APIReInitDataVolumeEvent(String id) { + super(id); + } + + public static APIReInitDataVolumeEvent __example__() { + APIReInitDataVolumeEvent event = new APIReInitDataVolumeEvent(); + + String volumeUuid = uuid(); + VolumeInventory vol = new VolumeInventory(); + vol.setName("test-data-volume"); + vol.setCreateDate(new Timestamp(org.zstack.header.message.DocUtils.date)); + vol.setLastOpDate(new Timestamp(org.zstack.header.message.DocUtils.date)); + vol.setType(VolumeType.Data.toString()); + vol.setUuid(volumeUuid); + vol.setSize(SizeUnit.GIGABYTE.toByte(100)); + vol.setActualSize(SizeUnit.GIGABYTE.toByte(20)); + vol.setDeviceId(1); + vol.setState(VolumeState.Enabled.toString()); + vol.setFormat("raw"); + vol.setDiskOfferingUuid(uuid()); + vol.setInstallPath(String.format("/zstack_ps/dataVolumes/acct-36c27e8ff05c4780bf6d2fa65700f22e/vol-%s/%s.qcow2", volumeUuid, volumeUuid)); + vol.setStatus(VolumeStatus.Ready.toString()); + vol.setPrimaryStorageUuid(uuid()); + vol.setVmInstanceUuid(uuid()); + + event.setInventory(vol); + return event; + } +} diff --git a/header/src/main/java/org/zstack/header/volume/APIReInitDataVolumeEventDoc_zh_cn.groovy b/header/src/main/java/org/zstack/header/volume/APIReInitDataVolumeEventDoc_zh_cn.groovy new file mode 100644 index 00000000000..91b427d28ea --- /dev/null +++ b/header/src/main/java/org/zstack/header/volume/APIReInitDataVolumeEventDoc_zh_cn.groovy @@ -0,0 +1,32 @@ +package org.zstack.header.volume + +import org.zstack.header.volume.VolumeInventory +import org.zstack.header.errorcode.ErrorCode + +doc { + + title "重新初始化数据云盘事件" + + ref { + name "inventory" + path "org.zstack.header.volume.APIReInitDataVolumeEvent.inventory" + desc "重新初始化后的数据云盘清单" + type "VolumeInventory" + since "5.4.2" + clz VolumeInventory.class + } + field { + name "success" + desc "操作是否成功" + type "boolean" + since "5.4.2" + } + ref { + name "error" + path "org.zstack.header.volume.APIReInitDataVolumeEvent.error" + desc "错误码,若不为null,则表示操作失败,操作成功时该字段为null" + type "ErrorCode" + since "5.4.2" + clz ErrorCode.class + } +} diff --git a/header/src/main/java/org/zstack/header/volume/APIReInitDataVolumeMsg.java b/header/src/main/java/org/zstack/header/volume/APIReInitDataVolumeMsg.java new file mode 100644 index 00000000000..48c86ba6261 --- /dev/null +++ b/header/src/main/java/org/zstack/header/volume/APIReInitDataVolumeMsg.java @@ -0,0 +1,49 @@ +package org.zstack.header.volume; + +import org.springframework.http.HttpMethod; +import org.zstack.header.identity.Action; +import org.zstack.header.message.APIEvent; +import org.zstack.header.message.APIMessage; +import org.zstack.header.message.APIParam; +import org.zstack.header.message.DefaultTimeout; +import org.zstack.header.other.APIAuditor; +import org.zstack.header.rest.RestRequest; + +import java.util.concurrent.TimeUnit; + +@Action(category = VolumeConstant.ACTION_CATEGORY) +@DefaultTimeout(timeunit = TimeUnit.HOURS, value = 3) +@RestRequest( + path = "/volumes/{uuid}/actions", + isAction = true, + method = HttpMethod.PUT, + responseClass = APIReInitDataVolumeEvent.class +) +public class APIReInitDataVolumeMsg extends APIMessage implements VolumeMessage, APIAuditor { + @APIParam(resourceType = VolumeVO.class, checkAccount = true, operationTarget = true) + private String uuid; + + public void setUuid(String uuid) { + this.uuid = uuid; + } + + public String getUuid() { + return uuid; + } + + @Override + public String getVolumeUuid() { + return uuid; + } + + @Override + public Result audit(APIMessage msg, APIEvent rsp) { + return new Result(((APIReInitDataVolumeMsg) msg).getUuid(), VolumeVO.class); + } + + public static APIReInitDataVolumeMsg __example__() { + APIReInitDataVolumeMsg msg = new APIReInitDataVolumeMsg(); + msg.setUuid(uuid()); + return msg; + } +} diff --git a/header/src/main/java/org/zstack/header/volume/APIReInitDataVolumeMsgDoc_zh_cn.groovy b/header/src/main/java/org/zstack/header/volume/APIReInitDataVolumeMsgDoc_zh_cn.groovy new file mode 100644 index 00000000000..949817704e9 --- /dev/null +++ b/header/src/main/java/org/zstack/header/volume/APIReInitDataVolumeMsgDoc_zh_cn.groovy @@ -0,0 +1,58 @@ +package org.zstack.header.volume + +import org.zstack.header.volume.APIReInitDataVolumeEvent + +doc { + title "重新初始化数据云盘" + + category "volume" + + desc """重新初始化一个处于可用状态的数据云盘。该操作会清空数据云盘中的现有数据,若数据云盘已挂载到云主机,云主机必须处于已停止状态。""" + + rest { + request { + url "PUT /v1/volumes/{uuid}/actions" + + header (Authorization: 'OAuth the-session-uuid') + + clz APIReInitDataVolumeMsg.class + + desc """""" + + params { + + column { + name "uuid" + enclosedIn "reInitDataVolume" + desc "资源的UUID,唯一标示该资源" + location "url" + type "String" + optional false + since "5.4.2" + } + column { + name "systemTags" + enclosedIn "" + desc "系统标签" + location "body" + type "List" + optional true + since "5.4.2" + } + column { + name "userTags" + enclosedIn "" + desc "用户标签" + location "body" + type "List" + optional true + since "5.4.2" + } + } + } + + response { + clz APIReInitDataVolumeEvent.class + } + } +} \ No newline at end of file diff --git a/identity/src/main/java/org/zstack/identity/login/LoginManagerImpl.java b/identity/src/main/java/org/zstack/identity/login/LoginManagerImpl.java index 45086320dba..b7cf5370ba6 100644 --- a/identity/src/main/java/org/zstack/identity/login/LoginManagerImpl.java +++ b/identity/src/main/java/org/zstack/identity/login/LoginManagerImpl.java @@ -267,6 +267,7 @@ private SessionInventory processSession(LoginSessionInfo info) { session.setUserType(info.getUserType()); } else { session = Session.login(info.getAccountUuid(), info.getUserUuid()); + session.setUserType(info.getUserType()); } return session; diff --git a/longjob/src/main/java/org/zstack/longjob/LongJobManagerImpl.java b/longjob/src/main/java/org/zstack/longjob/LongJobManagerImpl.java index 975b0e711db..79a01a76efa 100755 --- a/longjob/src/main/java/org/zstack/longjob/LongJobManagerImpl.java +++ b/longjob/src/main/java/org/zstack/longjob/LongJobManagerImpl.java @@ -613,6 +613,9 @@ private void handle(SubmitLongJobMsg msg) { vo.setTargetResourceUuid(msg.getTargetResourceUuid()); vo.setManagementNodeUuid(Platform.getManagementServerId()); vo.setAccountUuid(msg.getAccountUuid()); + Timestamp now = Timestamp.valueOf(LocalDateTime.now()); + vo.setCreateDate(now); + vo.setLastOpDate(now); vo = dbf.persistAndRefresh(vo); msg.setJobUuid(vo.getUuid()); tagMgr.createTags(msg.getSystemTags(), msg.getUserTags(), vo.getUuid(), LongJobVO.class.getSimpleName()); @@ -831,9 +834,7 @@ public void validateGlobalConfig(String category, String name, String oldValue, dbf.installEntityLifeCycleCallback(LongJobVO.class, EntityEvent.PRE_UPDATE, (evt, o) -> { LongJobVO job = (LongJobVO) o; if (job.getExecuteTime() == null && jobCompleted(job)) { - long time = (System.currentTimeMillis() - job.getCreateDate().getTime()) / 1000; - job.setExecuteTime(Long.max(time, 1)); - logger.info(String.format("longjob [uuid:%s] set execute time:%d", job.getUuid(), time)); + setExecuteTimeIfNeed(job); } }); diff --git a/longjob/src/main/java/org/zstack/longjob/LongJobUtils.java b/longjob/src/main/java/org/zstack/longjob/LongJobUtils.java index 2d6d2fabc8e..c4d37f98ebe 100644 --- a/longjob/src/main/java/org/zstack/longjob/LongJobUtils.java +++ b/longjob/src/main/java/org/zstack/longjob/LongJobUtils.java @@ -202,9 +202,10 @@ private static boolean isRecoverableError(ErrorCode errorCode) { return recoverable instanceof Boolean && (Boolean) recoverable; } - private static void setExecuteTimeIfNeed(LongJobVO job) { + static void setExecuteTimeIfNeed(LongJobVO job) { if (job.getExecuteTime() == null) { - long time = (System.currentTimeMillis() - job.getCreateDate().getTime()) / 1000; + long startTime = job.getCreateDate() == null ? System.currentTimeMillis() : job.getCreateDate().getTime(); + long time = (System.currentTimeMillis() - startTime) / 1000; job.setExecuteTime(Long.max(time, 1)); logger.info(String.format("longjob [uuid:%s] set execute time:%d.", job.getUuid(), time)); } diff --git a/network/src/main/java/org/zstack/network/l2/L2NetworkApiInterceptor.java b/network/src/main/java/org/zstack/network/l2/L2NetworkApiInterceptor.java index 40786eb7b2e..9b4ab106303 100755 --- a/network/src/main/java/org/zstack/network/l2/L2NetworkApiInterceptor.java +++ b/network/src/main/java/org/zstack/network/l2/L2NetworkApiInterceptor.java @@ -80,7 +80,9 @@ private void validate(final APIAttachL2NetworkToClusterMsg msg) { /* current ovs only support vlan, vxlan*/ L2NetworkVO l2 = dbf.findByUuid(msg.getL2NetworkUuid(), L2NetworkVO.class); - if (!StringUtils.isEmpty(l2.getPhysicalInterface())) { + // ZNS L2 networks are managed by SDN controller, physicalInterface is irrelevant + if (!L2NetworkConstant.VSWITCH_TYPE_ZNS.equals(l2.getvSwitchType()) + && !StringUtils.isEmpty(l2.getPhysicalInterface())) { /* find l2 network with same physical interface, but different vswitch Type */ List otherL2s = Q.New(L2NetworkVO.class).select(L2NetworkVO_.uuid) .eq(L2NetworkVO_.physicalInterface, l2.getPhysicalInterface()) @@ -113,6 +115,13 @@ private void validate(APIDeleteL2NetworkMsg msg) { } } + private boolean hasSdnControllerTag(List systemTags) { + if (systemTags == null || systemTags.isEmpty()) { + return false; + } + return systemTags.stream().anyMatch(tag -> tag.startsWith(L2NetworkSystemTags.L2_NETWORK_SDN_CONTROLLER_UUID_TOKEN + "::")); + } + private void validate(APICreateL2NetworkMsg msg) { if (!L2NetworkType.hasType(msg.getType())) { throw new ApiMessageInterceptionException(argerr(ORG_ZSTACK_NETWORK_L2_10011, "unsupported l2Network type[%s]", msg.getType())); @@ -124,8 +133,11 @@ private void validate(APICreateL2NetworkMsg msg) { throw new ApiMessageInterceptionException(argerr(ORG_ZSTACK_NETWORK_L2_10012, "unsupported vSwitch type[%s]", msg.getvSwitchType())); } + msg.setPhysicalInterface(StringUtils.trimToNull(msg.getPhysicalInterface())); + if (L2NetworkConstant.VSWITCH_TYPE_LINUX_BRIDGE.equals(msg.getvSwitchType()) - && (msg.getPhysicalInterface() == null || msg.getPhysicalInterface().trim().isEmpty())) { + && msg.getPhysicalInterface() == null + && !hasSdnControllerTag(msg.getSystemTags())) { throw new ApiMessageInterceptionException(argerr(ORG_ZSTACK_NETWORK_L2_10021, "physicalInterface is required when vSwitchType is [%s]", msg.getvSwitchType())); } @@ -133,26 +145,45 @@ private void validate(APICreateL2NetworkMsg msg) { private void validate(APIChangeL2NetworkVlanIdMsg msg) { L2NetworkVO l2 = dbf.findByUuid(msg.getL2NetworkUuid(), L2NetworkVO.class); - l2.getAttachedClusterRefs().forEach(ref -> { - if (Q.New(HostVO.class).eq(HostVO_.clusterUuid, ref.getClusterUuid()) - .notEq(HostVO_.status, HostStatus.Connected).isExists()) { - throw new ApiMessageInterceptionException(operr(ORG_ZSTACK_NETWORK_L2_10013, "cannot change vlan for l2Network[uuid:%s]" + - " because there are hosts status in Connecting or Disconnected", l2.getUuid())); - } - if (!Q.New(ClusterVO.class).eq(ClusterVO_.uuid, ref.getClusterUuid()) - .eq(ClusterVO_.hypervisorType, L2NetworkConstant.KVM_HYPERVISOR_TYPE).isExists()) { - throw new ApiMessageInterceptionException(operr(ORG_ZSTACK_NETWORK_L2_10014, "cannot change vlan for l2Network[uuid:%s]" + - " because it only supports an L2Network that is exclusively attached to a kvm cluster", l2.getUuid())); - } - }); + if (!L2NetworkConstant.VSWITCH_TYPE_ZNS.equals(l2.getvSwitchType())) { + l2.getAttachedClusterRefs().forEach(ref -> { + if (Q.New(HostVO.class).eq(HostVO_.clusterUuid, ref.getClusterUuid()) + .notEq(HostVO_.status, HostStatus.Connected).isExists()) { + throw new ApiMessageInterceptionException(operr(ORG_ZSTACK_NETWORK_L2_10013, "cannot change vlan for l2Network[uuid:%s]" + + " because there are hosts status in Connecting or Disconnected", l2.getUuid())); + } + if (!Q.New(ClusterVO.class).eq(ClusterVO_.uuid, ref.getClusterUuid()) + .eq(ClusterVO_.hypervisorType, L2NetworkConstant.KVM_HYPERVISOR_TYPE).isExists()) { + throw new ApiMessageInterceptionException(operr(ORG_ZSTACK_NETWORK_L2_10014, "cannot change vlan for l2Network[uuid:%s]" + + " because it only supports an L2Network that is exclusively attached to a kvm cluster", l2.getUuid())); + } + }); + } // pvlan isolated not support change vlan if (l2.getIsolated()) { throw new ApiMessageInterceptionException(argerr(ORG_ZSTACK_NETWORK_L2_10015, "cannot change vlan for l2Network[uuid:%s]" + " because this l2Network is isolated", l2.getUuid())); } + String targetType = StringUtils.trimToNull(msg.getType()); + msg.setType(targetType); + // When type is not specified (or blank), default to the current network type. + if (targetType == null) { + targetType = l2.getType(); + msg.setType(targetType); + } + + boolean targetIsVlan = L2NetworkConstant.L2_VLAN_NETWORK_TYPE.equals(targetType); + boolean targetIsNoVlan = L2NetworkConstant.L2_NO_VLAN_NETWORK_TYPE.equals(targetType); + boolean targetIsGeneve = L2NetworkConstant.L2_GENEVE_NETWORK_TYPE.equals(targetType); + boolean targetIsVxlan = L2NetworkConstant.VXLAN_NETWORK_TYPE.equals(targetType); + if (!targetIsVlan && !targetIsNoVlan && !targetIsGeneve && !targetIsVxlan) { + throw new ApiMessageInterceptionException(argerr(ORG_ZSTACK_NETWORK_L2_10021, + "unsupported l2Network type[%s] for ChangeL2NetworkVlanId", targetType)); + } + String sdnControllerUuid = L2NetworkSystemTags.L2_NETWORK_SDN_CONTROLLER_UUID .getTokenByResourceUuid(msg.getL2NetworkUuid(), L2NetworkSystemTags.L2_NETWORK_SDN_CONTROLLER_UUID_TOKEN); - if (msg.getType().equals(L2NetworkConstant.L2_VLAN_NETWORK_TYPE)) { + if (targetIsVlan) { if (msg.getVlan() == null) { throw new ApiMessageInterceptionException(argerr(ORG_ZSTACK_NETWORK_L2_10016, "vlan is required for " + "ChangeL2NetworkVlanId with type[%s]", msg.getType())); @@ -163,7 +194,9 @@ private void validate(APIChangeL2NetworkVlanIdMsg msg) { List attachedClusters = l2.getAttachedClusterRefs().stream() .map(L2NetworkClusterRefVO::getClusterUuid).collect(Collectors.toList()); List l2s; - if (sdnControllerUuid == null) { + if (attachedClusters.isEmpty()) { + l2s = java.util.Collections.emptyList(); + } else if (sdnControllerUuid == null) { l2s = SQL.New("select l2" + " from L2NetworkVO l2, L2NetworkClusterRefVO ref" + " where l2.uuid = ref.l2NetworkUuid" + @@ -196,7 +229,7 @@ private void validate(APIChangeL2NetworkVlanIdMsg msg) { throw new ApiMessageInterceptionException(argerr(ORG_ZSTACK_NETWORK_L2_10018, "There has been a l2Network attached to cluster with virtual network id[%s] and physical interface[%s]. Failed to change L2 network[uuid:%s]", msg.getVlan(), l2.getPhysicalInterface(), l2.getUuid())); } - } else if (msg.getType().equals(L2NetworkConstant.L2_NO_VLAN_NETWORK_TYPE)) { + } else if (targetIsNoVlan) { if (msg.getVlan() != null) { throw new ApiMessageInterceptionException(argerr(ORG_ZSTACK_NETWORK_L2_10019, "vlan is not allowed for " + "ChangeL2NetworkVlanId with type[%s]", msg.getType())); @@ -204,7 +237,9 @@ private void validate(APIChangeL2NetworkVlanIdMsg msg) { List attachedClusters = l2.getAttachedClusterRefs().stream() .map(L2NetworkClusterRefVO::getClusterUuid).collect(Collectors.toList()); List l2s; - if (sdnControllerUuid != null) { + if (attachedClusters.isEmpty()) { + l2s = java.util.Collections.emptyList(); + } else if (sdnControllerUuid != null) { l2s = SQL.New("select l2" + " from L2NetworkVO l2, L2NetworkClusterRefVO ref, SystemTagVO tag" + " where l2.uuid = ref.l2NetworkUuid" + @@ -233,6 +268,15 @@ private void validate(APIChangeL2NetworkVlanIdMsg msg) { throw new ApiMessageInterceptionException(argerr(ORG_ZSTACK_NETWORK_L2_10020, "There has been a l2Network attached to cluster that has physical interface[%s]. Failed to change l2Network[uuid:%s]", l2.getPhysicalInterface(), l2.getUuid())); } + } else if (targetIsGeneve || targetIsVxlan) { + if (msg.getVlan() == null) { + throw new ApiMessageInterceptionException(argerr(ORG_ZSTACK_NETWORK_L2_10016, "vni is required for " + + "ChangeL2NetworkVlanId with type[%s]", msg.getType())); + } + if (!NetworkUtils.isValidVni(msg.getVlan())) { + throw new ApiMessageInterceptionException(argerr(ORG_ZSTACK_NETWORK_L2_10017, "invalid vni[%d] for " + + "ChangeL2NetworkVlanId, must be between 1 and %d", msg.getVlan(), L2NetworkConstant.VXLAN_ID_MAX)); + } } } } diff --git a/network/src/main/java/org/zstack/network/l2/L2NetworkExtensionPointEmitter.java b/network/src/main/java/org/zstack/network/l2/L2NetworkExtensionPointEmitter.java index fa864bafaf2..b1eecae4d5e 100755 --- a/network/src/main/java/org/zstack/network/l2/L2NetworkExtensionPointEmitter.java +++ b/network/src/main/java/org/zstack/network/l2/L2NetworkExtensionPointEmitter.java @@ -53,6 +53,20 @@ public void run(L2NetworkDeleteExtensionPoint arg) { }); } + public void beforeUpdate(final L2NetworkInventory inv) { + for (L2NetworkUpdateExtensionPoint ext : updateExtensions) { + try { + ext.beforeChangeL2NetworkVlanId(inv); + } catch (RuntimeException e) { + // propagate validation failures and other runtime exceptions immediately + throw e; + } catch (Exception e) { + logger.warn(String.format("unhandled exception in L2NetworkUpdateExtensionPoint.beforeChangeL2NetworkVlanId of %s", + ext.getClass().getCanonicalName()), e); + } + } + } + public void afterUpdate(final L2NetworkInventory inv) { CollectionUtils.safeForEach(updateExtensions, arg -> arg.afterChangeL2NetworkVlanId(inv)); } diff --git a/network/src/main/java/org/zstack/network/l2/L2NetworkHostHelper.java b/network/src/main/java/org/zstack/network/l2/L2NetworkHostHelper.java index a612b3847c5..0136649f4bf 100644 --- a/network/src/main/java/org/zstack/network/l2/L2NetworkHostHelper.java +++ b/network/src/main/java/org/zstack/network/l2/L2NetworkHostHelper.java @@ -15,7 +15,6 @@ import java.util.HashSet; import java.util.List; import java.util.Set; -import java.util.stream.Collectors; import static java.util.Arrays.asList; @@ -87,6 +86,10 @@ public L2NetworkHostRefInventory getL2NetworkHostRef(String l2NetworkUuid, Strin } public static Set getHostsByL2NetworkAttachedCluster(L2NetworkInventory l2NetworkInventory) { + if (l2NetworkInventory.getAttachedClusterUuids() == null || l2NetworkInventory.getAttachedClusterUuids().isEmpty()) { + return new HashSet<>(); + } + return new HashSet<>(Q.New(HostVO.class) .in(HostVO_.clusterUuid, l2NetworkInventory.getAttachedClusterUuids()) .notIn(HostVO_.state,asList(HostState.PreMaintenance, HostState.Maintenance)) diff --git a/network/src/main/java/org/zstack/network/l2/L2NoVlanNetwork.java b/network/src/main/java/org/zstack/network/l2/L2NoVlanNetwork.java index 821a76ad462..ec9a7a5be0b 100755 --- a/network/src/main/java/org/zstack/network/l2/L2NoVlanNetwork.java +++ b/network/src/main/java/org/zstack/network/l2/L2NoVlanNetwork.java @@ -443,6 +443,7 @@ public String getSyncSignature() { @Override public void run(SyncTaskChain chain) { + extpEmitter.beforeUpdate(getSelfInventory()); changeL2NetworkVlanId(msg, new Completion(chain) { @Override public void success() { @@ -968,6 +969,10 @@ protected void scripts() { } L2NetworkVO tl2 = Q.New(L2NetworkVO.class).eq(L2NetworkVO_.uuid, msg.getL2NetworkUuid()).find(); + // ZNS L2NoVlan segments are uniquely identified by SDN controller, not by physicalInterface + if (L2NetworkConstant.VSWITCH_TYPE_ZNS.equals(tl2.getvSwitchType())) { + return; + } for (L2NetworkVO l2 : l2s) { if (l2.getPhysicalInterface().equals(tl2.getPhysicalInterface())) { throw new ApiMessageInterceptionException(argerr(ORG_ZSTACK_NETWORK_L2_10006, "There has been a l2Network[uuid:%s, name:%s] attached to cluster[uuid:%s] that has physical interface[%s]. Failed to attach l2Network[uuid:%s]", @@ -980,8 +985,10 @@ protected void scripts() { l2s = SQL.New("select l2" + " from L2VlanNetworkVO l2, L2NetworkClusterRefVO ref" + " where l2.uuid = ref.l2NetworkUuid" + - " and ref.clusterUuid = :clusterUuid") - .param("clusterUuid", msg.getClusterUuid()).list(); + " and ref.clusterUuid = :clusterUuid" + + " and l2.vSwitchType != :znsType") + .param("clusterUuid", msg.getClusterUuid()) + .param("znsType", L2NetworkConstant.VSWITCH_TYPE_ZNS).list(); } else { l2s = SQL.New("select l2" + " from L2VlanNetworkVO l2, L2NetworkClusterRefVO ref, SystemTagVO tag" + 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 d7c6c6798d9..43849b41e34 100755 --- a/network/src/main/java/org/zstack/network/l3/L3BasicNetwork.java +++ b/network/src/main/java/org/zstack/network/l3/L3BasicNetwork.java @@ -1047,6 +1047,7 @@ public void fail(ErrorCode errorCode) { private void handle(APIUpdateIpRangeMsg msg) { IpRangeVO vo = dbf.findByUuid(msg.getUuid(), IpRangeVO.class); + IpRangeInventory oldIpr = IpRangeInventory.valueOf(vo); boolean update = false; if (msg.getName() != null) { vo.setName(msg.getName()); @@ -1059,8 +1060,14 @@ private void handle(APIUpdateIpRangeMsg msg) { if (update) { vo = dbf.updateAndRefresh(vo); } + + IpRangeInventory newIpr = IpRangeInventory.valueOf(vo); + for (AfterUpdateIpRangeExtensionPoint ext : pluginRgty.getExtensionList(AfterUpdateIpRangeExtensionPoint.class)) { + ext.afterUpdateIpRange(oldIpr, newIpr); + } + APIUpdateIpRangeEvent evt = new APIUpdateIpRangeEvent(msg.getId()); - evt.setInventory(IpRangeInventory.valueOf(vo)); + evt.setInventory(newIpr); bus.publish(evt); } @@ -1534,12 +1541,14 @@ public void done(ErrorCodeList errorCodeList) { detachNetworkServiceFromL3NetworkMsg(l3VO, refVOS, new Completion(msg) { @Override public void success() { + dbf.removeCollection(refVOS, NetworkServiceL3NetworkRefVO.class); reply.setError(errorCodeList.getCauses().get(0)); bus.reply(msg, reply); } @Override public void fail(ErrorCode errorCode) { + dbf.removeCollection(refVOS, NetworkServiceL3NetworkRefVO.class); reply.setError(errorCodeList.getCauses().get(0)); bus.reply(msg, reply); } @@ -1551,6 +1560,13 @@ public void fail(ErrorCode errorCode) { private void handle(APIAttachNetworkServiceToL3NetworkMsg msg) { APIAttachNetworkServiceToL3NetworkEvent evt = new APIAttachNetworkServiceToL3NetworkEvent(msg.getId()); + if (msg.isSkipAttach()) { + self = dbf.reload(self); + evt.setInventory(L3NetworkInventory.valueOf(self)); + bus.publish(evt); + return; + } + AttachNetworkServiceToL3Msg amsg = new AttachNetworkServiceToL3Msg(); amsg.setL3NetworkUuid(msg.getL3NetworkUuid()); amsg.setNetworkServices(msg.getNetworkServices()); diff --git a/network/src/main/java/org/zstack/network/l3/L3NetworkManagerImpl.java b/network/src/main/java/org/zstack/network/l3/L3NetworkManagerImpl.java index 81fb7e94b3f..45fecdc0aa1 100755 --- a/network/src/main/java/org/zstack/network/l3/L3NetworkManagerImpl.java +++ b/network/src/main/java/org/zstack/network/l3/L3NetworkManagerImpl.java @@ -184,6 +184,41 @@ public void run(MessageReply reply) { } }); } + }).then(new NoRollbackFlow() { + @Override + public void run(FlowTrigger trigger, Map data) { + List exts = + pluginRgty.getExtensionList(AfterSetL3NetworkMtuExtensionPoint.class); + if (exts.isEmpty()) { + trigger.next(); + return; + } + + L3NetworkInventory l3Inv = L3NetworkInventory.valueOf(dbf.findByUuid(msg.getL3NetworkUuid(), L3NetworkVO.class)); + new While<>(exts).each((ext, wcompl) -> { + ext.afterSetL3NetworkMtu(l3Inv, msg.getMtu(), new Completion(wcompl) { + @Override + public void success() { + wcompl.done(); + } + + @Override + public void fail(ErrorCode errorCode) { + wcompl.addError(errorCode); + wcompl.allDone(); + } + }); + }).run(new WhileDoneCompletion(trigger) { + @Override + public void done(ErrorCodeList errorCodeList) { + if (errorCodeList.getCauses().isEmpty()) { + trigger.next(); + } else { + trigger.fail(errorCodeList.getCauses().get(0)); + } + } + }); + } }).done(new FlowDoneHandler(msg) { @Override public void handle(Map data) { @@ -192,8 +227,8 @@ public void handle(Map data) { }).error(new FlowErrorHandler(msg) { @Override public void handle(ErrorCode errCode, Map data) { + NetworkServiceSystemTag.L3_MTU.delete(msg.getL3NetworkUuid()); if (oldmtu != null) { - NetworkServiceSystemTag.L3_MTU.delete(msg.getL3NetworkUuid()); SystemTagCreator creator = NetworkServiceSystemTag.L3_MTU.newSystemTagCreator(msg.getL3NetworkUuid()); creator.recreate = true; creator.inherent = false; @@ -518,6 +553,7 @@ private void handle(APICreateL3NetworkMsg msg) { vo.setIpVersion(IPv6Constants.IPv4); } vo.setInternalId((int)dbf.generateSequenceNumber(L3NetworkSequenceNumberVO.class)); + vo.setType(msg.getType() != null ? msg.getType() : L3NetworkConstant.L3_BASIC_NETWORK_TYPE); FlowChain fchain = new SimpleFlowChain(); fchain.setName(String.format("create-l3-network-%s", vo.getUuid())); diff --git a/network/src/main/java/org/zstack/network/service/DhcpExtension.java b/network/src/main/java/org/zstack/network/service/DhcpExtension.java index 8e37da8b1e9..ff66b997243 100755 --- a/network/src/main/java/org/zstack/network/service/DhcpExtension.java +++ b/network/src/main/java/org/zstack/network/service/DhcpExtension.java @@ -437,6 +437,7 @@ public void enableNetworkService(L3NetworkVO l3VO, NetworkServiceProviderType pr SdnControllerEnableDHCPMsg msg = new SdnControllerEnableDHCPMsg(); msg.setL3NetworkUuid(l3VO.getUuid()); msg.setSdnControllerUuid(sdnControllerUuid); + msg.setSystemTags(systemTags); bus.makeTargetServiceIdByResourceUuid(msg, SdnControllerConstant.SERVICE_ID, sdnControllerUuid); bus.send(msg, new CloudBusCallBack(completion) { @Override diff --git a/network/src/main/java/org/zstack/network/service/MtuGetter.java b/network/src/main/java/org/zstack/network/service/MtuGetter.java index 9635ca3f0f5..b53da773b90 100644 --- a/network/src/main/java/org/zstack/network/service/MtuGetter.java +++ b/network/src/main/java/org/zstack/network/service/MtuGetter.java @@ -3,6 +3,7 @@ import org.springframework.beans.factory.annotation.Autowire; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Configurable; +import org.zstack.core.Platform; import org.zstack.core.componentloader.PluginRegistry; import org.zstack.core.db.Q; import org.zstack.header.network.l2.*; @@ -28,6 +29,13 @@ public class MtuGetter { @Autowired private PluginRegistry pluginRgty; + private PluginRegistry getPluginRegistry() { + if (pluginRgty == null) { + pluginRgty = Platform.getComponentLoader().getComponent(PluginRegistry.class); + } + return pluginRgty; + } + public Integer getMtu(String l3NetworkUuid) { String l2NetworkUuid = Q.New(L3NetworkVO.class).select(L3NetworkVO_.l2NetworkUuid).eq(L3NetworkVO_.uuid, l3NetworkUuid).findValue(); @@ -43,7 +51,7 @@ public Integer getMtu(String l3NetworkUuid) { } L2NetworkVO l2VO = Q.New(L2NetworkVO.class).eq(L2NetworkVO_.uuid, l2NetworkUuid).find(); - for (L2NetworkDefaultMtu e : pluginRgty.getExtensionList(L2NetworkDefaultMtu.class)) { + for (L2NetworkDefaultMtu e : getPluginRegistry().getExtensionList(L2NetworkDefaultMtu.class)) { if (l2VO.getType().equals(e.getL2NetworkType())) { mtu = e.getDefaultMtu(L2NetworkInventory.valueOf(l2VO)); } @@ -82,7 +90,7 @@ public Integer getL2Mtu(L2NetworkInventory l2Inv) { } /* compare to default mtu */ - for (L2NetworkDefaultMtu e : pluginRgty.getExtensionList(L2NetworkDefaultMtu.class)) { + for (L2NetworkDefaultMtu e : getPluginRegistry().getExtensionList(L2NetworkDefaultMtu.class)) { if (l2Inv.getType().equals(e.getL2NetworkType())) { Integer l2mtu = e.getDefaultMtu(l2Inv); if (mtu == null) { diff --git a/network/src/main/java/org/zstack/network/service/NetworkServiceApiInterceptor.java b/network/src/main/java/org/zstack/network/service/NetworkServiceApiInterceptor.java index dad5d87781a..9b95e53ee9a 100755 --- a/network/src/main/java/org/zstack/network/service/NetworkServiceApiInterceptor.java +++ b/network/src/main/java/org/zstack/network/service/NetworkServiceApiInterceptor.java @@ -1,6 +1,7 @@ package org.zstack.network.service; import org.springframework.beans.factory.annotation.Autowired; +import org.zstack.core.componentloader.PluginRegistry; import org.zstack.core.db.DatabaseFacade; import org.zstack.core.db.SimpleQuery; import org.zstack.core.db.SimpleQuery.Op; @@ -29,16 +30,22 @@ /** */ -public class NetworkServiceApiInterceptor implements ApiMessageInterceptor { - private final static CLogger logger = Utils.getLogger(NetworkServiceApiInterceptor.class); - @Autowired +public class NetworkServiceApiInterceptor implements ApiMessageInterceptor { + private final static CLogger logger = Utils.getLogger(NetworkServiceApiInterceptor.class); + @Autowired private DatabaseFacade dbf; + @Autowired + private PluginRegistry pluginRgty; @Override public APIMessage intercept(APIMessage msg) throws ApiMessageInterceptionException { if (msg instanceof APIAttachNetworkServiceToL3NetworkMsg) { APIAttachNetworkServiceToL3NetworkMsg attachMsg = (APIAttachNetworkServiceToL3NetworkMsg)msg; attachMsg.setNetworkServices(convertNetworkProviderTypeToUuid(attachMsg.getNetworkServices())); + if (skipAttachNetworkService(attachMsg)) { + attachMsg.setSkipAttach(true); + return msg; + } validate(attachMsg); } else if (msg instanceof APIDetachNetworkServiceFromL3NetworkMsg) { APIDetachNetworkServiceFromL3NetworkMsg detachMsg = (APIDetachNetworkServiceFromL3NetworkMsg)msg; @@ -59,6 +66,15 @@ public APIMessage intercept(APIMessage msg) throws ApiMessageInterceptionExcepti return msg; } + private boolean skipAttachNetworkService(APIAttachNetworkServiceToL3NetworkMsg msg) { + for (NetworkServiceAttachExtensionPoint ext : pluginRgty.getExtensionList(NetworkServiceAttachExtensionPoint.class)) { + if (ext.skipAttachNetworkService(msg)) { + return true; + } + } + return false; + } + private void validate(APIAttachNetworkServiceToL3NetworkMsg msg) { if (msg.getNetworkServices().isEmpty()) { throw new ApiMessageInterceptionException(argerr(ORG_ZSTACK_NETWORK_SERVICE_10006, "networkServices cannot be empty")); @@ -157,11 +173,11 @@ public String call(String type) { } private Map> convertNetworkProviderTypeToUuid(Map> map){ - if (map.isEmpty()) { + Map> mapNew = normalizeNetworkServices(map); + if (mapNew.isEmpty()) { throw new ApiMessageInterceptionException(argerr(ORG_ZSTACK_NETWORK_SERVICE_10012, "networkServices cannot be empty")); } - Map> mapNew = new HashMap<>(map); List networkServiceProviderVOs = Q.New(NetworkServiceProviderVO.class).list(); for (NetworkServiceProviderVO vo :networkServiceProviderVOs) { @@ -172,4 +188,39 @@ private Map> convertNetworkProviderTypeToUuid(Map> normalizeNetworkServices(Map> map) { + Map> ret = new LinkedHashMap<>(); + if (map == null) { + return ret; + } + + for (Map.Entry> entry : map.entrySet()) { + if (entry.getKey() == null) { + continue; + } + + String provider = entry.getKey().trim(); + if (provider.isEmpty()) { + continue; + } + + List services = new ArrayList<>(); + if (entry.getValue() != null) { + for (String service : entry.getValue()) { + if (service == null) { + continue; + } + + String normalized = service.trim(); + if (!normalized.isEmpty()) { + services.add(normalized); + } + } + } + + ret.computeIfAbsent(provider, k -> new ArrayList<>()).addAll(services); + } + return ret; + } } diff --git a/plugin/applianceVm/src/main/java/org/zstack/appliancevm/ApplianceVmConstant.java b/plugin/applianceVm/src/main/java/org/zstack/appliancevm/ApplianceVmConstant.java index dcada8edeee..094771f24bb 100755 --- a/plugin/applianceVm/src/main/java/org/zstack/appliancevm/ApplianceVmConstant.java +++ b/plugin/applianceVm/src/main/java/org/zstack/appliancevm/ApplianceVmConstant.java @@ -47,6 +47,7 @@ public static enum Params { timeout, rebuildSnat, fromApi, + skipGrayscaleUpgradeCheck, } public static final String REFRESH_FIREWALL_PATH = "/appliancevm/refreshfirewall"; diff --git a/plugin/applianceVm/src/main/java/org/zstack/appliancevm/ApplianceVmFacadeImpl.java b/plugin/applianceVm/src/main/java/org/zstack/appliancevm/ApplianceVmFacadeImpl.java index 6d63ce3522f..76d98729668 100755 --- a/plugin/applianceVm/src/main/java/org/zstack/appliancevm/ApplianceVmFacadeImpl.java +++ b/plugin/applianceVm/src/main/java/org/zstack/appliancevm/ApplianceVmFacadeImpl.java @@ -296,7 +296,7 @@ class VmDestroyHook implements VmInstanceBeforeDestroyHook, VmInstanceAfterDestr @Override public void afterDestroy(VmInstanceInventory vm) { if (applianceVm != null) { - ApplianceVmCanonicalEvents.NewVmCreatedData data = new ApplianceVmCanonicalEvents.NewVmCreatedData(); + ApplianceVmCanonicalEvents.VmDestroyedData data = new ApplianceVmCanonicalEvents.VmDestroyedData(); data.vm = applianceVm; data.fire(); } 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 c3b01dc3c8b..fab8dd0b583 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 @@ -5429,6 +5429,139 @@ public void handle(ErrorCode errCode, Map data) { }).start(); } + @Override + protected void handle(final ReInitDataVolumeOnPrimaryStorageMsg msg) { + final ReInitDataVolumeOnPrimaryStorageReply reply = new ReInitDataVolumeOnPrimaryStorageReply(); + + final FlowChain chain = FlowChainBuilder.newShareFlowChain(); + chain.setName(String.format("reinit-data-volume-%s", msg.getVolume().getUuid())); + chain.then(new ShareFlow() { + final String originalVolumePath = msg.getVolume().getInstallPath(); + final String targetPoolName = getTargetPoolNameFromAllocatedUrl(msg.getAllocatedInstallUrl()); + String newVolumePath = makeReInitDataVolumeInstallPath(msg.getVolume().getUuid(), targetPoolName); + boolean newVolumeCreated; + + @Override + public void setup() { + flow(new NoRollbackFlow() { + String __name__ = "create-empty-data-volume"; + + @Override + public void run(final FlowTrigger trigger, Map data) { + CreateEmptyVolumeCmd cmd = new CreateEmptyVolumeCmd(); + cmd.installPath = newVolumePath; + cmd.size = msg.getVolume().getSize(); + cmd.setShareable(msg.getVolume().isShareable()); + httpCall(CREATE_VOLUME_PATH, cmd, CreateEmptyVolumeRsp.class, new ReturnValueCompletion(trigger) { + @Override + public void success(CreateEmptyVolumeRsp ret) { + newVolumeCreated = true; + trigger.next(); + } + + @Override + public void fail(ErrorCode err) { + trigger.fail(err); + } + }); + } + }); + + flow(new NoRollbackFlow() { + String __name__ = "delete-origin-data-volume-which-has-no-snapshot"; + + @Override + public void run(FlowTrigger trigger, Map data) { + long snapshotCount = Q.New(VolumeSnapshotVO.class) + .like(VolumeSnapshotVO_.primaryStorageInstallPath, + String.format("%s@%%", originalVolumePath)) + .count(); + if (snapshotCount == 0) { + DeleteCmd cmd = new DeleteCmd(); + cmd.installPath = originalVolumePath; + httpCall(DELETE_PATH, cmd, DeleteRsp.class, new ReturnValueCompletion(null) { + @Override + public void success(DeleteRsp returnValue) { + logger.debug(String.format("successfully deleted %s", originalVolumePath)); + } + + @Override + public void fail(ErrorCode errorCode) { + logger.warn(String.format("unable to delete %s, %s. Need a cleanup", + originalVolumePath, errorCode)); + trash.createTrash(TrashType.ReInitDataVolume, false, msg.getVolume()); + } + }); + } else { + trash.createTrash(TrashType.ReInitDataVolume, false, msg.getVolume()); + } + trigger.next(); + } + }); + + done(new FlowDoneHandler(msg) { + @Override + public void handle(Map data) { + reply.setNewVolumeInstallPath(newVolumePath); + bus.reply(msg, reply); + } + }); + + error(new FlowErrorHandler(msg) { + @Override + public void handle(ErrorCode errCode, Map data) { + if (newVolumeCreated) { + cleanupNewReInitDataVolumeBits(newVolumePath, msg.getVolume()); + } + reply.setError(errCode); + bus.reply(msg, reply); + } + }); + } + }).start(); + } + + private void cleanupNewReInitDataVolumeBits(String installPath, VolumeInventory volume) { + DeleteCmd cmd = new DeleteCmd(); + cmd.installPath = installPath; + httpCall(DELETE_PATH, cmd, DeleteRsp.class, new ReturnValueCompletion(null) { + @Override + public void success(DeleteRsp returnValue) { + logger.debug(String.format("successfully deleted reinit new volume bits[path:%s, volumeUuid:%s]", + installPath, volume.getUuid())); + } + + @Override + public void fail(ErrorCode errorCode) { + logger.warn(String.format("unable to delete reinit new volume bits[path:%s, volumeUuid:%s], submit GC. %s", + installPath, volume.getUuid(), errorCode)); + submitNewReInitDataVolumeBitsGC(installPath, volume); + } + }); + } + + private void submitNewReInitDataVolumeBitsGC(String installPath, VolumeInventory volume) { + VolumeInventory cleanupVolume = new VolumeInventory(); + cleanupVolume.setUuid(volume.getUuid()); + cleanupVolume.setInstallPath(installPath); + cleanupVolume.setPrimaryStorageUuid(volume.getPrimaryStorageUuid()); + cleanupVolume.setFormat(volume.getFormat()); + cleanupVolume.setSize(0L); + + CephDeleteVolumeGC gc = new CephDeleteVolumeGC(); + gc.NAME = String.format("gc-ceph-%s-reinit-volume-%s-new-bits", self.getUuid(), volume.getUuid()); + gc.primaryStorageUuid = self.getUuid(); + gc.volume = cleanupVolume; + gc.deduplicateSubmit(CephGlobalConfig.GC_INTERVAL.value(Long.class), TimeUnit.SECONDS); + } + + private String makeReInitDataVolumeInstallPath(String volUuid, String targetPoolName) { + return String.format("ceph://%s/reinit-%s-%s", + targetPoolName, + volUuid, + System.currentTimeMillis()); + } + @Override protected void handle(DeleteSnapshotOnPrimaryStorageMsg msg) { inQueue().name(String.format("delete-snapshot-on-primarystorage-%s", self.getUuid())) diff --git a/plugin/expon/src/main/java/org/zstack/expon/ExponStorageController.java b/plugin/expon/src/main/java/org/zstack/expon/ExponStorageController.java index df5b1081d08..2f24bc3feaf 100644 --- a/plugin/expon/src/main/java/org/zstack/expon/ExponStorageController.java +++ b/plugin/expon/src/main/java/org/zstack/expon/ExponStorageController.java @@ -620,14 +620,13 @@ public void cleanActiveRecord(ImageCacheInventory cache) { } @Override - public void blacklist(String installPath, String protocol, HostInventory h, Completion comp) { + public void blacklist(String installPath, String protocol, HostInventory h) { logger.debug(String.format("blacklisting volume[path: %s, protocol:%s] on host[uuid:%s, ip:%s]", installPath, protocol, h.getUuid(), h.getManagementIp())); UssGatewayModule uss = getUssGateway(VolumeProtocol.valueOf(protocol), h.getManagementIp()); VolumeModule exponVol = apiHelper.getVolume(getVolIdFromPath(installPath)); apiHelper.addVolumePathToBlacklist(buildExponVolumeBoundPath(uss, exponVol.getVolumeName())); - comp.success(); } @Override diff --git a/plugin/externalStorage/src/main/java/org/zstack/externalStorage/primary/kvm/ExternalPrimaryStorageKvmFactory.java b/plugin/externalStorage/src/main/java/org/zstack/externalStorage/primary/kvm/ExternalPrimaryStorageKvmFactory.java index 6e5c0c591b8..aa25ed03592 100644 --- a/plugin/externalStorage/src/main/java/org/zstack/externalStorage/primary/kvm/ExternalPrimaryStorageKvmFactory.java +++ b/plugin/externalStorage/src/main/java/org/zstack/externalStorage/primary/kvm/ExternalPrimaryStorageKvmFactory.java @@ -141,6 +141,27 @@ public void done(ErrorCodeList errorCodeList) { } }); } + }).then(new NoRollbackFlow() { + String __name__ = "ensure-heartbeat-volume"; + + @Override + public void run(FlowTrigger trigger, Map data) { + ensureHeartbeatVolume(context.getInventory(), extPss, new WhileDoneCompletion(trigger) { + @Override + public void done(ErrorCodeList errorCodeList) { + if (errorCodeList.getCauses().isEmpty()) { + trigger.next(); + } else { + logger.warn(String.format("failed to ensure heartbeat volumes before checking KVM host[uuid:%s, name:%s] storage connection, %s", + context.getInventory().getUuid(), context.getInventory().getName(), errorCodeList.getReadableDetails())); + trigger.fail(operr(ORG_ZSTACK_EXTERNALSTORAGE_PRIMARY_KVM_10000, + new ErrorCodeList().causedBy(errorCodeList.getCauses()), + "failed to ensure heartbeat volumes before checking KVM host[uuid:%s, name:%s] storage connection", + context.getInventory().getUuid(), context.getInventory().getName())); + } + } + }); + } }).then(new NoRollbackFlow() { String __name__ = "check-host-status"; @@ -167,6 +188,25 @@ public void handle(Map data) { }).start(); } + private void ensureHeartbeatVolume(HostInventory host, List extPss, WhileDoneCompletion completion) { + new While<>(extPss).each((extPs, compl) -> { + logger.debug(String.format("ensuring heartbeat volume for external primary storage[uuid:%s, name:%s] before checking KVM host[uuid:%s, name:%s] storage connection", + extPs.getUuid(), extPs.getName(), host.getUuid(), host.getName())); + extPsFactory.getNodeSvc(extPs.getUuid()).activateHeartbeatVolume(host, new ReturnValueCompletion(compl) { + @Override + public void success(HeartbeatVolumeTopology returnValue) { + compl.done(); + } + + @Override + public void fail(ErrorCode errorCode) { + compl.addError(errorCode); + compl.done(); + } + }); + }).run(completion); + } + private void deployClient(final KVMHostConnectedContext context, List extPss, WhileDoneCompletion completion) { new While<>(extPss).each((extPs, compl) -> { logger.debug(String.format("deploying client for external primary storage[uuid:%s, name:%s] on KVM host[uuid:%s, name:%s]", @@ -335,6 +375,9 @@ public void done(ErrorCodeList errorCodeList) { @Override public void beforeStartVmOnKvm(KVMHostInventory host, VmInstanceSpec spec, KVMAgentCommands.StartVmCmd cmd) { List vols = getManagerExclusiveVolume(spec); + // captured here so blacklist can be invoked from the for-each body itself; a throw from + // inside the Completion callback would be eaten by AsyncSafeAspect on deactivate. + ErrorCode[] deactivateErr = new ErrorCode[1]; for (VolumeInventory vol : vols) { PrimaryStorageNodeSvc nodeSvc = extPsFactory.getNodeSvc(vol.getPrimaryStorageUuid()); @@ -360,6 +403,7 @@ public void beforeStartVmOnKvm(KVMHostInventory host, VmInstanceSpec spec, KVMAg clientHost.getUuid(), clientHost.getManagementIp(), host.getUuid(), host.getManagementIp())); + deactivateErr[0] = null; nodeSvc.deactivate(vol.getInstallPath(), vol.getProtocol(), client, new Completion(null) { @Override public void success() { @@ -369,11 +413,14 @@ public void success() { @Override public void fail(ErrorCode errorCode) { - logger.warn(String.format("failed to deactivate volume[uuid:%s, installPath:%s] on host[uuid:%s, ip:%s], add it to blacklist", - vol.getUuid(), vol.getInstallPath(), clientHost.getUuid(), clientHost.getManagementIp())); - nodeSvc.blacklist(vol.getInstallPath(), vol.getProtocol(), HostInventory.valueOf(clientHost), new NopeCompletion()); + deactivateErr[0] = errorCode; } }); + if (deactivateErr[0] != null) { + logger.warn(String.format("failed to deactivate volume[uuid:%s, installPath:%s] on host[uuid:%s, ip:%s]: %s, add it to blacklist", + vol.getUuid(), vol.getInstallPath(), clientHost.getUuid(), clientHost.getManagementIp(), deactivateErr[0].getDetails())); + nodeSvc.blacklist(vol.getInstallPath(), vol.getProtocol(), HostInventory.valueOf(clientHost)); + } } } }); diff --git a/plugin/flatNetworkProvider/src/main/java/org/zstack/network/service/flat/FlatDhcpBackend.java b/plugin/flatNetworkProvider/src/main/java/org/zstack/network/service/flat/FlatDhcpBackend.java index 5823bb2b9ee..db72febcf4d 100755 --- a/plugin/flatNetworkProvider/src/main/java/org/zstack/network/service/flat/FlatDhcpBackend.java +++ b/plugin/flatNetworkProvider/src/main/java/org/zstack/network/service/flat/FlatDhcpBackend.java @@ -996,7 +996,7 @@ public static Map getExistingDhcpServerIp(String l3Uuid, int ipV @Deferred private String allocateDhcpIp(String l3Uuid, int ipVersion, boolean allocate_ip, String requiredIp, String excludedIp) { - if (!isAllocateDhcpServerIp(l3Uuid)) { + if (!isAllocateDhcpServerIp(l3Uuid, ipVersion)) { return null; } @@ -1276,6 +1276,17 @@ private boolean isAllocateDhcpServerIp(String l3Uuid) { return type.isAllocateDhcpServerIp(); } + private boolean isAllocateDhcpServerIp(String l3Uuid, int ipVersion) { + String providerType = new NetworkProviderFinder().getNetworkProviderTypeByNetworkServiceType(l3Uuid, NetworkServiceType.DHCP.toString()); + if (providerType == null) { + return false; + } + + NetworkServiceProviderType type = NetworkServiceProviderType.valueOf(providerType); + return type.isAllocateDhcpServerIp() + && (ipVersion != IPv6Constants.IPv6 || type.isAllocateDhcpv6ServerIp()); + } + private boolean isCreateDhcpNameSpace(String l3Uuid) { String providerType = new NetworkProviderFinder().getNetworkProviderTypeByNetworkServiceType(l3Uuid, NetworkServiceType.DHCP.toString()); if (providerType == null) { @@ -2490,7 +2501,10 @@ private void validate(APIDetachNetworkServiceFromL3NetworkMsg msg) { } private void validate(APIChangeL3NetworkDhcpIpAddressMsg msg) { - if (!isAllocateDhcpServerIp(msg.getL3NetworkUuid())) { + if ((msg.getDhcpServerIp() != null && !isAllocateDhcpServerIp(msg.getL3NetworkUuid(), IPv6Constants.IPv4)) + || (msg.getDhcpv6ServerIp() != null && !isAllocateDhcpServerIp(msg.getL3NetworkUuid(), IPv6Constants.IPv6)) + || (msg.getDhcpServerIp() == null && msg.getDhcpv6ServerIp() == null + && !isAllocateDhcpServerIp(msg.getL3NetworkUuid()))) { throw new ApiMessageInterceptionException(argerr(ORG_ZSTACK_NETWORK_SERVICE_FLAT_10044, "could change dhcp server ip, because flat dhcp is not enabled")); } diff --git a/plugin/flatNetworkProvider/src/main/java/org/zstack/network/service/userdata/UserdataExtension.java b/plugin/flatNetworkProvider/src/main/java/org/zstack/network/service/userdata/UserdataExtension.java index 8e75c4edd53..0abb2aab587 100755 --- a/plugin/flatNetworkProvider/src/main/java/org/zstack/network/service/userdata/UserdataExtension.java +++ b/plugin/flatNetworkProvider/src/main/java/org/zstack/network/service/userdata/UserdataExtension.java @@ -1,10 +1,14 @@ package org.zstack.network.service.userdata; import org.springframework.beans.factory.annotation.Autowired; +import org.zstack.compute.vm.UserdataBuilder; import org.zstack.core.cloudbus.CloudBus; import org.zstack.core.componentloader.PluginRegistry; import org.zstack.core.db.DatabaseFacade; import org.zstack.core.db.Q; +import org.zstack.core.thread.ChainTask; +import org.zstack.core.thread.SyncTaskChain; +import org.zstack.core.thread.ThreadFacade; import org.zstack.header.Component; import org.zstack.header.core.Completion; import org.zstack.header.core.NoErrorCompletion; @@ -14,9 +18,15 @@ import org.zstack.header.network.l3.L3NetworkVO; import org.zstack.header.network.l3.L3NetworkVO_; import org.zstack.header.network.service.*; +import org.zstack.header.vm.VmAfterAttachNicExtensionPoint; +import org.zstack.header.vm.VmInstanceInventory; import org.zstack.header.vm.VmInstanceSpec; +import org.zstack.header.vm.VmInstanceState; +import org.zstack.header.vm.VmInstanceVO; import org.zstack.header.vm.VmNicInventory; import org.zstack.header.vm.VmNicSpec; +import org.zstack.header.vm.VmNicVO; +import org.zstack.header.vm.VmNicVO_; import org.zstack.network.securitygroup.SecurityGroupGetDefaultRuleExtensionPoint; import org.zstack.network.service.AbstractNetworkServiceExtension; import org.zstack.utils.CollectionUtils; @@ -25,11 +35,17 @@ import org.zstack.utils.network.IPv6Constants; import java.util.*; +import java.util.concurrent.TimeUnit; /** * Created by frank on 10/13/2015. */ -public class UserdataExtension extends AbstractNetworkServiceExtension implements Component, SecurityGroupGetDefaultRuleExtensionPoint { +public class UserdataExtension extends AbstractNetworkServiceExtension implements Component, + SecurityGroupGetDefaultRuleExtensionPoint, VmAfterAttachNicExtensionPoint { + private static final int APPLY_USERDATA_AFTER_ATTACH_NIC_RETRY_TIMES = 3; + private static final long APPLY_USERDATA_AFTER_ATTACH_NIC_INITIAL_DELAY_SECONDS = 0; + private static final long APPLY_USERDATA_AFTER_ATTACH_NIC_RETRY_DELAY_SECONDS = 5; + private CLogger logger = Utils.getLogger(UserdataExtension.class); @Autowired @@ -38,6 +54,8 @@ public class UserdataExtension extends AbstractNetworkServiceExtension implement private CloudBus bus; @Autowired private PluginRegistry pluginRgty; + @Autowired + private ThreadFacade thdf; private Map backends = new HashMap(); @@ -150,6 +168,162 @@ public List getGroupMembers(String sgUuid, int ipVersion) { return members; } + private boolean isAttachedNicOnDefaultL3(String nicUuid, VmInstanceInventory vm) { + if (vm.getDefaultL3NetworkUuid() == null) { + return false; + } + + String l3NetworkUuid = Q.New(VmNicVO.class) + .select(VmNicVO_.l3NetworkUuid) + .eq(VmNicVO_.uuid, nicUuid) + .eq(VmNicVO_.vmInstanceUuid, vm.getUuid()) + .findValue(); + + return vm.getDefaultL3NetworkUuid().equals(l3NetworkUuid); + } + + @Override + public void afterAttachNic(String nicUuid, VmInstanceInventory vm, Completion completion) { + if (!VmInstanceState.Running.toString().equals(vm.getState())) { + completion.success(); + return; + } + + if (vm.getDefaultL3NetworkUuid() == null || vm.getHostUuid() == null) { + completion.success(); + return; + } + + scheduleApplyUserdataAfterAttachNic(vm.getUuid(), nicUuid, + APPLY_USERDATA_AFTER_ATTACH_NIC_INITIAL_DELAY_SECONDS, 1); + completion.success(); + } + + @Override + public void afterAttachNicRollback(String nicUuid, VmInstanceInventory vmInstanceInventory, NoErrorCompletion completion) { + completion.done(); + } + + private boolean needRefreshUserdataAfterAttachNic(String nicUuid, VmInstanceInventory vm) { + if (!VmInstanceState.Running.toString().equals(vm.getState())) { + return false; + } + + if (vm.getDefaultL3NetworkUuid() == null || vm.getHostUuid() == null) { + return false; + } + + return !isAttachedNicOnDefaultL3(nicUuid, vm); + } + + private void scheduleApplyUserdataAfterAttachNic(String vmUuid, String nicUuid, long delaySeconds, int currentAttempt) { + thdf.submitTimeoutTask(() -> thdf.chainSubmit(new ChainTask(null) { + @Override + public String getSyncSignature() { + return String.format("refresh-userdata-metadata-after-attach-nic-vm-%s", vmUuid); + } + + @Override + public void run(SyncTaskChain chain) { + applyUserdataAfterAttachNic(vmUuid, nicUuid, currentAttempt, new NoErrorCompletion(chain) { + @Override + public void done() { + chain.next(); + } + }); + } + + @Override + public String getName() { + return String.format("refresh-userdata-metadata-after-attach-nic-vm-%s", vmUuid); + } + }), + TimeUnit.SECONDS, delaySeconds); + } + + private void applyUserdataAfterAttachNic(String vmUuid, String nicUuid, int currentAttempt, NoErrorCompletion completion) { + try { + VmInstanceVO vmVO = dbf.findByUuid(vmUuid, VmInstanceVO.class); + if (vmVO == null) { + completion.done(); + return; + } + + VmInstanceInventory vm = VmInstanceInventory.valueOf(vmVO); + if (!needRefreshUserdataAfterAttachNic(nicUuid, vm)) { + completion.done(); + return; + } + + L3NetworkVO defaultL3VO = Q.New(L3NetworkVO.class) + .eq(L3NetworkVO_.uuid, vm.getDefaultL3NetworkUuid()) + .find(); + if (defaultL3VO == null) { + completion.done(); + return; + } + + L3NetworkInventory defaultL3 = L3NetworkInventory.valueOf(defaultL3VO); + if (!defaultL3.getIpVersions().contains(IPv6Constants.IPv4)) { + completion.done(); + return; + } + + NetworkServiceProviderInventory provider = findProvider(defaultL3); + if (provider == null) { + completion.done(); + return; + } + + UserdataStruct struct = new UserdataStruct(); + struct.setL3NetworkUuid(vm.getDefaultL3NetworkUuid()); + struct.setParametersFromVmInventory(vm); + struct.setUserdataList(new UserdataBuilder().buildByVmUuid(vm.getUuid())); + + UserdataBackend bkd = getUserdataBackend(provider.getType()); + bkd.applyUserdata(struct, new Completion(null) { + @Override + public void success() { + completion.done(); + } + + @Override + public void fail(ErrorCode errorCode) { + retryApplyUserdataAfterAttachNic(vmUuid, nicUuid, currentAttempt, errorCode, null); + completion.done(); + } + }); + } catch (Throwable t) { + if (t instanceof Error) { + logger.warn(String.format("fatal error happened when refreshing userdata metadata after attaching nic[uuid:%s] to vm[uuid:%s]", + nicUuid, vmUuid), t); + completion.done(); + throw (Error) t; + } + + retryApplyUserdataAfterAttachNic(vmUuid, nicUuid, currentAttempt, null, t); + completion.done(); + } + } + + private void retryApplyUserdataAfterAttachNic(String vmUuid, String nicUuid, int currentAttempt, ErrorCode errorCode, Throwable t) { + String reason = errorCode == null ? t.toString() : errorCode.toString(); + String warn = String.format("failed to refresh userdata metadata after attaching nic[uuid:%s] to vm[uuid:%s], attempt %s/%s, %s", + nicUuid, vmUuid, currentAttempt, APPLY_USERDATA_AFTER_ATTACH_NIC_RETRY_TIMES, reason); + if (t == null) { + logger.warn(warn); + } else { + logger.warn(warn, t); + } + + if (currentAttempt >= APPLY_USERDATA_AFTER_ATTACH_NIC_RETRY_TIMES) { + return; + } + + scheduleApplyUserdataAfterAttachNic(vmUuid, nicUuid, + APPLY_USERDATA_AFTER_ATTACH_NIC_RETRY_DELAY_SECONDS, currentAttempt + 1); + } + @Override public void releaseNetworkService(final VmInstanceSpec servedVm, Map data, final NoErrorCompletion completion) { L3NetworkInventory defaultL3 = CollectionUtils.find(VmNicSpec.getL3NetworkInventoryOfSpec(servedVm.getL3Networks()), diff --git a/plugin/kvm/src/main/java/org/zstack/kvm/KVMAgentCommands.java b/plugin/kvm/src/main/java/org/zstack/kvm/KVMAgentCommands.java index 90e576cad7f..bc13261fb77 100755 --- a/plugin/kvm/src/main/java/org/zstack/kvm/KVMAgentCommands.java +++ b/plugin/kvm/src/main/java/org/zstack/kvm/KVMAgentCommands.java @@ -90,6 +90,28 @@ public static class UpdateVmPriorityCmd extends AgentCommand { public static class UpdateVmPriorityRsp extends AgentResponse { } + public static class VmShmemDevice { + public String name; + public String path; + public long size; + } + + public static class HotPlugVmShmemCmd extends AgentCommand { + public String vmUuid; + public VmShmemDevice shmem; + } + + public static class HotPlugVmShmemRsp extends AgentResponse { + } + + public static class HotUnplugVmShmemCmd extends AgentCommand { + public String vmUuid; + public VmShmemDevice shmem; + } + + public static class HotUnplugVmShmemRsp extends AgentResponse { + } + public static class ChangeVmNicStateCommand extends AgentCommand { @GrayVersion(value = "5.0.0") private String vmUuid; @@ -339,6 +361,8 @@ public void setVersion(String version) { public static class ConnectResponse extends AgentResponse { private String libvirtVersion; private String qemuVersion; + private boolean firstConnect; + private long agentStartTimeMillis; public String getLibvirtVersion() { return libvirtVersion; @@ -355,6 +379,22 @@ public String getQemuVersion() { public void setQemuVersion(String qemuVersion) { this.qemuVersion = qemuVersion; } + + public boolean isFirstConnect() { + return firstConnect; + } + + public void setFirstConnect(boolean firstConnect) { + this.firstConnect = firstConnect; + } + + public long getAgentStartTimeMillis() { + return agentStartTimeMillis; + } + + public void setAgentStartTimeMillis(long agentStartTimeMillis) { + this.agentStartTimeMillis = agentStartTimeMillis; + } } public static class PingCmd extends AgentCommand { @@ -1014,6 +1054,42 @@ public static class SetVmConsolePasswordLiveCmd extends AgentCommand implements public void setPassword(String password) { this.password = password; } } + public static class SetupVmHaEnabledMetadataLiveCmd extends AgentCommand implements Serializable { + @GrayVersion(value = "5.5.22") + private String vmUuid; + @GrayVersion(value = "5.5.22") + private Boolean enableHa; + + public String getVmUuid() { + return vmUuid; + } + + public void setVmUuid(String vmUuid) { + this.vmUuid = vmUuid; + } + + public Boolean getEnableHa() { + return enableHa; + } + + public void setEnableHa(Boolean enableHa) { + this.enableHa = enableHa; + } + } + + public static class ReconcileVmHaEnabledMetadataLiveCmd extends AgentCommand implements Serializable { + @GrayVersion(value = "5.5.22") + private List neverStopVmUuids; + + public List getNeverStopVmUuids() { + return neverStopVmUuids; + } + + public void setNeverStopVmUuids(List neverStopVmUuids) { + this.neverStopVmUuids = neverStopVmUuids; + } + } + public static class UpdateL2NetworkCmd extends AgentCommand { private String physicalInterfaceName; private String bridgeName; @@ -1242,6 +1318,14 @@ public static class NicTO extends BaseVirtualDeviceTO { private Boolean isolated; + // bridge sub-type: null for Linux bridge, "openvswitch" for OVS bridge + // generates in libvirt XML + private String bridgePortType; + + // OVS external_ids:iface-id, used by SDN controller to identify the port + // generates + private String interfaceId; + public List getIps() { return ips; } @@ -1434,6 +1518,22 @@ public void setL2NetworkUuid(String l2NetworkUuid) { this.l2NetworkUuid = l2NetworkUuid; } + public String getBridgePortType() { + return bridgePortType; + } + + public void setBridgePortType(String bridgePortType) { + this.bridgePortType = bridgePortType; + } + + public String getInterfaceId() { + return interfaceId; + } + + public void setInterfaceId(String interfaceId) { + this.interfaceId = interfaceId; + } + public static NicTO fromVmNicInventory(VmNicInventory nic) { KVMAgentCommands.NicTO to = new KVMAgentCommands.NicTO(); to.setMac(nic.getMac()); @@ -2236,6 +2336,8 @@ public static class StartVmCmd extends vdiCmd implements VmAddOnsCmd { private String nestedVirtualization; @GrayVersion(value = "5.0.0") private String hostManagementIp; + @GrayVersion(value = "5.5.22") + private Boolean enableHa; @GrayVersion(value = "5.0.0") private String clock; @GrayVersion(value = "5.0.0") @@ -2726,6 +2828,14 @@ public void setHostManagementIp(String hostManagementIp) { this.hostManagementIp = hostManagementIp; } + public Boolean getEnableHa() { + return enableHa; + } + + public void setEnableHa(Boolean enableHa) { + this.enableHa = enableHa; + } + public VolumeTO getRootVolume() { return rootVolume; } @@ -3282,6 +3392,8 @@ public static class StopVmCmd extends AgentCommand { private String type; @GrayVersion(value = "5.0.0") private long timeout; + @GrayVersion(value = "5.5.22") + private Boolean ignoreNotFoundError; private List vmNics; public String getUuid() { @@ -3308,6 +3420,14 @@ public void setType(String type) { this.type = type; } + public Boolean isIgnoreNotFoundError() { + return ignoreNotFoundError; + } + + public void setIgnoreNotFoundError(Boolean ignoreNotFoundError) { + this.ignoreNotFoundError = ignoreNotFoundError; + } + public List getVmNics() { return vmNics; } @@ -4972,6 +5092,8 @@ public static class OvsAddPortCmd extends AgentCommand { public Map nicMap = new HashMap<>(); @GrayVersion(value = "5.4.0") public Map nicVmInstanceUuidMap = new HashMap<>(); + @GrayVersion(value = "5.5.22") + public Map ifaceIdMap = new HashMap<>(); } public static class OvsAddPortRsp extends AgentResponse { @@ -4984,6 +5106,8 @@ public static class OvsSyncPortCmd extends AgentCommand { public Map nicMap = new HashMap<>(); @GrayVersion(value = "5.4.0") public String vmUuid; + @GrayVersion(value = "5.5.22") + public Map ifaceIdMap = new HashMap<>(); } public static class OvsSyncPortRsp extends AgentResponse { @@ -5147,6 +5271,45 @@ public void setAdditionalProperties(Map additionalProperties) { } } + public static class VmEventAlarmCmd { + private String hostUuid; + private String vmUuid; + private String eventType; + private Map properties = new HashMap<>(); + + public String getHostUuid() { + return hostUuid; + } + + public void setHostUuid(String hostUuid) { + this.hostUuid = hostUuid; + } + + public String getVmUuid() { + return vmUuid; + } + + public void setVmUuid(String vmUuid) { + this.vmUuid = vmUuid; + } + + public String getEventType() { + return eventType; + } + + public void setEventType(String eventType) { + this.eventType = eventType; + } + + public Map getProperties() { + return properties; + } + + public void setProperties(Map properties) { + this.properties = properties; + } + } + public static class HostProcessPhysicalMemoryUsageAlarmCmd { private String hostUuid; private String pid; diff --git a/plugin/kvm/src/main/java/org/zstack/kvm/KVMApiInterceptor.java b/plugin/kvm/src/main/java/org/zstack/kvm/KVMApiInterceptor.java index 93fd688935b..e8e30a6711f 100755 --- a/plugin/kvm/src/main/java/org/zstack/kvm/KVMApiInterceptor.java +++ b/plugin/kvm/src/main/java/org/zstack/kvm/KVMApiInterceptor.java @@ -111,6 +111,11 @@ private void validate(APIAttachL2NetworkToClusterMsg msg) { return; } + // ZNS L2 networks don't create vlan devices on host, skip length check + if (L2NetworkConstant.VSWITCH_TYPE_ZNS.equals(l2.getvSwitchType())) { + return; + } + if (NetworkUtils.generateVlanDeviceName(l2.getPhysicalInterface(), l2.getVlan()).length() > L2NetworkConstant.LINUX_IF_NAME_MAX_SIZE) { throw new ApiMessageInterceptionException(argerr(ORG_ZSTACK_KVM_10139, "cannot create vlan-device on %s because it's too long" diff --git a/plugin/kvm/src/main/java/org/zstack/kvm/KVMConstant.java b/plugin/kvm/src/main/java/org/zstack/kvm/KVMConstant.java index 314ff983470..70f64b0cfdc 100755 --- a/plugin/kvm/src/main/java/org/zstack/kvm/KVMConstant.java +++ b/plugin/kvm/src/main/java/org/zstack/kvm/KVMConstant.java @@ -67,6 +67,8 @@ public interface KVMConstant { String KVM_DETACH_VOLUME = "/vm/detachdatavolume"; String KVM_ATTACH_NIC_PATH = "/vm/attachnic"; String KVM_DETACH_NIC_PATH = "/vm/detachnic"; + String KVM_VM_SHMEM_HOTPLUG_PATH = "/vm/shmem/hotplug"; + String KVM_VM_SHMEM_HOTUNPLUG_PATH = "/vm/shmem/hotunplug"; String KVM_CHANGE_NIC_STATE_PATH = "/vm/changenicstate"; String KVM_UPDATE_NIC_PATH = "/vm/updatenic"; String KVM_SET_VF_NIC_MAC_PATH = "/vm/setvfnicmac"; @@ -133,6 +135,9 @@ public interface KVMConstant { String KVM_BLOCK_PULL_VOLUME_PATH = "/vm/volume/blockpull"; String TAKE_VM_CONSOLE_SCREENSHOT_PATH = "/vm/console/screenshot"; String UPDATE_VM_CONSOLE_PASSWORD_PATH = "/host/vm/updateConsolePassword/live"; + String SETUP_VM_HA_ENABLED_METADATA_LIVE_PATH = "/host/vm/setupHaEnabledMetadata/live"; + String RECONCILE_VM_HA_ENABLED_METADATA_LIVE_PATH = "/host/vm/reconcileHaEnabledMetadata/live"; + String HA_NETWORK_GROUP_SYNC_PATH = "/ha/networkgroup/sync"; String KVM_HOST_IPSET_ATTACH_NIC_PATH = "/network/ipset/attach"; String KVM_HOST_IPSET_DETACH_NIC_PATH = "/network/ipset/detach"; @@ -145,6 +150,7 @@ public interface KVMConstant { String HOST_PHYSICAL_DISK_REMOVE_ALARM_EVENT = "/host/physical/disk/remove/alarm"; String HOST_PHYSICAL_MEMORY_ECC_ERROR_ALARM_EVENT = "/host/physical/memory/ecc/error/alarm"; String HOST_PHYSICAL_GPU_REMOVE_ALARM_EVENT = "/host/physical/gpu/remove/alarm"; + String HOST_VM_EVENT_ALARM = "/host/vm/event/alarm"; String HOST_STORAGEDEVICE_HBA_STATE_EVENT = "/storagedevice/hba/state/alarm"; String HOST_PROCESS_PHYSICAL_MEMORY_USAGE_ALARM_PATH = "/host/process/physicalMemory/usage/alarm"; String HOST_KVMAGENT_STATUS_PATH = "/host/kvmagent/status"; diff --git a/plugin/kvm/src/main/java/org/zstack/kvm/KVMHost.java b/plugin/kvm/src/main/java/org/zstack/kvm/KVMHost.java index b485c343d18..0c3ec6d2d23 100755 --- a/plugin/kvm/src/main/java/org/zstack/kvm/KVMHost.java +++ b/plugin/kvm/src/main/java/org/zstack/kvm/KVMHost.java @@ -56,6 +56,7 @@ import org.zstack.header.core.workflow.*; import org.zstack.header.errorcode.ErrorCode; import org.zstack.header.errorcode.ErrorCodeList; +import org.zstack.header.errorcode.ErrorableValue; import org.zstack.header.errorcode.OperationFailureException; import org.zstack.header.errorcode.SysErrors; import org.zstack.header.exception.CloudRuntimeException; @@ -73,6 +74,7 @@ import org.zstack.header.rest.JsonAsyncRESTCallback; import org.zstack.header.rest.RESTFacade; import org.zstack.header.storage.primary.*; +import org.zstack.header.storage.snapshot.*; import org.zstack.header.tag.SystemTagInventory; import org.zstack.header.vm.*; import org.zstack.header.vm.devices.DeviceAddress; @@ -634,6 +636,10 @@ protected void handleLocalMessage(Message msg) { handle((CheckSnapshotOnHypervisorMsg) msg); } else if (msg instanceof MergeVolumeSnapshotOnKvmMsg) { handle((MergeVolumeSnapshotOnKvmMsg) msg); + } else if (msg instanceof KVMHotPlugVmShmemMsg) { + handle((KVMHotPlugVmShmemMsg) msg); + } else if (msg instanceof KVMHotUnplugVmShmemMsg) { + handle((KVMHotUnplugVmShmemMsg) msg); } else if (msg instanceof KVMHostAsyncHttpCallMsg) { handle((KVMHostAsyncHttpCallMsg) msg); } else if (msg instanceof KVMHostSyncHttpCallMsg) { @@ -859,12 +865,12 @@ public boolean skip(Map data) { @Override public void run(FlowTrigger trigger, Map data) { - SshShell sshShell = new SshShell(); + SshShell sshShell = Platform.New(() -> new SshShell()); sshShell.setHostname(getSelf().getManagementIp()); sshShell.setUsername(getSelf().getUsername()); sshShell.setPassword(getSelf().getPassword()); sshShell.setPort(getSelf().getPort()); - SshResult ret = sshShell.runCommand("sudo service zstack-kvmagent restart"); + SshResult ret = sshShell.runCommandWithPseudoTty("sudo service zstack-kvmagent restart"); if (ret.isSshFailure() || ret.getReturnCode() != 0) { trigger.fail(operr(ORG_ZSTACK_KVM_10017, ret.getExitErrorMessage())); @@ -2708,6 +2714,54 @@ public void done() { ); } + private void handle(final KVMHotPlugVmShmemMsg msg) { + KVMAgentCommands.HotPlugVmShmemCmd cmd = new KVMAgentCommands.HotPlugVmShmemCmd(); + cmd.vmUuid = msg.getVmUuid(); + cmd.shmem = buildVmShmemDevice(msg.getShmemName(), msg.getShmemPath(), msg.getShmemSize()); + + sendVmShmemCommand(msg, cmd, KVMConstant.KVM_VM_SHMEM_HOTPLUG_PATH, + KVMAgentCommands.HotPlugVmShmemRsp.class); + } + + private void handle(final KVMHotUnplugVmShmemMsg msg) { + KVMAgentCommands.HotUnplugVmShmemCmd cmd = new KVMAgentCommands.HotUnplugVmShmemCmd(); + cmd.vmUuid = msg.getVmUuid(); + cmd.shmem = buildVmShmemDevice(msg.getShmemName(), msg.getShmemPath(), msg.getShmemSize()); + + sendVmShmemCommand(msg, cmd, KVMConstant.KVM_VM_SHMEM_HOTUNPLUG_PATH, + KVMAgentCommands.HotUnplugVmShmemRsp.class); + } + + private KVMAgentCommands.VmShmemDevice buildVmShmemDevice(String name, String path, long size) { + KVMAgentCommands.VmShmemDevice shmem = new KVMAgentCommands.VmShmemDevice(); + shmem.name = name; + shmem.path = path; + shmem.size = size; + return shmem; + } + + private void sendVmShmemCommand(NeedReplyMessage origin, + Object cmd, + String path, + Class responseClass) { + KVMHostAsyncHttpCallMsg kmsg = new KVMHostAsyncHttpCallMsg(); + kmsg.setCommand(cmd); + kmsg.setHostUuid(((HostMessage) origin).getHostUuid()); + kmsg.setPath(path); + bus.makeTargetServiceIdByResourceUuid(kmsg, HostConstant.SERVICE_ID, ((HostMessage) origin).getHostUuid()); + bus.send(kmsg, new CloudBusCallBack(origin) { + @Override + public void run(MessageReply reply) { + ErrorableValue response = KVMHostAsyncHttpCallReply.unwrap(reply, responseClass); + MessageReply ret = new MessageReply(); + if (!response.isSuccess()) { + ret.setError(response.error); + } + bus.reply(origin, ret); + } + }); + } + private String buildUrl(String path) { UriComponentsBuilder ub = UriComponentsBuilder.newInstance(); ub.scheme(KVMGlobalProperty.AGENT_URL_SCHEME); @@ -3058,6 +3112,7 @@ public void success(TakeSnapshotResponse ret) { " data corruption may happen", ret.getNewVolumeInstallPath())); } + syncSnapshotMetadataAfterHypervisorSuccess(msg, ret); extEmitter.afterTakeSnapshot((KVMHostInventory) getSelfInventory(), msg, cmd, ret); reply.setNewVolumeInstallPath(ret.getNewVolumeInstallPath()); reply.setSnapshotInstallPath(ret.getSnapshotInstallPath()); @@ -3094,6 +3149,27 @@ public void handle(ErrorCode errCode, Map data) { }).start(); } + private void syncSnapshotMetadataAfterHypervisorSuccess(TakeSnapshotOnHypervisorMsg msg, TakeSnapshotResponse ret) { + VolumeInventory volume = msg.getVolume(); + if (volume == null || msg.getSnapshotName() == null) { + return; + } + + VolumeSnapshotInventory snapshot = new VolumeSnapshotInventory(); + snapshot.setUuid(msg.getSnapshotName()); + snapshot.setVolumeUuid(volume.getUuid()); + snapshot.setPrimaryStorageUuid(volume.getPrimaryStorageUuid()); + snapshot.setPrimaryStorageInstallPath(ret.getSnapshotInstallPath()); + snapshot.setType(VolumeSnapshotConstant.HYPERVISOR_SNAPSHOT_TYPE.toString()); + snapshot.setStatus(VolumeSnapshotStatus.Ready.toString()); + snapshot.setSize(ret.getSize()); + snapshot.setFormat(volume.getFormat()); + + for (VolumeSnapshotDBSyncExtensionPoint ext : pluginRgty.getExtensionList(VolumeSnapshotDBSyncExtensionPoint.class)) { + ext.syncVolumeSnapshotDBAfterTakeSnapshot(volume, snapshot, ret.getNewVolumeInstallPath()); + } + } + private void migrateVm(final MigrateStruct s, final Completion completion) { final TaskProgressRange parentStage = getTaskStage(); final TaskProgressRange MIGRATE_VM_STAGE = new TaskProgressRange(0, 90); @@ -3872,6 +3948,7 @@ protected void stopVm(final StopVmOnHypervisorMsg msg, final NoErrorCompletion c cmd.setUuid(vminv.getUuid()); cmd.setType(msg.getType()); cmd.setTimeout(120); + cmd.setIgnoreNotFoundError(msg.isIgnoreNotFoundError()); cmd.setVmNics(vminv.getVmNics()); try { @@ -4198,6 +4275,16 @@ private NicTO completeNicInfo(VmNicInventory nic) { KVMCompleteNicInformationExtensionPoint extp = factory.getCompleteNicInfoExtension(L2NetworkType.valueOf(l2inv.getType())); NicTO to = extp.completeNicInformation(l2inv, l3Inv, nic); + if (L2NetworkConstant.VSWITCH_TYPE_ZNS.equals(l2inv.getvSwitchType())) { + to.setBridgeName("br-int"); + to.setBridgePortType("openvswitch"); + String ifaceId = VmSystemTags.IFACE_ID.getTokenByResourceUuid( + nic.getUuid(), VmSystemTags.IFACE_ID_TOKEN); + if (ifaceId != null) { + to.setInterfaceId(ifaceId); + } + } + if (to.getUseVirtio() == null) { to.setUseVirtio(VmSystemTags.VIRTIO.hasTag(nic.getVmInstanceUuid())); to.setIps(getCleanTrafficIp(nic)); @@ -5175,12 +5262,12 @@ protected void deleteTakeOverFlag(Completion completion) { return; } - SshShell sshShell = new SshShell(); + SshShell sshShell = Platform.New(() -> new SshShell()); sshShell.setHostname(getSelf().getManagementIp()); sshShell.setUsername(getSelf().getUsername()); sshShell.setPassword(getSelf().getPassword()); sshShell.setPort(getSelf().getPort()); - SshResult ret = sshShell.runCommand(String.format("sudo /bin/sh -c \"rm -rf %s\"", hostTakeOverFlagPath)); + SshResult ret = sshShell.runCommandWithPseudoTty(String.format("sudo /bin/sh -c \"rm -rf %s\"", hostTakeOverFlagPath)); if (ret.isSshFailure() || ret.getReturnCode() != 0) { completion.fail(operr(ORG_ZSTACK_KVM_10092, ret.getExitErrorMessage())); return; @@ -5212,6 +5299,17 @@ private ErrorCode connectToAgent() { errCode = operr(ORG_ZSTACK_KVM_10093, "unable to connect to kvm host[uuid:%s, ip:%s, url:%s], because %s", self.getUuid(), self.getManagementIp(), connectPath, rsp.getError()); } else { + if (rsp.isFirstConnect()) { + long cutoffMillis = rsp.getAgentStartTimeMillis() - TimeUnit.SECONDS.toMillis(60); + int drained = restf.failPendingCallsForResourceBefore(self.getUuid(), cutoffMillis, + operr(ORG_ZSTACK_CORE_REST_10013, + "kvmagent on host[uuid:%s] restarted at %s, pending HTTP call sent before %s aborted", + self.getUuid(), rsp.getAgentStartTimeMillis(), cutoffMillis)); + if (drained > 0) { + logger.info(String.format("kvmagent on host[uuid:%s] restarted at %d, drained %d pending HTTP call(s)", + self.getUuid(), rsp.getAgentStartTimeMillis(), drained)); + } + } VersionComparator libvirtVersion = new VersionComparator(rsp.getLibvirtVersion()); VersionComparator qemuVersion = new VersionComparator(rsp.getQemuVersion()); boolean liveSnapshot = libvirtVersion.compare(KVMConstant.MIN_LIBVIRT_LIVESNAPSHOT_VERSION) >= 0 @@ -5275,12 +5373,12 @@ public void handle(Map data) { return; } - SshShell sshShell = new SshShell(); + SshShell sshShell = Platform.New(() -> new SshShell()); sshShell.setHostname(getSelf().getManagementIp()); sshShell.setUsername(getSelf().getUsername()); sshShell.setPassword(getSelf().getPassword()); sshShell.setPort(getSelf().getPort()); - SshResult ret = sshShell.runCommand(String.format("sudo /bin/sh -c \"echo uuid:%s > %s\"", self.getUuid(), hostTakeOverFlagPath)); + SshResult ret = sshShell.runCommandWithPseudoTty(String.format("sudo /bin/sh -c \"echo uuid:%s > %s\"", self.getUuid(), hostTakeOverFlagPath)); if (ret.isSshFailure() || ret.getReturnCode() != 0) { completion.fail(operr(ORG_ZSTACK_KVM_10097, ret.getExitErrorMessage())); @@ -5316,6 +5414,15 @@ private boolean noStorageAccessible(){ return inaccessiblePsCount == attachedPsCount && attachedPsCount > 0; } + @Transactional(readOnly = true) + private long getLibvirtRestartedEchoTimeout() { + long vmCount = KVMHostUtils.countVmsForLibvirtRestartEchoTimeout(self.getUuid()); + long timeout = KVMHostUtils.calculateLibvirtRestartEchoTimeoutMillis(vmCount); + logger.info(String.format("extend kvmagent echo timeout after libvirtd restart on host[uuid:%s, vmCount:%s] to %sms", + self.getUuid(), vmCount, timeout)); + return timeout; + } + private void updateHostOsInformation(String distro, String release, String version) { final KVMHostVO kvmHostVO = getSelf(); kvmHostVO.setOsDistribution(distro); @@ -5536,7 +5643,7 @@ public void run(FlowTrigger trigger, Map data) { sshShell.setPassword(getSelf().getPassword()); sshShell.setPort(getSelf().getPort()); sshShell.setWithSudo(false); - final String cmd = String.format("curl --connect-timeout 10 %s|| wget --spider -q --connect-timeout=10 %s|| test $? -eq 8", restf.getCallbackUrl(), restf.getCallbackUrl()); + final String cmd = String.format("curl --connect-timeout 10 --max-time 15 %s|| wget --spider -q --connect-timeout=10 --read-timeout=10 --tries=1 %s|| test $? -eq 8", restf.getCallbackUrl(), restf.getCallbackUrl()); SshResult ret = sshShell.runCommand(cmd); if (ret.getStderr() != null && ret.getStderr().contains("No route to host")) { // c.f. https://access.redhat.com/solutions/1120533 @@ -5586,6 +5693,7 @@ public void connectHook(final ConnectHostInfo info, final Completion complete) { chain.allowWatch(); chain.then(new ShareFlow() { boolean deployed = false; + boolean libvirtRestarted = false; @Override public void setup() { flow(new NoRollbackFlow() { @@ -5949,6 +6057,8 @@ public void success(Boolean run) { deployed = run; } if (deployed) { + libvirtRestarted = KVMHostUtils.shouldRestartLibvirtdDuringDeploy( + deployArguments.getInit(), deployArguments.getRestartLibvirtd()); // update host agent version when open grayScaleUpgrade upgradeChecker.updateAgentVersion(self.getUuid(), AnsibleConstant.KVM_AGENT_NAME, dbf.getDbVersion(), dbf.getDbVersion()); } @@ -5957,6 +6067,13 @@ public void success(Boolean run) { @Override public void fail(ErrorCode errorCode) { + if (KVMHostUtils.shouldContinueReconnectOnAnsibleFailure(info.isNewAdded(), errorCode)) { + logger.warn(String.format( + "kvm ansible failed to mask libvirt sockets because systemd dbus timed out on existing host[uuid:%s, ip:%s], continue reconnect and verify kvmagent, error: %s", + self.getUuid(), self.getManagementIp(), errorCode)); + trigger.next(); + return; + } trigger.fail(errorCode); } }); @@ -6016,6 +6133,9 @@ public boolean skip(Map data) { @Override public void run(final FlowTrigger trigger, Map data) { + final long echoTimeout = libvirtRestarted + ? getLibvirtRestartedEchoTimeout() + : TimeUnit.SECONDS.toMillis(CoreGlobalProperty.REST_FACADE_ECHO_TIMEOUT); restf.echo(echoPath, new Completion(trigger) { @Override public void success() { @@ -6047,7 +6167,7 @@ public void success() { public void fail(ErrorCode errorCode) { trigger.fail(errorCode); } - }); + }, TimeUnit.SECONDS.toMillis(1), echoTimeout); } @Override @@ -6059,7 +6179,7 @@ public void fail(ErrorCode errorCode) { trigger.fail(errorCode); } } - }); + }, TimeUnit.SECONDS.toMillis(1), echoTimeout); } }); diff --git a/plugin/kvm/src/main/java/org/zstack/kvm/KVMHostCapacityExtension.java b/plugin/kvm/src/main/java/org/zstack/kvm/KVMHostCapacityExtension.java index 5ad18e49c9f..16ff667f21d 100755 --- a/plugin/kvm/src/main/java/org/zstack/kvm/KVMHostCapacityExtension.java +++ b/plugin/kvm/src/main/java/org/zstack/kvm/KVMHostCapacityExtension.java @@ -16,6 +16,7 @@ import org.zstack.resourceconfig.ResourceConfigFacade; import java.util.Map; +import java.util.concurrent.TimeUnit; public class KVMHostCapacityExtension implements KVMHostConnectExtensionPoint, HostConnectionReestablishExtensionPoint { @@ -31,6 +32,7 @@ public class KVMHostCapacityExtension implements KVMHostConnectExtensionPoint, H public void reportCapacity(HostInventory host, Completion completion) { CheckHostCapacityMsg msg = new CheckHostCapacityMsg(); msg.setHostUuid(host.getUuid()); + msg.setTimeout(TimeUnit.MINUTES.toMillis(30)); bus.makeTargetServiceIdByResourceUuid(msg, HostConstant.SERVICE_ID, host.getUuid()); bus.send(msg, new CloudBusCallBack(completion) { @Override diff --git a/plugin/kvm/src/main/java/org/zstack/kvm/KVMHostFactory.java b/plugin/kvm/src/main/java/org/zstack/kvm/KVMHostFactory.java index 0188c920a83..be52c46b1fc 100755 --- a/plugin/kvm/src/main/java/org/zstack/kvm/KVMHostFactory.java +++ b/plugin/kvm/src/main/java/org/zstack/kvm/KVMHostFactory.java @@ -50,6 +50,7 @@ import org.zstack.header.network.l2.L2NetworkType; import org.zstack.header.network.l2.L2NetworkVO; import org.zstack.header.network.l2.L2NetworkVO_; + import org.zstack.header.rest.RESTFacade; import org.zstack.header.rest.SyncHttpCallHandler; import org.zstack.header.tag.FormTagExtensionPoint; @@ -380,7 +381,7 @@ protected void populateExtensions() { public KVMCompleteNicInformationExtensionPoint getCompleteNicInfoExtension(L2NetworkType type) { KVMCompleteNicInformationExtensionPoint extp = completeNicInfoExtensions.get(type); if (extp == null) { - throw new IllegalArgumentException(String.format("unble to fine KVMCompleteNicInformationExtensionPoint supporting L2NetworkType[%s]", type)); + throw new IllegalArgumentException(String.format("unable to find KVMCompleteNicInformationExtensionPoint supporting L2NetworkType[%s]", type)); } return extp; } @@ -723,6 +724,11 @@ public String handleSyncHttpCall(TransmitVmOperationToMnCmd cmd) { ext.handleKvmHardwareStatus(HostHardware.GPU, cmd); } break; + case GPU_XID: + for (KvmHardwareStatusHandlerExtensionPoint ext : pluginRgty.getExtensionList(KvmHardwareStatusHandlerExtensionPoint.class)) { + ext.handleKvmHardwareStatus(HostHardware.GPU_XID, cmd); + } + break; case POWERSUPPLY: physicalPowerSupplyStatusAlarmEvent(cmd); break; @@ -746,6 +752,12 @@ public String handleSyncHttpCall(TransmitVmOperationToMnCmd cmd) { return null; }); + restf.registerSyncHttpCallHandler(KVMConstant.HOST_VM_EVENT_ALARM, KVMAgentCommands.VmEventAlarmCmd.class, cmd -> { + for (VmEventAlarmHandlerExtensionPoint ext : pluginRgty.getExtensionList(VmEventAlarmHandlerExtensionPoint.class)) { + ext.handleVmEventAlarm(cmd); + } + return null; + }); restf.registerSyncHttpCallHandler(KVMConstant.HOST_PROCESS_PHYSICAL_MEMORY_USAGE_ALARM_PATH, HostProcessPhysicalMemoryUsageAlarmCmd.class, cmd -> { HostCanonicalEvents.HostProcessPhysicalMemoryUsageAlarmData data = new HostCanonicalEvents.HostProcessPhysicalMemoryUsageAlarmData(); diff --git a/plugin/kvm/src/main/java/org/zstack/kvm/KVMHostUtils.java b/plugin/kvm/src/main/java/org/zstack/kvm/KVMHostUtils.java index 3a0d857ff47..82f040f15bb 100644 --- a/plugin/kvm/src/main/java/org/zstack/kvm/KVMHostUtils.java +++ b/plugin/kvm/src/main/java/org/zstack/kvm/KVMHostUtils.java @@ -5,9 +5,13 @@ import org.zstack.core.CoreGlobalProperty; import org.zstack.core.db.Q; import org.zstack.header.network.l2.*; +import org.zstack.header.errorcode.ErrorCode; import org.zstack.header.tag.SystemTagVO; import org.zstack.header.tag.SystemTagVO_; import org.zstack.header.tag.TagType; +import org.zstack.header.vm.VmInstanceState; +import org.zstack.header.vm.VmInstanceVO; +import org.zstack.header.vm.VmInstanceVO_; import org.zstack.utils.CollectionUtils; import org.zstack.utils.TagUtils; import org.zstack.utils.logging.CLogger; @@ -19,7 +23,9 @@ import java.util.HashSet; import java.util.LinkedHashSet; import java.util.List; +import java.util.Locale; import java.util.Set; +import java.util.concurrent.TimeUnit; /** * Created by GuoYi on 4/16/20. @@ -31,6 +37,9 @@ public class KVMHostUtils { // to keep check-flow and deploy-flow IP lists identical. public static final Set EXCLUDED_INTERNAL_IPS = Collections.unmodifiableSet( new LinkedHashSet<>(Collections.singletonList("169.254.64.1"))); + public static final long LIBVIRT_RESTART_ECHO_TIMEOUT_VM_THRESHOLD = 100; + public static final long LIBVIRT_RESTART_ECHO_TIMEOUT_PER_VM_SECONDS = 1; + public static final long LIBVIRT_RESTART_ECHO_TIMEOUT_MAX_SECONDS = 180; // Collect host IPv4 addresses; mirrors host_plugin.fact() filters and // applies EXCLUDED_INTERNAL_IPS so check and deploy share one source. @@ -145,6 +154,61 @@ public static boolean shouldForceTlsRedeploy(boolean needDeployTlsCert, return allowRestartLibvirtd || isNewAdded; } + public static boolean shouldRestartLibvirtdDuringDeploy(String init, String restartLibvirtd) { + return "true".equalsIgnoreCase(init) || "true".equalsIgnoreCase(restartLibvirtd); + } + + public static long countVmsForLibvirtRestartEchoTimeout(String hostUuid) { + return Q.New(VmInstanceVO.class) + .eq(VmInstanceVO_.hostUuid, hostUuid) + .notEq(VmInstanceVO_.state, VmInstanceState.Stopped) + .count(); + } + + public static long calculateLibvirtRestartEchoTimeoutMillis(long vmCount) { + long defaultTimeoutSeconds = CoreGlobalProperty.REST_FACADE_ECHO_TIMEOUT; + if (vmCount <= LIBVIRT_RESTART_ECHO_TIMEOUT_VM_THRESHOLD) { + return TimeUnit.SECONDS.toMillis(defaultTimeoutSeconds); + } + + long maxExtraSeconds = Math.max(0, LIBVIRT_RESTART_ECHO_TIMEOUT_MAX_SECONDS - defaultTimeoutSeconds); + long extraVmCount = vmCount - LIBVIRT_RESTART_ECHO_TIMEOUT_VM_THRESHOLD; + long extraSeconds = Math.min(extraVmCount * LIBVIRT_RESTART_ECHO_TIMEOUT_PER_VM_SECONDS, maxExtraSeconds); + return TimeUnit.SECONDS.toMillis(defaultTimeoutSeconds + extraSeconds); + } + + public static boolean shouldContinueReconnectOnAnsibleFailure(boolean isNewAdded, ErrorCode errorCode) { + return !isNewAdded && isLibvirtSocketMaskSystemdTimeout(errorCode); + } + + public static boolean isLibvirtSocketMaskSystemdTimeout(ErrorCode errorCode) { + String errorText = collectErrorText(errorCode).toLowerCase(Locale.ROOT); + return errorText.contains("systemctl mask") + && errorText.contains("libvirtd.socket") + && errorText.contains("org.freedesktop.systemd1") + && errorText.contains("timed out") + && (errorText.contains("failed to get properties") + || errorText.contains("failed to activate service")); + } + + private static String collectErrorText(ErrorCode errorCode) { + StringBuilder sb = new StringBuilder(); + ErrorCode cursor = errorCode; + while (cursor != null) { + appendIfNotNull(sb, cursor.getDetails()); + appendIfNotNull(sb, cursor.getDescription()); + appendIfNotNull(sb, cursor.getMessage()); + cursor = cursor.getCause(); + } + return sb.toString(); + } + + private static void appendIfNotNull(StringBuilder sb, String text) { + if (text != null) { + sb.append(text).append('\n'); + } + } + private static SshShell newSsh(String host, String user, String pwd, int port) { SshShell s = new SshShell(); s.setHostname(host); diff --git a/plugin/kvm/src/main/java/org/zstack/kvm/KVMHotPlugVmShmemMsg.java b/plugin/kvm/src/main/java/org/zstack/kvm/KVMHotPlugVmShmemMsg.java new file mode 100644 index 00000000000..5070471ba00 --- /dev/null +++ b/plugin/kvm/src/main/java/org/zstack/kvm/KVMHotPlugVmShmemMsg.java @@ -0,0 +1,68 @@ +package org.zstack.kvm; + +import org.zstack.header.host.HostMessage; +import org.zstack.header.message.NeedReplyMessage; + +public class KVMHotPlugVmShmemMsg extends NeedReplyMessage implements HostMessage { + private String hostUuid; + private String vmUuid; + private String shmemName; + private String shmemPath; + private long shmemSize; + + @Override + public String getHostUuid() { + return hostUuid; + } + + public void setHostUuid(String hostUuid) { + this.hostUuid = normalize(hostUuid, "hostUuid"); + } + + public String getVmUuid() { + return vmUuid; + } + + public void setVmUuid(String vmUuid) { + this.vmUuid = normalize(vmUuid, "vmUuid"); + } + + public String getShmemName() { + return shmemName; + } + + public void setShmemName(String shmemName) { + this.shmemName = normalize(shmemName, "shmemName"); + } + + public String getShmemPath() { + return shmemPath; + } + + public void setShmemPath(String shmemPath) { + this.shmemPath = normalize(shmemPath, "shmemPath"); + } + + public long getShmemSize() { + return shmemSize; + } + + public void setShmemSize(long shmemSize) { + if (shmemSize <= 0) { + throw new IllegalArgumentException("shmemSize must be greater than 0"); + } + this.shmemSize = shmemSize; + } + + private String normalize(String value, String fieldName) { + if (value == null) { + return null; + } + + String normalized = value.trim(); + if (normalized.isEmpty()) { + throw new IllegalArgumentException(fieldName + " cannot be empty"); + } + return normalized; + } +} diff --git a/plugin/kvm/src/main/java/org/zstack/kvm/KVMHotUnplugVmShmemMsg.java b/plugin/kvm/src/main/java/org/zstack/kvm/KVMHotUnplugVmShmemMsg.java new file mode 100644 index 00000000000..4a3d5a3dcfa --- /dev/null +++ b/plugin/kvm/src/main/java/org/zstack/kvm/KVMHotUnplugVmShmemMsg.java @@ -0,0 +1,68 @@ +package org.zstack.kvm; + +import org.zstack.header.host.HostMessage; +import org.zstack.header.message.NeedReplyMessage; + +public class KVMHotUnplugVmShmemMsg extends NeedReplyMessage implements HostMessage { + private String hostUuid; + private String vmUuid; + private String shmemName; + private String shmemPath; + private long shmemSize; + + @Override + public String getHostUuid() { + return hostUuid; + } + + public void setHostUuid(String hostUuid) { + this.hostUuid = normalize(hostUuid, "hostUuid"); + } + + public String getVmUuid() { + return vmUuid; + } + + public void setVmUuid(String vmUuid) { + this.vmUuid = normalize(vmUuid, "vmUuid"); + } + + public String getShmemName() { + return shmemName; + } + + public void setShmemName(String shmemName) { + this.shmemName = normalize(shmemName, "shmemName"); + } + + public String getShmemPath() { + return shmemPath; + } + + public void setShmemPath(String shmemPath) { + this.shmemPath = normalize(shmemPath, "shmemPath"); + } + + public long getShmemSize() { + return shmemSize; + } + + public void setShmemSize(long shmemSize) { + if (shmemSize <= 0) { + throw new IllegalArgumentException("shmemSize must be greater than 0"); + } + this.shmemSize = shmemSize; + } + + private String normalize(String value, String fieldName) { + if (value == null) { + return null; + } + + String normalized = value.trim(); + if (normalized.isEmpty()) { + throw new IllegalArgumentException(fieldName + " cannot be empty"); + } + return normalized; + } +} diff --git a/plugin/kvm/src/main/java/org/zstack/kvm/KVMRealizeL2NoVlanNetworkBackend.java b/plugin/kvm/src/main/java/org/zstack/kvm/KVMRealizeL2NoVlanNetworkBackend.java index 1ed462ecfcd..3ec9dd0780e 100755 --- a/plugin/kvm/src/main/java/org/zstack/kvm/KVMRealizeL2NoVlanNetworkBackend.java +++ b/plugin/kvm/src/main/java/org/zstack/kvm/KVMRealizeL2NoVlanNetworkBackend.java @@ -236,7 +236,7 @@ public NicTO completeNicInformation(L2NetworkInventory l2Network, L3NetworkInven to.setBridgeName(makeBridgeName(l2Network.getUuid())); to.setPhysicalInterface(l2Network.getPhysicalInterface()); to.setMtu(new MtuGetter().getMtu(l3Network.getUuid())); - if (l2Network.getvSwitchType().equals(L2NetworkConstant.VSWITCH_TYPE_OVN_DPDK)) { + if (L2NetworkConstant.ACCEL_TYPE_VHOST_USER_SPACE.equals(nic.getType())) { to.setSrcPath(L2NetworkConstant.OVN_DPDK_VNIC_SRC_PATH + nic.getInternalName()); } diff --git a/plugin/kvm/src/main/java/org/zstack/kvm/KVMRealizeL2VlanNetworkBackend.java b/plugin/kvm/src/main/java/org/zstack/kvm/KVMRealizeL2VlanNetworkBackend.java index 74e700dd9f6..e486fddff98 100755 --- a/plugin/kvm/src/main/java/org/zstack/kvm/KVMRealizeL2VlanNetworkBackend.java +++ b/plugin/kvm/src/main/java/org/zstack/kvm/KVMRealizeL2VlanNetworkBackend.java @@ -249,7 +249,7 @@ public NicTO completeNicInformation(L2NetworkInventory l2Network, L3NetworkInven to.setMetaData(String.valueOf(vlanId)); to.setMtu(new MtuGetter().getMtu(l3Network.getUuid())); to.setVlanId(String.valueOf(vlanId)); - if (l2Network.getvSwitchType().equals(L2NetworkConstant.VSWITCH_TYPE_OVN_DPDK)) { + if (L2NetworkConstant.ACCEL_TYPE_VHOST_USER_SPACE.equals(nic.getType())) { to.setSrcPath(L2NetworkConstant.OVN_DPDK_VNIC_SRC_PATH + nic.getInternalName()); } diff --git a/plugin/kvm/src/main/java/org/zstack/kvm/VmEventAlarmHandlerExtensionPoint.java b/plugin/kvm/src/main/java/org/zstack/kvm/VmEventAlarmHandlerExtensionPoint.java new file mode 100644 index 00000000000..78113e77fc0 --- /dev/null +++ b/plugin/kvm/src/main/java/org/zstack/kvm/VmEventAlarmHandlerExtensionPoint.java @@ -0,0 +1,5 @@ +package org.zstack.kvm; + +public interface VmEventAlarmHandlerExtensionPoint { + void handleVmEventAlarm(KVMAgentCommands.VmEventAlarmCmd cmd); +} diff --git a/plugin/kvm/src/main/java/org/zstack/kvm/VmNicLifecycleKvmBridge.java b/plugin/kvm/src/main/java/org/zstack/kvm/VmNicLifecycleKvmBridge.java new file mode 100644 index 00000000000..c1ecdd4c716 --- /dev/null +++ b/plugin/kvm/src/main/java/org/zstack/kvm/VmNicLifecycleKvmBridge.java @@ -0,0 +1,114 @@ +package org.zstack.kvm; + +import org.springframework.beans.factory.annotation.Autowired; +import org.zstack.compute.vm.VmNicLifecycleGlobalConfig; +import org.zstack.core.asyncbatch.While; +import org.zstack.core.componentloader.PluginRegistry; +import org.zstack.core.db.Q; +import org.zstack.core.thread.ThreadFacade; +import org.zstack.core.thread.ThreadFacadeImpl; +import org.zstack.header.core.NoErrorCompletion; +import org.zstack.header.core.WhileDoneCompletion; +import org.zstack.header.errorcode.ErrorCodeList; +import org.zstack.header.vm.*; +import org.zstack.header.vm.VmNicLifecycleExtensionPoint; +import org.zstack.utils.Utils; +import org.zstack.utils.logging.CLogger; + +import java.util.List; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.stream.Collectors; + +public class VmNicLifecycleKvmBridge implements KVMPingAgentNoFailureExtensionPoint { + + private static final CLogger logger = Utils.getLogger(VmNicLifecycleKvmBridge.class); + + @Autowired + private PluginRegistry pluginRgty; + @Autowired + private ThreadFacade thdf; + + private List getExtensions() { + return pluginRgty.getExtensionList(VmNicLifecycleExtensionPoint.class); + } + + @Override + public void kvmPingAgentNoFailure(KVMHostInventory host, NoErrorCompletion completion) { + List extensions = getExtensions(); + if (extensions.isEmpty()) { + completion.done(); + return; + } + + String hostUuid = host.getUuid(); + + List allExpectedNics; + try { + List runningVms = Q.New(VmInstanceVO.class) + .eq(VmInstanceVO_.hostUuid, hostUuid) + .eq(VmInstanceVO_.state, VmInstanceState.Running) + .list(); + allExpectedNics = runningVms.stream() + .flatMap(vm -> VmNicInventory.valueOf(vm.getVmNics()).stream()) + .collect(Collectors.toList()); + } catch (Exception e) { + logger.warn(String.format("[VmNicLifecycle] failed to query Running VMs " + + "on host[uuid:%s] for reconciliation, skip this round", hostUuid), e); + completion.done(); + return; + } + + long timeoutSeconds = VmNicLifecycleGlobalConfig.RECONCILE_TIMEOUT.value(Long.class); + + new While<>(extensions).step((ext, whileCompletion) -> { + List matchedNics; + try { + matchedNics = allExpectedNics.stream() + .filter(ext::isApplicable) + .collect(Collectors.toList()); + } catch (Exception e) { + logger.warn(String.format("[VmNicLifecycle] %s.isApplicable threw exception " + + "during reconciliation on host[uuid:%s]", + ext.getClass().getSimpleName(), hostUuid), e); + whileCompletion.done(); + return; + } + + AtomicBoolean completed = new AtomicBoolean(false); + + ThreadFacadeImpl.TimeoutTaskReceipt receipt = thdf.submitTimeoutTask(() -> { + if (completed.compareAndSet(false, true)) { + logger.warn(String.format("[VmNicLifecycle] %s.reconcileOnHost timed out " + + "after %ds on host[uuid:%s]", + ext.getClass().getSimpleName(), timeoutSeconds, hostUuid)); + whileCompletion.done(); + } + }, TimeUnit.SECONDS, timeoutSeconds); + + try { + ext.reconcileOnHost(hostUuid, matchedNics, new NoErrorCompletion() { + @Override + public void done() { + if (completed.compareAndSet(false, true)) { + receipt.cancel(); + whileCompletion.done(); + } + } + }); + } catch (Exception e) { + if (completed.compareAndSet(false, true)) { + receipt.cancel(); + logger.warn(String.format("[VmNicLifecycle] %s.reconcileOnHost(host=%s) " + + "threw exception", ext.getClass().getSimpleName(), hostUuid), e); + whileCompletion.done(); + } + } + }, extensions.size()).run(new WhileDoneCompletion(completion) { + @Override + public void done(ErrorCodeList errorCodeList) { + completion.done(); + } + }); + } +} diff --git a/plugin/loadBalancer/src/main/java/org/zstack/network/service/lb/APIChangeLoadBalancerListenerMsg.java b/plugin/loadBalancer/src/main/java/org/zstack/network/service/lb/APIChangeLoadBalancerListenerMsg.java index 8228f15ae1a..3d77b9d1335 100644 --- a/plugin/loadBalancer/src/main/java/org/zstack/network/service/lb/APIChangeLoadBalancerListenerMsg.java +++ b/plugin/loadBalancer/src/main/java/org/zstack/network/service/lb/APIChangeLoadBalancerListenerMsg.java @@ -44,7 +44,7 @@ public class APIChangeLoadBalancerListenerMsg extends APIMessage implements Load @APIParam(numberRange = {LoadBalancerConstants.HEALTH_CHECK_INTERVAL_MIN, LoadBalancerConstants.HEALTH_CHECK_INTERVAL_MAX}, required = false) private Integer healthCheckInterval; - @APIParam(validValues = {LoadBalancerConstants.HEALTH_CHECK_TARGET_PROTOCL_TCP, LoadBalancerConstants.HEALTH_CHECK_TARGET_PROTOCL_UDP, LoadBalancerConstants.HEALTH_CHECK_TARGET_PROTOCL_HTTP}, required = false) + @APIParam(validValues = {LoadBalancerConstants.HEALTH_CHECK_TARGET_PROTOCL_TCP, LoadBalancerConstants.HEALTH_CHECK_TARGET_PROTOCL_UDP, LoadBalancerConstants.HEALTH_CHECK_TARGET_PROTOCL_HTTP, LoadBalancerConstants.HEALTH_CHECK_TARGET_PROTOCL_NONE}, required = false) private String healthCheckProtocol; @APIParam(validValues = {"GET", "HEAD"}, required = false) private String healthCheckMethod; diff --git a/plugin/loadBalancer/src/main/java/org/zstack/network/service/lb/APIChangeLoadBalancerListenerMsgDoc_zh_cn.groovy b/plugin/loadBalancer/src/main/java/org/zstack/network/service/lb/APIChangeLoadBalancerListenerMsgDoc_zh_cn.groovy index bbe5abcf884..c92f14186a4 100644 --- a/plugin/loadBalancer/src/main/java/org/zstack/network/service/lb/APIChangeLoadBalancerListenerMsgDoc_zh_cn.groovy +++ b/plugin/loadBalancer/src/main/java/org/zstack/network/service/lb/APIChangeLoadBalancerListenerMsgDoc_zh_cn.groovy @@ -102,7 +102,7 @@ doc { type "String" optional true since "3.9" - values ("tcp","udp","http") + values ("tcp","udp","http","none") } column { name "healthCheckMethod" diff --git a/plugin/loadBalancer/src/main/java/org/zstack/network/service/lb/APICreateLoadBalancerListenerMsg.java b/plugin/loadBalancer/src/main/java/org/zstack/network/service/lb/APICreateLoadBalancerListenerMsg.java index 0b123054386..5b495571cc9 100755 --- a/plugin/loadBalancer/src/main/java/org/zstack/network/service/lb/APICreateLoadBalancerListenerMsg.java +++ b/plugin/loadBalancer/src/main/java/org/zstack/network/service/lb/APICreateLoadBalancerListenerMsg.java @@ -39,7 +39,7 @@ public class APICreateLoadBalancerListenerMsg extends APICreateMessage implement private String protocol; @APIParam(resourceType = CertificateVO.class, required = false) private String certificateUuid; - @APIParam(validValues = {LoadBalancerConstants.HEALTH_CHECK_TARGET_PROTOCL_TCP, LoadBalancerConstants.HEALTH_CHECK_TARGET_PROTOCL_UDP, LoadBalancerConstants.HEALTH_CHECK_TARGET_PROTOCL_HTTP}, required = false) + @APIParam(validValues = {LoadBalancerConstants.HEALTH_CHECK_TARGET_PROTOCL_TCP, LoadBalancerConstants.HEALTH_CHECK_TARGET_PROTOCL_UDP, LoadBalancerConstants.HEALTH_CHECK_TARGET_PROTOCL_HTTP, LoadBalancerConstants.HEALTH_CHECK_TARGET_PROTOCL_NONE}, required = false) private String healthCheckProtocol; @APIParam(validValues = {"GET", "HEAD"}, required = false) private String healthCheckMethod; diff --git a/plugin/loadBalancer/src/main/java/org/zstack/network/service/lb/APICreateLoadBalancerListenerMsgDoc_zh_cn.groovy b/plugin/loadBalancer/src/main/java/org/zstack/network/service/lb/APICreateLoadBalancerListenerMsgDoc_zh_cn.groovy index cfaae8626bb..9496c068530 100644 --- a/plugin/loadBalancer/src/main/java/org/zstack/network/service/lb/APICreateLoadBalancerListenerMsgDoc_zh_cn.groovy +++ b/plugin/loadBalancer/src/main/java/org/zstack/network/service/lb/APICreateLoadBalancerListenerMsgDoc_zh_cn.groovy @@ -93,7 +93,7 @@ doc { type "String" optional true since "3.9" - values ("tcp","udp","http") + values ("tcp","udp","http","none") } column { name "healthCheckMethod" 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 f2f8271674b..b846b54185e 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 @@ -695,6 +695,21 @@ private boolean hasTag(APIMessage msg, PatternedSystemTag tag) { return false; } + private List getSystemTagTokens(APIMessage msg, PatternedSystemTag tag, String token) { + List tokens = new ArrayList<>(); + if (msg.getSystemTags() == null) { + return tokens; + } + + for (String t : msg.getSystemTags()) { + if (tag.isMatch(t)) { + tokens.add(tag.getTokenByTag(t, token)); + } + } + + return tokens; + } + private void insertTagIfNotExisting(APICreateMessage msg, PatternedSystemTag tag, String value) { if (!hasTag(msg, tag)) { msg.addSystemTag(value); @@ -713,6 +728,47 @@ private Boolean verifyHttpCode(String httpCode) { }); } + private boolean isHealthCheckProtocolNotSupportedByListenerProtocol(String listenerProtocol, String healthCheckProtocol) { + boolean isUdpListener = LoadBalancerConstants.LB_PROTOCOL_UDP.equals(listenerProtocol); + boolean isUdpHealthCheck = LoadBalancerConstants.HEALTH_CHECK_TARGET_PROTOCL_UDP.equals(healthCheckProtocol); + boolean isNoneHealthCheck = LoadBalancerConstants.HEALTH_CHECK_TARGET_PROTOCL_NONE.equals(healthCheckProtocol); + + if (isUdpListener) { + return !(isUdpHealthCheck || isNoneHealthCheck); + } + + return isUdpHealthCheck || isNoneHealthCheck; + } + + private String getHealthCheckProtocolFromTarget(String healthCheckTarget) { + if (healthCheckTarget == null) { + return null; + } + + String[] ts = healthCheckTarget.split(":"); + return ts.length == 2 ? ts[0] : null; + } + + private String getHealthCheckPortFromTarget(String healthCheckTarget) { + if (healthCheckTarget == null) { + return null; + } + + String[] ts = healthCheckTarget.split(":"); + return ts.length == 2 ? ts[1] : null; + } + + private boolean isNoneHealthCheckTargetWithSpecificPort(String healthCheckTarget) { + if (healthCheckTarget == null) { + return false; + } + + String[] ts = healthCheckTarget.split(":"); + return ts.length == 2 && + LoadBalancerConstants.HEALTH_CHECK_TARGET_PROTOCL_NONE.equals(ts[0]) && + !"default".equals(ts[1]); + } + private void validate(APICreateLoadBalancerListenerMsg msg) { LoadBalancerVO lbVO = dbf.findByUuid(msg.getLoadBalancerUuid(), LoadBalancerVO.class); @@ -730,34 +786,57 @@ private void validate(APICreateLoadBalancerListenerMsg msg) { msg.getProtocol(), msg.getHealthCheckProtocol())); } } + + List healthCheckTargets = getSystemTagTokens(msg, LoadBalancerSystemTags.HEALTH_TARGET, + LoadBalancerSystemTags.HEALTH_TARGET_TOKEN); + if (healthCheckTargets.size() > 1) { + throw new ApiMessageInterceptionException( + operr(ORG_ZSTACK_NETWORK_SERVICE_LB_10177, "only one health check target is allowed, but got %s", + healthCheckTargets)); + } + String healthCheckTarget = healthCheckTargets.isEmpty() ? null : healthCheckTargets.get(0); + if (isNoneHealthCheckTargetWithSpecificPort(healthCheckTarget)) { + throw new ApiMessageInterceptionException( + operr(ORG_ZSTACK_NETWORK_SERVICE_LB_10178, "the health check target [%s] is invalid, health check protocol none only supports default target", + healthCheckTarget)); + } + String healthCheckProtocolInTarget = getHealthCheckProtocolFromTarget(healthCheckTarget); + if (msg.getHealthCheckProtocol() == null) { - if (LoadBalancerConstants.LB_PROTOCOL_UDP.equals(msg.getProtocol())) { + if (healthCheckProtocolInTarget != null) { + msg.setHealthCheckProtocol(healthCheckProtocolInTarget); + } else if (LoadBalancerConstants.LB_PROTOCOL_UDP.equals(msg.getProtocol())) { msg.setHealthCheckProtocol(LoadBalancerConstants.HEALTH_CHECK_TARGET_PROTOCL_UDP); } else { msg.setHealthCheckProtocol(LoadBalancerConstants.HEALTH_CHECK_TARGET_PROTOCL_TCP); } } else { - if (LoadBalancerConstants.LB_PROTOCOL_UDP.equals(msg.getProtocol()) && !LoadBalancerConstants.HEALTH_CHECK_TARGET_PROTOCL_UDP.equals(msg.getHealthCheckProtocol()) || - !LoadBalancerConstants.LB_PROTOCOL_UDP.equals(msg.getProtocol()) && LoadBalancerConstants.HEALTH_CHECK_TARGET_PROTOCL_UDP.equals(msg.getHealthCheckProtocol())) { + if (healthCheckProtocolInTarget != null && !healthCheckProtocolInTarget.equals(msg.getHealthCheckProtocol())) { throw new ApiMessageInterceptionException( - operr(ORG_ZSTACK_NETWORK_SERVICE_LB_10062, "the listener with protocol [%s] doesn't support this health check:[%s]", - msg.getProtocol(), msg.getHealthCheckProtocol())); + operr(ORG_ZSTACK_NETWORK_SERVICE_LB_10179, "the health check protocol [%s] conflicts with health check target [%s]", + msg.getHealthCheckProtocol(), healthCheckTarget)); } - if (LoadBalancerConstants.HEALTH_CHECK_TARGET_PROTOCL_HTTP.equals(msg.getHealthCheckProtocol())) { - if (msg.getHealthCheckURI() == null) { - throw new ApiMessageInterceptionException( - operr(ORG_ZSTACK_NETWORK_SERVICE_LB_10063, "the http health check protocol must be specified its healthy checking parameter healthCheckURI")); - } + } - if (msg.getHealthCheckMethod() == null) { - msg.setHealthCheckMethod(LoadBalancerConstants.HealthCheckMothod.HEAD.toString()); - } - } - if (msg.getHealthCheckHttpCode() != null && !verifyHttpCode(msg.getHealthCheckHttpCode())) { + if (isHealthCheckProtocolNotSupportedByListenerProtocol(msg.getProtocol(), msg.getHealthCheckProtocol())) { + throw new ApiMessageInterceptionException( + operr(ORG_ZSTACK_NETWORK_SERVICE_LB_10062, "the listener with protocol [%s] doesn't support this health check:[%s]", + msg.getProtocol(), msg.getHealthCheckProtocol())); + } + if (LoadBalancerConstants.HEALTH_CHECK_TARGET_PROTOCL_HTTP.equals(msg.getHealthCheckProtocol())) { + if (msg.getHealthCheckURI() == null) { throw new ApiMessageInterceptionException( - operr(ORG_ZSTACK_NETWORK_SERVICE_LB_10064, "the http health check protocol's expecting code [%s] is invalidate", msg.getHealthCheckHttpCode())); + operr(ORG_ZSTACK_NETWORK_SERVICE_LB_10063, "the http health check protocol must be specified its healthy checking parameter healthCheckURI")); + } + + if (msg.getHealthCheckMethod() == null) { + msg.setHealthCheckMethod(LoadBalancerConstants.HealthCheckMothod.HEAD.toString()); } } + if (msg.getHealthCheckHttpCode() != null && !verifyHttpCode(msg.getHealthCheckHttpCode())) { + throw new ApiMessageInterceptionException( + operr(ORG_ZSTACK_NETWORK_SERVICE_LB_10064, "the http health check protocol's expecting code [%s] is invalidate", msg.getHealthCheckHttpCode())); + } if (LoadBalancerConstants.HEALTH_CHECK_TARGET_PROTOCL_HTTP.equals(msg.getHealthCheckProtocol())) { String expectResult = LoadBalancerConstants.HealthCheckStatusCode.http_2xx.toString(); @@ -1384,21 +1463,40 @@ private void validate(APIChangeLoadBalancerListenerMsg msg) { throw new ApiMessageInterceptionException(operr(ORG_ZSTACK_NETWORK_SERVICE_LB_10118, "the listener with protocol [%s] doesn't support select security policy", listenerVO.getProtocol(), msg.getHealthCheckProtocol())); } } - if (LoadBalancerConstants.HEALTH_CHECK_TARGET_PROTOCL_HTTP.equals(msg.getHealthCheckProtocol())) { - String healthTarget = LoadBalancerSystemTags.HEALTH_TARGET.getTokenByResourceUuid(msg.getLoadBalancerListenerUuid(), - LoadBalancerSystemTags.HEALTH_TARGET_TOKEN); - String[] ts = healthTarget.split(":"); - if (ts.length != 2) { - throw new OperationFailureException(argerr(ORG_ZSTACK_NETWORK_SERVICE_LB_10119, "invalid health target[%s], the format is targetCheckProtocol:port, for example, tcp:default", target)); - } + String healthTarget = LoadBalancerSystemTags.HEALTH_TARGET.getTokenByResourceUuid(msg.getLoadBalancerListenerUuid(), + LoadBalancerSystemTags.HEALTH_TARGET_TOKEN); + String currentHealthCheckProtocol = getHealthCheckProtocolFromTarget(healthTarget); + String currentHealthCheckTarget = getHealthCheckPortFromTarget(healthTarget); + String effectiveHealthCheckProtocol = msg.getHealthCheckProtocol() == null ? currentHealthCheckProtocol : msg.getHealthCheckProtocol(); + String effectiveHealthCheckTarget; + if (LoadBalancerConstants.HEALTH_CHECK_TARGET_PROTOCL_NONE.equals(msg.getHealthCheckProtocol()) && + msg.getHealthCheckTarget() == null) { + effectiveHealthCheckTarget = LoadBalancerConstants.HEALTH_CHECK_TARGET_DEFAULT; + } else { + effectiveHealthCheckTarget = msg.getHealthCheckTarget() == null ? currentHealthCheckTarget : msg.getHealthCheckTarget(); + } + if (LoadBalancerConstants.HEALTH_CHECK_TARGET_PROTOCL_NONE.equals(effectiveHealthCheckProtocol) && + !LoadBalancerConstants.HEALTH_CHECK_TARGET_DEFAULT.equals(effectiveHealthCheckTarget)) { + throw new ApiMessageInterceptionException( + operr(ORG_ZSTACK_NETWORK_SERVICE_LB_10178, "the health check target [%s] is invalid, health check protocol none only supports default target", + effectiveHealthCheckTarget)); + } - if (LoadBalancerConstants.LB_PROTOCOL_UDP.equals(listenerVO.getProtocol()) && !LoadBalancerConstants.HEALTH_CHECK_TARGET_PROTOCL_UDP.equals(msg.getHealthCheckProtocol()) || - !LoadBalancerConstants.LB_PROTOCOL_UDP.equals(listenerVO.getProtocol()) && LoadBalancerConstants.HEALTH_CHECK_TARGET_PROTOCL_UDP.equals(msg.getHealthCheckProtocol())) { + if (msg.getHealthCheckProtocol() != null) { + if (isHealthCheckProtocolNotSupportedByListenerProtocol(listenerVO.getProtocol(), msg.getHealthCheckProtocol())) { throw new ApiMessageInterceptionException( operr(ORG_ZSTACK_NETWORK_SERVICE_LB_10120, "the listener with protocol [%s] doesn't support this health check:[%s]", listenerVO.getProtocol(), msg.getHealthCheckProtocol())); } + } + + if (LoadBalancerConstants.HEALTH_CHECK_TARGET_PROTOCL_HTTP.equals(msg.getHealthCheckProtocol())) { + String[] ts = healthTarget.split(":"); + if (ts.length != 2) { + throw new OperationFailureException(argerr(ORG_ZSTACK_NETWORK_SERVICE_LB_10119, "invalid health target[%s], the format is targetCheckProtocol:port, for example, tcp:default", target)); + } + if (LoadBalancerConstants.HEALTH_CHECK_TARGET_PROTOCL_TCP.equals(ts[0]) && (msg.getHealthCheckMethod() == null || msg.getHealthCheckURI() == null)) { throw new ApiMessageInterceptionException( operr(ORG_ZSTACK_NETWORK_SERVICE_LB_10121, "the http health check protocol must be specified its healthy checking parameters including healthCheckMethod and healthCheckURI")); diff --git a/plugin/loadBalancer/src/main/java/org/zstack/network/service/lb/LoadBalancerBase.java b/plugin/loadBalancer/src/main/java/org/zstack/network/service/lb/LoadBalancerBase.java index dadec74b6ec..e219f24eb8b 100755 --- a/plugin/loadBalancer/src/main/java/org/zstack/network/service/lb/LoadBalancerBase.java +++ b/plugin/loadBalancer/src/main/java/org/zstack/network/service/lb/LoadBalancerBase.java @@ -2406,9 +2406,10 @@ public void run(SyncTaskChain chain) { LoadBalancerSystemTags.HEALTH_PARAMETER.delete(msg.getUuid()); } + String target = LoadBalancerConstants.HEALTH_CHECK_TARGET_PROTOCL_NONE.equals(msg.getHealthCheckProtocol()) ? "default" : ts[1]; LoadBalancerSystemTags.HEALTH_TARGET.update(msg.getUuid(), LoadBalancerSystemTags.HEALTH_TARGET.instantiateTag(map( - e(LoadBalancerSystemTags.HEALTH_TARGET_TOKEN, String.format("%s:%s", msg.getHealthCheckProtocol(), ts[1]))) + e(LoadBalancerSystemTags.HEALTH_TARGET_TOKEN, String.format("%s:%s", msg.getHealthCheckProtocol(), target))) )); ts = getHeathCheckTarget(msg.getUuid()); } diff --git a/plugin/loadBalancer/src/main/java/org/zstack/network/service/lb/LoadBalancerConstants.java b/plugin/loadBalancer/src/main/java/org/zstack/network/service/lb/LoadBalancerConstants.java index fe147c11cf4..f48b53c930b 100755 --- a/plugin/loadBalancer/src/main/java/org/zstack/network/service/lb/LoadBalancerConstants.java +++ b/plugin/loadBalancer/src/main/java/org/zstack/network/service/lb/LoadBalancerConstants.java @@ -29,6 +29,7 @@ public class LoadBalancerConstants { public static final String HEALTH_CHECK_TARGET_PROTOCL_TCP = "tcp"; public static final String HEALTH_CHECK_TARGET_PROTOCL_UDP = "udp"; public static final String HEALTH_CHECK_TARGET_PROTOCL_HTTP = "http"; + public static final String HEALTH_CHECK_TARGET_PROTOCL_NONE = "none"; public static final String HTTP_MODE_HTTP_KEEP_ALIVE = "http-keep-alive"; public static final String HTTP_MODE_HTTP_SERVER_CLOSE = "http-server-close"; @@ -131,6 +132,7 @@ public String toString() { HEALTH_CHECK_TARGET_PROTOCOLS.add(HEALTH_CHECK_TARGET_PROTOCL_TCP); HEALTH_CHECK_TARGET_PROTOCOLS.add(HEALTH_CHECK_TARGET_PROTOCL_UDP); HEALTH_CHECK_TARGET_PROTOCOLS.add(HEALTH_CHECK_TARGET_PROTOCL_HTTP); + HEALTH_CHECK_TARGET_PROTOCOLS.add(HEALTH_CHECK_TARGET_PROTOCL_NONE); HTTP_MODES.add(HTTP_MODE_HTTP_KEEP_ALIVE); HTTP_MODES.add(HTTP_MODE_HTTP_SERVER_CLOSE); diff --git a/plugin/loadBalancer/src/main/java/org/zstack/network/service/lb/LoadBalancerManagerImpl.java b/plugin/loadBalancer/src/main/java/org/zstack/network/service/lb/LoadBalancerManagerImpl.java index 8f1f8e1fc62..6b4da585104 100755 --- a/plugin/loadBalancer/src/main/java/org/zstack/network/service/lb/LoadBalancerManagerImpl.java +++ b/plugin/loadBalancer/src/main/java/org/zstack/network/service/lb/LoadBalancerManagerImpl.java @@ -732,6 +732,20 @@ public void validateSystemTag(String resourceUuid, Class resourceType, String sy } String port = ts[1]; + if (LoadBalancerConstants.HEALTH_CHECK_TARGET_PROTOCL_NONE.equals(protocol) && !"default".equals(port)) { + throw new OperationFailureException(argerr(ORG_ZSTACK_NETWORK_SERVICE_LB_10014, "invalid health target[%s], health check protocol none only supports default target", systemTag)); + } + + LoadBalancerListenerVO listener = Q.New(LoadBalancerListenerVO.class) + .eq(LoadBalancerListenerVO_.uuid, resourceUuid) + .find(); + if (listener != null) { + if (LoadBalancerConstants.HEALTH_CHECK_TARGET_PROTOCL_NONE.equals(protocol) && + !LoadBalancerConstants.LB_PROTOCOL_UDP.equals(listener.getProtocol())) { + throw new OperationFailureException(argerr(ORG_ZSTACK_NETWORK_SERVICE_LB_10014, "invalid health target[%s], health check protocol none is only supported by udp listener", systemTag)); + } + } + if (!"default".equals(port)) { try { int p = Integer.parseInt(port); diff --git a/plugin/localstorage/src/main/java/org/zstack/storage/primary/local/LocalStorageBase.java b/plugin/localstorage/src/main/java/org/zstack/storage/primary/local/LocalStorageBase.java index ed98d99747a..0f57a471769 100755 --- a/plugin/localstorage/src/main/java/org/zstack/storage/primary/local/LocalStorageBase.java +++ b/plugin/localstorage/src/main/java/org/zstack/storage/primary/local/LocalStorageBase.java @@ -68,6 +68,7 @@ import static org.zstack.storage.primary.local.LocalStorageUtils.getHostUuidFromInstallUrl; import static org.zstack.utils.CollectionDSL.*; import static org.zstack.utils.clouderrorcode.CloudOperationsErrorCode.*; +import org.zstack.header.storage.primary.ReInitDataVolumeOnPrimaryStorageMsg; /** * Created by frank on 6/30/2015. @@ -1425,6 +1426,12 @@ public void fail(ErrorCode errorCode) { }); } + @Override + protected void handle(ReInitDataVolumeOnPrimaryStorageMsg msg) { + bus.dealWithUnknownMessage(msg); + } + + protected String getHostUuidByResourceUuid(String resUuid) { String huuid; huuid = new SQLBatchWithReturn() { diff --git a/plugin/nfsPrimaryStorage/src/main/java/org/zstack/storage/primary/nfs/NfsPrimaryStorage.java b/plugin/nfsPrimaryStorage/src/main/java/org/zstack/storage/primary/nfs/NfsPrimaryStorage.java index 8be0ee64bed..253d2c00d92 100755 --- a/plugin/nfsPrimaryStorage/src/main/java/org/zstack/storage/primary/nfs/NfsPrimaryStorage.java +++ b/plugin/nfsPrimaryStorage/src/main/java/org/zstack/storage/primary/nfs/NfsPrimaryStorage.java @@ -71,6 +71,7 @@ import static org.zstack.utils.CollectionDSL.e; import static org.zstack.utils.CollectionDSL.map; import static org.zstack.utils.clouderrorcode.CloudOperationsErrorCode.*; +import org.zstack.header.storage.primary.ReInitDataVolumeOnPrimaryStorageMsg; public class NfsPrimaryStorage extends PrimaryStorageBase { private static final CLogger logger = Utils.getLogger(NfsPrimaryStorage.class); @@ -521,6 +522,12 @@ public void fail(ErrorCode errorCode) { }); } + @Override + protected void handle(ReInitDataVolumeOnPrimaryStorageMsg msg) { + bus.dealWithUnknownMessage(msg); + } + + @Override protected void handle(final DeleteSnapshotOnPrimaryStorageMsg msg) { final DeleteSnapshotOnPrimaryStorageReply reply = new DeleteSnapshotOnPrimaryStorageReply(); diff --git a/plugin/sdnController/src/main/java/org/zstack/sdnController/AbstractSdnControllerFactory.java b/plugin/sdnController/src/main/java/org/zstack/sdnController/AbstractSdnControllerFactory.java new file mode 100644 index 00000000000..095632acd68 --- /dev/null +++ b/plugin/sdnController/src/main/java/org/zstack/sdnController/AbstractSdnControllerFactory.java @@ -0,0 +1,45 @@ +package org.zstack.sdnController; + +import org.springframework.beans.factory.annotation.Autowire; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Configurable; +import org.zstack.core.cloudbus.EventFacade; +import org.zstack.core.db.DatabaseFacade; +import org.zstack.core.db.SQL; +import org.zstack.header.network.sdncontroller.*; +import org.zstack.sdnController.header.SdnControllerCanonicalEvents; +import org.zstack.utils.Utils; +import org.zstack.utils.logging.CLogger; + +@Configurable(preConstruction = true, autowire = Autowire.BY_TYPE) +public abstract class AbstractSdnControllerFactory implements SdnControllerFactory { + private static final CLogger logger = Utils.getLogger(AbstractSdnControllerFactory.class); + + @Autowired + private DatabaseFacade factoryDbf; + @Autowired + private EventFacade evtf; + + @Override + public void changeSdnControllerStatus(SdnControllerVO vo, SdnControllerStatusEvent event) { + SdnControllerStatus newStatus = resolveStatus(event, vo); + if (newStatus == vo.getStatus()) { + return; + } + SdnControllerStatus oldStatus = vo.getStatus(); + logger.debug(String.format("sdn controller[%s] event[%s]: %s -> %s", + vo.getUuid(), event, oldStatus, newStatus)); + SQL.New(SdnControllerVO.class) + .eq(SdnControllerVO_.uuid, vo.getUuid()) + .set(SdnControllerVO_.status, newStatus) + .update(); + vo.setStatus(newStatus); + SdnControllerCanonicalEvents.SdnControllerStatusChangedData d = new SdnControllerCanonicalEvents.SdnControllerStatusChangedData(); + d.setSdnControllerUuid(vo.getUuid()); + d.setSdnControllerType(vo.getVendorType()); + d.setOldStatus(oldStatus.toString()); + d.setNewStatus(newStatus.toString()); + d.setInv(SdnControllerInventory.valueOf(vo)); + evtf.fire(SdnControllerCanonicalEvents.SDNCONTROLLER_STATUS_CHANGED_PATH, d); + } +} diff --git a/plugin/sdnController/src/main/java/org/zstack/sdnController/SdnControllerBase.java b/plugin/sdnController/src/main/java/org/zstack/sdnController/SdnControllerBase.java index f1d1f11829b..848c962b2e3 100644 --- a/plugin/sdnController/src/main/java/org/zstack/sdnController/SdnControllerBase.java +++ b/plugin/sdnController/src/main/java/org/zstack/sdnController/SdnControllerBase.java @@ -11,7 +11,6 @@ import org.zstack.core.cascade.CascadeFacade; import org.zstack.core.cloudbus.CloudBus; import org.zstack.core.cloudbus.CloudBusCallBack; -import org.zstack.core.cloudbus.EventFacade; import org.zstack.core.componentloader.PluginRegistry; import org.zstack.core.db.DatabaseFacade; import org.zstack.core.db.Q; @@ -69,8 +68,6 @@ public class SdnControllerBase { @Autowired private ThreadFacade thdf; @Autowired - private EventFacade evtf; - @Autowired SdnControllerManager sdnMgr; @Autowired private PluginRegistry pluginRgty; @@ -154,6 +151,8 @@ public void run(SyncTaskChain chain) { flowChain.getData().put(SDN_CONTROLLER_UUID, self.getUuid()); flowChain.setName(String.format("sync-sdn-controller-data-%s-%s", self.getUuid(), self.getName())); + // allowEmptyFlow: vendors may not provide sync flows; treat empty chain as success + flowChain.allowEmptyFlow(); // Start the chain; flows in factory-provided chain should perform data sync operations flowChain.done(new FlowDoneHandler(msg) { @Override @@ -179,26 +178,6 @@ public String getName() { }); } - public void changeSdnControllerStatus(SdnControllerStatus status) { - if (status == self.getStatus()) { - return; - } - - SdnControllerStatus oldStatus = self.getStatus(); - logger.debug(String.format("sdn controller [%s] changed status, old status: [%s], new status: [%s]", - self.getUuid(), oldStatus, status.toString())); - self.setStatus(status); - self = dbf.updateAndRefresh(self); - - SdnControllerCanonicalEvents.SdnControllerStatusChangedData d = new SdnControllerCanonicalEvents.SdnControllerStatusChangedData(); - d.setSdnControllerUuid(self.getUuid()); - d.setSdnControllerType(self.getVendorType()); - d.setOldStatus(oldStatus.toString()); - d.setNewStatus(status.toString()); - d.setInv(SdnControllerInventory.valueOf(self)); - evtf.fire(SdnControllerCanonicalEvents.SDNCONTROLLER_STATUS_CHANGED_PATH, d); - } - private void doChangeSdnController(APIChangeSdnControllerMsg msg, Completion completion) { FlowChain chain = FlowChainBuilder.newSimpleFlowChain(); chain.setName(String.format("change-sdn-controller-%s-%s", self.getUuid(), self.getName())); @@ -224,6 +203,12 @@ public void run(FlowTrigger trigger, Map data) { } if (changed) { + String newUsername = self.getUsername(); + String newPassword = self.getPassword(); + // Keep concurrent DB changes while applying the credential update. + self = dbf.reload(self); + self.setUsername(newUsername); + self.setPassword(newPassword); self = dbf.updateAndRefresh(self); chain.getData().put(SDN_CONTROLLER_CHANGED, changed); } @@ -257,6 +242,11 @@ public void rollback(FlowRollback trigger, Map data) { self.setUsername(username); } if (password != null || username != null) { + String rollbackUsername = self.getUsername(); + String rollbackPassword = self.getPassword(); + self = dbf.reload(self); + self.setUsername(rollbackUsername); + self.setPassword(rollbackPassword); self = dbf.updateAndRefresh(self); } @@ -422,13 +412,13 @@ private void doReconnectSdnController(Completion completion) { @Override public void run(FlowTrigger trigger, Map data) { - changeSdnControllerStatus(SdnControllerStatus.Connecting); + sdnMgr.getSdnControllerFactory(self.getVendorType()).changeSdnControllerStatus(self, SdnControllerStatusEvent.RECONNECT_STARTED); trigger.next(); } @Override public void rollback(FlowRollback trigger, Map data) { - changeSdnControllerStatus(SdnControllerStatus.Disconnected); + sdnMgr.getSdnControllerFactory(self.getVendorType()).changeSdnControllerStatus(self, SdnControllerStatusEvent.RECONNECT_FAILED); trigger.rollback(); } }).then(new NoRollbackFlow() { @@ -454,7 +444,7 @@ public void fail(ErrorCode errorCode) { @Override public void run(FlowTrigger trigger, Map data) { - changeSdnControllerStatus(SdnControllerStatus.Connected); + sdnMgr.getSdnControllerFactory(self.getVendorType()).changeSdnControllerStatus(self, SdnControllerStatusEvent.RECONNECT_SUCCESS); trigger.next(); } }).done(new FlowDoneHandler(completion) { @@ -903,7 +893,7 @@ public void fail(ErrorCode errorCode) { @Override public void run(FlowTrigger trigger, Map data) { sdnPingTracker.untrack(msg.getSdnControllerUuid()); - dbf.removeByPrimaryKey(msg.getSdnControllerUuid(), SdnControllerVO.class); + controller.deleteSdnControllerDb(self); trigger.next(); } }).done(new FlowDoneHandler(completion) { diff --git a/plugin/sdnController/src/main/java/org/zstack/sdnController/SdnControllerFactory.java b/plugin/sdnController/src/main/java/org/zstack/sdnController/SdnControllerFactory.java index 6c25dcaddb9..9455cf2727c 100644 --- a/plugin/sdnController/src/main/java/org/zstack/sdnController/SdnControllerFactory.java +++ b/plugin/sdnController/src/main/java/org/zstack/sdnController/SdnControllerFactory.java @@ -4,13 +4,28 @@ import org.zstack.header.core.workflow.FlowChain; import org.zstack.header.network.l3.SdnControllerL3; import org.zstack.header.network.service.SdnControllerDhcp; -import org.zstack.network.securitygroup.SecurityGroupSdnBackend; +import org.zstack.header.network.sdncontroller.SdnControllerStatus; +import org.zstack.header.network.sdncontroller.SdnControllerStatusEvent; import org.zstack.header.network.sdncontroller.SdnControllerVO; +import org.zstack.network.securitygroup.SecurityGroupSdnBackend; public interface SdnControllerFactory { SdnControllerType getVendorType(); - SdnControllerVO persistSdnController(SdnControllerVO vo); + default SdnControllerStatus resolveStatus(SdnControllerStatusEvent event, SdnControllerVO vo) { + switch (event) { + case RECONNECT_STARTED: return SdnControllerStatus.Connecting; + case RECONNECT_SUCCESS: return SdnControllerStatus.Connected; + case RECONNECT_FAILED: return SdnControllerStatus.Disconnected; + case PING_FAILED: return SdnControllerStatus.Disconnected; + case INIT_SYNC_STARTED: return SdnControllerStatus.Connecting; + case INIT_SYNC_SUCCESS: return SdnControllerStatus.Connected; + case INIT_SYNC_FAILED: return SdnControllerStatus.Disconnected; + default: return vo.getStatus(); + } + } + + void changeSdnControllerStatus(SdnControllerVO vo, SdnControllerStatusEvent event); SdnController getSdnController(SdnControllerVO vo); diff --git a/plugin/sdnController/src/main/java/org/zstack/sdnController/SdnControllerL2.java b/plugin/sdnController/src/main/java/org/zstack/sdnController/SdnControllerL2.java index 502efb5f21f..4a63f3c5c2b 100644 --- a/plugin/sdnController/src/main/java/org/zstack/sdnController/SdnControllerL2.java +++ b/plugin/sdnController/src/main/java/org/zstack/sdnController/SdnControllerL2.java @@ -38,6 +38,7 @@ public interface SdnControllerL2 { default void addVmNics(List nics, Completion completion) {completion.success();}; default void removeVmNics(List nics, Completion completion) {completion.success();}; + default void releaseNicIps(List nics, Completion completion) {completion.success();}; default void addL3NetworkIpRange(L3NetworkInventory inv, IpRangeInventory ipr, Completion completion) {completion.success();}; default void deleteL3NetworkIpRange(L3NetworkInventory inv, IpRangeInventory ipr, Completion completion) {completion.success();}; diff --git a/plugin/sdnController/src/main/java/org/zstack/sdnController/SdnControllerManagerImpl.java b/plugin/sdnController/src/main/java/org/zstack/sdnController/SdnControllerManagerImpl.java index 2368fbb95ae..e832f146738 100644 --- a/plugin/sdnController/src/main/java/org/zstack/sdnController/SdnControllerManagerImpl.java +++ b/plugin/sdnController/src/main/java/org/zstack/sdnController/SdnControllerManagerImpl.java @@ -47,10 +47,10 @@ import static org.zstack.utils.clouderrorcode.CloudOperationsErrorCode.*; public class SdnControllerManagerImpl extends AbstractService implements SdnControllerManager, - L2NetworkCreateExtensionPoint, L2NetworkDeleteExtensionPoint, InstantiateResourceOnAttachingNicExtensionPoint, - PreVmInstantiateResourceExtensionPoint, VmReleaseResourceExtensionPoint, - ReleaseNetworkServiceOnDetachingNicExtensionPoint, SecurityGroupGetSdnBackendExtensionPoint, - AfterAddIpRangeExtensionPoint, IpRangeDeletionExtensionPoint, GetSdnControllerExtensionPoint { + L2NetworkCreateExtensionPoint, L2NetworkDeleteExtensionPoint, + SecurityGroupGetSdnBackendExtensionPoint, + AfterAddIpRangeExtensionPoint, IpRangeDeletionExtensionPoint, GetSdnControllerExtensionPoint, + AfterAllocateSdnNicExtensionPoint { private static final CLogger logger = Utils.getLogger(SdnControllerManagerImpl.class); private static final Logger log = LoggerFactory.getLogger(SdnControllerManagerImpl.class); @@ -270,8 +270,13 @@ private void handle(APIAddSdnControllerMsg msg) { @Override public void run(MessageReply reply) { if (reply.isSuccess()) { - tagMgr.createTagsFromAPICreateMessage(msg, vo.getUuid(), SdnControllerVO.class.getSimpleName()); - event.setInventory(SdnControllerInventory.valueOf(dbf.findByUuid(vo.getUuid(), SdnControllerVO.class))); + try { + tagMgr.createTagsFromAPICreateMessage(msg, vo.getUuid(), SdnControllerVO.class.getSimpleName()); + event.setInventory(SdnControllerInventory.valueOf(dbf.findByUuid(vo.getUuid(), SdnControllerVO.class))); + } catch (Exception e) { + logger.warn(String.format("failed to load SdnControllerVO[uuid:%s] after init: %s", + vo.getUuid(), e.getMessage()), e); + } } else { event.setError(reply.getError()); } @@ -454,267 +459,26 @@ public void done(ErrorCodeList errorCodeList) { }); } - @Override - public void releaseVmResource(VmInstanceSpec spec, Completion completion) { - if (VmInstanceConstant.VmOperation.DetachNic != spec.getCurrentVmOperation() && - VmInstanceConstant.VmOperation.Destroy != spec.getCurrentVmOperation()) { - completion.success(); - return; - } - - if (spec.getL3Networks() == null || spec.getL3Networks().isEmpty()) { - completion.success(); - return; - } - - // we run into this situation when VM nics are all detached and the - // VM is being rebooted - if (spec.getDestNics().isEmpty()) { - completion.success(); - return; - } - - Map> nicMaps = new HashMap<>(); - for (VmNicInventory nic : spec.getDestNics()) { - L3NetworkVO l3Vo = dbf.findByUuid(nic.getL3NetworkUuid(), L3NetworkVO.class); - if (l3Vo == null) { - continue; - } - - L2NetworkVO l2VO = dbf.findByUuid(l3Vo.getL2NetworkUuid(), L2NetworkVO.class); - if (l2VO == null) { - continue; - } - - VSwitchType vSwitchType = VSwitchType.valueOf(l2VO.getvSwitchType()); - if (vSwitchType.getSdnControllerType() == null) { - continue; - } - - String controllerUuid = L2NetworkSystemTags.L2_NETWORK_SDN_CONTROLLER_UUID.getTokenByResourceUuid( - l2VO.getUuid(), L2NetworkSystemTags.L2_NETWORK_SDN_CONTROLLER_UUID_TOKEN); - if (controllerUuid == null) { - completion.fail(operr(ORG_ZSTACK_SDNCONTROLLER_10005, "sdn l2 network[uuid:%s] is not attached controller", l2VO.getUuid())); - return; - } - - nicMaps.computeIfAbsent(controllerUuid, k -> new ArrayList<>()).add(nic); - } - - if (nicMaps.isEmpty()) { - completion.success(); - return; - } - - removeLogicalPort(nicMaps, completion); - } - - @Override - public void instantiateResourceOnAttachingNic(VmInstanceSpec spec, L3NetworkInventory l3, Completion completion) { - L2NetworkVO l2NetworkVO = dbf.findByUuid(l3.getL2NetworkUuid(), L2NetworkVO.class); - VSwitchType vSwitchType = VSwitchType.valueOf(l2NetworkVO.getvSwitchType()); - if (vSwitchType.getSdnControllerType() == null) { - completion.success(); - return; - } - - String controllerUuid = L2NetworkSystemTags.L2_NETWORK_SDN_CONTROLLER_UUID.getTokenByResourceUuid( - l2NetworkVO.getUuid(), L2NetworkSystemTags.L2_NETWORK_SDN_CONTROLLER_UUID_TOKEN); - if (controllerUuid == null) { - completion.fail(operr(ORG_ZSTACK_SDNCONTROLLER_10006, "sdn l2 network[uuid:%s] is not attached controller", l2NetworkVO.getUuid())); - return; - } - - Map> nicMaps = new HashMap<>(); - List nics = new ArrayList<>(); - nics.add(spec.getDestNics().get(0)); - nicMaps.put(controllerUuid, nics); - sdnAddVmNics(nicMaps, completion); - } - - @Override - public void releaseResourceOnAttachingNic(VmInstanceSpec spec, L3NetworkInventory l3, NoErrorCompletion completion) { - L2NetworkVO l2NetworkVO = dbf.findByUuid(l3.getL2NetworkUuid(), L2NetworkVO.class); - VSwitchType vSwitchType = VSwitchType.valueOf(l2NetworkVO.getvSwitchType()); - if (vSwitchType.getSdnControllerType() == null) { - completion.done(); - return; - } - - String controllerUuid = L2NetworkSystemTags.L2_NETWORK_SDN_CONTROLLER_UUID.getTokenByResourceUuid( - l2NetworkVO.getUuid(), L2NetworkSystemTags.L2_NETWORK_SDN_CONTROLLER_UUID_TOKEN); - if (controllerUuid == null) { - logger.warn(String.format("sdn l2 network[uuid:%s] is not attached controller", l2NetworkVO.getUuid())); - completion.done(); - return; - } - - Map> nicMaps = new HashMap<>(); - List nics = new ArrayList<>(); - nics.add(spec.getDestNics().get(0)); - nicMaps.put(controllerUuid, nics); - - removeLogicalPort(nicMaps, new Completion(completion) { - @Override - public void success() { - completion.done(); - } - - @Override - public void fail(ErrorCode errorCode) { - logger.info(String.format("failed to remove logical port for vm[uuid:%s] nic[internalName:%s], because: %s", - spec.getVmInventory().getUuid(), spec.getDestNics().get(0).getInternalName(), errorCode.getDetails())); - completion.done(); - } - }); - } - - @Override - public void releaseResourceOnDetachingNic(VmInstanceSpec spec, VmNicInventory nic, NoErrorCompletion completion) { - L3NetworkVO l3Vo = dbf.findByUuid(nic.getL3NetworkUuid(), L3NetworkVO.class); - L2NetworkVO l2NetworkVO = dbf.findByUuid(l3Vo.getL2NetworkUuid(), L2NetworkVO.class); - VSwitchType vSwitchType = VSwitchType.valueOf(l2NetworkVO.getvSwitchType()); - if (vSwitchType.getSdnControllerType() == null) { - completion.done(); - return; - } - - String controllerUuid = L2NetworkSystemTags.L2_NETWORK_SDN_CONTROLLER_UUID.getTokenByResourceUuid( - l2NetworkVO.getUuid(), L2NetworkSystemTags.L2_NETWORK_SDN_CONTROLLER_UUID_TOKEN); - if (controllerUuid == null) { - logger.warn(String.format("sdn l2 network[uuid:%s] is not attached controller", l2NetworkVO.getUuid())); - completion.done(); - return; - } - - Map> nicMaps = new HashMap<>(); - List nics = new ArrayList<>(); - nics.add(spec.getDestNics().get(0)); - nicMaps.put(controllerUuid, nics); - - removeLogicalPort(nicMaps, new Completion(completion) { - @Override - public void success() { - completion.done(); - } - - @Override - public void fail(ErrorCode errorCode) { - logger.info(String.format("failed to remove logical port for vm[uuid:%s] nic[internalName:%s], because: %s", - spec.getVmInventory().getUuid(), spec.getDestNics().get(0).getInternalName(), errorCode.getDetails())); - completion.done(); - } - }); - } - - @Override - public void preBeforeInstantiateVmResource(VmInstanceSpec spec) throws VmInstantiateResourceException { - + /** + * Returns true if the L2 network should be skipped for SDN port management: + * it has no SDN controller type configured on its VSwitchType. + */ + private boolean shouldSkipSdnForNic(L2NetworkVO l2VO) { + VSwitchType vSwitchType = VSwitchType.valueOf(l2VO.getvSwitchType()); + return vSwitchType.getSdnControllerType() == null; } - @Override - public void preInstantiateVmResource(VmInstanceSpec spec, Completion completion) { - if (spec.getL3Networks() == null || spec.getL3Networks().isEmpty()) { - completion.success(); - return; - } - - // we run into this situation when VM nics are all detached and the - // VM is being rebooted - if (spec.getDestNics().isEmpty()) { - completion.success(); - return; - } - - Map> nicMaps = new HashMap<>(); - for (VmNicInventory nic : spec.getDestNics()) { - L3NetworkVO l3Vo = dbf.findByUuid(nic.getL3NetworkUuid(), L3NetworkVO.class); - if (l3Vo == null) { - continue; - } - - L2NetworkVO l2VO = dbf.findByUuid(l3Vo.getL2NetworkUuid(), L2NetworkVO.class); - if (l2VO == null) { - continue; - } - - VSwitchType vSwitchType = VSwitchType.valueOf(l2VO.getvSwitchType()); - if (vSwitchType.getSdnControllerType() ==null) { - continue; - } - - String controllerUuid = L2NetworkSystemTags.L2_NETWORK_SDN_CONTROLLER_UUID.getTokenByResourceUuid( - l2VO.getUuid(), L2NetworkSystemTags.L2_NETWORK_SDN_CONTROLLER_UUID_TOKEN); - if (controllerUuid == null) { - completion.fail(operr(ORG_ZSTACK_SDNCONTROLLER_10007, "sdn l2 network[uuid:%s] is not attached controller", l2VO.getUuid())); - return; - } - - nicMaps.computeIfAbsent(controllerUuid, k -> new ArrayList<>()).add(nic); - } - - if (nicMaps.isEmpty()) { - completion.success(); - return; - } - - sdnAddVmNics(nicMaps, completion); - } - - @Override - public void preReleaseVmResource(VmInstanceSpec spec, Completion completion) { - // create/start/reboot vm failed, code will go here VmInstantiateResourcePreFlow.rollack() - // vm change image failed, - if (VmInstanceConstant.VmOperation.NewCreate != spec.getCurrentVmOperation()) { - completion.success(); - return; - } - - if (spec.getL3Networks() == null || spec.getL3Networks().isEmpty()) { - completion.success(); - return; - } - - // we run into this situation when VM nics are all detached and the - // VM is being rebooted - if (spec.getDestNics().isEmpty()) { - completion.success(); - return; - } - - Map> nicMaps = new HashMap<>(); - for (VmNicInventory nic : spec.getDestNics()) { - L3NetworkVO l3Vo = dbf.findByUuid(nic.getL3NetworkUuid(), L3NetworkVO.class); - if (l3Vo == null) { - continue; - } - - L2NetworkVO l2VO = dbf.findByUuid(l3Vo.getL2NetworkUuid(), L2NetworkVO.class); - if (l2VO == null) { - continue; - } - - VSwitchType vSwitchType = VSwitchType.valueOf(l2VO.getvSwitchType()); - if (vSwitchType.getSdnControllerType() ==null) { - continue; - } - - String controllerUuid = L2NetworkSystemTags.L2_NETWORK_SDN_CONTROLLER_UUID.getTokenByResourceUuid( - l2VO.getUuid(), L2NetworkSystemTags.L2_NETWORK_SDN_CONTROLLER_UUID_TOKEN); - if (controllerUuid == null) { - completion.fail(operr(ORG_ZSTACK_SDNCONTROLLER_10008, "sdn l2 network[uuid:%s] is not attached controller", l2VO.getUuid())); - return; - } - - nicMaps.computeIfAbsent(controllerUuid, k -> new ArrayList<>()).add(nic); + private Set getNewlyAllocatedNicUuidsForStart(VmInstanceSpec spec) { + if (spec.getCurrentVmOperation() != VmInstanceConstant.VmOperation.Start) { + return null; } - if (nicMaps.isEmpty()) { - completion.success(); - return; + List nicUuids = spec.getExtensionData(SdnControllerConstant.ALLOCATED_IPS_ON_START, List.class); + if (nicUuids == null || nicUuids.isEmpty()) { + return Collections.emptySet(); } - removeLogicalPort(nicMaps, completion); + return new HashSet<>(nicUuids); } @Override @@ -899,4 +663,207 @@ private SdnControllerVO getSdnControllerVO(L3NetworkInventory l3Network) { } return dbf.findByUuid(sdnControllerUuid, SdnControllerVO.class); } + + @Override + public void afterAllocateSdnNic(VmInstanceSpec spec, List nics, Completion completion) { + if (nics == null || nics.isEmpty()) { + completion.success(); + return; + } + + Set newlyAllocatedNicUuids = getNewlyAllocatedNicUuidsForStart(spec); + Map> nicMaps = new HashMap<>(); + for (VmNicInventory nic : nics) { + L3NetworkVO l3Vo = dbf.findByUuid(nic.getL3NetworkUuid(), L3NetworkVO.class); + if (l3Vo == null) { + continue; + } + + L2NetworkVO l2VO = dbf.findByUuid(l3Vo.getL2NetworkUuid(), L2NetworkVO.class); + if (l2VO == null || shouldSkipSdnForNic(l2VO)) { + continue; + } + + if (newlyAllocatedNicUuids != null + && L2NetworkConstant.VSWITCH_TYPE_OVN_DPDK.equals(l2VO.getvSwitchType()) + && !newlyAllocatedNicUuids.contains(nic.getUuid())) { + continue; + } + + String controllerUuid = L2NetworkSystemTags.L2_NETWORK_SDN_CONTROLLER_UUID.getTokenByResourceUuid( + l2VO.getUuid(), L2NetworkSystemTags.L2_NETWORK_SDN_CONTROLLER_UUID_TOKEN); + if (controllerUuid == null) { + completion.fail(operr(ORG_ZSTACK_SDNCONTROLLER_10006, "sdn l2 network[uuid:%s] has not attached controller", l2VO.getUuid())); + return; + } + + nicMaps.computeIfAbsent(controllerUuid, k -> new ArrayList<>()).add(nic); + } + + if (nicMaps.isEmpty()) { + completion.success(); + return; + } + + sdnAddVmNics(nicMaps, completion); + } + + @Override + public void rollbackSdnNic(VmInstanceSpec spec, List nics, Completion completion) { + if (nics == null || nics.isEmpty()) { + completion.success(); + return; + } + + Map> nicMaps = new HashMap<>(); + for (VmNicInventory nic : nics) { + L3NetworkVO l3Vo = dbf.findByUuid(nic.getL3NetworkUuid(), L3NetworkVO.class); + if (l3Vo == null) { + continue; + } + + L2NetworkVO l2VO = dbf.findByUuid(l3Vo.getL2NetworkUuid(), L2NetworkVO.class); + if (l2VO == null || shouldSkipSdnForNic(l2VO)) { + continue; + } + + String controllerUuid = L2NetworkSystemTags.L2_NETWORK_SDN_CONTROLLER_UUID.getTokenByResourceUuid( + l2VO.getUuid(), L2NetworkSystemTags.L2_NETWORK_SDN_CONTROLLER_UUID_TOKEN); + if (controllerUuid == null) { + continue; + } + + nicMaps.computeIfAbsent(controllerUuid, k -> new ArrayList<>()).add(nic); + } + + if (nicMaps.isEmpty()) { + completion.success(); + return; + } + + removeLogicalPort(nicMaps, completion); + } + + @Override + public void releaseSdnNics(List nics, Completion completion) { + if (nics == null || nics.isEmpty()) { + completion.success(); + return; + } + + Map> nicMaps = new HashMap<>(); + for (VmNicInventory nic : nics) { + L3NetworkVO l3Vo = dbf.findByUuid(nic.getL3NetworkUuid(), L3NetworkVO.class); + if (l3Vo == null) { + continue; + } + + L2NetworkVO l2VO = dbf.findByUuid(l3Vo.getL2NetworkUuid(), L2NetworkVO.class); + if (l2VO == null || shouldSkipSdnForNic(l2VO)) { + continue; + } + + String controllerUuid = L2NetworkSystemTags.L2_NETWORK_SDN_CONTROLLER_UUID.getTokenByResourceUuid( + l2VO.getUuid(), L2NetworkSystemTags.L2_NETWORK_SDN_CONTROLLER_UUID_TOKEN); + if (controllerUuid == null) { + continue; + } + + nicMaps.computeIfAbsent(controllerUuid, k -> new ArrayList<>()).add(nic); + } + + if (nicMaps.isEmpty()) { + completion.success(); + return; + } + + removeLogicalPort(nicMaps, completion); + } + + @Override + public void releaseNicIps(List nics, Completion completion) { + if (nics == null || nics.isEmpty()) { + completion.success(); + return; + } + + Map> nicMaps = new HashMap<>(); + for (VmNicInventory nic : nics) { + L3NetworkVO l3Vo = dbf.findByUuid(nic.getL3NetworkUuid(), L3NetworkVO.class); + if (l3Vo == null) { + continue; + } + + L2NetworkVO l2VO = dbf.findByUuid(l3Vo.getL2NetworkUuid(), L2NetworkVO.class); + if (l2VO == null || shouldSkipSdnForNic(l2VO)) { + continue; + } + + String controllerUuid = L2NetworkSystemTags.L2_NETWORK_SDN_CONTROLLER_UUID.getTokenByResourceUuid( + l2VO.getUuid(), L2NetworkSystemTags.L2_NETWORK_SDN_CONTROLLER_UUID_TOKEN); + if (controllerUuid == null) { + continue; + } + + nicMaps.computeIfAbsent(controllerUuid, k -> new ArrayList<>()).add(nic); + } + + if (nicMaps.isEmpty()) { + completion.success(); + return; + } + + releaseNicIpsFromPort(nicMaps, completion); + } + + private void releaseNicIpsFromPort(Map> nicMaps, Completion completion) { + new While<>(nicMaps.entrySet()).each((e, wcomp) -> { + SdnControllerVO vo = dbf.findByUuid(e.getKey(), SdnControllerVO.class); + if (vo == null) { + wcomp.addError(operr(ORG_ZSTACK_SDNCONTROLLER_10031, + "cannot release SDN NIC IPs because sdn controller[uuid:%s] cannot be found", e.getKey())); + wcomp.allDone(); + return; + } + SdnControllerFactory factory; + try { + factory = getSdnControllerFactory(vo.getVendorType()); + } catch (CloudRuntimeException ex) { + wcomp.addError(operr(ORG_ZSTACK_SDNCONTROLLER_10032, + "cannot release SDN NIC IPs because sdn controller factory[type:%s] cannot be found: %s", + vo.getVendorType(), ex.getMessage())); + wcomp.allDone(); + return; + } + SdnControllerL2 controller = factory.getSdnControllerL2(vo); + if (controller == null) { + wcomp.addError(operr(ORG_ZSTACK_SDNCONTROLLER_10033, + "cannot release SDN NIC IPs because sdn controller L2[controllerUuid:%s, type:%s] cannot be found", + vo.getUuid(), vo.getVendorType())); + wcomp.allDone(); + return; + } + controller.releaseNicIps(e.getValue(), new Completion(wcomp) { + @Override + public void success() { + wcomp.done(); + } + + @Override + public void fail(ErrorCode errorCode) { + wcomp.addError(errorCode); + wcomp.allDone(); + } + }); + }).run(new WhileDoneCompletion(completion) { + @Override + public void done(ErrorCodeList errorCodeList) { + if (errorCodeList.getCauses().isEmpty()) { + completion.success(); + } else { + completion.fail(errorCodeList.getCauses().get(0)); + } + } + }); + } } diff --git a/plugin/sdnController/src/main/java/org/zstack/sdnController/SdnControllerPingTracker.java b/plugin/sdnController/src/main/java/org/zstack/sdnController/SdnControllerPingTracker.java index a959dee3005..d52d26909be 100644 --- a/plugin/sdnController/src/main/java/org/zstack/sdnController/SdnControllerPingTracker.java +++ b/plugin/sdnController/src/main/java/org/zstack/sdnController/SdnControllerPingTracker.java @@ -18,6 +18,7 @@ import org.zstack.header.network.l2.SdnControllerDeleteExtensionPoint; import org.zstack.header.network.sdncontroller.SdnControllerConstant; import org.zstack.header.network.sdncontroller.SdnControllerStatus; +import org.zstack.header.network.sdncontroller.SdnControllerStatusEvent; import org.zstack.header.network.sdncontroller.SdnControllerVO; import org.zstack.header.network.sdncontroller.SdnControllerVO_; import org.zstack.sdnController.header.*; @@ -53,6 +54,11 @@ public String getResourceName() { @Override public NeedReplyMessage getPingMessage(String resUuid) { SdnControllerVO vo = dbf.findByUuid(resUuid, SdnControllerVO.class); + if (vo == null) { + logger.warn(String.format("SDN controller[uuid:%s] has been deleted, skip ping sending", resUuid)); + untrack(resUuid); + return null; + } if (vo.getStatus() == SdnControllerStatus.Connecting) { return null; } @@ -81,10 +87,9 @@ public void handleReply(final String resourceUuid, MessageReply reply) { return; } - if (!reply.isSuccess()) { logger.warn(String.format("[SDN Ping Tracker]: unable to ping the sdn controller[uuid: %s], %s", resourceUuid, reply.getError())); - new SdnControllerBase(vo).changeSdnControllerStatus(SdnControllerStatus.Disconnected); + sdnMgr.getSdnControllerFactory(vo.getVendorType()).changeSdnControllerStatus(vo, SdnControllerStatusEvent.PING_FAILED); return; } diff --git a/plugin/sdnController/src/main/java/org/zstack/sdnController/h3cVcfc/H3cVcfcSdnControllerFactory.java b/plugin/sdnController/src/main/java/org/zstack/sdnController/h3cVcfc/H3cVcfcSdnControllerFactory.java index 2d297ca518c..75864392a31 100644 --- a/plugin/sdnController/src/main/java/org/zstack/sdnController/h3cVcfc/H3cVcfcSdnControllerFactory.java +++ b/plugin/sdnController/src/main/java/org/zstack/sdnController/h3cVcfc/H3cVcfcSdnControllerFactory.java @@ -5,11 +5,10 @@ import org.zstack.header.network.sdncontroller.SdnControllerConstant; import org.zstack.header.network.sdncontroller.SdnControllerVO; import org.zstack.network.securitygroup.SecurityGroupSdnBackend; -import org.zstack.sdnController.SdnController; -import org.zstack.sdnController.SdnControllerFactory; +import org.zstack.sdnController.*; import org.zstack.sdnController.*; -public class H3cVcfcSdnControllerFactory implements SdnControllerFactory { +public class H3cVcfcSdnControllerFactory extends AbstractSdnControllerFactory { SdnControllerType sdnControllerType = new SdnControllerType(SdnControllerConstant.H3C_VCFC_CONTROLLER); @Autowired @@ -20,12 +19,6 @@ public SdnControllerType getVendorType() { return sdnControllerType; } - @Override - public SdnControllerVO persistSdnController(SdnControllerVO vo) { - vo = dbf.persistAndRefresh(vo); - return vo; - } - @Override public SdnController getSdnController(SdnControllerVO vo) { diff --git a/plugin/sharedMountPointPrimaryStorage/src/main/java/org/zstack/storage/primary/smp/SMPPrimaryStorageBase.java b/plugin/sharedMountPointPrimaryStorage/src/main/java/org/zstack/storage/primary/smp/SMPPrimaryStorageBase.java index 5cc408452cd..6f16e83eb3c 100755 --- a/plugin/sharedMountPointPrimaryStorage/src/main/java/org/zstack/storage/primary/smp/SMPPrimaryStorageBase.java +++ b/plugin/sharedMountPointPrimaryStorage/src/main/java/org/zstack/storage/primary/smp/SMPPrimaryStorageBase.java @@ -59,6 +59,7 @@ import static org.zstack.utils.CollectionDSL.e; import static org.zstack.utils.CollectionDSL.map; import static org.zstack.utils.clouderrorcode.CloudOperationsErrorCode.*; +import org.zstack.header.storage.primary.ReInitDataVolumeOnPrimaryStorageMsg; /** * Created by xing5 on 2016/3/26. @@ -991,6 +992,12 @@ public void fail(ErrorCode errorCode) { }); } + @Override + protected void handle(ReInitDataVolumeOnPrimaryStorageMsg msg) { + bus.dealWithUnknownMessage(msg); + } + + @Override protected void handle(final DeleteSnapshotOnPrimaryStorageMsg msg) { HypervisorBackend bkd = getHypervisorBackendByVolumeUuid(msg.getSnapshot().getVolumeUuid()); diff --git a/plugin/sugonSdnController/src/main/java/org/zstack/sugonSdnController/controller/SugonSdnController.java b/plugin/sugonSdnController/src/main/java/org/zstack/sugonSdnController/controller/SugonSdnController.java index 976ad9829c5..00e88fa61f4 100644 --- a/plugin/sugonSdnController/src/main/java/org/zstack/sugonSdnController/controller/SugonSdnController.java +++ b/plugin/sugonSdnController/src/main/java/org/zstack/sugonSdnController/controller/SugonSdnController.java @@ -22,10 +22,13 @@ import org.zstack.network.l3.L3NetworkSystemTags; import org.zstack.sdnController.SdnController; import org.zstack.sdnController.SdnControllerL2; +import org.zstack.sdnController.SdnControllerPingMsg; +import org.zstack.sdnController.SdnControllerPingReply; import org.zstack.sdnController.header.*; import org.zstack.sugonSdnController.controller.api.*; import org.zstack.sugonSdnController.controller.api.types.*; import org.zstack.sugonSdnController.header.APICreateL2TfNetworkMsg; +import org.zstack.sugonSdnController.network.TfZstackPortSync; import org.zstack.utils.StringDSL; import org.zstack.utils.Utils; import org.zstack.utils.logging.CLogger; @@ -45,6 +48,8 @@ public class SugonSdnController implements TfSdnController, SdnController, SdnCo CloudBus bus; @Autowired DatabaseFacade dbf; + @Autowired + TfZstackPortSync tfZstackPortSync; private SdnControllerVO sdnControllerVO; private TfHttpClient client; @@ -57,7 +62,9 @@ public SugonSdnController(SdnControllerVO vo) { @Override public void handleMessage(SdnControllerMessage msg) { - if (msg instanceof SdnControllerEnableDHCPMsg) { + if (msg instanceof SdnControllerPingMsg) { + handMessage((SdnControllerPingMsg) msg); + } else if (msg instanceof SdnControllerEnableDHCPMsg) { handMessage((SdnControllerEnableDHCPMsg) msg); } else if (msg instanceof SdnControllerDisableDHCPMsg) { handMessage((SdnControllerDisableDHCPMsg) msg); @@ -83,6 +90,23 @@ void handMessage(SdnControllerUpdateDHCPMsg msg) { bus.reply(msg, reply); } + void handMessage(SdnControllerPingMsg msg) { + SdnControllerPingReply reply = new SdnControllerPingReply(); + try { + Domain domain = (Domain) client.getDomain(); + if (domain == null) { + reply.setError(operr(ORG_ZSTACK_SUGONSDNCONTROLLER_CONTROLLER_10002, "get default domain on tf controller failed")); + } else { + tfZstackPortSync.triggerSyncIfDue(msg.getSdnControllerUuid()); + reply.setSuccess(true); + } + } catch (Exception e) { + logger.warn("ping tf sdn controller failed", e); + reply.setError(operr(ORG_ZSTACK_SUGONSDNCONTROLLER_CONTROLLER_10002, "get default domain on tf controller failed")); + } + bus.reply(msg, reply); + } + @Override public void preInitSdnController(AddSdnControllerMsg msg, Completion completion) { try { diff --git a/plugin/sugonSdnController/src/main/java/org/zstack/sugonSdnController/controller/SugonSdnControllerFactory.java b/plugin/sugonSdnController/src/main/java/org/zstack/sugonSdnController/controller/SugonSdnControllerFactory.java index b277a336c3d..97dde1b0725 100644 --- a/plugin/sugonSdnController/src/main/java/org/zstack/sugonSdnController/controller/SugonSdnControllerFactory.java +++ b/plugin/sugonSdnController/src/main/java/org/zstack/sugonSdnController/controller/SugonSdnControllerFactory.java @@ -3,13 +3,14 @@ import org.springframework.beans.factory.annotation.Autowired; import org.zstack.core.db.DatabaseFacade; import org.zstack.network.securitygroup.SecurityGroupSdnBackend; +import org.zstack.sdnController.AbstractSdnControllerFactory; import org.zstack.sdnController.SdnController; import org.zstack.sdnController.SdnControllerFactory; import org.zstack.sdnController.SdnControllerL2; import org.zstack.sdnController.SdnControllerType; import org.zstack.header.network.sdncontroller.SdnControllerVO; -public class SugonSdnControllerFactory implements SdnControllerFactory { +public class SugonSdnControllerFactory extends AbstractSdnControllerFactory { SdnControllerType sdnControllerType = new SdnControllerType(SugonSdnControllerConstant.TF_CONTROLLER); @@ -21,11 +22,6 @@ public SdnControllerType getVendorType() { return sdnControllerType; } - @Override - public SdnControllerVO persistSdnController(SdnControllerVO vo) { - vo = dbf.persistAndRefresh(vo); - return vo; - } @Override public SdnController getSdnController(SdnControllerVO vo) { diff --git a/plugin/sugonSdnController/src/main/java/org/zstack/sugonSdnController/controller/neutronClient/TfPortClient.java b/plugin/sugonSdnController/src/main/java/org/zstack/sugonSdnController/controller/neutronClient/TfPortClient.java index 1054f708696..2c531684d1b 100644 --- a/plugin/sugonSdnController/src/main/java/org/zstack/sugonSdnController/controller/neutronClient/TfPortClient.java +++ b/plugin/sugonSdnController/src/main/java/org/zstack/sugonSdnController/controller/neutronClient/TfPortClient.java @@ -32,6 +32,22 @@ public TfPortClient(){ if (sdn == null){ throw new RuntimeException("Can not find a tf sdn controller."); } + init(sdn); + } + + public TfPortClient(String sdnControllerUuid) { + SdnControllerVO sdn = Q.New(SdnControllerVO.class).eq( + SdnControllerVO_.uuid, sdnControllerUuid).find(); + if (sdn == null) { + throw new RuntimeException(String.format("Can not find a tf sdn controller[uuid:%s].", sdnControllerUuid)); + } + if (!Objects.equals(sdn.getVendorType(), SdnControllerConstant.TF_CONTROLLER)) { + throw new RuntimeException(String.format("Sdn controller[uuid:%s] is not a tf sdn controller.", sdnControllerUuid)); + } + init(sdn); + } + + private void init(SdnControllerVO sdn) { client = new TfHttpClient(sdn.getIp()); tenantId = StringDSL.transToTfUuid(sdn.getAccountUuid()); } @@ -509,4 +525,3 @@ public Status updateTfPort(String tfPortUUid, String accountId, String deviceId, } } - diff --git a/plugin/sugonSdnController/src/main/java/org/zstack/sugonSdnController/network/TfPortService.java b/plugin/sugonSdnController/src/main/java/org/zstack/sugonSdnController/network/TfPortService.java index c4767689bd1..e7a9f0c0419 100644 --- a/plugin/sugonSdnController/src/main/java/org/zstack/sugonSdnController/network/TfPortService.java +++ b/plugin/sugonSdnController/src/main/java/org/zstack/sugonSdnController/network/TfPortService.java @@ -33,6 +33,11 @@ public List getTfPortsDetail() { return tfPortClient.getVirtualMachineInterfaceDetail(); } + public List getTfPortsDetail(String sdnControllerUuid) { + TfPortClient tfPortClient = new TfPortClient(sdnControllerUuid); + return tfPortClient.getVirtualMachineInterfaceDetail(); + } + public TfPortResponse createTfPort(String tfPortUUid, String l2NetworkUuid, String l3NetworkUuid, String mac, String ip) { //invoke tf rest interface to retrieve real ip and mac and portId TfPortClient tfPortClient = new TfPortClient(); @@ -115,6 +120,12 @@ public TfPortResponse deleteTfPort(String portUUid) { return tfPortClient.deletePort(tfPortUUid); } + public TfPortResponse deleteTfPort(String sdnControllerUuid, String portUUid) { + String tfPortUUid = StringDSL.transToTfUuid(portUUid); + TfPortClient tfPortClient = new TfPortClient(sdnControllerUuid); + return tfPortClient.deletePort(tfPortUUid); + } + public Status updateTfPort(String portUUid, String bmUuid, KeyValuePairs bindInfo) { String accountId = StringDSL.transToTfUuid(acntMgr.getOwnerAccountUuidOfResource(bmUuid)); String tfBmUUid = StringDSL.transToTfUuid(bmUuid); diff --git a/plugin/sugonSdnController/src/main/java/org/zstack/sugonSdnController/network/TfZstackPortSync.java b/plugin/sugonSdnController/src/main/java/org/zstack/sugonSdnController/network/TfZstackPortSync.java index 184b2e721ed..710b63cdb2b 100644 --- a/plugin/sugonSdnController/src/main/java/org/zstack/sugonSdnController/network/TfZstackPortSync.java +++ b/plugin/sugonSdnController/src/main/java/org/zstack/sugonSdnController/network/TfZstackPortSync.java @@ -2,9 +2,8 @@ import org.springframework.beans.factory.annotation.Autowired; import org.zstack.core.db.Q; -import org.zstack.core.thread.PeriodicTask; +import org.zstack.core.thread.Task; import org.zstack.core.thread.ThreadFacade; -import org.zstack.header.managementnode.ManagementNodeReadyExtensionPoint; import org.zstack.header.network.l2.L2NetworkVO; import org.zstack.header.network.l2.L2NetworkVO_; import org.zstack.header.vm.VmNicVO; @@ -19,39 +18,57 @@ import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.HashSet; import java.util.List; -import java.util.concurrent.Future; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; -public class TfZstackPortSync implements ManagementNodeReadyExtensionPoint { +public class TfZstackPortSync { + private static final long SYNC_INTERVAL_MILLIS = TimeUnit.DAYS.toMillis(1); + private static final int MAX_DELETE_COUNT = 10; @Autowired protected ThreadFacade thdf; - private Future trackerThread = null; @Autowired private TfPortService tfPortService; private final static CLogger logger = Utils.getLogger(TfZstackPortSync.class); private final List excludeTypes = new ArrayList(Arrays.asList("neutron:LOADBALANCER", "VIP", "BMS")); + private final Map lastSyncTime = new ConcurrentHashMap<>(); + private final Set runningSyncs = Collections.newSetFromMap(new ConcurrentHashMap()); - @Override - public void managementNodeReady() { - if (trackerThread != null) { - trackerThread.cancel(true); + public void triggerSyncIfDue(String sdnControllerUuid) { + if (sdnControllerUuid == null) { + logger.warn("Port_Sync_Task: skip sync because sdn controller uuid is null."); + return; } - trackerThread = thdf.submitPeriodicTask(new SyncPort()); - } - private class SyncPort implements PeriodicTask { + long now = System.currentTimeMillis(); + Long lastSync = lastSyncTime.get(sdnControllerUuid); + if (lastSync != null && now - lastSync < SYNC_INTERVAL_MILLIS) { + return; + } + if (!runningSyncs.add(sdnControllerUuid)) { + return; + } - @Override - public TimeUnit getTimeUnit() { - return TimeUnit.DAYS; + lastSyncTime.put(sdnControllerUuid, now); + try { + thdf.submit(new SyncPort(sdnControllerUuid)); + } catch (RuntimeException e) { + lastSyncTime.remove(sdnControllerUuid); + runningSyncs.remove(sdnControllerUuid); + throw e; } + } - @Override - public long getInterval() { - return 1; + private class SyncPort implements Task { + private final String sdnControllerUuid; + + private SyncPort(String sdnControllerUuid) { + this.sdnControllerUuid = sdnControllerUuid; } @Override @@ -64,7 +81,10 @@ private HashSet getPortToDelete() { List zstackL2NetworksUuid = Q.New(L2NetworkVO.class).select(L2NetworkVO_.uuid).listValues(); List tfPortsUuid = new ArrayList<>(); try{ - List tfPorts = tfPortService.getTfPortsDetail(); + List tfPorts = tfPortService.getTfPortsDetail(sdnControllerUuid); + if (tfPorts == null) { + return new HashSet<>(); + } for (VirtualMachineInterface vmi : tfPorts) { // skip port if it's network not in zstack List> tfNetworks = vmi.getVirtualNetwork(); @@ -83,7 +103,7 @@ private HashSet getPortToDelete() { } } catch (Exception e) { logger.error(String.format("Port_Sync_Task: Fetch tf VirtualMachineInterface failed: %s.", e)); - return null; + return new HashSet<>(); } HashSet result = new HashSet<>(tfPortsUuid); result.removeAll(zstackPortsUuid); @@ -92,13 +112,13 @@ private HashSet getPortToDelete() { } @Override - public void run() { + public Void call() { logger.info("Port_Sync_Task: begin."); try { HashSet portsToDelete = getPortToDelete(); - int maxDeleteCount = 10; + int maxDeleteCount = MAX_DELETE_COUNT; for (String portUuid: portsToDelete) { - TfPortResponse response = tfPortService.deleteTfPort(portUuid); + TfPortResponse response = tfPortService.deleteTfPort(sdnControllerUuid, portUuid); if (response.getCode() == 200) { logger.info(String.format("Port_Sync_Task: VirtualMachineInterface: %s delete success.", portUuid)); @@ -113,7 +133,10 @@ public void run() { } } catch (Exception e) { logger.error(String.format("Port_Sync_Task failed: %s.", e)); + } finally { + runningSyncs.remove(sdnControllerUuid); } + return null; } } } diff --git a/plugin/virtualRouterProvider/src/main/java/org/zstack/network/service/virtualrouter/ReconnectVirtualRouterVmMsg.java b/plugin/virtualRouterProvider/src/main/java/org/zstack/network/service/virtualrouter/ReconnectVirtualRouterVmMsg.java index a0e0d182f18..1685900181d 100755 --- a/plugin/virtualRouterProvider/src/main/java/org/zstack/network/service/virtualrouter/ReconnectVirtualRouterVmMsg.java +++ b/plugin/virtualRouterProvider/src/main/java/org/zstack/network/service/virtualrouter/ReconnectVirtualRouterVmMsg.java @@ -9,6 +9,7 @@ public class ReconnectVirtualRouterVmMsg extends NeedReplyMessage implements VmInstanceMessage { private String virtualRouterVmUuid; private boolean statusChange = false; + private boolean skipGrayscaleUpgradeCheck = false; public String getVirtualRouterVmUuid() { @@ -31,4 +32,12 @@ public boolean isStatusChange() { public void setStatusChange(boolean statusChange) { this.statusChange = statusChange; } + + public boolean isSkipGrayscaleUpgradeCheck() { + return skipGrayscaleUpgradeCheck; + } + + public void setSkipGrayscaleUpgradeCheck(boolean skipGrayscaleUpgradeCheck) { + this.skipGrayscaleUpgradeCheck = skipGrayscaleUpgradeCheck; + } } diff --git a/plugin/virtualRouterProvider/src/main/java/org/zstack/network/service/virtualrouter/VirtualRouter.java b/plugin/virtualRouterProvider/src/main/java/org/zstack/network/service/virtualrouter/VirtualRouter.java index de4468664dd..85a275a84e0 100755 --- a/plugin/virtualRouterProvider/src/main/java/org/zstack/network/service/virtualrouter/VirtualRouter.java +++ b/plugin/virtualRouterProvider/src/main/java/org/zstack/network/service/virtualrouter/VirtualRouter.java @@ -68,6 +68,16 @@ public class VirtualRouter extends ApplianceVmBase { private static final CLogger logger = Utils.getLogger(VirtualRouter.class); + private enum GrayscaleUpgradeCheck { + REQUIRED, + SKIPPED + } + + private enum ReconnectSource { + INTERNAL, + API + } + static { allowedOperations.addState(VmInstanceState.Running, APIReconnectVirtualRouterMsg.class.getName()); allowedOperations.addState(VmInstanceState.Running, APIProvisionVirtualRouterConfigMsg.class.getName()); @@ -608,7 +618,7 @@ public String getSyncSignature() { public void run(final SyncTaskChain chain) { final ReconnectVirtualRouterVmReply reply = new ReconnectVirtualRouterVmReply(); - if (upgradeChecker.skipInnerDeployOrInitOnCurrentAgent(self.getUuid())) { + if (!msg.isSkipGrayscaleUpgradeCheck() && upgradeChecker.skipInnerDeployOrInitOnCurrentAgent(self.getUuid())) { bus.reply(msg, reply); chain.next(); return; @@ -626,7 +636,7 @@ public void run(final SyncTaskChain chain) { return; } - reconnect(new Completion(msg, chain) { + Completion completion = new Completion(msg, chain) { @Override public void success() { bus.reply(msg, reply); @@ -639,7 +649,13 @@ public void fail(ErrorCode errorCode) { bus.reply(msg, reply); chain.next(); } - }); + }; + + if (msg.isSkipGrayscaleUpgradeCheck()) { + reconnectWithoutGrayscaleUpgradeCheck(completion); + } else { + reconnect(completion); + } } @Override @@ -849,7 +865,7 @@ public void run(final SyncTaskChain chain) { return; } - reconnect(true, new Completion(msg, chain) { + reconnectFromApi(new Completion(msg, chain) { @Override public void success() { evt.setInventory((ApplianceVmInventory) getSelfInventory()); @@ -874,10 +890,18 @@ public String getName() { } private void reconnect(final Completion completion) { - reconnect(false, completion); + reconnect(ReconnectSource.INTERNAL, GrayscaleUpgradeCheck.REQUIRED, completion); + } + + private void reconnectFromApi(final Completion completion) { + reconnect(ReconnectSource.API, GrayscaleUpgradeCheck.REQUIRED, completion); + } + + private void reconnectWithoutGrayscaleUpgradeCheck(final Completion completion) { + reconnect(ReconnectSource.INTERNAL, GrayscaleUpgradeCheck.SKIPPED, completion); } - private void reconnect(Boolean fromApi, final Completion completion) { + private void reconnect(ReconnectSource source, GrayscaleUpgradeCheck grayscaleUpgradeCheck, final Completion completion) { ApplianceVmStatus oldStatus = getSelf().getStatus(); FlowChain chain = getReconnectChain(); @@ -887,7 +911,8 @@ private void reconnect(Boolean fromApi, final Completion completion) { chain.getData().put(Params.isReconnect.toString(), Boolean.TRUE.toString()); chain.getData().put(Params.managementNicIp.toString(), vr.getManagementNic().getIp()); chain.getData().put(Params.applianceVmUuid.toString(), self.getUuid()); - chain.getData().put(Params.fromApi.toString(), fromApi.toString()); + chain.getData().put(Params.fromApi.toString(), Boolean.toString(source == ReconnectSource.API)); + chain.getData().put(Params.skipGrayscaleUpgradeCheck.toString(), Boolean.toString(grayscaleUpgradeCheck == GrayscaleUpgradeCheck.SKIPPED)); SimpleQuery q = dbf.createQuery(ApplianceVmFirewallRuleVO.class); q.add(ApplianceVmFirewallRuleVO_.applianceVmUuid, Op.EQ, getSelf().getUuid()); diff --git a/plugin/virtualRouterProvider/src/main/java/org/zstack/network/service/virtualrouter/VirtualRouterManagerImpl.java b/plugin/virtualRouterProvider/src/main/java/org/zstack/network/service/virtualrouter/VirtualRouterManagerImpl.java index a876ee24a34..e6b4e2c15fb 100755 --- a/plugin/virtualRouterProvider/src/main/java/org/zstack/network/service/virtualrouter/VirtualRouterManagerImpl.java +++ b/plugin/virtualRouterProvider/src/main/java/org/zstack/network/service/virtualrouter/VirtualRouterManagerImpl.java @@ -20,6 +20,7 @@ import org.zstack.core.thread.ChainTask; import org.zstack.core.thread.SyncTaskChain; import org.zstack.core.thread.ThreadFacade; +import org.zstack.core.upgrade.UpgradeGlobalConfig; import org.zstack.core.workflow.FlowChainBuilder; import org.zstack.header.AbstractService; import org.zstack.header.apimediator.ApiMessageInterceptionException; @@ -2254,6 +2255,11 @@ private void handle(CheckVirtualRouterVmVersionMsg cmsg) { return; } + if (UpgradeGlobalConfig.GRAYSCALE_UPGRADE.value(Boolean.class)) { + logger.debug(String.format("skip checking virtual router[uuid:%s] version because grayscale upgrade is enabled", inv.getUuid())); + return; + } + if (vrVo.getStatus() == ApplianceVmStatus.Connecting) { reconenctVirtualRouter(inv.getUuid(), false); return; @@ -2281,6 +2287,11 @@ public void fail(ErrorCode errorCode) { @Override public void managementNodeReady() { + if (UpgradeGlobalConfig.GRAYSCALE_UPGRADE.value(Boolean.class)) { + logger.debug("skip checking virtual router versions on management node ready because grayscale upgrade is enabled"); + return; + } + List vrVos = Q.New(VirtualRouterVmVO.class).list(); for (VirtualRouterVmVO vrVo : vrVos) { CheckVirtualRouterVmVersionMsg msg = new CheckVirtualRouterVmVersionMsg(); diff --git a/plugin/virtualRouterProvider/src/main/java/org/zstack/network/service/virtualrouter/vyos/VyosDeployAgentFlow.java b/plugin/virtualRouterProvider/src/main/java/org/zstack/network/service/virtualrouter/vyos/VyosDeployAgentFlow.java index 163fd4d22d2..a6b8c6386b3 100755 --- a/plugin/virtualRouterProvider/src/main/java/org/zstack/network/service/virtualrouter/vyos/VyosDeployAgentFlow.java +++ b/plugin/virtualRouterProvider/src/main/java/org/zstack/network/service/virtualrouter/vyos/VyosDeployAgentFlow.java @@ -95,8 +95,9 @@ public void run(FlowTrigger trigger, Map data) { } boolean fromApi = Boolean.parseBoolean(String.valueOf(data.get(Params.fromApi.toString()))); + boolean skipGrayscaleUpgradeCheck = Boolean.parseBoolean(String.valueOf(data.get(Params.skipGrayscaleUpgradeCheck.toString()))); boolean isReconnect = Boolean.parseBoolean(String.valueOf(data.get(Params.isReconnect.toString()))); - if (!fromApi && upgradeChecker.skipInnerDeployOrInitOnCurrentAgent(vrUuid)) { + if (!fromApi && !skipGrayscaleUpgradeCheck && upgradeChecker.skipInnerDeployOrInitOnCurrentAgent(vrUuid)) { trigger.next(); return; } diff --git a/plugin/vxlan/src/main/java/org/zstack/network/l2/vxlan/vxlanNetworkPool/KVMRealizeL2VxlanNetworkBackend.java b/plugin/vxlan/src/main/java/org/zstack/network/l2/vxlan/vxlanNetworkPool/KVMRealizeL2VxlanNetworkBackend.java index 293e078c4a9..43c4ddef021 100755 --- a/plugin/vxlan/src/main/java/org/zstack/network/l2/vxlan/vxlanNetworkPool/KVMRealizeL2VxlanNetworkBackend.java +++ b/plugin/vxlan/src/main/java/org/zstack/network/l2/vxlan/vxlanNetworkPool/KVMRealizeL2VxlanNetworkBackend.java @@ -461,6 +461,11 @@ private Integer getVirtualNetworkId(String l2NetworkUuid) { @Override public void instantiateResourceOnAttachingNic(VmInstanceSpec spec, L3NetworkInventory l3, Completion completion) { + if (!KVMConstant.KVM_HYPERVISOR_TYPE.equals(spec.getDestHost().getHypervisorType())) { + completion.success(); + return; + } + L2NetworkVO vo = Q.New(L2NetworkVO.class).eq(L2NetworkVO_.uuid, l3.getL2NetworkUuid()).find(); if (!vo.getType().equals(VxlanNetworkConstant.VXLAN_NETWORK_TYPE)) { completion.success(); diff --git a/plugin/vxlan/src/main/java/org/zstack/network/l2/vxlan/vxlanNetworkPool/VxlanNetworkCheckerImpl.java b/plugin/vxlan/src/main/java/org/zstack/network/l2/vxlan/vxlanNetworkPool/VxlanNetworkCheckerImpl.java index d3a46ed8d78..9f9e9848714 100644 --- a/plugin/vxlan/src/main/java/org/zstack/network/l2/vxlan/vxlanNetworkPool/VxlanNetworkCheckerImpl.java +++ b/plugin/vxlan/src/main/java/org/zstack/network/l2/vxlan/vxlanNetworkPool/VxlanNetworkCheckerImpl.java @@ -38,7 +38,7 @@ public APIMessage intercept(APIMessage msg) throws ApiMessageInterceptionExcepti } private void validate(APIChangeL2NetworkVlanIdMsg msg) { - if (!msg.getType().equals(VxlanNetworkConstant.VXLAN_NETWORK_TYPE)){ + if (!VxlanNetworkConstant.VXLAN_NETWORK_TYPE.equals(msg.getType())){ return; } if (!NetworkUtils.isValidVni(msg.getVlan())) { diff --git a/plugin/xinfini/src/main/java/org/zstack/xinfini/XInfiniApiHelper.java b/plugin/xinfini/src/main/java/org/zstack/xinfini/XInfiniApiHelper.java index e11196568ca..b67bfa0da7e 100644 --- a/plugin/xinfini/src/main/java/org/zstack/xinfini/XInfiniApiHelper.java +++ b/plugin/xinfini/src/main/java/org/zstack/xinfini/XInfiniApiHelper.java @@ -523,6 +523,14 @@ public void deleteBdcBdev(int bdevId, int bdcId) { } else { retryUtilResourceDeleted(gReq, GetBdcBdevResponse.class); } + + // the polling above intentionally swallows timeout, so verify the bdev is really gone: + // a bdev that is still attached means the old client keeps holding the volume + if (!call(gReq, GetBdcBdevResponse.class).resourceIsDeleted()) { + throw new OperationFailureException(operr(ORG_ZSTACK_XINFINI_10004, + "bdev[id:%s] still exists after deletion polling on bdc[id:%s], " + + "the old storage client may still hold the volume", bdevId, bdcId)); + } } public VolumeModule rollbackSnapshot(int volId, int snapId) { diff --git a/plugin/xinfini/src/main/java/org/zstack/xinfini/XInfiniStorageController.java b/plugin/xinfini/src/main/java/org/zstack/xinfini/XInfiniStorageController.java index 0626b00ba7a..c9efd282c05 100644 --- a/plugin/xinfini/src/main/java/org/zstack/xinfini/XInfiniStorageController.java +++ b/plugin/xinfini/src/main/java/org/zstack/xinfini/XInfiniStorageController.java @@ -206,18 +206,25 @@ public synchronized ActiveVolumeTO activeIscsiVolume(String clientIp, String cli public void deactivate(String installPath, String protocol, HostInventory h, Completion comp) { logger.debug(String.format("deactivating volume[path: %s, protocol:%s] on host[uuid:%s, ip:%s]", installPath, protocol, h.getUuid(), h.getManagementIp())); - if (VolumeProtocol.Vhost.toString().equals(protocol)) { - deactivateVhost(installPath, h); - comp.success(); - return; - } else if (VolumeProtocol.iSCSI.toString().equals(protocol)) { - // iscsi target is shared by all hosts, we cannot control one volume on one host for now. - deactivateIscsi(installPath, h); - comp.success(); + // a deactivate failure must be reported through comp.fail() rather than swallowed, + // otherwise the caller cannot tell the old storage client is still holding the volume + try { + if (VolumeProtocol.Vhost.toString().equals(protocol)) { + deactivateVhost(installPath, h); + } else if (VolumeProtocol.iSCSI.toString().equals(protocol)) { + // iscsi target is shared by all hosts, we cannot control one volume on one host for now. + deactivateIscsi(installPath, h); + } else { + comp.fail(operr(ORG_ZSTACK_XINFINI_10013, "not supported protocol[%s] for deactivate", protocol)); + return; + } + } catch (Exception e) { + comp.fail(operr("failed to deactivate volume[path:%s, protocol:%s] on host[uuid:%s, ip:%s]: %s", + installPath, protocol, h.getUuid(), h.getManagementIp(), e.getMessage())); return; } - comp.fail(operr(ORG_ZSTACK_XINFINI_10013, "not supported protocol[%s] for deactivate", protocol)); + comp.success(); } private void deactivateIscsi(String installPath, HostInventory h) { @@ -259,7 +266,8 @@ private void deactivateVhost(String installPath, HostInventory h) { return; } - retry(() -> apiHelper.deleteBdcBdev(bdev.getSpec().getId(), bdc.getSpec().getId())); + // use the rethrowing retry: a bdev that cannot be removed must surface as a failure + retryOrThrow(() -> apiHelper.deleteBdcBdev(bdev.getSpec().getId(), bdc.getSpec().getId())); } @Override @@ -275,9 +283,10 @@ public void deactivate(String installPath, String protocol, ActiveVolumeClient c } @Override - public void blacklist(String installPath, String protocol, HostInventory h, Completion comp) { - // todo - comp.success(); + public void blacklist(String installPath, String protocol, HostInventory h) { + throw new OperationFailureException(operr("xinfini does not support volume path isolation yet, " + + "abort starting VM on host[uuid:%s, ip:%s] to prevent split-brain on volume[path:%s, protocol:%s]", + h.getUuid(), h.getManagementIp(), installPath, protocol)); } @Override @@ -1097,18 +1106,35 @@ private void retry(Runnable r) { retry(r, 3); } - private void retry(Runnable r, int retry) { - while (retry-- > 0) { + // retry is the swallowing variant of retryOrThrow: give up silently after the last attempt + try { + retryOrThrow(r, retry); + } catch (RuntimeException ignored) { + } + } + + private void retryOrThrow(Runnable r) { + retryOrThrow(r, 3); + } + + private void retryOrThrow(Runnable r, int retry) { + RuntimeException lastError = null; + for (int i = 0; i < retry; i++) { try { r.run(); return; - } catch (Exception e) { + } catch (RuntimeException e) { + lastError = e; logger.warn("runnable failed, try ", e); try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException ignore) {} } } + + if (lastError != null) { + throw lastError; + } } } 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 0d71b507b14..1a7342fc4a4 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 @@ -156,8 +156,7 @@ public void deactivate(String installPath, String protocol, ActiveVolumeClient c } @Override - public void blacklist(String installPath, String protocol, HostInventory h, Completion comp) { - comp.success(); + public void blacklist(String installPath, String protocol, HostInventory h) { } @Override diff --git a/rest/src/main/resources/scripts/GoApiTemplate.groovy b/rest/src/main/resources/scripts/GoApiTemplate.groovy index fefe945ba3c..eb207e67ac4 100644 --- a/rest/src/main/resources/scripts/GoApiTemplate.groovy +++ b/rest/src/main/resources/scripts/GoApiTemplate.groovy @@ -2,6 +2,8 @@ package scripts import org.zstack.header.query.APIQueryMessage import org.zstack.header.rest.RestRequest +import org.zstack.header.rest.SDK +import org.zstack.header.rest.RestResponse import org.zstack.rest.sdk.SdkFile import org.zstack.rest.sdk.SdkTemplate import org.zstack.utils.Utils @@ -20,6 +22,7 @@ class GoApiTemplate implements SdkTemplate { private RestRequest at private String path private Class responseClass + private String allTo; private String replyName private SdkTemplate inventoryGenerator @@ -54,6 +57,9 @@ class GoApiTemplate implements SdkTemplate { // Track APIs that should be skipped during generation private static Set skippedApis = new HashSet<>() + // Flag to indicate if the template was successfully initialized + private boolean valid = false + GoApiTemplate(Class apiMsgClass, SdkTemplate inventoryGenerator) { try { apiMsgClazz = apiMsgClass @@ -85,6 +91,12 @@ class GoApiTemplate implements SdkTemplate { } } + allTo = "" + if (responseClass != null) { + RestResponse restResponse = responseClass.getAnnotation(RestResponse) + allTo = restResponse != null ? restResponse.allTo() : "" + } + if (responseClass != null) { replyName = responseClass.simpleName.replaceAll('^API', '').replaceAll('Reply$', '').replaceAll('Event$', '') } else { @@ -103,6 +115,7 @@ class GoApiTemplate implements SdkTemplate { queryInventoryClass = findInventoryClass() logger.warn("[GoSDK] Processing API: " + clzName + " -> action=" + actionType + ", resource=" + resourceName + ", response=" + responseClass?.simpleName) + valid = true } catch (Throwable e) { logger.error("[GoSDK] CRITICAL ERROR constructing GoApiTemplate for ${apiMsgClass.name}: ${e.class.name}: ${e.message}", e) throw e @@ -113,6 +126,14 @@ class GoApiTemplate implements SdkTemplate { return at } + /** + * Check if the template was successfully initialized. + * Templates without @RestRequest annotation are invalid. + */ + boolean isValid() { + return valid + } + String getActionType() { return actionType } @@ -184,6 +205,21 @@ class GoApiTemplate implements SdkTemplate { logger.warn("[GoSDK] Registered ${mappings.size()} LongJob mappings") } + /** + * Reset all static state for clean re-generation. + * Should be called at the beginning of generate() or before each SDK generation run. + */ + static void reset() { + generatedParamFiles.clear() + generatedActionFiles.clear() + generatedViewFiles.clear() + knownInventoryClasses = null + groupedApiNames.clear() + longJobMappings.clear() + skippedApis.clear() + logger.warn("[GoSDK] Reset all static state") + } + /** * Check if current API supports async operation */ @@ -373,6 +409,13 @@ class GoApiTemplate implements SdkTemplate { return "v1/" + path } + private String getApiOptPath(String optPath) { + if (optPath.startsWith("/")) { + return "v1" + optPath + } + return "v1/" + optPath + } + List generate() { return [] } @@ -431,8 +474,12 @@ class GoApiTemplate implements SdkTemplate { // First check HTTP method from annotation, then fall back to actionType-based logic if (httpMethod == "POST") { - // POST operations (Create/Add) - builder.append(generateCreateMethod(apiPath, viewStructName, false, responseStructName, goInventoryFieldName)) + // POST operations: Delete-via-POST needs special handling + if (actionType == "Delete") { + builder.append(generateDeleteViaPostMethod(apiPath, responseStructName)) + } else { + builder.append(generateCreateMethod(apiPath, viewStructName, false, responseStructName, goInventoryFieldName)) + } } else if (httpMethod == "GET") { // GET operations (Get/Query) builder.append(generateGetMethod(apiPath, viewStructName, unwrapForGet, responseStructName, goInventoryFieldName)) @@ -505,56 +552,55 @@ class GoApiTemplate implements SdkTemplate { private String generateCreateMethod(String apiPath, String viewStructName, boolean unwrap, String responseStructName, String fieldName) { boolean hasParams = hasApiParams() - - if (!hasParams) { - // No params: don't require user to pass params, use empty map internally - if (unwrap) { - return """func (cli *ZSClient) ${clzName}() (*view.${viewStructName}, error) { -\tvar resp view.${responseStructName} -\tif err := cli.Post("${apiPath}", map[string]interface{}{}, &resp); err != nil { -\t\treturn nil, err -\t} -\treturn &resp.${fieldName}, nil -} -""" - } else { - return """func (cli *ZSClient) ${clzName}() (*view.${viewStructName}, error) { -\tresp := view.${viewStructName}{} -\tif err := cli.Post("${apiPath}", map[string]interface{}{}, &resp); err != nil { -\t\treturn nil, err -\t} -\treturn &resp, nil -} -""" - } + def placeholders = extractUrlPlaceholders(apiPath) + String pathExpr = placeholders.isEmpty() ? "\"${apiPath}\"" : buildFullPath(placeholders) + String placeholderParams = placeholders.collect { "${toSafeGoParamName(it)} string" }.join(", ") + String methodParams = "ctx context.Context" + if (!placeholderParams.isEmpty()) { + methodParams = "${methodParams}, ${placeholderParams}" } - - // Has params: require user to pass params + if (hasParams) { + methodParams = "${methodParams}, params param.${clzName}Param" + } + + String bodyExpr = hasParams ? "params" : "map[string]interface{}{}" + String responseKey = getPostResponseKey(viewStructName, responseStructName) + + String retViewStructName = viewStructName + String respDecl + String returnStmt if (unwrap) { - return """func (cli *ZSClient) ${clzName}(params param.${clzName}Param) (*view.${viewStructName}, error) { -\tvar resp view.${responseStructName} -\tif err := cli.Post("${apiPath}", params, &resp); err != nil { -\t\treturn nil, err -\t} -\treturn &resp.${fieldName}, nil -} -""" + respDecl = "var resp view.${responseStructName}" + returnStmt = "return &resp.${fieldName}, nil" } else { - return """func (cli *ZSClient) ${clzName}(params param.${clzName}Param) (*view.${viewStructName}, error) { -\tresp := view.${viewStructName}{} -\tif err := cli.Post("${apiPath}", params, &resp); err != nil { + respDecl = "resp := view.${viewStructName}{}" + returnStmt = "return &resp, nil" + } + + return """func (cli *ZSClient) ${clzName}(${methodParams}) (*view.${retViewStructName}, error) { +\t${respDecl} +\tif err := cli.PostWithRespKey(ctx, ${pathExpr}, "${responseKey}", ${bodyExpr}, &resp); err != nil { \t\treturn nil, err \t} -\treturn &resp, nil +\t${returnStmt} } """ + } + + private String getPostResponseKey(String viewStructName, String responseStructName) { + if (allTo != null && !allTo.isEmpty()) { + return allTo + } + if (inventoryFieldName != null && !inventoryFieldName.isEmpty() && viewStructName != responseStructName) { + return inventoryFieldName } + return "" } private String generateQueryMethod(String apiPath, String viewStructName) { - return """func (cli *ZSClient) ${clzName}(params *param.QueryParam) ([]view.${viewStructName}, error) { + return """func (cli *ZSClient) ${clzName}(ctx context.Context, params *param.QueryParam) ([]view.${viewStructName}, error) { \tvar resp []view.${viewStructName} -\treturn resp, cli.List("${apiPath}", params, &resp) +\treturn resp, cli.List(ctx, "${apiPath}", params, &resp) } """ } @@ -566,7 +612,7 @@ class GoApiTemplate implements SdkTemplate { private String generatePageMethod(String apiPath, String viewStructName) { String pageMethodName = clzName.replaceFirst('^Query', 'Page') String varName = resourceName.substring(0, 1).toLowerCase() + resourceName.substring(1) - if (varName.endsWith("y")) { + if (varName.endsWith("y") && varName.length() > 1 && !"aeiou".contains(varName.charAt(varName.length() - 2).toString())) { varName = varName.substring(0, varName.length() - 1) + "ies" } else if (!varName.endsWith("s")) { varName = varName + "s" @@ -574,9 +620,9 @@ class GoApiTemplate implements SdkTemplate { return """ // ${pageMethodName} Pagination -func (cli *ZSClient) ${pageMethodName}(params *param.QueryParam) ([]view.${viewStructName}, int, error) { +func (cli *ZSClient) ${pageMethodName}(ctx context.Context, params *param.QueryParam) ([]view.${viewStructName}, int, error) { \tvar ${varName} []view.${viewStructName} -\ttotal, err := cli.Page("${apiPath}", params, &${varName}) +\ttotal, err := cli.Page(ctx, "${apiPath}", params, &${varName}) \treturn ${varName}, total, err } """ @@ -602,9 +648,9 @@ func (cli *ZSClient) ${pageMethodName}(params *param.QueryParam) ([]view.${viewS String spec = buildSpecPath(remainingPlaceholders) return """ -func (cli *ZSClient) ${getMethodName}(${params}) (*view.${viewStructName}, error) { +func (cli *ZSClient) ${getMethodName}(ctx context.Context, ${params}) (*view.${viewStructName}, error) { \tvar resp view.${viewStructName} -\terr := cli.GetWithSpec("${cleanPath}", ${firstParam}, ${spec}, "", nil, &resp) +\terr := cli.GetWithSpec(ctx, "${cleanPath}", ${firstParam}, ${spec}, "${allTo}", nil, &resp) \tif err != nil { \t\treturn nil, err \t} @@ -615,9 +661,9 @@ func (cli *ZSClient) ${getMethodName}(${params}) (*view.${viewStructName}, error // Standard case: single uuid parameter return """ -func (cli *ZSClient) ${getMethodName}(uuid string) (*view.${viewStructName}, error) { +func (cli *ZSClient) ${getMethodName}(ctx context.Context, uuid string) (*view.${viewStructName}, error) { \tvar resp view.${viewStructName} -\tif err := cli.Get("${cleanPath}", uuid, nil, &resp); err != nil { +\tif err := cli.Get(ctx, "${cleanPath}", uuid, nil, &resp); err != nil { \t\treturn nil, err \t} \treturn &resp, nil @@ -639,9 +685,9 @@ func (cli *ZSClient) ${getMethodName}(uuid string) (*view.${viewStructName}, err if (placeholders.size() == 0) { // No placeholder: no uuid parameter needed // Use GetWithRespKey to extract the inventory field - return """func (cli *ZSClient) ${clzName}() (*view.${viewStructName}, error) { + return """func (cli *ZSClient) ${clzName}(ctx context.Context) (*view.${viewStructName}, error) { \tvar resp view.${responseStructName} -\tif err := cli.GetWithRespKey("${cleanPath}", "", "inventory", nil, &resp); err != nil { +\tif err := cli.GetWithRespKey(ctx, "${cleanPath}", "", "inventory", nil, &resp); err != nil { \t\treturn nil, err \t} \treturn &resp.${fieldName}, nil @@ -649,9 +695,9 @@ func (cli *ZSClient) ${getMethodName}(uuid string) (*view.${viewStructName}, err """ } else { // Single placeholder: use GetWithRespKey with uuid to extract inventory - return """func (cli *ZSClient) ${clzName}(uuid string) (*view.${viewStructName}, error) { + return """func (cli *ZSClient) ${clzName}(ctx context.Context, uuid string) (*view.${viewStructName}, error) { \tvar resp view.${responseStructName} -\tif err := cli.GetWithRespKey("${cleanPath}", uuid, "inventory", nil, &resp); err != nil { +\tif err := cli.GetWithRespKey(ctx, "${cleanPath}", uuid, "inventory", nil, &resp); err != nil { \t\treturn nil, err \t} \treturn &resp.${fieldName}, nil @@ -666,9 +712,9 @@ func (cli *ZSClient) ${getMethodName}(uuid string) (*view.${viewStructName}, err String params = placeholders.collect { "${toSafeGoParamName(it)} string" }.join(", ") String spec = buildSpecPath(remainingPlaceholders) - return """func (cli *ZSClient) ${clzName}(${params}) (*view.${viewStructName}, error) { + return """func (cli *ZSClient) ${clzName}(ctx context.Context, ${params}) (*view.${viewStructName}, error) { \tvar resp view.${responseStructName} -\terr := cli.GetWithSpec("${cleanPath}", ${firstParam}, ${spec}, "", nil, &resp) +\terr := cli.GetWithSpec(ctx, "${cleanPath}", ${firstParam}, ${spec}, "", nil, &resp) \tif err != nil { \t\treturn nil, err \t} @@ -677,14 +723,18 @@ func (cli *ZSClient) ${getMethodName}(uuid string) (*view.${viewStructName}, err """ } } else { + // Not unwrapping: use responseStructName when it differs from viewStructName + // This handles cases like GetSSOClient where response is {"inventories": [...]} + // and the response wrapper (GetSSOClientView) must be used instead of the element type (SSOClientInventoryView) + String actualViewStruct = (viewStructName != responseStructName) ? responseStructName : viewStructName if (!useSpec) { // Check if there are any placeholders if (placeholders.size() == 0) { // No placeholder: no uuid parameter needed // Use GetWithRespKey with empty responseKey to parse whole response - return """func (cli *ZSClient) ${clzName}() (*view.${viewStructName}, error) { -\tvar resp view.${viewStructName} -\tif err := cli.GetWithRespKey("${cleanPath}", "", "", nil, &resp); err != nil { + return """func (cli *ZSClient) ${clzName}(ctx context.Context) (*view.${actualViewStruct}, error) { +\tvar resp view.${actualViewStruct} +\tif err := cli.GetWithRespKey(ctx, "${cleanPath}", "", "", nil, &resp); err != nil { \t\treturn nil, err \t} \treturn &resp, nil @@ -692,9 +742,9 @@ func (cli *ZSClient) ${getMethodName}(uuid string) (*view.${viewStructName}, err """ } else { // Single placeholder: use GetWithRespKey with uuid - return """func (cli *ZSClient) ${clzName}(uuid string) (*view.${viewStructName}, error) { -\tvar resp view.${viewStructName} -\tif err := cli.GetWithRespKey("${cleanPath}", uuid, "", nil, &resp); err != nil { + return """func (cli *ZSClient) ${clzName}(ctx context.Context, uuid string) (*view.${actualViewStruct}, error) { +\tvar resp view.${actualViewStruct} +\tif err := cli.GetWithRespKey(ctx, "${cleanPath}", uuid, "", nil, &resp); err != nil { \t\treturn nil, err \t} \treturn &resp, nil @@ -709,9 +759,9 @@ func (cli *ZSClient) ${getMethodName}(uuid string) (*view.${viewStructName}, err String params = placeholders.collect { "${toSafeGoParamName(it)} string" }.join(", ") String spec = buildSpecPath(remainingPlaceholders) - return """func (cli *ZSClient) ${clzName}(${params}) (*view.${viewStructName}, error) { -\tvar resp view.${viewStructName} -\terr := cli.GetWithSpec("${cleanPath}", ${firstParam}, ${spec}, "", nil, &resp) + return """func (cli *ZSClient) ${clzName}(ctx context.Context, ${params}) (*view.${actualViewStruct}, error) { +\tvar resp view.${actualViewStruct} +\terr := cli.GetWithSpec(ctx, "${cleanPath}", ${firstParam}, ${spec}, "${allTo}", nil, &resp) \tif err != nil { \t\treturn nil, err \t} @@ -756,9 +806,9 @@ func (cli *ZSClient) ${getMethodName}(uuid string) (*view.${viewStructName}, err String paramName = toSafeGoParamName(placeholders[0]) if (isActionApi) { // Action APIs wrap params.Params inside a map - return """func (cli *ZSClient) ${clzName}(${paramName} string, params param.${clzName}Param) (*view.${viewStructName}, error) { + return """func (cli *ZSClient) ${clzName}(ctx context.Context, ${paramName} string, params param.${clzName}Param) (*view.${viewStructName}, error) { \tvar resp view.${responseStructName} -\tif err := cli.Put("${cleanPath}", ${paramName}, map[string]interface{}{ +\tif err := cli.Put(ctx, "${cleanPath}", ${paramName}, map[string]interface{}{ \t\t"${actionKey}": params.Params, \t}, &resp); err != nil { \t\treturn nil, err @@ -767,9 +817,9 @@ func (cli *ZSClient) ${getMethodName}(uuid string) (*view.${viewStructName}, err } """ } else { - return """func (cli *ZSClient) ${clzName}(${paramName} string, params param.${clzName}Param) (*view.${viewStructName}, error) { + return """func (cli *ZSClient) ${clzName}(ctx context.Context, ${paramName} string, params param.${clzName}Param) (*view.${viewStructName}, error) { \tvar resp view.${responseStructName} -\tif err := cli.Put("${cleanPath}", ${paramName}, params, &resp); err != nil { +\tif err := cli.Put(ctx, "${cleanPath}", ${paramName}, params, &resp); err != nil { \t\treturn nil, err \t} \treturn &resp.${fieldName}, nil @@ -781,9 +831,9 @@ func (cli *ZSClient) ${getMethodName}(uuid string) (*view.${viewStructName}, err if (!hasParams) { // No params: don't require user input if (isActionApi) { - return """func (cli *ZSClient) ${clzName}() (*view.${viewStructName}, error) { + return """func (cli *ZSClient) ${clzName}(ctx context.Context) (*view.${viewStructName}, error) { \tvar resp view.${responseStructName} -\tif err := cli.Put("${cleanPath}", "", map[string]interface{}{ +\tif err := cli.Put(ctx, "${cleanPath}", "", map[string]interface{}{ \t\t"${actionKey}": map[string]interface{}{}, \t}, &resp); err != nil { \t\treturn nil, err @@ -792,9 +842,9 @@ func (cli *ZSClient) ${getMethodName}(uuid string) (*view.${viewStructName}, err } """ } else { - return """func (cli *ZSClient) ${clzName}() (*view.${viewStructName}, error) { + return """func (cli *ZSClient) ${clzName}(ctx context.Context) (*view.${viewStructName}, error) { \tvar resp view.${responseStructName} -\tif err := cli.Put("${cleanPath}", "", map[string]interface{}{}, &resp); err != nil { +\tif err := cli.Put(ctx, "${cleanPath}", "", map[string]interface{}{}, &resp); err != nil { \t\treturn nil, err \t} \treturn &resp.${fieldName}, nil @@ -802,9 +852,9 @@ func (cli *ZSClient) ${getMethodName}(uuid string) (*view.${viewStructName}, err """ } } else if (isActionApi) { - return """func (cli *ZSClient) ${clzName}(params param.${clzName}Param) (*view.${viewStructName}, error) { + return """func (cli *ZSClient) ${clzName}(ctx context.Context, params param.${clzName}Param) (*view.${viewStructName}, error) { \tvar resp view.${responseStructName} -\tif err := cli.Put("${cleanPath}", "", map[string]interface{}{ +\tif err := cli.Put(ctx, "${cleanPath}", "", map[string]interface{}{ \t\t"${actionKey}": params.Params, \t}, &resp); err != nil { \t\treturn nil, err @@ -813,9 +863,9 @@ func (cli *ZSClient) ${getMethodName}(uuid string) (*view.${viewStructName}, err } """ } else { - return """func (cli *ZSClient) ${clzName}(uuid string, params param.${clzName}Param) (*view.${viewStructName}, error) { + return """func (cli *ZSClient) ${clzName}(ctx context.Context, uuid string, params param.${clzName}Param) (*view.${viewStructName}, error) { \tvar resp view.${responseStructName} -\tif err := cli.Put("${cleanPath}", uuid, params, &resp); err != nil { +\tif err := cli.Put(ctx, "${cleanPath}", uuid, params, &resp); err != nil { \t\treturn nil, err \t} \treturn &resp.${fieldName}, nil @@ -831,9 +881,9 @@ func (cli *ZSClient) ${getMethodName}(uuid string) (*view.${viewStructName}, err String params = placeholders.collect { "${toSafeGoParamName(it)} string" }.join(", ") String spec = buildSpecPath(remainingPlaceholders) - return """func (cli *ZSClient) ${clzName}(${params}, params param.${clzName}Param) (*view.${viewStructName}, error) { + return """func (cli *ZSClient) ${clzName}(ctx context.Context, ${params}, params param.${clzName}Param) (*view.${viewStructName}, error) { \tvar resp view.${responseStructName} -\terr := cli.PutWithSpec("${cleanPath}", ${firstParam}, ${spec}, "", params, &resp) +\terr := cli.PutWithSpec(ctx, "${cleanPath}", ${firstParam}, ${spec}, "", params, &resp) \tif err != nil { \t\treturn nil, err \t} @@ -850,9 +900,9 @@ func (cli *ZSClient) ${getMethodName}(uuid string) (*view.${viewStructName}, err String paramName = toSafeGoParamName(placeholders[0]) if (isActionApi) { // Action APIs wrap params.Params inside a map - return """func (cli *ZSClient) ${clzName}(${paramName} string, params param.${clzName}Param) (*view.${viewStructName}, error) { + return """func (cli *ZSClient) ${clzName}(ctx context.Context, ${paramName} string, params param.${clzName}Param) (*view.${viewStructName}, error) { \tresp := view.${viewStructName}{} -\tif err := cli.PutWithRespKey("${cleanPath}", ${paramName}, "", map[string]interface{}{ +\tif err := cli.PutWithRespKey(ctx, "${cleanPath}", ${paramName}, "", map[string]interface{}{ \t\t"${actionKey}": params.Params, \t}, &resp); err != nil { \t\treturn nil, err @@ -861,9 +911,9 @@ func (cli *ZSClient) ${getMethodName}(uuid string) (*view.${viewStructName}, err } """ } else { - return """func (cli *ZSClient) ${clzName}(${paramName} string, params param.${clzName}Param) (*view.${viewStructName}, error) { + return """func (cli *ZSClient) ${clzName}(ctx context.Context, ${paramName} string, params param.${clzName}Param) (*view.${viewStructName}, error) { \tresp := view.${viewStructName}{} -\tif err := cli.PutWithRespKey("${cleanPath}", ${paramName}, "", params, &resp); err != nil { +\tif err := cli.PutWithRespKey(ctx, "${cleanPath}", ${paramName}, "", params, &resp); err != nil { \t\treturn nil, err \t} \treturn &resp, nil @@ -875,9 +925,9 @@ func (cli *ZSClient) ${getMethodName}(uuid string) (*view.${viewStructName}, err if (!hasParams) { // No params: don't require user input if (isActionApi) { - return """func (cli *ZSClient) ${clzName}() (*view.${viewStructName}, error) { + return """func (cli *ZSClient) ${clzName}(ctx context.Context) (*view.${viewStructName}, error) { \tresp := view.${viewStructName}{} -\tif err := cli.PutWithRespKey("${cleanPath}", "", "", map[string]interface{}{ +\tif err := cli.PutWithRespKey(ctx, "${cleanPath}", "", "", map[string]interface{}{ \t\t"${actionKey}": map[string]interface{}{}, \t}, &resp); err != nil { \t\treturn nil, err @@ -886,9 +936,9 @@ func (cli *ZSClient) ${getMethodName}(uuid string) (*view.${viewStructName}, err } """ } else { - return """func (cli *ZSClient) ${clzName}() (*view.${viewStructName}, error) { + return """func (cli *ZSClient) ${clzName}(ctx context.Context) (*view.${viewStructName}, error) { \tresp := view.${viewStructName}{} -\tif err := cli.PutWithRespKey("${cleanPath}", "", "", map[string]interface{}{}, &resp); err != nil { +\tif err := cli.PutWithRespKey(ctx, "${cleanPath}", "", "", map[string]interface{}{}, &resp); err != nil { \t\treturn nil, err \t} \treturn &resp, nil @@ -896,9 +946,9 @@ func (cli *ZSClient) ${getMethodName}(uuid string) (*view.${viewStructName}, err """ } } else if (isActionApi) { - return """func (cli *ZSClient) ${clzName}(params param.${clzName}Param) (*view.${viewStructName}, error) { + return """func (cli *ZSClient) ${clzName}(ctx context.Context, params param.${clzName}Param) (*view.${viewStructName}, error) { \tresp := view.${viewStructName}{} -\tif err := cli.PutWithRespKey("${cleanPath}", "", "", map[string]interface{}{ +\tif err := cli.PutWithRespKey(ctx, "${cleanPath}", "", "", map[string]interface{}{ \t\t"${actionKey}": params.Params, \t}, &resp); err != nil { \t\treturn nil, err @@ -907,9 +957,9 @@ func (cli *ZSClient) ${getMethodName}(uuid string) (*view.${viewStructName}, err } """ } else { - return """func (cli *ZSClient) ${clzName}(uuid string, params param.${clzName}Param) (*view.${viewStructName}, error) { + return """func (cli *ZSClient) ${clzName}(ctx context.Context, uuid string, params param.${clzName}Param) (*view.${viewStructName}, error) { \tresp := view.${viewStructName}{} -\tif err := cli.PutWithRespKey("${cleanPath}", uuid, "", params, &resp); err != nil { +\tif err := cli.PutWithRespKey(ctx, "${cleanPath}", uuid, "", params, &resp); err != nil { \t\treturn nil, err \t} \treturn &resp, nil @@ -925,9 +975,9 @@ func (cli *ZSClient) ${getMethodName}(uuid string) (*view.${viewStructName}, err String params = placeholders.collect { "${toSafeGoParamName(it)} string" }.join(", ") String spec = buildSpecPath(remainingPlaceholders) - return """func (cli *ZSClient) ${clzName}(${params}, params param.${clzName}Param) (*view.${viewStructName}, error) { + return """func (cli *ZSClient) ${clzName}(ctx context.Context, ${params}, params param.${clzName}Param) (*view.${viewStructName}, error) { \tresp := view.${viewStructName}{} -\terr := cli.PutWithSpec("${cleanPath}", ${firstParam}, ${spec}, "", params, &resp) +\terr := cli.PutWithSpec(ctx, "${cleanPath}", ${firstParam}, ${spec}, "", params, &resp) \tif err != nil { \t\treturn nil, err \t} @@ -938,6 +988,39 @@ func (cli *ZSClient) ${getMethodName}(uuid string) (*view.${viewStructName}, err } } + /** + * Generate Delete-via-POST method. + * Some Delete APIs use POST instead of DELETE (e.g. APIDeleteSSOClientMsg). + * These return an Event with {"success": true} and no "inventory" key, + * so we must use PostWithRespKey with empty responseKey to avoid "key not found". + * + * Handles URL placeholders (e.g. /cdp-task/{uuid}/data) by extracting them + * as function parameters and building the full path with fmt.Sprintf. + */ + private String generateDeleteViaPostMethod(String apiPath, String responseStructName) { + boolean hasParams = hasApiParams() + def placeholders = extractUrlPlaceholders(apiPath) + String pathExpr = placeholders.isEmpty() ? "\"${removePlaceholders(apiPath)}\"" : buildFullPath(placeholders) + String placeholderParams = placeholders.collect { "${toSafeGoParamName(it)} string" }.join(", ") + String methodParams = "ctx context.Context" + if (!placeholderParams.isEmpty()) { + methodParams = "${methodParams}, ${placeholderParams}" + } + if (hasParams) { + methodParams = "${methodParams}, params param.${clzName}Param" + } + String bodyExpr = hasParams ? "params" : "map[string]interface{}{}" + + return """func (cli *ZSClient) ${clzName}(${methodParams}) (*view.${responseStructName}, error) { +\tresp := view.${responseStructName}{} +\tif err := cli.PostWithRespKey(ctx, ${pathExpr}, "", ${bodyExpr}, &resp); err != nil { +\t\treturn nil, err +\t} +\treturn &resp, nil +} +""" + } + private String generateDeleteMethod(String apiPath) { // Extract URL placeholders def placeholders = extractUrlPlaceholders(apiPath) @@ -948,8 +1031,8 @@ func (cli *ZSClient) ${getMethodName}(uuid string) (*view.${viewStructName}, err if (!useSpec) { // Single or no placeholder: use the standard Delete method - return """func (cli *ZSClient) ${clzName}(uuid string, deleteMode param.DeleteMode) error { -\treturn cli.Delete("${cleanPath}", uuid, string(deleteMode)) + return """func (cli *ZSClient) ${clzName}(ctx context.Context, uuid string, deleteMode param.DeleteMode) error { +\treturn cli.Delete(ctx, "${cleanPath}", uuid, string(deleteMode)) } """ } else { @@ -961,8 +1044,8 @@ func (cli *ZSClient) ${getMethodName}(uuid string) (*view.${viewStructName}, err String spec = buildSpecPath(remainingPlaceholders) String paramsStr = "fmt.Sprintf(\"deleteMode=%s\", deleteMode)" - return """func (cli *ZSClient) ${clzName}(${params}, deleteMode param.DeleteMode) error { -\treturn cli.DeleteWithSpec("${cleanPath}", ${firstParam}, ${spec}, ${paramsStr}, nil) + return """func (cli *ZSClient) ${clzName}(ctx context.Context, ${params}, deleteMode param.DeleteMode) error { +\treturn cli.DeleteWithSpec(ctx, "${cleanPath}", ${firstParam}, ${spec}, ${paramsStr}, nil) } """ } @@ -985,11 +1068,11 @@ func (cli *ZSClient) ${getMethodName}(uuid string) (*view.${viewStructName}, err // Build parameter key, for example expungeImage String paramKey = clzName.substring(0, 1).toLowerCase() + clzName.substring(1) - return """func (cli *ZSClient) ${clzName}(uuid string) error { + return """func (cli *ZSClient) ${clzName}(ctx context.Context, uuid string) error { \tparams := map[string]interface{}{ \t\t"${paramKey}": map[string]interface{}{}, \t} -\treturn cli.Put("${cleanPath}", uuid, params, nil) +\treturn cli.Put(ctx, "${cleanPath}", uuid, params, nil) } """ } @@ -1025,9 +1108,9 @@ func (cli *ZSClient) ${getMethodName}(uuid string) (*view.${viewStructName}, err switch (httpMethod) { case "GET": if (!useSpec) { - return """func (cli *ZSClient) ${clzName}(params param.${clzName}Param) (*view.${viewStructName}, error) { + return """func (cli *ZSClient) ${clzName}(ctx context.Context, params param.${clzName}Param) (*view.${viewStructName}, error) { \tvar resp ${respType} -\tif err := cli.Get("${cleanPath}", "", params, &resp); err != nil { +\tif err := cli.Get(ctx, "${cleanPath}", "", params, &resp); err != nil { \t\treturn nil, err \t} \t${returnStmt} @@ -1036,9 +1119,9 @@ func (cli *ZSClient) ${getMethodName}(uuid string) (*view.${viewStructName}, err } else { String params = placeholders.collect { "${toSafeGoParamName(it)} string" }.join(", ") String pathSpec = buildPathSpec(placeholders) - return """func (cli *ZSClient) ${clzName}(${params}, params param.${clzName}Param) (*view.${viewStructName}, error) { + return """func (cli *ZSClient) ${clzName}(ctx context.Context, ${params}, params param.${clzName}Param) (*view.${viewStructName}, error) { \tvar resp ${respType} -\terr := cli.GetWithSpec("${cleanPath}", ${pathSpec}, "", "", params, &resp) +\terr := cli.GetWithSpec(ctx, "${cleanPath}", ${pathSpec}, "", "${allTo}", params, &resp) \tif err != nil { \t\treturn nil, err \t} @@ -1048,9 +1131,9 @@ func (cli *ZSClient) ${getMethodName}(uuid string) (*view.${viewStructName}, err } case "POST": if (!useSpec) { - return """func (cli *ZSClient) ${clzName}(params param.${clzName}Param) (*view.${viewStructName}, error) { + return """func (cli *ZSClient) ${clzName}(ctx context.Context, params param.${clzName}Param) (*view.${viewStructName}, error) { \t${respDecl} -\tif err := cli.Post("${cleanPath}", params, &resp); err != nil { +\tif err := cli.Post(ctx, "${cleanPath}", params, &resp); err != nil { \t\treturn nil, err \t} \t${returnStmt} @@ -1060,9 +1143,9 @@ func (cli *ZSClient) ${getMethodName}(uuid string) (*view.${viewStructName}, err // POST lacks *WithSpec helpers; build the full URL manually String params = placeholders.collect { "${toSafeGoParamName(it)} string" }.join(", ") String fullPath = buildFullPath(placeholders) - return """func (cli *ZSClient) ${clzName}(${params}, params param.${clzName}Param) (*view.${viewStructName}, error) { + return """func (cli *ZSClient) ${clzName}(ctx context.Context, ${params}, params param.${clzName}Param) (*view.${viewStructName}, error) { \t${respDecl} -\terr := cli.Post(${fullPath}, params, &resp) +\terr := cli.Post(ctx, ${fullPath}, params, &resp) \tif err != nil { \t\treturn nil, err \t} @@ -1087,7 +1170,7 @@ func (cli *ZSClient) ${getMethodName}(uuid string) (*view.${viewStructName}, err """("${cleanPath}", ${paramName}, "", map[string]interface{}{ \t\t"${actionKey}": map[string]interface{}{}, \t}, &resp)""" - return """func (cli *ZSClient) ${clzName}(${paramName} string) (*view.${viewStructName}, error) { + return """func (cli *ZSClient) ${clzName}(ctx context.Context, ${paramName} string) (*view.${viewStructName}, error) { \t${respDecl} \tif err := ${putMethod}${putArgs}; err != nil { \t\treturn nil, err @@ -1100,7 +1183,7 @@ func (cli *ZSClient) ${getMethodName}(uuid string) (*view.${viewStructName}, err String putArgs = unwrap ? """("${cleanPath}", ${paramName}, map[string]interface{}{}, &resp)""" : """("${cleanPath}", ${paramName}, "", map[string]interface{}{}, &resp)""" - return """func (cli *ZSClient) ${clzName}(${paramName} string) (*view.${viewStructName}, error) { + return """func (cli *ZSClient) ${clzName}(ctx context.Context, ${paramName} string) (*view.${viewStructName}, error) { \t${respDecl} \tif err := ${putMethod}${putArgs}; err != nil { \t\treturn nil, err @@ -1119,7 +1202,7 @@ func (cli *ZSClient) ${getMethodName}(uuid string) (*view.${viewStructName}, err """("${cleanPath}", ${paramName}, "", map[string]interface{}{ \t\t"${actionKey}": params.Params, \t}, &resp)""" - return """func (cli *ZSClient) ${clzName}(${paramName} string, params param.${clzName}Param) (*view.${viewStructName}, error) { + return """func (cli *ZSClient) ${clzName}(ctx context.Context, ${paramName} string, params param.${clzName}Param) (*view.${viewStructName}, error) { \t${respDecl} \tif err := ${putMethod}${putArgs}; err != nil { \t\treturn nil, err @@ -1132,7 +1215,7 @@ func (cli *ZSClient) ${getMethodName}(uuid string) (*view.${viewStructName}, err String putArgs = unwrap ? """("${cleanPath}", ${paramName}, params, &resp)""" : """("${cleanPath}", ${paramName}, "", params, &resp)""" - return """func (cli *ZSClient) ${clzName}(${paramName} string, params param.${clzName}Param) (*view.${viewStructName}, error) { + return """func (cli *ZSClient) ${clzName}(ctx context.Context, ${paramName} string, params param.${clzName}Param) (*view.${viewStructName}, error) { \t${respDecl} \tif err := ${putMethod}${putArgs}; err != nil { \t\treturn nil, err @@ -1154,7 +1237,7 @@ func (cli *ZSClient) ${getMethodName}(uuid string) (*view.${viewStructName}, err """("${cleanPath}", "", "", map[string]interface{}{ \t\t"${actionKey}": map[string]interface{}{}, \t}, &resp)""" - return """func (cli *ZSClient) ${clzName}() (*view.${viewStructName}, error) { + return """func (cli *ZSClient) ${clzName}(ctx context.Context) (*view.${viewStructName}, error) { \t${respDecl} \tif err := ${putMethod}${putArgs}; err != nil { \t\treturn nil, err @@ -1167,7 +1250,7 @@ func (cli *ZSClient) ${getMethodName}(uuid string) (*view.${viewStructName}, err String putArgs = unwrap ? """("${cleanPath}", "", map[string]interface{}{}, &resp)""" : """("${cleanPath}", "", "", map[string]interface{}{}, &resp)""" - return """func (cli *ZSClient) ${clzName}() (*view.${viewStructName}, error) { + return """func (cli *ZSClient) ${clzName}(ctx context.Context) (*view.${viewStructName}, error) { \t${respDecl} \tif err := ${putMethod}${putArgs}; err != nil { \t\treturn nil, err @@ -1185,7 +1268,7 @@ func (cli *ZSClient) ${getMethodName}(uuid string) (*view.${viewStructName}, err """("${cleanPath}", "", "", map[string]interface{}{ \t\t"${actionKey}": params.Params, \t}, &resp)""" - return """func (cli *ZSClient) ${clzName}(params param.${clzName}Param) (*view.${viewStructName}, error) { + return """func (cli *ZSClient) ${clzName}(ctx context.Context, params param.${clzName}Param) (*view.${viewStructName}, error) { \t${respDecl} \tif err := ${putMethod}${putArgs}; err != nil { \t\treturn nil, err @@ -1198,7 +1281,7 @@ func (cli *ZSClient) ${getMethodName}(uuid string) (*view.${viewStructName}, err String putArgs = unwrap ? """("${cleanPath}", uuid, params, &resp)""" : """("${cleanPath}", uuid, "", params, &resp)""" - return """func (cli *ZSClient) ${clzName}(uuid string, params param.${clzName}Param) (*view.${viewStructName}, error) { + return """func (cli *ZSClient) ${clzName}(ctx context.Context, uuid string, params param.${clzName}Param) (*view.${viewStructName}, error) { \t${respDecl} \tif err := ${putMethod}${putArgs}; err != nil { \t\treturn nil, err @@ -1215,9 +1298,9 @@ func (cli *ZSClient) ${getMethodName}(uuid string) (*view.${viewStructName}, err String params = placeholders.collect { "${toSafeGoParamName(it)} string" }.join(", ") String spec = buildSpecPath(remainingPlaceholders) - return """func (cli *ZSClient) ${clzName}(${params}, params param.${clzName}Param) (*view.${viewStructName}, error) { + return """func (cli *ZSClient) ${clzName}(ctx context.Context, ${params}, params param.${clzName}Param) (*view.${viewStructName}, error) { \t${respDecl} -\terr := cli.PutWithSpec("${cleanPath}", ${firstParam}, ${spec}, "", params, &resp) +\terr := cli.PutWithSpec(ctx, "${cleanPath}", ${firstParam}, ${spec}, "", params, &resp) \tif err != nil { \t\treturn nil, err \t} @@ -1227,8 +1310,8 @@ func (cli *ZSClient) ${getMethodName}(uuid string) (*view.${viewStructName}, err } case "DELETE": if (!useSpec) { - return """func (cli *ZSClient) ${clzName}(uuid string, deleteMode param.DeleteMode) error { -\treturn cli.Delete("${cleanPath}", uuid, string(deleteMode)) + return """func (cli *ZSClient) ${clzName}(ctx context.Context, uuid string, deleteMode param.DeleteMode) error { +\treturn cli.Delete(ctx, "${cleanPath}", uuid, string(deleteMode)) } """ } else { @@ -1239,16 +1322,16 @@ func (cli *ZSClient) ${getMethodName}(uuid string) (*view.${viewStructName}, err String spec = buildSpecPath(remainingPlaceholders) String paramsStr = "fmt.Sprintf(\"deleteMode=%s\", deleteMode)" - return """func (cli *ZSClient) ${clzName}(${params}, deleteMode param.DeleteMode) error { - return cli.DeleteWithSpec("${cleanPath}", ${firstParam}, ${spec}, ${paramsStr}, nil) + return """func (cli *ZSClient) ${clzName}(ctx context.Context, ${params}, deleteMode param.DeleteMode) error { + return cli.DeleteWithSpec(ctx, "${cleanPath}", ${firstParam}, ${spec}, ${paramsStr}, nil) } """ } default: if (!useSpec) { - return """func (cli *ZSClient) ${clzName}(params param.${clzName}Param) (*view.${viewStructName}, error) { + return """func (cli *ZSClient) ${clzName}(ctx context.Context, params param.${clzName}Param) (*view.${viewStructName}, error) { \t${respDecl} -\tif err := cli.Post("${cleanPath}", params, &resp); err != nil { +\tif err := cli.Post(ctx, "${cleanPath}", params, &resp); err != nil { \t\treturn nil, err \t} \t${returnStmt} @@ -1258,9 +1341,9 @@ func (cli *ZSClient) ${getMethodName}(uuid string) (*view.${viewStructName}, err // POST lacks *WithSpec helpers; build the full URL manually String params = placeholders.collect { "${toSafeGoParamName(it)} string" }.join(", ") String fullPath = buildFullPath(placeholders) - return """func (cli *ZSClient) ${clzName}(${params}, params param.${clzName}Param) (*view.${viewStructName}, error) { + return """func (cli *ZSClient) ${clzName}(ctx context.Context, ${params}, params param.${clzName}Param) (*view.${viewStructName}, error) { \t${respDecl} -\terr := cli.Post(${fullPath}, params, &resp) +\terr := cli.Post(ctx, ${fullPath}, params, &resp) \tif err != nil { \t\treturn nil, err \t} @@ -1291,13 +1374,13 @@ func (cli *ZSClient) ${getMethodName}(uuid string) (*view.${viewStructName}, err def builder = new StringBuilder() builder.append("\n// ${asyncMethodName} Async\n") - builder.append("func (cli *ZSClient) ${asyncMethodName}(params param.${clzName}Param) (string, error) {\n") + builder.append("func (cli *ZSClient) ${asyncMethodName}(ctx context.Context, params param.${clzName}Param) (string, error) {\n") builder.append("\n") builder.append("\tresource := \"${resource}\"\n") builder.append("\tresponseKey := \"\"\n") builder.append("\tvar retVal interface{}\n") builder.append("\n") - builder.append("\tapiId, err := cli.PostWithAsync(resource, responseKey, params, retVal, true)\n") + builder.append("\tapiId, err := cli.PostWithAsync(ctx, resource, responseKey, params, retVal, true)\n") builder.append("\tif err != nil {\n") builder.append("\t\treturn \"\", err\n") builder.append("\t}\n") @@ -1451,4 +1534,3 @@ func (cli *ZSClient) ${getMethodName}(uuid string) (*view.${viewStructName}, err return "fmt.Sprintf(\"${formatStr}\", ${params})" } } - diff --git a/rest/src/main/resources/scripts/GoInventory.groovy b/rest/src/main/resources/scripts/GoInventory.groovy index c31e44149c6..e14cba4f679 100644 --- a/rest/src/main/resources/scripts/GoInventory.groovy +++ b/rest/src/main/resources/scripts/GoInventory.groovy @@ -106,6 +106,27 @@ class GoInventory implements SdkTemplate { return longJobMappings } + /** + * Reset all static and instance state for clean re-generation. + * Must be called before each generate() to avoid stale caches + * causing skipped or duplicate output across repeated runs. + */ + void reset() { + longJobMappings.clear() + allApiTemplates.clear() + inventories.clear() + markedInventories.clear() + additionalClasses.clear() + generatedViewStructs.clear() + generatedViewFiles.clear() + paramNestedTypes.clear() + generatedParamStructs.clear() + generatedClientMethods.clear() + generatingForParam = false + currentGeneratingClass = null + logger.warn("[GoSDK] Reset GoInventory state (static + instance)") + } + /** * Pre-analyze all API classes once and cache metadata. * This avoids expensive re-instantiation of GoApiTemplate and redundant logging. @@ -124,7 +145,7 @@ class GoInventory implements SdkTemplate { try { GoApiTemplate template = new GoApiTemplate(apiClass, this) // If it's a valid template (has @RestRequest) - if (template.at != null) { + if (template.isValid()) { allApiTemplates.add(template) } } catch (Throwable e) { @@ -160,6 +181,9 @@ class GoInventory implements SdkTemplate { List generate() { def files = [] + GoApiTemplate.reset() + reset() + logger.warn("[GoSDK] ===== GoInventory.generate() START =====") logger.warn("[GoSDK] GoInventory.generate() starting...") @@ -296,7 +320,7 @@ class GoInventory implements SdkTemplate { content.append("// Copyright (c) ZStack.io, Inc.\n\n") content.append("package view\n\n") content.append("import \"time\"\n\n") - content.append("var _ = time.Now // avoid unused import\n\n") + content.append("var _ = time.Now() // avoid unused import\n\n") classes.each { Class clz -> String structName = getViewStructName(clz) @@ -314,401 +338,6 @@ class GoInventory implements SdkTemplate { return files } - /** - * Generate ZSClient base file - * @deprecated client.go is manually maintained, this method should not be used - */ - @Deprecated - private SdkFile generateClientFile() { - def sdkFile = new SdkFile() - sdkFile.subPath = "/pkg/client/" - sdkFile.fileName = "client.go" - - def content = new StringBuilder() - content.append("// Copyright (c) ZStack.io, Inc.\n\n") - content.append("package client\n\n") - content.append("import (\n") - content.append("\t\"bytes\"\n") - content.append("\t\"crypto/sha512\"\n") - content.append("\t\"encoding/hex\"\n") - content.append("\t\"encoding/json\"\n") - content.append("\t\"fmt\"\n") - content.append("\t\"io\"\n") - content.append("\t\"net/http\"\n") - content.append("\t\"net/url\"\n") - content.append("\t\"strconv\"\n") - content.append("\t\"strings\"\n") - content.append("\t\"github.com/zstackio/zstack-sdk-go-v2/pkg/param\"\n") - content.append("\t\"time\"\n") - content.append(")\n\n") - content.append("// AuthType authentication type\n") - content.append("type AuthType string\n\n") - content.append("const (\n") - content.append("\tAuthTypeAccessKey AuthType = \"accesskey\"\n") - content.append("\tAuthTypeLogin AuthType = \"login\"\n") - content.append(")\n\n") - content.append("const (\n") - content.append("\tdefaultZStackPort = 8080\n") - content.append(")\n\n") - content.append("// ZSConfig client configuration\n") - content.append("type ZSConfig struct {\n") - content.append("\thostname string\n") - content.append("\tport int\n") - content.append("\tcontextPath string\n") - content.append("\taccessKeyId string\n") - content.append("\taccessKeySecret string\n") - content.append("\tusername string\n") - content.append("\tpassword string\n") - content.append("\tauthType AuthType\n") - content.append("\tdebug bool\n") - content.append("\ttimeout time.Duration\n") - content.append("}\n\n") - content.append("// NewZSConfig creates a new configuration\n") - content.append("func NewZSConfig(hostname string, port int, contextPath string) *ZSConfig {\n") - content.append("\treturn &ZSConfig{\n") - content.append("\t\thostname: hostname,\n") - content.append("\t\tport: port,\n") - content.append("\t\tcontextPath: contextPath,\n") - content.append("\t\ttimeout: 30 * time.Second,\n") - content.append("\t}\n") - content.append("}\n\n") - content.append("// DefaultZSConfig creates a default configuration\n") - content.append("func DefaultZSConfig(hostname, contextPath string) *ZSConfig {\n") - content.append("\treturn NewZSConfig(hostname, defaultZStackPort, contextPath)\n") - content.append("}\n\n") - content.append("// AccessKey sets access key authentication\n") - content.append("func (config *ZSConfig) AccessKey(id, secret string) *ZSConfig {\n") - content.append("\tconfig.accessKeyId = id\n") - content.append("\tconfig.accessKeySecret = secret\n") - content.append("\tconfig.authType = AuthTypeAccessKey\n") - content.append("\treturn config\n") - content.append("}\n\n") - content.append("// Login sets login authentication\n") - content.append("func (config *ZSConfig) Login(username, password string) *ZSConfig {\n") - content.append("\tconfig.username = username\n") - content.append("\tconfig.password = password\n") - content.append("\tconfig.authType = AuthTypeLogin\n") - content.append("\treturn config\n") - content.append("}\n\n") - content.append("// Debug enables debug mode\n") - content.append("func (config *ZSConfig) Debug(debug bool) *ZSConfig {\n") - content.append("\tconfig.debug = debug\n") - content.append("\treturn config\n") - content.append("}\n\n") - content.append("// ZSClient ZStack API client\n") - content.append("type ZSClient struct {\n") - content.append("\tconfig *ZSConfig\n") - content.append("\thttpClient *http.Client\n") - content.append("\tsessionId string\n") - content.append("}\n\n") - content.append("// JobView job inventory view\n") - content.append("type JobView struct {\n") - content.append("\tUUID string `json:\"uuid\"`\n") - content.append("\tState string `json:\"state\"`\n") - content.append("\tResult interface{} `json:\"result,omitempty\"`\n") - content.append("\tError interface{} `json:\"error,omitempty\"`\n") - content.append("\tCreateDate string `json:\"createDate\"`\n") - content.append("}\n\n") - content.append("const (\n") - content.append("\tJobStateProcessing = \"Processing\"\n") - content.append("\tJobStateSucceeded = \"Succeeded\"\n") - content.append("\tJobStateFailed = \"Failed\"\n") - content.append(")\n\n") - content.append("// NewZSClient creates a new ZStack client\n") - content.append("func NewZSClient(config *ZSConfig) *ZSClient {\n") - content.append("\t// Auto-encrypt password for login authentication\n") - content.append("\tif config.authType == AuthTypeLogin && config.password != \"\" {\n") - content.append("\t\tconfig.password = hashPasswordSHA512(config.password)\n") - content.append("\t\tif config.debug {\n") - content.append("\t\t\tfmt.Printf(\"[DEBUG] Password hashed: %s...\\n\", config.password[:16])\n") - content.append("\t\t}\n") - content.append("\t}\n") - content.append("\treturn &ZSClient{\n") - content.append("\t\tconfig: config,\n") - content.append("\t\thttpClient: &http.Client{\n") - content.append("\t\t\tTimeout: config.timeout,\n") - content.append("\t\t},\n") - content.append("\t}\n") - content.append("}\n\n") - content.append("// hashPasswordSHA512 encrypts password using SHA512\n") - content.append("func hashPasswordSHA512(password string) string {\n") - content.append("\thash := sha512.Sum512([]byte(password))\n") - content.append("\treturn hex.EncodeToString(hash[:])\n") - content.append("}\n\n") - content.append("func (cli *ZSClient) baseURL() string {\n") - content.append("\treturn fmt.Sprintf(\"http://%s:%d%s\", cli.config.hostname, cli.config.port, cli.config.contextPath)\n") - content.append("}\n\n") - content.append("// Get performs a GET request\n") - content.append("func (cli *ZSClient) Get(path string, uuid string, params interface{}, result interface{}) error {\n") - content.append("\turl := fmt.Sprintf(\"%s/%s\", cli.baseURL(), path)\n") - content.append("\tif uuid != \"\" {\n") - content.append("\t\turl = fmt.Sprintf(\"%s/%s\", url, uuid)\n") - content.append("\t}\n") - content.append("\treturn cli.doRequest(\"GET\", url, nil, result)\n") - content.append("}\n\n") - content.append("func (cli *ZSClient) QueryJob(uuid string) (*JobView, error) {\n") - content.append("\tvar resp JobView\n") - content.append("\turl := fmt.Sprintf(\"%s/v1/api-jobs/%s\", cli.baseURL(), uuid)\n") - content.append("\terr := cli.doRequest(\"GET\", url, nil, &resp)\n") - content.append("\treturn &resp, err\n") - content.append("}\n\n") - content.append("// List performs a list query\n") - content.append("func (cli *ZSClient) List(path string, params interface{}, result interface{}) error {\n") - content.append("\tbaseURL := cli.baseURL()\n") - content.append("\trequestURL := fmt.Sprintf(\"%s/%s\", baseURL, path)\n") - content.append("\n") - content.append("\tif params != nil {\n") - content.append("\t\tif queryParam, ok := params.(*param.QueryParam); ok {\n") - content.append("\t\t\tqueryString := cli.buildQueryString(queryParam)\n") - content.append("\t\t\tif queryString != \"\" {\n") - content.append("\t\t\t\trequestURL = fmt.Sprintf(\"%s?%s\", requestURL, queryString)\n") - content.append("\t\t\t}\n") - content.append("\t\t}\n") - content.append("\t}\n") - content.append("\n") - content.append("\t// Unmarshal response into wrapper with inventories field\n") - content.append("\tvar wrapper struct {\n") - content.append("\t\tInventories interface{} `json:\"inventories\"`\n") - content.append("\t\tInventory interface{} `json:\"inventory\"`\n") - content.append("\t}\n") - content.append("\n") - content.append("\tif err := cli.doRequest(\"GET\", requestURL, nil, &wrapper); err != nil {\n") - content.append("\t\treturn err\n") - content.append("\t}\n") - content.append("\n") - content.append("\t// Try inventories first (plural), then inventory (singular)\n") - content.append("\tvar data interface{}\n") - content.append("\tif wrapper.Inventories != nil {\n") - content.append("\t\tdata = wrapper.Inventories\n") - content.append("\t} else if wrapper.Inventory != nil {\n") - content.append("\t\tdata = wrapper.Inventory\n") - content.append("\t}\n") - content.append("\n") - content.append("\t// Re-marshal and unmarshal into the actual result type\n") - content.append("\tif data != nil {\n") - content.append("\t\tdataBytes, err := json.Marshal(data)\n") - content.append("\t\tif err != nil {\n") - content.append("\t\t\treturn fmt.Errorf(\"failed to marshal data: %v\", err)\n") - content.append("\t\t}\n") - content.append("\t\tif cli.config.debug {\n") - content.append("\t\t\tfmt.Printf(\"[DEBUG] Received %d bytes of inventory data\\n\", len(dataBytes))\n") - content.append("\t\t}\n") - content.append("\t\terr = json.Unmarshal(dataBytes, result)\n") - content.append("\t\tif err != nil {\n") - content.append("\t\t\treturn fmt.Errorf(\"failed to unmarshal data into result: %v\", err)\n") - content.append("\t\t}\n") - content.append("\t\treturn nil\n") - content.append("\t}\n") - content.append("\tif cli.config.debug {\n") - content.append("\t\tfmt.Println(\"[DEBUG] Both inventories and inventory are nil, returning empty result\")\n") - content.append("\t}\n") - content.append("\treturn nil\n") - content.append("}\n\n") - content.append("// Post performs a POST request\n") - content.append("func (cli *ZSClient) Post(path string, params interface{}, result interface{}) error {\n") - content.append("\turl := fmt.Sprintf(\"%s/%s\", cli.baseURL(), path)\n") - content.append("\treturn cli.doRequest(\"POST\", url, params, result)\n") - content.append("}\n\n") - content.append("// Put performs a PUT request\n") - content.append("func (cli *ZSClient) Put(path string, uuid string, params interface{}, result interface{}) error {\n") - content.append("\turl := fmt.Sprintf(\"%s/%s/%s\", cli.baseURL(), path, uuid)\n") - content.append("\treturn cli.doRequest(\"PUT\", url, params, result)\n") - content.append("}\n\n") - content.append("// Delete performs a DELETE request\n") - content.append("func (cli *ZSClient) Delete(path string, uuid string, deleteMode string) error {\n") - content.append("\turl := fmt.Sprintf(\"%s/%s/%s?deleteMode=%s\", cli.baseURL(), path, uuid, deleteMode)\n") - content.append("\treturn cli.doRequest(\"DELETE\", url, nil, nil)\n") - content.append("}\n\n") - content.append("func (cli *ZSClient) doRequest(method, url string, body interface{}, result interface{}) error {\n") - content.append("\t// Auto-login if using login auth and no session yet\n") - content.append("\tif cli.config.authType == AuthTypeLogin && cli.sessionId == \"\" && !strings.HasSuffix(url, \"/accounts/login\") {\n") - content.append("\t\terr := cli.Login(cli.config.username, cli.config.password)\n") - content.append("\t\tif err != nil {\n") - content.append("\t\t\treturn fmt.Errorf(\"auto-login failed: %v\", err)\n") - content.append("\t\t}\n") - content.append("\t}\n\n") - content.append("\tvar bodyReader io.Reader\n") - content.append("\tvar bodyBytes []byte\n") - content.append("\tif body != nil {\n") - content.append("\t\tvar err error\n") - content.append("\t\tbodyBytes, err = json.Marshal(body)\n") - content.append("\t\tif err != nil {\n") - content.append("\t\t\treturn err\n") - content.append("\t\t}\n") - content.append("\t\tbodyReader = bytes.NewBuffer(bodyBytes)\n") - content.append("\t}\n\n") - content.append("\treq, err := http.NewRequest(method, url, bodyReader)\n") - content.append("\tif err != nil {\n") - content.append("\t\treturn err\n") - content.append("\t}\n\n") - content.append("\treq.Header.Set(\"Content-Type\", \"application/json\")\n") - content.append("\tcli.addAuthHeaders(req)\n\n") - content.append("\tif cli.config.debug && bodyBytes != nil {\n") - content.append("\t\tfmt.Printf(\"[DEBUG] %s %s\\n\", method, url)\n") - content.append("\t\tfmt.Printf(\"[DEBUG] Body: %s\\n\", string(bodyBytes))\n") - content.append("\t\tfmt.Printf(\"[DEBUG] Headers: Authorization=%s\\n\", req.Header.Get(\"Authorization\"))\n") - content.append("\t}\n\n") - content.append("\tresp, err := cli.httpClient.Do(req)\n") - content.append("\tif err != nil {\n") - content.append("\t\treturn err\n") - content.append("\t}\n") - content.append("\tdefer resp.Body.Close()\n\n") - content.append("\tif resp.StatusCode == 202 {\n") - content.append("\t\tvar location struct {\n") - content.append("\t\t\tLocation string `json:\"location\"`\n") - content.append("\t\t\tUuid string `json:\"org.zstack.header.rest.APIEvent/uuid\"`\n") - content.append("\t\t}\n") - content.append("\t\tif err := json.NewDecoder(resp.Body).Decode(&location); err != nil {\n") - content.append("\t\t\treturn fmt.Errorf(\"failed to decode 202 response: %v\", err)\n") - content.append("\t\t}\n") - content.append("\t\tjobUUID := location.Uuid\n") - content.append("\t\tif jobUUID == \"\" {\n") - content.append("\t\t\tparts := bytes.Split([]byte(location.Location), []byte(\"/\"))\n") - content.append("\t\t\tif len(parts) > 0 {\n") - content.append("\t\t\t\tjobUUID = string(parts[len(parts)-1])\n") - content.append("\t\t\t}\n") - content.append("\t\t}\n") - content.append("\n") - content.append("\t\tif jobUUID == \"\" {\n") - content.append("\t\t\treturn fmt.Errorf(\"failed to extract job uuid from 202 response\")\n") - content.append("\t\t}\n") - content.append("\n") - content.append("\t\treturn cli.waitForJob(jobUUID, result)\n") - content.append("\t}\n\n") - content.append("\tif resp.StatusCode >= 400 {\n") - content.append("\t\trespBody, _ := io.ReadAll(resp.Body)\n") - content.append("\t\terrMsg := fmt.Sprintf(\"API error: %s %s returned status code %d\\n\", method, url, resp.StatusCode)\n") - content.append("\t\terrMsg += fmt.Sprintf(\"Authorization: %s\\n\", req.Header.Get(\"Authorization\"))\n") - content.append("\t\terrMsg += fmt.Sprintf(\"Response: %s\", string(respBody))\n") - content.append("\t\treturn fmt.Errorf(errMsg)\n") - content.append("\t}\n\n") - content.append("\tif result != nil {\n") - content.append("\t\treturn json.NewDecoder(resp.Body).Decode(result)\n") - content.append("\t}\n") - content.append("\treturn nil\n") - content.append("}\n\n") - content.append("func (cli *ZSClient) waitForJob(jobUUID string, result interface{}) error {\n") - content.append("\tticker := time.NewTicker(500 * time.Millisecond)\n") - content.append("\tdefer ticker.Stop()\n") - content.append("\n") - content.append("\ttimeout := time.After(30 * time.Minute)\n") - content.append("\n") - content.append("\tfor {\n") - content.append("\t\tselect {\n") - content.append("\t\tcase <-timeout:\n") - content.append("\t\t\treturn fmt.Errorf(\"job %s timeout\", jobUUID)\n") - content.append("\t\tcase <-ticker.C:\n") - content.append("\t\t\tjob, err := cli.QueryJob(jobUUID)\n") - content.append("\t\t\tif err != nil {\n") - content.append("\t\t\t\tcontinue\n") - content.append("\t\t\t}\n") - content.append("\n") - content.append("\t\t\tif job.State == JobStateSucceeded {\n") - content.append("\t\t\t\tif result != nil && job.Result != nil {\n") - content.append("\t\t\t\t\tdata, err := json.Marshal(job.Result)\n") - content.append("\t\t\t\t\tif err != nil {\n") - content.append("\t\t\t\t\t\treturn fmt.Errorf(\"failed to marshal job result: %v\", err)\n") - content.append("\t\t\t\t\t}\n") - content.append("\t\t\t\t\treturn json.Unmarshal(data, result)\n") - content.append("\t\t\t\t}\n") - content.append("\t\t\t\treturn nil\n") - content.append("\t\t\t}\n") - content.append("\n") - content.append("\t\t\tif job.State == JobStateFailed {\n") - content.append("\t\t\t\treturn fmt.Errorf(\"job failed: %v\", job.Error)\n") - content.append("\t\t\t}\n") - content.append("\t\t}\n") - content.append("\t}\n") - content.append("}\n\n") - content.append("func (cli *ZSClient) buildQueryString(params *param.QueryParam) string {\n") - content.append("\tif params == nil {\n") - content.append("\t\treturn \"\"\n") - content.append("\t}\n") - content.append("\tu := url.Values{}\n") - content.append("\n") - content.append("\tfor _, q := range params.Conditions {\n") - content.append("\t\tif q.Name != \"\" && q.Op != \"\" {\n") - content.append("\t\t\tu.Add(\"q\", fmt.Sprintf(\"%s%s%s\", q.Name, q.Op, q.Value))\n") - content.append("\t\t} else if q.Value != \"\" {\n") - content.append("\t\t\tu.Add(\"q\", q.Value)\n") - content.append("\t\t}\n") - content.append("\t}\n") - content.append("\n") - content.append("\tif params.LimitNum != nil {\n") - content.append("\t\tu.Set(\"limit\", strconv.Itoa(*params.LimitNum))\n") - content.append("\t}\n") - content.append("\tif params.StartNum != nil {\n") - content.append("\t\tu.Set(\"start\", strconv.Itoa(*params.StartNum))\n") - content.append("\t}\n") - content.append("\tif params.Count {\n") - content.append("\t\tu.Set(\"count\", \"true\")\n") - content.append("\t}\n") - content.append("\tif params.ReplyWithCount {\n") - content.append("\t\tu.Set(\"replyWithCount\", \"true\")\n") - content.append("\t}\n") - content.append("\tif params.GroupBy != \"\" {\n") - content.append("\t\tu.Set(\"groupBy\", params.GroupBy)\n") - content.append("\t}\n") - content.append("\tif params.SortBy != \"\" {\n") - content.append("\t\tu.Set(\"sortBy\", params.SortBy)\n") - content.append("\t}\n") - content.append("\tif params.SortDirection != \"\" {\n") - content.append("\t\tu.Set(\"sortDirection\", params.SortDirection)\n") - content.append("\t}\n") - content.append("\tfor _, f := range params.Fields {\n") - content.append("\t\tu.Add(\"fields\", f)\n") - content.append("\t}\n") - content.append("\n") - content.append("\treturn u.Encode()\n") - content.append("}\n\n") - content.append("func (cli *ZSClient) addAuthHeaders(req *http.Request) {\n") - content.append("\tif cli.config.authType == AuthTypeAccessKey {\n") - content.append("\t\treq.Header.Set(\"X-Access-Key-Id\", cli.config.accessKeyId)\n") - content.append("\t\treq.Header.Set(\"X-Access-Key-Secret\", cli.config.accessKeySecret)\n") - content.append("\t} else if cli.sessionId != \"\" {\n") - content.append("\t\treq.Header.Set(\"Authorization\", \"OAuth \"+cli.sessionId)\n") - content.append("\t}\n") - content.append("}\n\n") - content.append("// Login authenticates with username and password\n") - content.append("func (cli *ZSClient) Login(username, password string) error {\n") - content.append("\tif cli.config.authType != AuthTypeLogin {\n") - content.append("\t\treturn fmt.Errorf(\"client is not configured for login authentication\")\n") - content.append("\t}\n\n") - content.append("\tvar loginReq = map[string]map[string]string{\n") - content.append("\t\t\"logInByAccount\": {\n") - content.append("\t\t\t\"accountName\": username,\n") - content.append("\t\t\t\"password\": password, // Already hashed in NewZSClient\n") - content.append("\t\t},\n") - content.append("\t}\n\n") - content.append("\tvar loginResp struct {\n") - content.append("\t\tInventory struct {\n") - content.append("\t\t\tUUID string `json:\"uuid\"`\n") - content.append("\t\t} `json:\"inventory\"`\n") - content.append("\t}\n\n") - content.append("\turl := fmt.Sprintf(\"%s/v1/accounts/login\", cli.baseURL())\n") - content.append("\terr := cli.doRequest(\"PUT\", url, loginReq, &loginResp)\n") - content.append("\tif err != nil {\n") - content.append("\t\treturn fmt.Errorf(\"login failed: %v\", err)\n") - content.append("\t}\n\n") - content.append("\tcli.sessionId = loginResp.Inventory.UUID\n") - content.append("\tif cli.config.debug {\n") - content.append("\t\tfmt.Printf(\"[DEBUG] Login successful, sessionId=%s\\n\", cli.sessionId)\n") - content.append("\t}\n") - content.append("\treturn nil\n") - content.append("}\n\n") - content.append("func (cli *ZSClient) Logout() error {\n") - content.append("\tif cli.sessionId == \"\" {\n") - content.append("\t\treturn nil\n") - content.append("\t}\n\n") - content.append("\turl := fmt.Sprintf(\"%s/v1/accounts/sessions/%s\", cli.baseURL(), cli.sessionId)\n") - content.append("\terr := cli.doRequest(\"DELETE\", url, nil, nil)\n") - content.append("\tcli.sessionId = \"\"\n") - content.append("\treturn err\n") - content.append("}\n") - - sdkFile.content = content.toString() - return sdkFile - } /** * Generate base view file @@ -1728,6 +1357,7 @@ class GoInventory implements SdkTemplate { content.append("// Copyright (c) ZStack.io, Inc.\n\n") content.append("package client\n\n") content.append("import (\n") + content.append("\t\"context\"\n") if (needsFmt) { content.append("\t\"fmt\"\n") } @@ -1760,7 +1390,7 @@ class GoInventory implements SdkTemplate { content.append("// Copyright (c) ZStack.io, Inc.\n\n") content.append("package view\n\n") content.append("import \"time\"\n\n") - content.append("var _ = time.Now // avoid unused import\n\n") + content.append("var _ = time.Now() // avoid unused import\n\n") int addedCount = 0 Set processedViews = new HashSet<>() @@ -1912,7 +1542,7 @@ class GoInventory implements SdkTemplate { content.append("// Copyright (c) ZStack.io, Inc.\n\n") content.append("package view\n\n") content.append("import \"time\"\n\n") - content.append("var _ = time.Now // avoid unused import\n\n") + content.append("var _ = time.Now() // avoid unused import\n\n") logger.warn("[GoSDK] Generating new view file for: ${structName} (${fileName})") } @@ -2048,6 +1678,7 @@ class GoInventory implements SdkTemplate { content.append("// Copyright (c) ZStack.io, Inc.\n\n") content.append("package client\n\n") content.append("import (\n") + content.append("\t\"context\"\n") if (needsFmt) { content.append("\t\"fmt\"\n") } @@ -2086,7 +1717,7 @@ class GoInventory implements SdkTemplate { content.append("// Copyright (c) ZStack.io, Inc.\n\n") content.append("package param\n\n") content.append("import \"time\"\n\n") - content.append("var _ = time.Now // avoid unused import\n\n") + content.append("var _ = time.Now() // avoid unused import\n\n") boolean hasParams = false allApiTemplates.each { GoApiTemplate template -> diff --git a/rest/src/main/resources/scripts/RestDocumentationGenerator.groovy b/rest/src/main/resources/scripts/RestDocumentationGenerator.groovy index c11a35e40a7..7f4df6504a9 100755 --- a/rest/src/main/resources/scripts/RestDocumentationGenerator.groovy +++ b/rest/src/main/resources/scripts/RestDocumentationGenerator.groovy @@ -787,10 +787,13 @@ class RestDocumentationGenerator implements DocumentGenerator { return globalConfigMarkDown } - Boolean isConsistent(GlobalConfigMarkDown md, GlobalConfig globalConfig) { - if (md == null || globalConfig == null) { - return false - } + List isConsistent(GlobalConfigMarkDown md, GlobalConfig globalConfig) { + if (md == null) { + return ["GlobalConfigMarkDown is null"] + } + if (globalConfig == null) { + return ["GlobalConfig is null"] + } String mdPath = PathUtil.join(PathUtil.join(Paths.get("../doc").toAbsolutePath().normalize().toString(), "globalconfig"), md.globalConfig.category, md.globalConfig.name) + ".md" @@ -798,70 +801,77 @@ class RestDocumentationGenerator implements DocumentGenerator { initializer.bindResources.get(globalConfig.getIdentity()).each { classes.add(it.getName()) } List newClasses = classes.sort() String validatorString = initializer.validatorMap.get(globalConfig.getIdentity()) - Boolean flag = true - if (md.globalConfig.name != globalConfig.name) { - logger.info("name of ${mdPath} is not latest") - flag = false - } - if (md.globalConfig.defaultValue != globalConfig.defaultValue) { - logger.info("defaultValue of ${mdPath} is not latest") - flag = false - } - if (StringUtils.trimToEmpty(md.globalConfig.description) != StringUtils.trimToEmpty(globalConfig.description)) { - logger.info("desc of ${mdPath} is not latest") - flag = false - } - if (md.globalConfig.type != globalConfig.type) { - if (globalConfig.type != null) { - logger.info("type of ${mdPath} is not latest") - flag = false - } - } - if (md.globalConfig.category != globalConfig.category) { - logger.info("category of ${mdPath} is not latest") - flag = false - } - List oldClasses = md.globalConfig.resources.sort() - if (oldClasses != newClasses) { - logger.info("classes of ${mdPath} is not latest") - flag = false - } + List mismatches = [] + if (md.globalConfig.name != globalConfig.name) { + logger.info("name of ${mdPath} is not latest") + mismatches.add("name mismatch in ${mdPath}: markdown='${md.globalConfig.name}', current='${globalConfig.name}'") + } + if (md.globalConfig.defaultValue != globalConfig.defaultValue) { + logger.info("defaultValue of ${mdPath} is not latest") + mismatches.add("defaultValue mismatch in ${mdPath}: markdown='${md.globalConfig.defaultValue}', current='${globalConfig.defaultValue}'") + } + if (StringUtils.trimToEmpty(md.globalConfig.description) != StringUtils.trimToEmpty(globalConfig.description)) { + logger.info("desc of ${mdPath} is not latest") + mismatches.add("description mismatch in ${mdPath}: markdown='${StringUtils.trimToEmpty(md.globalConfig.description)}', current='${StringUtils.trimToEmpty(globalConfig.description)}'") + } + if (md.globalConfig.type != globalConfig.type) { + if (globalConfig.type != null) { + logger.info("type of ${mdPath} is not latest") + mismatches.add("type mismatch in ${mdPath}: markdown='${md.globalConfig.type}', current='${globalConfig.type}'") + } + } + if (md.globalConfig.category != globalConfig.category) { + logger.info("category of ${mdPath} is not latest") + mismatches.add("category mismatch in ${mdPath}: markdown='${md.globalConfig.category}', current='${globalConfig.category}'") + } + List oldClasses = md.globalConfig.resources.sort() + if (oldClasses != newClasses) { + logger.info("classes of ${mdPath} is not latest") + mismatches.add("resources mismatch in ${mdPath}: markdown='${oldClasses}', current='${newClasses}'") + } if (md.globalConfig.valueRange != (validatorString)) { boolean useBooleanValidator = (globalConfig.type == "java.lang.Boolean" && md.globalConfig.valueRange == "{true, false}") - if (validatorString != null || !useBooleanValidator) { - logger.info("valueRange of ${mdPath} is not latest") - logger.info("valueRange = ${md.globalConfig.valueRange} validatorString = ${validatorString}") - flag = false - } - } - return flag - } + if (validatorString != null || !useBooleanValidator) { + logger.info("valueRange of ${mdPath} is not latest") + logger.info("valueRange = ${md.globalConfig.valueRange} validatorString = ${validatorString}") + mismatches.add("valueRange mismatch in ${mdPath}: markdown='${md.globalConfig.valueRange}', current='${validatorString}'") + } + } + return mismatches + } void checkMD(String mdPath, GlobalConfig globalConfig) { String result = ShellUtils.runAndReturn( "grep '${PLACEHOLDER}' ${mdPath}").stdout.replaceAll("\n", "") - if (!result.empty) { - throw new CloudRuntimeException("Placeholders are detected in ${mdPath}, please replace them by content.") - } - GlobalConfigMarkDown markDown = getExistGlobalConfigMarkDown(mdPath) - if (markDown.desc_CN.isEmpty() - || markDown.name_CN.isEmpty() - || markDown.valueRangeRemark.isEmpty() - || markDown.defaultValueRemark.isEmpty() - || markDown.resourcesGranularitiesRemark.isEmpty() - || markDown.additionalRemark.isEmpty() - || markDown.backgroundInformation.isEmpty() - || markDown.isUIExposed.isEmpty() - || markDown.isCLIExposed.isEmpty() - ) { - throw new CloudRuntimeException("The necessary information of ${mdPath} is missing, please complete the information before submission.") - } - if (!isConsistent(markDown, globalConfig)) { - throw new CloudRuntimeException("${mdPath} is not match with its definition, please use Repair mode to correct it.") - } - } + if (!result.empty) { + throw new CloudRuntimeException("Placeholders detected in ${mdPath}; please replace them with actual content.") + } + GlobalConfigMarkDown markDown = getExistGlobalConfigMarkDown(mdPath) + List missingFields = [] + if (markDown.desc_CN.isEmpty()) missingFields.add("desc_CN") + if (markDown.name_CN.isEmpty()) missingFields.add("name_CN") + if (markDown.valueRangeRemark.isEmpty()) missingFields.add("valueRangeRemark") + if (markDown.defaultValueRemark.isEmpty()) missingFields.add("defaultValueRemark") + if (markDown.resourcesGranularitiesRemark.isEmpty()) missingFields.add("resourcesGranularitiesRemark") + if (markDown.additionalRemark.isEmpty()) missingFields.add("additionalRemark") + if (markDown.backgroundInformation.isEmpty()) missingFields.add("backgroundInformation") + if (markDown.isUIExposed.isEmpty()) missingFields.add("isUIExposed") + if (markDown.isCLIExposed.isEmpty()) missingFields.add("isCLIExposed") + List inconsistencies = isConsistent(markDown, globalConfig) + if (!missingFields.isEmpty() || !inconsistencies.isEmpty()) { + StringBuilder sb = new StringBuilder("Validation failed for ${mdPath}:\n") + if (!missingFields.isEmpty()) { + sb.append("Missing required fields: ${missingFields}\n") + } + if (!inconsistencies.isEmpty()) { + sb.append("Inconsistent fields:\n") + inconsistencies.each { sb.append("- ${it}\n") } + } + throw new CloudRuntimeException(sb.toString()) + } + } class ElaborationMarkDown { private def table = ["|编号|描述|原因|操作建议|更多|"] @@ -2815,23 +2825,32 @@ ${additionalRemark} return System.getProperty("ignoreError") != null } - void testGlobalConfigTemplateAndMarkDown() { - Map allConfigs = initializer.configs - allConfigs.each { - String newPath = - PathUtil.join(PathUtil.join(Paths.get("../doc").toAbsolutePath().normalize().toString(), - "globalconfig"), it.value.category, it.value.name) + DEPRECATED + ".md" - if (new File(newPath).exists()) { + void testGlobalConfigTemplateAndMarkDown() { + Map allConfigs = initializer.configs + List allErrors = [] + allConfigs.each { + String newPath = + PathUtil.join(PathUtil.join(Paths.get("../doc").toAbsolutePath().normalize().toString(), + "globalconfig"), it.value.category, it.value.name) + DEPRECATED + ".md" + if (new File(newPath).exists()) { return } - String mdPath = - PathUtil.join(PathUtil.join(Paths.get("../doc").toAbsolutePath().normalize().toString(), - "globalconfig"), it.value.category, it.value.name) + ".md" - File mdFile = new File(mdPath) - if (!mdFile.exists()) { - throw new CloudRuntimeException("Not found the document markdown of the global config ${it.value.name} , please generate it first.") - } - checkMD(mdPath, it.value) - } - } -} + String mdPath = + PathUtil.join(PathUtil.join(Paths.get("../doc").toAbsolutePath().normalize().toString(), + "globalconfig"), it.value.category, it.value.name) + ".md" + File mdFile = new File(mdPath) + if (!mdFile.exists()) { + allErrors.add("Global config markdown not found: ${mdPath}") + return + } + try { + checkMD(mdPath, it.value) + } catch (CloudRuntimeException e) { + allErrors.add(e.message) + } + } + if (!allErrors.isEmpty()) { + throw new CloudRuntimeException(allErrors.join("\n\n")) + } + } +} diff --git a/rest/src/main/resources/scripts/SdkDataStructureGenerator.groovy b/rest/src/main/resources/scripts/SdkDataStructureGenerator.groovy index dcaea05080d..373a5181bee 100755 --- a/rest/src/main/resources/scripts/SdkDataStructureGenerator.groovy +++ b/rest/src/main/resources/scripts/SdkDataStructureGenerator.groovy @@ -7,11 +7,12 @@ import org.zstack.header.exception.CloudRuntimeException import org.zstack.header.message.Message import org.zstack.header.query.APIQueryReply import org.zstack.header.rest.APINoSee -import org.zstack.header.rest.NoSDK -import org.zstack.header.rest.RestResponse -import org.zstack.header.rest.SDK -import org.zstack.rest.sdk.SdkFile -import org.zstack.rest.sdk.SdkTemplate +import org.zstack.header.rest.NoSDK +import org.zstack.header.rest.RestResponse +import org.zstack.header.rest.SDK +import org.zstack.header.rest.SDKGeneric +import org.zstack.rest.sdk.SdkFile +import org.zstack.rest.sdk.SdkTemplate import org.zstack.utils.FieldUtils import org.zstack.utils.Utils import org.zstack.utils.logging.CLogger @@ -360,21 +361,22 @@ ${output.join("\n")} // java type if (Collection.class.isAssignableFrom(field.type)) { Class genericType = FieldUtils.getGenericType(field) - if (genericType != null) { - if (isZStackClass(genericType)) { - addToLaterResolvedClassesIfNeed(genericType) - } - } - - return """\ - public ${field.type.name} ${fname}; - public void set${StringUtils.capitalize(fname)}(${field.type.name} ${fname}) { - this.${fname} = ${fname}; - } - public ${field.type.name} get${StringUtils.capitalize(fname)}() { - return this.${fname}; - } -""" + if (genericType != null) { + if (isZStackClass(genericType)) { + addToLaterResolvedClassesIfNeed(genericType) + } + } + String fieldType = getCollectionFieldType(field, genericType) + + return """\ + public ${fieldType} ${fname}; + public void set${StringUtils.capitalize(fname)}(${fieldType} ${fname}) { + this.${fname} = ${fname}; + } + public ${fieldType} get${StringUtils.capitalize(fname)}() { + return this.${fname}; + } +""" } else if (Map.class.isAssignableFrom(field.type)) { Class genericType = FieldUtils.getGenericType(field) if (genericType != null) { @@ -402,6 +404,22 @@ ${output.join("\n")} return this.${fname}; } """ - } - } -} + } + } + + def getCollectionFieldType(Field field, Class genericType) { + if (!field.isAnnotationPresent(SDKGeneric.class) || genericType == null) { + return field.type.name + } + + return "${field.type.name}<${getSdkTypeName(genericType)}>" + } + + def getSdkTypeName(Class clz) { + if (isZStackClass(clz)) { + return "${SdkApiTemplate.getPackageName(clz)}.${getTargetClassName(clz)}" + } + + return clz.name + } +} diff --git a/rest/src/main/resources/scripts/templates/base_param_types.go.template b/rest/src/main/resources/scripts/templates/base_param_types.go.template index 962ccda910b..1c3e8ec9ffa 100644 --- a/rest/src/main/resources/scripts/templates/base_param_types.go.template +++ b/rest/src/main/resources/scripts/templates/base_param_types.go.template @@ -4,7 +4,7 @@ package param import "time" -var _ = time.Now // avoid unused import +var _ = time.Now() // avoid unused import type DeleteMode string diff --git a/sdk/src/main/java/SourceClassMap.java b/sdk/src/main/java/SourceClassMap.java index 72fbac9b302..0b25de52539 100644 --- a/sdk/src/main/java/SourceClassMap.java +++ b/sdk/src/main/java/SourceClassMap.java @@ -11,7 +11,15 @@ public class SourceClassMap { put("org.zstack.accessKey.AccessKeyState", "org.zstack.sdk.AccessKeyState"); put("org.zstack.accessKey.AccessKeyType", "org.zstack.sdk.AccessKeyType"); put("org.zstack.ai.NginxRedirectRule", "org.zstack.sdk.NginxRedirectRule"); + put("org.zstack.ai.entity.AiHostCacheStorageInventory", "org.zstack.sdk.AiHostCacheStorageInventory"); + put("org.zstack.ai.entity.AiHostCacheStorageStatus", "org.zstack.sdk.AiHostCacheStorageStatus"); + put("org.zstack.ai.entity.AiHostModelCacheFailureCode", "org.zstack.sdk.AiHostModelCacheFailureCode"); + put("org.zstack.ai.entity.AiHostModelCacheFailurePhase", "org.zstack.sdk.AiHostModelCacheFailurePhase"); + put("org.zstack.ai.entity.AiHostModelCacheInventory", "org.zstack.sdk.AiHostModelCacheInventory"); + put("org.zstack.ai.entity.AiHostModelCachePolicyInventory", "org.zstack.sdk.AiHostModelCachePolicyInventory"); + put("org.zstack.ai.entity.AiHostModelCacheStatus", "org.zstack.sdk.AiHostModelCacheStatus"); put("org.zstack.ai.entity.ApplicationDevelopmentServiceInventory", "org.zstack.sdk.ApplicationDevelopmentServiceInventory"); + put("org.zstack.ai.entity.CdnModelServiceTemplateInventory", "org.zstack.sdk.CdnModelServiceTemplateInventory"); put("org.zstack.ai.entity.DatasetInventory", "org.zstack.sdk.DatasetInventory"); put("org.zstack.ai.entity.ModelCenterCapacityInventory", "org.zstack.sdk.ModelCenterCapacityInventory"); put("org.zstack.ai.entity.ModelCenterInventory", "org.zstack.sdk.ModelCenterInventory"); @@ -36,6 +44,8 @@ public class SourceClassMap { put("org.zstack.ai.message.ModelCenterServiceInventory$ServiceStatus", "org.zstack.sdk.ServiceStatus"); put("org.zstack.ai.message.ModelCenterServiceInventory$ZdfsService", "org.zstack.sdk.ZdfsService"); put("org.zstack.ai.message.ModelService", "org.zstack.sdk.ModelService"); + put("org.zstack.ai.message.ModelServiceInstanceLaunchCommandInventory", "org.zstack.sdk.ModelServiceInstanceLaunchCommandInventory"); + put("org.zstack.ai.message.ModelServiceLaunchCommandInventory", "org.zstack.sdk.ModelServiceLaunchCommandInventory"); put("org.zstack.ai.message.ModelServiceMatchEntry", "org.zstack.sdk.ModelServiceMatchEntry"); put("org.zstack.ai.message.ModelServiceMatchEntryName", "org.zstack.sdk.ModelServiceMatchEntryName"); put("org.zstack.ai.message.ModelServiceMatchStatus", "org.zstack.sdk.ModelServiceMatchStatus"); @@ -89,6 +99,7 @@ public class SourceClassMap { put("org.zstack.billing.SpendingDetails", "org.zstack.sdk.SpendingDetails"); put("org.zstack.billing.generator.BillingInventory", "org.zstack.sdk.BillingInventory"); put("org.zstack.billing.generator.baremetal2.BareMetal2BillingInventory", "org.zstack.sdk.BareMetal2BillingInventory"); + put("org.zstack.billing.generator.dgpu.DGpuBillingInventory", "org.zstack.sdk.DGpuBillingInventory"); put("org.zstack.billing.generator.pcidevice.PciDeviceBillingInventory", "org.zstack.sdk.PciDeviceBillingInventory"); put("org.zstack.billing.generator.pubip.vip.PubIpVipBandwidthInBillingInventory", "org.zstack.sdk.PubIpVipBandwidthInBillingInventory"); put("org.zstack.billing.generator.pubip.vip.PubIpVipBandwidthOutBillingInventory", "org.zstack.sdk.PubIpVipBandwidthOutBillingInventory"); @@ -101,6 +112,8 @@ public class SourceClassMap { put("org.zstack.billing.spendingcalculator.baremetal2.BareMetal2Spending", "org.zstack.sdk.BareMetal2Spending"); put("org.zstack.billing.spendingcalculator.baremetal2.BareMetal2SpendingDetails", "org.zstack.sdk.BareMetal2SpendingDetails"); put("org.zstack.billing.spendingcalculator.baremetal2.PriceBareMetal2ChassisOfferingRefInventory", "org.zstack.sdk.PriceBareMetal2ChassisOfferingRefInventory"); + put("org.zstack.billing.spendingcalculator.dgpu.DGpuSpending", "org.zstack.sdk.DGpuSpending"); + put("org.zstack.billing.spendingcalculator.dgpu.DGpuSpendingInventory", "org.zstack.sdk.DGpuSpendingInventory"); put("org.zstack.billing.spendingcalculator.pcidevice.PciDeviceSpending", "org.zstack.sdk.PciDeviceSpending"); put("org.zstack.billing.spendingcalculator.pcidevice.PciDeviceSpendingInventory", "org.zstack.sdk.PciDeviceSpendingInventory"); put("org.zstack.billing.spendingcalculator.pcidevice.PricePciDeviceOfferingRefInventory", "org.zstack.sdk.PricePciDeviceOfferingRefInventory"); @@ -187,6 +200,7 @@ public class SourceClassMap { put("org.zstack.guesttools.GuestVmScriptInventory", "org.zstack.sdk.GuestVmScriptInventory"); put("org.zstack.guesttools.InvocationRecord", "org.zstack.sdk.InvocationRecord"); put("org.zstack.guesttools.InvocationRecordDetail", "org.zstack.sdk.InvocationRecordDetail"); + put("org.zstack.ha.HaNetworkGroupInventory", "org.zstack.sdk.HaNetworkGroupInventory"); put("org.zstack.ha.HaStrategyConditionInventory", "org.zstack.sdk.HaStrategyConditionInventory"); put("org.zstack.header.acl.AccessControlListEntryInventory", "org.zstack.sdk.AccessControlListEntryInventory"); put("org.zstack.header.acl.AccessControlListInventory", "org.zstack.sdk.AccessControlListInventory"); @@ -614,6 +628,11 @@ public class SourceClassMap { put("org.zstack.network.service.virtualrouter.VirtualRouterOfferingInventory", "org.zstack.sdk.VirtualRouterOfferingInventory"); put("org.zstack.network.service.virtualrouter.VirtualRouterSoftwareVersionInventory", "org.zstack.sdk.VirtualRouterSoftwareVersionInventory"); put("org.zstack.network.service.virtualrouter.VirtualRouterVmInventory", "org.zstack.sdk.VirtualRouterVmInventory"); + put("org.zstack.network.zns.L2GeneveNetworkInventory", "org.zstack.sdk.network.zns.L2GeneveNetworkInventory"); + put("org.zstack.network.zns.ZnsControllerInventory", "org.zstack.sdk.network.zns.ZnsControllerInventory"); + put("org.zstack.network.zns.ZnsTenantInventory", "org.zstack.sdk.network.zns.ZnsTenantInventory"); + put("org.zstack.network.zns.ZnsTenantRouterInventory", "org.zstack.sdk.network.zns.ZnsTenantRouterInventory"); + put("org.zstack.network.zns.ZnsTransportZoneInventory", "org.zstack.sdk.network.zns.ZnsTransportZoneInventory"); put("org.zstack.observabilityServer.ObservabilityServerOfferingInventory", "org.zstack.sdk.ObservabilityServerOfferingInventory"); put("org.zstack.observabilityServer.ObservabilityServerVmInventory", "org.zstack.sdk.ObservabilityServerVmInventory"); put("org.zstack.observabilityServer.service.ObservabilityServerServiceDataInventory", "org.zstack.sdk.ObservabilityServerServiceDataInventory"); @@ -921,6 +940,13 @@ public class SourceClassMap { put("org.zstack.sdk.AffinityGroupInventory", "org.zstack.header.affinitygroup.AffinityGroupInventory"); put("org.zstack.sdk.AffinityGroupUsageInventory", "org.zstack.header.affinitygroup.AffinityGroupUsageInventory"); put("org.zstack.sdk.AgentVersionInventory", "org.zstack.core.upgrade.AgentVersionInventory"); + put("org.zstack.sdk.AiHostCacheStorageInventory", "org.zstack.ai.entity.AiHostCacheStorageInventory"); + put("org.zstack.sdk.AiHostCacheStorageStatus", "org.zstack.ai.entity.AiHostCacheStorageStatus"); + put("org.zstack.sdk.AiHostModelCacheFailureCode", "org.zstack.ai.entity.AiHostModelCacheFailureCode"); + put("org.zstack.sdk.AiHostModelCacheFailurePhase", "org.zstack.ai.entity.AiHostModelCacheFailurePhase"); + put("org.zstack.sdk.AiHostModelCacheInventory", "org.zstack.ai.entity.AiHostModelCacheInventory"); + put("org.zstack.sdk.AiHostModelCachePolicyInventory", "org.zstack.ai.entity.AiHostModelCachePolicyInventory"); + put("org.zstack.sdk.AiHostModelCacheStatus", "org.zstack.ai.entity.AiHostModelCacheStatus"); put("org.zstack.sdk.AiSiNoSecretResourcePoolInventory", "org.zstack.crypto.securitymachine.thirdparty.aisino.AiSiNoSecretResourcePoolInventory"); put("org.zstack.sdk.AlertInventory", "org.zstack.monitoring.AlertInventory"); put("org.zstack.sdk.AliyunDiskInventory", "org.zstack.header.aliyun.storage.disk.AliyunDiskInventory"); @@ -1010,6 +1036,7 @@ public class SourceClassMap { put("org.zstack.sdk.CbtTaskResourceRefInventory", "org.zstack.header.cbt.CbtTaskResourceRefInventory"); put("org.zstack.sdk.CbtTaskStatus", "org.zstack.header.cbt.CbtTaskStatus"); put("org.zstack.sdk.CdRomTO", "org.zstack.kvm.KVMAgentCommands$CdRomTO"); + put("org.zstack.sdk.CdnModelServiceTemplateInventory", "org.zstack.ai.entity.CdnModelServiceTemplateInventory"); put("org.zstack.sdk.CdpPolicyInventory", "org.zstack.header.storage.cdp.CdpPolicyInventory"); put("org.zstack.sdk.CdpPolicyState", "org.zstack.header.storage.cdp.CdpPolicyState"); put("org.zstack.sdk.CdpTaskInventory", "org.zstack.header.storage.cdp.CdpTaskInventory"); @@ -1048,9 +1075,12 @@ public class SourceClassMap { put("org.zstack.sdk.CpuMemoryCapacityData", "org.zstack.header.allocator.datatypes.CpuMemoryCapacityData"); put("org.zstack.sdk.CreateDataVolumeTemplateFromVolumeSnapshotFailure", "org.zstack.header.image.APICreateDataVolumeTemplateFromVolumeSnapshotEvent$Failure"); put("org.zstack.sdk.CreateRootVolumeTemplateFromVolumeSnapshotFailure", "org.zstack.header.image.APICreateRootVolumeTemplateFromVolumeSnapshotEvent$Failure"); + put("org.zstack.sdk.DGpuBillingInventory", "org.zstack.billing.generator.dgpu.DGpuBillingInventory"); put("org.zstack.sdk.DGpuDeviceInventory", "org.zstack.pciDevice.gpu.dgpu.DGpuDeviceInventory"); put("org.zstack.sdk.DGpuProfileInventory", "org.zstack.pciDevice.gpu.dgpu.DGpuProfileInventory"); put("org.zstack.sdk.DGpuSpecStatsInventory", "org.zstack.pciDevice.gpu.dgpu.DGpuSpecStatsInventory"); + put("org.zstack.sdk.DGpuSpending", "org.zstack.billing.spendingcalculator.dgpu.DGpuSpending"); + put("org.zstack.sdk.DGpuSpendingInventory", "org.zstack.billing.spendingcalculator.dgpu.DGpuSpendingInventory"); put("org.zstack.sdk.DGpuStatus", "org.zstack.pciDevice.gpu.dgpu.DGpuStatus"); put("org.zstack.sdk.DRSAdviceInventory", "org.zstack.drs.entity.DRSAdviceInventory"); put("org.zstack.sdk.DRSVmMigrationActivityInventory", "org.zstack.drs.entity.DRSVmMigrationActivityInventory"); @@ -1124,6 +1154,7 @@ public class SourceClassMap { put("org.zstack.sdk.GuestVmScriptExecutedRecordInventory", "org.zstack.guesttools.GuestVmScriptExecutedRecordInventory"); put("org.zstack.sdk.GuestVmScriptInventory", "org.zstack.guesttools.GuestVmScriptInventory"); put("org.zstack.sdk.H3cSdnControllerTenantInventory", "org.zstack.sdnController.header.H3cSdnControllerTenantInventory"); + put("org.zstack.sdk.HaNetworkGroupInventory", "org.zstack.ha.HaNetworkGroupInventory"); put("org.zstack.sdk.HaStrategyConditionInventory", "org.zstack.ha.HaStrategyConditionInventory"); put("org.zstack.sdk.HaiTaiSecretResourcePoolInventory", "org.zstack.crypto.securitymachine.thirdparty.haitai.HaiTaiSecretResourcePoolInventory"); put("org.zstack.sdk.HardwareL2VxlanNetworkInventory", "org.zstack.sdnController.header.HardwareL2VxlanNetworkInventory"); @@ -1272,7 +1303,9 @@ public class SourceClassMap { put("org.zstack.sdk.ModelServiceGroupDatasetRefInventory", "org.zstack.ai.entity.ModelServiceGroupDatasetRefInventory"); put("org.zstack.sdk.ModelServiceInstanceGroupInventory", "org.zstack.ai.entity.ModelServiceInstanceGroupInventory"); put("org.zstack.sdk.ModelServiceInstanceInventory", "org.zstack.ai.entity.ModelServiceInstanceInventory"); + put("org.zstack.sdk.ModelServiceInstanceLaunchCommandInventory", "org.zstack.ai.message.ModelServiceInstanceLaunchCommandInventory"); put("org.zstack.sdk.ModelServiceInventory", "org.zstack.ai.entity.ModelServiceInventory"); + put("org.zstack.sdk.ModelServiceLaunchCommandInventory", "org.zstack.ai.message.ModelServiceLaunchCommandInventory"); put("org.zstack.sdk.ModelServiceMatchEntry", "org.zstack.ai.message.ModelServiceMatchEntry"); put("org.zstack.sdk.ModelServiceMatchEntryName", "org.zstack.ai.message.ModelServiceMatchEntryName"); put("org.zstack.sdk.ModelServiceMatchStatus", "org.zstack.ai.message.ModelServiceMatchStatus"); @@ -1698,6 +1731,11 @@ public class SourceClassMap { put("org.zstack.sdk.license.header.server.LicenseUsageDetailView", "org.zstack.license.header.server.LicenseUsageDetailView"); put("org.zstack.sdk.license.header.server.LicenseUsageView", "org.zstack.license.header.server.LicenseUsageView"); put("org.zstack.sdk.license.header.server.TotalLicenseAuthorizedCapacityView", "org.zstack.license.header.server.TotalLicenseAuthorizedCapacityView"); + put("org.zstack.sdk.network.zns.L2GeneveNetworkInventory", "org.zstack.network.zns.L2GeneveNetworkInventory"); + put("org.zstack.sdk.network.zns.ZnsControllerInventory", "org.zstack.network.zns.ZnsControllerInventory"); + put("org.zstack.sdk.network.zns.ZnsTenantInventory", "org.zstack.network.zns.ZnsTenantInventory"); + put("org.zstack.sdk.network.zns.ZnsTenantRouterInventory", "org.zstack.network.zns.ZnsTenantRouterInventory"); + put("org.zstack.sdk.network.zns.ZnsTransportZoneInventory", "org.zstack.network.zns.ZnsTransportZoneInventory"); put("org.zstack.sdk.sns.SNSAliyunSmsEndpointInventory", "org.zstack.sns.SNSAliyunSmsEndpointInventory"); put("org.zstack.sdk.sns.SNSApplicationEndpointInventory", "org.zstack.sns.SNSApplicationEndpointInventory"); put("org.zstack.sdk.sns.SNSApplicationPlatformInventory", "org.zstack.sns.SNSApplicationPlatformInventory"); diff --git a/sdk/src/main/java/org/zstack/sdk/AiHostCacheStorageInventory.java b/sdk/src/main/java/org/zstack/sdk/AiHostCacheStorageInventory.java new file mode 100644 index 00000000000..48f68d0d28d --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/AiHostCacheStorageInventory.java @@ -0,0 +1,127 @@ +package org.zstack.sdk; + +import org.zstack.sdk.AiHostCacheStorageStatus; + +public class AiHostCacheStorageInventory { + + public java.lang.String uuid; + public void setUuid(java.lang.String uuid) { + this.uuid = uuid; + } + public java.lang.String getUuid() { + return this.uuid; + } + + public java.lang.String hostUuid; + public void setHostUuid(java.lang.String hostUuid) { + this.hostUuid = hostUuid; + } + public java.lang.String getHostUuid() { + return this.hostUuid; + } + + public java.lang.String sourceRoot; + public void setSourceRoot(java.lang.String sourceRoot) { + this.sourceRoot = sourceRoot; + } + public java.lang.String getSourceRoot() { + return this.sourceRoot; + } + + public java.lang.Long physicalTotalBytes; + public void setPhysicalTotalBytes(java.lang.Long physicalTotalBytes) { + this.physicalTotalBytes = physicalTotalBytes; + } + public java.lang.Long getPhysicalTotalBytes() { + return this.physicalTotalBytes; + } + + public java.lang.Long physicalAvailableBytes; + public void setPhysicalAvailableBytes(java.lang.Long physicalAvailableBytes) { + this.physicalAvailableBytes = physicalAvailableBytes; + } + public java.lang.Long getPhysicalAvailableBytes() { + return this.physicalAvailableBytes; + } + + public java.lang.Long policyUsedBytes; + public void setPolicyUsedBytes(java.lang.Long policyUsedBytes) { + this.policyUsedBytes = policyUsedBytes; + } + public java.lang.Long getPolicyUsedBytes() { + return this.policyUsedBytes; + } + + public java.lang.Long unmanagedUsedBytesEstimate; + public void setUnmanagedUsedBytesEstimate(java.lang.Long unmanagedUsedBytesEstimate) { + this.unmanagedUsedBytesEstimate = unmanagedUsedBytesEstimate; + } + public java.lang.Long getUnmanagedUsedBytesEstimate() { + return this.unmanagedUsedBytesEstimate; + } + + public java.lang.Long policyReservedBytes; + public void setPolicyReservedBytes(java.lang.Long policyReservedBytes) { + this.policyReservedBytes = policyReservedBytes; + } + public java.lang.Long getPolicyReservedBytes() { + return this.policyReservedBytes; + } + + public java.lang.Long policyMaxSizeBytes; + public void setPolicyMaxSizeBytes(java.lang.Long policyMaxSizeBytes) { + this.policyMaxSizeBytes = policyMaxSizeBytes; + } + public java.lang.Long getPolicyMaxSizeBytes() { + return this.policyMaxSizeBytes; + } + + public java.lang.Long effectiveAvailableBytes; + public void setEffectiveAvailableBytes(java.lang.Long effectiveAvailableBytes) { + this.effectiveAvailableBytes = effectiveAvailableBytes; + } + public java.lang.Long getEffectiveAvailableBytes() { + return this.effectiveAvailableBytes; + } + + public java.lang.Long highWatermarkBytes; + public void setHighWatermarkBytes(java.lang.Long highWatermarkBytes) { + this.highWatermarkBytes = highWatermarkBytes; + } + public java.lang.Long getHighWatermarkBytes() { + return this.highWatermarkBytes; + } + + public java.lang.Long lowWatermarkBytes; + public void setLowWatermarkBytes(java.lang.Long lowWatermarkBytes) { + this.lowWatermarkBytes = lowWatermarkBytes; + } + public java.lang.Long getLowWatermarkBytes() { + return this.lowWatermarkBytes; + } + + public AiHostCacheStorageStatus status; + public void setStatus(AiHostCacheStorageStatus status) { + this.status = status; + } + public AiHostCacheStorageStatus getStatus() { + return this.status; + } + + public java.lang.String statusReason; + public void setStatusReason(java.lang.String statusReason) { + this.statusReason = statusReason; + } + public java.lang.String getStatusReason() { + return this.statusReason; + } + + public java.sql.Timestamp lastSyncDate; + public void setLastSyncDate(java.sql.Timestamp lastSyncDate) { + this.lastSyncDate = lastSyncDate; + } + public java.sql.Timestamp getLastSyncDate() { + return this.lastSyncDate; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/AiHostCacheStorageStatus.java b/sdk/src/main/java/org/zstack/sdk/AiHostCacheStorageStatus.java new file mode 100644 index 00000000000..836b25f8ddb --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/AiHostCacheStorageStatus.java @@ -0,0 +1,9 @@ +package org.zstack.sdk; + +public enum AiHostCacheStorageStatus { + Healthy, + Unknown, + PhysicalInsufficient, + PolicyInsufficient, + Disabled, +} diff --git a/sdk/src/main/java/org/zstack/sdk/AiHostModelCacheFailureCode.java b/sdk/src/main/java/org/zstack/sdk/AiHostModelCacheFailureCode.java new file mode 100644 index 00000000000..adaf4985d4c --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/AiHostModelCacheFailureCode.java @@ -0,0 +1,11 @@ +package org.zstack.sdk; + +public enum AiHostModelCacheFailureCode { + JuicefsMountFailed, + JuicefsWarmupFailed, + InsufficientHostCacheStorage, + SourcePathInvalid, + PermissionDenied, + AgentTimeout, + Unknown, +} diff --git a/sdk/src/main/java/org/zstack/sdk/AiHostModelCacheFailurePhase.java b/sdk/src/main/java/org/zstack/sdk/AiHostModelCacheFailurePhase.java new file mode 100644 index 00000000000..15ec07a58b4 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/AiHostModelCacheFailurePhase.java @@ -0,0 +1,10 @@ +package org.zstack.sdk; + +public enum AiHostModelCacheFailurePhase { + ModelSourceMount, + ModelSourceWarmup, + PreparedSourceValidation, + CapacityCheck, + AgentExecution, + Unknown, +} diff --git a/sdk/src/main/java/org/zstack/sdk/AiHostModelCacheInventory.java b/sdk/src/main/java/org/zstack/sdk/AiHostModelCacheInventory.java new file mode 100644 index 00000000000..2c8b5fbba80 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/AiHostModelCacheInventory.java @@ -0,0 +1,177 @@ +package org.zstack.sdk; + +import org.zstack.sdk.AiHostModelCacheStatus; +import org.zstack.sdk.AiHostModelCacheFailurePhase; +import org.zstack.sdk.AiHostModelCacheFailureCode; + +public class AiHostModelCacheInventory { + + public java.lang.String uuid; + public void setUuid(java.lang.String uuid) { + this.uuid = uuid; + } + public java.lang.String getUuid() { + return this.uuid; + } + + public java.lang.String hostUuid; + public void setHostUuid(java.lang.String hostUuid) { + this.hostUuid = hostUuid; + } + public java.lang.String getHostUuid() { + return this.hostUuid; + } + + public java.lang.String modelCenterUuid; + public void setModelCenterUuid(java.lang.String modelCenterUuid) { + this.modelCenterUuid = modelCenterUuid; + } + public java.lang.String getModelCenterUuid() { + return this.modelCenterUuid; + } + + public java.lang.String modelUuid; + public void setModelUuid(java.lang.String modelUuid) { + this.modelUuid = modelUuid; + } + public java.lang.String getModelUuid() { + return this.modelUuid; + } + + public java.lang.String sourceRoot; + public void setSourceRoot(java.lang.String sourceRoot) { + this.sourceRoot = sourceRoot; + } + public java.lang.String getSourceRoot() { + return this.sourceRoot; + } + + public java.lang.String sourcePath; + public void setSourcePath(java.lang.String sourcePath) { + this.sourcePath = sourcePath; + } + public java.lang.String getSourcePath() { + return this.sourcePath; + } + + public java.lang.Long sizeBytes; + public void setSizeBytes(java.lang.Long sizeBytes) { + this.sizeBytes = sizeBytes; + } + public java.lang.Long getSizeBytes() { + return this.sizeBytes; + } + + public java.lang.Long sourceMtime; + public void setSourceMtime(java.lang.Long sourceMtime) { + this.sourceMtime = sourceMtime; + } + public java.lang.Long getSourceMtime() { + return this.sourceMtime; + } + + public java.lang.String checksum; + public void setChecksum(java.lang.String checksum) { + this.checksum = checksum; + } + public java.lang.String getChecksum() { + return this.checksum; + } + + public java.lang.String contentVersion; + public void setContentVersion(java.lang.String contentVersion) { + this.contentVersion = contentVersion; + } + public java.lang.String getContentVersion() { + return this.contentVersion; + } + + public java.lang.String identityHash; + public void setIdentityHash(java.lang.String identityHash) { + this.identityHash = identityHash; + } + public java.lang.String getIdentityHash() { + return this.identityHash; + } + + public AiHostModelCacheStatus status; + public void setStatus(AiHostModelCacheStatus status) { + this.status = status; + } + public AiHostModelCacheStatus getStatus() { + return this.status; + } + + public long desiredRefCount; + public void setDesiredRefCount(long desiredRefCount) { + this.desiredRefCount = desiredRefCount; + } + public long getDesiredRefCount() { + return this.desiredRefCount; + } + + public long runningRefCount; + public void setRunningRefCount(long runningRefCount) { + this.runningRefCount = runningRefCount; + } + public long getRunningRefCount() { + return this.runningRefCount; + } + + public java.lang.String reservationUuid; + public void setReservationUuid(java.lang.String reservationUuid) { + this.reservationUuid = reservationUuid; + } + public java.lang.String getReservationUuid() { + return this.reservationUuid; + } + + public java.lang.Integer waiterCount; + public void setWaiterCount(java.lang.Integer waiterCount) { + this.waiterCount = waiterCount; + } + public java.lang.Integer getWaiterCount() { + return this.waiterCount; + } + + public java.sql.Timestamp lastAccessDate; + public void setLastAccessDate(java.sql.Timestamp lastAccessDate) { + this.lastAccessDate = lastAccessDate; + } + public java.sql.Timestamp getLastAccessDate() { + return this.lastAccessDate; + } + + public java.sql.Timestamp lastSyncDate; + public void setLastSyncDate(java.sql.Timestamp lastSyncDate) { + this.lastSyncDate = lastSyncDate; + } + public java.sql.Timestamp getLastSyncDate() { + return this.lastSyncDate; + } + + public AiHostModelCacheFailurePhase failurePhase; + public void setFailurePhase(AiHostModelCacheFailurePhase failurePhase) { + this.failurePhase = failurePhase; + } + public AiHostModelCacheFailurePhase getFailurePhase() { + return this.failurePhase; + } + + public AiHostModelCacheFailureCode failureCode; + public void setFailureCode(AiHostModelCacheFailureCode failureCode) { + this.failureCode = failureCode; + } + public AiHostModelCacheFailureCode getFailureCode() { + return this.failureCode; + } + + public java.lang.String failureMessage; + public void setFailureMessage(java.lang.String failureMessage) { + this.failureMessage = failureMessage; + } + public java.lang.String getFailureMessage() { + return this.failureMessage; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/AiHostModelCachePolicyInventory.java b/sdk/src/main/java/org/zstack/sdk/AiHostModelCachePolicyInventory.java new file mode 100644 index 00000000000..1e424e7ca01 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/AiHostModelCachePolicyInventory.java @@ -0,0 +1,71 @@ +package org.zstack.sdk; + + + +public class AiHostModelCachePolicyInventory { + + public java.lang.String uuid; + public void setUuid(java.lang.String uuid) { + this.uuid = uuid; + } + public java.lang.String getUuid() { + return this.uuid; + } + + public java.lang.String hostUuid; + public void setHostUuid(java.lang.String hostUuid) { + this.hostUuid = hostUuid; + } + public java.lang.String getHostUuid() { + return this.hostUuid; + } + + public java.lang.String sourceRoot; + public void setSourceRoot(java.lang.String sourceRoot) { + this.sourceRoot = sourceRoot; + } + public java.lang.String getSourceRoot() { + return this.sourceRoot; + } + + public java.lang.Boolean enabled; + public void setEnabled(java.lang.Boolean enabled) { + this.enabled = enabled; + } + public java.lang.Boolean getEnabled() { + return this.enabled; + } + + public java.lang.Long maxSizeBytes; + public void setMaxSizeBytes(java.lang.Long maxSizeBytes) { + this.maxSizeBytes = maxSizeBytes; + } + public java.lang.Long getMaxSizeBytes() { + return this.maxSizeBytes; + } + + public java.lang.Integer highWatermarkPercent; + public void setHighWatermarkPercent(java.lang.Integer highWatermarkPercent) { + this.highWatermarkPercent = highWatermarkPercent; + } + public java.lang.Integer getHighWatermarkPercent() { + return this.highWatermarkPercent; + } + + public java.lang.Integer lowWatermarkPercent; + public void setLowWatermarkPercent(java.lang.Integer lowWatermarkPercent) { + this.lowWatermarkPercent = lowWatermarkPercent; + } + public java.lang.Integer getLowWatermarkPercent() { + return this.lowWatermarkPercent; + } + + public java.lang.String disabledReason; + public void setDisabledReason(java.lang.String disabledReason) { + this.disabledReason = disabledReason; + } + public java.lang.String getDisabledReason() { + return this.disabledReason; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/AiHostModelCacheStatus.java b/sdk/src/main/java/org/zstack/sdk/AiHostModelCacheStatus.java new file mode 100644 index 00000000000..7372bc3a0a1 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/AiHostModelCacheStatus.java @@ -0,0 +1,9 @@ +package org.zstack.sdk; + +public enum AiHostModelCacheStatus { + Preparing, + Ready, + Failed, + Unknown, + Cleaning, +} diff --git a/sdk/src/main/java/org/zstack/sdk/ArchitectureImageMapping.java b/sdk/src/main/java/org/zstack/sdk/ArchitectureImageMapping.java index bcce51854c0..28780208132 100644 --- a/sdk/src/main/java/org/zstack/sdk/ArchitectureImageMapping.java +++ b/sdk/src/main/java/org/zstack/sdk/ArchitectureImageMapping.java @@ -4,6 +4,14 @@ public class ArchitectureImageMapping { + public java.lang.String templateName; + public void setTemplateName(java.lang.String templateName) { + this.templateName = templateName; + } + public java.lang.String getTemplateName() { + return this.templateName; + } + public java.lang.String cpuArchitecture; public void setCpuArchitecture(java.lang.String cpuArchitecture) { this.cpuArchitecture = cpuArchitecture; @@ -12,6 +20,22 @@ public java.lang.String getCpuArchitecture() { return this.cpuArchitecture; } + public java.lang.String gpuVendor; + public void setGpuVendor(java.lang.String gpuVendor) { + this.gpuVendor = gpuVendor; + } + public java.lang.String getGpuVendor() { + return this.gpuVendor; + } + + public java.lang.String acceleratorType; + public void setAcceleratorType(java.lang.String acceleratorType) { + this.acceleratorType = acceleratorType; + } + public java.lang.String getAcceleratorType() { + return this.acceleratorType; + } + public java.lang.String vmImageUuid; public void setVmImageUuid(java.lang.String vmImageUuid) { this.vmImageUuid = vmImageUuid; @@ -20,6 +44,14 @@ public java.lang.String getVmImageUuid() { return this.vmImageUuid; } + public java.lang.String imageNamePattern; + public void setImageNamePattern(java.lang.String imageNamePattern) { + this.imageNamePattern = imageNamePattern; + } + public java.lang.String getImageNamePattern() { + return this.imageNamePattern; + } + public java.lang.String dockerImage; public void setDockerImage(java.lang.String dockerImage) { this.dockerImage = dockerImage; diff --git a/sdk/src/main/java/org/zstack/sdk/SetVmDGpuStrategyAction.java b/sdk/src/main/java/org/zstack/sdk/AttachDGpuToVmAction.java similarity index 88% rename from sdk/src/main/java/org/zstack/sdk/SetVmDGpuStrategyAction.java rename to sdk/src/main/java/org/zstack/sdk/AttachDGpuToVmAction.java index e8f773e19de..b28b8364e6d 100644 --- a/sdk/src/main/java/org/zstack/sdk/SetVmDGpuStrategyAction.java +++ b/sdk/src/main/java/org/zstack/sdk/AttachDGpuToVmAction.java @@ -4,7 +4,7 @@ import java.util.Map; import org.zstack.sdk.*; -public class SetVmDGpuStrategyAction extends AbstractAction { +public class AttachDGpuToVmAction extends AbstractAction { private static final HashMap parameterMap = new HashMap<>(); @@ -12,7 +12,7 @@ public class SetVmDGpuStrategyAction extends AbstractAction { public static class Result { public ErrorCode error; - public org.zstack.sdk.SetVmDGpuStrategyResult value; + public org.zstack.sdk.AttachDGpuToVmResult value; public Result throwExceptionIfError() { if (error != null) { @@ -72,8 +72,8 @@ private Result makeResult(ApiResult res) { return ret; } - org.zstack.sdk.SetVmDGpuStrategyResult value = res.getResult(org.zstack.sdk.SetVmDGpuStrategyResult.class); - ret.value = value == null ? new org.zstack.sdk.SetVmDGpuStrategyResult() : value; + org.zstack.sdk.AttachDGpuToVmResult value = res.getResult(org.zstack.sdk.AttachDGpuToVmResult.class); + ret.value = value == null ? new org.zstack.sdk.AttachDGpuToVmResult() : value; return ret; } @@ -106,7 +106,7 @@ protected RestInfo getRestInfo() { info.path = "/vm-instances/{vmInstanceUuid}/actions"; info.needSession = true; info.needPoll = true; - info.parameterName = "setVmDGpuStrategy"; + info.parameterName = "attachDGpuToVm"; return info; } diff --git a/sdk/src/main/java/org/zstack/sdk/AttachDGpuToVmResult.java b/sdk/src/main/java/org/zstack/sdk/AttachDGpuToVmResult.java new file mode 100644 index 00000000000..a3a4d2b2105 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/AttachDGpuToVmResult.java @@ -0,0 +1,14 @@ +package org.zstack.sdk; + +import org.zstack.sdk.DGpuDeviceInventory; + +public class AttachDGpuToVmResult { + public DGpuDeviceInventory inventory; + public void setInventory(DGpuDeviceInventory inventory) { + this.inventory = inventory; + } + public DGpuDeviceInventory getInventory() { + return this.inventory; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/AutoMatchModelServiceByModelResult.java b/sdk/src/main/java/org/zstack/sdk/AutoMatchModelServiceByModelResult.java index 9d53b9056fb..e22320fa2c6 100644 --- a/sdk/src/main/java/org/zstack/sdk/AutoMatchModelServiceByModelResult.java +++ b/sdk/src/main/java/org/zstack/sdk/AutoMatchModelServiceByModelResult.java @@ -28,4 +28,12 @@ public MatchEvidence getEvidence() { return this.evidence; } + public java.lang.String recommendedGpuSpecUuid; + public void setRecommendedGpuSpecUuid(java.lang.String recommendedGpuSpecUuid) { + this.recommendedGpuSpecUuid = recommendedGpuSpecUuid; + } + public java.lang.String getRecommendedGpuSpecUuid() { + return this.recommendedGpuSpecUuid; + } + } diff --git a/sdk/src/main/java/org/zstack/sdk/CalculateResourceSpendingAction.java b/sdk/src/main/java/org/zstack/sdk/CalculateResourceSpendingAction.java index 09a374d09b4..b8095f060d3 100644 --- a/sdk/src/main/java/org/zstack/sdk/CalculateResourceSpendingAction.java +++ b/sdk/src/main/java/org/zstack/sdk/CalculateResourceSpendingAction.java @@ -25,7 +25,7 @@ public Result throwExceptionIfError() { } } - @Param(required = false, validValues = {"VM","cpu","memory","rootVolume","dataVolume","snapShot","gpu","pubIpVipBandwidth","pubIpVipBandwidthIn","pubIpVipBandwidthOut","pubIpVmNicBandwidth","pubIpVmNicBandwidthIn","pubIpVmNicBandwidthOut","bareMetal2Instance","all"}, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + @Param(required = false, validValues = {"VM","cpu","memory","rootVolume","dataVolume","snapShot","gpu","dgpu","pubIpVipBandwidth","pubIpVipBandwidthIn","pubIpVipBandwidthOut","pubIpVmNicBandwidth","pubIpVmNicBandwidthIn","pubIpVmNicBandwidthOut","bareMetal2Instance","all"}, nonempty = false, nullElements = false, emptyString = true, noTrim = false) public java.lang.String resourceType; @Param(required = false, nonempty = false, nullElements = false, emptyString = true, noTrim = false) diff --git a/sdk/src/main/java/org/zstack/sdk/CdnModelServiceTemplateInventory.java b/sdk/src/main/java/org/zstack/sdk/CdnModelServiceTemplateInventory.java new file mode 100644 index 00000000000..a9e46573017 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/CdnModelServiceTemplateInventory.java @@ -0,0 +1,127 @@ +package org.zstack.sdk; + + + +public class CdnModelServiceTemplateInventory { + + public java.lang.String uuid; + public void setUuid(java.lang.String uuid) { + this.uuid = uuid; + } + public java.lang.String getUuid() { + return this.uuid; + } + + public java.lang.String name; + public void setName(java.lang.String name) { + this.name = name; + } + public java.lang.String getName() { + return this.name; + } + + public java.lang.String version; + public void setVersion(java.lang.String version) { + this.version = version; + } + public java.lang.String getVersion() { + return this.version; + } + + public java.lang.String platform; + public void setPlatform(java.lang.String platform) { + this.platform = platform; + } + public java.lang.String getPlatform() { + return this.platform; + } + + public java.lang.String framework; + public void setFramework(java.lang.String framework) { + this.framework = framework; + } + public java.lang.String getFramework() { + return this.framework; + } + + public java.lang.String gpuVendor; + public void setGpuVendor(java.lang.String gpuVendor) { + this.gpuVendor = gpuVendor; + } + public java.lang.String getGpuVendor() { + return this.gpuVendor; + } + + public java.lang.Long size; + public void setSize(java.lang.Long size) { + this.size = size; + } + public java.lang.Long getSize() { + return this.size; + } + + public java.lang.String projectId; + public void setProjectId(java.lang.String projectId) { + this.projectId = projectId; + } + public java.lang.String getProjectId() { + return this.projectId; + } + + public java.lang.String projectName; + public void setProjectName(java.lang.String projectName) { + this.projectName = projectName; + } + public java.lang.String getProjectName() { + return this.projectName; + } + + public java.lang.String downloadUrl; + public void setDownloadUrl(java.lang.String downloadUrl) { + this.downloadUrl = downloadUrl; + } + public java.lang.String getDownloadUrl() { + return this.downloadUrl; + } + + public boolean installed; + public void setInstalled(boolean installed) { + this.installed = installed; + } + public boolean getInstalled() { + return this.installed; + } + + public java.lang.String modelServiceUuid; + public void setModelServiceUuid(java.lang.String modelServiceUuid) { + this.modelServiceUuid = modelServiceUuid; + } + public java.lang.String getModelServiceUuid() { + return this.modelServiceUuid; + } + + public long usingServiceCount; + public void setUsingServiceCount(long usingServiceCount) { + this.usingServiceCount = usingServiceCount; + } + public long getUsingServiceCount() { + return this.usingServiceCount; + } + + public java.sql.Timestamp createDate; + public void setCreateDate(java.sql.Timestamp createDate) { + this.createDate = createDate; + } + public java.sql.Timestamp getCreateDate() { + return this.createDate; + } + + public java.sql.Timestamp lastOpDate; + public void setLastOpDate(java.sql.Timestamp lastOpDate) { + this.lastOpDate = lastOpDate; + } + public java.sql.Timestamp getLastOpDate() { + return this.lastOpDate; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/ChangeHaNetworkGroupStateAction.java b/sdk/src/main/java/org/zstack/sdk/ChangeHaNetworkGroupStateAction.java new file mode 100644 index 00000000000..81cd9a1925c --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/ChangeHaNetworkGroupStateAction.java @@ -0,0 +1,104 @@ +package org.zstack.sdk; + +import java.util.HashMap; +import java.util.Map; +import org.zstack.sdk.*; + +public class ChangeHaNetworkGroupStateAction extends AbstractAction { + + private static final HashMap parameterMap = new HashMap<>(); + + private static final HashMap nonAPIParameterMap = new HashMap<>(); + + public static class Result { + public ErrorCode error; + public org.zstack.sdk.ChangeHaNetworkGroupStateResult value; + + public Result throwExceptionIfError() { + if (error != null) { + throw new ApiException( + String.format("error[code: %s, description: %s, details: %s, globalErrorCode: %s]", error.code, error.description, error.details, error.globalErrorCode) + ); + } + + return this; + } + } + + @Param(required = true, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String uuid; + + @Param(required = true, validValues = {"enable","disable"}, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String stateEvent; + + @Param(required = false) + public java.util.List systemTags; + + @Param(required = false) + public java.util.List userTags; + + @Param(required = false) + public String sessionId; + + @Param(required = false) + public String accessKeyId; + + @Param(required = false) + public String accessKeySecret; + + @Param(required = false) + public String requestIp; + + @NonAPIParam + public long timeout = -1; + + @NonAPIParam + public long pollingInterval = -1; + + + private Result makeResult(ApiResult res) { + Result ret = new Result(); + if (res.error != null) { + ret.error = res.error; + return ret; + } + + org.zstack.sdk.ChangeHaNetworkGroupStateResult value = res.getResult(org.zstack.sdk.ChangeHaNetworkGroupStateResult.class); + ret.value = value == null ? new org.zstack.sdk.ChangeHaNetworkGroupStateResult() : value; + + return ret; + } + + public Result call() { + ApiResult res = ZSClient.call(this); + return makeResult(res); + } + + public void call(final Completion completion) { + ZSClient.call(this, new InternalCompletion() { + @Override + public void complete(ApiResult res) { + completion.complete(makeResult(res)); + } + }); + } + + protected Map getParameterMap() { + return parameterMap; + } + + protected Map getNonAPIParameterMap() { + return nonAPIParameterMap; + } + + protected RestInfo getRestInfo() { + RestInfo info = new RestInfo(); + info.httpMethod = "PUT"; + info.path = "/ha/network-groups/{uuid}/actions"; + info.needSession = true; + info.needPoll = true; + info.parameterName = "changeHaNetworkGroupState"; + return info; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/ChangeHaNetworkGroupStateResult.java b/sdk/src/main/java/org/zstack/sdk/ChangeHaNetworkGroupStateResult.java new file mode 100644 index 00000000000..b579aa5771d --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/ChangeHaNetworkGroupStateResult.java @@ -0,0 +1,14 @@ +package org.zstack.sdk; + +import org.zstack.sdk.HaNetworkGroupInventory; + +public class ChangeHaNetworkGroupStateResult { + public HaNetworkGroupInventory inventory; + public void setInventory(HaNetworkGroupInventory inventory) { + this.inventory = inventory; + } + public HaNetworkGroupInventory getInventory() { + return this.inventory; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/ChangeLoadBalancerListenerAction.java b/sdk/src/main/java/org/zstack/sdk/ChangeLoadBalancerListenerAction.java index 3c056c8af77..b5314b49922 100644 --- a/sdk/src/main/java/org/zstack/sdk/ChangeLoadBalancerListenerAction.java +++ b/sdk/src/main/java/org/zstack/sdk/ChangeLoadBalancerListenerAction.java @@ -49,7 +49,7 @@ public Result throwExceptionIfError() { @Param(required = false, nonempty = false, nullElements = false, emptyString = true, numberRange = {1L,2147483647L}, noTrim = false) public java.lang.Integer healthCheckInterval; - @Param(required = false, validValues = {"tcp","udp","http"}, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + @Param(required = false, validValues = {"tcp","udp","http","none"}, nonempty = false, nullElements = false, emptyString = true, noTrim = false) public java.lang.String healthCheckProtocol; @Param(required = false, validValues = {"GET","HEAD"}, nonempty = false, nullElements = false, emptyString = true, noTrim = false) diff --git a/sdk/src/main/java/org/zstack/sdk/CleanAiHostModelCacheAction.java b/sdk/src/main/java/org/zstack/sdk/CleanAiHostModelCacheAction.java new file mode 100644 index 00000000000..e907787f4b8 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/CleanAiHostModelCacheAction.java @@ -0,0 +1,113 @@ +package org.zstack.sdk; + +import java.util.HashMap; +import java.util.Map; +import org.zstack.sdk.*; + +public class CleanAiHostModelCacheAction extends AbstractAction { + + private static final HashMap parameterMap = new HashMap<>(); + + private static final HashMap nonAPIParameterMap = new HashMap<>(); + + public static class Result { + public ErrorCode error; + public org.zstack.sdk.CleanAiHostModelCacheResult value; + + public Result throwExceptionIfError() { + if (error != null) { + throw new ApiException( + String.format("error[code: %s, description: %s, details: %s, globalErrorCode: %s]", error.code, error.description, error.details, error.globalErrorCode) + ); + } + + return this; + } + } + + @Param(required = false, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String cacheUuid; + + @Param(required = false, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String hostUuid; + + @Param(required = false, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String modelUuid; + + @Param(required = false, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.util.List statuses; + + @Param(required = false, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.Boolean onlyUnused; + + @Param(required = false) + public java.util.List systemTags; + + @Param(required = false) + public java.util.List userTags; + + @Param(required = false) + public String sessionId; + + @Param(required = false) + public String accessKeyId; + + @Param(required = false) + public String accessKeySecret; + + @Param(required = false) + public String requestIp; + + @NonAPIParam + public long timeout = -1; + + @NonAPIParam + public long pollingInterval = -1; + + + private Result makeResult(ApiResult res) { + Result ret = new Result(); + if (res.error != null) { + ret.error = res.error; + return ret; + } + + org.zstack.sdk.CleanAiHostModelCacheResult value = res.getResult(org.zstack.sdk.CleanAiHostModelCacheResult.class); + ret.value = value == null ? new org.zstack.sdk.CleanAiHostModelCacheResult() : value; + + return ret; + } + + public Result call() { + ApiResult res = ZSClient.call(this); + return makeResult(res); + } + + public void call(final Completion completion) { + ZSClient.call(this, new InternalCompletion() { + @Override + public void complete(ApiResult res) { + completion.complete(makeResult(res)); + } + }); + } + + protected Map getParameterMap() { + return parameterMap; + } + + protected Map getNonAPIParameterMap() { + return nonAPIParameterMap; + } + + protected RestInfo getRestInfo() { + RestInfo info = new RestInfo(); + info.httpMethod = "PUT"; + info.path = "/ai/host-model-caches/actions"; + info.needSession = true; + info.needPoll = true; + info.parameterName = "cleanAiHostModelCache"; + return info; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/CleanAiHostModelCacheResult.java b/sdk/src/main/java/org/zstack/sdk/CleanAiHostModelCacheResult.java new file mode 100644 index 00000000000..a589ff41299 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/CleanAiHostModelCacheResult.java @@ -0,0 +1,30 @@ +package org.zstack.sdk; + + + +public class CleanAiHostModelCacheResult { + public java.util.List cleanedInventories; + public void setCleanedInventories(java.util.List cleanedInventories) { + this.cleanedInventories = cleanedInventories; + } + public java.util.List getCleanedInventories() { + return this.cleanedInventories; + } + + public java.util.List skippedReasons; + public void setSkippedReasons(java.util.List skippedReasons) { + this.skippedReasons = skippedReasons; + } + public java.util.List getSkippedReasons() { + return this.skippedReasons; + } + + public java.lang.Long bytesReclaimed; + public void setBytesReclaimed(java.lang.Long bytesReclaimed) { + this.bytesReclaimed = bytesReclaimed; + } + public java.lang.Long getBytesReclaimed() { + return this.bytesReclaimed; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/CreateHaNetworkGroupAction.java b/sdk/src/main/java/org/zstack/sdk/CreateHaNetworkGroupAction.java new file mode 100644 index 00000000000..4ec460f54a1 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/CreateHaNetworkGroupAction.java @@ -0,0 +1,119 @@ +package org.zstack.sdk; + +import java.util.HashMap; +import java.util.Map; +import org.zstack.sdk.*; + +public class CreateHaNetworkGroupAction extends AbstractAction { + + private static final HashMap parameterMap = new HashMap<>(); + + private static final HashMap nonAPIParameterMap = new HashMap<>(); + + public static class Result { + public ErrorCode error; + public org.zstack.sdk.CreateHaNetworkGroupResult value; + + public Result throwExceptionIfError() { + if (error != null) { + throw new ApiException( + String.format("error[code: %s, description: %s, details: %s, globalErrorCode: %s]", error.code, error.description, error.details, error.globalErrorCode) + ); + } + + return this; + } + } + + @Param(required = true, maxLength = 255, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String name; + + @Param(required = false, maxLength = 2048, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String description; + + @Param(required = true, validValues = {"Flat","Public"}, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String type; + + @Param(required = true, nonempty = false, nullElements = false, emptyString = true, numberRange = {1L,2147483647L}, noTrim = false) + public int minAvailableCount = 0; + + @Param(required = true, nonempty = true, nullElements = false, emptyString = true, noTrim = false) + public java.util.List l3NetworkUuids; + + @Param(required = false) + public java.lang.String resourceUuid; + + @Param(required = false, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.util.List tagUuids; + + @Param(required = false) + public java.util.List systemTags; + + @Param(required = false) + public java.util.List userTags; + + @Param(required = false) + public String sessionId; + + @Param(required = false) + public String accessKeyId; + + @Param(required = false) + public String accessKeySecret; + + @Param(required = false) + public String requestIp; + + @NonAPIParam + public long timeout = -1; + + @NonAPIParam + public long pollingInterval = -1; + + + private Result makeResult(ApiResult res) { + Result ret = new Result(); + if (res.error != null) { + ret.error = res.error; + return ret; + } + + org.zstack.sdk.CreateHaNetworkGroupResult value = res.getResult(org.zstack.sdk.CreateHaNetworkGroupResult.class); + ret.value = value == null ? new org.zstack.sdk.CreateHaNetworkGroupResult() : value; + + return ret; + } + + public Result call() { + ApiResult res = ZSClient.call(this); + return makeResult(res); + } + + public void call(final Completion completion) { + ZSClient.call(this, new InternalCompletion() { + @Override + public void complete(ApiResult res) { + completion.complete(makeResult(res)); + } + }); + } + + protected Map getParameterMap() { + return parameterMap; + } + + protected Map getNonAPIParameterMap() { + return nonAPIParameterMap; + } + + protected RestInfo getRestInfo() { + RestInfo info = new RestInfo(); + info.httpMethod = "POST"; + info.path = "/ha/network-groups"; + info.needSession = true; + info.needPoll = true; + info.parameterName = "params"; + return info; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/CreateHaNetworkGroupResult.java b/sdk/src/main/java/org/zstack/sdk/CreateHaNetworkGroupResult.java new file mode 100644 index 00000000000..64326458698 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/CreateHaNetworkGroupResult.java @@ -0,0 +1,14 @@ +package org.zstack.sdk; + +import org.zstack.sdk.HaNetworkGroupInventory; + +public class CreateHaNetworkGroupResult { + public HaNetworkGroupInventory inventory; + public void setInventory(HaNetworkGroupInventory inventory) { + this.inventory = inventory; + } + public HaNetworkGroupInventory getInventory() { + return this.inventory; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/CreateLoadBalancerListenerAction.java b/sdk/src/main/java/org/zstack/sdk/CreateLoadBalancerListenerAction.java index a886703d0b9..dd4399e0b0f 100644 --- a/sdk/src/main/java/org/zstack/sdk/CreateLoadBalancerListenerAction.java +++ b/sdk/src/main/java/org/zstack/sdk/CreateLoadBalancerListenerAction.java @@ -46,7 +46,7 @@ public Result throwExceptionIfError() { @Param(required = false, nonempty = false, nullElements = false, emptyString = true, noTrim = false) public java.lang.String certificateUuid; - @Param(required = false, validValues = {"tcp","udp","http"}, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + @Param(required = false, validValues = {"tcp","udp","http","none"}, nonempty = false, nullElements = false, emptyString = true, noTrim = false) public java.lang.String healthCheckProtocol; @Param(required = false, validValues = {"GET","HEAD"}, nonempty = false, nullElements = false, emptyString = true, noTrim = false) diff --git a/sdk/src/main/java/org/zstack/sdk/CreateResourcePriceAction.java b/sdk/src/main/java/org/zstack/sdk/CreateResourcePriceAction.java index 6fc1ddb04ab..61840e6b69a 100644 --- a/sdk/src/main/java/org/zstack/sdk/CreateResourcePriceAction.java +++ b/sdk/src/main/java/org/zstack/sdk/CreateResourcePriceAction.java @@ -25,7 +25,7 @@ public Result throwExceptionIfError() { } } - @Param(required = true, validValues = {"cpu","memory","rootVolume","dataVolume","snapShot","gpu","pubIpVmNicBandwidthOut","pubIpVmNicBandwidthIn","pubIpVipBandwidthOut","pubIpVipBandwidthIn","bareMetal2Instance"}, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + @Param(required = true, validValues = {"cpu","memory","rootVolume","dataVolume","snapShot","gpu","dgpu","pubIpVmNicBandwidthOut","pubIpVmNicBandwidthIn","pubIpVipBandwidthOut","pubIpVipBandwidthIn","bareMetal2Instance"}, nonempty = false, nullElements = false, emptyString = true, noTrim = false) public java.lang.String resourceName; @Param(required = false, nonempty = false, nullElements = false, emptyString = true, noTrim = false) diff --git a/sdk/src/main/java/org/zstack/sdk/DGpuBillingInventory.java b/sdk/src/main/java/org/zstack/sdk/DGpuBillingInventory.java new file mode 100644 index 00000000000..af398221700 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/DGpuBillingInventory.java @@ -0,0 +1,23 @@ +package org.zstack.sdk; + + + +public class DGpuBillingInventory extends org.zstack.sdk.BillingInventory { + + public java.lang.String vmName; + public void setVmName(java.lang.String vmName) { + this.vmName = vmName; + } + public java.lang.String getVmName() { + return this.vmName; + } + + public java.lang.Long allocatedMemory; + public void setAllocatedMemory(java.lang.Long allocatedMemory) { + this.allocatedMemory = allocatedMemory; + } + public java.lang.Long getAllocatedMemory() { + return this.allocatedMemory; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/DGpuSpending.java b/sdk/src/main/java/org/zstack/sdk/DGpuSpending.java new file mode 100644 index 00000000000..5e840f91695 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/DGpuSpending.java @@ -0,0 +1,23 @@ +package org.zstack.sdk; + + + +public class DGpuSpending extends org.zstack.sdk.SpendingDetails { + + public java.util.List sizeInventory; + public void setSizeInventory(java.util.List sizeInventory) { + this.sizeInventory = sizeInventory; + } + public java.util.List getSizeInventory() { + return this.sizeInventory; + } + + public java.lang.Long allocatedMemory; + public void setAllocatedMemory(java.lang.Long allocatedMemory) { + this.allocatedMemory = allocatedMemory; + } + public java.lang.Long getAllocatedMemory() { + return this.allocatedMemory; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/DGpuSpendingInventory.java b/sdk/src/main/java/org/zstack/sdk/DGpuSpendingInventory.java new file mode 100644 index 00000000000..656a8c95874 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/DGpuSpendingInventory.java @@ -0,0 +1,47 @@ +package org.zstack.sdk; + + + +public class DGpuSpendingInventory { + + public long startTime; + public void setStartTime(long startTime) { + this.startTime = startTime; + } + public long getStartTime() { + return this.startTime; + } + + public long endTime; + public void setEndTime(long endTime) { + this.endTime = endTime; + } + public long getEndTime() { + return this.endTime; + } + + public double spending; + public void setSpending(double spending) { + this.spending = spending; + } + public double getSpending() { + return this.spending; + } + + public java.lang.String vmName; + public void setVmName(java.lang.String vmName) { + this.vmName = vmName; + } + public java.lang.String getVmName() { + return this.vmName; + } + + public long allocatedMemory; + public void setAllocatedMemory(long allocatedMemory) { + this.allocatedMemory = allocatedMemory; + } + public long getAllocatedMemory() { + return this.allocatedMemory; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/DatasetInventory.java b/sdk/src/main/java/org/zstack/sdk/DatasetInventory.java index 69706e35dad..1aad9977472 100644 --- a/sdk/src/main/java/org/zstack/sdk/DatasetInventory.java +++ b/sdk/src/main/java/org/zstack/sdk/DatasetInventory.java @@ -52,6 +52,14 @@ public java.lang.String getModelCenterUuid() { return this.modelCenterUuid; } + public java.lang.String zoneUuid; + public void setZoneUuid(java.lang.String zoneUuid) { + this.zoneUuid = zoneUuid; + } + public java.lang.String getZoneUuid() { + return this.zoneUuid; + } + public java.lang.Long size; public void setSize(java.lang.Long size) { this.size = size; diff --git a/sdk/src/main/java/org/zstack/sdk/DeleteHaNetworkGroupAction.java b/sdk/src/main/java/org/zstack/sdk/DeleteHaNetworkGroupAction.java new file mode 100644 index 00000000000..1738b04a0e0 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/DeleteHaNetworkGroupAction.java @@ -0,0 +1,104 @@ +package org.zstack.sdk; + +import java.util.HashMap; +import java.util.Map; +import org.zstack.sdk.*; + +public class DeleteHaNetworkGroupAction extends AbstractAction { + + private static final HashMap parameterMap = new HashMap<>(); + + private static final HashMap nonAPIParameterMap = new HashMap<>(); + + public static class Result { + public ErrorCode error; + public org.zstack.sdk.DeleteHaNetworkGroupResult value; + + public Result throwExceptionIfError() { + if (error != null) { + throw new ApiException( + String.format("error[code: %s, description: %s, details: %s, globalErrorCode: %s]", error.code, error.description, error.details, error.globalErrorCode) + ); + } + + return this; + } + } + + @Param(required = true, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String uuid; + + @Param(required = false) + public java.lang.String deleteMode = "Permissive"; + + @Param(required = false) + public java.util.List systemTags; + + @Param(required = false) + public java.util.List userTags; + + @Param(required = false) + public String sessionId; + + @Param(required = false) + public String accessKeyId; + + @Param(required = false) + public String accessKeySecret; + + @Param(required = false) + public String requestIp; + + @NonAPIParam + public long timeout = -1; + + @NonAPIParam + public long pollingInterval = -1; + + + private Result makeResult(ApiResult res) { + Result ret = new Result(); + if (res.error != null) { + ret.error = res.error; + return ret; + } + + org.zstack.sdk.DeleteHaNetworkGroupResult value = res.getResult(org.zstack.sdk.DeleteHaNetworkGroupResult.class); + ret.value = value == null ? new org.zstack.sdk.DeleteHaNetworkGroupResult() : value; + + return ret; + } + + public Result call() { + ApiResult res = ZSClient.call(this); + return makeResult(res); + } + + public void call(final Completion completion) { + ZSClient.call(this, new InternalCompletion() { + @Override + public void complete(ApiResult res) { + completion.complete(makeResult(res)); + } + }); + } + + protected Map getParameterMap() { + return parameterMap; + } + + protected Map getNonAPIParameterMap() { + return nonAPIParameterMap; + } + + protected RestInfo getRestInfo() { + RestInfo info = new RestInfo(); + info.httpMethod = "DELETE"; + info.path = "/ha/network-groups/{uuid}"; + info.needSession = true; + info.needPoll = true; + info.parameterName = ""; + return info; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/DeleteHaNetworkGroupResult.java b/sdk/src/main/java/org/zstack/sdk/DeleteHaNetworkGroupResult.java new file mode 100644 index 00000000000..602e0408c62 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/DeleteHaNetworkGroupResult.java @@ -0,0 +1,7 @@ +package org.zstack.sdk; + + + +public class DeleteHaNetworkGroupResult { + +} diff --git a/sdk/src/main/java/org/zstack/sdk/GetAiHostModelCacheCapacityAction.java b/sdk/src/main/java/org/zstack/sdk/GetAiHostModelCacheCapacityAction.java new file mode 100644 index 00000000000..ea67ba722cb --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/GetAiHostModelCacheCapacityAction.java @@ -0,0 +1,95 @@ +package org.zstack.sdk; + +import java.util.HashMap; +import java.util.Map; +import org.zstack.sdk.*; + +public class GetAiHostModelCacheCapacityAction extends AbstractAction { + + private static final HashMap parameterMap = new HashMap<>(); + + private static final HashMap nonAPIParameterMap = new HashMap<>(); + + public static class Result { + public ErrorCode error; + public org.zstack.sdk.GetAiHostModelCacheCapacityResult value; + + public Result throwExceptionIfError() { + if (error != null) { + throw new ApiException( + String.format("error[code: %s, description: %s, details: %s, globalErrorCode: %s]", error.code, error.description, error.details, error.globalErrorCode) + ); + } + + return this; + } + } + + @Param(required = false, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String hostUuid; + + @Param(required = false) + public java.util.List systemTags; + + @Param(required = false) + public java.util.List userTags; + + @Param(required = false) + public String sessionId; + + @Param(required = false) + public String accessKeyId; + + @Param(required = false) + public String accessKeySecret; + + @Param(required = false) + public String requestIp; + + + private Result makeResult(ApiResult res) { + Result ret = new Result(); + if (res.error != null) { + ret.error = res.error; + return ret; + } + + org.zstack.sdk.GetAiHostModelCacheCapacityResult value = res.getResult(org.zstack.sdk.GetAiHostModelCacheCapacityResult.class); + ret.value = value == null ? new org.zstack.sdk.GetAiHostModelCacheCapacityResult() : value; + + return ret; + } + + public Result call() { + ApiResult res = ZSClient.call(this); + return makeResult(res); + } + + public void call(final Completion completion) { + ZSClient.call(this, new InternalCompletion() { + @Override + public void complete(ApiResult res) { + completion.complete(makeResult(res)); + } + }); + } + + protected Map getParameterMap() { + return parameterMap; + } + + protected Map getNonAPIParameterMap() { + return nonAPIParameterMap; + } + + protected RestInfo getRestInfo() { + RestInfo info = new RestInfo(); + info.httpMethod = "GET"; + info.path = "/ai/host-model-caches/capacities"; + info.needSession = true; + info.needPoll = false; + info.parameterName = ""; + return info; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/GetAiHostModelCacheCapacityResult.java b/sdk/src/main/java/org/zstack/sdk/GetAiHostModelCacheCapacityResult.java new file mode 100644 index 00000000000..ea127e2c772 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/GetAiHostModelCacheCapacityResult.java @@ -0,0 +1,14 @@ +package org.zstack.sdk; + + + +public class GetAiHostModelCacheCapacityResult { + public java.util.List inventories; + public void setInventories(java.util.List inventories) { + this.inventories = inventories; + } + public java.util.List getInventories() { + return this.inventories; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/GetModelServiceLaunchCommandsAction.java b/sdk/src/main/java/org/zstack/sdk/GetModelServiceLaunchCommandsAction.java new file mode 100644 index 00000000000..3300c3ac2ef --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/GetModelServiceLaunchCommandsAction.java @@ -0,0 +1,98 @@ +package org.zstack.sdk; + +import java.util.HashMap; +import java.util.Map; +import org.zstack.sdk.*; + +public class GetModelServiceLaunchCommandsAction extends AbstractAction { + + private static final HashMap parameterMap = new HashMap<>(); + + private static final HashMap nonAPIParameterMap = new HashMap<>(); + + public static class Result { + public ErrorCode error; + public org.zstack.sdk.GetModelServiceLaunchCommandsResult value; + + public Result throwExceptionIfError() { + if (error != null) { + throw new ApiException( + String.format("error[code: %s, description: %s, details: %s, globalErrorCode: %s]", error.code, error.description, error.details, error.globalErrorCode) + ); + } + + return this; + } + } + + @Param(required = false, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.util.List groupUuids; + + @Param(required = false, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.util.List instanceUuids; + + @Param(required = false) + public java.util.List systemTags; + + @Param(required = false) + public java.util.List userTags; + + @Param(required = false) + public String sessionId; + + @Param(required = false) + public String accessKeyId; + + @Param(required = false) + public String accessKeySecret; + + @Param(required = false) + public String requestIp; + + + private Result makeResult(ApiResult res) { + Result ret = new Result(); + if (res.error != null) { + ret.error = res.error; + return ret; + } + + org.zstack.sdk.GetModelServiceLaunchCommandsResult value = res.getResult(org.zstack.sdk.GetModelServiceLaunchCommandsResult.class); + ret.value = value == null ? new org.zstack.sdk.GetModelServiceLaunchCommandsResult() : value; + + return ret; + } + + public Result call() { + ApiResult res = ZSClient.call(this); + return makeResult(res); + } + + public void call(final Completion completion) { + ZSClient.call(this, new InternalCompletion() { + @Override + public void complete(ApiResult res) { + completion.complete(makeResult(res)); + } + }); + } + + protected Map getParameterMap() { + return parameterMap; + } + + protected Map getNonAPIParameterMap() { + return nonAPIParameterMap; + } + + protected RestInfo getRestInfo() { + RestInfo info = new RestInfo(); + info.httpMethod = "GET"; + info.path = "/ai/model-service-launch-commands"; + info.needSession = true; + info.needPoll = false; + info.parameterName = ""; + return info; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/GetModelServiceLaunchCommandsResult.java b/sdk/src/main/java/org/zstack/sdk/GetModelServiceLaunchCommandsResult.java new file mode 100644 index 00000000000..f4bf34bdddd --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/GetModelServiceLaunchCommandsResult.java @@ -0,0 +1,14 @@ +package org.zstack.sdk; + + + +public class GetModelServiceLaunchCommandsResult { + public java.util.List commands; + public void setCommands(java.util.List commands) { + this.commands = commands; + } + public java.util.List getCommands() { + return this.commands; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/HaNetworkGroupInventory.java b/sdk/src/main/java/org/zstack/sdk/HaNetworkGroupInventory.java new file mode 100644 index 00000000000..af8235e50e0 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/HaNetworkGroupInventory.java @@ -0,0 +1,79 @@ +package org.zstack.sdk; + + + +public class HaNetworkGroupInventory { + + public java.lang.String uuid; + public void setUuid(java.lang.String uuid) { + this.uuid = uuid; + } + public java.lang.String getUuid() { + return this.uuid; + } + + public java.lang.String name; + public void setName(java.lang.String name) { + this.name = name; + } + public java.lang.String getName() { + return this.name; + } + + public java.lang.String description; + public void setDescription(java.lang.String description) { + this.description = description; + } + public java.lang.String getDescription() { + return this.description; + } + + public java.lang.String type; + public void setType(java.lang.String type) { + this.type = type; + } + public java.lang.String getType() { + return this.type; + } + + public int minAvailableCount; + public void setMinAvailableCount(int minAvailableCount) { + this.minAvailableCount = minAvailableCount; + } + public int getMinAvailableCount() { + return this.minAvailableCount; + } + + public java.lang.String state; + public void setState(java.lang.String state) { + this.state = state; + } + public java.lang.String getState() { + return this.state; + } + + public java.sql.Timestamp createDate; + public void setCreateDate(java.sql.Timestamp createDate) { + this.createDate = createDate; + } + public java.sql.Timestamp getCreateDate() { + return this.createDate; + } + + public java.sql.Timestamp lastOpDate; + public void setLastOpDate(java.sql.Timestamp lastOpDate) { + this.lastOpDate = lastOpDate; + } + public java.sql.Timestamp getLastOpDate() { + return this.lastOpDate; + } + + public java.util.Set l3NetworkUuids; + public void setL3NetworkUuids(java.util.Set l3NetworkUuids) { + this.l3NetworkUuids = l3NetworkUuids; + } + public java.util.Set getL3NetworkUuids() { + return this.l3NetworkUuids; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/ImportModelServiceTemplateFromCdnAction.java b/sdk/src/main/java/org/zstack/sdk/ImportModelServiceTemplateFromCdnAction.java new file mode 100644 index 00000000000..6f4d9b4ac4d --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/ImportModelServiceTemplateFromCdnAction.java @@ -0,0 +1,110 @@ +package org.zstack.sdk; + +import java.util.HashMap; +import java.util.Map; +import org.zstack.sdk.*; + +public class ImportModelServiceTemplateFromCdnAction extends AbstractAction { + + private static final HashMap parameterMap = new HashMap<>(); + + private static final HashMap nonAPIParameterMap = new HashMap<>(); + + public static class Result { + public ErrorCode error; + public org.zstack.sdk.ImportModelServiceTemplateFromCdnResult value; + + public Result throwExceptionIfError() { + if (error != null) { + throw new ApiException( + String.format("error[code: %s, description: %s, details: %s, globalErrorCode: %s]", error.code, error.description, error.details, error.globalErrorCode) + ); + } + + return this; + } + } + + @Param(required = true, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String modelCenterUuid; + + @Param(required = true, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String templateName; + + @Param(required = false) + public java.lang.String resourceUuid; + + @Param(required = false, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.util.List tagUuids; + + @Param(required = false) + public java.util.List systemTags; + + @Param(required = false) + public java.util.List userTags; + + @Param(required = false) + public String sessionId; + + @Param(required = false) + public String accessKeyId; + + @Param(required = false) + public String accessKeySecret; + + @Param(required = false) + public String requestIp; + + @NonAPIParam + public long timeout = -1; + + @NonAPIParam + public long pollingInterval = -1; + + + private Result makeResult(ApiResult res) { + Result ret = new Result(); + if (res.error != null) { + ret.error = res.error; + return ret; + } + + org.zstack.sdk.ImportModelServiceTemplateFromCdnResult value = res.getResult(org.zstack.sdk.ImportModelServiceTemplateFromCdnResult.class); + ret.value = value == null ? new org.zstack.sdk.ImportModelServiceTemplateFromCdnResult() : value; + + return ret; + } + + public Result call() { + ApiResult res = ZSClient.call(this); + return makeResult(res); + } + + public void call(final Completion completion) { + ZSClient.call(this, new InternalCompletion() { + @Override + public void complete(ApiResult res) { + completion.complete(makeResult(res)); + } + }); + } + + protected Map getParameterMap() { + return parameterMap; + } + + protected Map getNonAPIParameterMap() { + return nonAPIParameterMap; + } + + protected RestInfo getRestInfo() { + RestInfo info = new RestInfo(); + info.httpMethod = "POST"; + info.path = "/ai/model-services/template/import/cdn"; + info.needSession = true; + info.needPoll = true; + info.parameterName = "param"; + return info; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/ImportModelServiceTemplateFromCdnResult.java b/sdk/src/main/java/org/zstack/sdk/ImportModelServiceTemplateFromCdnResult.java new file mode 100644 index 00000000000..765dd4e631c --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/ImportModelServiceTemplateFromCdnResult.java @@ -0,0 +1,14 @@ +package org.zstack.sdk; + +import org.zstack.sdk.ModelServiceInventory; + +public class ImportModelServiceTemplateFromCdnResult { + public ModelServiceInventory inventory; + public void setInventory(ModelServiceInventory inventory) { + this.inventory = inventory; + } + public ModelServiceInventory getInventory() { + return this.inventory; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/ImportModelServiceTemplateFromUploadAction.java b/sdk/src/main/java/org/zstack/sdk/ImportModelServiceTemplateFromUploadAction.java new file mode 100644 index 00000000000..c341b0c2448 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/ImportModelServiceTemplateFromUploadAction.java @@ -0,0 +1,113 @@ +package org.zstack.sdk; + +import java.util.HashMap; +import java.util.Map; +import org.zstack.sdk.*; + +public class ImportModelServiceTemplateFromUploadAction extends AbstractAction { + + private static final HashMap parameterMap = new HashMap<>(); + + private static final HashMap nonAPIParameterMap = new HashMap<>(); + + public static class Result { + public ErrorCode error; + public org.zstack.sdk.ImportModelServiceTemplateFromUploadResult value; + + public Result throwExceptionIfError() { + if (error != null) { + throw new ApiException( + String.format("error[code: %s, description: %s, details: %s, globalErrorCode: %s]", error.code, error.description, error.details, error.globalErrorCode) + ); + } + + return this; + } + } + + @Param(required = true, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String modelCenterUuid; + + @Param(required = true, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String fileName; + + @Param(required = false, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String templateName; + + @Param(required = false) + public java.lang.String resourceUuid; + + @Param(required = false, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.util.List tagUuids; + + @Param(required = false) + public java.util.List systemTags; + + @Param(required = false) + public java.util.List userTags; + + @Param(required = false) + public String sessionId; + + @Param(required = false) + public String accessKeyId; + + @Param(required = false) + public String accessKeySecret; + + @Param(required = false) + public String requestIp; + + @NonAPIParam + public long timeout = -1; + + @NonAPIParam + public long pollingInterval = -1; + + + private Result makeResult(ApiResult res) { + Result ret = new Result(); + if (res.error != null) { + ret.error = res.error; + return ret; + } + + org.zstack.sdk.ImportModelServiceTemplateFromUploadResult value = res.getResult(org.zstack.sdk.ImportModelServiceTemplateFromUploadResult.class); + ret.value = value == null ? new org.zstack.sdk.ImportModelServiceTemplateFromUploadResult() : value; + + return ret; + } + + public Result call() { + ApiResult res = ZSClient.call(this); + return makeResult(res); + } + + public void call(final Completion completion) { + ZSClient.call(this, new InternalCompletion() { + @Override + public void complete(ApiResult res) { + completion.complete(makeResult(res)); + } + }); + } + + protected Map getParameterMap() { + return parameterMap; + } + + protected Map getNonAPIParameterMap() { + return nonAPIParameterMap; + } + + protected RestInfo getRestInfo() { + RestInfo info = new RestInfo(); + info.httpMethod = "POST"; + info.path = "/ai/model-services/template/import/upload"; + info.needSession = true; + info.needPoll = true; + info.parameterName = "param"; + return info; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/ImportModelServiceTemplateFromUploadResult.java b/sdk/src/main/java/org/zstack/sdk/ImportModelServiceTemplateFromUploadResult.java new file mode 100644 index 00000000000..e17ea42af99 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/ImportModelServiceTemplateFromUploadResult.java @@ -0,0 +1,14 @@ +package org.zstack.sdk; + +import org.zstack.sdk.ModelServiceInventory; + +public class ImportModelServiceTemplateFromUploadResult { + public ModelServiceInventory inventory; + public void setInventory(ModelServiceInventory inventory) { + this.inventory = inventory; + } + public ModelServiceInventory getInventory() { + return this.inventory; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/ImportModelServiceTemplateFromUrlAction.java b/sdk/src/main/java/org/zstack/sdk/ImportModelServiceTemplateFromUrlAction.java new file mode 100644 index 00000000000..1bd3b5837e5 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/ImportModelServiceTemplateFromUrlAction.java @@ -0,0 +1,113 @@ +package org.zstack.sdk; + +import java.util.HashMap; +import java.util.Map; +import org.zstack.sdk.*; + +public class ImportModelServiceTemplateFromUrlAction extends AbstractAction { + + private static final HashMap parameterMap = new HashMap<>(); + + private static final HashMap nonAPIParameterMap = new HashMap<>(); + + public static class Result { + public ErrorCode error; + public org.zstack.sdk.ImportModelServiceTemplateFromUrlResult value; + + public Result throwExceptionIfError() { + if (error != null) { + throw new ApiException( + String.format("error[code: %s, description: %s, details: %s, globalErrorCode: %s]", error.code, error.description, error.details, error.globalErrorCode) + ); + } + + return this; + } + } + + @Param(required = true, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String modelCenterUuid; + + @Param(required = true, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String url; + + @Param(required = false, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String templateName; + + @Param(required = false) + public java.lang.String resourceUuid; + + @Param(required = false, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.util.List tagUuids; + + @Param(required = false) + public java.util.List systemTags; + + @Param(required = false) + public java.util.List userTags; + + @Param(required = false) + public String sessionId; + + @Param(required = false) + public String accessKeyId; + + @Param(required = false) + public String accessKeySecret; + + @Param(required = false) + public String requestIp; + + @NonAPIParam + public long timeout = -1; + + @NonAPIParam + public long pollingInterval = -1; + + + private Result makeResult(ApiResult res) { + Result ret = new Result(); + if (res.error != null) { + ret.error = res.error; + return ret; + } + + org.zstack.sdk.ImportModelServiceTemplateFromUrlResult value = res.getResult(org.zstack.sdk.ImportModelServiceTemplateFromUrlResult.class); + ret.value = value == null ? new org.zstack.sdk.ImportModelServiceTemplateFromUrlResult() : value; + + return ret; + } + + public Result call() { + ApiResult res = ZSClient.call(this); + return makeResult(res); + } + + public void call(final Completion completion) { + ZSClient.call(this, new InternalCompletion() { + @Override + public void complete(ApiResult res) { + completion.complete(makeResult(res)); + } + }); + } + + protected Map getParameterMap() { + return parameterMap; + } + + protected Map getNonAPIParameterMap() { + return nonAPIParameterMap; + } + + protected RestInfo getRestInfo() { + RestInfo info = new RestInfo(); + info.httpMethod = "POST"; + info.path = "/ai/model-services/template/import/url"; + info.needSession = true; + info.needPoll = true; + info.parameterName = "param"; + return info; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/ImportModelServiceTemplateFromUrlResult.java b/sdk/src/main/java/org/zstack/sdk/ImportModelServiceTemplateFromUrlResult.java new file mode 100644 index 00000000000..5199d7a5d7c --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/ImportModelServiceTemplateFromUrlResult.java @@ -0,0 +1,14 @@ +package org.zstack.sdk; + +import org.zstack.sdk.ModelServiceInventory; + +public class ImportModelServiceTemplateFromUrlResult { + public ModelServiceInventory inventory; + public void setInventory(ModelServiceInventory inventory) { + this.inventory = inventory; + } + public ModelServiceInventory getInventory() { + return this.inventory; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/ModelCenterCapacityInventory.java b/sdk/src/main/java/org/zstack/sdk/ModelCenterCapacityInventory.java index 92430b6daca..73354efe375 100644 --- a/sdk/src/main/java/org/zstack/sdk/ModelCenterCapacityInventory.java +++ b/sdk/src/main/java/org/zstack/sdk/ModelCenterCapacityInventory.java @@ -68,4 +68,20 @@ public long getCacheUsedCapacity() { return this.cacheUsedCapacity; } + public long availableCapacity; + public void setAvailableCapacity(long availableCapacity) { + this.availableCapacity = availableCapacity; + } + public long getAvailableCapacity() { + return this.availableCapacity; + } + + public long totalCapacity; + public void setTotalCapacity(long totalCapacity) { + this.totalCapacity = totalCapacity; + } + public long getTotalCapacity() { + return this.totalCapacity; + } + } diff --git a/sdk/src/main/java/org/zstack/sdk/ModelCenterInventory.java b/sdk/src/main/java/org/zstack/sdk/ModelCenterInventory.java index ec8bf2e9471..4c2236d9306 100644 --- a/sdk/src/main/java/org/zstack/sdk/ModelCenterInventory.java +++ b/sdk/src/main/java/org/zstack/sdk/ModelCenterInventory.java @@ -69,6 +69,14 @@ public int getManagementPort() { return this.managementPort; } + public java.lang.String zoneUuid; + public void setZoneUuid(java.lang.String zoneUuid) { + this.zoneUuid = zoneUuid; + } + public java.lang.String getZoneUuid() { + return this.zoneUuid; + } + public java.lang.String storageNetworkUuid; public void setStorageNetworkUuid(java.lang.String storageNetworkUuid) { this.storageNetworkUuid = storageNetworkUuid; diff --git a/sdk/src/main/java/org/zstack/sdk/ModelInventory.java b/sdk/src/main/java/org/zstack/sdk/ModelInventory.java index a501bd81fe2..2c731e65bcc 100644 --- a/sdk/src/main/java/org/zstack/sdk/ModelInventory.java +++ b/sdk/src/main/java/org/zstack/sdk/ModelInventory.java @@ -52,6 +52,14 @@ public java.lang.String getModelCenterUuid() { return this.modelCenterUuid; } + public java.lang.String zoneUuid; + public void setZoneUuid(java.lang.String zoneUuid) { + this.zoneUuid = zoneUuid; + } + public java.lang.String getZoneUuid() { + return this.zoneUuid; + } + public java.lang.String logo; public void setLogo(java.lang.String logo) { this.logo = logo; @@ -196,6 +204,14 @@ public java.lang.String getRequiredAccelerator() { return this.requiredAccelerator; } + public java.lang.String pipelineTag; + public void setPipelineTag(java.lang.String pipelineTag) { + this.pipelineTag = pipelineTag; + } + public java.lang.String getPipelineTag() { + return this.pipelineTag; + } + public java.util.List modelServiceRefs; public void setModelServiceRefs(java.util.List modelServiceRefs) { this.modelServiceRefs = modelServiceRefs; diff --git a/sdk/src/main/java/org/zstack/sdk/ModelServiceInstanceGroupInventory.java b/sdk/src/main/java/org/zstack/sdk/ModelServiceInstanceGroupInventory.java index 2451290084a..7e594109096 100644 --- a/sdk/src/main/java/org/zstack/sdk/ModelServiceInstanceGroupInventory.java +++ b/sdk/src/main/java/org/zstack/sdk/ModelServiceInstanceGroupInventory.java @@ -28,6 +28,14 @@ public java.lang.String getModelUuid() { return this.modelUuid; } + public java.lang.String zoneUuid; + public void setZoneUuid(java.lang.String zoneUuid) { + this.zoneUuid = zoneUuid; + } + public java.lang.String getZoneUuid() { + return this.zoneUuid; + } + public java.util.List instances; public void setInstances(java.util.List instances) { this.instances = instances; diff --git a/sdk/src/main/java/org/zstack/sdk/ModelServiceInstanceInventory.java b/sdk/src/main/java/org/zstack/sdk/ModelServiceInstanceInventory.java index 02ba10afbba..ce624aafe69 100644 --- a/sdk/src/main/java/org/zstack/sdk/ModelServiceInstanceInventory.java +++ b/sdk/src/main/java/org/zstack/sdk/ModelServiceInstanceInventory.java @@ -1,5 +1,6 @@ package org.zstack.sdk; +import org.zstack.sdk.ModelServiceLaunchCommandInventory; import org.zstack.sdk.VmInstanceInventory; public class ModelServiceInstanceInventory { @@ -84,6 +85,14 @@ public java.lang.String getJupyterUrl() { return this.jupyterUrl; } + public ModelServiceLaunchCommandInventory launchCommand; + public void setLaunchCommand(ModelServiceLaunchCommandInventory launchCommand) { + this.launchCommand = launchCommand; + } + public ModelServiceLaunchCommandInventory getLaunchCommand() { + return this.launchCommand; + } + public java.lang.String vmInstanceUuid; public void setVmInstanceUuid(java.lang.String vmInstanceUuid) { this.vmInstanceUuid = vmInstanceUuid; diff --git a/sdk/src/main/java/org/zstack/sdk/ModelServiceInstanceLaunchCommandInventory.java b/sdk/src/main/java/org/zstack/sdk/ModelServiceInstanceLaunchCommandInventory.java new file mode 100644 index 00000000000..aff3987038f --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/ModelServiceInstanceLaunchCommandInventory.java @@ -0,0 +1,47 @@ +package org.zstack.sdk; + +import org.zstack.sdk.ModelServiceLaunchCommandInventory; + +public class ModelServiceInstanceLaunchCommandInventory { + + public java.lang.String instanceUuid; + public void setInstanceUuid(java.lang.String instanceUuid) { + this.instanceUuid = instanceUuid; + } + public java.lang.String getInstanceUuid() { + return this.instanceUuid; + } + + public java.lang.String groupUuid; + public void setGroupUuid(java.lang.String groupUuid) { + this.groupUuid = groupUuid; + } + public java.lang.String getGroupUuid() { + return this.groupUuid; + } + + public java.lang.String instanceName; + public void setInstanceName(java.lang.String instanceName) { + this.instanceName = instanceName; + } + public java.lang.String getInstanceName() { + return this.instanceName; + } + + public java.lang.String status; + public void setStatus(java.lang.String status) { + this.status = status; + } + public java.lang.String getStatus() { + return this.status; + } + + public ModelServiceLaunchCommandInventory launchCommand; + public void setLaunchCommand(ModelServiceLaunchCommandInventory launchCommand) { + this.launchCommand = launchCommand; + } + public ModelServiceLaunchCommandInventory getLaunchCommand() { + return this.launchCommand; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/ModelServiceInventory.java b/sdk/src/main/java/org/zstack/sdk/ModelServiceInventory.java index 6d016f83c48..7a4bf7135aa 100644 --- a/sdk/src/main/java/org/zstack/sdk/ModelServiceInventory.java +++ b/sdk/src/main/java/org/zstack/sdk/ModelServiceInventory.java @@ -68,6 +68,14 @@ public java.lang.String getModelCenterUuid() { return this.modelCenterUuid; } + public java.lang.String zoneUuid; + public void setZoneUuid(java.lang.String zoneUuid) { + this.zoneUuid = zoneUuid; + } + public java.lang.String getZoneUuid() { + return this.zoneUuid; + } + public java.lang.String type; public void setType(java.lang.String type) { this.type = type; @@ -108,6 +116,14 @@ public java.lang.Boolean getSystem() { return this.system; } + public java.lang.Boolean hasNewVersion; + public void setHasNewVersion(java.lang.Boolean hasNewVersion) { + this.hasNewVersion = hasNewVersion; + } + public java.lang.Boolean getHasNewVersion() { + return this.hasNewVersion; + } + public java.lang.String gpuComputeCapability; public void setGpuComputeCapability(java.lang.String gpuComputeCapability) { this.gpuComputeCapability = gpuComputeCapability; diff --git a/sdk/src/main/java/org/zstack/sdk/ModelServiceLaunchCommandInventory.java b/sdk/src/main/java/org/zstack/sdk/ModelServiceLaunchCommandInventory.java new file mode 100644 index 00000000000..7d0ccb9f41c --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/ModelServiceLaunchCommandInventory.java @@ -0,0 +1,119 @@ +package org.zstack.sdk; + + + +public class ModelServiceLaunchCommandInventory { + + public java.lang.String adapter; + public void setAdapter(java.lang.String adapter) { + this.adapter = adapter; + } + public java.lang.String getAdapter() { + return this.adapter; + } + + public java.lang.String framework; + public void setFramework(java.lang.String framework) { + this.framework = framework; + } + public java.lang.String getFramework() { + return this.framework; + } + + public java.lang.String modelDir; + public void setModelDir(java.lang.String modelDir) { + this.modelDir = modelDir; + } + public java.lang.String getModelDir() { + return this.modelDir; + } + + public java.lang.String modelId; + public void setModelId(java.lang.String modelId) { + this.modelId = modelId; + } + public java.lang.String getModelId() { + return this.modelId; + } + + public java.lang.Integer backendPort; + public void setBackendPort(java.lang.Integer backendPort) { + this.backendPort = backendPort; + } + public java.lang.Integer getBackendPort() { + return this.backendPort; + } + + public java.lang.String startupMode; + public void setStartupMode(java.lang.String startupMode) { + this.startupMode = startupMode; + } + public java.lang.String getStartupMode() { + return this.startupMode; + } + + public java.lang.String source; + public void setSource(java.lang.String source) { + this.source = source; + } + public java.lang.String getSource() { + return this.source; + } + + public java.lang.String commandLine; + public void setCommandLine(java.lang.String commandLine) { + this.commandLine = commandLine; + } + public java.lang.String getCommandLine() { + return this.commandLine; + } + + public java.util.List commandArgs; + public void setCommandArgs(java.util.List commandArgs) { + this.commandArgs = commandArgs; + } + public java.util.List getCommandArgs() { + return this.commandArgs; + } + + public java.lang.String executedCommand; + public void setExecutedCommand(java.lang.String executedCommand) { + this.executedCommand = executedCommand; + } + public java.lang.String getExecutedCommand() { + return this.executedCommand; + } + + public java.lang.Boolean shell; + public void setShell(java.lang.Boolean shell) { + this.shell = shell; + } + public java.lang.Boolean getShell() { + return this.shell; + } + + public java.lang.Integer pid; + public void setPid(java.lang.Integer pid) { + this.pid = pid; + } + public java.lang.Integer getPid() { + return this.pid; + } + + public java.lang.String logFile; + public void setLogFile(java.lang.String logFile) { + this.logFile = logFile; + } + public java.lang.String getLogFile() { + return this.logFile; + } + + public java.lang.String generatedAt; + public void setGeneratedAt(java.lang.String generatedAt) { + this.generatedAt = generatedAt; + } + public java.lang.String getGeneratedAt() { + return this.generatedAt; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/ModelServiceTemplateInventory.java b/sdk/src/main/java/org/zstack/sdk/ModelServiceTemplateInventory.java index 04278cd76d4..e615c0fae4c 100644 --- a/sdk/src/main/java/org/zstack/sdk/ModelServiceTemplateInventory.java +++ b/sdk/src/main/java/org/zstack/sdk/ModelServiceTemplateInventory.java @@ -20,6 +20,14 @@ public java.lang.String getModelServiceUuid() { return this.modelServiceUuid; } + public java.lang.String name; + public void setName(java.lang.String name) { + this.name = name; + } + public java.lang.String getName() { + return this.name; + } + public java.lang.String cpuArchitecture; public void setCpuArchitecture(java.lang.String cpuArchitecture) { this.cpuArchitecture = cpuArchitecture; @@ -44,6 +52,30 @@ public java.lang.String getDockerImage() { return this.dockerImage; } + public java.lang.String gpuVendor; + public void setGpuVendor(java.lang.String gpuVendor) { + this.gpuVendor = gpuVendor; + } + public java.lang.String getGpuVendor() { + return this.gpuVendor; + } + + public java.lang.String acceleratorType; + public void setAcceleratorType(java.lang.String acceleratorType) { + this.acceleratorType = acceleratorType; + } + public java.lang.String getAcceleratorType() { + return this.acceleratorType; + } + + public java.lang.String imageNamePattern; + public void setImageNamePattern(java.lang.String imageNamePattern) { + this.imageNamePattern = imageNamePattern; + } + public java.lang.String getImageNamePattern() { + return this.imageNamePattern; + } + public java.sql.Timestamp createDate; public void setCreateDate(java.sql.Timestamp createDate) { this.createDate = createDate; diff --git a/sdk/src/main/java/org/zstack/sdk/NativeClusterInventory.java b/sdk/src/main/java/org/zstack/sdk/NativeClusterInventory.java index 150665bdb35..0b99be3c8b1 100644 --- a/sdk/src/main/java/org/zstack/sdk/NativeClusterInventory.java +++ b/sdk/src/main/java/org/zstack/sdk/NativeClusterInventory.java @@ -68,4 +68,20 @@ public java.lang.String getStatus() { return this.status; } + public java.lang.String zakuHealthStatus; + public void setZakuHealthStatus(java.lang.String zakuHealthStatus) { + this.zakuHealthStatus = zakuHealthStatus; + } + public java.lang.String getZakuHealthStatus() { + return this.zakuHealthStatus; + } + + public long id; + public void setId(long id) { + this.id = id; + } + public long getId() { + return this.id; + } + } diff --git a/sdk/src/main/java/org/zstack/sdk/NicTO.java b/sdk/src/main/java/org/zstack/sdk/NicTO.java index 6eecb1466a8..c1457f95d4b 100644 --- a/sdk/src/main/java/org/zstack/sdk/NicTO.java +++ b/sdk/src/main/java/org/zstack/sdk/NicTO.java @@ -197,4 +197,20 @@ public java.lang.Boolean getIsolated() { return this.isolated; } + public java.lang.String bridgePortType; + public void setBridgePortType(java.lang.String bridgePortType) { + this.bridgePortType = bridgePortType; + } + public java.lang.String getBridgePortType() { + return this.bridgePortType; + } + + public java.lang.String interfaceId; + public void setInterfaceId(java.lang.String interfaceId) { + this.interfaceId = interfaceId; + } + public java.lang.String getInterfaceId() { + return this.interfaceId; + } + } diff --git a/sdk/src/main/java/org/zstack/sdk/QueryAiHostModelCacheAction.java b/sdk/src/main/java/org/zstack/sdk/QueryAiHostModelCacheAction.java new file mode 100644 index 00000000000..26217b8ba58 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/QueryAiHostModelCacheAction.java @@ -0,0 +1,75 @@ +package org.zstack.sdk; + +import java.util.HashMap; +import java.util.Map; +import org.zstack.sdk.*; + +public class QueryAiHostModelCacheAction extends QueryAction { + + private static final HashMap parameterMap = new HashMap<>(); + + private static final HashMap nonAPIParameterMap = new HashMap<>(); + + public static class Result { + public ErrorCode error; + public org.zstack.sdk.QueryAiHostModelCacheResult value; + + public Result throwExceptionIfError() { + if (error != null) { + throw new ApiException( + String.format("error[code: %s, description: %s, details: %s, globalErrorCode: %s]", error.code, error.description, error.details, error.globalErrorCode) + ); + } + + return this; + } + } + + + + private Result makeResult(ApiResult res) { + Result ret = new Result(); + if (res.error != null) { + ret.error = res.error; + return ret; + } + + org.zstack.sdk.QueryAiHostModelCacheResult value = res.getResult(org.zstack.sdk.QueryAiHostModelCacheResult.class); + ret.value = value == null ? new org.zstack.sdk.QueryAiHostModelCacheResult() : value; + + return ret; + } + + public Result call() { + ApiResult res = ZSClient.call(this); + return makeResult(res); + } + + public void call(final Completion completion) { + ZSClient.call(this, new InternalCompletion() { + @Override + public void complete(ApiResult res) { + completion.complete(makeResult(res)); + } + }); + } + + protected Map getParameterMap() { + return parameterMap; + } + + protected Map getNonAPIParameterMap() { + return nonAPIParameterMap; + } + + protected RestInfo getRestInfo() { + RestInfo info = new RestInfo(); + info.httpMethod = "GET"; + info.path = "/ai/host-model-caches"; + info.needSession = true; + info.needPoll = false; + info.parameterName = ""; + return info; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/QueryAiHostModelCacheResult.java b/sdk/src/main/java/org/zstack/sdk/QueryAiHostModelCacheResult.java new file mode 100644 index 00000000000..21ce619035b --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/QueryAiHostModelCacheResult.java @@ -0,0 +1,22 @@ +package org.zstack.sdk; + + + +public class QueryAiHostModelCacheResult { + public java.util.List inventories; + public void setInventories(java.util.List inventories) { + this.inventories = inventories; + } + public java.util.List getInventories() { + return this.inventories; + } + + public java.lang.Long total; + public void setTotal(java.lang.Long total) { + this.total = total; + } + public java.lang.Long getTotal() { + return this.total; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/QueryCdnModelServiceTemplateListAction.java b/sdk/src/main/java/org/zstack/sdk/QueryCdnModelServiceTemplateListAction.java new file mode 100644 index 00000000000..ef3e76c8f4c --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/QueryCdnModelServiceTemplateListAction.java @@ -0,0 +1,75 @@ +package org.zstack.sdk; + +import java.util.HashMap; +import java.util.Map; +import org.zstack.sdk.*; + +public class QueryCdnModelServiceTemplateListAction extends QueryAction { + + private static final HashMap parameterMap = new HashMap<>(); + + private static final HashMap nonAPIParameterMap = new HashMap<>(); + + public static class Result { + public ErrorCode error; + public org.zstack.sdk.QueryCdnModelServiceTemplateListResult value; + + public Result throwExceptionIfError() { + if (error != null) { + throw new ApiException( + String.format("error[code: %s, description: %s, details: %s, globalErrorCode: %s]", error.code, error.description, error.details, error.globalErrorCode) + ); + } + + return this; + } + } + + + + private Result makeResult(ApiResult res) { + Result ret = new Result(); + if (res.error != null) { + ret.error = res.error; + return ret; + } + + org.zstack.sdk.QueryCdnModelServiceTemplateListResult value = res.getResult(org.zstack.sdk.QueryCdnModelServiceTemplateListResult.class); + ret.value = value == null ? new org.zstack.sdk.QueryCdnModelServiceTemplateListResult() : value; + + return ret; + } + + public Result call() { + ApiResult res = ZSClient.call(this); + return makeResult(res); + } + + public void call(final Completion completion) { + ZSClient.call(this, new InternalCompletion() { + @Override + public void complete(ApiResult res) { + completion.complete(makeResult(res)); + } + }); + } + + protected Map getParameterMap() { + return parameterMap; + } + + protected Map getNonAPIParameterMap() { + return nonAPIParameterMap; + } + + protected RestInfo getRestInfo() { + RestInfo info = new RestInfo(); + info.httpMethod = "GET"; + info.path = "/ai/model-services/template/cdn-list"; + info.needSession = true; + info.needPoll = false; + info.parameterName = ""; + return info; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/QueryCdnModelServiceTemplateListResult.java b/sdk/src/main/java/org/zstack/sdk/QueryCdnModelServiceTemplateListResult.java new file mode 100644 index 00000000000..7c652437380 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/QueryCdnModelServiceTemplateListResult.java @@ -0,0 +1,22 @@ +package org.zstack.sdk; + + + +public class QueryCdnModelServiceTemplateListResult { + public java.util.List inventories; + public void setInventories(java.util.List inventories) { + this.inventories = inventories; + } + public java.util.List getInventories() { + return this.inventories; + } + + public java.lang.Long total; + public void setTotal(java.lang.Long total) { + this.total = total; + } + public java.lang.Long getTotal() { + return this.total; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/QueryHaNetworkGroupAction.java b/sdk/src/main/java/org/zstack/sdk/QueryHaNetworkGroupAction.java new file mode 100644 index 00000000000..f358fa563ef --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/QueryHaNetworkGroupAction.java @@ -0,0 +1,75 @@ +package org.zstack.sdk; + +import java.util.HashMap; +import java.util.Map; +import org.zstack.sdk.*; + +public class QueryHaNetworkGroupAction extends QueryAction { + + private static final HashMap parameterMap = new HashMap<>(); + + private static final HashMap nonAPIParameterMap = new HashMap<>(); + + public static class Result { + public ErrorCode error; + public org.zstack.sdk.QueryHaNetworkGroupResult value; + + public Result throwExceptionIfError() { + if (error != null) { + throw new ApiException( + String.format("error[code: %s, description: %s, details: %s, globalErrorCode: %s]", error.code, error.description, error.details, error.globalErrorCode) + ); + } + + return this; + } + } + + + + private Result makeResult(ApiResult res) { + Result ret = new Result(); + if (res.error != null) { + ret.error = res.error; + return ret; + } + + org.zstack.sdk.QueryHaNetworkGroupResult value = res.getResult(org.zstack.sdk.QueryHaNetworkGroupResult.class); + ret.value = value == null ? new org.zstack.sdk.QueryHaNetworkGroupResult() : value; + + return ret; + } + + public Result call() { + ApiResult res = ZSClient.call(this); + return makeResult(res); + } + + public void call(final Completion completion) { + ZSClient.call(this, new InternalCompletion() { + @Override + public void complete(ApiResult res) { + completion.complete(makeResult(res)); + } + }); + } + + protected Map getParameterMap() { + return parameterMap; + } + + protected Map getNonAPIParameterMap() { + return nonAPIParameterMap; + } + + protected RestInfo getRestInfo() { + RestInfo info = new RestInfo(); + info.httpMethod = "GET"; + info.path = "/ha/network-groups"; + info.needSession = true; + info.needPoll = false; + info.parameterName = ""; + return info; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/QueryHaNetworkGroupResult.java b/sdk/src/main/java/org/zstack/sdk/QueryHaNetworkGroupResult.java new file mode 100644 index 00000000000..b865e2ded08 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/QueryHaNetworkGroupResult.java @@ -0,0 +1,22 @@ +package org.zstack.sdk; + + + +public class QueryHaNetworkGroupResult { + public java.util.List inventories; + public void setInventories(java.util.List inventories) { + this.inventories = inventories; + } + public java.util.List getInventories() { + return this.inventories; + } + + public java.lang.Long total; + public void setTotal(java.lang.Long total) { + this.total = total; + } + public java.lang.Long getTotal() { + return this.total; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/ReInitDataVolumeAction.java b/sdk/src/main/java/org/zstack/sdk/ReInitDataVolumeAction.java new file mode 100644 index 00000000000..c95275e1578 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/ReInitDataVolumeAction.java @@ -0,0 +1,101 @@ +package org.zstack.sdk; + +import java.util.HashMap; +import java.util.Map; +import org.zstack.sdk.*; + +public class ReInitDataVolumeAction extends AbstractAction { + + private static final HashMap parameterMap = new HashMap<>(); + + private static final HashMap nonAPIParameterMap = new HashMap<>(); + + public static class Result { + public ErrorCode error; + public org.zstack.sdk.ReInitDataVolumeResult value; + + public Result throwExceptionIfError() { + if (error != null) { + throw new ApiException( + String.format("error[code: %s, description: %s, details: %s, globalErrorCode: %s]", error.code, error.description, error.details, error.globalErrorCode) + ); + } + + return this; + } + } + + @Param(required = true, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String uuid; + + @Param(required = false) + public java.util.List systemTags; + + @Param(required = false) + public java.util.List userTags; + + @Param(required = false) + public String sessionId; + + @Param(required = false) + public String accessKeyId; + + @Param(required = false) + public String accessKeySecret; + + @Param(required = false) + public String requestIp; + + @NonAPIParam + public long timeout = -1; + + @NonAPIParam + public long pollingInterval = -1; + + + private Result makeResult(ApiResult res) { + Result ret = new Result(); + if (res.error != null) { + ret.error = res.error; + return ret; + } + + org.zstack.sdk.ReInitDataVolumeResult value = res.getResult(org.zstack.sdk.ReInitDataVolumeResult.class); + ret.value = value == null ? new org.zstack.sdk.ReInitDataVolumeResult() : value; + + return ret; + } + + public Result call() { + ApiResult res = ZSClient.call(this); + return makeResult(res); + } + + public void call(final Completion completion) { + ZSClient.call(this, new InternalCompletion() { + @Override + public void complete(ApiResult res) { + completion.complete(makeResult(res)); + } + }); + } + + protected Map getParameterMap() { + return parameterMap; + } + + protected Map getNonAPIParameterMap() { + return nonAPIParameterMap; + } + + protected RestInfo getRestInfo() { + RestInfo info = new RestInfo(); + info.httpMethod = "PUT"; + info.path = "/volumes/{uuid}/actions"; + info.needSession = true; + info.needPoll = true; + info.parameterName = "reInitDataVolume"; + return info; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/ReInitDataVolumeResult.java b/sdk/src/main/java/org/zstack/sdk/ReInitDataVolumeResult.java new file mode 100644 index 00000000000..7bbda5984de --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/ReInitDataVolumeResult.java @@ -0,0 +1,14 @@ +package org.zstack.sdk; + +import org.zstack.sdk.VolumeInventory; + +public class ReInitDataVolumeResult { + public VolumeInventory inventory; + public void setInventory(VolumeInventory inventory) { + this.inventory = inventory; + } + public VolumeInventory getInventory() { + return this.inventory; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/RefreshAiHostModelCacheAction.java b/sdk/src/main/java/org/zstack/sdk/RefreshAiHostModelCacheAction.java new file mode 100644 index 00000000000..6e86b554f39 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/RefreshAiHostModelCacheAction.java @@ -0,0 +1,95 @@ +package org.zstack.sdk; + +import java.util.HashMap; +import java.util.Map; +import org.zstack.sdk.*; + +public class RefreshAiHostModelCacheAction extends AbstractAction { + + private static final HashMap parameterMap = new HashMap<>(); + + private static final HashMap nonAPIParameterMap = new HashMap<>(); + + public static class Result { + public ErrorCode error; + public org.zstack.sdk.RefreshAiHostModelCacheResult value; + + public Result throwExceptionIfError() { + if (error != null) { + throw new ApiException( + String.format("error[code: %s, description: %s, details: %s, globalErrorCode: %s]", error.code, error.description, error.details, error.globalErrorCode) + ); + } + + return this; + } + } + + @Param(required = false, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.util.List hostUuids; + + @Param(required = false) + public java.util.List systemTags; + + @Param(required = false) + public java.util.List userTags; + + @Param(required = false) + public String sessionId; + + @Param(required = false) + public String accessKeyId; + + @Param(required = false) + public String accessKeySecret; + + @Param(required = false) + public String requestIp; + + + private Result makeResult(ApiResult res) { + Result ret = new Result(); + if (res.error != null) { + ret.error = res.error; + return ret; + } + + org.zstack.sdk.RefreshAiHostModelCacheResult value = res.getResult(org.zstack.sdk.RefreshAiHostModelCacheResult.class); + ret.value = value == null ? new org.zstack.sdk.RefreshAiHostModelCacheResult() : value; + + return ret; + } + + public Result call() { + ApiResult res = ZSClient.call(this); + return makeResult(res); + } + + public void call(final Completion completion) { + ZSClient.call(this, new InternalCompletion() { + @Override + public void complete(ApiResult res) { + completion.complete(makeResult(res)); + } + }); + } + + protected Map getParameterMap() { + return parameterMap; + } + + protected Map getNonAPIParameterMap() { + return nonAPIParameterMap; + } + + protected RestInfo getRestInfo() { + RestInfo info = new RestInfo(); + info.httpMethod = "PUT"; + info.path = "/ai/host-model-caches/actions"; + info.needSession = true; + info.needPoll = false; + info.parameterName = "refreshAiHostModelCache"; + return info; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/RefreshAiHostModelCacheResult.java b/sdk/src/main/java/org/zstack/sdk/RefreshAiHostModelCacheResult.java new file mode 100644 index 00000000000..218323a0506 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/RefreshAiHostModelCacheResult.java @@ -0,0 +1,22 @@ +package org.zstack.sdk; + + + +public class RefreshAiHostModelCacheResult { + public java.util.List inventories; + public void setInventories(java.util.List inventories) { + this.inventories = inventories; + } + public java.util.List getInventories() { + return this.inventories; + } + + public java.util.List failureReasons; + public void setFailureReasons(java.util.List failureReasons) { + this.failureReasons = failureReasons; + } + public java.util.List getFailureReasons() { + return this.failureReasons; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/RegisterLicenseClientAction.java b/sdk/src/main/java/org/zstack/sdk/RegisterLicenseClientAction.java new file mode 100644 index 00000000000..aa6c6904668 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/RegisterLicenseClientAction.java @@ -0,0 +1,122 @@ +package org.zstack.sdk; + +import java.util.HashMap; +import java.util.Map; +import org.zstack.sdk.*; + +public class RegisterLicenseClientAction extends AbstractAction { + + private static final HashMap parameterMap = new HashMap<>(); + + private static final HashMap nonAPIParameterMap = new HashMap<>(); + + public static class Result { + public ErrorCode error; + public org.zstack.sdk.RegisterLicenseClientResult value; + + public Result throwExceptionIfError() { + if (error != null) { + throw new ApiException( + String.format("error[code: %s, description: %s, details: %s, globalErrorCode: %s]", error.code, error.description, error.details, error.globalErrorCode) + ); + } + + return this; + } + } + + @Param(required = true, nonempty = true, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String serverUrl; + + @Param(required = false, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String siteName; + + @Param(required = false, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String productLine; + + @Param(required = false, validRegexValues = "^[a-f0-9]{32}$", nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String siteUuid; + + @Param(required = false, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String baseAuthEntity; + + @Param(required = false, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String bundle; + + @Param(required = false, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String bundleName; + + @Param(required = false, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.Boolean useCurrentLicense = false; + + @Param(required = false) + public java.util.List systemTags; + + @Param(required = false) + public java.util.List userTags; + + @Param(required = false) + public String sessionId; + + @Param(required = false) + public String accessKeyId; + + @Param(required = false) + public String accessKeySecret; + + @Param(required = false) + public String requestIp; + + @NonAPIParam + public long timeout = -1; + + @NonAPIParam + public long pollingInterval = -1; + + + private Result makeResult(ApiResult res) { + Result ret = new Result(); + if (res.error != null) { + ret.error = res.error; + return ret; + } + + org.zstack.sdk.RegisterLicenseClientResult value = res.getResult(org.zstack.sdk.RegisterLicenseClientResult.class); + ret.value = value == null ? new org.zstack.sdk.RegisterLicenseClientResult() : value; + + return ret; + } + + public Result call() { + ApiResult res = ZSClient.call(this); + return makeResult(res); + } + + public void call(final Completion completion) { + ZSClient.call(this, new InternalCompletion() { + @Override + public void complete(ApiResult res) { + completion.complete(makeResult(res)); + } + }); + } + + protected Map getParameterMap() { + return parameterMap; + } + + protected Map getNonAPIParameterMap() { + return nonAPIParameterMap; + } + + protected RestInfo getRestInfo() { + RestInfo info = new RestInfo(); + info.httpMethod = "POST"; + info.path = "/licenses/client"; + info.needSession = true; + info.needPoll = true; + info.parameterName = "params"; + return info; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/RegisterLicenseClientResult.java b/sdk/src/main/java/org/zstack/sdk/RegisterLicenseClientResult.java new file mode 100644 index 00000000000..f731129c21d --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/RegisterLicenseClientResult.java @@ -0,0 +1,38 @@ +package org.zstack.sdk; + + + +public class RegisterLicenseClientResult { + public java.lang.String siteUuid; + public void setSiteUuid(java.lang.String siteUuid) { + this.siteUuid = siteUuid; + } + public java.lang.String getSiteUuid() { + return this.siteUuid; + } + + public java.lang.String state; + public void setState(java.lang.String state) { + this.state = state; + } + public java.lang.String getState() { + return this.state; + } + + public long licenseCount; + public void setLicenseCount(long licenseCount) { + this.licenseCount = licenseCount; + } + public long getLicenseCount() { + return this.licenseCount; + } + + public java.lang.String config; + public void setConfig(java.lang.String config) { + this.config = config; + } + public java.lang.String getConfig() { + return this.config; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/SetVmDGpuStrategyResult.java b/sdk/src/main/java/org/zstack/sdk/SetVmDGpuStrategyResult.java deleted file mode 100644 index d7815916628..00000000000 --- a/sdk/src/main/java/org/zstack/sdk/SetVmDGpuStrategyResult.java +++ /dev/null @@ -1,7 +0,0 @@ -package org.zstack.sdk; - - - -public class SetVmDGpuStrategyResult { - -} diff --git a/sdk/src/main/java/org/zstack/sdk/SyncCdnModelServiceTemplateAction.java b/sdk/src/main/java/org/zstack/sdk/SyncCdnModelServiceTemplateAction.java new file mode 100644 index 00000000000..22ab1ad3dd3 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/SyncCdnModelServiceTemplateAction.java @@ -0,0 +1,92 @@ +package org.zstack.sdk; + +import java.util.HashMap; +import java.util.Map; +import org.zstack.sdk.*; + +public class SyncCdnModelServiceTemplateAction extends AbstractAction { + + private static final HashMap parameterMap = new HashMap<>(); + + private static final HashMap nonAPIParameterMap = new HashMap<>(); + + public static class Result { + public ErrorCode error; + public org.zstack.sdk.SyncCdnModelServiceTemplateResult value; + + public Result throwExceptionIfError() { + if (error != null) { + throw new ApiException( + String.format("error[code: %s, description: %s, details: %s, globalErrorCode: %s]", error.code, error.description, error.details, error.globalErrorCode) + ); + } + + return this; + } + } + + @Param(required = false) + public java.util.List systemTags; + + @Param(required = false) + public java.util.List userTags; + + @Param(required = false) + public String sessionId; + + @Param(required = false) + public String accessKeyId; + + @Param(required = false) + public String accessKeySecret; + + @Param(required = false) + public String requestIp; + + + private Result makeResult(ApiResult res) { + Result ret = new Result(); + if (res.error != null) { + ret.error = res.error; + return ret; + } + + org.zstack.sdk.SyncCdnModelServiceTemplateResult value = res.getResult(org.zstack.sdk.SyncCdnModelServiceTemplateResult.class); + ret.value = value == null ? new org.zstack.sdk.SyncCdnModelServiceTemplateResult() : value; + + return ret; + } + + public Result call() { + ApiResult res = ZSClient.call(this); + return makeResult(res); + } + + public void call(final Completion completion) { + ZSClient.call(this, new InternalCompletion() { + @Override + public void complete(ApiResult res) { + completion.complete(makeResult(res)); + } + }); + } + + protected Map getParameterMap() { + return parameterMap; + } + + protected Map getNonAPIParameterMap() { + return nonAPIParameterMap; + } + + protected RestInfo getRestInfo() { + RestInfo info = new RestInfo(); + info.httpMethod = "POST"; + info.path = "/ai/model-services/template/cdn/actions/sync"; + info.needSession = true; + info.needPoll = false; + info.parameterName = "param"; + return info; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/SyncCdnModelServiceTemplateResult.java b/sdk/src/main/java/org/zstack/sdk/SyncCdnModelServiceTemplateResult.java new file mode 100644 index 00000000000..e8213166b5d --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/SyncCdnModelServiceTemplateResult.java @@ -0,0 +1,22 @@ +package org.zstack.sdk; + + + +public class SyncCdnModelServiceTemplateResult { + public int syncedCount; + public void setSyncedCount(int syncedCount) { + this.syncedCount = syncedCount; + } + public int getSyncedCount() { + return this.syncedCount; + } + + public java.util.List templates; + public void setTemplates(java.util.List templates) { + this.templates = templates; + } + public java.util.List getTemplates() { + return this.templates; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/UpdateAiHostModelCachePolicyAction.java b/sdk/src/main/java/org/zstack/sdk/UpdateAiHostModelCachePolicyAction.java new file mode 100644 index 00000000000..68d150a9219 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/UpdateAiHostModelCachePolicyAction.java @@ -0,0 +1,119 @@ +package org.zstack.sdk; + +import java.util.HashMap; +import java.util.Map; +import org.zstack.sdk.*; + +public class UpdateAiHostModelCachePolicyAction extends AbstractAction { + + private static final HashMap parameterMap = new HashMap<>(); + + private static final HashMap nonAPIParameterMap = new HashMap<>(); + + public static class Result { + public ErrorCode error; + public org.zstack.sdk.UpdateAiHostModelCachePolicyResult value; + + public Result throwExceptionIfError() { + if (error != null) { + throw new ApiException( + String.format("error[code: %s, description: %s, details: %s, globalErrorCode: %s]", error.code, error.description, error.details, error.globalErrorCode) + ); + } + + return this; + } + } + + @Param(required = true, nonempty = true, nullElements = false, emptyString = false, noTrim = false) + public java.lang.String hostUuid; + + @Param(required = false, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String sourceRoot; + + @Param(required = false, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.Boolean enabled; + + @Param(required = false, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.Long maxSizeBytes; + + @Param(required = false, nonempty = false, nullElements = false, emptyString = true, numberRange = {0L,100L}, noTrim = false) + public java.lang.Integer highWatermarkPercent; + + @Param(required = false, nonempty = false, nullElements = false, emptyString = true, numberRange = {0L,100L}, noTrim = false) + public java.lang.Integer lowWatermarkPercent; + + @Param(required = false, maxLength = 1024, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String disabledReason; + + @Param(required = false) + public java.util.List systemTags; + + @Param(required = false) + public java.util.List userTags; + + @Param(required = false) + public String sessionId; + + @Param(required = false) + public String accessKeyId; + + @Param(required = false) + public String accessKeySecret; + + @Param(required = false) + public String requestIp; + + @NonAPIParam + public long timeout = -1; + + @NonAPIParam + public long pollingInterval = -1; + + + private Result makeResult(ApiResult res) { + Result ret = new Result(); + if (res.error != null) { + ret.error = res.error; + return ret; + } + + org.zstack.sdk.UpdateAiHostModelCachePolicyResult value = res.getResult(org.zstack.sdk.UpdateAiHostModelCachePolicyResult.class); + ret.value = value == null ? new org.zstack.sdk.UpdateAiHostModelCachePolicyResult() : value; + + return ret; + } + + public Result call() { + ApiResult res = ZSClient.call(this); + return makeResult(res); + } + + public void call(final Completion completion) { + ZSClient.call(this, new InternalCompletion() { + @Override + public void complete(ApiResult res) { + completion.complete(makeResult(res)); + } + }); + } + + protected Map getParameterMap() { + return parameterMap; + } + + protected Map getNonAPIParameterMap() { + return nonAPIParameterMap; + } + + protected RestInfo getRestInfo() { + RestInfo info = new RestInfo(); + info.httpMethod = "PUT"; + info.path = "/ai/host-model-cache-policies/{hostUuid}/actions"; + info.needSession = true; + info.needPoll = true; + info.parameterName = "updateAiHostModelCachePolicy"; + return info; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/UpdateAiHostModelCachePolicyResult.java b/sdk/src/main/java/org/zstack/sdk/UpdateAiHostModelCachePolicyResult.java new file mode 100644 index 00000000000..9e2b2870009 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/UpdateAiHostModelCachePolicyResult.java @@ -0,0 +1,14 @@ +package org.zstack.sdk; + +import org.zstack.sdk.AiHostModelCachePolicyInventory; + +public class UpdateAiHostModelCachePolicyResult { + public AiHostModelCachePolicyInventory inventory; + public void setInventory(AiHostModelCachePolicyInventory inventory) { + this.inventory = inventory; + } + public AiHostModelCachePolicyInventory getInventory() { + return this.inventory; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/UpdateHaNetworkGroupAction.java b/sdk/src/main/java/org/zstack/sdk/UpdateHaNetworkGroupAction.java new file mode 100644 index 00000000000..6bbc6dc2350 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/UpdateHaNetworkGroupAction.java @@ -0,0 +1,113 @@ +package org.zstack.sdk; + +import java.util.HashMap; +import java.util.Map; +import org.zstack.sdk.*; + +public class UpdateHaNetworkGroupAction extends AbstractAction { + + private static final HashMap parameterMap = new HashMap<>(); + + private static final HashMap nonAPIParameterMap = new HashMap<>(); + + public static class Result { + public ErrorCode error; + public org.zstack.sdk.UpdateHaNetworkGroupResult value; + + public Result throwExceptionIfError() { + if (error != null) { + throw new ApiException( + String.format("error[code: %s, description: %s, details: %s, globalErrorCode: %s]", error.code, error.description, error.details, error.globalErrorCode) + ); + } + + return this; + } + } + + @Param(required = true, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String uuid; + + @Param(required = false, maxLength = 255, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String name; + + @Param(required = false, maxLength = 2048, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String description; + + @Param(required = false, nonempty = false, nullElements = false, emptyString = true, numberRange = {1L,2147483647L}, noTrim = false) + public java.lang.Integer minAvailableCount; + + @Param(required = false, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.util.List l3NetworkUuids; + + @Param(required = false) + public java.util.List systemTags; + + @Param(required = false) + public java.util.List userTags; + + @Param(required = false) + public String sessionId; + + @Param(required = false) + public String accessKeyId; + + @Param(required = false) + public String accessKeySecret; + + @Param(required = false) + public String requestIp; + + @NonAPIParam + public long timeout = -1; + + @NonAPIParam + public long pollingInterval = -1; + + + private Result makeResult(ApiResult res) { + Result ret = new Result(); + if (res.error != null) { + ret.error = res.error; + return ret; + } + + org.zstack.sdk.UpdateHaNetworkGroupResult value = res.getResult(org.zstack.sdk.UpdateHaNetworkGroupResult.class); + ret.value = value == null ? new org.zstack.sdk.UpdateHaNetworkGroupResult() : value; + + return ret; + } + + public Result call() { + ApiResult res = ZSClient.call(this); + return makeResult(res); + } + + public void call(final Completion completion) { + ZSClient.call(this, new InternalCompletion() { + @Override + public void complete(ApiResult res) { + completion.complete(makeResult(res)); + } + }); + } + + protected Map getParameterMap() { + return parameterMap; + } + + protected Map getNonAPIParameterMap() { + return nonAPIParameterMap; + } + + protected RestInfo getRestInfo() { + RestInfo info = new RestInfo(); + info.httpMethod = "PUT"; + info.path = "/ha/network-groups/{uuid}"; + info.needSession = true; + info.needPoll = true; + info.parameterName = "updateHaNetworkGroup"; + return info; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/UpdateHaNetworkGroupResult.java b/sdk/src/main/java/org/zstack/sdk/UpdateHaNetworkGroupResult.java new file mode 100644 index 00000000000..d2294f92d05 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/UpdateHaNetworkGroupResult.java @@ -0,0 +1,14 @@ +package org.zstack.sdk; + +import org.zstack.sdk.HaNetworkGroupInventory; + +public class UpdateHaNetworkGroupResult { + public HaNetworkGroupInventory inventory; + public void setInventory(HaNetworkGroupInventory inventory) { + this.inventory = inventory; + } + public HaNetworkGroupInventory getInventory() { + return this.inventory; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/UpdateModelAction.java b/sdk/src/main/java/org/zstack/sdk/UpdateModelAction.java index f7936631adf..0d0025b5e8f 100644 --- a/sdk/src/main/java/org/zstack/sdk/UpdateModelAction.java +++ b/sdk/src/main/java/org/zstack/sdk/UpdateModelAction.java @@ -61,6 +61,9 @@ public Result throwExceptionIfError() { @Param(required = false, nonempty = false, nullElements = false, emptyString = true, noTrim = false) public java.lang.String defaultModelServiceUuid; + @Param(required = false, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.Boolean clearDefaultModelService; + @Param(required = false) public java.util.List systemTags; diff --git a/sdk/src/main/java/org/zstack/sdk/UpdateModelCenterAction.java b/sdk/src/main/java/org/zstack/sdk/UpdateModelCenterAction.java index 95cddcf3b8e..ce8ac2a2890 100644 --- a/sdk/src/main/java/org/zstack/sdk/UpdateModelCenterAction.java +++ b/sdk/src/main/java/org/zstack/sdk/UpdateModelCenterAction.java @@ -46,6 +46,9 @@ public Result throwExceptionIfError() { @Param(required = false, nonempty = false, nullElements = false, emptyString = true, noTrim = false) public java.lang.Integer managementPort; + @Param(required = false, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String zoneUuid; + @Param(required = false, nonempty = false, nullElements = false, emptyString = true, noTrim = false) public java.lang.String storageNetworkUuid; diff --git a/sdk/src/main/java/org/zstack/sdk/UpdateNativeClusterZakuHealthStatusAction.java b/sdk/src/main/java/org/zstack/sdk/UpdateNativeClusterZakuHealthStatusAction.java new file mode 100644 index 00000000000..788bde3715e --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/UpdateNativeClusterZakuHealthStatusAction.java @@ -0,0 +1,104 @@ +package org.zstack.sdk; + +import java.util.HashMap; +import java.util.Map; +import org.zstack.sdk.*; + +public class UpdateNativeClusterZakuHealthStatusAction extends AbstractAction { + + private static final HashMap parameterMap = new HashMap<>(); + + private static final HashMap nonAPIParameterMap = new HashMap<>(); + + public static class Result { + public ErrorCode error; + public org.zstack.sdk.UpdateNativeClusterZakuHealthStatusResult value; + + public Result throwExceptionIfError() { + if (error != null) { + throw new ApiException( + String.format("error[code: %s, description: %s, details: %s, globalErrorCode: %s]", error.code, error.description, error.details, error.globalErrorCode) + ); + } + + return this; + } + } + + @Param(required = true, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String uuid; + + @Param(required = true, validValues = {"Unknown","Healthy","Unhealthy"}, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String zakuHealthStatus; + + @Param(required = false) + public java.util.List systemTags; + + @Param(required = false) + public java.util.List userTags; + + @Param(required = false) + public String sessionId; + + @Param(required = false) + public String accessKeyId; + + @Param(required = false) + public String accessKeySecret; + + @Param(required = false) + public String requestIp; + + @NonAPIParam + public long timeout = -1; + + @NonAPIParam + public long pollingInterval = -1; + + + private Result makeResult(ApiResult res) { + Result ret = new Result(); + if (res.error != null) { + ret.error = res.error; + return ret; + } + + org.zstack.sdk.UpdateNativeClusterZakuHealthStatusResult value = res.getResult(org.zstack.sdk.UpdateNativeClusterZakuHealthStatusResult.class); + ret.value = value == null ? new org.zstack.sdk.UpdateNativeClusterZakuHealthStatusResult() : value; + + return ret; + } + + public Result call() { + ApiResult res = ZSClient.call(this); + return makeResult(res); + } + + public void call(final Completion completion) { + ZSClient.call(this, new InternalCompletion() { + @Override + public void complete(ApiResult res) { + completion.complete(makeResult(res)); + } + }); + } + + protected Map getParameterMap() { + return parameterMap; + } + + protected Map getNonAPIParameterMap() { + return nonAPIParameterMap; + } + + protected RestInfo getRestInfo() { + RestInfo info = new RestInfo(); + info.httpMethod = "PUT"; + info.path = "/container/native/cluster/{uuid}/actions"; + info.needSession = true; + info.needPoll = true; + info.parameterName = "updateNativeClusterZakuHealthStatus"; + return info; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/UpdateNativeClusterZakuHealthStatusResult.java b/sdk/src/main/java/org/zstack/sdk/UpdateNativeClusterZakuHealthStatusResult.java new file mode 100644 index 00000000000..082f307a4b4 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/UpdateNativeClusterZakuHealthStatusResult.java @@ -0,0 +1,14 @@ +package org.zstack.sdk; + +import org.zstack.sdk.NativeClusterInventory; + +public class UpdateNativeClusterZakuHealthStatusResult { + public NativeClusterInventory inventory; + public void setInventory(NativeClusterInventory inventory) { + this.inventory = inventory; + } + public NativeClusterInventory getInventory() { + return this.inventory; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/UpdateVmDGpuAction.java b/sdk/src/main/java/org/zstack/sdk/UpdateVmDGpuAction.java new file mode 100644 index 00000000000..090d04f5b3f --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/UpdateVmDGpuAction.java @@ -0,0 +1,113 @@ +package org.zstack.sdk; + +import java.util.HashMap; +import java.util.Map; +import org.zstack.sdk.*; + +public class UpdateVmDGpuAction extends AbstractAction { + + private static final HashMap parameterMap = new HashMap<>(); + + private static final HashMap nonAPIParameterMap = new HashMap<>(); + + public static class Result { + public ErrorCode error; + public org.zstack.sdk.UpdateVmDGpuResult value; + + public Result throwExceptionIfError() { + if (error != null) { + throw new ApiException( + String.format("error[code: %s, description: %s, details: %s, globalErrorCode: %s]", error.code, error.description, error.details, error.globalErrorCode) + ); + } + + return this; + } + } + + @Param(required = true, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String vmInstanceUuid; + + @Param(required = true, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String dgpuProfileUuid; + + @Param(required = false, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String gpuDeviceUuid; + + @Param(required = true, validValues = {"BySpec","ByDevice"}, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String chooser; + + @Param(required = false, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.Boolean autoDetachOnStop; + + @Param(required = false) + public java.util.List systemTags; + + @Param(required = false) + public java.util.List userTags; + + @Param(required = false) + public String sessionId; + + @Param(required = false) + public String accessKeyId; + + @Param(required = false) + public String accessKeySecret; + + @Param(required = false) + public String requestIp; + + @NonAPIParam + public long timeout = -1; + + @NonAPIParam + public long pollingInterval = -1; + + + private Result makeResult(ApiResult res) { + Result ret = new Result(); + if (res.error != null) { + ret.error = res.error; + return ret; + } + + org.zstack.sdk.UpdateVmDGpuResult value = res.getResult(org.zstack.sdk.UpdateVmDGpuResult.class); + ret.value = value == null ? new org.zstack.sdk.UpdateVmDGpuResult() : value; + + return ret; + } + + public Result call() { + ApiResult res = ZSClient.call(this); + return makeResult(res); + } + + public void call(final Completion completion) { + ZSClient.call(this, new InternalCompletion() { + @Override + public void complete(ApiResult res) { + completion.complete(makeResult(res)); + } + }); + } + + protected Map getParameterMap() { + return parameterMap; + } + + protected Map getNonAPIParameterMap() { + return nonAPIParameterMap; + } + + protected RestInfo getRestInfo() { + RestInfo info = new RestInfo(); + info.httpMethod = "PUT"; + info.path = "/vm-instances/{vmInstanceUuid}/actions"; + info.needSession = true; + info.needPoll = true; + info.parameterName = "updateVmDGpu"; + return info; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/UpdateVmDGpuResult.java b/sdk/src/main/java/org/zstack/sdk/UpdateVmDGpuResult.java new file mode 100644 index 00000000000..e9113800099 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/UpdateVmDGpuResult.java @@ -0,0 +1,7 @@ +package org.zstack.sdk; + + + +public class UpdateVmDGpuResult { + +} diff --git a/sdk/src/main/java/org/zstack/sdk/VmModelMountInventory.java b/sdk/src/main/java/org/zstack/sdk/VmModelMountInventory.java index e328b9292b4..3ba54b88f0d 100644 --- a/sdk/src/main/java/org/zstack/sdk/VmModelMountInventory.java +++ b/sdk/src/main/java/org/zstack/sdk/VmModelMountInventory.java @@ -52,6 +52,14 @@ public java.lang.String getSourcePath() { return this.sourcePath; } + public java.lang.String cacheUuid; + public void setCacheUuid(java.lang.String cacheUuid) { + this.cacheUuid = cacheUuid; + } + public java.lang.String getCacheUuid() { + return this.cacheUuid; + } + public VmModelMountStatus status; public void setStatus(VmModelMountStatus status) { this.status = status; diff --git a/sdk/src/main/java/org/zstack/sdk/ZdfsInventory.java b/sdk/src/main/java/org/zstack/sdk/ZdfsInventory.java index 4697da9943f..f6920f8748d 100644 --- a/sdk/src/main/java/org/zstack/sdk/ZdfsInventory.java +++ b/sdk/src/main/java/org/zstack/sdk/ZdfsInventory.java @@ -68,6 +68,14 @@ public int getSshPort() { return this.sshPort; } + public int metaServerPort; + public void setMetaServerPort(int metaServerPort) { + this.metaServerPort = metaServerPort; + } + public int getMetaServerPort() { + return this.metaServerPort; + } + public java.sql.Timestamp createDate; public void setCreateDate(java.sql.Timestamp createDate) { this.createDate = createDate; diff --git a/sdk/src/main/java/org/zstack/sdk/network/zns/CreateL2GeneveNetworkAction.java b/sdk/src/main/java/org/zstack/sdk/network/zns/CreateL2GeneveNetworkAction.java new file mode 100644 index 00000000000..16c4675b2c8 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/network/zns/CreateL2GeneveNetworkAction.java @@ -0,0 +1,131 @@ +package org.zstack.sdk.network.zns; + +import java.util.HashMap; +import java.util.Map; +import org.zstack.sdk.*; + +public class CreateL2GeneveNetworkAction extends AbstractAction { + + private static final HashMap parameterMap = new HashMap<>(); + + private static final HashMap nonAPIParameterMap = new HashMap<>(); + + public static class Result { + public ErrorCode error; + public org.zstack.sdk.CreateL2NetworkResult value; + + public Result throwExceptionIfError() { + if (error != null) { + throw new ApiException( + String.format("error[code: %s, description: %s, details: %s, globalErrorCode: %s]", error.code, error.description, error.details, error.globalErrorCode) + ); + } + + return this; + } + } + + @Param(required = true, nonempty = false, nullElements = false, emptyString = true, numberRange = {1L,16777214L}, noTrim = false) + public java.lang.Integer geneveId; + + @Param(required = true, maxLength = 255, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String name; + + @Param(required = false, maxLength = 2048, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String description; + + @Param(required = true, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String zoneUuid; + + @Param(required = false, maxLength = 1024, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String physicalInterface; + + @Param(required = false) + public java.lang.String type; + + @Param(required = false, validValues = {"LinuxBridge","OvsDpdk","MacVlan","OvnDpdk"}, maxLength = 1024, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String vSwitchType = "LinuxBridge"; + + @Param(required = false, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.Boolean isolated = false; + + @Param(required = false, nonempty = false, nullElements = false, emptyString = false, noTrim = false) + public java.lang.String pvlan; + + @Param(required = false) + public java.lang.String resourceUuid; + + @Param(required = false, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.util.List tagUuids; + + @Param(required = false) + public java.util.List systemTags; + + @Param(required = false) + public java.util.List userTags; + + @Param(required = false) + public String sessionId; + + @Param(required = false) + public String accessKeyId; + + @Param(required = false) + public String accessKeySecret; + + @Param(required = false) + public String requestIp; + + @NonAPIParam + public long timeout = -1; + + @NonAPIParam + public long pollingInterval = -1; + + + private Result makeResult(ApiResult res) { + Result ret = new Result(); + if (res.error != null) { + ret.error = res.error; + return ret; + } + + org.zstack.sdk.CreateL2NetworkResult value = res.getResult(org.zstack.sdk.CreateL2NetworkResult.class); + ret.value = value == null ? new org.zstack.sdk.CreateL2NetworkResult() : value; + + return ret; + } + + public Result call() { + ApiResult res = ZSClient.call(this); + return makeResult(res); + } + + public void call(final Completion completion) { + ZSClient.call(this, new InternalCompletion() { + @Override + public void complete(ApiResult res) { + completion.complete(makeResult(res)); + } + }); + } + + protected Map getParameterMap() { + return parameterMap; + } + + protected Map getNonAPIParameterMap() { + return nonAPIParameterMap; + } + + protected RestInfo getRestInfo() { + RestInfo info = new RestInfo(); + info.httpMethod = "POST"; + info.path = "/l2-networks/geneve"; + info.needSession = true; + info.needPoll = true; + info.parameterName = "params"; + return info; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/network/zns/GetCandidateZnsNicModesForAttachingL3NetworkAction.java b/sdk/src/main/java/org/zstack/sdk/network/zns/GetCandidateZnsNicModesForAttachingL3NetworkAction.java new file mode 100644 index 00000000000..2272e122af2 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/network/zns/GetCandidateZnsNicModesForAttachingL3NetworkAction.java @@ -0,0 +1,104 @@ +package org.zstack.sdk.network.zns; + +import java.util.HashMap; +import java.util.Map; +import org.zstack.sdk.*; + +public class GetCandidateZnsNicModesForAttachingL3NetworkAction extends AbstractAction { + + private static final HashMap parameterMap = new HashMap<>(); + + private static final HashMap nonAPIParameterMap = new HashMap<>(); + + public static class Result { + public ErrorCode error; + public org.zstack.sdk.network.zns.GetCandidateZnsNicModesForAttachingL3NetworkResult value; + + public Result throwExceptionIfError() { + if (error != null) { + throw new ApiException( + String.format("error[code: %s, description: %s, details: %s, globalErrorCode: %s]", error.code, error.description, error.details, error.globalErrorCode) + ); + } + + return this; + } + } + + @Param(required = true, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String vmInstanceUuid; + + @Param(required = true, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String l3NetworkUuid; + + @Param(required = false) + public java.lang.Integer limit = 1000; + + @Param(required = false) + public java.lang.Integer start = 0; + + @Param(required = false) + public java.util.List systemTags; + + @Param(required = false) + public java.util.List userTags; + + @Param(required = false) + public String sessionId; + + @Param(required = false) + public String accessKeyId; + + @Param(required = false) + public String accessKeySecret; + + @Param(required = false) + public String requestIp; + + + private Result makeResult(ApiResult res) { + Result ret = new Result(); + if (res.error != null) { + ret.error = res.error; + return ret; + } + + org.zstack.sdk.network.zns.GetCandidateZnsNicModesForAttachingL3NetworkResult value = res.getResult(org.zstack.sdk.network.zns.GetCandidateZnsNicModesForAttachingL3NetworkResult.class); + ret.value = value == null ? new org.zstack.sdk.network.zns.GetCandidateZnsNicModesForAttachingL3NetworkResult() : value; + + return ret; + } + + public Result call() { + ApiResult res = ZSClient.call(this); + return makeResult(res); + } + + public void call(final Completion completion) { + ZSClient.call(this, new InternalCompletion() { + @Override + public void complete(ApiResult res) { + completion.complete(makeResult(res)); + } + }); + } + + protected Map getParameterMap() { + return parameterMap; + } + + protected Map getNonAPIParameterMap() { + return nonAPIParameterMap; + } + + protected RestInfo getRestInfo() { + RestInfo info = new RestInfo(); + info.httpMethod = "GET"; + info.path = "/vm-instances/{vmInstanceUuid}/zns-nic-mode-candidates"; + info.needSession = true; + info.needPoll = false; + info.parameterName = ""; + return info; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/network/zns/GetCandidateZnsNicModesForAttachingL3NetworkResult.java b/sdk/src/main/java/org/zstack/sdk/network/zns/GetCandidateZnsNicModesForAttachingL3NetworkResult.java new file mode 100644 index 00000000000..d06037cf53a --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/network/zns/GetCandidateZnsNicModesForAttachingL3NetworkResult.java @@ -0,0 +1,14 @@ +package org.zstack.sdk.network.zns; + + + +public class GetCandidateZnsNicModesForAttachingL3NetworkResult { + public java.util.List znsNicModes; + public void setZnsNicModes(java.util.List znsNicModes) { + this.znsNicModes = znsNicModes; + } + public java.util.List getZnsNicModes() { + return this.znsNicModes; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/network/zns/L2GeneveNetworkInventory.java b/sdk/src/main/java/org/zstack/sdk/network/zns/L2GeneveNetworkInventory.java new file mode 100644 index 00000000000..3baa9daea19 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/network/zns/L2GeneveNetworkInventory.java @@ -0,0 +1,23 @@ +package org.zstack.sdk.network.zns; + + + +public class L2GeneveNetworkInventory extends org.zstack.sdk.L2NetworkInventory { + + public java.lang.Integer geneveId; + public void setGeneveId(java.lang.Integer geneveId) { + this.geneveId = geneveId; + } + public java.lang.Integer getGeneveId() { + return this.geneveId; + } + + public java.lang.Integer vni; + public void setVni(java.lang.Integer vni) { + this.vni = vni; + } + public java.lang.Integer getVni() { + return this.vni; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/network/zns/QueryZnsTenantAction.java b/sdk/src/main/java/org/zstack/sdk/network/zns/QueryZnsTenantAction.java new file mode 100644 index 00000000000..3637f519a88 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/network/zns/QueryZnsTenantAction.java @@ -0,0 +1,75 @@ +package org.zstack.sdk.network.zns; + +import java.util.HashMap; +import java.util.Map; +import org.zstack.sdk.*; + +public class QueryZnsTenantAction extends QueryAction { + + private static final HashMap parameterMap = new HashMap<>(); + + private static final HashMap nonAPIParameterMap = new HashMap<>(); + + public static class Result { + public ErrorCode error; + public org.zstack.sdk.network.zns.QueryZnsTenantResult value; + + public Result throwExceptionIfError() { + if (error != null) { + throw new ApiException( + String.format("error[code: %s, description: %s, details: %s, globalErrorCode: %s]", error.code, error.description, error.details, error.globalErrorCode) + ); + } + + return this; + } + } + + + + private Result makeResult(ApiResult res) { + Result ret = new Result(); + if (res.error != null) { + ret.error = res.error; + return ret; + } + + org.zstack.sdk.network.zns.QueryZnsTenantResult value = res.getResult(org.zstack.sdk.network.zns.QueryZnsTenantResult.class); + ret.value = value == null ? new org.zstack.sdk.network.zns.QueryZnsTenantResult() : value; + + return ret; + } + + public Result call() { + ApiResult res = ZSClient.call(this); + return makeResult(res); + } + + public void call(final Completion completion) { + ZSClient.call(this, new InternalCompletion() { + @Override + public void complete(ApiResult res) { + completion.complete(makeResult(res)); + } + }); + } + + protected Map getParameterMap() { + return parameterMap; + } + + protected Map getNonAPIParameterMap() { + return nonAPIParameterMap; + } + + protected RestInfo getRestInfo() { + RestInfo info = new RestInfo(); + info.httpMethod = "GET"; + info.path = "/sdn-controller/zns/tenants"; + info.needSession = true; + info.needPoll = false; + info.parameterName = ""; + return info; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/network/zns/QueryZnsTenantResult.java b/sdk/src/main/java/org/zstack/sdk/network/zns/QueryZnsTenantResult.java new file mode 100644 index 00000000000..3f33998de12 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/network/zns/QueryZnsTenantResult.java @@ -0,0 +1,22 @@ +package org.zstack.sdk.network.zns; + + + +public class QueryZnsTenantResult { + public java.util.List inventories; + public void setInventories(java.util.List inventories) { + this.inventories = inventories; + } + public java.util.List getInventories() { + return this.inventories; + } + + public java.lang.Long total; + public void setTotal(java.lang.Long total) { + this.total = total; + } + public java.lang.Long getTotal() { + return this.total; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/network/zns/QueryZnsTenantRouterAction.java b/sdk/src/main/java/org/zstack/sdk/network/zns/QueryZnsTenantRouterAction.java new file mode 100644 index 00000000000..6145c60fc01 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/network/zns/QueryZnsTenantRouterAction.java @@ -0,0 +1,75 @@ +package org.zstack.sdk.network.zns; + +import java.util.HashMap; +import java.util.Map; +import org.zstack.sdk.*; + +public class QueryZnsTenantRouterAction extends QueryAction { + + private static final HashMap parameterMap = new HashMap<>(); + + private static final HashMap nonAPIParameterMap = new HashMap<>(); + + public static class Result { + public ErrorCode error; + public org.zstack.sdk.network.zns.QueryZnsTenantRouterResult value; + + public Result throwExceptionIfError() { + if (error != null) { + throw new ApiException( + String.format("error[code: %s, description: %s, details: %s, globalErrorCode: %s]", error.code, error.description, error.details, error.globalErrorCode) + ); + } + + return this; + } + } + + + + private Result makeResult(ApiResult res) { + Result ret = new Result(); + if (res.error != null) { + ret.error = res.error; + return ret; + } + + org.zstack.sdk.network.zns.QueryZnsTenantRouterResult value = res.getResult(org.zstack.sdk.network.zns.QueryZnsTenantRouterResult.class); + ret.value = value == null ? new org.zstack.sdk.network.zns.QueryZnsTenantRouterResult() : value; + + return ret; + } + + public Result call() { + ApiResult res = ZSClient.call(this); + return makeResult(res); + } + + public void call(final Completion completion) { + ZSClient.call(this, new InternalCompletion() { + @Override + public void complete(ApiResult res) { + completion.complete(makeResult(res)); + } + }); + } + + protected Map getParameterMap() { + return parameterMap; + } + + protected Map getNonAPIParameterMap() { + return nonAPIParameterMap; + } + + protected RestInfo getRestInfo() { + RestInfo info = new RestInfo(); + info.httpMethod = "GET"; + info.path = "/sdn-controller/zns/tenant-routers"; + info.needSession = true; + info.needPoll = false; + info.parameterName = ""; + return info; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/network/zns/QueryZnsTenantRouterResult.java b/sdk/src/main/java/org/zstack/sdk/network/zns/QueryZnsTenantRouterResult.java new file mode 100644 index 00000000000..d9981b90e35 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/network/zns/QueryZnsTenantRouterResult.java @@ -0,0 +1,22 @@ +package org.zstack.sdk.network.zns; + + + +public class QueryZnsTenantRouterResult { + public java.util.List inventories; + public void setInventories(java.util.List inventories) { + this.inventories = inventories; + } + public java.util.List getInventories() { + return this.inventories; + } + + public java.lang.Long total; + public void setTotal(java.lang.Long total) { + this.total = total; + } + public java.lang.Long getTotal() { + return this.total; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/network/zns/ZnsControllerInventory.java b/sdk/src/main/java/org/zstack/sdk/network/zns/ZnsControllerInventory.java new file mode 100644 index 00000000000..ec0431656a3 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/network/zns/ZnsControllerInventory.java @@ -0,0 +1,31 @@ +package org.zstack.sdk.network.zns; + + + +public class ZnsControllerInventory extends org.zstack.sdk.SdnControllerInventory { + + public java.util.List transportZones; + public void setTransportZones(java.util.List transportZones) { + this.transportZones = transportZones; + } + public java.util.List getTransportZones() { + return this.transportZones; + } + + public java.util.List tenants; + public void setTenants(java.util.List tenants) { + this.tenants = tenants; + } + public java.util.List getTenants() { + return this.tenants; + } + + public java.util.List tenantRouters; + public void setTenantRouters(java.util.List tenantRouters) { + this.tenantRouters = tenantRouters; + } + public java.util.List getTenantRouters() { + return this.tenantRouters; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/network/zns/ZnsTenantInventory.java b/sdk/src/main/java/org/zstack/sdk/network/zns/ZnsTenantInventory.java new file mode 100644 index 00000000000..def84d31247 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/network/zns/ZnsTenantInventory.java @@ -0,0 +1,63 @@ +package org.zstack.sdk.network.zns; + + + +public class ZnsTenantInventory { + + public java.lang.String uuid; + public void setUuid(java.lang.String uuid) { + this.uuid = uuid; + } + public java.lang.String getUuid() { + return this.uuid; + } + + public java.lang.String sdnControllerUuid; + public void setSdnControllerUuid(java.lang.String sdnControllerUuid) { + this.sdnControllerUuid = sdnControllerUuid; + } + public java.lang.String getSdnControllerUuid() { + return this.sdnControllerUuid; + } + + public java.lang.String znsResourceUuid; + public void setZnsResourceUuid(java.lang.String znsResourceUuid) { + this.znsResourceUuid = znsResourceUuid; + } + public java.lang.String getZnsResourceUuid() { + return this.znsResourceUuid; + } + + public java.lang.String name; + public void setName(java.lang.String name) { + this.name = name; + } + public java.lang.String getName() { + return this.name; + } + + public java.lang.String description; + public void setDescription(java.lang.String description) { + this.description = description; + } + public java.lang.String getDescription() { + return this.description; + } + + public java.sql.Timestamp createDate; + public void setCreateDate(java.sql.Timestamp createDate) { + this.createDate = createDate; + } + public java.sql.Timestamp getCreateDate() { + return this.createDate; + } + + public java.sql.Timestamp lastOpDate; + public void setLastOpDate(java.sql.Timestamp lastOpDate) { + this.lastOpDate = lastOpDate; + } + public java.sql.Timestamp getLastOpDate() { + return this.lastOpDate; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/network/zns/ZnsTenantRouterInventory.java b/sdk/src/main/java/org/zstack/sdk/network/zns/ZnsTenantRouterInventory.java new file mode 100644 index 00000000000..a4624e92320 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/network/zns/ZnsTenantRouterInventory.java @@ -0,0 +1,79 @@ +package org.zstack.sdk.network.zns; + + + +public class ZnsTenantRouterInventory { + + public java.lang.String uuid; + public void setUuid(java.lang.String uuid) { + this.uuid = uuid; + } + public java.lang.String getUuid() { + return this.uuid; + } + + public java.lang.String sdnControllerUuid; + public void setSdnControllerUuid(java.lang.String sdnControllerUuid) { + this.sdnControllerUuid = sdnControllerUuid; + } + public java.lang.String getSdnControllerUuid() { + return this.sdnControllerUuid; + } + + public java.lang.String tenantUuid; + public void setTenantUuid(java.lang.String tenantUuid) { + this.tenantUuid = tenantUuid; + } + public java.lang.String getTenantUuid() { + return this.tenantUuid; + } + + public java.lang.String znsResourceUuid; + public void setZnsResourceUuid(java.lang.String znsResourceUuid) { + this.znsResourceUuid = znsResourceUuid; + } + public java.lang.String getZnsResourceUuid() { + return this.znsResourceUuid; + } + + public java.lang.String name; + public void setName(java.lang.String name) { + this.name = name; + } + public java.lang.String getName() { + return this.name; + } + + public java.lang.String description; + public void setDescription(java.lang.String description) { + this.description = description; + } + public java.lang.String getDescription() { + return this.description; + } + + public java.lang.String state; + public void setState(java.lang.String state) { + this.state = state; + } + public java.lang.String getState() { + return this.state; + } + + public java.sql.Timestamp createDate; + public void setCreateDate(java.sql.Timestamp createDate) { + this.createDate = createDate; + } + public java.sql.Timestamp getCreateDate() { + return this.createDate; + } + + public java.sql.Timestamp lastOpDate; + public void setLastOpDate(java.sql.Timestamp lastOpDate) { + this.lastOpDate = lastOpDate; + } + public java.sql.Timestamp getLastOpDate() { + return this.lastOpDate; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/network/zns/ZnsTransportZoneInventory.java b/sdk/src/main/java/org/zstack/sdk/network/zns/ZnsTransportZoneInventory.java new file mode 100644 index 00000000000..890e452aa04 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/network/zns/ZnsTransportZoneInventory.java @@ -0,0 +1,95 @@ +package org.zstack.sdk.network.zns; + + + +public class ZnsTransportZoneInventory { + + public java.lang.String uuid; + public void setUuid(java.lang.String uuid) { + this.uuid = uuid; + } + public java.lang.String getUuid() { + return this.uuid; + } + + public java.lang.String name; + public void setName(java.lang.String name) { + this.name = name; + } + public java.lang.String getName() { + return this.name; + } + + public java.lang.String description; + public void setDescription(java.lang.String description) { + this.description = description; + } + public java.lang.String getDescription() { + return this.description; + } + + public java.lang.String type; + public void setType(java.lang.String type) { + this.type = type; + } + public java.lang.String getType() { + return this.type; + } + + public java.lang.String physicalNetwork; + public void setPhysicalNetwork(java.lang.String physicalNetwork) { + this.physicalNetwork = physicalNetwork; + } + public java.lang.String getPhysicalNetwork() { + return this.physicalNetwork; + } + + public java.lang.String status; + public void setStatus(java.lang.String status) { + this.status = status; + } + public java.lang.String getStatus() { + return this.status; + } + + public boolean isDefault; + public void setIsDefault(boolean isDefault) { + this.isDefault = isDefault; + } + public boolean getIsDefault() { + return this.isDefault; + } + + public java.lang.String tags; + public void setTags(java.lang.String tags) { + this.tags = tags; + } + public java.lang.String getTags() { + return this.tags; + } + + public java.lang.String znsSdnControllerUuid; + public void setZnsSdnControllerUuid(java.lang.String znsSdnControllerUuid) { + this.znsSdnControllerUuid = znsSdnControllerUuid; + } + public java.lang.String getZnsSdnControllerUuid() { + return this.znsSdnControllerUuid; + } + + public java.sql.Timestamp createDate; + public void setCreateDate(java.sql.Timestamp createDate) { + this.createDate = createDate; + } + public java.sql.Timestamp getCreateDate() { + return this.createDate; + } + + public java.sql.Timestamp lastOpDate; + public void setLastOpDate(java.sql.Timestamp lastOpDate) { + this.lastOpDate = lastOpDate; + } + public java.sql.Timestamp getLastOpDate() { + return this.lastOpDate; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/zwatch/alarm/AddLabelToAlarmAction.java b/sdk/src/main/java/org/zstack/sdk/zwatch/alarm/AddLabelToAlarmAction.java index 95b4d5c6283..880b2ffab8e 100644 --- a/sdk/src/main/java/org/zstack/sdk/zwatch/alarm/AddLabelToAlarmAction.java +++ b/sdk/src/main/java/org/zstack/sdk/zwatch/alarm/AddLabelToAlarmAction.java @@ -34,7 +34,7 @@ public Result throwExceptionIfError() { @Param(required = true, nonempty = false, nullElements = false, emptyString = true, noTrim = false) public java.lang.String value; - @Param(required = true, validValues = {"Regex","Equal"}, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + @Param(required = true, validValues = {"Regex","Equal","RegexAgainst","NotEqual"}, nonempty = false, nullElements = false, emptyString = true, noTrim = false) public java.lang.String operator; @Param(required = false) diff --git a/sdk/src/main/java/org/zstack/sdk/zwatch/alarm/UpdateAlarmLabelAction.java b/sdk/src/main/java/org/zstack/sdk/zwatch/alarm/UpdateAlarmLabelAction.java index a953f33e32b..507a121d590 100644 --- a/sdk/src/main/java/org/zstack/sdk/zwatch/alarm/UpdateAlarmLabelAction.java +++ b/sdk/src/main/java/org/zstack/sdk/zwatch/alarm/UpdateAlarmLabelAction.java @@ -34,7 +34,7 @@ public Result throwExceptionIfError() { @Param(required = true, nonempty = false, nullElements = false, emptyString = true, noTrim = false) public java.lang.String value; - @Param(required = true, validValues = {"Regex","Equal"}, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + @Param(required = true, validValues = {"Regex","Equal","RegexAgainst","NotEqual"}, nonempty = false, nullElements = false, emptyString = true, noTrim = false) public java.lang.String operator; @Param(required = false) diff --git a/search/src/main/java/org/zstack/query/QueryFacadeImpl.java b/search/src/main/java/org/zstack/query/QueryFacadeImpl.java index 9bd8fa8c724..00c43997d01 100755 --- a/search/src/main/java/org/zstack/query/QueryFacadeImpl.java +++ b/search/src/main/java/org/zstack/query/QueryFacadeImpl.java @@ -349,7 +349,7 @@ private Method getReplySetter(AutoQuery at) { } } - private void handle(APIQueryMessage msg) { + private APIQueryReply doQuery(APIQueryMessage msg) { AutoQuery at = autoQueryMap.get(msg.getClass()); if (at == null) { at = msg.getClass().getAnnotation(AutoQuery.class); @@ -374,7 +374,7 @@ private void handle(APIQueryMessage msg) { if (result.inventories != null) { replySetter.invoke(reply, result.inventories); } - bus.reply(msg, reply); + return reply; } catch (OperationFailureException of) { throw of; } catch (Exception e) { @@ -382,6 +382,39 @@ private void handle(APIQueryMessage msg) { } } + private void handle(APIQueryMessage msg) { + thdf.syncSubmit(new SyncTask() { + @Override + public Void call() { + APIQueryReply reply; + try { + reply = doQuery(msg); + } catch (OperationFailureException of) { + reply = new APIQueryReply(); + reply.setError(of.getErrorCode()); + } + + bus.reply(msg, reply); + return null; + } + + @Override + public String getName() { + return getSyncSignature(); + } + + @Override + public String getSyncSignature() { + return "api-query"; + } + + @Override + public int getSyncLevel() { + return getQuerySyncLevel(); + } + }); + } + private String toZQLConditionString(QueryCondition c) { // make every condition value as string, the ZQL // will put them in right type because it knows every field's type diff --git a/search/src/main/java/org/zstack/zql/ast/ZQLMetadata.java b/search/src/main/java/org/zstack/zql/ast/ZQLMetadata.java index 40141fd9a5b..cdcbb094a91 100755 --- a/search/src/main/java/org/zstack/zql/ast/ZQLMetadata.java +++ b/search/src/main/java/org/zstack/zql/ast/ZQLMetadata.java @@ -110,7 +110,7 @@ public boolean hasInventoryField(String fname) { public void errorIfNoField(String fname) { if (!hasInventoryField(fname)) { - throw new CloudRuntimeException(String.format("inventory[${selfInventoryClass}] has no field[%s]", fname)); + throw new CloudRuntimeException(String.format("inventory[%s] has no field[%s]", simpleInventoryName(), fname)); } } diff --git a/simulator/simulatorImpl/src/main/java/org/zstack/simulator/kvm/KVMSimulatorConfig.java b/simulator/simulatorImpl/src/main/java/org/zstack/simulator/kvm/KVMSimulatorConfig.java index 4a1cfaa1798..4fd96811d08 100755 --- a/simulator/simulatorImpl/src/main/java/org/zstack/simulator/kvm/KVMSimulatorConfig.java +++ b/simulator/simulatorImpl/src/main/java/org/zstack/simulator/kvm/KVMSimulatorConfig.java @@ -85,6 +85,9 @@ public class KVMSimulatorConfig { public volatile boolean vmSyncSuccess = true; public List hardenVmConsoleCmds = new ArrayList(); public List deleteVmConsoleFirewallCmds = new ArrayList(); + public volatile List setupVmHaEnabledMetadataLiveCmds = new ArrayList(); + public volatile List reconcileVmHaEnabledMetadataLiveCmds = new ArrayList(); + public volatile List syncHaNetworkGroupConfigCmds = new ArrayList(); public Map takeSnapshotCmdSize = new HashMap(); } diff --git a/simulator/simulatorImpl/src/main/java/org/zstack/simulator/kvm/KVMSimulatorController.java b/simulator/simulatorImpl/src/main/java/org/zstack/simulator/kvm/KVMSimulatorController.java index 802fffbd702..e58b718cfd7 100755 --- a/simulator/simulatorImpl/src/main/java/org/zstack/simulator/kvm/KVMSimulatorController.java +++ b/simulator/simulatorImpl/src/main/java/org/zstack/simulator/kvm/KVMSimulatorController.java @@ -705,6 +705,38 @@ private void getVncPort(HttpEntity entity) { replyer.reply(entity, rsp); } + @RequestMapping(value = KVMConstant.SETUP_VM_HA_ENABLED_METADATA_LIVE_PATH, method = RequestMethod.POST) + private @ResponseBody String setupVmHaEnabledMetadataLive(HttpServletRequest req) { + HttpEntity entity = restf.httpServletRequestToHttpEntity(req); + SetupVmHaEnabledMetadataLiveCmd cmd = JSONObjectUtil.toObject(entity.getBody(), SetupVmHaEnabledMetadataLiveCmd.class); + synchronized (config.setupVmHaEnabledMetadataLiveCmds) { + config.setupVmHaEnabledMetadataLiveCmds.add(cmd); + } + replyer.reply(entity, new AgentResponse()); + return null; + } + + @RequestMapping(value = KVMConstant.RECONCILE_VM_HA_ENABLED_METADATA_LIVE_PATH, method = RequestMethod.POST) + private @ResponseBody String reconcileVmHaEnabledMetadataLive(HttpServletRequest req) { + HttpEntity entity = restf.httpServletRequestToHttpEntity(req); + ReconcileVmHaEnabledMetadataLiveCmd cmd = JSONObjectUtil.toObject(entity.getBody(), ReconcileVmHaEnabledMetadataLiveCmd.class); + synchronized (config.reconcileVmHaEnabledMetadataLiveCmds) { + config.reconcileVmHaEnabledMetadataLiveCmds.add(cmd); + } + replyer.reply(entity, new AgentResponse()); + return null; + } + + @RequestMapping(value = KVMConstant.HA_NETWORK_GROUP_SYNC_PATH, method = RequestMethod.POST) + private @ResponseBody String syncHaNetworkGroupConfig(HttpServletRequest req) { + HttpEntity entity = restf.httpServletRequestToHttpEntity(req); + synchronized (config.syncHaNetworkGroupConfigCmds) { + config.syncHaNetworkGroupConfigCmds.add(entity.getBody()); + } + replyer.reply(entity, new AgentResponse()); + return null; + } + @RequestMapping(value=KVMConstant.KVM_LOGOUT_ISCSI_PATH, method=RequestMethod.POST) private @ResponseBody String logoutIscsiTarget(HttpServletRequest req) throws InterruptedException { HttpEntity entity = restf.httpServletRequestToHttpEntity(req); diff --git a/simulator/simulatorImpl/src/main/java/org/zstack/simulator/storage/primary/SimulatorPrimaryStorage.java b/simulator/simulatorImpl/src/main/java/org/zstack/simulator/storage/primary/SimulatorPrimaryStorage.java index 0efb78db682..021eb33ebc6 100755 --- a/simulator/simulatorImpl/src/main/java/org/zstack/simulator/storage/primary/SimulatorPrimaryStorage.java +++ b/simulator/simulatorImpl/src/main/java/org/zstack/simulator/storage/primary/SimulatorPrimaryStorage.java @@ -23,6 +23,8 @@ import static org.zstack.core.Platform.err; import static org.zstack.utils.clouderrorcode.CloudOperationsErrorCode.*; +import org.zstack.header.storage.primary.ReInitDataVolumeOnPrimaryStorageMsg; +import org.zstack.header.storage.primary.ReInitDataVolumeOnPrimaryStorageReply; public class SimulatorPrimaryStorage extends PrimaryStorageBase { @@ -219,6 +221,14 @@ protected void handle(ReInitRootVolumeFromTemplateOnPrimaryStorageMsg msg) { bus.reply(msg, reply); } + @Override + protected void handle(ReInitDataVolumeOnPrimaryStorageMsg msg) { + ReInitDataVolumeOnPrimaryStorageReply reply = new ReInitDataVolumeOnPrimaryStorageReply(); + reply.setSuccess(true); + bus.reply(msg, reply); + } + + @Override protected void connectHook(ConnectParam param, Completion completion) { completion.success(); diff --git a/storage/src/main/java/org/zstack/storage/addon/primary/ExternalPrimaryStorage.java b/storage/src/main/java/org/zstack/storage/addon/primary/ExternalPrimaryStorage.java index 332b10331a1..921c8431326 100644 --- a/storage/src/main/java/org/zstack/storage/addon/primary/ExternalPrimaryStorage.java +++ b/storage/src/main/java/org/zstack/storage/addon/primary/ExternalPrimaryStorage.java @@ -28,7 +28,10 @@ import org.zstack.header.errorcode.ErrorCodeList; import org.zstack.header.errorcode.OperationFailureException; import org.zstack.header.host.HostInventory; +import org.zstack.header.host.HostState; +import org.zstack.header.host.HostStatus; import org.zstack.header.host.HostVO; +import org.zstack.header.host.HostVO_; import org.zstack.header.image.ImageConstant; import org.zstack.header.image.ImageInventory; import org.zstack.header.image.ImageVO; @@ -65,6 +68,7 @@ import static org.zstack.core.Platform.operr; import static org.zstack.storage.addon.primary.ExternalPrimaryStorageNameHelper.*; import static org.zstack.utils.clouderrorcode.CloudOperationsErrorCode.*; +import org.zstack.header.storage.primary.ReInitDataVolumeOnPrimaryStorageMsg; @Configurable(preConstruction = true, autowire = Autowire.BY_TYPE, dependencyCheck = true) @@ -113,6 +117,61 @@ public ExternalPrimaryStorage(ExternalPrimaryStorage other) { this.selfConfig = other.selfConfig; } + @Override + public void attachHook(String clusterUuid, Completion completion) { + List hosts = Q.New(HostVO.class) + .eq(HostVO_.clusterUuid, clusterUuid) + .eq(HostVO_.status, HostStatus.Connected) + .notIn(HostVO_.state, Arrays.asList(HostState.PreMaintenance, HostState.Maintenance)) + .list(); + if (hosts.isEmpty()) { + completion.success(); + return; + } + + List hostInventories = HostInventory.valueOf(hosts); + // Deploy-client is idempotent. Hosts prepared before an attach failure are left for + // the next attach or reconnect to overwrite. + new While<>(hostInventories).each((host, compl) -> { + node.deployClient(host, new Completion(compl) { + @Override + public void success() { + compl.done(); + } + + @Override + public void fail(ErrorCode errorCode) { + compl.addError(errorCode); + compl.allDone(); + } + }); + }).run(new WhileDoneCompletion(completion) { + @Override + public void done(ErrorCodeList errorCodeList) { + if (!errorCodeList.getCauses().isEmpty()) { + completion.fail(errorCodeList.getCauses().get(0)); + return; + } + + activateHeartbeatVolumeForAttach(hostInventories.get(0), completion); + } + }); + } + + private void activateHeartbeatVolumeForAttach(HostInventory host, Completion completion) { + node.activateHeartbeatVolume(host, new ReturnValueCompletion(completion) { + @Override + public void success(HeartbeatVolumeTopology returnValue) { + completion.success(); + } + + @Override + public void fail(ErrorCode errorCode) { + completion.fail(errorCode); + } + }); + } + @Override public void handleMessage(Message msg) { if (msg instanceof PrimaryStorageMessage && !destMaker.isManagedByUs(((PrimaryStorageMessage) msg).getPrimaryStorageUuid())) { @@ -2004,6 +2063,12 @@ public void handle(ErrorCode errCode, Map data) { }).start(); } + @Override + protected void handle(ReInitDataVolumeOnPrimaryStorageMsg msg) { + bus.dealWithUnknownMessage(msg); + } + + @Override protected void handle(AskInstallPathForNewSnapshotMsg msg) { AskInstallPathForNewSnapshotReply reply = new AskInstallPathForNewSnapshotReply(); diff --git a/storage/src/main/java/org/zstack/storage/primary/PrimaryStorageBase.java b/storage/src/main/java/org/zstack/storage/primary/PrimaryStorageBase.java index 312d3c20d3f..9920d4900ee 100755 --- a/storage/src/main/java/org/zstack/storage/primary/PrimaryStorageBase.java +++ b/storage/src/main/java/org/zstack/storage/primary/PrimaryStorageBase.java @@ -162,6 +162,8 @@ public void setNewAdded(boolean newAdded) { protected abstract void handle(ReInitRootVolumeFromTemplateOnPrimaryStorageMsg msg); + protected abstract void handle(ReInitDataVolumeOnPrimaryStorageMsg msg); + protected abstract void handle(AskInstallPathForNewSnapshotMsg msg); protected abstract void handle(GetPrimaryStorageResourceLocationMsg msg); @@ -190,7 +192,7 @@ protected String getSyncId() { return String.format("primaryStorage-%s", self.getUuid()); } - protected static List trashLists = CollectionDSL.list(TrashType.MigrateVolume, TrashType.MigrateVolumeSnapshot, TrashType.RevertVolume, TrashType.VolumeSnapshot, TrashType.ReimageVolume); + protected static List trashLists = CollectionDSL.list(TrashType.MigrateVolume, TrashType.MigrateVolumeSnapshot, TrashType.RevertVolume, TrashType.VolumeSnapshot, TrashType.ReimageVolume, TrashType.ReInitDataVolume); protected void fireDisconnectedCanonicalEvent(ErrorCode reason) { PrimaryStorageCanonicalEvent.DisconnectedData data = new PrimaryStorageCanonicalEvent.DisconnectedData(); @@ -313,6 +315,9 @@ private void checkPrimaryStatus(Message msg) { } else if (msg instanceof ReInitRootVolumeFromTemplateOnPrimaryStorageMsg) { new PrimaryStorageValidater().disable().maintenance() .validate(); + } else if (msg instanceof ReInitDataVolumeOnPrimaryStorageMsg) { + new PrimaryStorageValidater().disable().maintenance() + .validate(); } else if (msg instanceof CheckVolumeSnapshotOperationOnPrimaryStorageMsg) { SnapshotBackendOperation operation = ((CheckVolumeSnapshotOperationOnPrimaryStorageMsg) msg).getOperation(); if (operation == SnapshotBackendOperation.FILE_CREATION) { @@ -374,6 +379,8 @@ protected void handleLocalMessage(Message msg) { handle((RevertVolumeFromSnapshotOnPrimaryStorageMsg) msg); } else if (msg instanceof ReInitRootVolumeFromTemplateOnPrimaryStorageMsg) { handle((ReInitRootVolumeFromTemplateOnPrimaryStorageMsg) msg); + } else if (msg instanceof ReInitDataVolumeOnPrimaryStorageMsg) { + handle((ReInitDataVolumeOnPrimaryStorageMsg) msg); } else if (msg instanceof MergeVolumeSnapshotOnPrimaryStorageMsg) { handle((MergeVolumeSnapshotOnPrimaryStorageMsg) msg); } else if (msg instanceof FlattenVolumeOnPrimaryStorageMsg) { diff --git a/storage/src/main/java/org/zstack/storage/primary/PrimaryStorageDeleteBitGC.java b/storage/src/main/java/org/zstack/storage/primary/PrimaryStorageDeleteBitGC.java index 72e3f743001..db8a4ef5093 100644 --- a/storage/src/main/java/org/zstack/storage/primary/PrimaryStorageDeleteBitGC.java +++ b/storage/src/main/java/org/zstack/storage/primary/PrimaryStorageDeleteBitGC.java @@ -53,6 +53,7 @@ protected void triggerNow(GCCompletion completion) { delMsg.setBitsUuid(volume.getUuid()); delMsg.setBitsType(VolumeVO.class.getSimpleName()); delMsg.setPrimaryStorageUuid(primaryStorageUuid); + delMsg.setSize(volume.getSize()); delMsg.setHypervisorType(VolumeFormat.getMasterHypervisorTypeByVolumeFormat(volume.getFormat()).toString()); bus.makeTargetServiceIdByResourceUuid(delMsg, PrimaryStorageConstant.SERVICE_ID, primaryStorageUuid); bus.send(delMsg, new CloudBusCallBack(completion) { @@ -75,4 +76,4 @@ private boolean shouldCancal() { } return false; } -} \ No newline at end of file +} diff --git a/storage/src/main/java/org/zstack/storage/snapshot/VolumeSnapshotManagerImpl.java b/storage/src/main/java/org/zstack/storage/snapshot/VolumeSnapshotManagerImpl.java index 6ac46abd7d8..6555a9b404f 100755 --- a/storage/src/main/java/org/zstack/storage/snapshot/VolumeSnapshotManagerImpl.java +++ b/storage/src/main/java/org/zstack/storage/snapshot/VolumeSnapshotManagerImpl.java @@ -73,6 +73,7 @@ public class VolumeSnapshotManagerImpl extends AbstractService implements VolumeBeforeExpungeExtensionPoint, ResourceOwnerAfterChangeExtensionPoint, ReportQuotaExtensionPoint, + VolumeSnapshotDBSyncExtensionPoint, AfterReimageVmInstanceExtensionPoint, VmJustBeforeDeleteFromDbExtensionPoint, VolumeJustBeforeDeleteFromDbExtensionPoint, @@ -157,8 +158,8 @@ private void handleLocalMessage(Message msg) { handle((CreateVolumeSnapshotMsg) msg); } else if (msg instanceof VolumeSnapshotReportPrimaryStorageCapacityUsageMsg) { handle((VolumeSnapshotReportPrimaryStorageCapacityUsageMsg) msg); - } else if (msg instanceof MarkRootVolumeAsSnapshotMsg) { - handle((MarkRootVolumeAsSnapshotMsg) msg); + } else if (msg instanceof MarkVolumeAsSnapshotMsg) { + handle((MarkVolumeAsSnapshotMsg) msg); } else if (msg instanceof AskVolumeSnapshotStructMsg) { handle((AskVolumeSnapshotStructMsg) msg); } else if (msg instanceof GetVolumeSnapshotTreeRootNodeMsg) { @@ -680,6 +681,12 @@ private void rollbackSnapshot(String uuid) { return; } + if (vo.getStatus() == VolumeSnapshotStatus.Ready) { + logger.warn(String.format("volume snapshot[uuid:%s] has been marked Ready, skip rollback to keep control plane metadata consistent with hypervisor snapshot", + uuid)); + return; + } + dbf.getEntityManager().remove(vo); String sql = "delete from AccountResourceRefVO where resourceUuid = :vsUuid and resourceType = 'VolumeSnapshotVO'"; @@ -697,6 +704,42 @@ private void rollbackSnapshot(String uuid) { } } + @Override + @Transactional + public VolumeSnapshotInventory syncVolumeSnapshotDBAfterTakeSnapshot(VolumeInventory volume, + VolumeSnapshotInventory snapshot, + String volumeNewInstallPath) { + if (volumeNewInstallPath != null) { + VolumeVO latestVol = dbf.findByUuid(volume.getUuid(), VolumeVO.class); + latestVol.setInstallPath(volumeNewInstallPath); + dbf.update(latestVol); + } + + VolumeSnapshotVO svo = dbf.findByUuid(snapshot.getUuid(), VolumeSnapshotVO.class); + if (svo == null) { + return null; + } + + svo.setType(snapshot.getType()); + svo.setPrimaryStorageUuid(snapshot.getPrimaryStorageUuid()); + svo.setPrimaryStorageInstallPath(snapshot.getPrimaryStorageInstallPath()); + svo.setStatus(VolumeSnapshotStatus.Ready); + svo.setSize(snapshot.getSize()); + if (snapshot.getFormat() != null) { + svo.setFormat(snapshot.getFormat()); + } + svo = dbf.updateAndRefresh(svo); + + markSnapshotTreeCompleted(VolumeSnapshotInventory.valueOf(svo)); + if (svo.getParentUuid() == null) { + VolumeSnapshotReferenceUtils.updateReferenceAfterFirstSnapshot(svo); + } + + logger.debug(String.format("synced volume snapshot[uuid:%s] metadata after hypervisor snapshot succeeded", + svo.getUuid())); + return VolumeSnapshotInventory.valueOf(svo); + } + private void handle(final AskVolumeSnapshotStructMsg msg) { AskVolumeSnapshotStructReply reply = new AskVolumeSnapshotStructReply(); CreateVolumeSnapshotMsg cmsg = new CreateVolumeSnapshotMsg(); @@ -991,33 +1034,14 @@ public void run(MessageReply reply) { done(new FlowDoneHandler(msg) { @Override public void handle(Map data) { - markSnapshotTreeCompleted(snapshot); - if (volumeNewInstallPath != null) { - vol.setInstallPath(volumeNewInstallPath); - dbf.update(vol); - } - - VolumeSnapshotVO svo = dbf.findByUuid(snapshot.getUuid(), VolumeSnapshotVO.class); - svo.setType(snapshot.getType()); - svo.setPrimaryStorageUuid(snapshot.getPrimaryStorageUuid()); - svo.setPrimaryStorageInstallPath(snapshot.getPrimaryStorageInstallPath()); - svo.setStatus(VolumeSnapshotStatus.Ready); - svo.setSize(snapshot.getSize()); - if (snapshot.getFormat() != null) { - svo.setFormat(snapshot.getFormat()); - } - svo = dbf.updateAndRefresh(svo); - - if (struct.isNewChain()) { - VolumeSnapshotReferenceUtils.updateReferenceAfterFirstSnapshot(svo); - } + VolumeSnapshotInventory sp = syncVolumeSnapshotDBAfterTakeSnapshot( + vol.toInventory(), snapshot, volumeNewInstallPath); new FireSnapShotCanonicalEvent(). fireSnapShotStatusChangedEvent( VolumeSnapshotStatus.valueOf(snapshot.getStatus()), - VolumeSnapshotInventory.valueOf(svo)); + sp); - VolumeSnapshotInventory sp = svo.toInventory(); callExtensionPoints(sp); ret.setInventory(sp); @@ -1034,8 +1058,18 @@ private void callExtensionPoints(VolumeSnapshotInventory sp) { error(new FlowErrorHandler(msg) { @Override public void handle(ErrorCode errCode, Map data) { - if (struct != null) { - rollbackSnapshot(struct.getCurrent().getUuid()); + if (snapshot != null) { + syncVolumeSnapshotDBAfterTakeSnapshot(vol.toInventory(), snapshot, volumeNewInstallPath); + logger.warn(String.format("volume snapshot[uuid:%s] has been created on primary storage, keep database record for recovery after error: %s", + snapshot.getUuid(), errCode)); + } else if (struct != null) { + String snapshotUuid = struct.getCurrent().getUuid(); + if (getCurrentSnapshotStatus(snapshotUuid) == VolumeSnapshotStatus.Ready) { + logger.warn(String.format("volume snapshot[uuid:%s] has been marked Ready, keep database record after error: %s", + snapshotUuid, errCode)); + } else { + rollbackSnapshot(snapshotUuid); + } } ret.setError(errCode); bus.reply(msg, ret); @@ -1045,8 +1079,15 @@ public void handle(ErrorCode errCode, Map data) { }).start(); } - private void handle(MarkRootVolumeAsSnapshotMsg msg) { - final MarkRootVolumeAsSnapshotReply ret = new MarkRootVolumeAsSnapshotReply(); + private VolumeSnapshotStatus getCurrentSnapshotStatus(String uuid) { + return Q.New(VolumeSnapshotVO.class) + .select(VolumeSnapshotVO_.status) + .eq(VolumeSnapshotVO_.uuid, uuid) + .findValue(); + } + + private void handle(MarkVolumeAsSnapshotMsg msg) { + final MarkVolumeAsSnapshotReply ret = new MarkVolumeAsSnapshotReply(); VolumeInventory vol = msg.getVolume(); String psType = Q.New(PrimaryStorageVO.class).select(PrimaryStorageVO_.type).eq(PrimaryStorageVO_.uuid, vol.getPrimaryStorageUuid()).findValue(); diff --git a/storage/src/main/java/org/zstack/storage/volume/VolumeApiInterceptor.java b/storage/src/main/java/org/zstack/storage/volume/VolumeApiInterceptor.java index d1485039388..f9e18f0a1e5 100755 --- a/storage/src/main/java/org/zstack/storage/volume/VolumeApiInterceptor.java +++ b/storage/src/main/java/org/zstack/storage/volume/VolumeApiInterceptor.java @@ -40,6 +40,8 @@ import org.zstack.header.storage.primary.PrimaryStorageHostRefVO; import org.zstack.header.storage.primary.PrimaryStorageHostRefVO_; import org.zstack.header.storage.primary.PrimaryStorageHostStatus; +import org.zstack.header.storage.primary.PrimaryStorageVO; +import org.zstack.header.storage.primary.PrimaryStorageVO_; import org.zstack.header.storage.snapshot.ConsistentType; import org.zstack.header.storage.snapshot.VolumeSnapshotTreeVO; import org.zstack.header.storage.snapshot.VolumeSnapshotTreeVO_; @@ -65,6 +67,7 @@ import org.zstack.header.volume.APIDetachDataVolumeFromVmMsg; import org.zstack.header.volume.APIFlattenVolumeMsg; import org.zstack.header.volume.APIGetDataVolumeAttachableVmMsg; +import org.zstack.header.volume.APIReInitDataVolumeMsg; import org.zstack.header.volume.APIRecoverDataVolumeMsg; import org.zstack.header.volume.APIUndoSnapshotCreationMsg; import org.zstack.header.volume.VolumeConstant; @@ -99,6 +102,8 @@ * To change this template use File | Settings | File Templates. */ public class VolumeApiInterceptor implements ApiMessageInterceptor, Component, GlobalApiMessageInterceptor { + private static final String CEPH_PRIMARY_STORAGE_TYPE = "Ceph"; + @Autowired private CloudBus bus; @Autowired @@ -148,6 +153,8 @@ public APIMessage intercept(APIMessage msg) throws ApiMessageInterceptionExcepti validate((APIDetachDataVolumeFromHostMsg) msg); } else if (msg instanceof APIFlattenVolumeMsg) { validate((APIFlattenVolumeMsg) msg); + } else if (msg instanceof APIReInitDataVolumeMsg) { + validate((APIReInitDataVolumeMsg) msg); } else if (msg instanceof APIUndoSnapshotCreationMsg) { validate((APIUndoSnapshotCreationMsg) msg); } else if (msg instanceof APICreateVmInstanceMsg) { @@ -583,6 +590,57 @@ private void validate(APIFlattenVolumeMsg msg) { } } + private void validate(APIReInitDataVolumeMsg msg) { + String volumeUuid = msg.getVolumeUuid() == null ? null : msg.getVolumeUuid().trim(); + msg.setUuid(volumeUuid); + Tuple t = Q.New(VolumeVO.class) + .select(VolumeVO_.type, VolumeVO_.status, VolumeVO_.vmInstanceUuid, VolumeVO_.primaryStorageUuid) + .eq(VolumeVO_.uuid, volumeUuid) + .findTuple(); + + if (t == null) { + throw new ApiMessageInterceptionException(argerr(ORG_ZSTACK_STORAGE_VOLUME_10097, "volume[uuid:%s] not found", volumeUuid)); + } + + VolumeType type = t.get(0, VolumeType.class); + if (type != VolumeType.Data) { + throw new ApiMessageInterceptionException(argerr(ORG_ZSTACK_STORAGE_VOLUME_10098, + "volume[uuid:%s, type:%s] is not a data volume, only data volumes can be re-initialized", + volumeUuid, type)); + } + + VolumeStatus status = t.get(1, VolumeStatus.class); + if (status != VolumeStatus.Ready) { + throw new ApiMessageInterceptionException(operr(ORG_ZSTACK_STORAGE_VOLUME_10099, + "volume[uuid:%s] is not in status Ready, current status is %s", + volumeUuid, status)); + } + + String primaryStorageUuid = t.get(3, String.class); + String primaryStorageType = Q.New(PrimaryStorageVO.class) + .select(PrimaryStorageVO_.type) + .eq(PrimaryStorageVO_.uuid, primaryStorageUuid) + .findValue(); + if (!CEPH_PRIMARY_STORAGE_TYPE.equals(primaryStorageType)) { + throw new ApiMessageInterceptionException(operr(ORG_ZSTACK_STORAGE_VOLUME_10003, + "current primary storage %s is not Ceph type, re-initializing data volume is not supported", + primaryStorageUuid)); + } + + String vmInstanceUuid = t.get(2, String.class); + if (vmInstanceUuid != null) { + VmInstanceState vmState = Q.New(VmInstanceVO.class) + .select(VmInstanceVO_.state) + .eq(VmInstanceVO_.uuid, vmInstanceUuid) + .findValue(); + if (vmState != VmInstanceState.Stopped) { + throw new ApiMessageInterceptionException(operr(ORG_ZSTACK_STORAGE_VOLUME_10100, + "cannot re-initialize data volume[uuid:%s], the vm[uuid:%s] it attached to is not in Stopped state, current state is %s", + volumeUuid, vmInstanceUuid, vmState)); + } + } + } + private void validate(APIUndoSnapshotCreationMsg msg) { String currentTreeUuid = Q.New(VolumeSnapshotTreeVO.class) .select(VolumeSnapshotTreeVO_.uuid) diff --git a/storage/src/main/java/org/zstack/storage/volume/VolumeBase.java b/storage/src/main/java/org/zstack/storage/volume/VolumeBase.java index d75fb654a3e..85efec20c2d 100755 --- a/storage/src/main/java/org/zstack/storage/volume/VolumeBase.java +++ b/storage/src/main/java/org/zstack/storage/volume/VolumeBase.java @@ -191,6 +191,9 @@ private void handle(ReInitVolumeMsg msg) { chain.then(new ShareFlow() { VolumeVO vo = self; String allocatedInstallUrl; + String reinitNewVolumeInstallPath; + boolean primaryStorageReinitSucceeded; + boolean dbInstallPathSwitched; @Override public void setup() { @@ -246,7 +249,12 @@ public void run(MessageReply reply) { @Override public void rollback(FlowRollback trigger, Map data) { - if (success) { + if (success && !dbInstallPathSwitched) { + if (primaryStorageReinitSucceeded) { + cleanupReinitNewVolumeBits(self.getPrimaryStorageUuid(), reinitNewVolumeInstallPath, self); + trigger.rollback(); + return; + } ReleasePrimaryStorageSpaceMsg rmsg = new ReleasePrimaryStorageSpaceMsg(); rmsg.setPrimaryStorageUuid(self.getPrimaryStorageUuid()); rmsg.setDiskSize(originSize); @@ -263,7 +271,7 @@ public void rollback(FlowRollback trigger, Map data) { @Override public void run(final FlowTrigger trigger, Map data) { - MarkRootVolumeAsSnapshotMsg gmsg = new MarkRootVolumeAsSnapshotMsg(); + MarkVolumeAsSnapshotMsg gmsg = new MarkVolumeAsSnapshotMsg(); rootVolumeInventory.setDescription(String.format("save snapshot for reimage vm [uuid:%s]", msg.getVmInstanceUuid())); rootVolumeInventory.setName(String.format("reimage-vm-point-%s-%s", msg.getVmInstanceUuid(), TimeUtils.getCurrentTimeStamp("yyyyMMddHHmmss"))); gmsg.setVolume(rootVolumeInventory); @@ -295,14 +303,19 @@ public void run(final FlowTrigger trigger, Map data) { bus.send(rmsg, new CloudBusCallBack(trigger) { @Override public void run(MessageReply reply) { - if (reply.isSuccess()) { - ReInitRootVolumeFromTemplateOnPrimaryStorageReply re = (ReInitRootVolumeFromTemplateOnPrimaryStorageReply) reply; - vo.setInstallPath(re.getNewVolumeInstallPath()); - vo = dbf.updateAndRefresh(vo); - trigger.next(); - } else { + if (!reply.isSuccess()) { trigger.fail(reply.getError()); + return; } + + ReInitRootVolumeFromTemplateOnPrimaryStorageReply re = reply.castReply(); + reinitNewVolumeInstallPath = re.getNewVolumeInstallPath(); + primaryStorageReinitSucceeded = true; + + vo.setInstallPath(reinitNewVolumeInstallPath); + vo = dbf.updateAndRefresh(vo); + dbInstallPathSwitched = true; + trigger.next(); } }); } @@ -324,7 +337,9 @@ public void run(MessageReply reply) { return; } - vo.setSize(((SyncVolumeSizeReply) reply).getSize()); + SyncVolumeSizeReply syncReply = reply.castReply(); + vo.setSize(syncReply.getSize()); + vo.setActualSize(syncReply.getActualSize()); trigger.next(); } }); @@ -360,6 +375,242 @@ public void handle(ErrorCode errCode, Map data) { }).start(); } + private void handle(final APIReInitDataVolumeMsg msg) { + thdf.chainSubmit(new ChainTask(msg) { + @Override + public String getSyncSignature() { + return syncThreadId; + } + + @Override + public void run(final SyncTaskChain chain) { + reInitDataVolume(msg, new NoErrorCompletion(chain) { + @Override + public void done() { + chain.next(); + } + }); + } + + @Override + public String getName() { + return "reinit-data-volume"; + } + }); + } + + private void reInitDataVolume(final APIReInitDataVolumeMsg msg, NoErrorCompletion completion) { + final APIReInitDataVolumeEvent evt = new APIReInitDataVolumeEvent(msg.getId()); + + refreshVO(); + VolumeInventory dataVolumeInventory = VolumeInventory.valueOf(self); + List systemTags = Q.New(SystemTagVO.class).select(SystemTagVO_.tag) + .eq(SystemTagVO_.resourceUuid, dataVolumeInventory.getUuid()) + .listValues(); + FlowChain chain = FlowChainBuilder.newShareFlowChain(); + chain.setName(String.format("reinit-data-volume-%s", self.getUuid())); + chain.then(new ShareFlow() { + VolumeVO vo = self; + String allocatedInstallUrl; + String reinitNewVolumeInstallPath; + boolean primaryStorageReinitSucceeded; + boolean dbInstallPathSwitched; + + @Override + public void setup() { + flow(new Flow() { + String __name__ = "allocate-primary-storage"; + + boolean success; + + @Override + public void run(FlowTrigger trigger, Map data) { + AllocatePrimaryStorageSpaceMsg amsg = new AllocatePrimaryStorageSpaceMsg(); + amsg.setRequiredPrimaryStorageUuid(self.getPrimaryStorageUuid()); + amsg.setPurpose(PrimaryStorageAllocationPurpose.CreateDataVolume.toString()); + amsg.setSize(self.getSize()); + amsg.setSystemTags(systemTags); + amsg.setRequiredInstallUri(String.format("volume://%s", vo.getUuid())); + + bus.makeTargetServiceIdByResourceUuid(amsg, PrimaryStorageConstant.SERVICE_ID, self.getUuid()); + bus.send(amsg, new CloudBusCallBack(trigger) { + @Override + public void run(MessageReply reply) { + if (!reply.isSuccess()) { + trigger.fail(reply.getError()); + return; + } + AllocatePrimaryStorageSpaceReply ar = (AllocatePrimaryStorageSpaceReply) reply; + allocatedInstallUrl = ar.getAllocatedInstallUrl(); + success = true; + trigger.next(); + } + }); + } + + @Override + public void rollback(FlowRollback trigger, Map data) { + if (success && !dbInstallPathSwitched) { + if (primaryStorageReinitSucceeded) { + cleanupReinitNewVolumeBits(self.getPrimaryStorageUuid(), reinitNewVolumeInstallPath, self); + trigger.rollback(); + return; + } + ReleasePrimaryStorageSpaceMsg rmsg = new ReleasePrimaryStorageSpaceMsg(); + rmsg.setPrimaryStorageUuid(self.getPrimaryStorageUuid()); + rmsg.setDiskSize(self.getSize()); + rmsg.setAllocatedInstallUrl(allocatedInstallUrl); + bus.makeTargetServiceIdByResourceUuid(rmsg, PrimaryStorageConstant.SERVICE_ID, self.getPrimaryStorageUuid()); + bus.send(rmsg); + } + trigger.rollback(); + } + }); + + flow(new NoRollbackFlow() { + String __name__ = "mark-data-volume-as-snapshot-on-primary-storage"; + + @Override + public void run(final FlowTrigger trigger, Map data) { + MarkVolumeAsSnapshotMsg gmsg = new MarkVolumeAsSnapshotMsg(); + dataVolumeInventory.setDescription(String.format("save snapshot for reinit data volume [uuid:%s]", self.getUuid())); + dataVolumeInventory.setName(String.format("reinit-data-vol-point-%s-%s", self.getUuid(), TimeUtils.getCurrentTimeStamp("yyyyMMddHHmmss"))); + gmsg.setVolume(dataVolumeInventory); + gmsg.setAccountUuid(msg.getSession().getAccountUuid()); + bus.makeLocalServiceId(gmsg, VolumeSnapshotConstant.SERVICE_ID); + bus.send(gmsg, new CloudBusCallBack(trigger) { + @Override + public void run(MessageReply reply) { + if (reply.isSuccess()) { + trigger.next(); + } else { + trigger.fail(reply.getError()); + } + } + }); + } + }); + + flow(new NoRollbackFlow() { + String __name__ = "reinit-data-volume-on-primary-storage"; + + @Override + public void run(final FlowTrigger trigger, Map data) { + ReInitDataVolumeOnPrimaryStorageMsg rmsg = new ReInitDataVolumeOnPrimaryStorageMsg(); + rmsg.setVolume(dataVolumeInventory); + rmsg.setAllocatedInstallUrl(allocatedInstallUrl); + bus.makeTargetServiceIdByResourceUuid(rmsg, PrimaryStorageConstant.SERVICE_ID, dataVolumeInventory.getPrimaryStorageUuid()); + bus.send(rmsg, new CloudBusCallBack(trigger) { + @Override + public void run(MessageReply reply) { + if (!reply.isSuccess()) { + trigger.fail(reply.getError()); + return; + } + + ReInitDataVolumeOnPrimaryStorageReply re = reply.castReply(); + reinitNewVolumeInstallPath = re.getNewVolumeInstallPath(); + primaryStorageReinitSucceeded = true; + + vo.setInstallPath(reinitNewVolumeInstallPath); + vo = dbf.updateAndRefresh(vo); + dbInstallPathSwitched = true; + trigger.next(); + } + }); + } + }); + + flow(new NoRollbackFlow() { + String __name__ = "sync-volume-size-after-reinit"; + + @Override + public void run(final FlowTrigger trigger, Map data) { + SyncVolumeSizeMsg smsg = new SyncVolumeSizeMsg(); + smsg.setVolumeUuid(vo.getUuid()); + bus.makeTargetServiceIdByResourceUuid(smsg, VolumeConstant.SERVICE_ID, dataVolumeInventory.getUuid()); + bus.send(smsg, new CloudBusCallBack(msg) { + @Override + public void run(MessageReply reply) { + if (!reply.isSuccess()) { + trigger.fail(reply.getError()); + return; + } + + SyncVolumeSizeReply syncReply = reply.castReply(); + vo.setSize(syncReply.getSize()); + vo.setActualSize(syncReply.getActualSize()); + trigger.next(); + } + }); + } + }); + + done(new FlowDoneHandler(msg) { + @Override + public void handle(Map data) { + dbf.update(vo); + + List list = pluginRgty.getExtensionList( + AfterReimageVmInstanceExtensionPoint.class); + for (AfterReimageVmInstanceExtensionPoint ext : list) { + ext.afterReimageVmInstance(dataVolumeInventory); + } + + self = dbf.reload(self); + evt.setInventory(VolumeInventory.valueOf(self)); + bus.publish(evt); + completion.done(); + } + }); + + error(new FlowErrorHandler(msg) { + @Override + public void handle(ErrorCode errCode, Map data) { + logger.warn(String.format("failed to reinit data volume[uuid:%s], %s", + dataVolumeInventory.getUuid(), errCode)); + evt.setError(errCode); + bus.publish(evt); + completion.done(); + } + }); + } + }).start(); + } + + private void cleanupReinitNewVolumeBits(String primaryStorageUuid, String installPath, VolumeVO volume) { + if (primaryStorageUuid == null || installPath == null || volume == null) { + return; + } + + DeleteVolumeBitsOnPrimaryStorageMsg dmsg = new DeleteVolumeBitsOnPrimaryStorageMsg(); + dmsg.setPrimaryStorageUuid(primaryStorageUuid); + dmsg.setInstallPath(installPath); + dmsg.setBitsUuid(volume.getUuid()); + dmsg.setBitsType(VolumeVO.class.getSimpleName()); + dmsg.setSize(volume.getSize()); + dmsg.setHypervisorType(VolumeFormat.getMasterHypervisorTypeByVolumeFormat(volume.getFormat()).toString()); + bus.makeTargetServiceIdByResourceUuid(dmsg, PrimaryStorageConstant.SERVICE_ID, primaryStorageUuid); + bus.send(dmsg, new CloudBusCallBack(null) { + @Override + public void run(MessageReply reply) { + if (reply.isSuccess()) { + return; + } + + logger.warn(String.format("failed to delete reinit new volume bits[path:%s, volumeUuid:%s], submit GC. %s", + installPath, volume.getUuid(), reply.getError())); + PrimaryStorageDeleteBitGC gc = new PrimaryStorageDeleteBitGC(); + gc.NAME = String.format("gc-delete-reinit-volume-%s-bits-on-primary-storage-%s", volume.getUuid(), primaryStorageUuid); + gc.primaryStorageInstallPath = installPath; + gc.primaryStorageUuid = primaryStorageUuid; + gc.volume = volume; + gc.submit(PrimaryStorageGlobalConfig.PRIMARY_STORAGE_DELETEBITS_GARBAGE_COLLECTOR_INTERVAL.value(Long.class), + TimeUnit.SECONDS); + } + }); + } + private void handle(ChangeVolumeStatusMsg msg) { thdf.chainSubmit(new ChainTask(msg) { @Override @@ -2173,6 +2424,8 @@ private void handleApiMessage(APIMessage msg) { handle((APIDetachDataVolumeFromHostMsg) msg); } else if (msg instanceof APIFlattenVolumeMsg) { handle((APIFlattenVolumeMsg) msg); + } else if (msg instanceof APIReInitDataVolumeMsg) { + handle((APIReInitDataVolumeMsg) msg); } else if (msg instanceof APIUndoSnapshotCreationMsg) { handle((APIUndoSnapshotCreationMsg) msg); } else { diff --git a/test/src/test/bash/test_zstack_server_mariadb_recovery.sh b/test/src/test/bash/test_zstack_server_mariadb_recovery.sh new file mode 100755 index 00000000000..a7e974fc8b1 --- /dev/null +++ b/test/src/test/bash/test_zstack_server_mariadb_recovery.sh @@ -0,0 +1,173 @@ +#!/bin/sh + +set -eu + +script_dir=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd) +repo_dir=$(CDPATH= cd -- "$script_dir/../../../.." && pwd) +script="$repo_dir/conf/install/zstack-server" +tmp_dir=$(mktemp -d) + +cleanup() { + rm -rf "$tmp_dir" +} + +trap cleanup EXIT + +bin_dir="$tmp_dir/bin" +mkdir -p "$bin_dir" + +cat > "$bin_dir/zstack-ctl" <<'EOF' +#!/bin/sh +echo "zstack-ctl $*" >> "$ZSTUB_CALLS" +exit 0 +EOF + +cat > "$bin_dir/systemctl" <<'EOF' +#!/bin/sh +case "$1 $2" in + "list-unit-files mariadb.service") + echo "mariadb.service enabled" + exit 0 + ;; + "is-active --quiet") + [ "${ZSTUB_MARIADB_ACTIVE:-false}" = "true" ] && exit 0 + exit 3 + ;; + "reset-failed mariadb") + echo "systemctl reset-failed mariadb" >> "$ZSTUB_CALLS" + exit 0 + ;; + "start mariadb") + echo "systemctl start mariadb" >> "$ZSTUB_CALLS" + exit 0 + ;; +esac +exit 1 +EOF + +cat > "$bin_dir/lsof" <<'EOF' +#!/bin/sh +exit 1 +EOF + +cat > "$bin_dir/fuser" <<'EOF' +#!/bin/sh +exit 1 +EOF + +chmod +x "$bin_dir/zstack-ctl" "$bin_dir/systemctl" "$bin_dir/lsof" "$bin_dir/fuser" + +assert_contains() { + grep -F "$1" "$2" >/dev/null || { + echo "expected '$1' in $2" >&2 + exit 1 + } +} + +calls="$tmp_dir/calls" +socket="$tmp_dir/mysql.sock" +log_dir="$tmp_dir/log" +touch "$socket" + +PATH="$bin_dir:$PATH" \ +ZSTUB_CALLS="$calls" \ +ZSTACK_MARIADB_SOCKET="$socket" \ +ZSTACK_SERVER_LOG_DIR="$log_dir" \ +sh "$script" start >/dev/null + +[ ! -e "$socket" ] || { + echo "expected stale socket to be removed" >&2 + exit 1 +} +assert_contains "systemctl reset-failed mariadb" "$calls" +assert_contains "systemctl start mariadb" "$calls" +assert_contains "zstack-ctl start" "$calls" + +sysv_bin_dir="$tmp_dir/sysv-bin" +mkdir -p "$sysv_bin_dir" +cp "$bin_dir/zstack-ctl" "$bin_dir/lsof" "$bin_dir/fuser" "$sysv_bin_dir/" +ln -s /usr/bin/grep "$sysv_bin_dir/grep" +cat > "$sysv_bin_dir/which" <<'EOF' +#!/bin/sh +command -v "$1" +EOF +cat > "$sysv_bin_dir/service" <<'EOF' +#!/bin/sh +if [ "$1 $2" = "mariadb status" ]; then + echo "mariadb is running" + exit 0 +fi +exit 1 +EOF +chmod +x "$sysv_bin_dir/which" "$sysv_bin_dir/service" + +calls="$tmp_dir/calls-sysv-active" +socket="$tmp_dir/mysql-sysv-active.sock" +touch "$socket" + +PATH="$sysv_bin_dir" \ +ZSTUB_CALLS="$calls" \ +ZSTACK_MARIADB_SOCKET="$socket" \ +ZSTACK_SERVER_LOG_DIR="$log_dir" \ +/bin/sh "$script" start >/dev/null + +[ -e "$socket" ] || { + echo "expected active SysV MariaDB socket to be kept" >&2 + exit 1 +} +if grep -F "systemctl start mariadb" "$calls" >/dev/null 2>&1; then + echo "unexpected call: systemctl start mariadb" >&2 + exit 1 +fi +assert_contains "zstack-ctl start" "$calls" + +no_probe_bin_dir="$tmp_dir/no-probe-bin" +mkdir -p "$no_probe_bin_dir" +cp "$bin_dir/zstack-ctl" "$bin_dir/systemctl" "$no_probe_bin_dir/" +ln -s /usr/bin/grep "$no_probe_bin_dir/grep" +cat > "$no_probe_bin_dir/which" <<'EOF' +#!/bin/sh +command -v "$1" +EOF +chmod +x "$no_probe_bin_dir/which" + +calls="$tmp_dir/calls-no-probe" +socket="$tmp_dir/mysql-no-probe.sock" +touch "$socket" + +PATH="$no_probe_bin_dir" \ +ZSTUB_CALLS="$calls" \ +ZSTACK_MARIADB_SOCKET="$socket" \ +ZSTACK_SERVER_LOG_DIR="$log_dir" \ +/bin/sh "$script" start >/dev/null + +[ -e "$socket" ] || { + echo "expected socket to be kept when lsof and fuser are unavailable" >&2 + exit 1 +} +if grep -F "systemctl start mariadb" "$calls" >/dev/null 2>&1; then + echo "unexpected call: systemctl start mariadb" >&2 + exit 1 +fi +assert_contains "zstack-ctl start" "$calls" + +calls="$tmp_dir/calls-active" +socket="$tmp_dir/mysql-active.sock" +touch "$socket" + +PATH="$bin_dir:$PATH" \ +ZSTUB_CALLS="$calls" \ +ZSTUB_MARIADB_ACTIVE=true \ +ZSTACK_MARIADB_SOCKET="$socket" \ +ZSTACK_SERVER_LOG_DIR="$log_dir" \ +sh "$script" start >/dev/null + +[ -e "$socket" ] || { + echo "expected active MariaDB socket to be kept" >&2 + exit 1 +} +if grep -F "systemctl start mariadb" "$calls" >/dev/null 2>&1; then + echo "unexpected call: systemctl start mariadb" >&2 + exit 1 +fi +assert_contains "zstack-ctl start" "$calls" diff --git a/test/src/test/groovy/org/zstack/test/integration/image/DeleteIsoCase.groovy b/test/src/test/groovy/org/zstack/test/integration/image/DeleteIsoCase.groovy index 7e26ba7edbe..d0528e8707e 100644 --- a/test/src/test/groovy/org/zstack/test/integration/image/DeleteIsoCase.groovy +++ b/test/src/test/groovy/org/zstack/test/integration/image/DeleteIsoCase.groovy @@ -172,6 +172,13 @@ class DeleteIsoCase extends SubCase { isoUuid = iso1.uuid } + detachIsoFromVmInstance { + vmInstanceUuid = newVm2.uuid + isoUuid = iso2.uuid + } + + assert [iso1.uuid] == IsoOperator.getIsoUuidByVmUuid(newVm2.uuid) + attachIsoToVmInstance { vmInstanceUuid = newVm.uuid isoUuid = iso2.uuid diff --git a/test/src/test/groovy/org/zstack/test/integration/kvm/host/HostAgentRestartDrainCase.groovy b/test/src/test/groovy/org/zstack/test/integration/kvm/host/HostAgentRestartDrainCase.groovy new file mode 100644 index 00000000000..c940a7c6d46 --- /dev/null +++ b/test/src/test/groovy/org/zstack/test/integration/kvm/host/HostAgentRestartDrainCase.groovy @@ -0,0 +1,117 @@ +package org.zstack.test.integration.kvm.host + +import org.springframework.http.HttpEntity +import org.zstack.header.Constants +import org.zstack.header.errorcode.ErrorCode +import org.zstack.header.errorcode.SysErrors +import org.zstack.header.rest.JsonAsyncRESTCallback +import org.zstack.header.rest.RESTFacade +import org.zstack.kvm.KVMAgentCommands +import org.zstack.kvm.KVMConstant +import org.zstack.sdk.HostInventory +import org.zstack.test.integration.kvm.Env +import org.zstack.test.integration.kvm.KvmTest +import org.zstack.testlib.EnvSpec +import org.zstack.testlib.SubCase + +import java.util.concurrent.CountDownLatch +import java.util.concurrent.TimeUnit +import java.util.concurrent.atomic.AtomicReference + +class HostAgentRestartDrainCase extends SubCase { + EnvSpec env + HostInventory host + RESTFacade restf + + static class StuckCall { + CountDownLatch entered = new CountDownLatch(1) + CountDownLatch release = new CountDownLatch(1) + CountDownLatch done = new CountDownLatch(1) + AtomicReference received = new AtomicReference<>() + } + + @Override + void setup() { + useSpring(KvmTest.springSpec) + } + + @Override + void environment() { + env = Env.noVmEnv() + } + + @Override + void test() { + env.create { + host = env.inventoryByName("kvm") + restf = bean(RESTFacade.class) + testFirstConnectDrainsStaleCalls() + testNoFirstConnectKeepsStaleCalls() + testDifferentResourceUuidIsolated() + } + } + + @Override + void clean() { + env.delete() + } + + private StuckCall sendStuckCall(String resourceUuid) { + StuckCall h = new StuckCall() + def stuckPath = "/test/stuck/${UUID.randomUUID()}" + env.simulator(stuckPath) { + h.entered.countDown() + h.release.await(120, TimeUnit.SECONDS) + return new KVMAgentCommands.AgentResponse() + } + + Map headers = [(Constants.AGENT_HTTP_HEADER_RESOURCE_UUID): resourceUuid] + restf.asyncJsonPost(restf.makeUrl(stuckPath), "{}", headers, new JsonAsyncRESTCallback(null) { + @Override void fail(ErrorCode err) { h.received.set(err); h.done.countDown() } + @Override void success(String ret) { h.done.countDown() } + @Override Class getReturnClass() { return String.class } + }, TimeUnit.MINUTES, 30) + assert h.entered.await(5, TimeUnit.SECONDS) + return h + } + + private void overrideConnectResponse(boolean firstConnect, long agentStartTimeMillis) { + env.afterSimulator(KVMConstant.KVM_CONNECT_PATH) { KVMAgentCommands.ConnectResponse rsp, HttpEntity e -> + rsp.firstConnect = firstConnect + rsp.agentStartTimeMillis = agentStartTimeMillis + return rsp + } + } + + void testFirstConnectDrainsStaleCalls() { + StuckCall h = sendStuckCall(host.uuid) + overrideConnectResponse(true, System.currentTimeMillis() + 70_000L) + reconnectHost { + uuid = host.uuid + } + assert h.done.await(5, TimeUnit.SECONDS) + assert h.received.get() != null + assert h.received.get().code == SysErrors.OPERATION_ERROR.toString() + h.release.countDown() + } + + void testNoFirstConnectKeepsStaleCalls() { + StuckCall h = sendStuckCall(host.uuid) + overrideConnectResponse(false, System.currentTimeMillis() + 70_000L) + reconnectHost { + uuid = host.uuid + } + assert !h.done.await(500, TimeUnit.MILLISECONDS) + h.release.countDown() + } + + void testDifferentResourceUuidIsolated() { + StuckCall h = sendStuckCall("unrelated-resource-uuid") + overrideConnectResponse(true, System.currentTimeMillis() + 70_000L) + reconnectHost { + uuid = host.uuid + } + assert !h.done.await(500, TimeUnit.MILLISECONDS) + h.release.countDown() + } +} diff --git a/test/src/test/groovy/org/zstack/test/integration/kvm/host/KVMHostRequirettySudoCase.groovy b/test/src/test/groovy/org/zstack/test/integration/kvm/host/KVMHostRequirettySudoCase.groovy new file mode 100644 index 00000000000..1f98d09313a --- /dev/null +++ b/test/src/test/groovy/org/zstack/test/integration/kvm/host/KVMHostRequirettySudoCase.groovy @@ -0,0 +1,245 @@ +package org.zstack.test.integration.kvm.host + +import org.zstack.core.CoreGlobalProperty +import org.zstack.core.cloudbus.CloudBus +import org.zstack.core.db.Q +import org.zstack.header.core.Completion +import org.zstack.header.core.workflow.Flow +import org.zstack.header.core.workflow.FlowTrigger +import org.zstack.header.core.workflow.NoRollbackFlow +import org.zstack.header.errorcode.ErrorCode +import org.zstack.header.host.ConnectHostInfo +import org.zstack.header.host.ReconnectHostMsg +import org.zstack.header.host.ReconnectHostReply +import org.zstack.kvm.KVMGlobalProperty +import org.zstack.kvm.KVMHost +import org.zstack.kvm.KVMHostConnectExtensionPoint +import org.zstack.kvm.KVMHostConnectedContext +import org.zstack.kvm.KVMHostFactory +import org.zstack.kvm.KVMHostVO +import org.zstack.kvm.KVMHostVO_ +import org.zstack.sdk.HostInventory +import org.zstack.sdk.KVMHostInventory +import org.zstack.test.integration.kvm.Env +import org.zstack.test.integration.kvm.KvmTest +import org.zstack.testlib.EnvSpec +import org.zstack.testlib.SubCase +import org.zstack.utils.ssh.SshResult +import org.zstack.utils.ssh.SshShell + +import java.lang.reflect.InvocationTargetException +import java.util.concurrent.CountDownLatch +import java.util.concurrent.TimeUnit + +class KVMHostRequirettySudoCase extends SubCase { + EnvSpec env + HostInventory host + KVMHostFactory factory + final List commandsWithoutPty = Collections.synchronizedList(new ArrayList()) + final List commandsWithPty = Collections.synchronizedList(new ArrayList()) + + @Override + void setup() { + useSpring(KvmTest.springSpec) + } + + @Override + void environment() { + env = Env.noVmEnv() + } + + @Override + void test() { + env.create { + host = env.inventoryByName("kvm") + factory = bean(KVMHostFactory.class) + env.mockFactory(SshShell.class) { SshShell shell -> + return new RecordingSshShell(commandsWithoutPty, commandsWithPty) + } + + testRequirettySudoCommandsUsePseudoTty() + } + } + + @Override + void clean() { + env.delete() + } + + void testRequirettySudoCommandsUsePseudoTty() { + KVMHostInventory updated = updateKVMHost { + uuid = host.uuid + username = "zstac77375" + password = "password" + sshPort = 22 + } as KVMHostInventory + assert updated.username == "zstac77375" + + KVMHost kvmHost = getKvmHost() + testRestartKvmAgent(kvmHost) + testDeleteTakeOverFlag(kvmHost) + testWriteTakeOverFlag(kvmHost) + + assert commandsWithPty.contains("sudo service zstack-kvmagent restart") + assert commandsWithPty.any { it == String.format("sudo /bin/sh -c \"rm -rf %s\"", KVMGlobalProperty.TAKEVOERFLAGPATH) } + assert commandsWithPty.any { it == String.format("sudo /bin/sh -c \"echo uuid:%s > %s\"", host.uuid, KVMGlobalProperty.TAKEVOERFLAGPATH) } + + assert !commandsWithoutPty.contains("sudo service zstack-kvmagent restart") + assert !commandsWithoutPty.any { it.startsWith("sudo /bin/sh -c \"rm -rf ") } + assert !commandsWithoutPty.any { it.startsWith("sudo /bin/sh -c \"echo uuid:") } + } + + void testRestartKvmAgent(KVMHost kvmHost) { + env.message(ReconnectHostMsg.class) { ReconnectHostMsg msg, CloudBus bus -> + ReconnectHostReply reply = new ReconnectHostReply() + bus.reply(msg, reply) + } + + ErrorCode error + try { + error = runWithUnitTestOff { Completion completion -> + invokeKVMHost(kvmHost, "restartKvmAgentOnHost", [Boolean.TYPE, Completion.class] as Class[], [true, completion] as Object[]) + } + } finally { + env.cleanMessageHandlers() + } + + assert error == null + } + + void testDeleteTakeOverFlag(KVMHost kvmHost) { + ErrorCode error = runWithUnitTestOff { Completion completion -> + invokeKVMHost(kvmHost, "deleteTakeOverFlag", [Completion.class] as Class[], [completion] as Object[]) + } + + assert error == null + } + + void testWriteTakeOverFlag(KVMHost kvmHost) { + ConnectHostInfo info = new ConnectHostInfo() + info.setNewAdded(false) + + List extensions = new ArrayList(factory.getConnectExtensions()) + factory.getConnectExtensions().clear() + factory.getConnectExtensions().add(noOpConnectExtension()) + try { + ErrorCode error = runWithUnitTestOff { Completion completion -> + invokeKVMHost(kvmHost, "continueConnect", [ConnectHostInfo.class, Completion.class] as Class[], [info, completion] as Object[]) + } + + assert error == null + } finally { + factory.getConnectExtensions().clear() + factory.getConnectExtensions().addAll(extensions) + } + } + + static KVMHostConnectExtensionPoint noOpConnectExtension() { + return new KVMHostConnectExtensionPoint() { + @Override + Flow createKvmHostConnectingFlow(KVMHostConnectedContext context) { + return new NoRollbackFlow() { + String __name__ = "no-op kvm host connect extension" + + @Override + void run(FlowTrigger trigger, Map data) { + trigger.next() + } + } + } + } + } + + KVMHost getKvmHost() { + KVMHostVO vo = Q.New(KVMHostVO.class).eq(KVMHostVO_.uuid, host.uuid).find() + return factory.getHost(vo) as KVMHost + } + + ErrorCode runWithUnitTestOff(Closure caller) { + boolean oldUnitTestOn = CoreGlobalProperty.UNIT_TEST_ON + CountDownLatch latch = new CountDownLatch(1) + ErrorCode[] error = new ErrorCode[1] + Throwable[] thrown = new Throwable[1] + + Completion completion = new Completion(null) { + @Override + void success() { + latch.countDown() + } + + @Override + void fail(ErrorCode errorCode) { + error[0] = errorCode + latch.countDown() + } + } + + boolean completed + CoreGlobalProperty.UNIT_TEST_ON = false + try { + caller.call(completion) + completed = latch.await(60, TimeUnit.SECONDS) + } catch (Throwable t) { + thrown[0] = t + latch.countDown() + completed = true + } finally { + CoreGlobalProperty.UNIT_TEST_ON = oldUnitTestOn + } + + assert completed + if (thrown[0] != null) { + throw thrown[0] + } + + return error[0] + } + + static void invokeKVMHost(KVMHost kvmHost, String methodName, Class[] parameterTypes, Object[] args) { + def method = KVMHost.class.getDeclaredMethod(methodName, parameterTypes) + method.setAccessible(true) + try { + method.invoke(kvmHost, args) + } catch (InvocationTargetException e) { + throw e.getTargetException() + } + } + + static class RecordingSshShell extends SshShell { + final List commandsWithoutPty + final List commandsWithPty + + RecordingSshShell(List commandsWithoutPty, List commandsWithPty) { + this.commandsWithoutPty = commandsWithoutPty + this.commandsWithPty = commandsWithPty + } + + @Override + SshResult runCommand(String cmd) { + commandsWithoutPty.add(cmd) + return result(cmd, false) + } + + @Override + SshResult runCommandWithPseudoTty(String cmd) { + commandsWithPty.add(cmd) + return result(cmd, true) + } + + SshResult result(String cmd, boolean withPty) { + SshResult ret = new SshResult() + ret.setCommandToExecute(cmd) + ret.setReturnCode((isRequirettySudoCommand(cmd) && !withPty) ? 1 : 0) + ret.setStdout(cmd == "uname -m" ? "x86_64\n" : "") + ret.setStderr(ret.getReturnCode() == 0 ? "" : "sudo: sorry, you must have a tty to run sudo") + ret.setExitErrorMessage(ret.getStderr()) + return ret + } + + boolean isRequirettySudoCommand(String cmd) { + return cmd == "sudo service zstack-kvmagent restart" || + cmd.startsWith("sudo /bin/sh -c \"rm -rf ") || + cmd.startsWith("sudo /bin/sh -c \"echo uuid:") + } + } +} diff --git a/test/src/test/groovy/org/zstack/test/integration/kvm/host/LibvirtRestartEchoTimeoutCase.groovy b/test/src/test/groovy/org/zstack/test/integration/kvm/host/LibvirtRestartEchoTimeoutCase.groovy new file mode 100644 index 00000000000..b67eced4a13 --- /dev/null +++ b/test/src/test/groovy/org/zstack/test/integration/kvm/host/LibvirtRestartEchoTimeoutCase.groovy @@ -0,0 +1,86 @@ +package org.zstack.test.integration.kvm.host + +import org.zstack.core.CoreGlobalProperty +import org.zstack.core.db.Q +import org.zstack.core.db.SQL +import org.zstack.header.vm.VmInstanceState +import org.zstack.header.vm.VmInstanceVO +import org.zstack.header.vm.VmInstanceVO_ +import org.zstack.kvm.KVMHostUtils +import org.zstack.sdk.HostInventory +import org.zstack.sdk.VmInstanceInventory +import org.zstack.test.integration.kvm.Env +import org.zstack.test.integration.kvm.KvmTest +import org.zstack.testlib.EnvSpec +import org.zstack.testlib.SubCase + +import java.util.concurrent.TimeUnit + +class LibvirtRestartEchoTimeoutCase extends SubCase { + EnvSpec env + + @Override + void setup() { + useSpring(KvmTest.springSpec) + } + + @Override + void environment() { + env = Env.oneVmBasicEnv() + } + + @Override + void test() { + env.create { + testCalculateLibvirtRestartEchoTimeout() + testCountVmsForLibvirtRestartEchoTimeoutExcludesStoppedVm() + } + } + + @Override + void clean() { + env.delete() + } + + void testCalculateLibvirtRestartEchoTimeout() { + int oldTimeout = CoreGlobalProperty.REST_FACADE_ECHO_TIMEOUT + try { + CoreGlobalProperty.REST_FACADE_ECHO_TIMEOUT = 60 + + assert KVMHostUtils.calculateLibvirtRestartEchoTimeoutMillis(100) == TimeUnit.SECONDS.toMillis(60) + assert KVMHostUtils.calculateLibvirtRestartEchoTimeoutMillis(101) == TimeUnit.SECONDS.toMillis(61) + assert KVMHostUtils.calculateLibvirtRestartEchoTimeoutMillis(10000) == TimeUnit.SECONDS.toMillis(180) + + CoreGlobalProperty.REST_FACADE_ECHO_TIMEOUT = 300 + assert KVMHostUtils.calculateLibvirtRestartEchoTimeoutMillis(10000) == TimeUnit.SECONDS.toMillis(300) + } finally { + CoreGlobalProperty.REST_FACADE_ECHO_TIMEOUT = oldTimeout + } + } + + void testCountVmsForLibvirtRestartEchoTimeoutExcludesStoppedVm() { + HostInventory host = env.inventoryByName("kvm") as HostInventory + VmInstanceInventory vm = env.inventoryByName("vm") as VmInstanceInventory + + long originalCount = KVMHostUtils.countVmsForLibvirtRestartEchoTimeout(host.uuid) + assert originalCount > 0 + + VmInstanceState originalState = Q.New(VmInstanceVO.class) + .select(VmInstanceVO_.state) + .eq(VmInstanceVO_.uuid, vm.uuid) + .findValue() + try { + SQL.New(VmInstanceVO.class) + .eq(VmInstanceVO_.uuid, vm.uuid) + .set(VmInstanceVO_.state, VmInstanceState.Stopped) + .update() + + assert KVMHostUtils.countVmsForLibvirtRestartEchoTimeout(host.uuid) == originalCount - 1 + } finally { + SQL.New(VmInstanceVO.class) + .eq(VmInstanceVO_.uuid, vm.uuid) + .set(VmInstanceVO_.state, originalState) + .update() + } + } +} diff --git a/test/src/test/groovy/org/zstack/test/integration/kvm/nic/ChangeWindowsVmNicDriverCase.groovy b/test/src/test/groovy/org/zstack/test/integration/kvm/nic/ChangeWindowsVmNicDriverCase.groovy index 86b6bab37c1..f2d5806aaf4 100644 --- a/test/src/test/groovy/org/zstack/test/integration/kvm/nic/ChangeWindowsVmNicDriverCase.groovy +++ b/test/src/test/groovy/org/zstack/test/integration/kvm/nic/ChangeWindowsVmNicDriverCase.groovy @@ -2,10 +2,13 @@ package org.zstack.test.integration.kvm.nic import org.springframework.beans.factory.annotation.Autowired import org.zstack.compute.vm.VmSystemTags +import org.zstack.compute.vm.VmNicManagerImpl import org.zstack.header.image.ImagePlatform import org.zstack.header.tag.SystemTagVO import org.zstack.header.tag.SystemTagVO_ import org.zstack.sdk.VmInstanceInventory +import org.zstack.sdk.L3NetworkInventory +import org.zstack.sdk.VmNicInventory import org.zstack.header.vm.VmNicVO import org.zstack.header.vm.VmNicVO_ import org.zstack.tag.SystemTag @@ -16,6 +19,7 @@ import org.zstack.test.integration.kvm.KvmTest import org.zstack.testlib.EnvSpec import org.zstack.testlib.SubCase import org.zstack.core.db.Q +import org.zstack.core.db.SQL class ChangeWindowsVmNicDriverCase extends SubCase { EnvSpec env @@ -39,6 +43,7 @@ class ChangeWindowsVmNicDriverCase extends SubCase { void test() { env.create { testChangeWindowsVmNicDriver() + testPrepareDbInitialValueForVirtioTaggedWindowsVm() } } @@ -88,4 +93,38 @@ class ChangeWindowsVmNicDriverCase extends SubCase { assert VmSystemTags.VIRTIO.hasTag(vm.uuid) assert Q.New(VmNicVO.class).eq(VmNicVO_.vmInstanceUuid, vm.uuid).select(VmNicVO_.driverType).findValue().equals("virtio") } -} \ No newline at end of file + + void testPrepareDbInitialValueForVirtioTaggedWindowsVm() { + VmInstanceInventory vm = env.inventoryByName("vm") as VmInstanceInventory + L3NetworkInventory pubL3 = env.inventoryByName("pubL3") as L3NetworkInventory + VmNicVO originalNic = Q.New(VmNicVO.class) + .eq(VmNicVO_.vmInstanceUuid, vm.uuid) + .find() + + assert VmSystemTags.VIRTIO.hasTag(vm.uuid) + assert originalNic.driverType == "virtio" + + VmNicInventory newNic = createVmNic { + l3NetworkUuid = pubL3.uuid + } + + attachVmNicToVm { + vmInstanceUuid = vm.uuid + vmNicUuid = newNic.uuid + } + + SQL.New(VmNicVO.class) + .eq(VmNicVO_.uuid, newNic.uuid) + .set(VmNicVO_.driverType, null) + .update() + assert Q.New(VmNicVO.class) + .eq(VmNicVO_.uuid, newNic.uuid) + .select(VmNicVO_.driverType) + .findValue() == null + + bean(VmNicManagerImpl.class).prepareDbInitialValue() + + assert Q.New(VmNicVO.class).eq(VmNicVO_.uuid, originalNic.uuid).select(VmNicVO_.driverType).findValue() == "virtio" + assert Q.New(VmNicVO.class).eq(VmNicVO_.uuid, newNic.uuid).select(VmNicVO_.driverType).findValue() == "virtio" + } +} diff --git a/test/src/test/groovy/org/zstack/test/integration/kvm/nic/VmNicBasicCase.groovy b/test/src/test/groovy/org/zstack/test/integration/kvm/nic/VmNicBasicCase.groovy index 43e6d80c840..8ee2a8bd3ff 100644 --- a/test/src/test/groovy/org/zstack/test/integration/kvm/nic/VmNicBasicCase.groovy +++ b/test/src/test/groovy/org/zstack/test/integration/kvm/nic/VmNicBasicCase.groovy @@ -82,6 +82,7 @@ class VmNicBasicCase extends SubCase { assert nic.ip != null assert nic.mac != null assert nic.usedIps.size() != 0 + assert dbFindByUuid(nic.uuid, VmNicVO.class).driverType == null IpRangeInventory ipRangeInventory = pubL3.ipRanges.get(0) assert nic.gateway == ipRangeInventory.gateway @@ -101,6 +102,7 @@ class VmNicBasicCase extends SubCase { void testAttachVmNicToVm () { L3NetworkInventory l3 = env.inventoryByName("l3") VmInstanceInventory vm = env.inventoryByName("vm") + String expectedDriverType = vm.vmNics[0].driverType changeL3NetworkState { uuid = nic.l3NetworkUuid @@ -149,6 +151,8 @@ class VmNicBasicCase extends SubCase { assert vmNicVO.deviceId == 1 assert vmNicVO.internalName == VmNicVO.generateNicInternalName(vmInstanceVO.getInternalId(), 1) assert vmNicVO.vmInstanceUuid == vm.getUuid() + assert vmNicVO.driverType == expectedDriverType + assert vm.vmNics.find { it.uuid == nic.uuid }.driverType == expectedDriverType usedIpUuid = vmNicVO.usedIpUuid diff --git a/test/src/test/groovy/org/zstack/test/integration/network/sdnController/SugonSdnControllerCase.groovy b/test/src/test/groovy/org/zstack/test/integration/network/sdnController/SugonSdnControllerCase.groovy index 8e28757ba5a..c11fb00950b 100644 --- a/test/src/test/groovy/org/zstack/test/integration/network/sdnController/SugonSdnControllerCase.groovy +++ b/test/src/test/groovy/org/zstack/test/integration/network/sdnController/SugonSdnControllerCase.groovy @@ -1,7 +1,12 @@ package org.zstack.test.integration.network.sdnController +import org.springframework.http.HttpEntity import org.zstack.core.db.DatabaseFacade +import org.zstack.core.cloudbus.CloudBus +import org.zstack.header.message.MessageReply import org.zstack.header.network.sdncontroller.SdnControllerVO +import org.zstack.header.network.sdncontroller.SdnControllerConstant +import org.zstack.sdnController.SdnControllerPingMsg import org.zstack.sdk.* import org.zstack.sugonSdnController.controller.SugonSdnControllerConstant import org.zstack.sugonSdnController.controller.api.types.MacAddressesType @@ -16,6 +21,9 @@ import javax.persistence.TypedQuery; import org.springframework.http.ResponseEntity import org.springframework.http.HttpStatus +import javax.servlet.http.HttpServletRequest +import java.util.concurrent.atomic.AtomicInteger + class SugonSdnControllerCase extends SubCase { EnvSpec env @@ -37,6 +45,7 @@ class SugonSdnControllerCase extends SubCase { void test() { env.create { dbf = bean(DatabaseFacade.class) + testTfPortSyncTriggeredByPingSuccess() testTfApi() } } @@ -46,6 +55,53 @@ class SugonSdnControllerCase extends SubCase { env.delete() } + void testTfPortSyncTriggeredByPingSuccess() { + String sql = "select sdn" + + " from SdnControllerVO sdn" + + " where sdn.vendorType = :vendorType"; + TypedQuery q = dbf.getEntityManager().createQuery(sql, SdnControllerVO.class); + q.setParameter("vendorType", SugonSdnControllerConstant.TF_CONTROLLER); + SdnControllerVO sdn = q.getResultList().get(0); + AtomicInteger syncCount = new AtomicInteger(0) + + env.simulator(TfCommands.TF_CREATE_VMI) { HttpServletRequest req, HttpEntity e, EnvSpec spec -> + if (req.method == "GET") { + syncCount.incrementAndGet() + return '{"virtual-machine-interfaces":[]}' + } + + VirtualMachineInterface rsp = new VirtualMachineInterface(); + rsp.name = TfCommands.TEST_VMI_UUID + rsp.uuid = TfCommands.TEST_VMI_UUID + Project project = new Project(); + project.name = TfCommands.TEST_PROJECT_UUID + project.uuid = TfCommands.TEST_PROJECT_UUID + project.displayName = "admin"; + rsp.setParent(project) + String json = ApiSerializer.serializeObject("virtual-machine-interface", rsp); + ResponseEntity response = new ResponseEntity(json, HttpStatus.OK); + return response.getBody() + } + + sendTfPing(sdn.uuid) + retryInSecs { + assert syncCount.get() == 1 + } + + sendTfPing(sdn.uuid) + sleep(500) + assert syncCount.get() == 1 + } + + void sendTfPing(String sdnControllerUuid) { + CloudBus bus = bean(CloudBus.class) + SdnControllerPingMsg msg = new SdnControllerPingMsg() + msg.sdnControllerUuid = sdnControllerUuid + bus.makeTargetServiceIdByResourceUuid(msg, SdnControllerConstant.SERVICE_ID, sdnControllerUuid) + MessageReply reply = bus.call(msg) + assert reply.success + } + void testTfApi() { def zone = env.inventoryByName("zone") as ZoneInventory def cluster1 = env.inventoryByName("cluster1") as ClusterInventory diff --git a/test/src/test/groovy/org/zstack/test/integration/networkservice/provider/flat/userdata/TestUserDataBatchApllyCase.groovy b/test/src/test/groovy/org/zstack/test/integration/networkservice/provider/flat/userdata/TestUserDataBatchApllyCase.groovy index 68038204981..f80f4c17335 100644 --- a/test/src/test/groovy/org/zstack/test/integration/networkservice/provider/flat/userdata/TestUserDataBatchApllyCase.groovy +++ b/test/src/test/groovy/org/zstack/test/integration/networkservice/provider/flat/userdata/TestUserDataBatchApllyCase.groovy @@ -29,8 +29,8 @@ class TestUserDataBatchApllyCase extends SubCase { env = env { instanceOffering { name = "instanceOffering" - memory = SizeUnit.GIGABYTE.toByte(8) - cpu = 4 + memory = SizeUnit.GIGABYTE.toByte(1) + cpu = 1 } sftpBackupStorage { @@ -115,6 +115,8 @@ class TestUserDataBatchApllyCase extends SubCase { @Override void test() { env.create { + testApplyUserdataAfterAttachNonDefaultVmNic() + testApplyUserdataAfterAttachNonDefaultL3Network() testReconnectHost() } } @@ -215,6 +217,90 @@ class TestUserDataBatchApllyCase extends SubCase { assert ccmd.l3NetworkUuid == l31.uuid } } -} + void testApplyUserdataAfterAttachNonDefaultVmNic() { + L3NetworkInventory l31 = env.inventoryByName("l3-1") + L3NetworkInventory l32 = env.inventoryByName("l3-2") + + VmInstanceInventory vm = createVmWithHostnameTag("vm-for-attach-nic", l31.uuid) + VmNicInventory defaultNic = vm.vmNics.get(0) + + VmNicInventory nic = createVmNic { + l3NetworkUuid = l32.uuid + } + + Map userdataCmd = captureApplyUserdataCmd() + + attachVmNicToVm { + vmInstanceUuid = vm.uuid + vmNicUuid = nic.uuid + } + + assertApplyUserdataMetadataRefreshed(userdataCmd, defaultNic, nic) + destroyVmInstance { + uuid = vm.uuid + } + } + + void testApplyUserdataAfterAttachNonDefaultL3Network() { + L3NetworkInventory l31 = env.inventoryByName("l3-1") + L3NetworkInventory l32 = env.inventoryByName("l3-2") + + VmInstanceInventory vm = createVmWithHostnameTag("vm-for-attach-l3", l31.uuid) + VmNicInventory defaultNic = vm.vmNics.get(0) + + Map userdataCmd = captureApplyUserdataCmd() + + attachL3NetworkToVm { + vmInstanceUuid = vm.uuid + l3NetworkUuid = l32.uuid + } + VmNicInventory attachedNic = queryVmNic { + conditions = ["vmInstance.uuid=${vm.uuid}", "l3NetworkUuid=${l32.uuid}"] + }[0] + + assertApplyUserdataMetadataRefreshed(userdataCmd, defaultNic, attachedNic) + destroyVmInstance { + uuid = vm.uuid + } + } + + private VmInstanceInventory createVmWithHostnameTag(String vmName, String l3NetworkUuid) { + ImageInventory image = env.inventoryByName("image") + InstanceOfferingInventory offer = env.inventoryByName("instanceOffering") + + VmInstanceInventory vm = createVmInstance { + name = vmName + instanceOfferingUuid = offer.uuid + imageUuid = image.uuid + l3NetworkUuids = [l3NetworkUuid] + } + createSystemTag { + resourceUuid = vm.uuid + resourceType = VmInstanceVO.class.getSimpleName() + tag = "hostname::kvm" + } + + return vm + } + + private Map captureApplyUserdataCmd() { + Map holder = [:] + env.afterSimulator(FlatUserdataBackend.APPLY_USER_DATA) { rsp, HttpEntity e -> + holder.cmd = json(e.body, FlatUserdataBackend.ApplyUserdataCmd.class) + return rsp + } + return holder + } + + private void assertApplyUserdataMetadataRefreshed(Map holder, VmNicInventory defaultNic, VmNicInventory attachedNic) { + retryInSecs { + assert holder.cmd != null + assert holder.cmd.userdata.vmIp == defaultNic.ip + assert holder.cmd.userdata.l3NetworkUuid == defaultNic.l3NetworkUuid + assert holder.cmd.userdata.networkInterfaces.size() == 2 + assert holder.cmd.userdata.networkInterfaces.collect { it.macAddress }.toSet() == [defaultNic.mac, attachedNic.mac].toSet() + } + } +} diff --git a/test/src/test/groovy/org/zstack/test/integration/networkservice/provider/virtualrouter/loadbalancer/VirtualRouterLoadBalancerUDPCase.groovy b/test/src/test/groovy/org/zstack/test/integration/networkservice/provider/virtualrouter/loadbalancer/VirtualRouterLoadBalancerUDPCase.groovy index 05a95e520a4..0b04f1f66e2 100755 --- a/test/src/test/groovy/org/zstack/test/integration/networkservice/provider/virtualrouter/loadbalancer/VirtualRouterLoadBalancerUDPCase.groovy +++ b/test/src/test/groovy/org/zstack/test/integration/networkservice/provider/virtualrouter/loadbalancer/VirtualRouterLoadBalancerUDPCase.groovy @@ -7,6 +7,7 @@ import org.zstack.core.db.Q import org.zstack.header.network.service.NetworkServiceType import org.zstack.network.service.eip.EipConstant import org.zstack.network.service.lb.LoadBalancerConstants +import org.zstack.network.service.lb.LoadBalancerSystemTags import org.zstack.network.service.lb.LoadBalancerVO import org.zstack.network.service.portforwarding.PortForwardingConstant import org.zstack.network.service.vip.VipVO @@ -221,9 +222,114 @@ class VirtualRouterLoadBalancerUDPCase extends SubCase{ } assert count == 1 + count = 0 + cmd = null + ChangeLoadBalancerListenerAction changeAction = new ChangeLoadBalancerListenerAction() + changeAction.uuid = listener.uuid + changeAction.healthCheckProtocol = "none" + changeAction.sessionId = adminSession() + ChangeLoadBalancerListenerAction.Result changeResult = changeAction.call() + assert changeResult.error == null + assert LoadBalancerSystemTags.HEALTH_TARGET.getTokenByResourceUuid(listener.uuid, + LoadBalancerSystemTags.HEALTH_TARGET_TOKEN) == "none:default" + assert count == 1 + assert cmd.lbs.any { VirtualRouterLoadBalancerBackend.LbTO lbtemp -> + lbtemp.listenerUuid == listener.uuid && lbtemp.getParameters().contains("healthCheckTarget::none:default") + } + + changeAction.healthCheckProtocol = null + changeAction.healthCheckTarget = "10000" + changeResult = changeAction.call() + assert changeResult.error != null + assert LoadBalancerSystemTags.HEALTH_TARGET.getTokenByResourceUuid(listener.uuid, + LoadBalancerSystemTags.HEALTH_TARGET_TOKEN) == "none:default" + deleteLoadBalancerListener { uuid = listener.uuid } + + LoadBalancerListenerInventory listenerWithSpecificHealthTarget = createLoadBalancerListener { + protocol = "udp" + loadBalancerUuid = lb.uuid + loadBalancerPort = 10002 + instancePort = 10002 + name = "test-listener-specific-health-target" + systemTags = ["healthCheckTarget::udp:10002"] + } + + changeAction = new ChangeLoadBalancerListenerAction() + changeAction.uuid = listenerWithSpecificHealthTarget.uuid + changeAction.healthCheckProtocol = "none" + changeAction.sessionId = adminSession() + changeResult = changeAction.call() + assert changeResult.error == null + assert LoadBalancerSystemTags.HEALTH_TARGET.getTokenByResourceUuid(listenerWithSpecificHealthTarget.uuid, + LoadBalancerSystemTags.HEALTH_TARGET_TOKEN) == "none:default" + + deleteLoadBalancerListener { + uuid = listenerWithSpecificHealthTarget.uuid + } + + CreateLoadBalancerListenerAction badTcpDisabledHealthCheckAction = new CreateLoadBalancerListenerAction() + badTcpDisabledHealthCheckAction.loadBalancerUuid = lb.uuid + badTcpDisabledHealthCheckAction.name = "test-tcp-listener-none-health-check" + badTcpDisabledHealthCheckAction.loadBalancerPort = 10001 + badTcpDisabledHealthCheckAction.instancePort = 10001 + badTcpDisabledHealthCheckAction.protocol = "tcp" + badTcpDisabledHealthCheckAction.healthCheckProtocol = "none" + badTcpDisabledHealthCheckAction.sessionId = adminSession() + CreateLoadBalancerListenerAction.Result badTcpDisabledHealthCheckResult = badTcpDisabledHealthCheckAction.call() + assert badTcpDisabledHealthCheckResult.error != null + + badTcpDisabledHealthCheckAction.healthCheckProtocol = null + badTcpDisabledHealthCheckAction.systemTags = ["healthCheckTarget::none:default"] + badTcpDisabledHealthCheckResult = badTcpDisabledHealthCheckAction.call() + assert badTcpDisabledHealthCheckResult.error != null + + CreateLoadBalancerListenerAction badDisabledHealthCheckAction = new CreateLoadBalancerListenerAction() + badDisabledHealthCheckAction.loadBalancerUuid = lb.uuid + badDisabledHealthCheckAction.name = "test-listener-none-specific-port" + badDisabledHealthCheckAction.loadBalancerPort = 10001 + badDisabledHealthCheckAction.instancePort = 10001 + badDisabledHealthCheckAction.protocol = "udp" + badDisabledHealthCheckAction.healthCheckProtocol = "none" + badDisabledHealthCheckAction.systemTags = ["healthCheckTarget::none:10001"] + badDisabledHealthCheckAction.sessionId = adminSession() + CreateLoadBalancerListenerAction.Result badDisabledHealthCheckResult = badDisabledHealthCheckAction.call() + assert badDisabledHealthCheckResult.error != null + + badDisabledHealthCheckAction.healthCheckProtocol = null + badDisabledHealthCheckAction.systemTags = ["healthCheckTarget::udp:default", "healthCheckTarget::none:default"] + badDisabledHealthCheckResult = badDisabledHealthCheckAction.call() + assert badDisabledHealthCheckResult.error != null + + LoadBalancerListenerInventory listenerWithDisabledHealthCheck = createLoadBalancerListener { + protocol = "udp" + healthCheckProtocol = "none" + loadBalancerUuid = lb.uuid + loadBalancerPort = 10001 + instancePort = 10001 + name = "test-listener-none-health-check" + } + + count = 0 + cmd = null + + addVmNicToLoadBalancer { + listenerUuid = listenerWithDisabledHealthCheck.uuid + vmNicUuids = [vm.getVmNics().get(0).getUuid()] + } + + assert count == 1 + assert LoadBalancerSystemTags.HEALTH_TARGET.getTokenByResourceUuid(listenerWithDisabledHealthCheck.uuid, + LoadBalancerSystemTags.HEALTH_TARGET_TOKEN) == "none:default" + assert cmd.lbs.any { VirtualRouterLoadBalancerBackend.LbTO lbtemp -> + lbtemp.listenerUuid == listenerWithDisabledHealthCheck.uuid && lbtemp.getParameters().contains("healthCheckTarget::none:default") + } + + deleteLoadBalancerListener { + uuid = listenerWithDisabledHealthCheck.uuid + } } void TestVirtualRouterDownReconnectVm(){ diff --git a/test/src/test/groovy/org/zstack/test/integration/storage/primary/addon/xinfini/XinfiniPrimaryStorageCase.groovy b/test/src/test/groovy/org/zstack/test/integration/storage/primary/addon/xinfini/XinfiniPrimaryStorageCase.groovy index fc924175afa..2b31ba85be7 100644 --- a/test/src/test/groovy/org/zstack/test/integration/storage/primary/addon/xinfini/XinfiniPrimaryStorageCase.groovy +++ b/test/src/test/groovy/org/zstack/test/integration/storage/primary/addon/xinfini/XinfiniPrimaryStorageCase.groovy @@ -12,7 +12,12 @@ import org.zstack.xinfini.XInfiniApiHelper import org.zstack.xinfini.XInfiniPathHelper import org.zstack.xinfini.sdk.vhost.BdcModule import org.zstack.xinfini.sdk.vhost.BdcBdevModule +import org.zstack.header.core.Completion +import org.zstack.header.errorcode.ErrorCode +import org.zstack.header.errorcode.OperationFailureException import org.zstack.header.host.HostConstant +import org.zstack.header.host.HostVO +import org.zstack.header.host.HostVO_ import org.zstack.header.host.PingHostMsg import org.zstack.header.message.MessageReply import org.zstack.header.storage.backup.DownloadImageFromRemoteTargetMsg @@ -44,6 +49,8 @@ import org.zstack.storage.backup.BackupStorageSystemTags import org.zstack.tag.SystemTagCreator import org.zstack.test.integration.storage.StorageTest import org.zstack.testlib.EnvSpec +import org.zstack.testlib.ExternalPrimaryStorageSpec +import org.zstack.testlib.HttpError import org.zstack.testlib.SubCase import org.zstack.utils.data.SizeUnit import org.zstack.utils.gson.JSONObjectUtil @@ -181,6 +188,7 @@ class XinfiniPrimaryStorageCase extends SubCase { simulatorEnv() testCreateXinfiniStorage() testCreateVm() + testPreventSplitBrainOnDeactivateFailure() testHandleInactiveVolume() testCreateVolumeRollback() testAttachIso() @@ -343,6 +351,86 @@ class XinfiniPrimaryStorageCase extends SubCase { deleteVm(vm2.uuid) } + // when the old host's storage client cannot be isolated, deactivate must report + // a failure instead of silently succeeding, otherwise the VM gets started on a + // new host while the old QEMU still holds the volume (split-brain). + void testPreventSplitBrainOnDeactivateFailure() { + def rootVolPath = Q.New(VolumeVO.class) + .eq(VolumeVO_.uuid, vm.rootVolumeUuid) + .select(VolumeVO_.installPath).findValue() as String + int volId = XInfiniPathHelper.getVolIdFromPath(rootVolPath) + BdcModule bdc = controller.apiHelper.queryBdcByIp(host1.managementIp) + BdcBdevModule bdev = controller.apiHelper.queryBdcBdevByVolumeIdAndBdcId(volId, bdc.spec.id) + assert bdev != null + + // simMode: 0 = default, 1 = delete request fails, 2 = delete accepted but bdev never disappears + int[] simMode = [0] + boolean[] bdcInactive = [false] + + env.simulator("/afa/v1/bdcs/\\d+") { HttpServletRequest req, HttpEntity e, EnvSpec spec -> + return [ + metadata: [id: 1, name: "bdc-1", state: [state: "active"]], + spec : [id: 1, name: "bdc-1", ip: "127.0.0.1", port: 9500], + status : [id: 1, run_state: bdcInactive[0] ? "Offline" : "Active", + installed: true, hostname: "localhost", version: "1.0.0"] + ] + } + + env.simulator("/afa/v1/bdc-bdevs/\\d+") { HttpServletRequest req, HttpEntity e, EnvSpec spec -> + def matcher = (req.getRequestURI() =~ /\/(\d+)$/) + int bdevId = matcher.find() ? Integer.parseInt(matcher.group(1)) : -1 + def store = ExternalPrimaryStorageSpec.XinfiniSimulators.bdcBdevs + if (req.getMethod() == "DELETE") { + if (simMode[0] == 1) { + return [message: "delete bdev failed on purpose"] + } + if (simMode[0] != 2) { + store.remove(bdevId) + } + return [:] + } + + def stored = store.get(bdevId) + if (stored == null) { + throw new HttpError(404, "not found") + } + return [metadata: [id: stored.spec?.id, name: stored.spec?.name, state: [state: "active"]], + spec: stored.spec, status: stored.status] + } + + def hostVO = Q.New(HostVO.class).eq(HostVO_.uuid, host1.uuid).find() + def headerHost = org.zstack.header.host.HostInventory.valueOf(hostVO) + + // scenario 1: the delete bdev request fails -> deactivate must report failure + simMode[0] = 1 + boolean[] result = [false, false] // [success, fail] + controller.deactivate(rootVolPath, "Vhost", headerHost, new Completion(null) { + @Override + void success() { result[0] = true } + + @Override + void fail(ErrorCode errorCode) { result[1] = true } + }) + assert result[1]: "deactivate must fail when the bdev cannot be deleted" + assert !result[0]: "deactivate must not report success when the bdev cannot be deleted" + + // scenario 2: the delete request is accepted but the bdev stays attached -> + // deleteBdcBdev must error out instead of silently treating it as deleted + simMode[0] = 2 + bdcInactive[0] = true + boolean errored = false + try { + controller.apiHelper.deleteBdcBdev(bdev.spec.id, bdc.spec.id) + } catch (OperationFailureException ignored) { + errored = true + } + assert errored: "deleteBdcBdev must error out when the bdev is still attached" + + // restore default simulator behaviour for the rest of the suite + simMode[0] = 0 + bdcInactive[0] = false + } + void testHandleInactiveVolume() { def rootVolInstallPath = Q.New(VolumeVO.class).eq(VolumeVO_.uuid, vm.rootVolumeUuid).select(VolumeVO_.installPath).findValue() int volId = XInfiniPathHelper.getVolIdFromPath(rootVolInstallPath as String) diff --git a/test/src/test/groovy/org/zstack/test/integration/storage/primary/addon/zbs/ZbsPrimaryStorageCase.groovy b/test/src/test/groovy/org/zstack/test/integration/storage/primary/addon/zbs/ZbsPrimaryStorageCase.groovy index e5bfba095e9..d938f1da8fc 100644 --- a/test/src/test/groovy/org/zstack/test/integration/storage/primary/addon/zbs/ZbsPrimaryStorageCase.groovy +++ b/test/src/test/groovy/org/zstack/test/integration/storage/primary/addon/zbs/ZbsPrimaryStorageCase.groovy @@ -12,6 +12,8 @@ import org.zstack.header.storage.addon.primary.ExternalPrimaryStorageSpaceVO_ import org.zstack.header.storage.addon.primary.PrimaryStorageOutputProtocolRefVO import org.zstack.header.storage.primary.PrimaryStorageCapacityVO import org.zstack.header.storage.primary.PrimaryStorageCapacityVO_ +import org.zstack.header.storage.primary.PrimaryStorageClusterRefVO +import org.zstack.header.storage.primary.PrimaryStorageClusterRefVO_ import org.zstack.header.storage.primary.PrimaryStorageHostRefVO import org.zstack.header.storage.primary.PrimaryStorageHostRefVO_ import org.zstack.header.storage.primary.PrimaryStorageStatus @@ -37,6 +39,7 @@ import org.zstack.utils.data.SizeUnit import org.zstack.utils.gson.JSONObjectUtil import java.util.concurrent.CyclicBarrier +import java.util.concurrent.atomic.AtomicBoolean import java.util.concurrent.atomic.AtomicInteger /** @@ -175,6 +178,9 @@ class ZbsPrimaryStorageCase extends SubCase { testSyncPrimaryStorageCapacityConcurrently() testDefaultConfig() testUpdateExternalPrimaryStorage() + testPrepareHostsWhenAttachPrimaryStorageToCluster() + testAttachPrimaryStorageFailsWhenPreparingUsableHostFails() + testAttachPrimaryStorageFailsWhenActivatingHeartbeatVolumeFails() testMdsConnectFailed() testLifecycle() testDataVolumeLifecycle() @@ -210,8 +216,25 @@ class ZbsPrimaryStorageCase extends SubCase { clusterUuid = cluster.uuid } + Set heartbeatPools = Collections.synchronizedSet(new HashSet<>()) + AtomicBoolean checkStartedBeforeHeartbeatReady = new AtomicBoolean(false) + env.afterSimulator(ZbsStorageController.CREATE_VOLUME_PATH) { rsp, HttpEntity e -> + ZbsStorageController.CreateVolumeCmd cmd = JSONObjectUtil.toObject(e.body, ZbsStorageController.CreateVolumeCmd) + if (cmd.volume == ZbsConstants.ZBS_HEARTBEAT_VOLUME_NAME) { + heartbeatPools.add(cmd.logicalPool) + ZbsStorageController.CreateVolumeRsp createVolumeRsp = new ZbsStorageController.CreateVolumeRsp() + createVolumeRsp.installPath = "zbs://${cmd.logicalPool}/${cmd.volume}" + return createVolumeRsp + } + + return rsp + } + env.afterSimulator(ZbsStorageController.CHECK_HOST_STORAGE_CONNECTION_PATH) { rsp, HttpEntity e -> ZbsStorageController.CheckHostStorageConnectionCmd cmd = JSONObjectUtil.toObject(e.body, ZbsStorageController.CheckHostStorageConnectionCmd) + if (!heartbeatPools.containsAll(["lpool1", "lpool2"])) { + checkStartedBeforeHeartbeatReady.set(true) + } ZbsStorageController.CheckHostStorageConnectionRsp checkHostStorageConnectionRsp = new ZbsStorageController.CheckHostStorageConnectionRsp() checkHostStorageConnectionRsp.error = "fake error" @@ -225,6 +248,10 @@ class ZbsPrimaryStorageCase extends SubCase { uuid = kvm.getUuid() } } + retryInSecs { + assert heartbeatPools.containsAll(["lpool1", "lpool2"]) + assert !checkStartedBeforeHeartbeatReady.get() + } retryInSecs { assert Q.New(PrimaryStorageHostRefVO.class) @@ -464,7 +491,205 @@ class ZbsPrimaryStorageCase extends SubCase { assert rc.value == ZbsConstants.VOLUME_PHYSICAL_BLOCK_SIZE } + void testPrepareHostsWhenAttachPrimaryStorageToCluster() { + KVMHostInventory kvm2 = env.inventoryByName("kvm-2") as KVMHostInventory + KVMHostInventory kvm3 = env.inventoryByName("kvm-3") as KVMHostInventory + changeHostState { + uuid = kvm3.uuid + stateEvent = "maintain" + } + + List attachCalls = Collections.synchronizedList(new ArrayList<>()) + AtomicInteger attachCheckHostStatusCount = new AtomicInteger(0) + env.afterSimulator(ZbsStorageController.DEPLOY_CLIENT_PATH) { rsp, HttpEntity e -> + def cmd = JSONObjectUtil.toObject(e.body, ZbsStorageController.DeployClientCmd) + attachCalls.add("deploy:${cmd.ip}".toString()) + return rsp + } + env.afterSimulator(ZbsStorageController.CREATE_VOLUME_PATH) { rsp, HttpEntity e -> + def cmd = JSONObjectUtil.toObject(e.body, ZbsStorageController.CreateVolumeCmd) + if (cmd.volume == ZbsConstants.ZBS_HEARTBEAT_VOLUME_NAME) { + attachCalls.add("heartbeat:${cmd.logicalPool}".toString()) + ZbsStorageController.CreateVolumeRsp createVolumeRsp = new ZbsStorageController.CreateVolumeRsp() + createVolumeRsp.installPath = "zbs://${cmd.logicalPool}/${cmd.volume}" + return createVolumeRsp + } + + return rsp + } + env.afterSimulator(ZbsStorageController.CHECK_HOST_STORAGE_CONNECTION_PATH) { rsp, HttpEntity e -> + attachCheckHostStatusCount.incrementAndGet() + return rsp + } + + attachPrimaryStorageToCluster { + primaryStorageUuid = ps.uuid + clusterUuid = cluster.uuid + } + + assert attachCalls.findAll { it.startsWith("deploy:") }.sort() == ["deploy:127.0.0.1", "deploy:127.0.0.2"] + assert attachCalls.take(2).every { it.startsWith("deploy:") } + assert attachCalls.findAll { it.startsWith("heartbeat:") }.sort() == ["heartbeat:lpool1", "heartbeat:lpool2"] + assert attachCheckHostStatusCount.get() == 0 + + env.cleanAfterSimulatorHandlers() + changeHostState { + uuid = kvm3.uuid + stateEvent = "enable" + } + retryInSecs { + HostInventory host = queryHost { + conditions = ["uuid=${kvm3.uuid}"] + }[0] as HostInventory + assert host.state == "Enabled" + assert host.status == "Connected" + } + + List reconnectCalls = Collections.synchronizedList(new ArrayList<>()) + AtomicInteger reconnectCheckHostStatusCount = new AtomicInteger(0) + env.afterSimulator(ZbsStorageController.DEPLOY_CLIENT_PATH) { rsp, HttpEntity e -> + def cmd = JSONObjectUtil.toObject(e.body, ZbsStorageController.DeployClientCmd) + if (cmd.ip == "127.0.0.2") { + reconnectCalls.add("deploy:${cmd.ip}".toString()) + } + return rsp + } + env.afterSimulator(ZbsStorageController.CREATE_VOLUME_PATH) { rsp, HttpEntity e -> + def cmd = JSONObjectUtil.toObject(e.body, ZbsStorageController.CreateVolumeCmd) + if (cmd.volume == ZbsConstants.ZBS_HEARTBEAT_VOLUME_NAME) { + reconnectCalls.add("heartbeat:${cmd.logicalPool}".toString()) + ZbsStorageController.CreateVolumeRsp createVolumeRsp = new ZbsStorageController.CreateVolumeRsp() + createVolumeRsp.installPath = "zbs://${cmd.logicalPool}/${cmd.volume}" + return createVolumeRsp + } + + return rsp + } + env.afterSimulator(ZbsStorageController.CHECK_HOST_STORAGE_CONNECTION_PATH) { rsp, HttpEntity e -> + def cmd = JSONObjectUtil.toObject(e.body, ZbsStorageController.CheckHostStorageConnectionCmd) + if (cmd.hostUuid == kvm2.uuid) { + reconnectCheckHostStatusCount.incrementAndGet() + } + ZbsStorageController.CheckHostStorageConnectionRsp checkHostStorageConnectionRsp = new ZbsStorageController.CheckHostStorageConnectionRsp() + checkHostStorageConnectionRsp.success = true + return checkHostStorageConnectionRsp + } + + reconnectHost { + uuid = kvm2.uuid + } + + assert reconnectCalls.contains("deploy:127.0.0.2") + assert reconnectCalls.containsAll(["heartbeat:lpool1", "heartbeat:lpool2"]) + assert reconnectCheckHostStatusCount.get() > 0 + + if (Q.New(PrimaryStorageClusterRefVO.class) + .eq(PrimaryStorageClusterRefVO_.primaryStorageUuid, ps.uuid) + .eq(PrimaryStorageClusterRefVO_.clusterUuid, cluster.uuid) + .isExists()) { + detachPrimaryStorageFromCluster { + primaryStorageUuid = ps.uuid + clusterUuid = cluster.uuid + } + } + } + + void testAttachPrimaryStorageFailsWhenPreparingUsableHostFails() { + env.cleanAfterSimulatorHandlers() + + PrimaryStorageStatus statusBeforeAttach = Q.New(ExternalPrimaryStorageVO.class) + .select(ExternalPrimaryStorageVO_.status) + .eq(ExternalPrimaryStorageVO_.uuid, ps.uuid) + .findValue() + AtomicInteger failedDeployCount = new AtomicInteger(0) + AtomicInteger heartbeatCount = new AtomicInteger(0) + env.afterSimulator(ZbsStorageController.DEPLOY_CLIENT_PATH) { rsp, HttpEntity e -> + def cmd = JSONObjectUtil.toObject(e.body, ZbsStorageController.DeployClientCmd) + if (cmd.ip == "127.0.0.1") { + failedDeployCount.incrementAndGet() + ZbsStorageController.DeployClientRsp deployClientRsp = new ZbsStorageController.DeployClientRsp() + deployClientRsp.success = false + deployClientRsp.error = "on purpose" + return deployClientRsp + } + + return rsp + } + env.afterSimulator(ZbsStorageController.CREATE_VOLUME_PATH) { rsp, HttpEntity e -> + def cmd = JSONObjectUtil.toObject(e.body, ZbsStorageController.CreateVolumeCmd) + if (cmd.volume == ZbsConstants.ZBS_HEARTBEAT_VOLUME_NAME) { + heartbeatCount.incrementAndGet() + } + + return rsp + } + + expect(AssertionError.class) { + attachPrimaryStorageToCluster { + primaryStorageUuid = ps.uuid + clusterUuid = cluster.uuid + } + } + + assert !Q.New(PrimaryStorageClusterRefVO.class) + .eq(PrimaryStorageClusterRefVO_.primaryStorageUuid, ps.uuid) + .eq(PrimaryStorageClusterRefVO_.clusterUuid, cluster.uuid) + .isExists() + assert Q.New(ExternalPrimaryStorageVO.class) + .select(ExternalPrimaryStorageVO_.status) + .eq(ExternalPrimaryStorageVO_.uuid, ps.uuid) + .findValue() == statusBeforeAttach + assert failedDeployCount.get() == 1 + assert heartbeatCount.get() == 0 + } + + void testAttachPrimaryStorageFailsWhenActivatingHeartbeatVolumeFails() { + env.cleanAfterSimulatorHandlers() + + PrimaryStorageStatus statusBeforeAttach = Q.New(ExternalPrimaryStorageVO.class) + .select(ExternalPrimaryStorageVO_.status) + .eq(ExternalPrimaryStorageVO_.uuid, ps.uuid) + .findValue() + AtomicInteger deployCount = new AtomicInteger(0) + AtomicInteger failedHeartbeatCount = new AtomicInteger(0) + env.afterSimulator(ZbsStorageController.DEPLOY_CLIENT_PATH) { rsp, HttpEntity e -> + deployCount.incrementAndGet() + return rsp + } + env.afterSimulator(ZbsStorageController.CREATE_VOLUME_PATH) { rsp, HttpEntity e -> + def cmd = JSONObjectUtil.toObject(e.body, ZbsStorageController.CreateVolumeCmd) + if (cmd.volume == ZbsConstants.ZBS_HEARTBEAT_VOLUME_NAME) { + failedHeartbeatCount.incrementAndGet() + ZbsStorageController.CreateVolumeRsp createVolumeRsp = new ZbsStorageController.CreateVolumeRsp() + createVolumeRsp.setError("on purpose") + return createVolumeRsp + } + + return rsp + } + + expect(AssertionError.class) { + attachPrimaryStorageToCluster { + primaryStorageUuid = ps.uuid + clusterUuid = cluster.uuid + } + } + + assert !Q.New(PrimaryStorageClusterRefVO.class) + .eq(PrimaryStorageClusterRefVO_.primaryStorageUuid, ps.uuid) + .eq(PrimaryStorageClusterRefVO_.clusterUuid, cluster.uuid) + .isExists() + assert Q.New(ExternalPrimaryStorageVO.class) + .select(ExternalPrimaryStorageVO_.status) + .eq(ExternalPrimaryStorageVO_.uuid, ps.uuid) + .findValue() == statusBeforeAttach + assert deployCount.get() > 0 + assert failedHeartbeatCount.get() == 1 + } + void testLifecycle() { + env.cleanAfterSimulatorHandlers() + updateExternalPrimaryStorage { uuid = ps.uuid name = "test-zbs-new-name" diff --git a/test/src/test/groovy/org/zstack/test/integration/storage/snapshot/CreateSnapshotRollbackAfterDataPlaneSuccessCase.groovy b/test/src/test/groovy/org/zstack/test/integration/storage/snapshot/CreateSnapshotRollbackAfterDataPlaneSuccessCase.groovy new file mode 100644 index 00000000000..46979001b31 --- /dev/null +++ b/test/src/test/groovy/org/zstack/test/integration/storage/snapshot/CreateSnapshotRollbackAfterDataPlaneSuccessCase.groovy @@ -0,0 +1,205 @@ +package org.zstack.test.integration.storage.snapshot + +import org.springframework.http.HttpEntity +import org.zstack.core.Platform +import org.zstack.core.componentloader.PluginRegistry +import org.zstack.core.db.Q +import org.zstack.header.core.Completion +import org.zstack.header.core.workflow.Flow +import org.zstack.header.storage.snapshot.ConsistentType +import org.zstack.header.storage.snapshot.CreateVolumesSnapshotOverlayInnerMsg +import org.zstack.header.storage.snapshot.TakeVolumesSnapshotOnKvmReply +import org.zstack.header.storage.snapshot.VolumeSnapshotConstant +import org.zstack.header.storage.snapshot.VolumeSnapshotCreationExtensionPoint +import org.zstack.header.storage.snapshot.VolumeSnapshotStatus +import org.zstack.header.storage.snapshot.VolumeSnapshotTreeStatus +import org.zstack.header.storage.snapshot.VolumeSnapshotTreeVO +import org.zstack.header.storage.snapshot.VolumeSnapshotInventory +import org.zstack.header.storage.snapshot.VolumeSnapshotVO +import org.zstack.header.storage.snapshot.VolumeSnapshotVO_ +import org.zstack.header.storage.snapshot.group.VolumeSnapshotGroupInventory +import org.zstack.header.storage.snapshot.reference.VolumeSnapshotReferenceVO +import org.zstack.header.storage.snapshot.reference.VolumeSnapshotReferenceVO_ +import org.zstack.header.volume.CreateVolumeSnapshotGroupMessage +import org.zstack.header.volume.VolumeVO +import org.zstack.header.volume.VolumeVO_ +import org.zstack.kvm.KVMAgentCommands +import org.zstack.kvm.KVMConstant +import org.zstack.sdk.VmInstanceInventory +import org.zstack.test.integration.ldap.Env +import org.zstack.test.integration.storage.StorageTest +import org.zstack.testlib.EnvSpec +import org.zstack.testlib.SubCase +import org.zstack.utils.gson.JSONObjectUtil + +class CreateSnapshotRollbackAfterDataPlaneSuccessCase extends SubCase { + EnvSpec env + VmInstanceInventory vm + + int takeSnapshotCount = 0 + String firstSnapshotInstallPath + String firstNewVolumeInstallPath + String secondVolumeInstallPath + String secondSnapshotInstallPath + String secondNewVolumeInstallPath + long snapshotSize = 1L + + @Override + void clean() { + env.delete() + } + + @Override + void setup() { + useSpring(StorageTest.springSpec) + } + + @Override + void environment() { + env = Env.localStorageOneVmEnv() + } + + @Override + void test() { + env.create { + vm = env.inventoryByName("vm") as VmInstanceInventory + testKeepSnapshotMetadataWhenControlPlaneFailsAfterDataPlaneSuccess() + } + } + + void testKeepSnapshotMetadataWhenControlPlaneFailsAfterDataPlaneSuccess() { + String originalVolumeInstallPath = Q.New(VolumeVO.class) + .select(VolumeVO_.installPath) + .eq(VolumeVO_.uuid, vm.rootVolumeUuid) + .findValue() + + env.simulator(KVMConstant.KVM_TAKE_VOLUME_SNAPSHOT_PATH) { HttpEntity e, EnvSpec espec -> + KVMAgentCommands.TakeSnapshotCmd cmd = JSONObjectUtil.toObject(e.body, KVMAgentCommands.TakeSnapshotCmd.class) + takeSnapshotCount++ + + if (takeSnapshotCount == 1) { + assert cmd.volumeInstallPath == originalVolumeInstallPath + firstSnapshotInstallPath = cmd.volumeInstallPath + firstNewVolumeInstallPath = cmd.installPath + } else if (takeSnapshotCount == 2) { + secondVolumeInstallPath = cmd.volumeInstallPath + secondSnapshotInstallPath = cmd.volumeInstallPath + secondNewVolumeInstallPath = cmd.installPath + } + + KVMAgentCommands.TakeSnapshotResponse rsp = new KVMAgentCommands.TakeSnapshotResponse() + rsp.newVolumeInstallPath = cmd.installPath + rsp.snapshotInstallPath = cmd.volumeInstallPath + rsp.size = snapshotSize + return rsp + } + + PluginRegistry pluginRegistry = bean(PluginRegistry.class) + List extensions = pluginRegistry.getExtensionList(VolumeSnapshotCreationExtensionPoint.class) + FailAfterSnapshotCreatedExtension failureExtension = new FailAfterSnapshotCreatedExtension() + extensions.add(failureExtension) + + try { + expectError { + createVolumeSnapshot { + name = "snapshot-fail-after-metadata-synced" + volumeUuid = vm.rootVolumeUuid + } + } + + assert takeSnapshotCount == 1 + + VolumeSnapshotVO firstSnapshot + retryInSecs(10, 1) { + firstSnapshot = Q.New(VolumeSnapshotVO.class) + .eq(VolumeSnapshotVO_.volumeUuid, vm.rootVolumeUuid) + .find() + assert firstSnapshot != null + assert firstSnapshot.status == VolumeSnapshotStatus.Ready + } + + assert firstSnapshot.latest + assert firstSnapshot.primaryStorageInstallPath == firstSnapshotInstallPath + assert firstSnapshot.type == VolumeSnapshotConstant.HYPERVISOR_SNAPSHOT_TYPE.toString() + assert firstSnapshot.size == snapshotSize + + VolumeSnapshotTreeVO firstTree = dbFindByUuid(firstSnapshot.treeUuid, VolumeSnapshotTreeVO.class) + assert firstTree.current + assert firstTree.status == VolumeSnapshotTreeStatus.Completed + + assert Q.New(VolumeVO.class) + .select(VolumeVO_.installPath) + .eq(VolumeVO_.uuid, vm.rootVolumeUuid) + .findValue() == firstNewVolumeInstallPath + + VolumeSnapshotReferenceVO ref = Q.New(VolumeSnapshotReferenceVO.class) + .eq(VolumeSnapshotReferenceVO_.volumeUuid, vm.rootVolumeUuid) + .limit(1) + .find() + if (ref != null && ref.referenceInstallUrl == firstSnapshotInstallPath) { + assert ref.referenceUuid == firstSnapshot.uuid + assert ref.referenceType == VolumeSnapshotVO.class.simpleName + } + + org.zstack.sdk.VolumeSnapshotInventory secondSnapshotInv = createVolumeSnapshot { + name = "snapshot-after-recovery" + volumeUuid = vm.rootVolumeUuid + } as org.zstack.sdk.VolumeSnapshotInventory + + assert takeSnapshotCount == 2 + assert secondVolumeInstallPath == firstNewVolumeInstallPath + + VolumeSnapshotVO firstSnapshotAfterRecovery = dbFindByUuid(firstSnapshot.uuid, VolumeSnapshotVO.class) + VolumeSnapshotVO secondSnapshot = dbFindByUuid(secondSnapshotInv.uuid, VolumeSnapshotVO.class) + assert !firstSnapshotAfterRecovery.latest + assert secondSnapshot.latest + assert secondSnapshot.parentUuid == firstSnapshot.uuid + assert secondSnapshot.primaryStorageInstallPath == secondSnapshotInstallPath + assert secondSnapshot.status == VolumeSnapshotStatus.Ready + + assert Q.New(VolumeSnapshotVO.class) + .eq(VolumeSnapshotVO_.volumeUuid, vm.rootVolumeUuid) + .count() == 2 + assert Q.New(VolumeVO.class) + .select(VolumeVO_.installPath) + .eq(VolumeVO_.uuid, vm.rootVolumeUuid) + .findValue() == secondNewVolumeInstallPath + } finally { + extensions.remove(failureExtension) + } + } + + private static class FailAfterSnapshotCreatedExtension implements VolumeSnapshotCreationExtensionPoint { + boolean failAfterSnapshotCreated = true + + @Override + void afterVolumeSnapshotCreated(VolumeSnapshotInventory snapshot, Completion completion) { + if (failAfterSnapshotCreated) { + failAfterSnapshotCreated = false + completion.fail(Platform.operr("TEST.ERROR", "fail after KVM snapshot has been created")) + return + } + + completion.success() + } + + @Override + void afterVolumeLiveSnapshotGroupCreatedOnBackend(CreateVolumesSnapshotOverlayInnerMsg msg, TakeVolumesSnapshotOnKvmReply treply, Completion completion) { + completion.success() + } + + @Override + void afterVolumeLiveSnapshotGroupCreationFailsOnBackend(CreateVolumesSnapshotOverlayInnerMsg msg, TakeVolumesSnapshotOnKvmReply treply) { + } + + @Override + void afterVolumeSnapshotGroupCreated(VolumeSnapshotGroupInventory snapshotGroup, ConsistentType consistentType, Completion completion) { + completion.success() + } + + @Override + List beforeCreateVolumeSnapshotFlow(CreateVolumeSnapshotGroupMessage msg) { + return null + } + } +} diff --git a/test/src/test/groovy/org/zstack/test/unittest/network/sdncontroller/SdnControllerInventoryCase.groovy b/test/src/test/groovy/org/zstack/test/unittest/network/sdncontroller/SdnControllerInventoryCase.groovy new file mode 100644 index 00000000000..1038493b6c5 --- /dev/null +++ b/test/src/test/groovy/org/zstack/test/unittest/network/sdncontroller/SdnControllerInventoryCase.groovy @@ -0,0 +1,22 @@ +package org.zstack.test.unittest.network.sdncontroller + +import org.junit.Test +import org.zstack.header.network.sdncontroller.SdnControllerInventory +import org.zstack.header.network.sdncontroller.SdnControllerVO + +class SdnControllerInventoryCase { + @Test + void testInventoryIpStripsEndpointPort() { + assert inventoryIp(" 10.0.0.10:8080 ") == "10.0.0.10" + assert inventoryIp(" controller.example.com:6640 ") == "controller.example.com" + assert inventoryIp(" [fe80::1]:6640 ") == "fe80::1" + assert inventoryIp(" 2001:db8::1 ") == "2001:db8::1" + assert inventoryIp(" controller.example.com ") == "controller.example.com" + } + + private static String inventoryIp(String endpoint) { + SdnControllerVO vo = new SdnControllerVO() + vo.setIp(endpoint) + return SdnControllerInventory.valueOf(vo).getIp() + } +} diff --git a/test/src/test/java/org/zstack/test/kvm/KVMHostUtilsTest.java b/test/src/test/java/org/zstack/test/kvm/KVMHostUtilsTest.java index 6933d2e9db2..0ae331da3d5 100644 --- a/test/src/test/java/org/zstack/test/kvm/KVMHostUtilsTest.java +++ b/test/src/test/java/org/zstack/test/kvm/KVMHostUtilsTest.java @@ -2,9 +2,12 @@ import org.junit.Assert; import org.junit.Test; +import org.zstack.core.CoreGlobalProperty; +import org.zstack.header.errorcode.ErrorCode; import org.zstack.kvm.KVMHostUtils; import java.util.Collections; +import java.util.concurrent.TimeUnit; public class KVMHostUtilsTest { @@ -187,4 +190,83 @@ public void shouldForceTlsRedeploy_newAddedForces() { public void shouldForceTlsRedeploy_reconnectWithoutRestartSkips() { Assert.assertFalse(KVMHostUtils.shouldForceTlsRedeploy(true, false, false)); } + + @Test + public void shouldRestartLibvirtdDuringDeploy_initOrRestartLibvirtdTriggers() { + Assert.assertFalse(KVMHostUtils.shouldRestartLibvirtdDuringDeploy(null, null)); + Assert.assertFalse(KVMHostUtils.shouldRestartLibvirtdDuringDeploy("false", "false")); + Assert.assertTrue(KVMHostUtils.shouldRestartLibvirtdDuringDeploy("true", "false")); + Assert.assertTrue(KVMHostUtils.shouldRestartLibvirtdDuringDeploy("false", "true")); + Assert.assertTrue(KVMHostUtils.shouldRestartLibvirtdDuringDeploy("TrUe", null)); + Assert.assertTrue(KVMHostUtils.shouldRestartLibvirtdDuringDeploy(null, "TrUe")); + } + + @Test + public void calculateLibvirtRestartEchoTimeout_keepsDefaultAtThreshold() { + int oldTimeout = CoreGlobalProperty.REST_FACADE_ECHO_TIMEOUT; + try { + CoreGlobalProperty.REST_FACADE_ECHO_TIMEOUT = 60; + Assert.assertEquals(TimeUnit.SECONDS.toMillis(60), + KVMHostUtils.calculateLibvirtRestartEchoTimeoutMillis(100)); + } finally { + CoreGlobalProperty.REST_FACADE_ECHO_TIMEOUT = oldTimeout; + } + } + + @Test + public void calculateLibvirtRestartEchoTimeout_addsOneSecondAfterThreshold() { + int oldTimeout = CoreGlobalProperty.REST_FACADE_ECHO_TIMEOUT; + try { + CoreGlobalProperty.REST_FACADE_ECHO_TIMEOUT = 60; + Assert.assertEquals(TimeUnit.SECONDS.toMillis(61), + KVMHostUtils.calculateLibvirtRestartEchoTimeoutMillis(101)); + } finally { + CoreGlobalProperty.REST_FACADE_ECHO_TIMEOUT = oldTimeout; + } + } + + @Test + public void calculateLibvirtRestartEchoTimeout_capsAt180Seconds() { + int oldTimeout = CoreGlobalProperty.REST_FACADE_ECHO_TIMEOUT; + try { + CoreGlobalProperty.REST_FACADE_ECHO_TIMEOUT = 60; + Assert.assertEquals(TimeUnit.SECONDS.toMillis(180), + KVMHostUtils.calculateLibvirtRestartEchoTimeoutMillis(10000)); + } finally { + CoreGlobalProperty.REST_FACADE_ECHO_TIMEOUT = oldTimeout; + } + } + + @Test + public void calculateLibvirtRestartEchoTimeout_doesNotReduceConfiguredTimeoutAboveCap() { + int oldTimeout = CoreGlobalProperty.REST_FACADE_ECHO_TIMEOUT; + try { + CoreGlobalProperty.REST_FACADE_ECHO_TIMEOUT = 180; + Assert.assertEquals(TimeUnit.SECONDS.toMillis(180), + KVMHostUtils.calculateLibvirtRestartEchoTimeoutMillis(10000)); + + CoreGlobalProperty.REST_FACADE_ECHO_TIMEOUT = 300; + Assert.assertEquals(TimeUnit.SECONDS.toMillis(300), + KVMHostUtils.calculateLibvirtRestartEchoTimeoutMillis(10000)); + } finally { + CoreGlobalProperty.REST_FACADE_ECHO_TIMEOUT = oldTimeout; + } + } + + @Test + public void zstac77120_continueReconnectOnLibvirtSocketMaskSystemdTimeout() { + ErrorCode error = new ErrorCode(); + error.setDetails("[HOST: 192.168.51.12] ERROR: run shell command: systemctl mask libvirtd.socket libvirtd-ro.socket libvirtd-admin.socket libvirtd-tls.socket libvirtd-tcp.socket failed! stderr: Failed to get properties: Failed to activate service 'org.freedesktop.systemd1': timed out (service_start_timeout=25000ms)"); + + Assert.assertTrue(KVMHostUtils.shouldContinueReconnectOnAnsibleFailure(false, error)); + Assert.assertFalse(KVMHostUtils.shouldContinueReconnectOnAnsibleFailure(true, error)); + } + + @Test + public void zstac77120_doNotContinueReconnectOnOtherAnsibleFailures() { + ErrorCode error = new ErrorCode(); + error.setDetails("[HOST: 192.168.51.12] ERROR: run shell command: systemctl restart libvirtd failed! stderr: Job for libvirtd.service failed"); + + Assert.assertFalse(KVMHostUtils.shouldContinueReconnectOnAnsibleFailure(false, error)); + } } diff --git a/test/src/test/resources/springConfigXml/Kvm.xml b/test/src/test/resources/springConfigXml/Kvm.xml index b5c509ebad7..9001b76bda8 100755 --- a/test/src/test/resources/springConfigXml/Kvm.xml +++ b/test/src/test/resources/springConfigXml/Kvm.xml @@ -90,6 +90,12 @@ + + + + + + @@ -101,9 +107,9 @@ - - - + + + diff --git a/testlib/src/main/java/org/zstack/testlib/ApiHelper.groovy b/testlib/src/main/java/org/zstack/testlib/ApiHelper.groovy index b505a267862..ea5faa760de 100644 --- a/testlib/src/main/java/org/zstack/testlib/ApiHelper.groovy +++ b/testlib/src/main/java/org/zstack/testlib/ApiHelper.groovy @@ -14,27 +14,27 @@ abstract class ApiHelper { return res.value } } - + def createBareMetal2InstanceFromVmBackup(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.heder.storage.volume.backup.CreateBareMetal2InstanceFromVmBackupAction.class) Closure c) { def a = new org.zstack.heder.storage.volume.backup.CreateBareMetal2InstanceFromVmBackupAction() a.sessionId = Test.currentEnvSpec?.session?.uuid c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -48,20 +48,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -75,20 +75,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -102,20 +102,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -129,20 +129,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -156,20 +156,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -183,20 +183,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -210,20 +210,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -237,20 +237,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -264,20 +264,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -291,20 +291,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -318,22 +318,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -347,20 +349,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -374,20 +376,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -401,20 +403,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -428,20 +430,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -455,20 +457,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -482,20 +484,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -509,20 +511,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -536,20 +538,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -563,20 +565,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -590,20 +592,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -617,20 +619,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -644,20 +646,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -671,20 +673,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -698,20 +700,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -725,20 +727,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -752,20 +754,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -779,20 +781,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -806,20 +808,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -833,20 +835,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -860,20 +862,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -887,20 +889,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -914,20 +916,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -941,20 +943,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -968,20 +970,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -995,20 +997,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -1022,20 +1024,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -1049,20 +1051,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -1076,20 +1078,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -1103,20 +1105,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -1130,20 +1132,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -1157,20 +1159,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -1184,20 +1186,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -1211,20 +1213,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -1238,20 +1240,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -1265,20 +1267,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -1292,20 +1294,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -1319,20 +1321,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -1346,20 +1348,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -1373,20 +1375,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -1400,20 +1402,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -1427,20 +1429,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -1454,20 +1456,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -1481,20 +1483,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -1508,20 +1510,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -1535,20 +1537,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -1562,20 +1564,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -1589,20 +1591,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -1616,20 +1618,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -1643,20 +1645,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -1670,20 +1672,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -1697,20 +1699,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -1724,20 +1726,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -1751,20 +1753,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -1778,20 +1780,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -1805,20 +1807,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -1832,20 +1834,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -1859,20 +1861,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -1886,20 +1888,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -1913,20 +1915,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -1940,20 +1942,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -1967,20 +1969,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -1994,20 +1996,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -2021,20 +2023,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -2048,20 +2050,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -2075,20 +2077,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -2102,20 +2104,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -2129,20 +2131,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -2156,20 +2158,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -2183,20 +2185,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -2210,20 +2212,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -2237,20 +2239,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -2264,20 +2266,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -2291,20 +2293,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -2318,20 +2320,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -2345,20 +2347,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -2372,20 +2374,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -2399,20 +2401,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -2426,20 +2428,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -2453,20 +2455,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -2480,20 +2482,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -2507,20 +2509,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -2534,20 +2536,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -2561,20 +2563,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -2588,20 +2590,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -2615,20 +2617,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -2642,20 +2644,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -2669,20 +2671,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -2696,20 +2698,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -2723,20 +2725,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -2750,20 +2752,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -2777,20 +2779,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -2804,20 +2806,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -2831,20 +2833,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -2858,20 +2860,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -2885,20 +2887,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -2912,20 +2914,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -2939,20 +2941,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -2966,20 +2968,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -2993,20 +2995,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -3020,20 +3022,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -3047,20 +3049,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -3074,20 +3076,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -3101,20 +3103,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -3128,20 +3130,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -3155,20 +3157,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -3182,20 +3184,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -3209,20 +3211,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -3236,20 +3238,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -3263,20 +3265,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -3290,20 +3292,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -3317,20 +3319,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -3344,20 +3346,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -3371,20 +3373,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -3398,20 +3400,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -3425,20 +3427,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -3452,20 +3454,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -3479,20 +3481,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -3506,20 +3508,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -3533,20 +3535,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -3560,20 +3562,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -3587,20 +3589,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -3614,20 +3616,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -3641,20 +3643,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -3668,20 +3670,47 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + + + if (System.getProperty("apipath") != null) { + if (a.apiId == null) { + a.apiId = Platform.uuid + } + + def tracker = new ApiPathTracker(a.apiId) + def out = errorOut(a.call()) + def path = tracker.getApiPath() + if (!path.isEmpty()) { + Test.apiPaths[a.class.name] = path.join(" --->\n") + } + + return out + } else { + return errorOut(a.call()) + } + } + + + def attachDGpuToVm(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.AttachDGpuToVmAction.class) Closure c) { + def a = new org.zstack.sdk.AttachDGpuToVmAction() + a.sessionId = Test.currentEnvSpec?.session?.uuid + c.resolveStrategy = Closure.OWNER_FIRST + c.delegate = a + c() + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -3695,20 +3724,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -3722,20 +3751,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -3749,20 +3778,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -3776,20 +3805,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -3803,20 +3832,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -3830,20 +3859,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -3857,20 +3886,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -3884,20 +3913,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -3911,20 +3940,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -3938,20 +3967,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -3965,20 +3994,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -3992,20 +4021,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -4019,20 +4048,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -4046,20 +4075,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -4073,20 +4102,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -4100,20 +4129,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -4127,20 +4156,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -4154,20 +4183,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -4181,20 +4210,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -4208,20 +4237,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -4235,20 +4264,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -4262,20 +4291,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -4289,20 +4318,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -4316,20 +4345,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -4343,20 +4372,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -4370,20 +4399,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -4397,20 +4426,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -4424,20 +4453,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -4451,20 +4480,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -4478,20 +4507,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -4505,20 +4534,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -4532,20 +4561,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -4559,20 +4588,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -4586,20 +4615,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -4613,20 +4642,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -4640,20 +4669,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -4667,20 +4696,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -4694,20 +4723,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -4721,20 +4750,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -4748,20 +4777,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -4775,20 +4804,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -4802,20 +4831,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -4829,20 +4858,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -4856,20 +4885,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -4883,20 +4912,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -4910,20 +4939,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -4937,20 +4966,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -4964,20 +4993,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -4991,20 +5020,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -5018,20 +5047,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -5045,20 +5074,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -5072,20 +5101,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -5099,20 +5128,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -5126,20 +5155,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -5153,20 +5182,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -5180,20 +5209,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -5207,20 +5236,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -5234,20 +5263,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -5261,20 +5290,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -5288,20 +5317,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -5315,20 +5344,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -5342,20 +5371,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -5369,20 +5398,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -5396,20 +5425,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -5423,20 +5452,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -5450,20 +5479,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -5477,20 +5506,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -5504,20 +5533,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -5531,20 +5560,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -5558,20 +5587,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -5585,20 +5614,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -5612,20 +5641,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -5639,20 +5668,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -5666,20 +5695,47 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + + + if (System.getProperty("apipath") != null) { + if (a.apiId == null) { + a.apiId = Platform.uuid + } + + def tracker = new ApiPathTracker(a.apiId) + def out = errorOut(a.call()) + def path = tracker.getApiPath() + if (!path.isEmpty()) { + Test.apiPaths[a.class.name] = path.join(" --->\n") + } + + return out + } else { + return errorOut(a.call()) + } + } + + + def changeHaNetworkGroupState(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.ChangeHaNetworkGroupStateAction.class) Closure c) { + def a = new org.zstack.sdk.ChangeHaNetworkGroupStateAction() + a.sessionId = Test.currentEnvSpec?.session?.uuid + c.resolveStrategy = Closure.OWNER_FIRST + c.delegate = a + c() + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -5693,20 +5749,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -5720,20 +5776,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -5747,20 +5803,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -5774,20 +5830,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -5801,20 +5857,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -5828,20 +5884,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -5855,20 +5911,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -5882,20 +5938,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -5909,20 +5965,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -5936,20 +5992,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -5963,20 +6019,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -5990,20 +6046,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -6017,20 +6073,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -6044,20 +6100,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -6071,20 +6127,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -6098,20 +6154,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -6125,20 +6181,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -6152,20 +6208,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -6179,20 +6235,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -6206,20 +6262,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -6233,20 +6289,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -6260,20 +6316,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -6287,20 +6343,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -6314,20 +6370,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -6341,20 +6397,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -6368,20 +6424,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -6395,20 +6451,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -6422,20 +6478,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -6449,20 +6505,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -6476,20 +6532,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -6503,20 +6559,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -6530,20 +6586,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -6557,20 +6613,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -6584,20 +6640,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -6611,20 +6667,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -6638,20 +6694,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -6665,20 +6721,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -6692,20 +6748,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -6719,20 +6775,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -6746,20 +6802,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -6773,20 +6829,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -6800,20 +6856,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -6827,20 +6883,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -6854,20 +6910,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -6881,20 +6937,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -6908,20 +6964,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -6935,20 +6991,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -6962,20 +7018,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -6989,20 +7045,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -7016,20 +7072,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -7043,20 +7099,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -7070,20 +7126,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -7097,20 +7153,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -7124,20 +7180,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -7151,20 +7207,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -7178,20 +7234,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -7205,20 +7261,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -7232,20 +7288,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -7259,20 +7315,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -7286,20 +7342,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -7313,20 +7369,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -7340,20 +7396,47 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + + + if (System.getProperty("apipath") != null) { + if (a.apiId == null) { + a.apiId = Platform.uuid + } + + def tracker = new ApiPathTracker(a.apiId) + def out = errorOut(a.call()) + def path = tracker.getApiPath() + if (!path.isEmpty()) { + Test.apiPaths[a.class.name] = path.join(" --->\n") + } + + return out + } else { + return errorOut(a.call()) + } + } + + + def cleanAiHostModelCache(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.CleanAiHostModelCacheAction.class) Closure c) { + def a = new org.zstack.sdk.CleanAiHostModelCacheAction() + a.sessionId = Test.currentEnvSpec?.session?.uuid + c.resolveStrategy = Closure.OWNER_FIRST + c.delegate = a + c() + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -7367,20 +7450,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -7394,20 +7477,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -7421,20 +7504,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -7448,20 +7531,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -7475,20 +7558,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -7502,20 +7585,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -7529,20 +7612,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -7556,20 +7639,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -7583,20 +7666,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -7610,20 +7693,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -7637,20 +7720,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -7664,20 +7747,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -7691,20 +7774,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -7718,20 +7801,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -7745,20 +7828,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -7772,20 +7855,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -7799,20 +7882,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -7826,20 +7909,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -7853,20 +7936,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -7880,20 +7963,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -7907,20 +7990,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -7934,20 +8017,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -7961,20 +8044,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -7988,20 +8071,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -8015,20 +8098,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -8042,20 +8125,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -8069,20 +8152,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -8096,20 +8179,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -8123,20 +8206,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -8150,20 +8233,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -8177,20 +8260,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -8204,20 +8287,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -8231,20 +8314,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -8258,20 +8341,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -8285,20 +8368,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -8312,20 +8395,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -8339,20 +8422,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -8366,20 +8449,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -8393,20 +8476,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -8416,24 +8499,24 @@ abstract class ApiHelper { def createBareMetal2IpmiChassisHardwareInfo(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.CreateBareMetal2IpmiChassisHardwareInfoAction.class) Closure c) { def a = new org.zstack.sdk.CreateBareMetal2IpmiChassisHardwareInfoAction() - + c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -8447,20 +8530,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -8474,20 +8557,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -8501,20 +8584,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -8528,20 +8611,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -8555,20 +8638,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -8582,20 +8665,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -8609,20 +8692,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -8636,20 +8719,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -8663,20 +8746,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -8690,20 +8773,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -8717,20 +8800,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -8744,20 +8827,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -8771,20 +8854,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -8798,20 +8881,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -8825,20 +8908,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -8852,20 +8935,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -8879,20 +8962,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -8906,20 +8989,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -8933,20 +9016,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -8960,20 +9043,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -8987,20 +9070,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -9014,20 +9097,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -9041,20 +9124,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -9068,20 +9151,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -9095,20 +9178,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -9122,20 +9205,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -9149,20 +9232,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -9176,20 +9259,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -9203,20 +9286,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -9230,20 +9313,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -9257,20 +9340,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -9284,20 +9367,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -9311,20 +9394,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -9338,20 +9421,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -9365,20 +9448,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -9392,20 +9475,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -9419,20 +9502,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -9446,20 +9529,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -9473,20 +9556,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -9500,20 +9583,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -9527,20 +9610,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -9554,20 +9637,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -9581,20 +9664,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -9608,20 +9691,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -9635,20 +9718,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -9662,20 +9745,47 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + + + if (System.getProperty("apipath") != null) { + if (a.apiId == null) { + a.apiId = Platform.uuid + } + + def tracker = new ApiPathTracker(a.apiId) + def out = errorOut(a.call()) + def path = tracker.getApiPath() + if (!path.isEmpty()) { + Test.apiPaths[a.class.name] = path.join(" --->\n") + } + + return out + } else { + return errorOut(a.call()) + } + } + + + def createHaNetworkGroup(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.CreateHaNetworkGroupAction.class) Closure c) { + def a = new org.zstack.sdk.CreateHaNetworkGroupAction() + a.sessionId = Test.currentEnvSpec?.session?.uuid + c.resolveStrategy = Closure.OWNER_FIRST + c.delegate = a + c() + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -9689,20 +9799,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -9716,20 +9826,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -9743,20 +9853,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -9770,20 +9880,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -9797,20 +9907,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -9824,20 +9934,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -9851,20 +9961,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -9878,20 +9988,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -9905,20 +10015,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -9932,20 +10042,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -9959,20 +10069,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -9986,20 +10096,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -10013,20 +10123,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -10040,20 +10150,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -10067,20 +10177,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -10094,20 +10204,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -10121,20 +10231,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -10148,20 +10258,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -10175,20 +10285,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -10202,20 +10312,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -10229,20 +10339,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -10256,20 +10366,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -10283,20 +10393,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -10310,20 +10420,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -10337,20 +10447,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -10364,20 +10474,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -10391,20 +10501,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -10418,20 +10528,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -10445,20 +10555,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -10472,20 +10582,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -10499,20 +10609,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -10526,20 +10636,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -10553,20 +10663,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -10580,20 +10690,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -10607,20 +10717,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -10634,20 +10744,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -10661,20 +10771,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -10688,20 +10798,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -10715,20 +10825,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -10742,20 +10852,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -10769,20 +10879,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -10796,20 +10906,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -10823,20 +10933,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -10850,20 +10960,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -10877,20 +10987,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -10904,20 +11014,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -10931,20 +11041,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -10958,20 +11068,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -10985,20 +11095,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -11012,20 +11122,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -11039,20 +11149,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -11066,20 +11176,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -11093,20 +11203,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -11120,20 +11230,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -11147,20 +11257,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -11174,20 +11284,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -11201,20 +11311,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -11228,20 +11338,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -11255,20 +11365,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -11282,20 +11392,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -11309,20 +11419,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -11336,20 +11446,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -11363,20 +11473,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -11390,20 +11500,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -11417,20 +11527,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -11444,20 +11554,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -11471,20 +11581,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -11498,20 +11608,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -11525,20 +11635,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -11552,20 +11662,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -11579,20 +11689,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -11606,20 +11716,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -11633,20 +11743,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -11660,20 +11770,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -11687,20 +11797,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -11714,20 +11824,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -11741,20 +11851,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -11768,20 +11878,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -11795,20 +11905,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -11822,20 +11932,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -11849,20 +11959,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -11876,20 +11986,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -11903,20 +12013,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -11930,20 +12040,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -11957,20 +12067,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -11984,20 +12094,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -12011,20 +12121,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -12038,20 +12148,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -12065,20 +12175,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -12092,20 +12202,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -12119,20 +12229,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -12146,20 +12256,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -12173,20 +12283,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -12200,20 +12310,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -12227,20 +12337,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -12254,20 +12364,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -12281,20 +12391,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -12308,20 +12418,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -12335,20 +12445,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -12362,20 +12472,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -12389,20 +12499,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -12416,20 +12526,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -12443,20 +12553,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -12470,20 +12580,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -12497,20 +12607,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -12524,20 +12634,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -12551,20 +12661,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -12578,20 +12688,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -12605,20 +12715,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -12632,20 +12742,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -12659,20 +12769,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -12686,20 +12796,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -12713,20 +12823,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -12740,20 +12850,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -12767,20 +12877,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -12794,20 +12904,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -12821,20 +12931,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -12848,20 +12958,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -12875,20 +12985,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -12902,20 +13012,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -12929,20 +13039,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -12956,20 +13066,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -12983,20 +13093,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -13010,20 +13120,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -13037,20 +13147,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -13064,20 +13174,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -13091,20 +13201,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -13118,20 +13228,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -13145,20 +13255,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -13172,20 +13282,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -13199,20 +13309,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -13226,20 +13336,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -13253,20 +13363,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -13280,20 +13390,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -13307,20 +13417,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -13334,20 +13444,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -13361,20 +13471,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -13388,20 +13498,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -13415,20 +13525,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -13442,20 +13552,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -13469,20 +13579,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -13496,20 +13606,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -13523,20 +13633,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -13550,20 +13660,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -13577,20 +13687,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -13604,20 +13714,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -13631,20 +13741,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -13658,20 +13768,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -13685,20 +13795,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -13712,20 +13822,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -13739,20 +13849,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -13766,20 +13876,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -13793,20 +13903,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -13820,20 +13930,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -13847,20 +13957,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -13874,20 +13984,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -13901,20 +14011,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -13928,20 +14038,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -13955,20 +14065,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -13982,20 +14092,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -14009,20 +14119,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -14036,20 +14146,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -14063,20 +14173,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -14090,20 +14200,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -14117,20 +14227,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -14144,20 +14254,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -14171,20 +14281,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -14198,20 +14308,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -14225,20 +14335,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -14252,20 +14362,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -14279,20 +14389,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -14306,20 +14416,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -14333,20 +14443,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -14360,20 +14470,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -14387,20 +14497,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -14414,20 +14524,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -14441,20 +14551,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -14468,20 +14578,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -14495,20 +14605,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -14522,20 +14632,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -14549,20 +14659,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -14576,20 +14686,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -14603,20 +14713,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -14630,20 +14740,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -14657,20 +14767,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -14684,20 +14794,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -14711,20 +14821,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -14738,20 +14848,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -14765,20 +14875,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -14792,20 +14902,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -14819,20 +14929,47 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + + + if (System.getProperty("apipath") != null) { + if (a.apiId == null) { + a.apiId = Platform.uuid + } + + def tracker = new ApiPathTracker(a.apiId) + def out = errorOut(a.call()) + def path = tracker.getApiPath() + if (!path.isEmpty()) { + Test.apiPaths[a.class.name] = path.join(" --->\n") + } + + return out + } else { + return errorOut(a.call()) + } + } + + + def deleteHaNetworkGroup(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.DeleteHaNetworkGroupAction.class) Closure c) { + def a = new org.zstack.sdk.DeleteHaNetworkGroupAction() + a.sessionId = Test.currentEnvSpec?.session?.uuid + c.resolveStrategy = Closure.OWNER_FIRST + c.delegate = a + c() + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -14846,20 +14983,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -14873,20 +15010,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -14900,20 +15037,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -14927,20 +15064,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -14954,20 +15091,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -14981,20 +15118,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -15008,20 +15145,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -15035,20 +15172,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -15062,20 +15199,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -15089,20 +15226,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -15116,20 +15253,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -15143,20 +15280,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -15170,20 +15307,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -15197,20 +15334,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -15224,20 +15361,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -15251,20 +15388,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -15278,20 +15415,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -15305,20 +15442,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -15332,20 +15469,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -15359,20 +15496,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -15386,20 +15523,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -15413,20 +15550,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -15440,20 +15577,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -15467,20 +15604,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -15494,20 +15631,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -15521,20 +15658,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -15548,20 +15685,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -15575,20 +15712,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -15602,20 +15739,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -15629,20 +15766,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -15656,20 +15793,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -15683,20 +15820,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -15710,20 +15847,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -15737,20 +15874,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -15764,20 +15901,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -15791,20 +15928,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -15818,20 +15955,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -15845,20 +15982,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -15872,20 +16009,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -15899,20 +16036,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -15926,20 +16063,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -15953,20 +16090,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -15980,20 +16117,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -16007,20 +16144,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -16034,20 +16171,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -16061,20 +16198,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -16088,20 +16225,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -16115,20 +16252,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -16142,20 +16279,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -16169,20 +16306,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -16196,20 +16333,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -16223,20 +16360,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -16250,20 +16387,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -16277,20 +16414,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -16304,20 +16441,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -16331,20 +16468,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -16358,20 +16495,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -16385,20 +16522,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -16412,20 +16549,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -16439,20 +16576,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -16466,20 +16603,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -16493,20 +16630,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -16520,20 +16657,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -16547,20 +16684,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -16574,20 +16711,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -16601,20 +16738,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -16628,20 +16765,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -16655,20 +16792,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -16682,20 +16819,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -16709,20 +16846,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -16736,20 +16873,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -16763,20 +16900,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -16790,20 +16927,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -16817,20 +16954,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -16844,20 +16981,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -16871,20 +17008,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -16898,20 +17035,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -16925,20 +17062,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -16952,20 +17089,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -16979,20 +17116,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -17006,20 +17143,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -17033,20 +17170,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -17060,20 +17197,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -17087,20 +17224,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -17114,20 +17251,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -17141,20 +17278,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -17168,20 +17305,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -17195,20 +17332,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -17222,20 +17359,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -17249,20 +17386,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -17276,20 +17413,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -17303,20 +17440,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -17330,20 +17467,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -17357,20 +17494,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -17384,20 +17521,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -17411,20 +17548,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -17438,20 +17575,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -17465,20 +17602,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -17492,20 +17629,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -17519,20 +17656,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -17546,20 +17683,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -17573,20 +17710,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -17600,20 +17737,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -17627,20 +17764,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -17654,20 +17791,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -17681,20 +17818,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -17708,20 +17845,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -17735,20 +17872,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -17762,20 +17899,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -17789,20 +17926,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -17816,20 +17953,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -17843,20 +17980,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -17870,20 +18007,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -17897,20 +18034,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -17924,20 +18061,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -17951,20 +18088,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -17978,20 +18115,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -18005,20 +18142,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -18032,20 +18169,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -18059,20 +18196,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -18086,20 +18223,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -18113,20 +18250,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -18140,20 +18277,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -18167,20 +18304,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -18194,20 +18331,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -18221,20 +18358,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -18248,20 +18385,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -18275,20 +18412,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -18302,20 +18439,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -18329,20 +18466,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -18356,20 +18493,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -18383,20 +18520,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -18410,20 +18547,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -18437,20 +18574,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -18464,20 +18601,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -18491,20 +18628,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -18518,20 +18655,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -18545,20 +18682,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -18572,20 +18709,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -18599,20 +18736,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -18626,20 +18763,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -18653,20 +18790,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -18680,20 +18817,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -18707,20 +18844,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -18734,20 +18871,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -18761,20 +18898,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -18788,20 +18925,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -18815,20 +18952,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -18842,20 +18979,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -18869,20 +19006,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -18896,20 +19033,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -18923,20 +19060,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -18950,20 +19087,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -18977,20 +19114,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -19004,20 +19141,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -19031,20 +19168,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -19058,20 +19195,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -19085,20 +19222,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -19112,20 +19249,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -19139,20 +19276,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -19166,20 +19303,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -19193,20 +19330,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -19220,20 +19357,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -19247,20 +19384,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -19274,20 +19411,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -19301,20 +19438,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -19328,20 +19465,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -19355,20 +19492,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -19382,20 +19519,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -19409,20 +19546,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -19436,20 +19573,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -19463,20 +19600,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -19490,20 +19627,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -19517,20 +19654,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -19544,20 +19681,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -19571,20 +19708,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -19598,20 +19735,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -19625,20 +19762,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -19652,20 +19789,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -19679,20 +19816,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -19706,20 +19843,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -19733,20 +19870,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -19760,20 +19897,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -19787,20 +19924,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -19814,20 +19951,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -19841,20 +19978,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -19868,20 +20005,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -19895,20 +20032,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -19922,20 +20059,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -19949,20 +20086,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -19976,20 +20113,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -20003,20 +20140,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -20030,20 +20167,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -20057,20 +20194,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -20084,20 +20221,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -20111,20 +20248,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -20138,20 +20275,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -20165,20 +20302,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -20192,20 +20329,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -20219,20 +20356,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -20246,20 +20383,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -20273,20 +20410,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -20300,20 +20437,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -20327,20 +20464,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -20354,20 +20491,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -20381,20 +20518,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -20408,20 +20545,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -20435,20 +20572,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -20462,20 +20599,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -20489,20 +20626,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -20516,20 +20653,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -20543,20 +20680,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -20570,20 +20707,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -20597,20 +20734,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -20624,20 +20761,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -20651,20 +20788,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -20678,20 +20815,47 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + + + if (System.getProperty("apipath") != null) { + if (a.apiId == null) { + a.apiId = Platform.uuid + } + + def tracker = new ApiPathTracker(a.apiId) + def out = errorOut(a.call()) + def path = tracker.getApiPath() + if (!path.isEmpty()) { + Test.apiPaths[a.class.name] = path.join(" --->\n") + } + + return out + } else { + return errorOut(a.call()) + } + } + + + def getAiHostModelCacheCapacity(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.GetAiHostModelCacheCapacityAction.class) Closure c) { + def a = new org.zstack.sdk.GetAiHostModelCacheCapacityAction() + a.sessionId = Test.currentEnvSpec?.session?.uuid + c.resolveStrategy = Closure.OWNER_FIRST + c.delegate = a + c() + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -20705,20 +20869,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -20732,20 +20896,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -20759,20 +20923,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -20786,20 +20950,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -20813,20 +20977,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -20840,20 +21004,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -20867,20 +21031,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -20894,20 +21058,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -20921,20 +21085,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -20948,20 +21112,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -20975,20 +21139,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -21002,20 +21166,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -21029,20 +21193,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -21056,20 +21220,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -21083,20 +21247,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -21110,20 +21274,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -21137,20 +21301,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -21164,20 +21328,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -21191,20 +21355,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -21218,20 +21382,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -21245,20 +21409,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -21272,20 +21436,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -21299,20 +21463,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -21326,20 +21490,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -21353,20 +21517,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -21380,20 +21544,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -21407,20 +21571,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -21434,20 +21598,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -21461,20 +21625,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -21488,20 +21652,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -21515,20 +21679,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -21542,20 +21706,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -21569,20 +21733,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -21596,20 +21760,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -21623,20 +21787,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -21650,20 +21814,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -21677,20 +21841,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -21704,20 +21868,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -21731,20 +21895,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -21758,20 +21922,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -21785,20 +21949,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -21812,20 +21976,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -21839,20 +22003,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -21866,20 +22030,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -21893,20 +22057,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -21920,20 +22084,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -21947,20 +22111,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -21974,20 +22138,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -22001,20 +22165,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -22028,20 +22192,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -22055,20 +22219,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -22082,20 +22246,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -22105,24 +22269,24 @@ abstract class ApiHelper { def getCurrentTime(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.GetCurrentTimeAction.class) Closure c) { def a = new org.zstack.sdk.GetCurrentTimeAction() - + c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -22136,20 +22300,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -22163,20 +22327,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -22190,20 +22354,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -22217,20 +22381,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -22244,20 +22408,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -22271,20 +22435,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -22298,20 +22462,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -22325,20 +22489,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -22352,20 +22516,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -22379,20 +22543,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -22406,20 +22570,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -22433,20 +22597,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -22460,20 +22624,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -22487,20 +22651,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -22514,20 +22678,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -22541,20 +22705,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -22568,20 +22732,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -22595,20 +22759,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -22622,20 +22786,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -22649,20 +22813,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -22676,20 +22840,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -22703,20 +22867,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -22730,20 +22894,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -22757,20 +22921,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -22784,20 +22948,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -22811,20 +22975,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -22838,20 +23002,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -22865,20 +23029,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -22892,20 +23056,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -22919,20 +23083,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -22946,20 +23110,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -22973,20 +23137,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -23000,20 +23164,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -23027,20 +23191,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -23054,20 +23218,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -23081,20 +23245,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -23108,20 +23272,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -23135,20 +23299,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -23162,20 +23326,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -23189,20 +23353,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -23216,20 +23380,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -23243,20 +23407,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -23270,20 +23434,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -23297,20 +23461,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -23324,20 +23488,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -23351,20 +23515,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -23378,20 +23542,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -23405,20 +23569,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -23432,20 +23596,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -23459,20 +23623,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -23486,20 +23650,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -23513,20 +23677,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -23540,20 +23704,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -23563,24 +23727,24 @@ abstract class ApiHelper { def getLicenseAddOns(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.GetLicenseAddOnsAction.class) Closure c) { def a = new org.zstack.sdk.GetLicenseAddOnsAction() - + c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -23594,20 +23758,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -23617,24 +23781,24 @@ abstract class ApiHelper { def getLicenseInfo(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.GetLicenseInfoAction.class) Closure c) { def a = new org.zstack.sdk.GetLicenseInfoAction() - + c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -23644,24 +23808,24 @@ abstract class ApiHelper { def getLicenseRecords(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.GetLicenseRecordsAction.class) Closure c) { def a = new org.zstack.sdk.GetLicenseRecordsAction() - + c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -23675,20 +23839,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -23702,20 +23866,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -23729,20 +23893,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -23756,20 +23920,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -23783,20 +23947,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -23810,20 +23974,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -23833,24 +23997,24 @@ abstract class ApiHelper { def getLoginCaptcha(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.GetLoginCaptchaAction.class) Closure c) { def a = new org.zstack.sdk.GetLoginCaptchaAction() - + c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -23860,24 +24024,24 @@ abstract class ApiHelper { def getLoginProcedures(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.GetLoginProceduresAction.class) Closure c) { def a = new org.zstack.sdk.GetLoginProceduresAction() - + c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -23891,20 +24055,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -23914,24 +24078,24 @@ abstract class ApiHelper { def getManagementNodeArch(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.GetManagementNodeArchAction.class) Closure c) { def a = new org.zstack.sdk.GetManagementNodeArchAction() - + c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -23941,24 +24105,24 @@ abstract class ApiHelper { def getManagementNodeOS(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.GetManagementNodeOSAction.class) Closure c) { def a = new org.zstack.sdk.GetManagementNodeOSAction() - + c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -23972,20 +24136,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -23999,20 +24163,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -24026,20 +24190,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -24053,20 +24217,47 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + + + if (System.getProperty("apipath") != null) { + if (a.apiId == null) { + a.apiId = Platform.uuid + } + + def tracker = new ApiPathTracker(a.apiId) + def out = errorOut(a.call()) + def path = tracker.getApiPath() + if (!path.isEmpty()) { + Test.apiPaths[a.class.name] = path.join(" --->\n") + } + + return out + } else { + return errorOut(a.call()) + } + } + + + def getModelServiceLaunchCommands(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.GetModelServiceLaunchCommandsAction.class) Closure c) { + def a = new org.zstack.sdk.GetModelServiceLaunchCommandsAction() + a.sessionId = Test.currentEnvSpec?.session?.uuid + c.resolveStrategy = Closure.OWNER_FIRST + c.delegate = a + c() + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -24080,20 +24271,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -24107,20 +24298,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -24134,20 +24325,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -24161,20 +24352,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -24188,20 +24379,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -24215,20 +24406,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -24242,20 +24433,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -24269,20 +24460,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -24296,20 +24487,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -24323,20 +24514,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -24350,20 +24541,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -24377,20 +24568,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -24404,20 +24595,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -24431,20 +24622,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -24458,20 +24649,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -24485,20 +24676,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -24512,20 +24703,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -24539,20 +24730,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -24566,20 +24757,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -24593,20 +24784,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -24620,20 +24811,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -24647,20 +24838,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -24674,20 +24865,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -24701,20 +24892,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -24728,20 +24919,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -24755,20 +24946,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -24782,20 +24973,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -24809,20 +25000,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -24836,20 +25027,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -24863,20 +25054,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -24890,20 +25081,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -24917,20 +25108,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -24940,24 +25131,24 @@ abstract class ApiHelper { def getSSOClient(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.GetSSOClientAction.class) Closure c) { def a = new org.zstack.sdk.GetSSOClientAction() - + c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -24971,20 +25162,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -24998,20 +25189,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -25025,20 +25216,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -25048,24 +25239,24 @@ abstract class ApiHelper { def getSignatureServerEncryptPublicKey(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.GetSignatureServerEncryptPublicKeyAction.class) Closure c) { def a = new org.zstack.sdk.GetSignatureServerEncryptPublicKeyAction() - + c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -25079,20 +25270,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -25102,24 +25293,24 @@ abstract class ApiHelper { def getSupportAPIs(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.GetSupportAPIsAction.class) Closure c) { def a = new org.zstack.sdk.GetSupportAPIsAction() - + c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -25133,20 +25324,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -25156,24 +25347,24 @@ abstract class ApiHelper { def getSupportedIdentityModels(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.GetSupportedIdentityModelsAction.class) Closure c) { def a = new org.zstack.sdk.GetSupportedIdentityModelsAction() - + c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -25187,20 +25378,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -25214,20 +25405,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -25241,20 +25432,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -25264,24 +25455,24 @@ abstract class ApiHelper { def getTwoFactorAuthenticationSecret(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.GetTwoFactorAuthenticationSecretAction.class) Closure c) { def a = new org.zstack.sdk.GetTwoFactorAuthenticationSecretAction() - + c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -25291,24 +25482,24 @@ abstract class ApiHelper { def getTwoFactorAuthenticationState(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.GetTwoFactorAuthenticationStateAction.class) Closure c) { def a = new org.zstack.sdk.GetTwoFactorAuthenticationStateAction() - + c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -25322,20 +25513,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -25349,20 +25540,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -25376,20 +25567,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -25403,20 +25594,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -25430,20 +25621,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -25457,20 +25648,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -25484,20 +25675,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -25507,24 +25698,24 @@ abstract class ApiHelper { def getVersion(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.GetVersionAction.class) Closure c) { def a = new org.zstack.sdk.GetVersionAction() - + c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -25538,20 +25729,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -25565,20 +25756,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -25592,20 +25783,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -25619,20 +25810,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -25646,20 +25837,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -25673,20 +25864,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -25700,20 +25891,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -25727,20 +25918,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -25754,20 +25945,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -25781,20 +25972,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -25808,20 +25999,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -25835,20 +26026,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -25862,20 +26053,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -25889,20 +26080,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -25916,20 +26107,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -25943,20 +26134,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -25970,20 +26161,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -25997,20 +26188,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -26024,20 +26215,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -26051,20 +26242,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -26078,20 +26269,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -26105,20 +26296,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -26132,20 +26323,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -26159,20 +26350,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -26186,20 +26377,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -26213,20 +26404,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -26240,20 +26431,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -26267,20 +26458,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -26294,20 +26485,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -26321,20 +26512,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -26348,20 +26539,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -26375,20 +26566,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -26402,20 +26593,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -26429,20 +26620,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -26456,20 +26647,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -26483,20 +26674,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -26510,20 +26701,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -26537,20 +26728,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -26564,20 +26755,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -26591,20 +26782,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -26618,20 +26809,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -26645,20 +26836,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -26672,20 +26863,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -26699,20 +26890,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -26726,20 +26917,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -26753,20 +26944,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -26780,20 +26971,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -26807,20 +26998,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -26834,20 +27025,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -26861,20 +27052,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -26888,20 +27079,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -26915,20 +27106,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -26942,20 +27133,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -26969,20 +27160,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -26996,20 +27187,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -27023,20 +27214,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -27050,20 +27241,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -27077,20 +27268,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -27104,20 +27295,101 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + + + if (System.getProperty("apipath") != null) { + if (a.apiId == null) { + a.apiId = Platform.uuid + } + + def tracker = new ApiPathTracker(a.apiId) + def out = errorOut(a.call()) + def path = tracker.getApiPath() + if (!path.isEmpty()) { + Test.apiPaths[a.class.name] = path.join(" --->\n") + } + + return out + } else { + return errorOut(a.call()) + } + } + + + def importModelServiceTemplateFromCdn(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.ImportModelServiceTemplateFromCdnAction.class) Closure c) { + def a = new org.zstack.sdk.ImportModelServiceTemplateFromCdnAction() + a.sessionId = Test.currentEnvSpec?.session?.uuid + c.resolveStrategy = Closure.OWNER_FIRST + c.delegate = a + c() + + + if (System.getProperty("apipath") != null) { + if (a.apiId == null) { + a.apiId = Platform.uuid + } + + def tracker = new ApiPathTracker(a.apiId) + def out = errorOut(a.call()) + def path = tracker.getApiPath() + if (!path.isEmpty()) { + Test.apiPaths[a.class.name] = path.join(" --->\n") + } + + return out + } else { + return errorOut(a.call()) + } + } + + + def importModelServiceTemplateFromUpload(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.ImportModelServiceTemplateFromUploadAction.class) Closure c) { + def a = new org.zstack.sdk.ImportModelServiceTemplateFromUploadAction() + a.sessionId = Test.currentEnvSpec?.session?.uuid + c.resolveStrategy = Closure.OWNER_FIRST + c.delegate = a + c() + + + if (System.getProperty("apipath") != null) { + if (a.apiId == null) { + a.apiId = Platform.uuid + } + + def tracker = new ApiPathTracker(a.apiId) + def out = errorOut(a.call()) + def path = tracker.getApiPath() + if (!path.isEmpty()) { + Test.apiPaths[a.class.name] = path.join(" --->\n") + } + + return out + } else { + return errorOut(a.call()) + } + } + + + def importModelServiceTemplateFromUrl(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.ImportModelServiceTemplateFromUrlAction.class) Closure c) { + def a = new org.zstack.sdk.ImportModelServiceTemplateFromUrlAction() + a.sessionId = Test.currentEnvSpec?.session?.uuid + c.resolveStrategy = Closure.OWNER_FIRST + c.delegate = a + c() + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -27131,20 +27403,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -27158,20 +27430,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -27185,20 +27457,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -27208,24 +27480,24 @@ abstract class ApiHelper { def isOpensourceVersion(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.IsOpensourceVersionAction.class) Closure c) { def a = new org.zstack.sdk.IsOpensourceVersionAction() - + c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -27235,24 +27507,24 @@ abstract class ApiHelper { def isReadyToGo(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.IsReadyToGoAction.class) Closure c) { def a = new org.zstack.sdk.IsReadyToGoAction() - + c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -27266,20 +27538,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -27293,20 +27565,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -27320,20 +27592,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -27347,20 +27619,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -27374,20 +27646,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -27401,20 +27673,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -27428,20 +27700,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -27455,20 +27727,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -27482,20 +27754,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -27505,24 +27777,24 @@ abstract class ApiHelper { def logIn(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.LogInAction.class) Closure c) { def a = new org.zstack.sdk.LogInAction() - + c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -27532,24 +27804,24 @@ abstract class ApiHelper { def logInByAccount(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.LogInByAccountAction.class) Closure c) { def a = new org.zstack.sdk.LogInByAccountAction() - + c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -27559,24 +27831,24 @@ abstract class ApiHelper { def logInByLdap(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.LogInByLdapAction.class) Closure c) { def a = new org.zstack.sdk.LogInByLdapAction() - + c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -27586,24 +27858,24 @@ abstract class ApiHelper { def logInByUser(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.LogInByUserAction.class) Closure c) { def a = new org.zstack.sdk.LogInByUserAction() - + c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -27613,24 +27885,24 @@ abstract class ApiHelper { def logOut(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.LogOutAction.class) Closure c) { def a = new org.zstack.sdk.LogOutAction() - + c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -27640,24 +27912,24 @@ abstract class ApiHelper { def loginByCas(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.LoginByCasAction.class) Closure c) { def a = new org.zstack.sdk.LoginByCasAction() - + c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -27667,24 +27939,24 @@ abstract class ApiHelper { def loginIAM2VirtualIDWithLdap(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.LoginIAM2VirtualIDWithLdapAction.class) Closure c) { def a = new org.zstack.sdk.LoginIAM2VirtualIDWithLdapAction() - + c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -27698,20 +27970,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -27725,20 +27997,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -27752,20 +28024,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -27779,20 +28051,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -27806,20 +28078,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -27833,20 +28105,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -27860,20 +28132,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -27887,20 +28159,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -27914,20 +28186,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -27941,20 +28213,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -27968,20 +28240,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -27995,20 +28267,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -28022,20 +28294,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -28049,20 +28321,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -28076,20 +28348,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -28103,20 +28375,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -28130,20 +28402,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -28157,20 +28429,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -28184,20 +28456,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -28211,20 +28483,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -28238,20 +28510,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -28265,20 +28537,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -28292,20 +28564,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -28319,20 +28591,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -28346,20 +28618,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -28373,20 +28645,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -28400,20 +28672,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -28427,20 +28699,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -28454,20 +28726,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -28481,20 +28753,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -28508,20 +28780,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -28535,20 +28807,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -28562,20 +28834,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -28589,20 +28861,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -28616,22 +28888,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -28645,22 +28919,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -28674,22 +28950,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -28703,22 +28981,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -28732,22 +29012,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -28761,22 +29043,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -28790,22 +29074,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -28819,22 +29105,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -28848,22 +29136,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -28877,22 +29167,55 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } + + + if (System.getProperty("apipath") != null) { + if (a.apiId == null) { + a.apiId = Platform.uuid + } + + def tracker = new ApiPathTracker(a.apiId) + def out = errorOut(a.call()) + def path = tracker.getApiPath() + if (!path.isEmpty()) { + Test.apiPaths[a.class.name] = path.join(" --->\n") + } + + return out + } else { + return errorOut(a.call()) + } + } + + + def queryAiHostModelCache(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.QueryAiHostModelCacheAction.class) Closure c) { + def a = new org.zstack.sdk.QueryAiHostModelCacheAction() + a.sessionId = Test.currentEnvSpec?.session?.uuid + c.resolveStrategy = Closure.OWNER_FIRST + c.delegate = a + c() + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -28906,22 +29229,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -28935,22 +29260,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -28964,22 +29291,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -28993,22 +29322,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -29022,22 +29353,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -29051,22 +29384,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -29080,22 +29415,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -29109,22 +29446,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -29138,22 +29477,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -29167,22 +29508,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -29196,22 +29539,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -29225,22 +29570,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -29254,22 +29601,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -29283,22 +29632,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -29312,22 +29663,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -29341,22 +29694,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -29370,22 +29725,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -29399,22 +29756,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -29428,22 +29787,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -29457,22 +29818,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -29486,22 +29849,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -29515,22 +29880,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -29544,22 +29911,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -29573,22 +29942,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -29602,22 +29973,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -29631,22 +30004,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -29660,22 +30035,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -29689,22 +30066,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -29718,22 +30097,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -29747,22 +30128,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -29776,22 +30159,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -29805,22 +30190,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -29834,22 +30221,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -29863,22 +30252,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -29892,22 +30283,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -29921,22 +30314,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -29950,22 +30345,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -29979,22 +30376,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -30008,22 +30407,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -30037,22 +30438,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -30066,22 +30469,55 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } + + + if (System.getProperty("apipath") != null) { + if (a.apiId == null) { + a.apiId = Platform.uuid + } + + def tracker = new ApiPathTracker(a.apiId) + def out = errorOut(a.call()) + def path = tracker.getApiPath() + if (!path.isEmpty()) { + Test.apiPaths[a.class.name] = path.join(" --->\n") + } + + return out + } else { + return errorOut(a.call()) + } + } + + + def queryCdnModelServiceTemplateList(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.QueryCdnModelServiceTemplateListAction.class) Closure c) { + def a = new org.zstack.sdk.QueryCdnModelServiceTemplateListAction() + a.sessionId = Test.currentEnvSpec?.session?.uuid + c.resolveStrategy = Closure.OWNER_FIRST + c.delegate = a + c() + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -30095,22 +30531,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -30124,22 +30562,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -30153,22 +30593,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -30182,22 +30624,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -30211,22 +30655,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -30240,22 +30686,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -30269,22 +30717,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -30298,22 +30748,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -30327,22 +30779,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -30356,22 +30810,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -30385,22 +30841,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -30414,22 +30872,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -30443,22 +30903,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -30472,22 +30934,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -30501,22 +30965,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -30530,22 +30996,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -30559,22 +31027,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -30588,22 +31058,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -30617,22 +31089,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -30646,22 +31120,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -30675,22 +31151,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -30704,22 +31182,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -30733,22 +31213,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -30762,22 +31244,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -30791,22 +31275,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -30820,22 +31306,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -30849,22 +31337,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -30878,22 +31368,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -30907,22 +31399,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -30936,22 +31430,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -30965,22 +31461,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -30994,22 +31492,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -31023,22 +31523,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -31052,22 +31554,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -31081,22 +31585,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -31110,22 +31616,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -31139,22 +31647,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -31168,22 +31678,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -31197,22 +31709,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -31226,22 +31740,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -31255,22 +31771,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -31284,22 +31802,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -31313,22 +31833,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -31342,22 +31864,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -31371,22 +31895,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -31400,22 +31926,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -31429,22 +31957,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -31458,22 +31988,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -31487,22 +32019,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -31516,22 +32050,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -31545,22 +32081,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -31574,22 +32112,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -31603,22 +32143,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -31632,22 +32174,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -31661,22 +32205,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -31690,22 +32236,55 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } + + + if (System.getProperty("apipath") != null) { + if (a.apiId == null) { + a.apiId = Platform.uuid + } + + def tracker = new ApiPathTracker(a.apiId) + def out = errorOut(a.call()) + def path = tracker.getApiPath() + if (!path.isEmpty()) { + Test.apiPaths[a.class.name] = path.join(" --->\n") + } + + return out + } else { + return errorOut(a.call()) + } + } + + + def queryHaNetworkGroup(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.QueryHaNetworkGroupAction.class) Closure c) { + def a = new org.zstack.sdk.QueryHaNetworkGroupAction() + a.sessionId = Test.currentEnvSpec?.session?.uuid + c.resolveStrategy = Closure.OWNER_FIRST + c.delegate = a + c() + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -31719,22 +32298,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -31748,22 +32329,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -31777,22 +32360,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -31806,22 +32391,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -31835,22 +32422,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -31864,22 +32453,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -31893,22 +32484,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -31922,22 +32515,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -31951,22 +32546,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -31980,22 +32577,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -32009,22 +32608,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -32038,22 +32639,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -32067,22 +32670,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -32096,22 +32701,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -32125,22 +32732,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -32154,22 +32763,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -32183,22 +32794,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -32212,22 +32825,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -32241,22 +32856,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -32270,22 +32887,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -32299,22 +32918,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -32328,22 +32949,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -32357,22 +32980,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -32386,22 +33011,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -32415,22 +33042,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -32444,22 +33073,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -32473,22 +33104,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -32502,22 +33135,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -32531,22 +33166,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -32560,22 +33197,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -32589,22 +33228,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -32618,22 +33259,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -32647,22 +33290,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -32676,22 +33321,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -32705,22 +33352,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -32734,22 +33383,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -32763,22 +33414,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -32792,22 +33445,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -32821,22 +33476,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -32850,22 +33507,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -32879,22 +33538,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -32908,22 +33569,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -32937,22 +33600,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -32966,22 +33631,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -32995,22 +33662,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -33024,22 +33693,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -33053,22 +33724,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -33082,22 +33755,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -33111,22 +33786,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -33140,22 +33817,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -33169,22 +33848,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -33198,22 +33879,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -33227,22 +33910,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -33256,22 +33941,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -33285,22 +33972,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -33314,22 +34003,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -33343,22 +34034,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -33372,22 +34065,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -33401,22 +34096,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -33430,22 +34127,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -33459,22 +34158,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -33488,22 +34189,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -33517,22 +34220,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -33546,22 +34251,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -33575,22 +34282,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -33604,22 +34313,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -33633,22 +34344,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -33662,22 +34375,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -33691,22 +34406,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -33720,22 +34437,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -33749,22 +34468,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -33778,22 +34499,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -33807,22 +34530,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -33836,22 +34561,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -33865,22 +34592,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -33894,22 +34623,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -33923,22 +34654,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -33952,22 +34685,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -33981,22 +34716,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -34010,22 +34747,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -34039,22 +34778,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -34068,22 +34809,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -34097,22 +34840,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -34126,22 +34871,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -34155,22 +34902,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -34184,22 +34933,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -34213,22 +34964,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -34242,22 +34995,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -34271,22 +35026,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -34300,22 +35057,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -34329,22 +35088,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -34358,22 +35119,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -34387,22 +35150,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -34416,22 +35181,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -34445,22 +35212,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -34474,22 +35243,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -34503,22 +35274,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -34532,22 +35305,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -34561,22 +35336,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -34590,22 +35367,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -34619,22 +35398,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -34648,22 +35429,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -34677,22 +35460,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -34706,22 +35491,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -34735,22 +35522,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -34764,22 +35553,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -34793,22 +35584,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -34822,22 +35615,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -34851,22 +35646,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -34880,22 +35677,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -34909,22 +35708,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -34938,22 +35739,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -34967,22 +35770,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -34996,22 +35801,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -35025,22 +35832,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -35054,22 +35863,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -35083,22 +35894,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -35112,22 +35925,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -35141,22 +35956,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -35170,22 +35987,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -35199,22 +36018,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -35228,22 +36049,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -35257,22 +36080,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -35286,22 +36111,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -35315,22 +36142,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -35344,22 +36173,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -35373,22 +36204,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -35402,22 +36235,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -35431,22 +36266,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -35460,22 +36297,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -35489,22 +36328,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -35518,22 +36359,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -35547,22 +36390,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -35576,22 +36421,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -35605,22 +36452,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -35634,22 +36483,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -35663,22 +36514,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -35692,22 +36545,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -35721,22 +36576,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -35750,22 +36607,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -35779,22 +36638,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -35808,22 +36669,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -35837,22 +36700,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -35866,22 +36731,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -35895,22 +36762,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -35924,22 +36793,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -35953,22 +36824,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -35982,22 +36855,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -36011,22 +36886,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -36040,22 +36917,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -36069,22 +36948,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -36098,22 +36979,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -36127,22 +37010,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -36156,22 +37041,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -36185,22 +37072,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -36214,22 +37103,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -36243,22 +37134,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -36272,22 +37165,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -36301,22 +37196,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -36330,22 +37227,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -36359,22 +37258,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -36388,22 +37289,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -36417,22 +37320,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -36446,22 +37351,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -36475,22 +37382,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -36504,22 +37413,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -36533,22 +37444,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -36562,22 +37475,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -36591,22 +37506,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -36620,22 +37537,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -36649,22 +37568,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -36678,22 +37599,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -36707,22 +37630,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -36736,22 +37661,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -36765,22 +37692,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -36794,22 +37723,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -36823,22 +37754,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -36852,22 +37785,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -36881,22 +37816,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -36910,22 +37847,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -36939,22 +37878,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -36968,22 +37909,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -36997,22 +37940,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -37026,22 +37971,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -37055,22 +38002,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -37084,22 +38033,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -37113,22 +38064,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -37142,22 +38095,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -37171,22 +38126,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -37200,22 +38157,51 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } + + + if (System.getProperty("apipath") != null) { + if (a.apiId == null) { + a.apiId = Platform.uuid + } + + def tracker = new ApiPathTracker(a.apiId) + def out = errorOut(a.call()) + def path = tracker.getApiPath() + if (!path.isEmpty()) { + Test.apiPaths[a.class.name] = path.join(" --->\n") + } + + return out + } else { + return errorOut(a.call()) + } + } + + + def reInitDataVolume(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.ReInitDataVolumeAction.class) Closure c) { + def a = new org.zstack.sdk.ReInitDataVolumeAction() + a.sessionId = Test.currentEnvSpec?.session?.uuid + c.resolveStrategy = Closure.OWNER_FIRST + c.delegate = a + c() if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -37229,20 +38215,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -37256,20 +38242,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -37283,20 +38269,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -37310,20 +38296,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -37337,20 +38323,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -37364,20 +38350,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -37391,20 +38377,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -37418,20 +38404,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -37445,20 +38431,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -37472,20 +38458,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -37499,20 +38485,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -37526,20 +38512,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -37553,20 +38539,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -37580,20 +38566,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -37607,20 +38593,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -37634,20 +38620,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -37661,20 +38647,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -37688,20 +38674,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -37715,20 +38701,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -37742,20 +38728,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -37769,20 +38755,47 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + + + if (System.getProperty("apipath") != null) { + if (a.apiId == null) { + a.apiId = Platform.uuid + } + + def tracker = new ApiPathTracker(a.apiId) + def out = errorOut(a.call()) + def path = tracker.getApiPath() + if (!path.isEmpty()) { + Test.apiPaths[a.class.name] = path.join(" --->\n") + } + + return out + } else { + return errorOut(a.call()) + } + } + + + def recoverImage(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.RecoverImageAction.class) Closure c) { + def a = new org.zstack.sdk.RecoverImageAction() + a.sessionId = Test.currentEnvSpec?.session?.uuid + c.resolveStrategy = Closure.OWNER_FIRST + c.delegate = a + c() + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -37790,26 +38803,26 @@ abstract class ApiHelper { } - def recoverImage(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.RecoverImageAction.class) Closure c) { - def a = new org.zstack.sdk.RecoverImageAction() + def recoverResourceSplitBrain(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.RecoverResourceSplitBrainAction.class) Closure c) { + def a = new org.zstack.sdk.RecoverResourceSplitBrainAction() a.sessionId = Test.currentEnvSpec?.session?.uuid c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -37817,26 +38830,26 @@ abstract class ApiHelper { } - def recoverResourceSplitBrain(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.RecoverResourceSplitBrainAction.class) Closure c) { - def a = new org.zstack.sdk.RecoverResourceSplitBrainAction() + def recoverVmInstance(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.RecoverVmInstanceAction.class) Closure c) { + def a = new org.zstack.sdk.RecoverVmInstanceAction() a.sessionId = Test.currentEnvSpec?.session?.uuid c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -37844,26 +38857,26 @@ abstract class ApiHelper { } - def recoverVmInstance(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.RecoverVmInstanceAction.class) Closure c) { - def a = new org.zstack.sdk.RecoverVmInstanceAction() + def recoveryImageFromImageStoreBackupStorage(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.RecoveryImageFromImageStoreBackupStorageAction.class) Closure c) { + def a = new org.zstack.sdk.RecoveryImageFromImageStoreBackupStorageAction() a.sessionId = Test.currentEnvSpec?.session?.uuid c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -37871,26 +38884,26 @@ abstract class ApiHelper { } - def recoveryImageFromImageStoreBackupStorage(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.RecoveryImageFromImageStoreBackupStorageAction.class) Closure c) { - def a = new org.zstack.sdk.RecoveryImageFromImageStoreBackupStorageAction() + def recoveryVirtualBorderRouterRemote(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.RecoveryVirtualBorderRouterRemoteAction.class) Closure c) { + def a = new org.zstack.sdk.RecoveryVirtualBorderRouterRemoteAction() a.sessionId = Test.currentEnvSpec?.session?.uuid c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -37898,26 +38911,26 @@ abstract class ApiHelper { } - def recoveryVirtualBorderRouterRemote(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.RecoveryVirtualBorderRouterRemoteAction.class) Closure c) { - def a = new org.zstack.sdk.RecoveryVirtualBorderRouterRemoteAction() + def refreshAiHostModelCache(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.RefreshAiHostModelCacheAction.class) Closure c) { + def a = new org.zstack.sdk.RefreshAiHostModelCacheAction() a.sessionId = Test.currentEnvSpec?.session?.uuid c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -37927,24 +38940,24 @@ abstract class ApiHelper { def refreshCaptcha(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.RefreshCaptchaAction.class) Closure c) { def a = new org.zstack.sdk.RefreshCaptchaAction() - + c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -37958,20 +38971,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -37985,20 +38998,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -38012,20 +39025,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -38039,20 +39052,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -38066,20 +39079,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -38093,20 +39106,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -38120,20 +39133,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -38147,20 +39160,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -38174,20 +39187,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -38201,20 +39214,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -38228,20 +39241,47 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + + + if (System.getProperty("apipath") != null) { + if (a.apiId == null) { + a.apiId = Platform.uuid + } + + def tracker = new ApiPathTracker(a.apiId) + def out = errorOut(a.call()) + def path = tracker.getApiPath() + if (!path.isEmpty()) { + Test.apiPaths[a.class.name] = path.join(" --->\n") + } + + return out + } else { + return errorOut(a.call()) + } + } + + + def registerLicenseClient(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.RegisterLicenseClientAction.class) Closure c) { + def a = new org.zstack.sdk.RegisterLicenseClientAction() + a.sessionId = Test.currentEnvSpec?.session?.uuid + c.resolveStrategy = Closure.OWNER_FIRST + c.delegate = a + c() + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -38255,20 +39295,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -38282,20 +39322,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -38309,20 +39349,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -38336,20 +39376,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -38363,20 +39403,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -38390,20 +39430,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -38417,20 +39457,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -38444,20 +39484,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -38471,20 +39511,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -38498,20 +39538,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -38525,20 +39565,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -38552,20 +39592,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -38579,20 +39619,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -38606,20 +39646,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -38633,20 +39673,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -38660,20 +39700,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -38687,20 +39727,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -38714,20 +39754,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -38741,20 +39781,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -38768,20 +39808,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -38795,20 +39835,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -38822,20 +39862,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -38849,20 +39889,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -38876,20 +39916,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -38903,20 +39943,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -38930,20 +39970,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -38957,20 +39997,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -38984,20 +40024,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -39011,20 +40051,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -39038,20 +40078,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -39065,20 +40105,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -39092,20 +40132,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -39119,20 +40159,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -39146,20 +40186,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -39173,20 +40213,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -39200,20 +40240,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -39227,20 +40267,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -39254,20 +40294,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -39281,20 +40321,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -39308,20 +40348,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -39335,20 +40375,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -39362,20 +40402,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -39389,20 +40429,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -39416,20 +40456,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -39443,20 +40483,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -39470,20 +40510,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -39497,20 +40537,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -39524,20 +40564,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -39551,20 +40591,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -39578,20 +40618,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -39605,20 +40645,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -39632,20 +40672,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -39659,20 +40699,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -39686,20 +40726,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -39713,20 +40753,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -39740,20 +40780,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -39767,20 +40807,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -39794,20 +40834,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -39821,20 +40861,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -39848,20 +40888,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -39875,20 +40915,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -39902,20 +40942,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -39929,20 +40969,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -39956,20 +40996,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -39983,20 +41023,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -40010,20 +41050,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -40037,20 +41077,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -40064,20 +41104,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -40091,20 +41131,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -40118,20 +41158,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -40145,20 +41185,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -40172,20 +41212,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -40199,20 +41239,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -40226,20 +41266,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -40253,20 +41293,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -40280,20 +41320,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -40307,20 +41347,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -40334,20 +41374,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -40361,47 +41401,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - - if (System.getProperty("apipath") != null) { - if (a.apiId == null) { - a.apiId = Platform.uuid - } - - def tracker = new ApiPathTracker(a.apiId) - def out = errorOut(a.call()) - def path = tracker.getApiPath() - if (!path.isEmpty()) { - Test.apiPaths[a.class.name] = path.join(" --->\n") - } - - return out - } else { - return errorOut(a.call()) - } - } - - def setVmDGpuStrategy(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.SetVmDGpuStrategyAction.class) Closure c) { - def a = new org.zstack.sdk.SetVmDGpuStrategyAction() - a.sessionId = Test.currentEnvSpec?.session?.uuid - c.resolveStrategy = Closure.OWNER_FIRST - c.delegate = a - c() - if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -40415,20 +41428,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -40442,20 +41455,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -40469,20 +41482,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -40496,20 +41509,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -40523,20 +41536,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -40550,20 +41563,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -40577,20 +41590,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -40604,20 +41617,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -40631,20 +41644,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -40658,20 +41671,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -40685,20 +41698,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -40712,20 +41725,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -40739,20 +41752,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -40766,20 +41779,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -40793,20 +41806,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -40820,20 +41833,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -40847,20 +41860,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -40874,20 +41887,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -40901,20 +41914,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -40928,20 +41941,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -40955,20 +41968,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -40982,20 +41995,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -41009,20 +42022,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -41036,20 +42049,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -41063,20 +42076,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -41090,20 +42103,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -41117,20 +42130,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -41144,20 +42157,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -41171,20 +42184,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -41198,20 +42211,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -41225,20 +42238,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -41252,20 +42265,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -41279,20 +42292,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -41306,20 +42319,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -41333,20 +42346,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -41360,20 +42373,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -41387,20 +42400,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -41414,20 +42427,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -41441,20 +42454,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -41468,20 +42481,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -41495,20 +42508,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -41522,20 +42535,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -41549,20 +42562,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -41576,20 +42589,47 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + + + if (System.getProperty("apipath") != null) { + if (a.apiId == null) { + a.apiId = Platform.uuid + } + + def tracker = new ApiPathTracker(a.apiId) + def out = errorOut(a.call()) + def path = tracker.getApiPath() + if (!path.isEmpty()) { + Test.apiPaths[a.class.name] = path.join(" --->\n") + } + + return out + } else { + return errorOut(a.call()) + } + } + + + def syncAliyunRouterInterfaceFromRemote(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.SyncAliyunRouterInterfaceFromRemoteAction.class) Closure c) { + def a = new org.zstack.sdk.SyncAliyunRouterInterfaceFromRemoteAction() + a.sessionId = Test.currentEnvSpec?.session?.uuid + c.resolveStrategy = Closure.OWNER_FIRST + c.delegate = a + c() + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -41597,26 +42637,26 @@ abstract class ApiHelper { } - def syncAliyunRouterInterfaceFromRemote(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.SyncAliyunRouterInterfaceFromRemoteAction.class) Closure c) { - def a = new org.zstack.sdk.SyncAliyunRouterInterfaceFromRemoteAction() + def syncAliyunSnapshotRemote(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.SyncAliyunSnapshotRemoteAction.class) Closure c) { + def a = new org.zstack.sdk.SyncAliyunSnapshotRemoteAction() a.sessionId = Test.currentEnvSpec?.session?.uuid c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -41624,26 +42664,26 @@ abstract class ApiHelper { } - def syncAliyunSnapshotRemote(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.SyncAliyunSnapshotRemoteAction.class) Closure c) { - def a = new org.zstack.sdk.SyncAliyunSnapshotRemoteAction() + def syncAliyunVirtualRouterFromRemote(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.SyncAliyunVirtualRouterFromRemoteAction.class) Closure c) { + def a = new org.zstack.sdk.SyncAliyunVirtualRouterFromRemoteAction() a.sessionId = Test.currentEnvSpec?.session?.uuid c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -41651,26 +42691,26 @@ abstract class ApiHelper { } - def syncAliyunVirtualRouterFromRemote(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.SyncAliyunVirtualRouterFromRemoteAction.class) Closure c) { - def a = new org.zstack.sdk.SyncAliyunVirtualRouterFromRemoteAction() + def syncCdnModelServiceTemplate(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.SyncCdnModelServiceTemplateAction.class) Closure c) { + def a = new org.zstack.sdk.SyncCdnModelServiceTemplateAction() a.sessionId = Test.currentEnvSpec?.session?.uuid c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -41684,20 +42724,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -41711,20 +42751,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -41738,20 +42778,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -41765,20 +42805,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -41792,20 +42832,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -41819,20 +42859,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -41846,20 +42886,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -41873,20 +42913,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -41900,20 +42940,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -41927,20 +42967,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -41954,20 +42994,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -41981,20 +43021,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -42008,20 +43048,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -42035,20 +43075,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -42062,20 +43102,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -42089,20 +43129,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -42116,20 +43156,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -42143,20 +43183,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -42170,20 +43210,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -42197,20 +43237,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -42224,20 +43264,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -42251,20 +43291,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -42278,20 +43318,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -42305,20 +43345,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -42332,20 +43372,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -42359,20 +43399,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -42386,20 +43426,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -42413,20 +43453,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -42440,20 +43480,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -42463,24 +43503,24 @@ abstract class ApiHelper { def tokenIntrospection(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.TokenIntrospectionAction.class) Closure c) { def a = new org.zstack.sdk.TokenIntrospectionAction() - + c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -42494,20 +43534,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -42521,20 +43561,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -42548,20 +43588,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -42575,20 +43615,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -42602,20 +43642,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -42629,20 +43669,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -42656,20 +43696,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -42683,20 +43723,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -42710,20 +43750,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -42737,20 +43777,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -42764,20 +43804,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -42791,20 +43831,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -42818,20 +43858,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -42845,20 +43885,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -42872,20 +43912,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -42899,20 +43939,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -42926,20 +43966,47 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + + + if (System.getProperty("apipath") != null) { + if (a.apiId == null) { + a.apiId = Platform.uuid + } + + def tracker = new ApiPathTracker(a.apiId) + def out = errorOut(a.call()) + def path = tracker.getApiPath() + if (!path.isEmpty()) { + Test.apiPaths[a.class.name] = path.join(" --->\n") + } + + return out + } else { + return errorOut(a.call()) + } + } + + + def updateAiHostModelCachePolicy(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.UpdateAiHostModelCachePolicyAction.class) Closure c) { + def a = new org.zstack.sdk.UpdateAiHostModelCachePolicyAction() + a.sessionId = Test.currentEnvSpec?.session?.uuid + c.resolveStrategy = Closure.OWNER_FIRST + c.delegate = a + c() + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -42953,20 +44020,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -42980,20 +44047,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -43007,20 +44074,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -43034,20 +44101,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -43061,20 +44128,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -43088,20 +44155,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -43115,20 +44182,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -43142,20 +44209,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -43169,20 +44236,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -43196,20 +44263,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -43223,20 +44290,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -43250,20 +44317,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -43277,20 +44344,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -43304,20 +44371,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -43331,20 +44398,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -43358,20 +44425,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -43385,20 +44452,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -43412,20 +44479,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -43439,20 +44506,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -43466,20 +44533,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -43493,20 +44560,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -43520,20 +44587,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -43547,20 +44614,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -43574,20 +44641,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -43601,20 +44668,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -43628,20 +44695,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -43655,20 +44722,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -43682,20 +44749,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -43709,20 +44776,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -43736,20 +44803,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -43763,20 +44830,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -43790,20 +44857,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -43817,20 +44884,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -43844,20 +44911,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -43871,20 +44938,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -43898,20 +44965,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -43925,20 +44992,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -43952,20 +45019,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -43979,20 +45046,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -44006,20 +45073,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -44033,20 +45100,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -44060,20 +45127,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -44087,20 +45154,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -44114,20 +45181,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -44141,20 +45208,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -44168,20 +45235,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -44195,20 +45262,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -44222,20 +45289,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -44249,20 +45316,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -44276,20 +45343,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -44303,20 +45370,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -44330,20 +45397,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -44357,20 +45424,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -44384,20 +45451,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -44411,20 +45478,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -44438,20 +45505,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -44465,20 +45532,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -44492,20 +45559,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -44519,20 +45586,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -44546,20 +45613,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -44573,20 +45640,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -44600,20 +45667,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -44627,20 +45694,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -44654,20 +45721,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -44681,20 +45748,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -44708,20 +45775,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -44735,20 +45802,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -44762,20 +45829,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -44789,20 +45856,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -44816,20 +45883,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -44843,20 +45910,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -44870,20 +45937,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -44897,20 +45964,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -44924,20 +45991,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -44951,20 +46018,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -44978,20 +46045,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -45005,20 +46072,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -45032,20 +46099,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -45059,20 +46126,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -45086,20 +46153,47 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + + + if (System.getProperty("apipath") != null) { + if (a.apiId == null) { + a.apiId = Platform.uuid + } + + def tracker = new ApiPathTracker(a.apiId) + def out = errorOut(a.call()) + def path = tracker.getApiPath() + if (!path.isEmpty()) { + Test.apiPaths[a.class.name] = path.join(" --->\n") + } + + return out + } else { + return errorOut(a.call()) + } + } + + + def updateHaNetworkGroup(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.UpdateHaNetworkGroupAction.class) Closure c) { + def a = new org.zstack.sdk.UpdateHaNetworkGroupAction() + a.sessionId = Test.currentEnvSpec?.session?.uuid + c.resolveStrategy = Closure.OWNER_FIRST + c.delegate = a + c() + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -45113,20 +46207,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -45140,20 +46234,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -45167,20 +46261,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -45194,20 +46288,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -45221,20 +46315,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -45248,20 +46342,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -45275,20 +46369,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -45302,20 +46396,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -45329,20 +46423,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -45356,20 +46450,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -45383,20 +46477,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -45410,20 +46504,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -45437,20 +46531,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -45464,20 +46558,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -45491,20 +46585,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -45518,20 +46612,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -45545,20 +46639,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -45572,20 +46666,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -45599,20 +46693,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -45626,20 +46720,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -45653,20 +46747,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -45680,20 +46774,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -45707,20 +46801,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -45734,20 +46828,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -45761,20 +46855,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -45788,20 +46882,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -45815,20 +46909,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -45842,20 +46936,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -45869,20 +46963,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -45896,20 +46990,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -45923,20 +47017,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -45950,20 +47044,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -45977,20 +47071,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -46004,20 +47098,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -46031,20 +47125,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -46058,20 +47152,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -46085,20 +47179,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -46112,20 +47206,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -46139,20 +47233,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -46166,20 +47260,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -46193,20 +47287,47 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + + + if (System.getProperty("apipath") != null) { + if (a.apiId == null) { + a.apiId = Platform.uuid + } + + def tracker = new ApiPathTracker(a.apiId) + def out = errorOut(a.call()) + def path = tracker.getApiPath() + if (!path.isEmpty()) { + Test.apiPaths[a.class.name] = path.join(" --->\n") + } + + return out + } else { + return errorOut(a.call()) + } + } + + + def updateNativeClusterZakuHealthStatus(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.UpdateNativeClusterZakuHealthStatusAction.class) Closure c) { + def a = new org.zstack.sdk.UpdateNativeClusterZakuHealthStatusAction() + a.sessionId = Test.currentEnvSpec?.session?.uuid + c.resolveStrategy = Closure.OWNER_FIRST + c.delegate = a + c() + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -46220,20 +47341,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -46247,20 +47368,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -46274,20 +47395,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -46301,20 +47422,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -46328,20 +47449,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -46355,20 +47476,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -46382,20 +47503,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -46409,20 +47530,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -46436,20 +47557,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -46463,20 +47584,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -46490,20 +47611,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -46517,20 +47638,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -46544,20 +47665,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -46571,20 +47692,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -46598,20 +47719,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -46625,20 +47746,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -46652,20 +47773,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -46679,20 +47800,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -46706,20 +47827,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -46733,20 +47854,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -46760,20 +47881,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -46787,20 +47908,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -46814,20 +47935,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -46841,20 +47962,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -46868,20 +47989,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -46895,20 +48016,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -46922,20 +48043,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -46949,20 +48070,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -46976,20 +48097,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -47003,20 +48124,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -47030,20 +48151,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -47057,20 +48178,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -47084,20 +48205,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -47111,20 +48232,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -47138,20 +48259,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -47165,20 +48286,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -47192,20 +48313,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -47219,20 +48340,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -47246,20 +48367,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -47273,20 +48394,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -47300,20 +48421,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -47327,20 +48448,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -47354,20 +48475,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -47381,20 +48502,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -47408,20 +48529,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -47435,20 +48556,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -47462,20 +48583,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -47489,20 +48610,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -47516,20 +48637,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -47543,20 +48664,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -47570,20 +48691,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -47597,20 +48718,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -47624,20 +48745,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -47651,20 +48772,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -47678,20 +48799,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -47705,20 +48826,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -47732,20 +48853,47 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + + + if (System.getProperty("apipath") != null) { + if (a.apiId == null) { + a.apiId = Platform.uuid + } + + def tracker = new ApiPathTracker(a.apiId) + def out = errorOut(a.call()) + def path = tracker.getApiPath() + if (!path.isEmpty()) { + Test.apiPaths[a.class.name] = path.join(" --->\n") + } + + return out + } else { + return errorOut(a.call()) + } + } + + + def updateVmDGpu(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.UpdateVmDGpuAction.class) Closure c) { + def a = new org.zstack.sdk.UpdateVmDGpuAction() + a.sessionId = Test.currentEnvSpec?.session?.uuid + c.resolveStrategy = Closure.OWNER_FIRST + c.delegate = a + c() + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -47759,20 +48907,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -47786,20 +48934,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -47813,20 +48961,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -47840,20 +48988,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -47867,20 +49015,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -47894,20 +49042,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -47921,20 +49069,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -47948,20 +49096,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -47975,20 +49123,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -48002,20 +49150,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -48029,20 +49177,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -48056,20 +49204,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -48083,20 +49231,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -48110,20 +49258,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -48137,20 +49285,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -48164,20 +49312,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -48191,20 +49339,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -48218,20 +49366,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -48245,20 +49393,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -48272,20 +49420,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -48299,20 +49447,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -48326,20 +49474,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -48353,20 +49501,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -48380,20 +49528,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -48407,20 +49555,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -48434,20 +49582,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -48461,20 +49609,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -48484,24 +49632,24 @@ abstract class ApiHelper { def validatePassword(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.ValidatePasswordAction.class) Closure c) { def a = new org.zstack.sdk.ValidatePasswordAction() - + c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -48515,20 +49663,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -48542,20 +49690,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -48565,24 +49713,24 @@ abstract class ApiHelper { def validateSession(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.ValidateSessionAction.class) Closure c) { def a = new org.zstack.sdk.ValidateSessionAction() - + c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -48596,20 +49744,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -48623,20 +49771,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -48650,20 +49798,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -48677,20 +49825,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -48704,20 +49852,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -48731,20 +49879,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -48758,20 +49906,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -48785,20 +49933,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -48812,22 +49960,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -48841,20 +49991,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -48868,20 +50018,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -48895,20 +50045,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -48922,20 +50072,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -48949,20 +50099,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -48976,20 +50126,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -49003,20 +50153,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -49030,20 +50180,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -49057,20 +50207,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -49084,22 +50234,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -49113,22 +50265,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -49142,22 +50296,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -49171,22 +50327,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -49200,20 +50358,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -49227,20 +50385,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -49254,20 +50412,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -49281,20 +50439,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -49308,20 +50466,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -49335,20 +50493,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -49362,20 +50520,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -49389,20 +50547,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -49416,20 +50574,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -49443,20 +50601,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -49470,20 +50628,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -49497,20 +50655,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -49524,20 +50682,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -49551,20 +50709,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -49578,20 +50736,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -49605,20 +50763,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -49632,20 +50790,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -49659,20 +50817,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -49686,20 +50844,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -49713,20 +50871,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -49740,20 +50898,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -49767,20 +50925,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -49794,20 +50952,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -49821,20 +50979,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -49848,20 +51006,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -49875,20 +51033,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -49902,20 +51060,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -49929,20 +51087,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -49956,20 +51114,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -49983,20 +51141,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -50010,20 +51168,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -50037,20 +51195,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -50064,20 +51222,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -50091,20 +51249,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -50118,20 +51276,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -50145,20 +51303,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -50172,20 +51330,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -50199,20 +51357,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -50226,20 +51384,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -50253,20 +51411,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -50280,20 +51438,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -50307,20 +51465,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -50334,20 +51492,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -50361,20 +51519,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -50388,20 +51546,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -50411,24 +51569,24 @@ abstract class ApiHelper { def loginIAM2VirtualID(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.iam2.api.LoginIAM2VirtualIDAction.class) Closure c) { def a = new org.zstack.sdk.iam2.api.LoginIAM2VirtualIDAction() - + c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -50442,22 +51600,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -50471,22 +51631,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -50500,22 +51662,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -50529,22 +51693,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -50558,22 +51724,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -50587,22 +51755,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -50616,22 +51786,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -50645,22 +51817,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -50674,22 +51848,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -50703,22 +51879,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -50732,22 +51910,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -50761,22 +51941,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -50790,20 +51972,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -50817,20 +51999,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -50844,20 +52026,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -50871,20 +52053,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -50898,20 +52080,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -50925,20 +52107,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -50952,20 +52134,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -50979,20 +52161,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -51006,20 +52188,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -51033,20 +52215,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -51060,20 +52242,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -51087,20 +52269,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -51114,20 +52296,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -51141,20 +52323,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -51168,20 +52350,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -51195,20 +52377,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -51222,20 +52404,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -51249,20 +52431,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -51276,20 +52458,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -51303,20 +52485,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -51330,20 +52512,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -51357,20 +52539,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -51384,20 +52566,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -51411,20 +52593,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -51438,20 +52620,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -51465,20 +52647,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -51492,20 +52674,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -51519,20 +52701,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -51546,20 +52728,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -51573,20 +52755,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -51600,20 +52782,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -51627,20 +52809,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -51654,20 +52836,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -51681,20 +52863,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -51708,20 +52890,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -51735,20 +52917,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -51762,20 +52944,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -51789,20 +52971,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -51816,20 +52998,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -51843,20 +53025,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -51870,20 +53052,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -51897,22 +53079,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -51926,20 +53110,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -51953,20 +53137,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -51980,20 +53164,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -52007,20 +53191,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -52034,20 +53218,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -52061,20 +53245,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -52088,22 +53272,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -52117,20 +53303,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -52144,20 +53330,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -52171,20 +53357,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -52198,20 +53384,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -52225,20 +53411,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -52252,20 +53438,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -52279,20 +53465,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -52306,20 +53492,136 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + + + if (System.getProperty("apipath") != null) { + if (a.apiId == null) { + a.apiId = Platform.uuid + } + + def tracker = new ApiPathTracker(a.apiId) + def out = errorOut(a.call()) + def path = tracker.getApiPath() + if (!path.isEmpty()) { + Test.apiPaths[a.class.name] = path.join(" --->\n") + } + + return out + } else { + return errorOut(a.call()) + } + } + + + def createL2GeneveNetwork(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.network.zns.CreateL2GeneveNetworkAction.class) Closure c) { + def a = new org.zstack.sdk.network.zns.CreateL2GeneveNetworkAction() + a.sessionId = Test.currentEnvSpec?.session?.uuid + c.resolveStrategy = Closure.OWNER_FIRST + c.delegate = a + c() + + + if (System.getProperty("apipath") != null) { + if (a.apiId == null) { + a.apiId = Platform.uuid + } + + def tracker = new ApiPathTracker(a.apiId) + def out = errorOut(a.call()) + def path = tracker.getApiPath() + if (!path.isEmpty()) { + Test.apiPaths[a.class.name] = path.join(" --->\n") + } + + return out + } else { + return errorOut(a.call()) + } + } + + + def getCandidateZnsNicModesForAttachingL3Network(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.network.zns.GetCandidateZnsNicModesForAttachingL3NetworkAction.class) Closure c) { + def a = new org.zstack.sdk.network.zns.GetCandidateZnsNicModesForAttachingL3NetworkAction() + a.sessionId = Test.currentEnvSpec?.session?.uuid + c.resolveStrategy = Closure.OWNER_FIRST + c.delegate = a + c() + + + if (System.getProperty("apipath") != null) { + if (a.apiId == null) { + a.apiId = Platform.uuid + } + + def tracker = new ApiPathTracker(a.apiId) + def out = errorOut(a.call()) + def path = tracker.getApiPath() + if (!path.isEmpty()) { + Test.apiPaths[a.class.name] = path.join(" --->\n") + } + + return out + } else { + return errorOut(a.call()) + } + } + + + def queryZnsTenant(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.network.zns.QueryZnsTenantAction.class) Closure c) { + def a = new org.zstack.sdk.network.zns.QueryZnsTenantAction() + a.sessionId = Test.currentEnvSpec?.session?.uuid + c.resolveStrategy = Closure.OWNER_FIRST + c.delegate = a + c() + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } + + + if (System.getProperty("apipath") != null) { + if (a.apiId == null) { + a.apiId = Platform.uuid + } + + def tracker = new ApiPathTracker(a.apiId) + def out = errorOut(a.call()) + def path = tracker.getApiPath() + if (!path.isEmpty()) { + Test.apiPaths[a.class.name] = path.join(" --->\n") + } + + return out + } else { + return errorOut(a.call()) + } + } + + + def queryZnsTenantRouter(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.network.zns.QueryZnsTenantRouterAction.class) Closure c) { + def a = new org.zstack.sdk.network.zns.QueryZnsTenantRouterAction() + a.sessionId = Test.currentEnvSpec?.session?.uuid + c.resolveStrategy = Closure.OWNER_FIRST + c.delegate = a + c() + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -52333,20 +53635,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -52360,20 +53662,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -52387,20 +53689,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -52414,20 +53716,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -52441,20 +53743,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -52468,20 +53770,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -52495,20 +53797,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -52522,20 +53824,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -52549,22 +53851,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -52578,22 +53882,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -52607,22 +53913,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -52636,22 +53944,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -52665,22 +53975,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -52694,20 +54006,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -52721,20 +54033,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -52748,20 +54060,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -52775,20 +54087,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -52802,20 +54114,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -52829,20 +54141,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -52856,20 +54168,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -52883,20 +54195,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -52910,20 +54222,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -52937,20 +54249,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -52964,22 +54276,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -52993,22 +54307,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -53022,20 +54338,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -53049,20 +54365,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -53076,20 +54392,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -53103,20 +54419,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -53130,20 +54446,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -53157,20 +54473,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -53184,20 +54500,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -53211,20 +54527,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -53238,22 +54554,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -53267,22 +54585,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -53296,22 +54616,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -53325,20 +54647,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -53352,20 +54674,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -53379,20 +54701,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -53406,20 +54728,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -53433,20 +54755,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -53460,22 +54782,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -53489,22 +54813,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -53518,20 +54844,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -53545,20 +54871,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -53572,20 +54898,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -53599,20 +54925,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -53626,20 +54952,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -53653,22 +54979,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -53682,20 +55010,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -53709,20 +55037,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -53736,20 +55064,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -53763,22 +55091,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -53792,20 +55122,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -53819,20 +55149,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -53846,20 +55176,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -53873,22 +55203,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -53902,20 +55234,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -53929,20 +55261,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -53956,22 +55288,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -53985,20 +55319,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -54012,20 +55346,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -54039,20 +55373,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -54066,22 +55400,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -54095,20 +55431,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -54122,20 +55458,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -54149,20 +55485,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -54176,20 +55512,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -54203,22 +55539,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -54232,22 +55570,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -54261,20 +55601,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -54288,20 +55628,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -54315,20 +55655,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -54342,20 +55682,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -54369,20 +55709,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -54396,20 +55736,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -54423,20 +55763,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -54450,20 +55790,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -54477,20 +55817,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -54504,20 +55844,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -54531,22 +55871,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -54560,22 +55902,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -54589,22 +55933,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -54618,22 +55964,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -54647,22 +55995,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -54676,22 +56026,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -54705,22 +56057,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -54734,20 +56088,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -54761,20 +56115,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -54788,20 +56142,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -54815,20 +56169,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -54842,20 +56196,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -54869,20 +56223,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -54896,20 +56250,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -54923,20 +56277,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -54950,20 +56304,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -54977,20 +56331,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -55004,20 +56358,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -55031,20 +56385,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -55058,20 +56412,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -55085,20 +56439,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -55112,20 +56466,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -55139,20 +56493,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -55166,20 +56520,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -55193,20 +56547,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -55220,22 +56574,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -55249,22 +56605,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -55278,22 +56636,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -55307,20 +56667,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -55334,20 +56694,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -55361,20 +56721,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -55388,20 +56748,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -55415,20 +56775,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -55442,20 +56802,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -55469,20 +56829,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -55496,20 +56856,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -55523,20 +56883,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -55550,20 +56910,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -55577,20 +56937,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -55604,20 +56964,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -55631,20 +56991,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -55658,22 +57018,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -55687,22 +57049,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -55716,20 +57080,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -55743,20 +57107,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -55770,20 +57134,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -55797,22 +57161,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -55826,20 +57192,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -55853,20 +57219,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -55880,22 +57246,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -55909,20 +57277,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -55936,20 +57304,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -55963,20 +57331,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -55990,20 +57358,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -56017,20 +57385,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -56044,20 +57412,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -56071,20 +57439,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -56098,20 +57466,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -56125,20 +57493,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -56152,20 +57520,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -56179,20 +57547,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -56206,20 +57574,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -56233,20 +57601,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -56260,20 +57628,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -56287,20 +57655,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -56314,20 +57682,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -56341,20 +57709,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -56368,22 +57736,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -56397,22 +57767,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -56426,22 +57798,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -56455,22 +57829,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -56484,22 +57860,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -56513,20 +57891,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -56540,20 +57918,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -56567,20 +57945,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -56594,20 +57972,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -56621,20 +57999,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -56648,20 +58026,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -56675,20 +58053,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -56702,20 +58080,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -56729,20 +58107,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -56756,20 +58134,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -56783,20 +58161,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -56810,20 +58188,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -56837,20 +58215,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -56864,22 +58242,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -56893,22 +58273,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -56922,22 +58304,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -56951,22 +58335,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -56980,22 +58366,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -57009,22 +58397,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -57038,22 +58428,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -57067,22 +58459,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -57096,20 +58490,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -57123,20 +58517,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -57150,20 +58544,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -57177,20 +58571,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -57204,20 +58598,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -57231,20 +58625,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -57258,20 +58652,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -57285,22 +58679,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -57314,20 +58710,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -57341,20 +58737,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -57368,20 +58764,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -57395,20 +58791,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -57422,22 +58818,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -57451,22 +58849,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -57480,22 +58880,24 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - - a.conditions = a.conditions.collect { it.toString() } + + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -57509,20 +58911,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -57536,20 +58938,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) diff --git a/testlib/src/main/java/org/zstack/testlib/ApiHelperGenerator.groovy b/testlib/src/main/java/org/zstack/testlib/ApiHelperGenerator.groovy index bc30fc25bd9..198570fd59d 100755 --- a/testlib/src/main/java/org/zstack/testlib/ApiHelperGenerator.groovy +++ b/testlib/src/main/java/org/zstack/testlib/ApiHelperGenerator.groovy @@ -29,9 +29,11 @@ class ApiHelperGenerator { return "" } - return """ - a.conditions = a.conditions.collect { it.toString() } -""" + return """ + if (a.conditions != null) { + a.conditions = a.conditions.collect { it.toString() } + } +""" }() String funcName = actionClass.simpleName - "Action" diff --git a/testlib/src/main/java/org/zstack/testlib/EnvSpec.groovy b/testlib/src/main/java/org/zstack/testlib/EnvSpec.groovy index 5491d321f1b..fec7d2c2eaf 100755 --- a/testlib/src/main/java/org/zstack/testlib/EnvSpec.groovy +++ b/testlib/src/main/java/org/zstack/testlib/EnvSpec.groovy @@ -4,6 +4,7 @@ import groovy.transform.AutoClone import org.codehaus.groovy.runtime.InvokerHelper import org.springframework.http.* import org.springframework.http.client.HttpComponentsClientHttpRequestFactory +import org.springframework.web.multipart.MultipartHttpServletRequest import org.springframework.web.client.RestTemplate import org.zstack.compute.vm.VmGlobalConfig import org.zstack.configuration.SqlForeignKeyGenerator @@ -109,6 +110,7 @@ class EnvSpec extends ApiHelper implements Node { private ConcurrentHashMap> defaultHttpConditionHandlers = [:] protected static RestTemplate restTemplate protected static Set simulatorClasses = Platform.reflections.getSubTypesOf(Simulator.class) + private static volatile List> cachedEORelations static Set cleanupClosures = [] private Map virtualFilesSystems = [:] @@ -707,7 +709,8 @@ class EnvSpec extends ApiHelper implements Node { "EventRecordsVO", "AuditsVO", "AlarmRecordsVO", "VmCrashHistoryVO", "EncryptionIntegrityVO", "FileIntegrityVerificationVO", "EncryptEntityMetadataVO", "VmInstanceDeviceAddressGroupVO", "HostOsCategoryVO", "KvmHostHypervisorMetadataVO", "HaStrategyConditionVO", "SystemTagVO", "ConsoleProxyAgentVO", "ConsoleProxyVO", "XmlHookVO", "SSOServerTokenVO", - "HostNetworkLabelVO", "L3NetworkSequenceNumberVO"]) { + "HostNetworkLabelVO", "L3NetworkSequenceNumberVO", + "HaNetworkGroupGlobalConfigVersionVO"]) { return } @@ -803,8 +806,6 @@ class EnvSpec extends ApiHelper implements Node { } private void cleanupEO() { - SqlForeignKeyGenerator g = new SqlForeignKeyGenerator() - def vos = Platform.reflections.getTypesAnnotatedWith(EO.class).findAll { it.isAnnotationPresent(EO.class) } logger.debug(String.format("cleanupEO->clean targets(%s): %s", vos.size(), vos.toString())) Map eoNameEOClassMap = new HashMap<>() @@ -823,7 +824,19 @@ class EnvSpec extends ApiHelper implements Node { logger.debug(String.format("cleanupEO->clean targets(%s): %s", eoNameEOClassMap.size(), eoNameEOClassMap.toString())) logger.debug(String.format("cleanupEO->all nodes(%s): %s", nodes.size(), nodes.toString())) - new TraverseCleanEO(g.generateEORelations(), nodes, eoNameEOClassMap, eoNameVOClassMap).traverse() + new TraverseCleanEO(eoRelations(), nodes, eoNameEOClassMap, eoNameVOClassMap).traverse() + } + + private static List> eoRelations() { + if (cachedEORelations == null) { + synchronized (EnvSpec.class) { + if (cachedEORelations == null) { + cachedEORelations = Collections.unmodifiableList(new SqlForeignKeyGenerator().generateEORelations()) + } + } + } + + return cachedEORelations } protected void callDeleteOnResourcesNeedDeletion() { @@ -987,21 +1000,78 @@ class EnvSpec extends ApiHelper implements Node { } HttpEntity getEntityFromRequest(HttpServletRequest req) { - StringBuilder sb = new StringBuilder() - String line - while ((line = req.getReader().readLine()) != null) { - sb.append(line) - } - req.getReader().close() - HttpHeaders header = new HttpHeaders() for (Enumeration e = req.getHeaderNames() ; e.hasMoreElements() ;) { String name = e.nextElement().toString() header.add(name, req.getHeader(name)) } + + StringBuilder sb = new StringBuilder() + if (req.getContentType()?.toLowerCase()?.startsWith("multipart/")) { + sb.append(readMultipartBody(req)) + } else { + def reader = req.getReader() + try { + String line + while ((line = reader.readLine()) != null) { + sb.append(line) + } + } finally { + reader.close() + } + } + return new HttpEntity(sb.toString(), header) } + protected String readMultipartBody(HttpServletRequest req) { + byte[] raw = req.inputStream.bytes + if (raw.length > 0) { + return new String(raw, "UTF-8") + } + + if (req instanceof MultipartHttpServletRequest) { + return readSpringMultipartBody(req as MultipartHttpServletRequest) + } + + StringBuilder sb = new StringBuilder() + try { + req.getParts().each { part -> + appendMultipartPart(sb, part.name, part.submittedFileName, part.contentType, part.inputStream.bytes) + } + } catch (Throwable t) { + logger.debug("failed to read multipart parts for ${req.requestURI}", t) + } + return sb.toString() + } + + protected String readSpringMultipartBody(MultipartHttpServletRequest req) { + StringBuilder sb = new StringBuilder() + req.parameterMap.each { String name, String[] values -> + values.each { value -> + appendMultipartPart(sb, name, null, "text/plain", value == null ? new byte[0] : value.getBytes("UTF-8")) + } + } + req.fileMap.each { String name, file -> + appendMultipartPart(sb, name, file.originalFilename, file.contentType, file.bytes) + } + return sb.toString() + } + + protected void appendMultipartPart(StringBuilder sb, String name, String filename, String contentType, byte[] content) { + sb.append("Content-Disposition: form-data; name=\"").append(name).append("\"") + if (filename != null) { + sb.append("; filename=\"").append(filename).append("\"") + } + sb.append("\n") + if (contentType != null) { + sb.append("Content-Type: ").append(contentType).append("\n") + } + sb.append("\n") + sb.append(new String(content == null ? new byte[0] : content, "UTF-8")) + sb.append("\n") + } + void handleConditionSimulatorHttpRequests(HttpServletRequest req, HttpEntity entity, HttpServletResponse rsp) { def url = req.getRequestURI() if (httpConditionHandlers[url] == null || httpConditionHandlers[url].isEmpty()) { @@ -1222,4 +1292,4 @@ class EnvSpec extends ApiHelper implements Node { void resetAllMessageSize() { messageHandlerCounters.clear() } -} \ No newline at end of file +} diff --git a/testlib/src/main/java/org/zstack/testlib/KVMHostSpec.groovy b/testlib/src/main/java/org/zstack/testlib/KVMHostSpec.groovy index 64d4253fa99..22ee8722cdb 100755 --- a/testlib/src/main/java/org/zstack/testlib/KVMHostSpec.groovy +++ b/testlib/src/main/java/org/zstack/testlib/KVMHostSpec.groovy @@ -36,11 +36,12 @@ class KVMHostSpec extends HostSpec { delegate.managementIp = managementIp delegate.username = username delegate.password = password - delegate.userTags = userTags - delegate.systemTags = systemTags - delegate.clusterUuid = (parent as ClusterSpec).inventory.uuid - delegate.sessionId = sessionId - } as HostInventory + delegate.userTags = userTags + delegate.systemTags = systemTags + delegate.clusterUuid = (parent as ClusterSpec).inventory.uuid + delegate.sessionId = sessionId + delegate.timeout = 60000 + } as HostInventory postCreate { inventory = queryHost { diff --git a/testlib/src/main/java/org/zstack/testlib/KVMSimulator.groovy b/testlib/src/main/java/org/zstack/testlib/KVMSimulator.groovy index 81bd88ac6bf..1aeb890345b 100755 --- a/testlib/src/main/java/org/zstack/testlib/KVMSimulator.groovy +++ b/testlib/src/main/java/org/zstack/testlib/KVMSimulator.groovy @@ -691,5 +691,17 @@ class KVMSimulator implements Simulator { spec.simulator(KVMConstant.KVM_HOST_IPSET_SYNC_PATH) { return new KVMAgentCommands.AgentResponse() } + + spec.simulator(KVMConstant.SETUP_VM_HA_ENABLED_METADATA_LIVE_PATH) { + return new KVMAgentCommands.AgentResponse() + } + + spec.simulator(KVMConstant.RECONCILE_VM_HA_ENABLED_METADATA_LIVE_PATH) { + return new KVMAgentCommands.AgentResponse() + } + + spec.simulator(KVMConstant.HA_NETWORK_GROUP_SYNC_PATH) { + return new KVMAgentCommands.AgentResponse() + } } } diff --git a/testlib/src/main/java/org/zstack/testlib/SdnControllerSpec.groovy b/testlib/src/main/java/org/zstack/testlib/SdnControllerSpec.groovy index 25b24d7f412..cb05661c4f5 100644 --- a/testlib/src/main/java/org/zstack/testlib/SdnControllerSpec.groovy +++ b/testlib/src/main/java/org/zstack/testlib/SdnControllerSpec.groovy @@ -1,8 +1,10 @@ package org.zstack.testlib +import org.springframework.http.HttpEntity import org.springframework.http.HttpStatus import org.springframework.http.ResponseEntity import org.zstack.sdk.SdnControllerInventory +import org.zstack.utils.gson.JSONObjectUtil import org.zstack.sdnController.h3cVcfc.H3cVcfcCommands import org.zstack.sdnController.h3cVcfc.H3cVcfcCommands.LoginReply import org.zstack.sdnController.h3cVcfc.H3cVcfcCommands.LoginRsp @@ -15,7 +17,6 @@ import org.zstack.sdnController.h3cVcfc.H3cVcfcCommands.GetH3cTenantsRsp import org.zstack.sdnController.h3cVcfc.H3cVcfcCommands.H3cTenantStruct import org.zstack.sdnController.h3cVcfc.H3cVcfcCommands.GetH3cTeamLederIpReply import org.zstack.sdnController.h3cVcfc.H3cVcfcV2Commands -import org.springframework.http.HttpEntity import org.zstack.sugonSdnController.controller.SugonSdnControllerConstant import org.zstack.sugonSdnController.controller.api.ApiSerializer import org.zstack.sugonSdnController.controller.api.TfCommands @@ -58,9 +59,9 @@ class SdnControllerSpec extends Spec implements HasSession { } postCreate { - inventory = querySdnController { + inventory = JSONObjectUtil.rehashObject(querySdnController { conditions=["uuid=${inventory.uuid}".toString()] - }[0] + }[0], SdnControllerInventory.class) } return id(name, inventory.uuid) diff --git a/testlib/src/main/java/org/zstack/testlib/Test.groovy b/testlib/src/main/java/org/zstack/testlib/Test.groovy index 40f46defad1..ba84a10c09a 100755 --- a/testlib/src/main/java/org/zstack/testlib/Test.groovy +++ b/testlib/src/main/java/org/zstack/testlib/Test.groovy @@ -633,12 +633,14 @@ abstract class Test extends ApiHelper implements Retry { } static void handleHttp(HttpServletRequest request, HttpServletResponse response) { - if (WebBeanConstructor.WEB_HOOK_PATH.toString().contains(request.getRequestURI())) { - ZSClient.webHookCallback(request, response) - } else { - currentEnvSpec.handleSimulatorHttpRequests(request, response) - } - } + if (WebBeanConstructor.WEB_HOOK_PATH.toString().contains(request.getRequestURI())) { + ZSClient.webHookCallback(request, response) + } else if (currentEnvSpec == null) { + response.sendError(HttpServletResponse.SC_NOT_FOUND) + } else { + currentEnvSpec.handleSimulatorHttpRequests(request, response) + } + } static class SubCaseResult { Boolean success diff --git a/testlib/src/main/java/org/zstack/testlib/TestLibController.java b/testlib/src/main/java/org/zstack/testlib/TestLibController.java index 286eae91b04..545acb8b278 100755 --- a/testlib/src/main/java/org/zstack/testlib/TestLibController.java +++ b/testlib/src/main/java/org/zstack/testlib/TestLibController.java @@ -27,7 +27,7 @@ public class TestLibController { private static final ExecutorService pool = Executors.newFixedThreadPool(32); @RequestMapping( - value = "/**", + value = {"/**", "/v1/sites/**", "/v1/quota/**"}, method = { RequestMethod.POST, RequestMethod.PUT, RequestMethod.DELETE, RequestMethod.GET, RequestMethod.HEAD, RequestMethod.OPTIONS, RequestMethod.PATCH, RequestMethod.TRACE @@ -39,6 +39,11 @@ public void handle(HttpServletRequest request, HttpServletResponse response) thr return; } + if (isMultipartRequest(request)) { + Test.handleHttp(request, response); + return; + } + final AsyncContext asyncContext = request.startAsync(); asyncContext.setTimeout(TestConfigUtils.getMessageTimeoutMillisConfig()); @@ -59,6 +64,11 @@ public void handle(HttpServletRequest request, HttpServletResponse response) thr }); } + private boolean isMultipartRequest(HttpServletRequest request) { + String contentType = request.getContentType(); + return contentType != null && contentType.toLowerCase().startsWith("multipart/"); + } + @PreDestroy public void shutdownPool() { logger.info("Shutting down TestLibController pool"); diff --git a/testlib/src/main/java/org/zstack/testlib/util/TestConfigUtils.groovy b/testlib/src/main/java/org/zstack/testlib/util/TestConfigUtils.groovy index f71282c36d2..51765b4ef89 100644 --- a/testlib/src/main/java/org/zstack/testlib/util/TestConfigUtils.groovy +++ b/testlib/src/main/java/org/zstack/testlib/util/TestConfigUtils.groovy @@ -4,7 +4,7 @@ package org.zstack.testlib.util import java.util.concurrent.TimeUnit class TestConfigUtils { - private final static long DEFAULT_MESSAGE_TIMEOUT_SECS = TimeUnit.SECONDS.toMillis(25) + private final static long DEFAULT_MESSAGE_TIMEOUT_SECS = TimeUnit.SECONDS.toMillis(60) static long getMessageTimeoutMillisConfig(){ String msgTimeoutStr = System.getProperty("msgTimeoutMins") 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 0c66ce52f55..27c12405e70 100644 --- a/utils/src/main/java/org/zstack/utils/clouderrorcode/CloudOperationsErrorCode.java +++ b/utils/src/main/java/org/zstack/utils/clouderrorcode/CloudOperationsErrorCode.java @@ -1500,6 +1500,14 @@ public class CloudOperationsErrorCode { public static final String ORG_ZSTACK_BILLING_10027 = "ORG_ZSTACK_BILLING_10027"; + public static final String ORG_ZSTACK_BILLING_10028 = "ORG_ZSTACK_BILLING_10028"; + + public static final String ORG_ZSTACK_BILLING_10029 = "ORG_ZSTACK_BILLING_10029"; + + public static final String ORG_ZSTACK_BILLING_10030 = "ORG_ZSTACK_BILLING_10030"; + + public static final String ORG_ZSTACK_BILLING_10031 = "ORG_ZSTACK_BILLING_10031"; + public static final String ORG_ZSTACK_CRYPTO_CCS_10000 = "ORG_ZSTACK_CRYPTO_CCS_10000"; public static final String ORG_ZSTACK_CRYPTO_CCS_10001 = "ORG_ZSTACK_CRYPTO_CCS_10001"; @@ -1872,6 +1880,42 @@ public class CloudOperationsErrorCode { public static final String ORG_ZSTACK_HA_10018 = "ORG_ZSTACK_HA_10018"; + public static final String ORG_ZSTACK_HA_10019 = "ORG_ZSTACK_HA_10019"; + + public static final String ORG_ZSTACK_HA_10020 = "ORG_ZSTACK_HA_10020"; + + public static final String ORG_ZSTACK_HA_10021 = "ORG_ZSTACK_HA_10021"; + + public static final String ORG_ZSTACK_HA_10022 = "ORG_ZSTACK_HA_10022"; + + public static final String ORG_ZSTACK_HA_10023 = "ORG_ZSTACK_HA_10023"; + + public static final String ORG_ZSTACK_HA_10024 = "ORG_ZSTACK_HA_10024"; + + public static final String ORG_ZSTACK_HA_10025 = "ORG_ZSTACK_HA_10025"; + + public static final String ORG_ZSTACK_HA_10026 = "ORG_ZSTACK_HA_10026"; + + public static final String ORG_ZSTACK_HA_10027 = "ORG_ZSTACK_HA_10027"; + + public static final String ORG_ZSTACK_HA_10028 = "ORG_ZSTACK_HA_10028"; + + public static final String ORG_ZSTACK_HA_10029 = "ORG_ZSTACK_HA_10029"; + + public static final String ORG_ZSTACK_HA_10030 = "ORG_ZSTACK_HA_10030"; + + public static final String ORG_ZSTACK_HA_10031 = "ORG_ZSTACK_HA_10031"; + + public static final String ORG_ZSTACK_HA_10032 = "ORG_ZSTACK_HA_10032"; + + public static final String ORG_ZSTACK_HA_10033 = "ORG_ZSTACK_HA_10033"; + + public static final String ORG_ZSTACK_HA_10034 = "ORG_ZSTACK_HA_10034"; + + public static final String ORG_ZSTACK_HA_10035 = "ORG_ZSTACK_HA_10035"; + + public static final String ORG_ZSTACK_HA_10036 = "ORG_ZSTACK_HA_10036"; + public static final String ORG_ZSTACK_NETWORK_SERVICE_SLB_10000 = "ORG_ZSTACK_NETWORK_SERVICE_SLB_10000"; public static final String ORG_ZSTACK_NETWORK_SERVICE_SLB_10001 = "ORG_ZSTACK_NETWORK_SERVICE_SLB_10001"; @@ -10573,6 +10617,8 @@ public class CloudOperationsErrorCode { public static final String ORG_ZSTACK_CORE_REST_10012 = "ORG_ZSTACK_CORE_REST_10012"; + public static final String ORG_ZSTACK_CORE_REST_10013 = "ORG_ZSTACK_CORE_REST_10013"; + public static final String ORG_ZSTACK_LICENSE_10000 = "ORG_ZSTACK_LICENSE_10000"; public static final String ORG_ZSTACK_LICENSE_10001 = "ORG_ZSTACK_LICENSE_10001"; @@ -11393,6 +11439,14 @@ public class CloudOperationsErrorCode { public static final String ORG_ZSTACK_STORAGE_VOLUME_10096 = "ORG_ZSTACK_STORAGE_VOLUME_10096"; + public static final String ORG_ZSTACK_STORAGE_VOLUME_10097 = "ORG_ZSTACK_STORAGE_VOLUME_10097"; + + public static final String ORG_ZSTACK_STORAGE_VOLUME_10098 = "ORG_ZSTACK_STORAGE_VOLUME_10098"; + + public static final String ORG_ZSTACK_STORAGE_VOLUME_10099 = "ORG_ZSTACK_STORAGE_VOLUME_10099"; + + public static final String ORG_ZSTACK_STORAGE_VOLUME_10100 = "ORG_ZSTACK_STORAGE_VOLUME_10100"; + public static final String ORG_ZSTACK_TEST_INTEGRATION_PREMIUM_STORAGE_PRIMARY_BLOCK_VENDOR_XSTOR_10000 = "ORG_ZSTACK_TEST_INTEGRATION_PREMIUM_STORAGE_PRIMARY_BLOCK_VENDOR_XSTOR_10000"; public static final String ORG_ZSTACK_TEST_INTEGRATION_PREMIUM_STORAGE_PRIMARY_BLOCK_VENDOR_XSTOR_10001 = "ORG_ZSTACK_TEST_INTEGRATION_PREMIUM_STORAGE_PRIMARY_BLOCK_VENDOR_XSTOR_10001"; @@ -11987,6 +12041,128 @@ public class CloudOperationsErrorCode { public static final String ORG_ZSTACK_NETWORK_OVN_10084 = "ORG_ZSTACK_NETWORK_OVN_10084"; + public static final String ORG_ZSTACK_NETWORK_ZNS_10000 = "ORG_ZSTACK_NETWORK_ZNS_10000"; + + public static final String ORG_ZSTACK_NETWORK_ZNS_10001 = "ORG_ZSTACK_NETWORK_ZNS_10001"; + + public static final String ORG_ZSTACK_NETWORK_ZNS_10002 = "ORG_ZSTACK_NETWORK_ZNS_10002"; + + public static final String ORG_ZSTACK_NETWORK_ZNS_10003 = "ORG_ZSTACK_NETWORK_ZNS_10003"; + + public static final String ORG_ZSTACK_NETWORK_ZNS_10004 = "ORG_ZSTACK_NETWORK_ZNS_10004"; + + public static final String ORG_ZSTACK_NETWORK_ZNS_10005 = "ORG_ZSTACK_NETWORK_ZNS_10005"; + + public static final String ORG_ZSTACK_NETWORK_ZNS_10006 = "ORG_ZSTACK_NETWORK_ZNS_10006"; + + public static final String ORG_ZSTACK_NETWORK_ZNS_10007 = "ORG_ZSTACK_NETWORK_ZNS_10007"; + + public static final String ORG_ZSTACK_NETWORK_ZNS_10008 = "ORG_ZSTACK_NETWORK_ZNS_10008"; + + public static final String ORG_ZSTACK_NETWORK_ZNS_10009 = "ORG_ZSTACK_NETWORK_ZNS_10009"; + + // ZNS error-code semantic mapping: + // 10000 ZNS async API returned unexpected status (not 200/202) + // 10001 ZNS API returned HTTP error status + // 10002 ZNS API I/O/connection error + // 10003 ZNS API unexpected exception + // 10004 ZNS sync GET failed (without query params) + // 10005 ZNS sync GET failed (with query params) + // 10006 failed to resolve ZNS SdnController for an L2 network + // 10007 failed to resolve ZNS SdnControllerL2 for an L2 network + // 10008 reserved + // 10009 VM NIC cannot change between ZNS and non-ZNS networks + // 10010 unsupported API for ZNS controller + // 10011 ZNS L2 only supports L3BasicNetwork + // 10012 duplicate ZNS L2NoVlan creation under same controller + // 10013 invalid ZNS L2 target type in create/change-vlan flow + // 10014 duplicate/invalid Geneve change (or non-Geneve target from Geneve) + // 10015 VM NIC cannot move across different ZNS controllers + // 10016 duplicate Geneve VNI under same controller + // 10017 non-ZNS L2 cannot change to Geneve type + // 10018 ZNS non-Geneve L2 cannot change to L2GeneveNetwork + // 10019 only one L3 network is allowed per ZNS L2 network + public static final String ORG_ZSTACK_NETWORK_ZNS_10010 = "ORG_ZSTACK_NETWORK_ZNS_10010"; + + public static final String ORG_ZSTACK_NETWORK_ZNS_10011 = "ORG_ZSTACK_NETWORK_ZNS_10011"; + + public static final String ORG_ZSTACK_NETWORK_ZNS_10012 = "ORG_ZSTACK_NETWORK_ZNS_10012"; + + public static final String ORG_ZSTACK_NETWORK_ZNS_10013 = "ORG_ZSTACK_NETWORK_ZNS_10013"; + + public static final String ORG_ZSTACK_NETWORK_ZNS_10014 = "ORG_ZSTACK_NETWORK_ZNS_10014"; + + public static final String ORG_ZSTACK_NETWORK_ZNS_10015 = "ORG_ZSTACK_NETWORK_ZNS_10015"; + + public static final String ORG_ZSTACK_NETWORK_ZNS_10016 = "ORG_ZSTACK_NETWORK_ZNS_10016"; + + public static final String ORG_ZSTACK_NETWORK_ZNS_10017 = "ORG_ZSTACK_NETWORK_ZNS_10017"; + + public static final String ORG_ZSTACK_NETWORK_ZNS_10018 = "ORG_ZSTACK_NETWORK_ZNS_10018"; + public static final String ORG_ZSTACK_NETWORK_ZNS_10019 = "ORG_ZSTACK_NETWORK_ZNS_10019"; + + // ZNS DHCP + // 10020 ZNS DHCP enable/check failed due to invalid L3/segment state + // 10021 ZNS compute manager not found on controller + // 10022 ZNS reconnect: compute manager UUID missing + // 10023 reserved + // 10024 unsupported legacy SdnControllerDhcp path for ZNS L3 + public static final String ORG_ZSTACK_NETWORK_ZNS_10020 = "ORG_ZSTACK_NETWORK_ZNS_10020"; + public static final String ORG_ZSTACK_NETWORK_ZNS_10021 = "ORG_ZSTACK_NETWORK_ZNS_10021"; + public static final String ORG_ZSTACK_NETWORK_ZNS_10022 = "ORG_ZSTACK_NETWORK_ZNS_10022"; + public static final String ORG_ZSTACK_NETWORK_ZNS_10023 = "ORG_ZSTACK_NETWORK_ZNS_10023"; + public static final String ORG_ZSTACK_NETWORK_ZNS_10024 = "ORG_ZSTACK_NETWORK_ZNS_10024"; + + // ZNS Wave 4 operation error codes + // 10025 ZNS create segment failed + // 10026 ZNS patch segment failed (e.g. CIDR/gateway sync) + // 10027 ZNS attach router to segment failed + // 10028 ZNS detach router from segment failed + // 10029 ZNS patch DHCP config on segment failed + // 10030 ZNS patch segment MTU failed + // 10031 duplicate IpRange ip_version on same ZNS L3 network + // 10032 ZNS L2 has sub-resources, cannot delete + // 10033 ZNS VPC L3 missing znsTenantRouterUuid system tag + public static final String ORG_ZSTACK_NETWORK_ZNS_10025 = "ORG_ZSTACK_NETWORK_ZNS_10025"; + public static final String ORG_ZSTACK_NETWORK_ZNS_10026 = "ORG_ZSTACK_NETWORK_ZNS_10026"; + public static final String ORG_ZSTACK_NETWORK_ZNS_10027 = "ORG_ZSTACK_NETWORK_ZNS_10027"; + public static final String ORG_ZSTACK_NETWORK_ZNS_10028 = "ORG_ZSTACK_NETWORK_ZNS_10028"; + public static final String ORG_ZSTACK_NETWORK_ZNS_10029 = "ORG_ZSTACK_NETWORK_ZNS_10029"; + public static final String ORG_ZSTACK_NETWORK_ZNS_10030 = "ORG_ZSTACK_NETWORK_ZNS_10030"; + public static final String ORG_ZSTACK_NETWORK_ZNS_10031 = "ORG_ZSTACK_NETWORK_ZNS_10031"; + public static final String ORG_ZSTACK_NETWORK_ZNS_10032 = "ORG_ZSTACK_NETWORK_ZNS_10032"; + public static final String ORG_ZSTACK_NETWORK_ZNS_10033 = "ORG_ZSTACK_NETWORK_ZNS_10033"; + // 10034 ZNS API returned HTTP 409 Conflict (sub-resources still exist) + public static final String ORG_ZSTACK_NETWORK_ZNS_10034 = "ORG_ZSTACK_NETWORK_ZNS_10034"; + // 10035 ZNS returned an IP version that Cloud did not allocate + // 10036 ZNS returned IP does not match Cloud allocated IP + // 10037 ZNS returned IP is outside Cloud L3 IP range + // 10038 ZNS returned IP is already used by another NIC + // 10039 ZNS did not return any IPs + // 10040 ZNS did not return Cloud allocated IP version + // 10041 VM NIC MAC update is not supported for ZNS NICs + // 10042 L3Network not found while enabling ZNS DHCP + // 10043 failed to allocate DHCPv4 server IP in ZNS DHCP helper + // 10044 ZNS DHCP enable has no eligible IpRange + // 10045 ZNS DHCP enable has no Cloud-reserved DHCPv4 server IP + // 10046 ZNS DHCP 409 fallback GET returned empty + // 10047 ZNS DHCP update has no Cloud-reserved DHCPv4 server IP + // 10048 failed to allocate DHCPv4 server IP in ZNS DHCP backend + public static final String ORG_ZSTACK_NETWORK_ZNS_10035 = "ORG_ZSTACK_NETWORK_ZNS_10035"; + public static final String ORG_ZSTACK_NETWORK_ZNS_10036 = "ORG_ZSTACK_NETWORK_ZNS_10036"; + public static final String ORG_ZSTACK_NETWORK_ZNS_10037 = "ORG_ZSTACK_NETWORK_ZNS_10037"; + public static final String ORG_ZSTACK_NETWORK_ZNS_10038 = "ORG_ZSTACK_NETWORK_ZNS_10038"; + public static final String ORG_ZSTACK_NETWORK_ZNS_10039 = "ORG_ZSTACK_NETWORK_ZNS_10039"; + public static final String ORG_ZSTACK_NETWORK_ZNS_10040 = "ORG_ZSTACK_NETWORK_ZNS_10040"; + public static final String ORG_ZSTACK_NETWORK_ZNS_10041 = "ORG_ZSTACK_NETWORK_ZNS_10041"; + public static final String ORG_ZSTACK_NETWORK_ZNS_10042 = "ORG_ZSTACK_NETWORK_ZNS_10042"; + public static final String ORG_ZSTACK_NETWORK_ZNS_10043 = "ORG_ZSTACK_NETWORK_ZNS_10043"; + public static final String ORG_ZSTACK_NETWORK_ZNS_10044 = "ORG_ZSTACK_NETWORK_ZNS_10044"; + public static final String ORG_ZSTACK_NETWORK_ZNS_10045 = "ORG_ZSTACK_NETWORK_ZNS_10045"; + public static final String ORG_ZSTACK_NETWORK_ZNS_10046 = "ORG_ZSTACK_NETWORK_ZNS_10046"; + public static final String ORG_ZSTACK_NETWORK_ZNS_10047 = "ORG_ZSTACK_NETWORK_ZNS_10047"; + public static final String ORG_ZSTACK_NETWORK_ZNS_10048 = "ORG_ZSTACK_NETWORK_ZNS_10048"; + public static final String ORG_ZSTACK_PREMIUM_EXTERNALSERVICE_MARKETPLACE_10000 = "ORG_ZSTACK_PREMIUM_EXTERNALSERVICE_MARKETPLACE_10000"; public static final String ORG_ZSTACK_ALIYUN_NAS_STORAGE_PRIMARY_IMAGESTORE_10000 = "ORG_ZSTACK_ALIYUN_NAS_STORAGE_PRIMARY_IMAGESTORE_10000"; @@ -13697,6 +13873,12 @@ public class CloudOperationsErrorCode { public static final String ORG_ZSTACK_NETWORK_SERVICE_LB_10176 = "ORG_ZSTACK_NETWORK_SERVICE_LB_10176"; + public static final String ORG_ZSTACK_NETWORK_SERVICE_LB_10177 = "ORG_ZSTACK_NETWORK_SERVICE_LB_10177"; + + public static final String ORG_ZSTACK_NETWORK_SERVICE_LB_10178 = "ORG_ZSTACK_NETWORK_SERVICE_LB_10178"; + + public static final String ORG_ZSTACK_NETWORK_SERVICE_LB_10179 = "ORG_ZSTACK_NETWORK_SERVICE_LB_10179"; + public static final String ORG_ZSTACK_IPSEC_10000 = "ORG_ZSTACK_IPSEC_10000"; public static final String ORG_ZSTACK_IPSEC_10001 = "ORG_ZSTACK_IPSEC_10001"; @@ -15410,6 +15592,12 @@ public class CloudOperationsErrorCode { public static final String ORG_ZSTACK_SDNCONTROLLER_10030 = "ORG_ZSTACK_SDNCONTROLLER_10030"; + public static final String ORG_ZSTACK_SDNCONTROLLER_10031 = "ORG_ZSTACK_SDNCONTROLLER_10031"; + + public static final String ORG_ZSTACK_SDNCONTROLLER_10032 = "ORG_ZSTACK_SDNCONTROLLER_10032"; + + public static final String ORG_ZSTACK_SDNCONTROLLER_10033 = "ORG_ZSTACK_SDNCONTROLLER_10033"; + public static final String ORG_ZSTACK_TEST_INTEGRATION_PREMIUM_ZSV_SNAPSHOT_10000 = "ORG_ZSTACK_TEST_INTEGRATION_PREMIUM_ZSV_SNAPSHOT_10000"; public static final String ORG_ZSTACK_TEST_INTEGRATION_PREMIUM_ZSV_SNAPSHOT_10001 = "ORG_ZSTACK_TEST_INTEGRATION_PREMIUM_ZSV_SNAPSHOT_10001"; @@ -16041,4 +16229,6 @@ public class CloudOperationsErrorCode { public static final String ORG_ZSTACK_DGPU_10011 = "ORG_ZSTACK_DGPU_10011"; public static final String ORG_ZSTACK_DGPU_10012 = "ORG_ZSTACK_DGPU_10012"; + + public static final String ORG_ZSTACK_DGPU_10013 = "ORG_ZSTACK_DGPU_10013"; } diff --git a/utils/src/main/java/org/zstack/utils/ssh/SshShell.java b/utils/src/main/java/org/zstack/utils/ssh/SshShell.java index 80ea35c94ce..67299048bd2 100755 --- a/utils/src/main/java/org/zstack/utils/ssh/SshShell.java +++ b/utils/src/main/java/org/zstack/utils/ssh/SshShell.java @@ -29,6 +29,14 @@ public class SshShell { private String privateKey; private int port = 22; private Boolean withSudo = true; + private int connectTimeoutSeconds = 10; + private int serverAliveIntervalSeconds = 5; + private int serverAliveCountMax = 2; + + private String sshTimeoutOptions() { + return String.format("-o ConnectTimeout=%d -o ServerAliveInterval=%d -o ServerAliveCountMax=%d", + connectTimeoutSeconds, serverAliveIntervalSeconds, serverAliveCountMax); + } private void checkParams() { DebugUtils.Assert(hostname != null && !hostname.trim().equals(""), "hostname cannot be null"); @@ -37,21 +45,30 @@ private void checkParams() { } public SshResult runCommand(String cmd) { + return runCommand(cmd, false); + } + + public SshResult runCommandWithPseudoTty(String cmd) { + return runCommand(cmd, true); + } + + private SshResult runCommand(String cmd, boolean allocatePseudoTty) { checkParams(); String ssh; File tempPasswordFile = null; + String pseudoTtyOption = allocatePseudoTty ? "-tt " : ""; try { if (privateKey != null) { tempPasswordFile = File.createTempFile("zstack", "tmp"); writeSecretFile(tempPasswordFile, privateKey); - ssh = String.format("ssh -q -i %s -o UserKnownHostsFile=/dev/null -o PasswordAuthentication=no -o StrictHostKeyChecking=no -p %s %s@%s '%s'", - tempPasswordFile.getAbsolutePath(), port, username, hostname, cmd); + ssh = String.format("ssh -q %s-i %s -o UserKnownHostsFile=/dev/null -o PasswordAuthentication=no -o StrictHostKeyChecking=no %s -p %s %s@%s '%s'", + pseudoTtyOption, tempPasswordFile.getAbsolutePath(), sshTimeoutOptions(), port, username, hostname, cmd); } else { tempPasswordFile = File.createTempFile("zstack", "tmp"); writeSecretFile(tempPasswordFile, password); - ssh = String.format("sshpass -f%s ssh -q -o UserKnownHostsFile=/dev/null -o PubkeyAuthentication=no -o StrictHostKeyChecking=no -p %s %s@%s '%s'", - tempPasswordFile.getAbsolutePath(), port, username, hostname, cmd); + ssh = String.format("sshpass -f%s ssh -q %s-o UserKnownHostsFile=/dev/null -o PubkeyAuthentication=no -o StrictHostKeyChecking=no %s -p %s %s@%s '%s'", + tempPasswordFile.getAbsolutePath(), pseudoTtyOption, sshTimeoutOptions(), port, username, hostname, cmd); } if (logger.isTraceEnabled()) { @@ -89,7 +106,7 @@ public SshResult runScript(String script) { tempPasswordFile = File.createTempFile("zstack", "tmp"); writeSecretFile(tempPasswordFile, privateKey); ssh = ln( - "ssh -q -i {0} -o UserKnownHostsFile=/dev/null -o PasswordAuthentication=no -o StrictHostKeyChecking=no -p {1} -T {2}@{3} << 'EOF'", + "ssh -q -i {0} -o UserKnownHostsFile=/dev/null -o PasswordAuthentication=no -o StrictHostKeyChecking=no {5} -p {1} -T {2}@{3} << 'EOF'", "s=`mktemp`", "cat << 'EOT' > $s", "{4}", @@ -99,12 +116,12 @@ public SshResult runScript(String script) { "rm -f $s", "exit $ret", "EOF" - ).format(tempPasswordFile.getAbsolutePath(), port, username, hostname, script); + ).format(tempPasswordFile.getAbsolutePath(), port, username, hostname, script, sshTimeoutOptions()); } else { tempPasswordFile = File.createTempFile("zstack", "tmp"); writeSecretFile(tempPasswordFile, password); ssh = ln( - "sshpass -f{0} ssh -q -o UserKnownHostsFile=/dev/null -o PubkeyAuthentication=no -o StrictHostKeyChecking=no -p {1} -T {2}@{3} << 'EOF'", + "sshpass -f{0} ssh -q -o UserKnownHostsFile=/dev/null -o PubkeyAuthentication=no -o StrictHostKeyChecking=no {5} -p {1} -T {2}@{3} << 'EOF'", "s=`mktemp`", "cat << 'EOT' > $s", "{4}", @@ -114,7 +131,7 @@ public SshResult runScript(String script) { "rm -f $s", "exit $ret", "EOF" - ).format(tempPasswordFile.getAbsolutePath(), port, username, hostname, script); + ).format(tempPasswordFile.getAbsolutePath(), port, username, hostname, script, sshTimeoutOptions()); } if (logger.isTraceEnabled()) { @@ -209,4 +226,28 @@ public Boolean getWithSudo() { public void setWithSudo(Boolean withSudo) { this.withSudo = withSudo; } -} \ No newline at end of file + + public int getConnectTimeoutSeconds() { + return connectTimeoutSeconds; + } + + public void setConnectTimeoutSeconds(int connectTimeoutSeconds) { + this.connectTimeoutSeconds = connectTimeoutSeconds; + } + + public int getServerAliveIntervalSeconds() { + return serverAliveIntervalSeconds; + } + + public void setServerAliveIntervalSeconds(int serverAliveIntervalSeconds) { + this.serverAliveIntervalSeconds = serverAliveIntervalSeconds; + } + + public int getServerAliveCountMax() { + return serverAliveCountMax; + } + + public void setServerAliveCountMax(int serverAliveCountMax) { + this.serverAliveCountMax = serverAliveCountMax; + } +}