diff --git a/VERSION b/VERSION index b8ac796c95..8577c9efcf 100755 --- a/VERSION +++ b/VERSION @@ -1,3 +1,3 @@ MAJOR=5 MINOR=4 -UPDATE=2 +UPDATE=6 diff --git a/build/deploydb.sh b/build/deploydb.sh index b0d922475b..dc9c5478d2 100755 --- a/build/deploydb.sh +++ b/build/deploydb.sh @@ -27,7 +27,12 @@ else loginCmd="--user=$user --password=$password --host=$host --port=$port" fi -if command -v greatdb &> /dev/null; then +# Detect MySQL version +# Extract major version number from various MySQL/MariaDB/GreatDB output formats +db_version=$(${MYSQL} --version 2>/dev/null | grep -oP '\d+\.\d+\.\d+' | head -1 | cut -d'.' -f1 || echo "5") + +# GreatDB and MySQL 8.0+ require CREATE USER before GRANT +if command -v greatdb &> /dev/null || [ "$db_version" -ge 8 ] 2>/dev/null; then ${MYSQL} ${loginCmd} << EOF set global log_bin_trust_function_creators=1; DROP DATABASE IF EXISTS zstack; @@ -42,16 +47,17 @@ if command -v greatdb &> /dev/null; then grant all privileges on zstack_rest.* to root@'127.0.0.1'; EOF else + # MySQL 5.x: GRANT with IDENTIFIED BY auto-creates users ${MYSQL} ${loginCmd} << EOF - set global log_bin_trust_function_creators=1; - DROP DATABASE IF EXISTS zstack; - CREATE DATABASE zstack; - DROP DATABASE IF EXISTS zstack_rest; - CREATE DATABASE zstack_rest; - grant all privileges on zstack.* to root@'%' identified by "${password}"; - grant all privileges on zstack_rest.* to root@'%' identified by "${password}"; - grant all privileges on zstack.* to root@'127.0.0.1' identified by "${password}"; - grant all privileges on zstack_rest.* to root@'127.0.0.1' identified by "${password}"; + set global log_bin_trust_function_creators=1; + DROP DATABASE IF EXISTS zstack; + CREATE DATABASE zstack; + DROP DATABASE IF EXISTS zstack_rest; + CREATE DATABASE zstack_rest; + grant all privileges on zstack.* to root@'%' identified by "${password}"; + grant all privileges on zstack_rest.* to root@'%' identified by "${password}"; + grant all privileges on zstack.* to root@'127.0.0.1' identified by "${password}"; + grant all privileges on zstack_rest.* to root@'127.0.0.1' identified by "${password}"; EOF fi diff --git a/build/pom.xml b/build/pom.xml index 504841e00b..c2eb9f2cbb 100755 --- a/build/pom.xml +++ b/build/pom.xml @@ -495,6 +495,16 @@ vpc ${project.version} + + org.zstack + nfvInstGroup + ${project.version} + + + org.zstack + nfvInst + ${project.version} + org.zstack 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 814cf91b83..c1eb12ba20 100755 --- a/compute/src/main/java/org/zstack/compute/allocator/HostAllocatorManagerImpl.java +++ b/compute/src/main/java/org/zstack/compute/allocator/HostAllocatorManagerImpl.java @@ -530,12 +530,14 @@ public void fail(ErrorCode errorCode) { @Override public void rollback(FlowRollback trigger, Map data) { - ReturnHostCapacityMsg rmsg = new ReturnHostCapacityMsg(); - rmsg.setHostUuid(reply.getHost().getUuid()); - rmsg.setMemoryCapacity(spec.getMemoryCapacity()); - rmsg.setCpuCapacity(spec.getCpuCapacity()); - bus.makeTargetServiceIdByResourceUuid(rmsg, HostAllocatorConstant.SERVICE_ID, rmsg.getHostUuid()); - bus.send(rmsg); + if (reply.getHost() != null) { + ReturnHostCapacityMsg rmsg = new ReturnHostCapacityMsg(); + rmsg.setHostUuid(reply.getHost().getUuid()); + rmsg.setMemoryCapacity(spec.getMemoryCapacity()); + rmsg.setCpuCapacity(spec.getCpuCapacity()); + bus.makeTargetServiceIdByResourceUuid(rmsg, HostAllocatorConstant.SERVICE_ID, rmsg.getHostUuid()); + bus.send(rmsg); + } trigger.rollback(); } }).then(new NoRollbackFlow() { diff --git a/compute/src/main/java/org/zstack/compute/allocator/HostSortorChain.java b/compute/src/main/java/org/zstack/compute/allocator/HostSortorChain.java index a96ac0db75..cbffe13761 100644 --- a/compute/src/main/java/org/zstack/compute/allocator/HostSortorChain.java +++ b/compute/src/main/java/org/zstack/compute/allocator/HostSortorChain.java @@ -195,7 +195,11 @@ public void fail(ErrorCode errorCode) { @Override public void done(ErrorCodeList errorCodeList) { if (selectedHost.get() == null) { - completion.fail(errorCodeList); + if (!errorCodeList.getCauses().isEmpty()) { + completion.fail(errorCodeList.getCauses().get(0)); + } else { + completion.fail(operr("failed to reserve host capacity for all candidate hosts")); + } return; } completion.success(selectedHost.get()); diff --git a/compute/src/main/java/org/zstack/compute/allocator/SysComponentMemUsageExtensionPoint.java b/compute/src/main/java/org/zstack/compute/allocator/SysComponentMemUsageExtensionPoint.java new file mode 100644 index 0000000000..8503295269 --- /dev/null +++ b/compute/src/main/java/org/zstack/compute/allocator/SysComponentMemUsageExtensionPoint.java @@ -0,0 +1,17 @@ +package org.zstack.compute.allocator; + +public interface SysComponentMemUsageExtensionPoint { + /** + * Retrieves the amount of huge page memory used by the system component (in byte). + * + * @return the number of byte of huge page memory in use + */ + long getHugePageMemoryUsage(String hostUuid); + + /** + * Retrieves the amount of normal memory used by the system component (in byte). + * + * @return the number of byte of normal memory in use + */ + long getNormalMemoryUsage(String hostUuid); +} diff --git a/compute/src/main/java/org/zstack/compute/host/HostSystemTags.java b/compute/src/main/java/org/zstack/compute/host/HostSystemTags.java index 8de3693633..f5a061c378 100755 --- a/compute/src/main/java/org/zstack/compute/host/HostSystemTags.java +++ b/compute/src/main/java/org/zstack/compute/host/HostSystemTags.java @@ -109,4 +109,7 @@ public class HostSystemTags { public static String DEPLOY_MODE_TOKEN = "deployMode"; public static PatternedSystemTag DEPLOY_MODE = new PatternedSystemTag(String.format("deployMode::{%s}", DEPLOY_MODE_TOKEN), HostVO.class); + + public static String HYGON_MDEV_MAX_QEMU_NUM_TOKEN = "hygonMdevMaxQemuNum"; + public static PatternedSystemTag HYGON_MDEV_MAX_QEMU_NUM = new PatternedSystemTag(String.format("hygonMdevMaxQemuNum::{%s}", HYGON_MDEV_MAX_QEMU_NUM_TOKEN), HostVO.class); } diff --git a/compute/src/main/java/org/zstack/compute/vm/AbstractVmInstance.java b/compute/src/main/java/org/zstack/compute/vm/AbstractVmInstance.java index 100bdb2bc8..51c5ed925e 100755 --- a/compute/src/main/java/org/zstack/compute/vm/AbstractVmInstance.java +++ b/compute/src/main/java/org/zstack/compute/vm/AbstractVmInstance.java @@ -65,6 +65,7 @@ public abstract class AbstractVmInstance implements VmInstance { AttachIsoToVmInstanceMsg.class.getName(), APIDetachIsoFromVmInstanceMsg.class.getName(), APIGetVmConsoleAddressMsg.class.getName(), + APIUpdateConsolePasswordMsg.class.getName(), APIDeleteVmStaticIpMsg.class.getName(), APIPauseVmInstanceMsg.class.getName(), CreateTemplateFromRootVolumeSnapShotVmMsg.class.getName(), diff --git a/compute/src/main/java/org/zstack/compute/vm/MacOperator.java b/compute/src/main/java/org/zstack/compute/vm/MacOperator.java index ea1c9bf133..5d500f451b 100644 --- a/compute/src/main/java/org/zstack/compute/vm/MacOperator.java +++ b/compute/src/main/java/org/zstack/compute/vm/MacOperator.java @@ -127,7 +127,7 @@ public boolean checkDuplicateMac(String hypervisorType, String l3Uuid, String ma public static String generateMacWithDeviceId(short deviceId) { VmMacAddressSchemaType type; try { - type = VmMacAddressSchemaType.valueOf(VmGlobalProperty.vmMacAddressSchema.toLowerCase()); + type = VmMacAddressSchemaType.valueOf(VmGlobalProperty.vmMacAddressSchema); } catch (Exception e) { type = VmMacAddressSchemaType.Random; } @@ -148,8 +148,8 @@ public static String generateMacWithDeviceIdIp(short deviceId) { } /* encode mgt ip address into mac address: for example, - * mgt ip is: 172.24.0.81, its hex string: AC 18 0 51, - * so mac address will look like: 18:00:51:xx:xx:yy + * mgt ip is: 172.24.0.81, its hex string: AC 18 00 51, + * so mac address will look like: fa:00:51:xx:xx:yy * xx:xx are random. yy is device ID */ int mgtIpL = (int)NetworkUtils.ipv4StringToLong(mgtIp); String mgtIpStr = Integer.toHexString(mgtIpL); @@ -158,7 +158,7 @@ public static String generateMacWithDeviceIdIp(short deviceId) { mgtIpStr = compensate + mgtIpStr; } - StringBuilder sb = new StringBuilder(mgtIpStr.substring(2, 4)).append(":"); + StringBuilder sb = new StringBuilder("fa").append(":"); sb.append(mgtIpStr, 4, 6).append(":"); sb.append(mgtIpStr, 6, 8).append(":"); diff --git a/compute/src/main/java/org/zstack/compute/vm/StaticIpOperator.java b/compute/src/main/java/org/zstack/compute/vm/StaticIpOperator.java index 183b095154..0fe152196f 100755 --- a/compute/src/main/java/org/zstack/compute/vm/StaticIpOperator.java +++ b/compute/src/main/java/org/zstack/compute/vm/StaticIpOperator.java @@ -318,8 +318,7 @@ public void validateSystemTagInCreateMessage(APICreateMessage msg) { validateSystemTagInApiMessage(msg); } - public void validateSystemTagInApiMessage(APIMessage msg) { - Map staticIps = getNicNetworkInfoBySystemTag(msg.getSystemTags()); + public List fillUpStaticIpInfoToVmNics(Map staticIps) { List newSystags = new ArrayList<>(); for (Map.Entry e : staticIps.entrySet()) { String l3Uuid = e.getKey(); @@ -350,7 +349,7 @@ public void validateSystemTagInApiMessage(APIMessage msg) { )); } else if (!nicIp.ipv4Netmask.equals(ipRangeVO.getNetmask())) { throw new ApiMessageInterceptionException(operr("netmask error, expect: %s, got: %s", - ipRangeVO.getNetmask(), nicIp.ipv4Netmask)); + ipRangeVO.getNetmask(), nicIp.ipv4Netmask)); } if (StringUtils.isEmpty(nicIp.ipv4Gateway)) { @@ -397,10 +396,16 @@ public void validateSystemTagInApiMessage(APIMessage msg) { } } } + } - if (!newSystags.isEmpty()) { - msg.getSystemTags().addAll(newSystags); - } + return newSystags; + } + + public void validateSystemTagInApiMessage(APIMessage msg) { + Map staticIps = getNicNetworkInfoBySystemTag(msg.getSystemTags()); + List newSystags = fillUpStaticIpInfoToVmNics(staticIps); + if (!newSystags.isEmpty()) { + msg.getSystemTags().addAll(newSystags); } } diff --git a/compute/src/main/java/org/zstack/compute/vm/VmGlobalConfig.java b/compute/src/main/java/org/zstack/compute/vm/VmGlobalConfig.java index bd79900c13..b9b5cfa3ef 100755 --- a/compute/src/main/java/org/zstack/compute/vm/VmGlobalConfig.java +++ b/compute/src/main/java/org/zstack/compute/vm/VmGlobalConfig.java @@ -133,4 +133,8 @@ public class VmGlobalConfig { @GlobalConfigValidation(validValues = {"None", "AuthenticAMD"}) @BindResourceConfig(value = {VmInstanceVO.class}) public static GlobalConfig VM_CPUID_VENDOR = new GlobalConfig(CATEGORY, "vm.cpuid.vendor"); + + @GlobalConfigValidation(validValues = {"true", "false", "auto"}) + @GlobalConfigDef(defaultValue = "false", type = String.class, description = "generate config required for vhost primary storage") + public static GlobalConfig GENERATE_CONFIG_VHOST_REQUIRED = new GlobalConfig(CATEGORY, "generate.config.vhost.required"); } 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 fe1f33f104..e598163a5a 100755 --- a/compute/src/main/java/org/zstack/compute/vm/VmInstanceApiInterceptor.java +++ b/compute/src/main/java/org/zstack/compute/vm/VmInstanceApiInterceptor.java @@ -9,6 +9,8 @@ import org.zstack.compute.VmNicUtils; import org.zstack.core.cloudbus.CloudBus; import org.zstack.core.componentloader.PluginRegistry; +import org.zstack.core.config.GlobalConfigVO; +import org.zstack.core.config.GlobalConfigVO_; import org.zstack.core.db.*; import org.zstack.core.db.SimpleQuery.Op; import org.zstack.header.apimediator.ApiMessageInterceptionException; @@ -137,6 +139,8 @@ else if (msg instanceof APIAttachVmNicToVmMsg) { validate((APIUpdateVmInstanceMsg) msg); } else if (msg instanceof APISetVmConsolePasswordMsg) { validate((APISetVmConsolePasswordMsg) msg); + } else if (msg instanceof APIUpdateConsolePasswordMsg) { + validate((APIUpdateConsolePasswordMsg) msg); } else if (msg instanceof APIChangeInstanceOfferingMsg) { validate((APIChangeInstanceOfferingMsg) msg); } else if (msg instanceof APIMigrateVmMsg) { @@ -1533,6 +1537,23 @@ private void validate(APISetVmConsolePasswordMsg msg) { } } + private void validate(APIUpdateConsolePasswordMsg msg) { + VmInstanceVO vm = dbf.findByUuid(msg.getUuid(), VmInstanceVO.class); + if (vm.getState() != VmInstanceState.Running) { + throw new ApiMessageInterceptionException(operr( + "Cannot update console password for VM[uuid:%s] because it is not in 'Running' state. Current state is '%s'.", + vm.getUuid(), vm.getState() + )); + } + boolean hasPassword = VmSystemTags.CONSOLE_PASSWORD.hasTag(vm.getUuid()); + if (!hasPassword) { + throw new ApiMessageInterceptionException(operr( + "Cannot update the console password for VM[uuid:%s] because no console password is currently set. ", + vm.getUuid() + )); + } + } + private void validate(APIAttachL3NetworkToVmNicMsg msg) { throw new ApiMessageInterceptionException(argerr("can not call this api because it's Deprecated")); } 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 ed98aef34e..68c50b7947 100755 --- a/compute/src/main/java/org/zstack/compute/vm/VmInstanceBase.java +++ b/compute/src/main/java/org/zstack/compute/vm/VmInstanceBase.java @@ -3277,6 +3277,8 @@ protected void handleApiMessage(APIMessage msg) { handle((APISetVmBootVolumeMsg) msg); } else if (msg instanceof APISetVmConsolePasswordMsg) { handle((APISetVmConsolePasswordMsg) msg); + } else if (msg instanceof APIUpdateConsolePasswordMsg) { + handle((APIUpdateConsolePasswordMsg) msg); } else if (msg instanceof APISetVmSoundTypeMsg) { handle((APISetVmSoundTypeMsg) msg); } else if (msg instanceof APISetVmQxlMemoryMsg) { @@ -4197,6 +4199,115 @@ public void handle(Map data) { }).start(); } + private void handle(APIUpdateConsolePasswordMsg msg) { + thdf.chainSubmit(new ChainTask(msg) { + @Override + public String getSyncSignature() { + return syncThreadName; + } + + @Override + public String getName() { + return String.format("update-and-apply-console-password-for-vm-%s", msg.getVmInstanceUuid()); + } + + @Override + public void run(SyncTaskChain chain) { + final APIUpdateConsolePasswordEvent evt = new APIUpdateConsolePasswordEvent(msg.getId()); + + refreshVO(); + + ErrorCode error = validateOperationByState(msg, self.getState(), SysErrors.OPERATION_ERROR); + if (error != null) { + throw new OperationFailureException(error); + } + + if (self.getHostUuid() == null) { + throw new OperationFailureException(operr( + "cannot update console password of vm[uuid:%s], the vm is not running on any host", + self.getUuid() + )); + } + + + FlowChain fchain = FlowChainBuilder.newSimpleFlowChain(); + fchain.setName(getName()); + + fchain.then(new Flow() { + String __name__ = "persist-new-console-password-in-db"; + private String oldPassword; + + @Override + public void run(FlowTrigger trigger, Map data) { + oldPassword = Optional.ofNullable(VmSystemTags.CONSOLE_PASSWORD.getTag(self.getUuid())) + .map(tag -> VmSystemTags.CONSOLE_PASSWORD.getTokenByTag(tag, VmSystemTags.CONSOLE_PASSWORD_TOKEN)) + .orElse(null); + + SystemTagCreator creator = VmSystemTags.CONSOLE_PASSWORD.newSystemTagCreator(self.getUuid()); + creator.setTagByTokens(map(e(VmSystemTags.CONSOLE_PASSWORD_TOKEN, msg.getPassword()))); + creator.recreate = true; + creator.create(); + trigger.next(); + } + + @Override + public void rollback(FlowRollback trigger, Map data) { + if (oldPassword == null) { + VmSystemTags.CONSOLE_PASSWORD.delete(self.getUuid()); + } else { + SystemTagCreator creator = VmSystemTags.CONSOLE_PASSWORD.newSystemTagCreator(self.getUuid()); + creator.setTagByTokens(map(e(VmSystemTags.CONSOLE_PASSWORD_TOKEN, oldPassword))); + creator.recreate = true; + creator.create(); + } + trigger.rollback(); + } + }); + + fchain.then(new NoRollbackFlow() { + String __name__ = "apply-new-console-password-on-hypervisor"; + + @Override + public void run(FlowTrigger trigger, Map data) { + UpdateVmConsolePasswordOnHypervisorMsg umsg = new UpdateVmConsolePasswordOnHypervisorMsg(); + umsg.setVmInstanceUuid(self.getUuid()); + umsg.setHostUuid(self.getHostUuid()); + umsg.setPassword(msg.getPassword()); + + bus.makeTargetServiceIdByResourceUuid(umsg, HostConstant.SERVICE_ID, self.getHostUuid()); + + bus.send(umsg, new CloudBusCallBack(trigger) { + @Override + public void run(MessageReply reply) { + if (!reply.isSuccess()) { + trigger.fail(reply.getError()); + } else { + trigger.next(); + } + } + }); + } + }); + + fchain.done(new FlowDoneHandler(msg) { + @Override + public void handle(Map data) { + evt.setInventory(getSelfInventory()); + bus.publish(evt); + chain.next(); + } + }).error(new FlowErrorHandler(msg) { + @Override + public void handle(ErrorCode errCode, Map data) { + evt.setError(errCode); + bus.publish(evt); + chain.next(); + } + }).start(); + } + }); + } + private void handle(APISetVmSoundTypeMsg msg) { APISetVmSoundTypeEvent evt = new APISetVmSoundTypeEvent(msg.getId()); SystemTagCreator creator = VmSystemTags.SOUND_TYPE.newSystemTagCreator(self.getUuid()); @@ -7257,6 +7368,10 @@ public DiskOfferingVO call(DiskOfferingVO arg) { getTokenByResourceUuid(self.getUuid(), VmSystemTags.CONSOLE_PASSWORD_TOKEN)); spec.setUsbRedirect(Boolean.parseBoolean(VmSystemTags.USB_REDIRECT.getTokenByResourceUuid(self.getUuid(), VmSystemTags.USB_REDIRECT_TOKEN))); spec.setEnableSecurityElement(Boolean.parseBoolean(VmSystemTags.SECURITY_ELEMENT_ENABLE.getTokenByResourceUuid(self.getUuid(), VmSystemTags.SECURITY_ELEMENT_ENABLE_TOKEN))); + String hygonToken = VmSystemTags.HYGON_SECURITY_ELEMENT_ENABLE.getTokenByResourceUuid(self.getUuid(), VmSystemTags.HYGON_SECURITY_ELEMENT_ENABLE_TOKEN); + if (StringUtils.isNotBlank(hygonToken) && "true".equalsIgnoreCase(hygonToken)) { + spec.setEnableHygonSecurityElement(Boolean.TRUE); + } if (struct.getStrategy() == VmCreationStrategy.CreateStopped || struct.getStrategy() == VmCreationStrategy.CreatedPaused) { spec.setCreatePaused(true); } @@ -7741,12 +7856,17 @@ public String call(VmNicInventory arg) { } spec.setCurrentVmOperation(operation); + selectBootOrder(spec); spec.setConsolePassword(VmSystemTags.CONSOLE_PASSWORD. getTokenByResourceUuid(self.getUuid(), VmSystemTags.CONSOLE_PASSWORD_TOKEN)); spec.setVDIMonitorNumber(VmSystemTags.VDI_MONITOR_NUMBER.getTokenByResourceUuid(self.getUuid(), VmSystemTags.VDI_MONITOR_NUMBER_TOKEN)); spec.setUsbRedirect(Boolean.parseBoolean(VmSystemTags.USB_REDIRECT.getTokenByResourceUuid(self.getUuid(), VmSystemTags.USB_REDIRECT_TOKEN))); spec.setEnableSecurityElement(Boolean.parseBoolean(VmSystemTags.SECURITY_ELEMENT_ENABLE.getTokenByResourceUuid(self.getUuid(), VmSystemTags.SECURITY_ELEMENT_ENABLE_TOKEN))); + String hygonToken = VmSystemTags.HYGON_SECURITY_ELEMENT_ENABLE.getTokenByResourceUuid(self.getUuid(), VmSystemTags.HYGON_SECURITY_ELEMENT_ENABLE_TOKEN); + if (StringUtils.isNotBlank(hygonToken) && "true".equalsIgnoreCase(hygonToken)) { + spec.setEnableHygonSecurityElement(Boolean.TRUE); + } for (BuildVmSpecExtensionPoint ext : pluginRgty.getExtensionList(BuildVmSpecExtensionPoint.class)) { ext.afterBuildVmSpec(spec); diff --git a/compute/src/main/java/org/zstack/compute/vm/VmInstanceManagerImpl.java b/compute/src/main/java/org/zstack/compute/vm/VmInstanceManagerImpl.java index 8ed1ba2e94..db203212e8 100755 --- a/compute/src/main/java/org/zstack/compute/vm/VmInstanceManagerImpl.java +++ b/compute/src/main/java/org/zstack/compute/vm/VmInstanceManagerImpl.java @@ -2078,18 +2078,18 @@ private void validateL3NetworkAttachSecurityGroup(String l3Uuid, List se VmSystemTags.L3_NETWORK_SECURITY_GROUP_UUIDS_REF.installValidator(validator); } - private void installSeDeviceValidator() { - VmSystemTags.SECURITY_ELEMENT_ENABLE.installValidator(new SystemTagValidator() { + private void installBooleanTagValidator(PatternedSystemTag tag, String tokenName, String tagDescription) { + tag.installValidator(new SystemTagValidator() { @Override public void validateSystemTag(String resourceUuid, Class resourceType, String systemTag) { - String SecurityElementEnableTokenByTag = null; - if (VmSystemTags.SECURITY_ELEMENT_ENABLE.isMatch(systemTag)) { - SecurityElementEnableTokenByTag = VmSystemTags.SECURITY_ELEMENT_ENABLE.getTokenByTag(systemTag, VmSystemTags.SECURITY_ELEMENT_ENABLE_TOKEN); + String tokenValue = null; + if (tag.isMatch(systemTag)) { + tokenValue = tag.getTokenByTag(systemTag, tokenName); } else { - throw new OperationFailureException(argerr("invalid securityElementEnable[%s], %s is not securityElementEnable tag", systemTag, SecurityElementEnableTokenByTag)); + throw new OperationFailureException(argerr("invalid %s tag[%s]", tagDescription, systemTag)); } - if (!isBoolean(SecurityElementEnableTokenByTag)) { - throw new OperationFailureException(argerr("invalid securityElementEnable[%s], %s is not boolean class", systemTag, SecurityElementEnableTokenByTag)); + if (!isBoolean(tokenValue)) { + throw new OperationFailureException(argerr("invalid %s[%s], value [%s] is not boolean", tagDescription, systemTag, tokenValue)); } } private boolean isBoolean(String param) { @@ -2098,6 +2098,18 @@ private boolean isBoolean(String param) { }); } + private void installSeDeviceValidator() { + installBooleanTagValidator(VmSystemTags.SECURITY_ELEMENT_ENABLE, + VmSystemTags.SECURITY_ELEMENT_ENABLE_TOKEN, + "securityElementEnable"); + } + + private void installHygonSeDeviceValidator() { + installBooleanTagValidator(VmSystemTags.HYGON_SECURITY_ELEMENT_ENABLE, + VmSystemTags.HYGON_SECURITY_ELEMENT_ENABLE_TOKEN, + "hygonSecurityElementEnable"); + } + private void installSystemTagValidator() { installHostnameValidator(); installUserdataValidator(); @@ -2107,6 +2119,7 @@ private void installSystemTagValidator() { installUsbRedirectValidator(); installL3NetworkSecurityGroupValidator(); installSeDeviceValidator(); + installHygonSeDeviceValidator(); new StaticIpOperator().installStaticIpValidator(); } private void installUsbRedirectValidator() { diff --git a/compute/src/main/java/org/zstack/compute/vm/VmNicQosConfigBackend.java b/compute/src/main/java/org/zstack/compute/vm/VmNicQosConfigBackend.java index 422a4fa9d7..e00e4b0496 100644 --- a/compute/src/main/java/org/zstack/compute/vm/VmNicQosConfigBackend.java +++ b/compute/src/main/java/org/zstack/compute/vm/VmNicQosConfigBackend.java @@ -1,11 +1,20 @@ package org.zstack.compute.vm; +import java.util.List; + public interface VmNicQosConfigBackend { String getVmInstanceType(); void addNicQos(String vmUuid, String vmNicUuid, Long outboundBandwidth, Long inboundBandwidth); void deleteNicQos(String vmUuid, String vmNicUuid,String direction); VmNicQosStruct getNicQos(String vmUuid, String vmNicUuid); + /** + * Batch version: return QoS struct for provided NIC UUIDs in the same order. + */ + default List getNicQosBatch(List vmNicUuids) { + throw new UnsupportedOperationException("getNicQosBatch is not supported"); + } + void addVmQos(String vmUuid, Long outboundBandwidth, Long inboundBandwidth); void deleteVmQos(String vmUuid, String direction); VmNicQosStruct getVmQos(String vmUuid); 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 21c9668175..713c64890e 100755 --- a/compute/src/main/java/org/zstack/compute/vm/VmSystemTags.java +++ b/compute/src/main/java/org/zstack/compute/vm/VmSystemTags.java @@ -99,6 +99,10 @@ public class VmSystemTags { public static String SECURITY_ELEMENT_ENABLE_TOKEN = "securityElementEnable"; public static PatternedSystemTag SECURITY_ELEMENT_ENABLE = new PatternedSystemTag(String.format("securityElementEnable::{%s}", SECURITY_ELEMENT_ENABLE_TOKEN),VmInstanceVO.class); + // set hygonSecurityElementEnable::true to enable hygon se redirect + public static String HYGON_SECURITY_ELEMENT_ENABLE_TOKEN = "hygonSecurityElementEnable"; + public static PatternedSystemTag HYGON_SECURITY_ELEMENT_ENABLE = new PatternedSystemTag(String.format("hygonSecurityElementEnable::{%s}", HYGON_SECURITY_ELEMENT_ENABLE_TOKEN),VmInstanceVO.class); + // set rdpEnable::true to enable RDP tag public static String RDP_ENABLE_TOKEN = "RDPEnable"; public static PatternedSystemTag RDP_ENABLE = new PatternedSystemTag(String.format("RDPEnable::{%s}",RDP_ENABLE_TOKEN),VmInstanceVO.class); diff --git a/conf/db/upgrade/V5.4.6__schema.sql b/conf/db/upgrade/V5.4.6__schema.sql new file mode 100644 index 0000000000..c487fde82d --- /dev/null +++ b/conf/db/upgrade/V5.4.6__schema.sql @@ -0,0 +1,353 @@ +-- Fix UsedIpVO gateway and netmask from empty strings +DROP PROCEDURE IF EXISTS fixUsedIpGatewayAndNetmask; + +DELIMITER $$ + +CREATE PROCEDURE fixUsedIpGatewayAndNetmask() +BEGIN + DECLARE done INT DEFAULT FALSE; + DECLARE v_usedIpUuid VARCHAR(32); + DECLARE v_ipRangeUuid VARCHAR(32); + DECLARE v_gateway VARCHAR(64); + DECLARE v_netmask VARCHAR(64); + + -- Cursor for UsedIpVO records with empty gateway or netmask + DECLARE cur CURSOR FOR + SELECT uuid, ipRangeUuid + FROM UsedIpVO + WHERE (gateway = '' OR netmask = '' OR gateway IS NULL OR netmask IS NULL) + AND ipRangeUuid IS NOT NULL; + + DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; + + OPEN cur; + + read_loop: LOOP + FETCH cur INTO v_usedIpUuid, v_ipRangeUuid; + + IF done THEN + LEAVE read_loop; + END IF; + + -- Get gateway and netmask from IpRangeVO + SELECT gateway, netmask + INTO v_gateway, v_netmask + FROM IpRangeVO + WHERE uuid = v_ipRangeUuid; + + -- Update UsedIpVO with correct gateway and netmask + IF v_gateway IS NOT NULL AND v_netmask IS NOT NULL THEN + UPDATE UsedIpVO + SET gateway = v_gateway, netmask = v_netmask + WHERE uuid = v_usedIpUuid; + END IF; + + END LOOP; + + CLOSE cur; + +END$$ + +DELIMITER ; + +-- Execute the procedure +CALL fixUsedIpGatewayAndNetmask(); + +-- Drop the procedure after use +DROP PROCEDURE IF EXISTS fixUsedIpGatewayAndNetmask; + + +-- Update ModelServiceVO framework values +DROP PROCEDURE IF EXISTS updateModelServiceFramework; + +DELIMITER $$ + +CREATE PROCEDURE updateModelServiceFramework() +BEGIN + DECLARE v_table_exists INT DEFAULT 0; + + -- Check if ModelServiceVO table and framework column exist + SELECT COUNT(*) INTO v_table_exists + FROM information_schema.COLUMNS + WHERE TABLE_SCHEMA = DATABASE() + AND TABLE_NAME = 'ModelServiceVO' + AND COLUMN_NAME = 'framework'; + + IF v_table_exists > 0 THEN + -- Update llama.cpp to LlamaCpp + UPDATE ModelServiceVO + SET framework = 'LlamaCpp' + WHERE framework = 'llama.cpp'; + + -- Update sentence_transformers to SentenceTransformers + UPDATE ModelServiceVO + SET framework = 'SentenceTransformers' + WHERE framework = 'sentence_transformers'; + END IF; +END$$ + +DELIMITER ; + +-- Execute the procedure +CALL updateModelServiceFramework(); + +-- Drop the procedure after use +DROP PROCEDURE IF EXISTS updateModelServiceFramework; + +UPDATE ModelVO SET architectureType = 'xtts-v2' WHERE uuid = '39280569b4e0490fb581f6ab98e76400'; +UPDATE ModelVO SET architectureType = 'sdxl-turbo' WHERE uuid = '6a720c01935f4f9ea09f81bde722ee42'; + +CALL ADD_COLUMN('ModelServiceVO', 'containerArgs', 'TEXT', 1, NULL); +CALL ADD_COLUMN('ModelServiceVO', 'containerCommand', 'TEXT', 1, NULL); + +-- Upgrade gpuVendor field in ModelServiceGpuVendorVO +Update ModelServiceGpuVendorVO set gpuVendor = 'Huawei' where gpuVendor = 'HUAWEI'; +Update ModelServiceGpuVendorVO set gpuVendor = 'Haiguang' where gpuVendor = 'HAIGUANG'; +Update ModelServiceGpuVendorVO set gpuVendor = 'TianShu' where gpuVendor = 'TIANSHU'; +Update ModelServiceGpuVendorVO set gpuVendor = 'Intel' where gpuVendor = 'INTEL'; + +CALL ADD_COLUMN('GpuDeviceVO', 'isolated', 'TINYINT(1)', 1, NULL); +CALL ADD_COLUMN('GpuDeviceSpecVO', 'isolated', 'TINYINT(1)', 1, NULL); + +DELIMITER $$ + +DROP PROCEDURE IF EXISTS fix_missing_architecture_records$$ + +CREATE PROCEDURE fix_missing_architecture_records() +BEGIN + DECLARE done INT DEFAULT FALSE; + DECLARE v_model_service_uuid VARCHAR(32); + DECLARE v_architecture VARCHAR(32); + DECLARE v_exists INT; + + -- Cursor to find all model services that have templates but missing architecture records + DECLARE service_cursor CURSOR FOR + SELECT DISTINCT mst.modelServiceUuid, mst.cpuArchitecture + FROM ModelServiceTemplateVO mst + WHERE NOT EXISTS ( + SELECT 1 + FROM ModelServiceCpuArchitectureVO msca + WHERE msca.modelServiceUuid = mst.modelServiceUuid + AND msca.architecture = mst.cpuArchitecture + ) + ORDER BY mst.modelServiceUuid, mst.cpuArchitecture; + + DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; + + -- Start transaction + START TRANSACTION; + + -- Create a temporary table to store statistics + CREATE TEMPORARY TABLE IF NOT EXISTS fix_stats ( + total_services INT DEFAULT 0, + total_records_added INT DEFAULT 0 + ); + + INSERT INTO fix_stats VALUES (0, 0); + + -- Open cursor and process each missing architecture record + OPEN service_cursor; + + read_loop: LOOP + FETCH service_cursor INTO v_model_service_uuid, v_architecture; + + IF done THEN + LEAVE read_loop; + END IF; + + -- Double check if the record doesn't exist (to avoid duplicates) + SELECT COUNT(*) INTO v_exists + FROM ModelServiceCpuArchitectureVO + WHERE modelServiceUuid = v_model_service_uuid + AND architecture = v_architecture; + + IF v_exists = 0 THEN + -- Insert the missing architecture record + INSERT INTO ModelServiceCpuArchitectureVO (modelServiceUuid, architecture, lastOpDate, createDate) + VALUES ( + v_model_service_uuid, + v_architecture, + CURRENT_TIMESTAMP(3), + CURRENT_TIMESTAMP(3) + ); + + -- Update statistics + UPDATE fix_stats SET total_records_added = total_records_added + 1; + + -- Log the fix + SELECT CONCAT('Fixed: Added architecture record [', v_architecture, '] for model service [', v_model_service_uuid, ']') AS log_message; + END IF; + + END LOOP; + + CLOSE service_cursor; + + -- Count total affected services + UPDATE fix_stats SET total_services = ( + SELECT COUNT(DISTINCT modelServiceUuid) + FROM ModelServiceCpuArchitectureVO + WHERE createDate >= (SELECT MIN(createDate) FROM (SELECT createDate FROM ModelServiceCpuArchitectureVO ORDER BY createDate DESC LIMIT 1000) AS recent) + ); + + -- Display summary + SELECT + total_records_added AS 'Total Architecture Records Added', + (SELECT COUNT(DISTINCT modelServiceUuid) FROM ModelServiceTemplateVO) AS 'Total Model Services with Templates', + (SELECT COUNT(DISTINCT modelServiceUuid) FROM ModelServiceCpuArchitectureVO) AS 'Total Model Services with Architecture Records' + FROM fix_stats; + + -- Cleanup + DROP TEMPORARY TABLE IF EXISTS fix_stats; + + -- Commit transaction + COMMIT; + + SELECT 'Fix completed successfully!' AS status; +END$$ + +DELIMITER ; + +CALL fix_missing_architecture_records(); + +-- Add new gpu constraint fields +CALL ADD_COLUMN('ModelVO', 'recommendedGpuNum', 'VARCHAR(256)', 1, NULL); +CALL ADD_COLUMN('ModelVO', 'gpuConstraintDescription', 'VARCHAR(512)', 1, NULL); + +DELIMITER $$ + +CREATE PROCEDURE update_system_model_service_templates() +BEGIN + DECLARE done INT DEFAULT FALSE; + DECLARE model_name VARCHAR(255); + DECLARE gpu_vendor_name VARCHAR(32); + DECLARE py_version VARCHAR(255); + DECLARE cuda_version VARCHAR(255); + DECLARE cann_version VARCHAR(255); + DECLARE fw_version VARCHAR(255); + DECLARE service_uuid VARCHAR(32); + + DECLARE templates_cursor CURSOR FOR + SELECT name, vendor, pythonVersion, cudaVersion, cannVersion, frameworkVersion FROM system_models_templates_to_update; + + DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; + + CREATE TEMPORARY TABLE IF NOT EXISTS system_models_templates_to_update ( + name VARCHAR(255), + vendor VARCHAR(32), + pythonVersion VARCHAR(255), + cudaVersion VARCHAR(255), + cannVersion VARCHAR(255), + frameworkVersion VARCHAR(255) + ); + + INSERT INTO system_models_templates_to_update (name, vendor, pythonVersion, cudaVersion, cannVersion, frameworkVersion) VALUES + ('vLLM-0.7.2', 'NVIDIA', '3.10', '12.5', NULL, '0.7.2'), + ('vLLM-0.8.5', 'NVIDIA', '3.10', '12.5', NULL, '0.8.5'), + ('vLLM-0.9.2', 'NVIDIA', '3.10', '12.5', NULL, '0.9.2'), + ('vLLM-0.11.0', 'NVIDIA', '3.10', '12.5', NULL, '0.11.0'), + ('SGLang-0.4.9.post1', 'NVIDIA', '3.10', '12.5', NULL, '0.4.9.post1'), + ('SGLang-0.5.2', 'NVIDIA', '3.10', '12.5', NULL, '0.5.2'), + ('SGLang-0.5.4', 'NVIDIA', '3.10', '12.5', NULL, '0.5.4'), + ('Transformers-4.48.3', 'NVIDIA', '3.10', '12.5', NULL, '4.48.3'), + ('Transformers-4.57.1', 'NVIDIA', '3.10', '12.5', NULL, '4.57.1'), + ('Transformers-4.56.2', 'NVIDIA', '3.10', '12.5', NULL, '4.56.2'), + ('sentence_transformers-3.1.1', 'NVIDIA', '3.10', '12.5', NULL, '3.1.1'), + ('Diffusers-0.30.0', 'NVIDIA', '3.10', '12.5', NULL, '0.30.0'), + ('Diffusers-0.35.1', 'NVIDIA', '3.10', '12.5', NULL, '0.35.1'), + ('MindIE-2.0.RC1-910B', 'Huawei', '3.9', NULL, '8.0', '2.0.RC1'), + ('MindIE-2.1.RC1-910B', 'Huawei', '3.9', NULL, '8.0', '2.1.RC1'), + ('MindIE-2.1.RC2-910B', 'Huawei', '3.9', NULL, '8.0', '2.1.RC2'), + ('MindIE-1.0.0-310P', 'Huawei', '3.9', NULL, '7.0', '1.0.0'), + ('vLLM-Ascend-0.11.0.rc0', 'Huawei', '3.9', NULL, '8.0', '0.11.0.rc0'), + ('vLLM-0.5.0-HYGON-Z100L', 'Haiguang', '3.10', NULL, NULL, '0.5.0'), + ('vLLM-0.8.5-HYGON-K100-AI', 'Haiguang', '3.10', NULL, NULL, '0.8.5'), + ('vLLM-0.9.2-HYGON-K100-AI', 'Haiguang', '3.10', NULL, NULL, '0.9.2'), + ('vLLM-0.7.2-HYGON-K100-AI', 'Haiguang', '3.10', NULL, NULL, '0.7.2'), + ('MinerU2.5-2509', 'NVIDIA', '3.10', '12.5', NULL, '2.5'); + + OPEN templates_cursor; + update_template_loop: LOOP + FETCH templates_cursor INTO model_name, gpu_vendor_name, py_version, cuda_version, cann_version, fw_version; + IF done THEN + LEAVE update_template_loop; + END IF; + + SELECT COUNT(*) INTO @cnt FROM `zstack`.`ModelServiceVO` WHERE name = model_name AND system = 1; + IF @cnt > 0 THEN + SELECT uuid INTO service_uuid FROM `zstack`.`ModelServiceVO` WHERE name = model_name AND system = 1 LIMIT 1; + ELSE + SET service_uuid = NULL; + END IF; + + IF service_uuid IS NOT NULL THEN + SELECT COUNT(*) INTO @tmpl_cnt FROM `zstack`.`ModelServiceTemplateVO` WHERE `modelServiceUuid` = service_uuid; + IF @tmpl_cnt > 0 THEN + UPDATE `zstack`.`ModelServiceTemplateVO` SET + `pythonVersionSemver` = py_version, + `cudaVersion` = cuda_version, + `cannVersion` = cann_version, + `frameworkVersionSemver` = fw_version, + `gpuVendor` = gpu_vendor_name + WHERE `modelServiceUuid` = service_uuid; + SELECT CONCAT('INFO: Updated ModelServiceTemplateVO for service_uuid=', service_uuid, ', updated_rows=', ROW_COUNT()) AS msg; + ELSE + INSERT INTO `zstack`.`ModelServiceTemplateVO` (`uuid`, `modelServiceUuid`, `pythonVersionSemver`, `cudaVersion`, `cannVersion`, `frameworkVersionSemver`, `gpuVendor`) + VALUES (REPLACE(UUID(),'-',''), service_uuid, py_version, cuda_version, cann_version, fw_version, gpu_vendor_name); + SELECT CONCAT('INFO: Inserted ModelServiceTemplateVO for service_uuid=', service_uuid, ', inserted_rows=', ROW_COUNT()) AS msg; + END IF; + + -- Ensure ModelServiceGpuVendorVO record exists with the corresponding gpuVendor for this modelServiceUuid + SELECT COUNT(*) INTO @gv_cnt FROM `zstack`.`ModelServiceGpuVendorVO` + WHERE `modelServiceUuid` = service_uuid AND `gpuVendor` = gpu_vendor_name; + IF @gv_cnt = 0 THEN + INSERT INTO `zstack`.`ModelServiceGpuVendorVO` (`modelServiceUuid`, `gpuVendor`) + VALUES (service_uuid, gpu_vendor_name); + SELECT CONCAT('INFO: Inserted ModelServiceGpuVendorVO for service_uuid=', service_uuid, ', gpuVendor=', gpu_vendor_name) AS msg; + ELSE + SELECT CONCAT('INFO: ModelServiceGpuVendorVO exists for service_uuid=', service_uuid, ', gpuVendor=', gpu_vendor_name) AS msg; + END IF; + ELSE + SELECT CONCAT('WARN: Service not found for model=', model_name, ', skipping template and gpuVendor update.') AS msg; + END IF; + + SET service_uuid = NULL; + END LOOP; + CLOSE templates_cursor; + + DROP TEMPORARY TABLE IF EXISTS system_models_templates_to_update; +END $$ +DELIMITER ; + +CALL update_system_model_service_templates(); +DROP PROCEDURE IF EXISTS update_system_model_service_templates; + +Update ModelServiceTemplateVO set gpuVendor = 'Huawei' where gpuVendor = 'HUAWEI'; +Update ModelServiceTemplateVO set gpuVendor = 'Haiguang' where gpuVendor = 'HAIGUANG'; +Update ModelServiceTemplateVO set gpuVendor = 'TianShu' where gpuVendor = 'TIANSHU'; +Update ModelServiceTemplateVO set gpuVendor = 'Intel' where gpuVendor = 'INTEL'; + +CALL ADD_COLUMN('GpuDeviceVO', 'gpuStatus', 'varchar(16)', 1, NULL); + +UPDATE `zstack`.`GpuDeviceVO` SET `gpuStatus`='NOMINAL' WHERE `gpuStatus` IS NULL; + +-- Add supportMetrics column to ModelServiceInstanceGroupVO +DROP PROCEDURE IF EXISTS addModelServiceInstanceGroupSupportMetricsColumn; +DELIMITER $$ +CREATE PROCEDURE addModelServiceInstanceGroupSupportMetricsColumn() +BEGIN + DECLARE columnExists BOOLEAN DEFAULT FALSE; + + SELECT COUNT(*) INTO columnExists + FROM INFORMATION_SCHEMA.COLUMNS + WHERE TABLE_NAME = 'ModelServiceInstanceGroupVO' + AND COLUMN_NAME = 'supportMetrics' + AND TABLE_SCHEMA = 'zstack'; + + IF columnExists = FALSE THEN + ALTER TABLE `zstack`.`ModelServiceInstanceGroupVO` ADD COLUMN `supportMetrics` TEXT DEFAULT NULL; + END IF; +END $$ +DELIMITER ; + +CALL addModelServiceInstanceGroupSupportMetricsColumn(); +DROP PROCEDURE IF EXISTS addModelServiceInstanceGroupSupportMetricsColumn; diff --git a/conf/db/upgrade/V5.5.0__schema.sql b/conf/db/upgrade/V5.5.0__schema.sql new file mode 100644 index 0000000000..a559decf34 --- /dev/null +++ b/conf/db/upgrade/V5.5.0__schema.sql @@ -0,0 +1,478 @@ +CALL ADD_COLUMN('VmVfNicVO', 'secondaryPciDeviceUuid', 'VARCHAR(32)', 1, NULL); +ALTER TABLE `zstack`.`VmVfNicVO` ADD CONSTRAINT `fkVmVfNicVOSecondaryPciDeviceVO` FOREIGN KEY (`secondaryPciDeviceUuid`) REFERENCES `zstack`.`PciDeviceVO` (`uuid`) ON DELETE SET NULL; + +CALL ADD_COLUMN('LicenseAuthorizedCapacityVO', 'resourceInfo', 'text', 1, NULL); + +CALL ADD_COLUMN('PciDeviceVO', 'dependentDevices', 'varchar(255)', 1, NULL); + +CREATE TABLE IF NOT EXISTS `zstack`.`ExternalPrimaryStorageSpaceVO` +( + uuid VARCHAR(32) NOT NULL, + primaryStorageUuid VARCHAR(32), + locationUrl VARCHAR(255), + type VARCHAR(255), + name VARCHAR(255), + availableCapacity BIGINT, + totalCapacity BIGINT, + availablePhysicalCapacity BIGINT, + totalPhysicalCapacity BIGINT, + `lastOpDate` TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + `createDate` TIMESTAMP, + PRIMARY KEY (`uuid`), + CONSTRAINT `fkExternalPrimaryStorageSpaceVOPrimaryStorageEO` FOREIGN KEY (`primaryStorageUuid`) REFERENCES `zstack`.`PrimaryStorageEO` (`uuid`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + + +DROP PROCEDURE IF EXISTS UpdateVolumeInstallPathForZbs; + +DELIMITER $$ +CREATE PROCEDURE UpdateVolumeInstallPathForZbs() +BEGIN + DECLARE done INT DEFAULT FALSE; + DECLARE psUuid VARCHAR(32); + DECLARE cur CURSOR FOR + SELECT uuid FROM `zstack`.`ExternalPrimaryStorageVO` WHERE identity = 'zbs'; + DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; + + OPEN cur; + read_loop: LOOP + FETCH cur INTO psUuid; + IF done THEN + LEAVE read_loop; + END IF; + + UPDATE `zstack`.`VolumeEO` + SET installPath = CONCAT('zbs://', SUBSTRING_INDEX(SUBSTRING(installPath, 5), '/', -2)) + WHERE primaryStorageUuid = psUuid + AND installPath LIKE 'cbd:%/%/%'; + + UPDATE `zstack`.`VolumeSnapshotEO` + SET primaryStorageInstallPath = CONCAT('zbs://', SUBSTRING_INDEX(SUBSTRING(primaryStorageInstallPath, 5), '/', -2)) + WHERE primaryStorageUuid = psUuid + AND primaryStorageInstallPath LIKE 'cbd:%/%/%'; + + UPDATE `zstack`.`ImageCacheVO` + SET installUrl = CONCAT('zbs://', SUBSTRING_INDEX(SUBSTRING(installUrl, 5), '/', -2)) + WHERE primaryStorageUuid = psUuid + AND installUrl LIKE 'cbd:%/%/%'; + + UPDATE `zstack`.`ImageCacheShadowVO` + SET installUrl = CONCAT('zbs://', SUBSTRING_INDEX(SUBSTRING(installUrl, 5), '/', -2)) + WHERE primaryStorageUuid = psUuid + AND installUrl LIKE 'cbd:%/%/%'; + END LOOP; + CLOSE cur; +END $$ + +DELIMITER ; + +CALL UpdateVolumeInstallPathForZbs(); + +ALTER TABLE `zstack`.`ExternalPrimaryStorageVO` MODIFY `addonInfo` TEXT DEFAULT NULL; + +-- ----------------------------------- +-- BEGIN OF HYGON CCP DEVICE VIRTUALIZATION +-- ----------------------------------- +CREATE TABLE IF NOT EXISTS `zstack`.`HygonCcpDeviceVO` ( + `uuid` varchar(32) NOT NULL UNIQUE COMMENT 'uuid', + `name` varchar(255) NOT NULL, + `description` text DEFAULT NULL, + `hostUuid` varchar(32) NOT NULL, + `pciBdf` varchar(32) NOT NULL, + `deviceType` varchar(32) NOT NULL, + `deviceId` varchar(32) NOT NULL, + `driverStatus` varchar(32) NOT NULL, + `isMasterPsp` tinyint(1) DEFAULT 0, + `vendorIdx` INT DEFAULT NULL, + `state` varchar(32) NOT NULL, + `lastOpDate` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP, + `createDate` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', + PRIMARY KEY (`uuid`), + INDEX `idxHygonCCPDeviceVOhostUuid` (`hostUuid`), + INDEX `idxHygonCCPDeviceVOdeviceType` (`deviceType`), + INDEX `idxHygonCCPDeviceVOpciBdf` (`pciBdf`), + CONSTRAINT `fkHygonCCPDeviceVOHostEO` FOREIGN KEY (`hostUuid`) REFERENCES `zstack`.`HostEO` (`uuid`) ON DELETE CASCADE + ) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE IF NOT EXISTS `zstack`.`HygonCcpMdevVO` ( + `uuid` varchar(32) NOT NULL UNIQUE, + `name` varchar(128) NOT NULL, + `description` text DEFAULT NULL, + `hostUuid` varchar(32) NOT NULL, + `ccpDeviceUuid` varchar(32) NOT NULL, + `mdevUuid` varchar(64) NOT NULL UNIQUE, + `vendorIdx` INT DEFAULT NULL, + `useFlag` tinyint(1) NOT NULL DEFAULT 0, + `vmInstanceUuid` varchar(32) DEFAULT NULL, + `status` varchar(32) NOT NULL, + `state` varchar(32) NOT NULL, + `lastOpDate` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP, + `createDate` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', + PRIMARY KEY (`uuid`), + INDEX `idxHygonCcpMdevVOhostUuid` (`hostUuid`), + INDEX `idxHygonCcpMdevVOccpDeviceUuid` (`ccpDeviceUuid`), + INDEX `idxHygonCcpMdevVOmdevUuid` (`mdevUuid`), + INDEX `idxHygonCcpMdevVOvmInstanceUuid` (`vmInstanceUuid`), + INDEX `idxHygonCcpMdevVOuseFlag` (`useFlag`), + CONSTRAINT `fkHygonCcpMdevVOHostEO` FOREIGN KEY (`hostUuid`) REFERENCES `zstack`.`HostEO` (`uuid`) ON DELETE CASCADE, + CONSTRAINT `fkHygonCcpMdevVOHygonCCPDeviceVO` FOREIGN KEY (`ccpDeviceUuid`) REFERENCES `zstack`.`HygonCcpDeviceVO` (`uuid`) ON DELETE CASCADE, + CONSTRAINT `fkHygonCcpMdevVOVmInstanceEO` FOREIGN KEY (`vmInstanceUuid`) REFERENCES `zstack`.`VmInstanceEO` (`uuid`) ON DELETE SET NULL + ) ENGINE=InnoDB DEFAULT CHARSET=utf8; +-- --------------------------------- +-- END OF HYGON CCP DEVICE VIRTUALIZATION +-- --------------------------------- + +CREATE TABLE IF NOT EXISTS `zstack`.`NfvInstOfferingVO` ( + `uuid` varchar(32) NOT NULL UNIQUE, + `managementNetworkUuid` varchar(32) NOT NULL, + `imageUuid` varchar(32) NOT NULL, + `zoneUuid` varchar(32) NOT NULL, + PRIMARY KEY (`uuid`), + CONSTRAINT fkNfvInstOfferingVOL3NetworkEO FOREIGN KEY (managementNetworkUuid) REFERENCES `zstack`.`L3NetworkEO` (uuid) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE IF NOT EXISTS `zstack`.`NfvInstGroupVO` ( + `uuid` VARCHAR(32) NOT NULL UNIQUE, + `name` VARCHAR(255) NOT NULL, + `description` VARCHAR(2048) DEFAULT NULL, + `nfvInstOfferingUuid` VARCHAR(32) DEFAULT NULL, + `instType` VARCHAR(64) NOT NULL, + `funcType` VARCHAR(64) NOT NULL, + `configVersion` int unsigned DEFAULT 0, + `netOsDistro` VARCHAR(128) DEFAULT NULL, + `baseOsDistro` VARCHAR(128) DEFAULT NULL, + `status` VARCHAR(32) DEFAULT 'Initializing', + `statusDetail` VARCHAR(255) DEFAULT NULL, + `operationMode` VARCHAR(32) DEFAULT 'Normal', + `vipUuid` VARCHAR(32) DEFAULT NULL, + `ipv6VipUuid` VARCHAR(32) DEFAULT NULL, + `primaryStorageUuid` VARCHAR(32) DEFAULT NULL, + `primaryStoragePoolUuid` VARCHAR(32) DEFAULT NULL, + `clusterUuid` VARCHAR(32) DEFAULT NULL, + `zoneUuid` VARCHAR(32) DEFAULT NULL, + `lastOpDate` timestamp ON UPDATE CURRENT_TIMESTAMP, + `createDate` timestamp, + PRIMARY KEY (`uuid`), + CONSTRAINT `fkNfvInstGroupVONfvInstOfferingVO` FOREIGN KEY (`nfvInstOfferingUuid`) REFERENCES `zstack`.`NfvInstOfferingVO` (uuid) ON DELETE SET NULL, + CONSTRAINT `fkNfvInstGroupVOPrimaryStorageEO` FOREIGN KEY (`primaryStorageUuid`) REFERENCES `zstack`.`PrimaryStorageEO` (uuid) ON DELETE SET NULL, + CONSTRAINT `fkNfvInstGroupVOClusterEO` FOREIGN KEY (`clusterUuid`) REFERENCES `zstack`.`ClusterEO` (uuid) ON DELETE SET NULL, + CONSTRAINT `fkNfvInstGroupVOZoneEO` FOREIGN KEY (`zoneUuid`) REFERENCES `zstack`.`ZoneEO` (uuid) ON DELETE SET NULL, + KEY `idx_nfv_inst_group_status_mode` (`status`, `operationMode`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE IF NOT EXISTS `zstack`.`NfvInstGroupMonitorIpVO` ( + `id` bigint unsigned NOT NULL UNIQUE AUTO_INCREMENT, + `nfvInstGroupUuid` varchar(32) NOT NULL, + `monitorIp` varchar(255) NOT NULL, + `createDate` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', + `lastOpDate` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`id`), + CONSTRAINT fkNfvInstGroupMonitorIpVONfvInstGroupVO FOREIGN KEY (nfvInstGroupUuid) REFERENCES NfvInstGroupVO (uuid) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE IF NOT EXISTS `zstack`.`NfvInstGroupNetworkServiceRefVO` ( + `id` bigint unsigned NOT NULL UNIQUE AUTO_INCREMENT, + `nfvInstGroupUuid` varchar(32) NOT NULL, + `networkServiceName` VARCHAR(255) NOT NULL, + `networkServiceUuid` varchar(32) NOT NULL, + `createDate` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', + `lastOpDate` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`id`), + CONSTRAINT fkNfvInstGroupNetworkServiceRefVONfvInstGroupVO FOREIGN KEY (nfvInstGroupUuid) REFERENCES NfvInstGroupVO (uuid) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE IF NOT EXISTS `zstack`.`NfvInstGroupL3NetworkRefVO` ( + `id` bigint unsigned NOT NULL UNIQUE AUTO_INCREMENT, + `nfvInstGroupUuid` varchar(32) NOT NULL, + `networkServiceUuid` VARCHAR(32) NOT NULL, + `l3NetworkUuid` varchar(32) NOT NULL, + `type` varchar(255) NOT NULL, + `createDate` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', + `lastOpDate` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`id`), + CONSTRAINT fkNfvInstGroupL3NetworkRefVONfvInstGroupVO FOREIGN KEY (nfvInstGroupUuid) REFERENCES NfvInstGroupVO (uuid) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE IF NOT EXISTS `zstack`.`NfvInstVO` ( + `uuid` varchar(32) NOT NULL UNIQUE, + `nfvInstGroupUuid` varchar(32) NOT NULL, + `configVersion` int unsigned NOT NULL DEFAULT 0, + `netOsDistro` VARCHAR(128) NOT NULL, + `baseOsDistro` VARCHAR(128) NOT NULL, + `clusterStatus` VARCHAR(32) DEFAULT 'Unknown', + `statusDetail` VARCHAR(255) DEFAULT NULL, + PRIMARY KEY (`uuid`), + CONSTRAINT fkNfvInstVONfvInstGroupVO FOREIGN KEY (nfvInstGroupUuid) REFERENCES NfvInstGroupVO (uuid) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE IF NOT EXISTS `zstack`.`NfvInstMetaDataVO` ( + `uuid` varchar(32) NOT NULL UNIQUE, + `agentVersion` varchar(32) DEFAULT NULL, + `netOsVersion` varchar(32) DEFAULT NULL, + `baseOsVersion` varchar(32) DEFAULT NULL, + `kernelVersion` varchar(256) DEFAULT NULL, + PRIMARY KEY (`uuid`), + CONSTRAINT `fkNfvInstMetadataVONfvInstVO` FOREIGN KEY (`uuid`) REFERENCES `NfvInstVO` (`uuid`) ON UPDATE RESTRICT ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE IF NOT EXISTS `zstack`.`NfvInstGroupConfigTaskVO` ( + `id` bigint unsigned NOT NULL UNIQUE AUTO_INCREMENT, + `nfvInstGroupUuid` varchar(32) NOT NULL, + `configVersion` int unsigned DEFAULT 0, + `serviceUuid` varchar(32) NOT NULL, + `taskName` VARCHAR(255) NOT NULL, + `path` VARCHAR(255) NOT NULL, + `taskData` text DEFAULT NULL, + `checkStatus` BOOLEAN DEFAULT FALSE, + PRIMARY KEY (`id`), + CONSTRAINT fkNfvInstGroupConfigTaskVONfvInstGroupVO FOREIGN KEY (nfvInstGroupUuid) REFERENCES NfvInstGroupVO (uuid) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CALL ADD_COLUMN('OvnControllerVmInstanceVO', 'nbClusterStatus', 'VARCHAR(32)', 1, 'Unknown'); +CALL ADD_COLUMN('OvnControllerVmInstanceVO', 'sbClusterStatus', 'VARCHAR(32)', 1, 'Unknown'); + +-- ======================================== +-- Upgrade OvnControllerVmOfferingVO and OvnControllerVmInstanceVO hierarchy +-- Only execute if NOT already upgraded +-- ======================================== + +DELIMITER $$ + +DROP PROCEDURE IF EXISTS upgrade_ovn_controller_to_nfv_inst$$ + +CREATE PROCEDURE upgrade_ovn_controller_to_nfv_inst() +BEGIN + DECLARE already_upgraded INT DEFAULT 0; + DECLARE has_management_network_column INT DEFAULT 0; + DECLARE offering_count INT DEFAULT 0; + DECLARE offering_migrated_count INT DEFAULT 0; + DECLARE instance_in_nfv_inst_count INT DEFAULT 0; + DECLARE instance_in_nfv_group_count INT DEFAULT 0; + + -- Check if upgrade has already been done by checking any of these conditions: + -- a. OvnControllerVmOfferingVO no longer has managementNetworkUuid column + SELECT COUNT(*) INTO has_management_network_column + FROM information_schema.COLUMNS + WHERE TABLE_SCHEMA = 'zstack' + AND TABLE_NAME = 'OvnControllerVmOfferingVO' + AND COLUMN_NAME = 'managementNetworkUuid'; + + IF has_management_network_column = 0 THEN + SET already_upgraded = 1; + END IF; + + -- b. Check if OvnControllerVmOfferingVO records exist in NfvInstOfferingVO + IF already_upgraded = 0 THEN + SELECT COUNT(*) INTO offering_count FROM OvnControllerVmOfferingVO; + + IF offering_count > 0 THEN + SELECT COUNT(*) INTO offering_migrated_count + FROM OvnControllerVmOfferingVO ovo + INNER JOIN NfvInstOfferingVO nivo ON ovo.uuid = nivo.uuid; + + IF offering_migrated_count = offering_count THEN + SET already_upgraded = 1; + END IF; + END IF; + END IF; + + -- c. Check if OvnControllerVmInstanceVO records exist in NfvInstVO + IF already_upgraded = 0 THEN + SELECT COUNT(*) INTO instance_in_nfv_inst_count + FROM OvnControllerVmInstanceVO ovi + INNER JOIN NfvInstVO niv ON ovi.uuid = niv.uuid; + + IF instance_in_nfv_inst_count > 0 THEN + SET already_upgraded = 1; + END IF; + END IF; + + -- d. Check if NfvInstGroupVO created for OvnControllerVmInstanceVO + IF already_upgraded = 0 THEN + SELECT COUNT(*) INTO instance_in_nfv_group_count + FROM OvnControllerVmInstanceVO ovi + INNER JOIN NfvInstVO niv ON ovi.uuid = niv.uuid + INNER JOIN NfvInstGroupVO nig ON niv.nfvInstGroupUuid = nig.uuid + WHERE nig.funcType = 'OVN_SDN_CONTROLLER'; + + IF instance_in_nfv_group_count > 0 THEN + SET already_upgraded = 1; + END IF; + END IF; + + -- If any condition is met, skip the upgrade + IF already_upgraded = 1 THEN + SELECT 'Upgrade already completed, skipping OVN Controller to NFV Instance migration' AS message; + ELSE + -- ======================================== + -- Step 1: Create NfvInstOfferingVO records for existing OvnControllerVmOfferingVO + -- This must be done BEFORE dropping columns to preserve data + -- ======================================== + INSERT INTO NfvInstOfferingVO (uuid, managementNetworkUuid, imageUuid, zoneUuid) + SELECT + ovo.uuid, + ovo.managementNetworkUuid, + ovo.imageUuid, + ovo.zoneUuid + FROM OvnControllerVmOfferingVO ovo + WHERE NOT EXISTS ( + SELECT 1 FROM NfvInstOfferingVO nivo WHERE nivo.uuid = ovo.uuid + ); + + -- ======================================== + -- Step 2: Now safe to drop foreign key from OvnControllerVmOfferingVO + -- (Columns will be dropped after procedure execution) + -- ======================================== + IF has_management_network_column > 0 THEN + -- Check if foreign key exists before dropping + IF EXISTS ( + SELECT 1 FROM information_schema.TABLE_CONSTRAINTS + WHERE TABLE_SCHEMA = 'zstack' + AND TABLE_NAME = 'OvnControllerVmOfferingVO' + AND CONSTRAINT_NAME = 'fkOvnControllerVmOfferingVOL3NetworkEO' + ) THEN + ALTER TABLE OvnControllerVmOfferingVO DROP FOREIGN KEY fkOvnControllerVmOfferingVOL3NetworkEO; + END IF; + END IF; + + -- ======================================== + -- Step 3: Create NfvInstGroupVO for each OvnControllerVmInstanceVO + -- ======================================== + + -- First, create a temporary table to store the mapping between instance UUID and generated group UUID + CREATE TEMPORARY TABLE IF NOT EXISTS temp_ovn_inst_group_mapping ( + inst_uuid VARCHAR(32) NOT NULL PRIMARY KEY, + group_uuid VARCHAR(32) NOT NULL, + group_name VARCHAR(255) NOT NULL + ); + + -- Generate random UUIDs for each OVN instance and store the mapping + INSERT INTO temp_ovn_inst_group_mapping (inst_uuid, group_uuid, group_name) + SELECT + ovn.uuid AS inst_uuid, + REPLACE(UUID(), '-', '') AS group_uuid, + LEFT(CONCAT('OVN-Controller-Group-', vm.name), 255) AS group_name + FROM OvnControllerVmInstanceVO ovn + INNER JOIN VmInstanceVO vm ON ovn.uuid = vm.uuid + WHERE NOT EXISTS ( + SELECT 1 FROM NfvInstGroupVO nfv_grp WHERE nfv_grp.uuid = ovn.uuid + ); + + -- Insert ResourceVO records for each NfvInstGroup + INSERT INTO ResourceVO (uuid, resourceName, resourceType, concreteResourceType) + SELECT + mapping.group_uuid AS uuid, + mapping.group_name AS resourceName, + 'NfvInstGroupVO' AS resourceType, + 'org.zstack.network.service.nfvinstgroup.NfvInstGroupVO' AS concreteResourceType + FROM temp_ovn_inst_group_mapping mapping + WHERE NOT EXISTS ( + SELECT 1 FROM ResourceVO res WHERE res.uuid = mapping.group_uuid + ); + + -- Insert NfvInstGroupVO records + INSERT INTO NfvInstGroupVO ( + uuid, + name, + description, + nfvInstOfferingUuid, + instType, + funcType, + configVersion, + netOsDistro, + baseOsDistro, + status, + operationMode, + vipUuid, + primaryStorageUuid, + clusterUuid, + zoneUuid, + createDate, + lastOpDate + ) + SELECT + mapping.group_uuid AS group_uuid, -- group uuid: randomly generated + mapping.group_name AS name, -- group name (limit to 255 chars) + CONCAT('Auto-created group for OVN controller ', vm.name) AS description, + ovn_off.uuid AS offering_uuid, -- nfvInstOfferingUuid + 'KVM' AS inst_type, -- instType + 'OVN_SDN_CONTROLLER' AS func_type, -- funcType + 0 AS config_version, -- configVersion + 'euler' AS net_os_distro, -- netOsDistro + 'euler' AS base_os_distro, -- baseOsDistro + 'Initializing' AS status, -- status + 'Normal' AS operation_mode, -- operationMode + NULL AS vip_uuid, -- vipUuid (will be set later if needed) + vol.primaryStorageUuid AS ps_uuid, -- primaryStorageUuid (from VolumeVO via rootVolumeUuid) + vm.clusterUuid AS cluster_uuid, -- clusterUuid + vm.zoneUuid AS zone_uuid, -- zoneUuid + vm.createDate AS create_date, -- createDate + vm.lastOpDate AS last_op_date -- lastOpDate + FROM temp_ovn_inst_group_mapping mapping + INNER JOIN OvnControllerVmInstanceVO ovn ON mapping.inst_uuid = ovn.uuid + INNER JOIN VmInstanceVO vm ON ovn.uuid = vm.uuid + LEFT JOIN VolumeVO vol ON vm.rootVolumeUuid = vol.uuid + LEFT JOIN OvnControllerVmOfferingVO ovn_off ON vm.instanceOfferingUuid = ovn_off.uuid + WHERE NOT EXISTS ( + SELECT 1 FROM NfvInstGroupVO nfv_grp WHERE nfv_grp.uuid = mapping.group_uuid + ); + + -- ======================================== + -- Step 4: Create NfvInstVO records for each OvnControllerVmInstanceVO + -- ======================================== + INSERT INTO NfvInstVO ( + uuid, + nfvInstGroupUuid, + configVersion, + netOsDistro, + baseOsDistro, + clusterStatus, + statusDetail + ) + SELECT + ovn.uuid AS inst_uuid, + mapping.group_uuid AS group_uuid, -- link to the group we created (using mapping) + 0 AS config_version, -- configVersion + 'euler' AS net_os_distro, -- netOsDistro (required field) + 'euler' AS base_os_distro, -- baseOsDistro (required field) + 'Unknown' AS cluster_status, -- clusterStatus + NULL AS status_detail -- statusDetail + FROM OvnControllerVmInstanceVO ovn + INNER JOIN temp_ovn_inst_group_mapping mapping ON ovn.uuid = mapping.inst_uuid + WHERE NOT EXISTS ( + SELECT 1 FROM NfvInstVO nfv WHERE nfv.uuid = ovn.uuid + ); + + -- Clean up temporary table + DROP TEMPORARY TABLE IF EXISTS temp_ovn_inst_group_mapping; + + SELECT 'OVN Controller to NFV Instance migration completed successfully' AS message; + + -- Drop columns after data migration (if not already dropped) + CALL DROP_COLUMN('OvnControllerVmOfferingVO', 'managementNetworkUuid'); + CALL DROP_COLUMN('OvnControllerVmOfferingVO', 'imageUuid'); + CALL DROP_COLUMN('OvnControllerVmOfferingVO', 'zoneUuid'); + END IF; +END$$ + +DELIMITER ; + +-- Execute the upgrade procedure +CALL upgrade_ovn_controller_to_nfv_inst(); + +-- Drop the procedure after execution +DROP PROCEDURE IF EXISTS upgrade_ovn_controller_to_nfv_inst; + +CREATE TABLE IF NOT EXISTS `OvnControllerVO` ( + `uuid` varchar(32) NOT NULL UNIQUE, + `remoteOvn` tinyint(1) NOT NULL DEFAULT 0, + PRIMARY KEY (`uuid`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +INSERT IGNORE INTO OvnControllerVO (uuid, remoteOvn) +SELECT uuid, 0 FROM SdnControllerVO where vendorType = 'Ovn'; + +UPDATE VolumeSnapshotVO AS sp, PrimaryStorageVO AS ps +SET sp.primaryStorageInstallPath = REPLACE(sp.primaryStorageInstallPath, '/dev/', 'sharedblock://') +WHERE sp.primaryStorageUuid = ps.uuid AND ps.type = 'SharedBlock' AND sp.volumeType = 'Memory' AND sp.primaryStorageInstallPath LIKE '/dev/%'; + diff --git a/conf/errorCodes/license.xml b/conf/errorCodes/license.xml index fa1db7d837..feaa70a2be 100755 --- a/conf/errorCodes/license.xml +++ b/conf/errorCodes/license.xml @@ -76,6 +76,21 @@ License public key error + + 3005 + The remote license has expired + + + + 3006 + The remote license expires earlier than the local license + + + + 3007 + The remote license available capacity is lower than the local license + + 3100 License server generic error diff --git a/conf/globalConfig/ceph.xml b/conf/globalConfig/ceph.xml index be1993a594..ccde2ee280 100755 --- a/conf/globalConfig/ceph.xml +++ b/conf/globalConfig/ceph.xml @@ -107,7 +107,7 @@ sds.admin.password the password of ceph admin user - password + Admin@123 ceph java.lang.String diff --git a/conf/persistence.xml b/conf/persistence.xml index 33f4326f40..30c36210dd 100755 --- a/conf/persistence.xml +++ b/conf/persistence.xml @@ -139,6 +139,7 @@ org.zstack.storage.primary.local.LocalStorageResourceRefVO org.zstack.storage.primary.local.LocalStorageHostRefVO org.zstack.header.storage.addon.primary.ExternalPrimaryStorageVO + org.zstack.header.storage.addon.primary.ExternalPrimaryStorageSpaceVO org.zstack.header.storage.addon.primary.PrimaryStorageOutputProtocolRefVO org.zstack.header.storage.addon.primary.ExternalPrimaryStorageHostRefVO org.zstack.storage.ceph.backup.CephBackupStorageVO diff --git a/conf/serviceConfig/vmInstance.xml b/conf/serviceConfig/vmInstance.xml index 81a683490e..e24559a05c 100755 --- a/conf/serviceConfig/vmInstance.xml +++ b/conf/serviceConfig/vmInstance.xml @@ -117,6 +117,9 @@ org.zstack.header.vm.APISetVmConsolePasswordMsg + + org.zstack.header.vm.APIUpdateConsolePasswordMsg + org.zstack.header.vm.APIGetVmConsoleAddressMsg diff --git a/conf/springConfigXml/ExternalPrimaryStorage.xml b/conf/springConfigXml/ExternalPrimaryStorage.xml index f0b5f60289..60c3ed6115 100644 --- a/conf/springConfigXml/ExternalPrimaryStorage.xml +++ b/conf/springConfigXml/ExternalPrimaryStorage.xml @@ -25,10 +25,13 @@ + + + @@ -44,6 +47,13 @@ + + + + + + + @@ -52,10 +62,4 @@ - - - - - - diff --git a/conf/springConfigXml/cbd.xml b/conf/springConfigXml/cbd.xml index 1582b32551..fc95b60b6b 100644 --- a/conf/springConfigXml/cbd.xml +++ b/conf/springConfigXml/cbd.xml @@ -16,6 +16,10 @@ + + + + diff --git a/conf/springConfigXml/vyos.xml b/conf/springConfigXml/vyos.xml index 30a2ecbf07..0793d44131 100755 --- a/conf/springConfigXml/vyos.xml +++ b/conf/springConfigXml/vyos.xml @@ -125,6 +125,7 @@ + diff --git a/conf/springConfigXml/zbs.xml b/conf/springConfigXml/zbs.xml index 4ef20cc35c..2e0234ddc1 100644 --- a/conf/springConfigXml/zbs.xml +++ b/conf/springConfigXml/zbs.xml @@ -21,7 +21,6 @@ - diff --git a/conf/zstack.xml b/conf/zstack.xml index ed752bf46b..5a5dbc3e24 100755 --- a/conf/zstack.xml +++ b/conf/zstack.xml @@ -120,4 +120,5 @@ + diff --git a/header/src/main/java/org/zstack/header/message/NeedReplyMessage.java b/header/src/main/java/org/zstack/header/message/NeedReplyMessage.java index 20aa942729..c873b03b04 100755 --- a/header/src/main/java/org/zstack/header/message/NeedReplyMessage.java +++ b/header/src/main/java/org/zstack/header/message/NeedReplyMessage.java @@ -24,6 +24,11 @@ public List getSystemTags() { return systemTags; } + public String getSystemTag(Predicate isMatch) { + return systemTags == null ? null : + systemTags.stream().filter(isMatch).findFirst().orElse(null); + } + public void setSystemTags(List systemTags) { this.systemTags = systemTags; } diff --git a/header/src/main/java/org/zstack/header/network/l3/L3NetworkUpdateExtensionPoint.java b/header/src/main/java/org/zstack/header/network/l3/L3NetworkUpdateExtensionPoint.java deleted file mode 100644 index 6699c0b002..0000000000 --- a/header/src/main/java/org/zstack/header/network/l3/L3NetworkUpdateExtensionPoint.java +++ /dev/null @@ -1,5 +0,0 @@ -package org.zstack.header.network.l3; - -public interface L3NetworkUpdateExtensionPoint { - void updateL3NetworkMtu(L3NetworkInventory inventory); -} diff --git a/header/src/main/java/org/zstack/header/network/l3/SdnControllerDisableDHCPMsg.java b/header/src/main/java/org/zstack/header/network/l3/SdnControllerDisableDHCPMsg.java new file mode 100644 index 0000000000..7d0e0c9dcb --- /dev/null +++ b/header/src/main/java/org/zstack/header/network/l3/SdnControllerDisableDHCPMsg.java @@ -0,0 +1,46 @@ +package org.zstack.header.network.l3; + +import org.zstack.header.message.NeedReplyMessage; +import org.zstack.header.network.sdncontroller.SdnControllerMessage; +import org.zstack.utils.network.IPv6Constants; + +public class SdnControllerDisableDHCPMsg extends NeedReplyMessage implements SdnControllerMessage { + private String l3NetworkUuid; + private Integer ipVersion = IPv6Constants.DUAL_STACK; + private String sdnControllerUuid; + private boolean checkIpRange = false; + + public Integer getIpVersion() { + return ipVersion; + } + + public void setIpVersion(Integer ipVersion) { + this.ipVersion = ipVersion; + } + + public String getL3NetworkUuid() { + return l3NetworkUuid; + } + + public void setL3NetworkUuid(String l3NetworkUuid) { + this.l3NetworkUuid = l3NetworkUuid; + } + + @Override + public String getSdnControllerUuid() { + return sdnControllerUuid; + } + + public void setSdnControllerUuid(String sdnControllerUuid) { + this.sdnControllerUuid = sdnControllerUuid; + } + + public boolean isCheckIpRange() { + return checkIpRange; + } + + public void setCheckIpRange(boolean checkIpRange) { + this.checkIpRange = checkIpRange; + } +} + diff --git a/header/src/main/java/org/zstack/header/network/l3/SdnControllerDisableDHCPReply.java b/header/src/main/java/org/zstack/header/network/l3/SdnControllerDisableDHCPReply.java new file mode 100644 index 0000000000..990833e6a7 --- /dev/null +++ b/header/src/main/java/org/zstack/header/network/l3/SdnControllerDisableDHCPReply.java @@ -0,0 +1,6 @@ +package org.zstack.header.network.l3; + +import org.zstack.header.message.MessageReply; + +public class SdnControllerDisableDHCPReply extends MessageReply { +} diff --git a/header/src/main/java/org/zstack/header/network/l3/SdnControllerEnableDHCPMsg.java b/header/src/main/java/org/zstack/header/network/l3/SdnControllerEnableDHCPMsg.java new file mode 100644 index 0000000000..ade67404bd --- /dev/null +++ b/header/src/main/java/org/zstack/header/network/l3/SdnControllerEnableDHCPMsg.java @@ -0,0 +1,26 @@ +package org.zstack.header.network.l3; + +import org.zstack.header.message.NeedReplyMessage; +import org.zstack.header.network.sdncontroller.SdnControllerMessage; + +public class SdnControllerEnableDHCPMsg extends NeedReplyMessage implements SdnControllerMessage { + private String l3NetworkUuid; + private String sdnControllerUuid; + + public String getL3NetworkUuid() { + return l3NetworkUuid; + } + + public void setL3NetworkUuid(String l3NetworkUuid) { + this.l3NetworkUuid = l3NetworkUuid; + } + + @Override + public String getSdnControllerUuid() { + return sdnControllerUuid; + } + + public void setSdnControllerUuid(String sdnControllerUuid) { + this.sdnControllerUuid = sdnControllerUuid; + } +} diff --git a/header/src/main/java/org/zstack/header/network/l3/SdnControllerEnableDHCPReply.java b/header/src/main/java/org/zstack/header/network/l3/SdnControllerEnableDHCPReply.java new file mode 100644 index 0000000000..15cf0701b0 --- /dev/null +++ b/header/src/main/java/org/zstack/header/network/l3/SdnControllerEnableDHCPReply.java @@ -0,0 +1,6 @@ +package org.zstack.header.network.l3; + +import org.zstack.header.message.MessageReply; + +public class SdnControllerEnableDHCPReply extends MessageReply { +} diff --git a/header/src/main/java/org/zstack/header/network/l3/SdnControllerUpdateDHCPMsg.java b/header/src/main/java/org/zstack/header/network/l3/SdnControllerUpdateDHCPMsg.java new file mode 100644 index 0000000000..3cc193a7d2 --- /dev/null +++ b/header/src/main/java/org/zstack/header/network/l3/SdnControllerUpdateDHCPMsg.java @@ -0,0 +1,37 @@ +package org.zstack.header.network.l3; + +import org.zstack.header.message.NeedReplyMessage; +import org.zstack.header.network.sdncontroller.SdnControllerMessage; +import org.zstack.utils.network.IPv6Constants; + +public class SdnControllerUpdateDHCPMsg extends NeedReplyMessage implements SdnControllerMessage { + private String l3NetworkUuid; + private String sdnControllerUuid; + private Integer ipVersion = IPv6Constants.DUAL_STACK; + + @Override + public String getSdnControllerUuid() { + return sdnControllerUuid; + } + + public void setSdnControllerUuid(String sdnControllerUuid) { + this.sdnControllerUuid = sdnControllerUuid; + } + + public String getL3NetworkUuid() { + return l3NetworkUuid; + } + + public void setL3NetworkUuid(String l3NetworkUuid) { + this.l3NetworkUuid = l3NetworkUuid; + } + + public Integer getIpVersion() { + return ipVersion; + } + + public void setIpVersion(Integer ipVersion) { + this.ipVersion = ipVersion; + } +} + diff --git a/header/src/main/java/org/zstack/header/network/l3/SdnControllerUpdateDHCPReply.java b/header/src/main/java/org/zstack/header/network/l3/SdnControllerUpdateDHCPReply.java new file mode 100644 index 0000000000..ddda3d6555 --- /dev/null +++ b/header/src/main/java/org/zstack/header/network/l3/SdnControllerUpdateDHCPReply.java @@ -0,0 +1,6 @@ +package org.zstack.header.network.l3; + +import org.zstack.header.message.MessageReply; + +public class SdnControllerUpdateDHCPReply extends MessageReply { +} diff --git a/header/src/main/java/org/zstack/header/network/service/SdnControllerDhcp.java b/header/src/main/java/org/zstack/header/network/service/SdnControllerDhcp.java index 065d90e17d..c4a482b426 100644 --- a/header/src/main/java/org/zstack/header/network/service/SdnControllerDhcp.java +++ b/header/src/main/java/org/zstack/header/network/service/SdnControllerDhcp.java @@ -24,14 +24,14 @@ public interface SdnControllerDhcp { /** * 启用指定 L3 网络的 DHCP 服务 - * @param l3_min L3 网络索引 - * @param l3_max L3 网络索引 + * @param l3Min L3 网络索引 + * @param l3Max L3 网络索引 * @param invs L3 网络清单列表 * @param sync 是否同步操作 * @param completion 操作完成后的回调 * */ - void enableDhcp(long l3Min, long l3Max, List invs, boolean sync, Completion completion); + void enableDhcp(long l3Min, long l3Max, List invs, Integer ipversion, boolean sync, Completion completion); /** * 启用指定 L3 网络的 DHCP 服务 @@ -39,7 +39,7 @@ public interface SdnControllerDhcp { * @param completion 操作完成后的回调 * */ - void enableDhcp(List invs, Completion completion); + void enableDhcp(List invs, Integer ipversion, Completion completion); /** * 禁用指定 L3 网络的 DHCP 服务 @@ -48,5 +48,5 @@ public interface SdnControllerDhcp { * @param completion 操作完成后的回调 * */ - void disableDhcp(List invs, int ipversion, Completion completion); + void disableDhcp(List invs, Integer ipversion, Completion completion); } diff --git a/header/src/main/java/org/zstack/header/storage/addon/StorageCapacity.java b/header/src/main/java/org/zstack/header/storage/addon/StorageCapacity.java index 59388eaa75..9f2ff79c7d 100644 --- a/header/src/main/java/org/zstack/header/storage/addon/StorageCapacity.java +++ b/header/src/main/java/org/zstack/header/storage/addon/StorageCapacity.java @@ -1,8 +1,29 @@ package org.zstack.header.storage.addon; +import java.util.HashMap; +import java.util.Map; + public class StorageCapacity { + public static class Capacity { + public long total; + public long available; + } + private long totalCapacity; private long availableCapacity; + /*** + * key: location url, it must be unique and consistent anywhere and anytime. + * ZStack use location url to identify different storage locations and generate storage space resource uuid based on it. + * storage space resource uuid = UUID.nameUUIDFromBytes((psUuid + locationUrl).getBytes()).toString() + *

+ * if storage do not support multiple locations, return null or empty map. + * if storage support multiple locations, the location url must be the prefix of volume install url. + * ZStack will retrieve the location url from volume install url to find the corresponding capacity info. + */ + private Map capacitiesByLocationUrl; + + // remove in future versions + @Deprecated private StorageHealthy healthy; public long getTotalCapacity() { @@ -21,6 +42,25 @@ public void setAvailableCapacity(long availableCapacity) { this.availableCapacity = availableCapacity; } + public Map getCapacitiesByLocationUrl() { + return capacitiesByLocationUrl; + } + + public void setCapacitiesByLocationUrl(Map capacitiesByLocationUrl) { + this.capacitiesByLocationUrl = capacitiesByLocationUrl; + } + + public void putCapacity(String locationUrl, long availableCapacity, long totalCapacity) { + if (this.capacitiesByLocationUrl == null) { + this.capacitiesByLocationUrl = new HashMap<>(); + } + + Capacity capacity = new Capacity(); + capacity.available = availableCapacity; + capacity.total = totalCapacity; + this.capacitiesByLocationUrl.put(locationUrl, capacity); + } + public StorageHealthy getHealthy() { return healthy; } diff --git a/header/src/main/java/org/zstack/header/storage/addon/primary/ExternalPrimaryStorageSpaceInventory.java b/header/src/main/java/org/zstack/header/storage/addon/primary/ExternalPrimaryStorageSpaceInventory.java new file mode 100644 index 0000000000..c6236d14fa --- /dev/null +++ b/header/src/main/java/org/zstack/header/storage/addon/primary/ExternalPrimaryStorageSpaceInventory.java @@ -0,0 +1,133 @@ +package org.zstack.header.storage.addon.primary; + +import org.zstack.header.search.Inventory; + +import javax.persistence.*; +import java.io.Serializable; +import java.sql.Timestamp; +import java.util.Collection; +import java.util.List; +import java.util.stream.Collectors; + +@Inventory(mappingVOClass = ExternalPrimaryStorageSpaceVO.class) +public class ExternalPrimaryStorageSpaceInventory implements Serializable { + private String uuid; + private String primaryStorageUuid; + private String locationUrl; + private String type; + private String name; + private Long availableCapacity; + private Long totalCapacity; + private Long availablePhysicalCapacity; + private Long totalPhysicalCapacity; + private Timestamp createDate; + private Timestamp lastOpDate; + + public static ExternalPrimaryStorageSpaceInventory valueOf(ExternalPrimaryStorageSpaceVO vo) { + ExternalPrimaryStorageSpaceInventory inv = new ExternalPrimaryStorageSpaceInventory(); + inv.setUuid(vo.getUuid()); + inv.setPrimaryStorageUuid(vo.getPrimaryStorageUuid()); + inv.setLocationUrl(vo.getLocationUrl()); + inv.setType(vo.getType()); + inv.setName(vo.getName()); + inv.setAvailableCapacity(vo.getAvailableCapacity()); + inv.setTotalCapacity(vo.getTotalCapacity()); + inv.setAvailablePhysicalCapacity(vo.getAvailablePhysicalCapacity()); + inv.setTotalPhysicalCapacity(vo.getTotalPhysicalCapacity()); + inv.setCreateDate(vo.getCreateDate()); + inv.setLastOpDate(vo.getLastOpDate()); + return inv; + } + + public static List valueOf(Collection vos) { + return vos.stream().map(ExternalPrimaryStorageSpaceInventory::valueOf).collect(Collectors.toList()); + } + + public String getUuid() { + return uuid; + } + + public void setUuid(String uuid) { + this.uuid = uuid; + } + + public String getPrimaryStorageUuid() { + return primaryStorageUuid; + } + + public void setPrimaryStorageUuid(String primaryStorageUuid) { + this.primaryStorageUuid = primaryStorageUuid; + } + + public String getLocationUrl() { + return locationUrl; + } + + public void setLocationUrl(String locationUrl) { + this.locationUrl = locationUrl; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Long getAvailableCapacity() { + return availableCapacity; + } + + public void setAvailableCapacity(Long availableCapacity) { + this.availableCapacity = availableCapacity; + } + + public Long getTotalCapacity() { + return totalCapacity; + } + + public void setTotalCapacity(Long totalCapacity) { + this.totalCapacity = totalCapacity; + } + + public Long getAvailablePhysicalCapacity() { + return availablePhysicalCapacity; + } + + public void setAvailablePhysicalCapacity(Long availablePhysicalCapacity) { + this.availablePhysicalCapacity = availablePhysicalCapacity; + } + + public Long getTotalPhysicalCapacity() { + return totalPhysicalCapacity; + } + + public void setTotalPhysicalCapacity(Long totalPhysicalCapacity) { + this.totalPhysicalCapacity = totalPhysicalCapacity; + } + + public Timestamp getCreateDate() { + return createDate; + } + + public void setCreateDate(Timestamp createDate) { + this.createDate = createDate; + } + + public Timestamp getLastOpDate() { + return lastOpDate; + } + + public void setLastOpDate(Timestamp lastOpDate) { + this.lastOpDate = lastOpDate; + } +} \ No newline at end of file diff --git a/header/src/main/java/org/zstack/header/storage/addon/primary/ExternalPrimaryStorageSpaceVO.java b/header/src/main/java/org/zstack/header/storage/addon/primary/ExternalPrimaryStorageSpaceVO.java new file mode 100644 index 0000000000..59473955b8 --- /dev/null +++ b/header/src/main/java/org/zstack/header/storage/addon/primary/ExternalPrimaryStorageSpaceVO.java @@ -0,0 +1,140 @@ +package org.zstack.header.storage.addon.primary; + +import org.zstack.header.storage.primary.PrimaryStorageEO; +import org.zstack.header.vo.ForeignKey; +import org.zstack.header.vo.ToInventory; + +import javax.persistence.*; +import java.sql.Timestamp; + +@Entity +@Table +public class ExternalPrimaryStorageSpaceVO implements ToInventory { + @Column + @Id + private String uuid; + + @Column + @ForeignKey(parentEntityClass = PrimaryStorageEO.class, onDeleteAction = ForeignKey.ReferenceOption.CASCADE) + private String primaryStorageUuid; + + @Column + private String locationUrl; + + @Column + private String type; + + @Column + private String name; + + @Column + private long availableCapacity; + + @Column + private long totalCapacity; + + @Column + private long availablePhysicalCapacity; + + @Column + private long totalPhysicalCapacity; + + @Column + private Timestamp createDate; + @Column + private Timestamp lastOpDate; + + + @PreUpdate + private void preUpdate() { + lastOpDate = null; + } + + public String getUuid() { + return uuid; + } + + public void setUuid(String uuid) { + this.uuid = uuid; + } + + public String getPrimaryStorageUuid() { + return primaryStorageUuid; + } + + public void setPrimaryStorageUuid(String primaryStorageUuid) { + this.primaryStorageUuid = primaryStorageUuid; + } + + public String getLocationUrl() { + return locationUrl; + } + + public void setLocationUrl(String locationUrl) { + this.locationUrl = locationUrl; + } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public long getAvailableCapacity() { + return availableCapacity; + } + + public void setAvailableCapacity(long availableCapacity) { + this.availableCapacity = availableCapacity; + } + + public long getTotalCapacity() { + return totalCapacity; + } + + public void setTotalCapacity(long totalCapacity) { + this.totalCapacity = totalCapacity; + } + + public long getAvailablePhysicalCapacity() { + return availablePhysicalCapacity; + } + + public void setAvailablePhysicalCapacity(long availablePhysicalCapacity) { + this.availablePhysicalCapacity = availablePhysicalCapacity; + } + + public long getTotalPhysicalCapacity() { + return totalPhysicalCapacity; + } + + public void setTotalPhysicalCapacity(long totalPhysicalCapacity) { + this.totalPhysicalCapacity = totalPhysicalCapacity; + } + + public Timestamp getCreateDate() { + return createDate; + } + + public void setCreateDate(Timestamp createDate) { + this.createDate = createDate; + } + + public Timestamp getLastOpDate() { + return lastOpDate; + } + + public void setLastOpDate(Timestamp lastOpDate) { + this.lastOpDate = lastOpDate; + } +} diff --git a/header/src/main/java/org/zstack/header/storage/addon/primary/ExternalPrimaryStorageSpaceVO_.java b/header/src/main/java/org/zstack/header/storage/addon/primary/ExternalPrimaryStorageSpaceVO_.java new file mode 100644 index 0000000000..a09a94b389 --- /dev/null +++ b/header/src/main/java/org/zstack/header/storage/addon/primary/ExternalPrimaryStorageSpaceVO_.java @@ -0,0 +1,19 @@ +package org.zstack.header.storage.addon.primary; + + +import javax.persistence.metamodel.SingularAttribute; +import javax.persistence.metamodel.StaticMetamodel; + +@StaticMetamodel(ExternalPrimaryStorageSpaceVO.class) +public class ExternalPrimaryStorageSpaceVO_ { + + public static volatile SingularAttribute uuid; + public static volatile SingularAttribute primaryStorageUuid; + public static volatile SingularAttribute type; + public static volatile SingularAttribute name; + public static volatile SingularAttribute locationUrl; + public static volatile SingularAttribute availableCapacity; + public static volatile SingularAttribute totalCapacity; + public static volatile SingularAttribute availablePhysicalCapacity; + public static volatile SingularAttribute totalPhysicalCapacity; +} diff --git a/header/src/main/java/org/zstack/header/storage/addon/primary/HeartbeatVolumeTopology.java b/header/src/main/java/org/zstack/header/storage/addon/primary/HeartbeatVolumeTopology.java new file mode 100644 index 0000000000..fb5023c03d --- /dev/null +++ b/header/src/main/java/org/zstack/header/storage/addon/primary/HeartbeatVolumeTopology.java @@ -0,0 +1,26 @@ +package org.zstack.header.storage.addon.primary; + +import java.util.HashMap; +import java.util.Map; + +public class HeartbeatVolumeTopology { + /** + * key: storage space url + * value: heartbeat volume covering the storage space, if the volume has no heartbeat, we should + * treat the storage space as disconnected too. one storage space can only be covered by one heartbeat volume. + * and one heartbeat volume can cover multiple storage spaces. + */ + private Map heartbeatVolumeByCoveringPaths = new HashMap<>(); + + public Map getHeartbeatVolumeByCoveringPaths() { + return heartbeatVolumeByCoveringPaths; + } + + public void setHeartbeatVolumeByCoveringPaths(Map heartbeatVolumeByCoveringPaths) { + this.heartbeatVolumeByCoveringPaths = heartbeatVolumeByCoveringPaths; + } + + public void putHeartbeatVolume(String coveringPath, HeartbeatVolumeTO heartbeatVolumeTO) { + this.heartbeatVolumeByCoveringPaths.put(coveringPath, heartbeatVolumeTO); + } +} diff --git a/header/src/main/java/org/zstack/header/storage/addon/primary/PrimaryStorageControllerSvc.java b/header/src/main/java/org/zstack/header/storage/addon/primary/PrimaryStorageControllerSvc.java index 5d6896960c..48d9b29068 100644 --- a/header/src/main/java/org/zstack/header/storage/addon/primary/PrimaryStorageControllerSvc.java +++ b/header/src/main/java/org/zstack/header/storage/addon/primary/PrimaryStorageControllerSvc.java @@ -1,5 +1,6 @@ package org.zstack.header.storage.addon.primary; +import org.zstack.header.apimediator.ApiMessageInterceptionException; import org.zstack.header.core.Completion; import org.zstack.header.core.ReturnValueCompletion; import org.zstack.header.host.HostInventory; @@ -17,11 +18,14 @@ public interface PrimaryStorageControllerSvc { void connect(String config, String url, ReturnValueCompletion comp); void ping(Completion completion); + void getCapacity(List requiredUrls, ReturnValueCompletion comp); void reportCapacity(ReturnValueCompletion comp); void reportHealthy(ReturnValueCompletion comp); void reportNodeHealthy(HostInventory host, ReturnValueCompletion comp); StorageCapabilities reportCapabilities(); + // TODO: remove this method in future + @Deprecated String allocateSpace(AllocateSpaceSpec aspec); void createVolume(CreateVolumeSpec v, ReturnValueCompletioncomp); @@ -48,7 +52,7 @@ public interface PrimaryStorageControllerSvc { void expungeSnapshot(String installPath, Completion comp); void revertVolumeSnapshot(String snapshotInstallPath, ReturnValueCompletion comp); - void validateConfig(String config); + String validateConfig(String config) throws ApiMessageInterceptionException; void setTrashExpireTime(int timeInSeconds, Completion completion); void onFirstAdditionConfigure(Completion completion); 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 f292e69418..d7a6207cbc 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 @@ -25,11 +25,11 @@ public interface PrimaryStorageNodeSvc { void deployClient(HostInventory h, Completion comp); - void activateHeartbeatVolume(HostInventory h, ReturnValueCompletion comp); + void activateHeartbeatVolume(HostInventory h, ReturnValueCompletion comp); void deactivateHeartbeatVolume(HostInventory h, Completion comp); - HeartbeatVolumeTO getHeartbeatVolumeActiveInfo(HostInventory h); + HeartbeatVolumeTopology getHeartbeatVolumeActiveInfo(HostInventory h); String getIdentity(); } diff --git a/header/src/main/java/org/zstack/header/storage/addon/primary/StorageCapabilities.java b/header/src/main/java/org/zstack/header/storage/addon/primary/StorageCapabilities.java index b2a6b7fe64..e1ca8e8e5c 100644 --- a/header/src/main/java/org/zstack/header/storage/addon/primary/StorageCapabilities.java +++ b/header/src/main/java/org/zstack/header/storage/addon/primary/StorageCapabilities.java @@ -9,10 +9,10 @@ public class StorageCapabilities { private VolumeSnapshotCapability snapshotCapability; + private boolean supportMultiSpace; private boolean supportCloneFromVolume; - + private boolean supportCloneFromAnotherSpace; private boolean supportStorageQos; - private boolean supportLiveExpandVolume; private boolean supportShareableVolume; private boolean supportExportVolumeSnapshot; @@ -68,6 +68,14 @@ public void setSupportCloneFromVolume(boolean supportCloneFromVolume) { this.supportCloneFromVolume = supportCloneFromVolume; } + public boolean isSupportCloneFromAnotherSpace() { + return supportCloneFromAnotherSpace; + } + + public void setSupportCloneFromAnotherSpace(boolean supportCloneFromAnotherSpace) { + this.supportCloneFromAnotherSpace = supportCloneFromAnotherSpace; + } + public List getSupportedImageFormats() { return supportedImageFormats; } @@ -91,4 +99,12 @@ public boolean isSupportLiveExpandVolume() { public void setSupportLiveExpandVolume(boolean supportLiveExpandVolume) { this.supportLiveExpandVolume = supportLiveExpandVolume; } + + public boolean isSupportMultiSpace() { + return supportMultiSpace; + } + + public void setSupportMultiSpace(boolean supportMultiSpace) { + this.supportMultiSpace = supportMultiSpace; + } } diff --git a/header/src/main/java/org/zstack/header/storage/primary/AllocatePrimaryStorageSpaceMsg.java b/header/src/main/java/org/zstack/header/storage/primary/AllocatePrimaryStorageSpaceMsg.java index 7b8543d03f..3413603d29 100644 --- a/header/src/main/java/org/zstack/header/storage/primary/AllocatePrimaryStorageSpaceMsg.java +++ b/header/src/main/java/org/zstack/header/storage/primary/AllocatePrimaryStorageSpaceMsg.java @@ -1,6 +1,10 @@ package org.zstack.header.storage.primary; public class AllocatePrimaryStorageSpaceMsg extends AllocatePrimaryStorageMsg { + /** + * Indicates whether to force allocate primary storage space even if the primary storage + * is marked as full. Because some volume snapshot instantiated before allocated + */ private boolean force; private String requiredInstallUri; diff --git a/header/src/main/java/org/zstack/header/storage/primary/GetOwningVolumePathFromInternalSnapshotMsg.java b/header/src/main/java/org/zstack/header/storage/primary/GetOwningVolumePathFromInternalSnapshotMsg.java new file mode 100644 index 0000000000..8e82eafac9 --- /dev/null +++ b/header/src/main/java/org/zstack/header/storage/primary/GetOwningVolumePathFromInternalSnapshotMsg.java @@ -0,0 +1,27 @@ +package org.zstack.header.storage.primary; + +import org.zstack.header.message.NeedReplyMessage; + +import java.util.List; + +public class GetOwningVolumePathFromInternalSnapshotMsg extends NeedReplyMessage implements PrimaryStorageMessage { + private String primaryStorageUuid; + private List snapshotPaths; + + @Override + public String getPrimaryStorageUuid() { + return primaryStorageUuid; + } + + public void setPrimaryStorageUuid(String primaryStorageUuid) { + this.primaryStorageUuid = primaryStorageUuid; + } + + public List getSnapshotPaths() { + return snapshotPaths; + } + + public void setSnapshotPaths(List snapshotPaths) { + this.snapshotPaths = snapshotPaths; + } +} diff --git a/header/src/main/java/org/zstack/header/storage/primary/GetOwningVolumePathFromInternalSnapshotReply.java b/header/src/main/java/org/zstack/header/storage/primary/GetOwningVolumePathFromInternalSnapshotReply.java new file mode 100644 index 0000000000..0083623318 --- /dev/null +++ b/header/src/main/java/org/zstack/header/storage/primary/GetOwningVolumePathFromInternalSnapshotReply.java @@ -0,0 +1,22 @@ +package org.zstack.header.storage.primary; + +import org.zstack.header.message.MessageReply; + +import java.util.HashMap; +import java.util.Map; + +public class GetOwningVolumePathFromInternalSnapshotReply extends MessageReply { + private Map owningVolumePaths = new HashMap<>(); + + public Map getOwningVolumePaths() { + return owningVolumePaths; + } + + public void setOwningVolumePaths(Map owningVolumePaths) { + this.owningVolumePaths = owningVolumePaths; + } + + public void putOwningVolumePath(String snapshotPath, String volumePath) { + this.owningVolumePaths.put(snapshotPath, volumePath); + } +} diff --git a/header/src/main/java/org/zstack/header/storage/primary/PSCapacityExtensionPoint.java b/header/src/main/java/org/zstack/header/storage/primary/PSCapacityExtensionPoint.java index 6a3eba3cd3..7a86252c67 100644 --- a/header/src/main/java/org/zstack/header/storage/primary/PSCapacityExtensionPoint.java +++ b/header/src/main/java/org/zstack/header/storage/primary/PSCapacityExtensionPoint.java @@ -4,8 +4,27 @@ import org.springframework.transaction.annotation.Transactional; public interface PSCapacityExtensionPoint { - String buildAllocatedInstallUrl(AllocatePrimaryStorageSpaceMsg msg, PrimaryStorageInventory psInv); + /** + * Allocate space dry run, return the installUrl that can be used to allocate space + * note: this method will not actually allocate space, just check whether the space can be allocated, + * and it has no thread safety guarantee, so it is possible that the space can be allocated in dry run, + * but fail in actual allocation. + * @param msg + * @param psInv + * @return installUrl that can be used to allocate space + */ + String allocateSpaceDryRun(AllocatePrimaryStorageSpaceMsg msg, PrimaryStorageInventory psInv); + + /** + * Reserve capacity after space allocation. + * throw exception if failed + * @param msg + * @param allocatedInstallUrl + * @param size + * @param psUuid + * @return the actually reserved size + */ @Transactional(propagation = Propagation.MANDATORY) long reserveCapacity(AllocatePrimaryStorageSpaceMsg msg, String allocatedInstallUrl, long size, String psUuid); diff --git a/header/src/main/java/org/zstack/header/storage/primary/VolumeSnapshotCapability.java b/header/src/main/java/org/zstack/header/storage/primary/VolumeSnapshotCapability.java index 59d63b473c..79050146db 100755 --- a/header/src/main/java/org/zstack/header/storage/primary/VolumeSnapshotCapability.java +++ b/header/src/main/java/org/zstack/header/storage/primary/VolumeSnapshotCapability.java @@ -10,6 +10,11 @@ public static enum VolumeSnapshotArrangementType { CHAIN, INDIVIDUAL } + + public static enum VolumeSnapshotPlacementType { + INTERNAL, + EXTERNAL, + } private boolean support; @@ -28,13 +33,14 @@ public static enum VolumeSnapshotArrangementType { private VolumeSnapshotArrangementType arrangementType; + private VolumeSnapshotPlacementType placementType; + /*** * If volume snapshot is inner snapshot on volume, it must be set. * A regex match volume install path from inner volume snapshot install path. * such as pool/vol from pool/vol@snapshot can be extracted by regex ^[^@]+ */ - // TODO(mj) refactor it - private String volumePathFromInnerSnapshotRegex; + private String volumePathFromInternalSnapshotRegex; public boolean isSupport() { return support; @@ -52,6 +58,14 @@ public void setArrangementType(VolumeSnapshotArrangementType arrangementType) { this.arrangementType = arrangementType; } + public VolumeSnapshotPlacementType getPlacementType() { + return placementType; + } + + public void setPlacementType(VolumeSnapshotPlacementType placementType) { + this.placementType = placementType; + } + public boolean isSupportCreateOnHypervisor() { return supportCreateOnHypervisor; } @@ -68,11 +82,13 @@ public void setSupportLazyDelete(boolean supportLazyDelete) { this.supportLazyDelete = supportLazyDelete; } - public String getVolumePathFromInnerSnapshotRegex() { - return volumePathFromInnerSnapshotRegex; + @Deprecated + public String getVolumePathFromInternalSnapshotRegex() { + return volumePathFromInternalSnapshotRegex; } - public void setVolumePathFromInnerSnapshotRegex(String volumePathFromInnerSnapshotRegex) { - this.volumePathFromInnerSnapshotRegex = volumePathFromInnerSnapshotRegex; + @Deprecated + public void setVolumePathFromInternalSnapshotRegex(String volumePathFromInternalSnapshotRegex) { + this.volumePathFromInternalSnapshotRegex = volumePathFromInternalSnapshotRegex; } } diff --git a/header/src/main/java/org/zstack/header/vm/APIUpdateConsolePasswordEvent.java b/header/src/main/java/org/zstack/header/vm/APIUpdateConsolePasswordEvent.java new file mode 100644 index 0000000000..8e8df9cd1f --- /dev/null +++ b/header/src/main/java/org/zstack/header/vm/APIUpdateConsolePasswordEvent.java @@ -0,0 +1,38 @@ +package org.zstack.header.vm; + +import org.zstack.header.message.APIEvent; +import org.zstack.header.rest.RestResponse; + +/** + * Created by haoyu.ding on 2025/11/19. + */ +@RestResponse(allTo = "inventory") +public class APIUpdateConsolePasswordEvent extends APIEvent { + private VmInstanceInventory inventory; + + public APIUpdateConsolePasswordEvent() { + super(null); + } + + public APIUpdateConsolePasswordEvent(String apiId) { + super(apiId); + } + + public VmInstanceInventory getInventory() { + return inventory; + } + + public void setInventory(VmInstanceInventory inventory) { + this.inventory = inventory; + } + + public static APIUpdateConsolePasswordEvent __example__() { + APIUpdateConsolePasswordEvent event = new APIUpdateConsolePasswordEvent(uuid()); + VmInstanceInventory vm = new VmInstanceInventory(); + vm.setUuid(uuid()); + vm.setName("Test-VM-Updated"); + vm.setState(VmInstanceState.Running.toString()); + event.setInventory(vm); + return event; + } +} \ No newline at end of file diff --git a/header/src/main/java/org/zstack/header/vm/APIUpdateConsolePasswordEventDoc_zh_cn.groovy b/header/src/main/java/org/zstack/header/vm/APIUpdateConsolePasswordEventDoc_zh_cn.groovy new file mode 100644 index 0000000000..06edb77809 --- /dev/null +++ b/header/src/main/java/org/zstack/header/vm/APIUpdateConsolePasswordEventDoc_zh_cn.groovy @@ -0,0 +1,32 @@ +package org.zstack.header.vm + +import org.zstack.header.vm.VmInstanceInventory +import org.zstack.header.errorcode.ErrorCode + +doc { + + title "更新虚拟机控制台密码事件" + + ref { + name "inventory" + path "org.zstack.header.vm.APIUpdateConsolePasswordEvent.inventory" + desc "null" + type "VmInstanceInventory" + since "5.4.2" + clz VmInstanceInventory.class + } + field { + name "success" + desc "" + type "boolean" + since "5.4.2" + } + ref { + name "error" + path "org.zstack.header.vm.APIUpdateConsolePasswordEvent.error" + desc "错误码,若不为null,则表示操作失败, 操作成功时该字段为null",false + type "ErrorCode" + since "5.4.2" + clz ErrorCode.class + } +} diff --git a/header/src/main/java/org/zstack/header/vm/APIUpdateConsolePasswordMsg.java b/header/src/main/java/org/zstack/header/vm/APIUpdateConsolePasswordMsg.java new file mode 100644 index 0000000000..1d5c31917a --- /dev/null +++ b/header/src/main/java/org/zstack/header/vm/APIUpdateConsolePasswordMsg.java @@ -0,0 +1,55 @@ +package org.zstack.header.vm; + +import org.springframework.http.HttpMethod; +import org.zstack.header.identity.Action; +import org.zstack.header.log.NoLogging; +import org.zstack.header.message.APIMessage; +import org.zstack.header.message.APIParam; +import org.zstack.header.rest.RestRequest; + +/** + * Created by haoyu.ding on 2025/11/19. + */ +@Action(category = VmInstanceConstant.ACTION_CATEGORY) +@RestRequest( + path = "/vm-instances/{uuid}/actions", + isAction = true, + method = HttpMethod.PUT, + responseClass = APIUpdateConsolePasswordEvent.class +) +public class APIUpdateConsolePasswordMsg extends APIMessage implements VmInstanceMessage { + @APIParam(resourceType = VmInstanceVO.class, checkAccount = true, operationTarget = true) + private String uuid; + + @APIParam + @NoLogging + private String password; + + @Override + public String getVmInstanceUuid() { + return uuid; + } + + public String getUuid() { + return uuid; + } + + public void setUuid(String uuid) { + this.uuid = uuid; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public static APIUpdateConsolePasswordMsg __example__() { + APIUpdateConsolePasswordMsg msg = new APIUpdateConsolePasswordMsg(); + msg.setUuid(uuid()); + msg.setPassword("new-password-123"); + return msg; + } +} \ No newline at end of file diff --git a/header/src/main/java/org/zstack/header/vm/APIUpdateConsolePasswordMsgDoc_zh_cn.groovy b/header/src/main/java/org/zstack/header/vm/APIUpdateConsolePasswordMsgDoc_zh_cn.groovy new file mode 100644 index 0000000000..9b4a3afacd --- /dev/null +++ b/header/src/main/java/org/zstack/header/vm/APIUpdateConsolePasswordMsgDoc_zh_cn.groovy @@ -0,0 +1,67 @@ +package org.zstack.header.vm + +import org.zstack.header.vm.APIUpdateConsolePasswordEvent + +doc { + title "UpdateConsolePassword" + + category "vmInstance" + + desc """更新虚拟机控制台密码,虚拟机必须处于运行状态且已设置控制台密码""" + + rest { + request { + url "PUT /v1/vm-instances/{uuid}/actions" + + header (Authorization: 'OAuth the-session-uuid') + + clz APIUpdateConsolePasswordMsg.class + + desc """""" + + params { + + column { + name "uuid" + enclosedIn "updateConsolePassword" + desc "资源的UUID,唯一标示该资源" + location "url" + type "String" + optional false + since "5.4.2" + } + column { + name "password" + enclosedIn "updateConsolePassword" + desc "" + location "body" + 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 APIUpdateConsolePasswordEvent.class + } + } +} \ No newline at end of file diff --git a/header/src/main/java/org/zstack/header/vm/UpdateVmConsolePasswordOnHypervisorMsg.java b/header/src/main/java/org/zstack/header/vm/UpdateVmConsolePasswordOnHypervisorMsg.java new file mode 100644 index 0000000000..c008220bd5 --- /dev/null +++ b/header/src/main/java/org/zstack/header/vm/UpdateVmConsolePasswordOnHypervisorMsg.java @@ -0,0 +1,37 @@ +package org.zstack.header.vm; + +import org.zstack.header.host.HostMessage; +import org.zstack.header.log.NoLogging; +import org.zstack.header.message.NeedReplyMessage; + +public class UpdateVmConsolePasswordOnHypervisorMsg extends NeedReplyMessage implements HostMessage { + private String hostUuid; + private String vmInstanceUuid; + @NoLogging + private String password; + + @Override + public String getHostUuid() { + return hostUuid; + } + + public void setHostUuid(String hostUuid) { + this.hostUuid = hostUuid; + } + + public String getVmInstanceUuid() { + return vmInstanceUuid; + } + + public void setVmInstanceUuid(String vmInstanceUuid) { + this.vmInstanceUuid = vmInstanceUuid; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } +} \ No newline at end of file diff --git a/header/src/main/java/org/zstack/header/vm/UpdateVmConsolePasswordOnHypervisorReply.java b/header/src/main/java/org/zstack/header/vm/UpdateVmConsolePasswordOnHypervisorReply.java new file mode 100644 index 0000000000..f85cd1fe51 --- /dev/null +++ b/header/src/main/java/org/zstack/header/vm/UpdateVmConsolePasswordOnHypervisorReply.java @@ -0,0 +1,6 @@ +package org.zstack.header.vm; + +import org.zstack.header.message.MessageReply; + +public class UpdateVmConsolePasswordOnHypervisorReply extends MessageReply { +} \ No newline at end of file diff --git a/header/src/main/java/org/zstack/header/vm/VmInstanceSpec.java b/header/src/main/java/org/zstack/header/vm/VmInstanceSpec.java index 96da4293fa..7007c592ae 100755 --- a/header/src/main/java/org/zstack/header/vm/VmInstanceSpec.java +++ b/header/src/main/java/org/zstack/header/vm/VmInstanceSpec.java @@ -122,6 +122,7 @@ public boolean isRoot() { public static class ImageSpec implements Serializable { private ImageInventory inventory; + // FIXME: not for multi space primary storage private boolean needDownload = true; private ImageBackupStorageRefInventory selectedBackupStorage; @@ -352,6 +353,7 @@ public void setHostname(String hostname) { private boolean ignoreResourceReleaseFailure; private boolean usbRedirect = false; private boolean enableSecurityElement = false; + private Boolean enableHygonSecurityElement; private String enableRDP = "false"; private String VDIMonitorNumber = "1"; @NoLogging @@ -460,6 +462,14 @@ public void setEnableSecurityElement(boolean enableSecurityElement) { this.enableSecurityElement = enableSecurityElement; } + public Boolean isEnableHygonSecurityElement() { + return enableHygonSecurityElement; + } + + public void setEnableHygonSecurityElement(Boolean enableHygonSecurityElement) { + this.enableHygonSecurityElement = enableHygonSecurityElement; + } + public void setCreatePaused(boolean createPaused) { this.createPaused = createPaused; } @@ -788,6 +798,13 @@ public void setRootVolumeSystemTags(List rootVolumeSystemTags) { this.rootVolumeSystemTags = rootVolumeSystemTags; } + public void addRootVolumeSystemTag(String rootVolumeSystemTag) { + if (this.rootVolumeSystemTags == null) { + this.rootVolumeSystemTags = new ArrayList<>(); + } + this.rootVolumeSystemTags.add(rootVolumeSystemTag); + } + public List getDataVolumeSystemTags() { return dataVolumeSystemTags; } 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 b67aea2b6e..b8b017f1d4 100755 --- a/network/src/main/java/org/zstack/network/l2/L2NetworkApiInterceptor.java +++ b/network/src/main/java/org/zstack/network/l2/L2NetworkApiInterceptor.java @@ -27,6 +27,8 @@ import static org.zstack.core.Platform.argerr; import static org.zstack.core.Platform.operr; +import static org.zstack.utils.CollectionDSL.e; +import static org.zstack.utils.CollectionDSL.map; /** * Created with IntelliJ IDEA. @@ -141,6 +143,8 @@ private void validate(APIChangeL2NetworkVlanIdMsg msg) { throw new ApiMessageInterceptionException(argerr("cannot change vlan for l2Network[uuid:%s]" + " because this l2Network is isolated", l2.getUuid())); } + 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 (msg.getVlan() == null) { throw new ApiMessageInterceptionException(argerr("vlan is required for " + @@ -151,15 +155,35 @@ private void validate(APIChangeL2NetworkVlanIdMsg msg) { } List attachedClusters = l2.getAttachedClusterRefs().stream() .map(L2NetworkClusterRefVO::getClusterUuid).collect(Collectors.toList()); - List l2s = SQL.New("select l2" + - " from L2NetworkVO l2, L2NetworkClusterRefVO ref" + - " where l2.virtualNetworkId = :virtualNetworkId" + - " and l2.physicalInterface = :physicalInterface" + - " and ref.clusterUuid in (:clusterUuids)" + - " and l2.type = 'L2VlanNetwork'") - .param("virtualNetworkId", msg.getVlan()) - .param("physicalInterface", l2.getPhysicalInterface()) - .param("clusterUuids", attachedClusters).list(); + List l2s; + if (sdnControllerUuid == null) { + l2s = SQL.New("select l2" + + " from L2NetworkVO l2, L2NetworkClusterRefVO ref" + + " where l2.uuid = ref.l2NetworkUuid" + + " and l2.virtualNetworkId = :virtualNetworkId" + + " and l2.physicalInterface = :physicalInterface" + + " and ref.clusterUuid in (:clusterUuids)" + + " and l2.type = 'L2VlanNetwork'") + .param("virtualNetworkId", msg.getVlan()) + .param("physicalInterface", l2.getPhysicalInterface()) + .param("clusterUuids", attachedClusters).list(); + } else { + l2s = SQL.New("select l2" + + " from L2NetworkVO l2, L2NetworkClusterRefVO ref, SystemTagVO tag" + + " where l2.uuid = ref.l2NetworkUuid" + + " and l2.virtualNetworkId = :virtualNetworkId" + + " and l2.physicalInterface = :physicalInterface" + + " and ref.clusterUuid in (:clusterUuids)" + + " and l2.type = 'L2VlanNetwork'" + + " and tag.resourceUuid=l2.uuid " + + " and tag.resourceType='L2NetworkVO' " + + " and tag.tag=:tag") + .param("virtualNetworkId", msg.getVlan()) + .param("physicalInterface", l2.getPhysicalInterface()) + .param("tag", L2NetworkSystemTags.L2_NETWORK_SDN_CONTROLLER_UUID.instantiateTag( + map(e(L2NetworkSystemTags.L2_NETWORK_SDN_CONTROLLER_UUID_TOKEN, sdnControllerUuid)))) + .param("clusterUuids", attachedClusters).list(); + } l2s = l2s.stream().filter(l -> !l.getUuid().equals(msg.getUuid())).collect(Collectors.toList()); if (!l2s.isEmpty()) { throw new ApiMessageInterceptionException(argerr("There has been a l2Network attached to cluster with virtual network id[%s] and physical interface[%s]. Failed to change L2 network[uuid:%s]", @@ -172,14 +196,31 @@ private void validate(APIChangeL2NetworkVlanIdMsg msg) { } List attachedClusters = l2.getAttachedClusterRefs().stream() .map(L2NetworkClusterRefVO::getClusterUuid).collect(Collectors.toList()); - List l2s = SQL.New("select l2" + - " from L2NetworkVO l2, L2NetworkClusterRefVO ref" + - " where l2.uuid = ref.l2NetworkUuid" + - " and l2.physicalInterface = :physicalInterface" + - " and ref.clusterUuid in (:clusterUuids)" + - " and type = 'L2NoVlanNetwork'") - .param("physicalInterface", l2.getPhysicalInterface()) - .param("clusterUuids", attachedClusters).list(); + List l2s; + if (sdnControllerUuid != null) { + l2s = SQL.New("select l2" + + " from L2NetworkVO l2, L2NetworkClusterRefVO ref, SystemTagVO tag" + + " where l2.uuid = ref.l2NetworkUuid" + + " and l2.physicalInterface = :physicalInterface" + + " and ref.clusterUuid in (:clusterUuids)" + + " and l2.type = 'L2NoVlanNetwork'" + + " and tag.resourceUuid=l2.uuid " + + " and tag.resourceType='L2NetworkVO' " + + " and tag.tag=:tag") + .param("physicalInterface", l2.getPhysicalInterface()) + .param("tag", L2NetworkSystemTags.L2_NETWORK_SDN_CONTROLLER_UUID.instantiateTag( + map(e(L2NetworkSystemTags.L2_NETWORK_SDN_CONTROLLER_UUID_TOKEN, sdnControllerUuid)))) + .param("clusterUuids", attachedClusters).list(); + } else { + l2s = SQL.New("select l2" + + " from L2NetworkVO l2, L2NetworkClusterRefVO ref" + + " where l2.uuid = ref.l2NetworkUuid" + + " and l2.physicalInterface = :physicalInterface" + + " and ref.clusterUuid in (:clusterUuids)" + + " and l2.type = 'L2NoVlanNetwork'") + .param("physicalInterface", l2.getPhysicalInterface()) + .param("clusterUuids", attachedClusters).list(); + } l2s = l2s.stream().filter(l -> !l.getUuid().equals(msg.getUuid())).collect(Collectors.toList()); if (!l2s.isEmpty()) { throw new ApiMessageInterceptionException(argerr("There has been a l2Network attached to cluster that has physical interface[%s]. Failed to change l2Network[uuid:%s]", 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 c3449db014..6adceecec8 100755 --- a/network/src/main/java/org/zstack/network/l2/L2NoVlanNetwork.java +++ b/network/src/main/java/org/zstack/network/l2/L2NoVlanNetwork.java @@ -50,6 +50,8 @@ import static java.util.Arrays.asList; import static org.zstack.core.Platform.*; +import static org.zstack.utils.CollectionDSL.e; +import static org.zstack.utils.CollectionDSL.map; @Configurable(preConstruction = true, autowire = Autowire.BY_TYPE) public class L2NoVlanNetwork implements L2Network { @@ -935,14 +937,30 @@ private void attachL2NetworkToCluster(final AttachL2NetworkToClusterMsg msg, fi protected void scripts() { String type = Q.New(L2NetworkVO.class).select(L2NetworkVO_.type).eq(L2NetworkVO_.uuid, msg.getL2NetworkUuid()).findValue(); - + String sdnControllerUuid = L2NetworkSystemTags.L2_NETWORK_SDN_CONTROLLER_UUID + .getTokenByResourceUuid(msg.getL2NetworkUuid(), L2NetworkSystemTags.L2_NETWORK_SDN_CONTROLLER_UUID_TOKEN); if (L2NetworkConstant.L2_NO_VLAN_NETWORK_TYPE.equals(type)) { - List l2s = SQL.New("select l2" + - " from L2NetworkVO l2, L2NetworkClusterRefVO ref" + - " where l2.uuid = ref.l2NetworkUuid" + - " and ref.clusterUuid = :clusterUuid" + - " and type = 'L2NoVlanNetwork'") - .param("clusterUuid", msg.getClusterUuid()).list(); + List l2s; + if (sdnControllerUuid == null) { + l2s = SQL.New("select l2" + + " from L2NetworkVO l2, L2NetworkClusterRefVO ref" + + " where l2.uuid = ref.l2NetworkUuid" + + " and ref.clusterUuid = :clusterUuid" + + " and type = 'L2NoVlanNetwork'") + .param("clusterUuid", msg.getClusterUuid()).list(); + } else { + l2s = SQL.New("select l2" + + " from L2NetworkVO l2, L2NetworkClusterRefVO ref, SystemTagVO tag" + + " where l2.uuid = ref.l2NetworkUuid" + + " and ref.clusterUuid = :clusterUuid" + + " and l2.type = 'L2NoVlanNetwork'" + + " and tag.resourceUuid=l2.uuid " + + " and tag.resourceType='L2NetworkVO' " + + " and tag.tag=:tag") + .param("tag", L2NetworkSystemTags.L2_NETWORK_SDN_CONTROLLER_UUID.instantiateTag( + map(e(L2NetworkSystemTags.L2_NETWORK_SDN_CONTROLLER_UUID_TOKEN, sdnControllerUuid)))) + .param("clusterUuid", msg.getClusterUuid()).list(); + } if (l2s.isEmpty()) { return; @@ -956,11 +974,26 @@ protected void scripts() { } } } else if (L2NetworkConstant.L2_VLAN_NETWORK_TYPE.equals(type)) { - List l2s = SQL.New("select l2" + - " from L2VlanNetworkVO l2, L2NetworkClusterRefVO ref" + - " where l2.uuid = ref.l2NetworkUuid" + - " and ref.clusterUuid = :clusterUuid") - .param("clusterUuid", msg.getClusterUuid()).list(); + List l2s; + if (sdnControllerUuid == null) { + l2s = SQL.New("select l2" + + " from L2VlanNetworkVO l2, L2NetworkClusterRefVO ref" + + " where l2.uuid = ref.l2NetworkUuid" + + " and ref.clusterUuid = :clusterUuid") + .param("clusterUuid", msg.getClusterUuid()).list(); + } else { + l2s = SQL.New("select l2" + + " from L2VlanNetworkVO l2, L2NetworkClusterRefVO ref, SystemTagVO tag" + + " where l2.uuid = ref.l2NetworkUuid" + + " and ref.clusterUuid = :clusterUuid" + + " and tag.resourceUuid=l2.uuid " + + " and tag.resourceType='L2NetworkVO' " + + " and tag.tag=:tag") + .param("tag", L2NetworkSystemTags.L2_NETWORK_SDN_CONTROLLER_UUID.instantiateTag( + map(e(L2NetworkSystemTags.L2_NETWORK_SDN_CONTROLLER_UUID_TOKEN, sdnControllerUuid)))) + .param("clusterUuid", msg.getClusterUuid()).list(); + } + if (l2s.isEmpty()) { return; } 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 19b9e530a5..4b12079e6e 100755 --- a/network/src/main/java/org/zstack/network/l3/L3BasicNetwork.java +++ b/network/src/main/java/org/zstack/network/l3/L3BasicNetwork.java @@ -13,7 +13,6 @@ import org.zstack.core.componentloader.PluginRegistry; import org.zstack.core.db.*; import org.zstack.core.db.SimpleQuery.Op; -import org.zstack.core.defer.Defer; import org.zstack.core.defer.Deferred; import org.zstack.core.errorcode.ErrorFacade; import org.zstack.core.retry.Retry; @@ -42,6 +41,7 @@ import org.zstack.header.network.l2.L2NetworkConstant; import org.zstack.header.network.l2.L2NetworkVO; import org.zstack.header.network.l3.*; +import org.zstack.header.network.sdncontroller.SdnControllerConstant; import org.zstack.header.network.service.*; import org.zstack.identity.AccountManager; import org.zstack.network.service.NetworkServiceManager; @@ -62,10 +62,8 @@ import javax.persistence.Tuple; import java.math.BigInteger; import java.util.*; -import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; -import static org.codehaus.groovy.runtime.InvokerHelper.asList; import static org.zstack.core.Platform.err; import static org.zstack.utils.CollectionDSL.*; @@ -262,36 +260,28 @@ public void run(IpRangeDeletionExtensionPoint arg) { @Override public void run(FlowTrigger trigger, Map data) { - boolean isLastIpRange = isLastNormalIpRangeOfVersion(msg.getIpRangeUuid(), inv.getIpVersion()); - data.put("isLastIpRange", isLastIpRange); - - if (!self.enableIpAddressAllocation()) { - trigger.next(); - return; - } - - SdnControllerDhcp sdnDhcp = l3NwMgr.getSdnControllerDhcp(self.getUuid()); - if (sdnDhcp == null) { + String sdnControllerUuid = L3NetworkHelper.getSdnControllerUuidFromL3Uuid(self.getUuid()); + if (sdnControllerUuid == null) { trigger.next(); return; } - if (isLastIpRange) { - sdnDhcp.disableDhcp(Collections.singletonList(L3NetworkInventory.valueOf(self)), inv.getIpVersion(), - new Completion(trigger) { - @Override - public void success() { - trigger.next(); - } - - @Override - public void fail(ErrorCode errorCode) { - trigger.fail(errorCode); - } - }); - } else { - trigger.next(); - } + SdnControllerDisableDHCPMsg msg = new SdnControllerDisableDHCPMsg(); + msg.setL3NetworkUuid(self.getUuid()); + msg.setIpVersion(iprvo.getIpVersion()); + msg.setSdnControllerUuid(sdnControllerUuid); + msg.setCheckIpRange(true); + bus.makeTargetServiceIdByResourceUuid(msg, SdnControllerConstant.SERVICE_ID, sdnControllerUuid); + bus.send(msg, new CloudBusCallBack(trigger) { + @Override + public void run(MessageReply reply) { + if (!reply.isSuccess()) { + trigger.fail(reply.getError()); + } else { + trigger.next(); + } + } + }); } }).then(new NoRollbackFlow() { String __name__ = "delete-ip-range"; @@ -304,7 +294,7 @@ public void run(FlowTrigger trigger, Map data) { return; } - boolean isLastIpRange = (boolean) data.get("isLastIpRange"); + boolean isLastIpRange = isLastNormalIpRangeOfVersion(msg.getIpRangeUuid(), inv.getIpVersion()); if (isLastIpRange) { sdnL3.deleteIpRange(inv, new Completion(trigger) { @Override @@ -1237,31 +1227,29 @@ public void run(FlowTrigger trigger, Map data) { @Override public void run(FlowTrigger trigger, Map data) { - if (!self.enableIpAddressAllocation()) { - trigger.next(); - return; - } - - if (sdnDhcp == null) { + String sdnControllerUuid = L3NetworkHelper.getSdnControllerUuidFromL3Uuid(self.getUuid()); + if (sdnControllerUuid == null) { trigger.next(); return; } - List iprs = IpRangeHelper.getNormalIpRanges(self); - if (iprs.isEmpty()) { - trigger.next(); - return; + SdnControllerUpdateDHCPMsg dmsg = new SdnControllerUpdateDHCPMsg(); + if (NetworkUtils.isIpv4Address(msg.getDns())) { + dmsg.setIpVersion(IPv6Constants.IPv4); + } else { + dmsg.setIpVersion(IPv6Constants.IPv6); } - - sdnDhcp.enableDhcp(Collections.singletonList(L3NetworkInventory.valueOf(self)), new Completion(trigger) { + dmsg.setL3NetworkUuid(self.getUuid()); + dmsg.setSdnControllerUuid(sdnControllerUuid); + bus.makeTargetServiceIdByResourceUuid(dmsg, SdnControllerConstant.SERVICE_ID, sdnControllerUuid); + bus.send(dmsg, new CloudBusCallBack(trigger) { @Override - public void success() { - trigger.next(); - } - - @Override - public void fail(ErrorCode errorCode) { - trigger.fail(errorCode); + public void run(MessageReply reply) { + if (!reply.isSuccess()) { + trigger.fail(reply.getError()); + } else { + trigger.next(); + } } }); } @@ -1355,31 +1343,29 @@ public void rollback(FlowRollback trigger, Map data) { @Override public void run(FlowTrigger trigger, Map data) { - if (!self.enableIpAddressAllocation()) { + String sdnControllerUuid = L3NetworkHelper.getSdnControllerUuidFromL3Uuid(self.getUuid()); + if (sdnControllerUuid == null) { trigger.next(); return; } - if (sdnDhcp == null) { - trigger.next(); - return; - } - - List iprs = IpRangeHelper.getNormalIpRanges(self); - if (iprs.isEmpty()) { - trigger.next(); - return; + SdnControllerUpdateDHCPMsg dmsg = new SdnControllerUpdateDHCPMsg(); + if (NetworkUtils.isIpv4Address(msg.getDns())) { + dmsg.setIpVersion(IPv6Constants.IPv4); + } else { + dmsg.setIpVersion(IPv6Constants.IPv6); } - - sdnDhcp.enableDhcp(Collections.singletonList(L3NetworkInventory.valueOf(self)), new Completion(trigger) { - @Override - public void success() { - trigger.next(); - } - + dmsg.setL3NetworkUuid(self.getUuid()); + dmsg.setSdnControllerUuid(sdnControllerUuid); + bus.makeTargetServiceIdByResourceUuid(dmsg, SdnControllerConstant.SERVICE_ID, sdnControllerUuid); + bus.send(dmsg, new CloudBusCallBack(trigger) { @Override - public void fail(ErrorCode errorCode) { - trigger.fail(errorCode); + public void run(MessageReply reply) { + if (!reply.isSuccess()) { + trigger.fail(reply.getError()); + } else { + trigger.next(); + } } }); } 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 7c1ee6da36..80ba293281 100755 --- a/network/src/main/java/org/zstack/network/l3/L3NetworkManagerImpl.java +++ b/network/src/main/java/org/zstack/network/l3/L3NetworkManagerImpl.java @@ -36,7 +36,9 @@ import org.zstack.header.network.l3.datatypes.IpCapacityData; import org.zstack.header.network.service.GetSdnControllerExtensionPoint; import org.zstack.header.network.service.SdnControllerDhcp; +import org.zstack.header.network.sdncontroller.SdnControllerConstant; import org.zstack.header.vm.VmNicInventory; + import org.zstack.header.vm.VmNicVO; import org.zstack.header.vm.VmNicVO_; import org.zstack.header.zone.ZoneVO; @@ -53,7 +55,6 @@ import org.zstack.utils.ExceptionDSL; import org.zstack.utils.ObjectUtils; import org.zstack.utils.Utils; -import org.zstack.utils.gson.JSONObjectUtil; import org.zstack.utils.logging.CLogger; import org.zstack.utils.network.IPv6Constants; import org.zstack.utils.network.IPv6NetworkUtils; @@ -65,7 +66,6 @@ import java.math.BigInteger; import java.util.*; import java.util.concurrent.Callable; -import java.util.stream.Collectors; import static org.zstack.core.Platform.err; import static org.zstack.utils.CollectionDSL.*; @@ -157,38 +157,29 @@ private void handle(final APISetL3NetworkMtuMsg msg) { ); creator.create(); - L3NetworkVO l3Vo = dbf.findByUuid(msg.getL3NetworkUuid(), L3NetworkVO.class); FlowChain chain = FlowChainBuilder.newSimpleFlowChain(); chain.setName("change-l3-network-mtu"); chain.then(new NoRollbackFlow() { @Override public void run(FlowTrigger trigger, Map data) { - if (!l3Vo.enableIpAddressAllocation()) { - trigger.next(); - return; - } - - SdnControllerDhcp dhcp = getSdnControllerDhcp(msg.getL3NetworkUuid()); - if (dhcp == null) { + String sdnControllerUuid = L3NetworkHelper.getSdnControllerUuidFromL3Uuid(msg.getL3NetworkUuid()); + if (sdnControllerUuid == null) { trigger.next(); return; } - List iprs = IpRangeHelper.getNormalIpRanges(l3Vo); - if (iprs.isEmpty()) { - trigger.next(); - return; - } - - dhcp.enableDhcp(Collections.singletonList(L3NetworkInventory.valueOf(l3Vo)), new Completion(trigger) { + SdnControllerUpdateDHCPMsg dmsg = new SdnControllerUpdateDHCPMsg(); + dmsg.setL3NetworkUuid(msg.getL3NetworkUuid()); + dmsg.setSdnControllerUuid(sdnControllerUuid); + bus.makeTargetServiceIdByResourceUuid(dmsg, SdnControllerConstant.SERVICE_ID, sdnControllerUuid); + bus.send(dmsg, new CloudBusCallBack(trigger) { @Override - public void success() { - trigger.next(); - } - - @Override - public void fail(ErrorCode errorCode) { - trigger.fail(errorCode); + public void run(MessageReply reply) { + if (!reply.isSuccess()) { + trigger.fail(reply.getError()); + } else { + trigger.next(); + } } }); } diff --git a/network/src/main/java/org/zstack/network/l3/NormalIpRangeFactory.java b/network/src/main/java/org/zstack/network/l3/NormalIpRangeFactory.java index b27778e644..6b7d70d45e 100644 --- a/network/src/main/java/org/zstack/network/l3/NormalIpRangeFactory.java +++ b/network/src/main/java/org/zstack/network/l3/NormalIpRangeFactory.java @@ -1,30 +1,31 @@ package org.zstack.network.l3; import org.springframework.beans.factory.annotation.Autowired; -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.core.db.Q; import org.zstack.core.db.SQLBatchWithReturn; import org.zstack.core.workflow.SimpleFlowChain; import org.zstack.header.core.Completion; -import org.zstack.header.core.NoErrorCompletion; import org.zstack.header.core.ReturnValueCompletion; -import org.zstack.header.core.WhileDoneCompletion; import org.zstack.header.core.workflow.*; import org.zstack.header.errorcode.ErrorCode; -import org.zstack.header.errorcode.ErrorCodeList; import org.zstack.header.message.APICreateMessage; +import org.zstack.header.message.MessageReply; import org.zstack.header.network.l3.*; +import org.zstack.header.network.sdncontroller.SdnControllerConstant; import org.zstack.header.network.service.SdnControllerDhcp; import org.zstack.utils.CollectionUtils; + import org.zstack.utils.function.ForEachFunction; import org.zstack.utils.network.IPv6Constants; import org.zstack.utils.network.IPv6NetworkUtils; import org.zstack.utils.network.NetworkUtils; import java.util.ArrayList; -import java.util.Collections; import java.util.List; import java.util.Map; @@ -35,6 +36,9 @@ public class NormalIpRangeFactory implements IpRangeFactory { protected PluginRegistry pluginRgty; @Autowired protected L3NetworkManager l3Mgr; + @Autowired + private CloudBus bus; + @Override public IpRangeType getType() { @@ -113,27 +117,25 @@ public void rollback(FlowRollback trigger, Map data) { @Override public void run(FlowTrigger trigger, Map data) { - L3NetworkVO l3vo = dbf.findByUuid(iprs.get(0).getL3NetworkUuid(), L3NetworkVO.class); - if (!l3vo.enableIpAddressAllocation()) { - trigger.next(); - return; - } - - SdnControllerDhcp sdnDhcp = l3Mgr.getSdnControllerDhcp(l3vo.getUuid()); - if (sdnDhcp == null) { + String sdnControllerUuid = L3NetworkHelper.getSdnControllerUuidFromL3Uuid(iprs.get(0).getL3NetworkUuid()); + if (sdnControllerUuid == null) { trigger.next(); return; } - sdnDhcp.enableDhcp(Collections.singletonList(L3NetworkInventory.valueOf(l3vo)), new Completion(trigger) { + SdnControllerUpdateDHCPMsg dmsg = new SdnControllerUpdateDHCPMsg(); + dmsg.setL3NetworkUuid(iprs.get(0).getL3NetworkUuid()); + dmsg.setIpVersion(iprs.get(0).getIpVersion()); + dmsg.setSdnControllerUuid(sdnControllerUuid); + bus.makeTargetServiceIdByResourceUuid(dmsg, SdnControllerConstant.SERVICE_ID, sdnControllerUuid); + bus.send(dmsg, new CloudBusCallBack(trigger) { @Override - public void success() { - trigger.next(); - } - - @Override - public void fail(ErrorCode errorCode) { - trigger.fail(errorCode); + public void run(MessageReply reply) { + if (!reply.isSuccess()) { + trigger.fail(reply.getError()); + } else { + trigger.next(); + } } }); } 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 0dfbb39c1a..90e78646d5 100755 --- a/network/src/main/java/org/zstack/network/service/DhcpExtension.java +++ b/network/src/main/java/org/zstack/network/service/DhcpExtension.java @@ -2,8 +2,11 @@ import org.apache.commons.lang.StringUtils; import org.springframework.beans.factory.annotation.Autowired; +import org.zstack.core.cloudbus.CloudBus; +import org.zstack.core.cloudbus.CloudBusCallBack; import org.zstack.core.componentloader.PluginRegistry; import org.zstack.core.db.Q; + import org.zstack.core.db.SimpleQuery; import org.zstack.core.db.SimpleQuery.Op; import org.zstack.header.Component; @@ -12,11 +15,16 @@ import org.zstack.header.errorcode.ErrorCode; import org.zstack.header.exception.CloudRuntimeException; import org.zstack.header.network.l3.*; +import org.zstack.header.network.sdncontroller.SdnControllerConstant; import org.zstack.header.network.service.*; import org.zstack.header.vm.*; +import org.zstack.header.message.MessageReply; + import org.zstack.header.vm.VmInstanceSpec.HostName; import org.zstack.network.l3.IpRangeHelper; import org.zstack.network.l3.L3NetworkGlobalConfig; +import org.zstack.network.l3.L3NetworkHelper; + import org.zstack.network.l3.L3NetworkManager; import org.zstack.utils.CollectionUtils; import org.zstack.utils.Utils; @@ -43,6 +51,9 @@ public class DhcpExtension extends AbstractNetworkServiceExtension implements Co private PluginRegistry pluginRgty; @Autowired private L3NetworkManager l3Mgr; + @Autowired + private CloudBus bus; + private final Map dhcpBackends = new HashMap(); @@ -395,15 +406,22 @@ public void fail(ErrorCode errorCode) { @Override public void enableNetworkService(L3NetworkVO l3VO, NetworkServiceProviderType providerType, List systemTags, Completion completion) { - SdnControllerDhcp sdnDhcp = l3Mgr.getSdnControllerDhcp(l3VO.getUuid()); - if (sdnDhcp != null) { - List normalIpRange = IpRangeHelper.getNormalIpRanges(l3VO); - if (normalIpRange.isEmpty()) { - completion.success(); - return; - } - - sdnDhcp.allocateDhcpAndEnableDhcp(l3VO, systemTags, completion); + String sdnControllerUuid = L3NetworkHelper.getSdnControllerUuidFromL3Uuid(l3VO.getUuid()); + if (sdnControllerUuid != null) { + SdnControllerEnableDHCPMsg msg = new SdnControllerEnableDHCPMsg(); + msg.setL3NetworkUuid(l3VO.getUuid()); + msg.setSdnControllerUuid(sdnControllerUuid); + bus.makeTargetServiceIdByResourceUuid(msg, SdnControllerConstant.SERVICE_ID, sdnControllerUuid); + bus.send(msg, new CloudBusCallBack(completion) { + @Override + public void run(MessageReply reply) { + if (!reply.isSuccess()) { + completion.fail(reply.getError()); + } else { + completion.success(); + } + } + }); return; } @@ -418,15 +436,22 @@ public void enableNetworkService(L3NetworkVO l3VO, NetworkServiceProviderType pr @Override public void disableNetworkService(L3NetworkVO l3VO, NetworkServiceProviderType providerType, Completion completion) { - SdnControllerDhcp sdnDhcp = l3Mgr.getSdnControllerDhcp(l3VO.getUuid()); - if (sdnDhcp != null) { - List normalIpRange = IpRangeHelper.getNormalIpRanges(l3VO); - if (normalIpRange.isEmpty()) { - completion.success(); - return; - } - - sdnDhcp.disableDhcp(Collections.singletonList(L3NetworkInventory.valueOf(l3VO)), IPv6Constants.DUAL_STACK, completion); + String sdnControllerUuid = L3NetworkHelper.getSdnControllerUuidFromL3Uuid(l3VO.getUuid()); + if (sdnControllerUuid != null) { + SdnControllerDisableDHCPMsg msg = new SdnControllerDisableDHCPMsg(); + msg.setL3NetworkUuid(l3VO.getUuid()); + msg.setSdnControllerUuid(sdnControllerUuid); + bus.makeTargetServiceIdByResourceUuid(msg, SdnControllerConstant.SERVICE_ID, sdnControllerUuid); + bus.send(msg, new CloudBusCallBack(completion) { + @Override + public void run(MessageReply reply) { + if (!reply.isSuccess()) { + completion.fail(reply.getError()); + } else { + completion.success(); + } + } + }); return; } diff --git a/plugin/applianceVm/src/main/java/org/zstack/appliancevm/ApplianceVmBase.java b/plugin/applianceVm/src/main/java/org/zstack/appliancevm/ApplianceVmBase.java index 6f3f6e0924..8d039b0e69 100755 --- a/plugin/applianceVm/src/main/java/org/zstack/appliancevm/ApplianceVmBase.java +++ b/plugin/applianceVm/src/main/java/org/zstack/appliancevm/ApplianceVmBase.java @@ -96,7 +96,7 @@ protected List createBootstrapFlows(HypervisorType hvType) { return flows; } - protected List createAfterConnectNewCreatedVirtualRouterFlows() { + protected List createAfterConnectNewCreatedFlows() { return new ArrayList<>(); } @@ -796,8 +796,8 @@ private FlowChain addBootstrapFlows(FlowChain chain, HypervisorType hvType) { return chain; } - private FlowChain addAfterConnectNewCreatedVirtualRouterFlows(FlowChain chain) { - for (Flow flow : createAfterConnectNewCreatedVirtualRouterFlows()) { + private FlowChain addAfterConnectNewCreatedFlows(FlowChain chain) { + for (Flow flow : createAfterConnectNewCreatedFlows()) { chain.then(flow); } @@ -836,7 +836,7 @@ public void run(FlowTrigger trigger, Map data) { } }); - addAfterConnectNewCreatedVirtualRouterFlows(chain); + addAfterConnectNewCreatedFlows(chain); boolean noRollbackOnFailure = ApplianceVmGlobalProperty.NO_ROLLBACK_ON_POST_FAILURE; chain.noRollback(noRollbackOnFailure); @@ -960,7 +960,7 @@ public void run(FlowTrigger trigger, Map data) { } }); - addAfterConnectNewCreatedVirtualRouterFlows(chain); + addAfterConnectNewCreatedFlows(chain); } boolean noRollbackOnFailure = ApplianceVmGlobalProperty.NO_ROLLBACK_ON_POST_FAILURE; diff --git a/plugin/applianceVm/src/main/java/org/zstack/appliancevm/ApplianceVmCascadeExtension.java b/plugin/applianceVm/src/main/java/org/zstack/appliancevm/ApplianceVmCascadeExtension.java index bef8e06bdd..d2134ad3f8 100755 --- a/plugin/applianceVm/src/main/java/org/zstack/appliancevm/ApplianceVmCascadeExtension.java +++ b/plugin/applianceVm/src/main/java/org/zstack/appliancevm/ApplianceVmCascadeExtension.java @@ -74,6 +74,8 @@ public class ApplianceVmCascadeExtension extends AbstractAsyncCascadeExtension { private PluginRegistry pluginRgty; @Autowired protected ThreadFacade thdf; + @Autowired + private ApplianceVmFacade apvmFacade; private static String NAME = ApplianceVmVO.class.getSimpleName(); @@ -287,10 +289,22 @@ private void handleL2NetworkDetach(CascadeAction action, final Completion comple .map(VmInstanceVO::getUuid).collect(Collectors.toList())).list(); if (!applianceVmVOS.isEmpty()) { - for (ApvmCascadeFilterExtensionPoint ext : pluginRgty.getExtensionList(ApvmCascadeFilterExtensionPoint.class)) { - applianceVmVOS = ext.filterApplianceVmCascade(applianceVmVOS, action, action.getParentIssuer(), l3uuids, - new ArrayList<>(), new ArrayList<>()); + List toMigrateVms = new ArrayList<>(); + Map> apvmsByType = applianceVmVOS.stream() + .collect(Collectors.groupingBy(ApplianceVmVO::getApplianceVmType)); + + for (Map.Entry> entry : apvmsByType.entrySet()) { + ApplianceVmType vmType = ApplianceVmType.valueOf(entry.getKey()); + List vmsOfType = entry.getValue(); + + ApvmCascadeFilterExtensionPoint ext = apvmFacade.getApvmCascadeFilterExtensionPoint(vmType); + if (ext != null) { + vmsOfType = ext.filterApplianceVmCascade(vmsOfType, action, action.getParentIssuer(), l3uuids, + new ArrayList<>(), new ArrayList<>()); + } + toMigrateVms.addAll(vmsOfType); } + applianceVmVOS = toMigrateVms; } if (applianceVmVOS.isEmpty()) { @@ -788,12 +802,32 @@ public String call(L3NetworkInventory arg) { q.setParameter("l3Uuids", l3uuids); List apvms = q.getResultList(); if (!apvms.isEmpty()) { - for (ApvmCascadeFilterExtensionPoint ext : pluginRgty.getExtensionList(ApvmCascadeFilterExtensionPoint.class)) { - apvms = ext.filterApplianceVmCascade(apvms, action, action.getParentIssuer(), l3uuids, - toDeleteNics, toDeleteIps); + List toDeleteVms = new ArrayList<>(); + List vmNics = new ArrayList<>(); + List ips = new ArrayList<>(); + Map> apvmsByType = apvms.stream() + .collect(Collectors.groupingBy(ApplianceVmVO::getApplianceVmType)); + + for (Map.Entry> entry : apvmsByType.entrySet()) { + ApplianceVmType vmType = ApplianceVmType.valueOf(entry.getKey()); + List vmsOfType = entry.getValue(); + + ApvmCascadeFilterExtensionPoint ext = apvmFacade.getApvmCascadeFilterExtensionPoint(vmType); + if (ext != null) { + vmsOfType = ext.filterApplianceVmCascade(vmsOfType, action, action.getParentIssuer(), l3uuids, + vmNics, ips); + if (!vmNics.isEmpty()) { + toDeleteNics.addAll(vmNics); + } + if (!ips.isEmpty()) { + toDeleteIps.addAll(ips); + } + } + toDeleteVms.addAll(vmsOfType); } - if (!apvms.isEmpty()) { - ret = ApplianceVmInventory.valueOf1(apvms); + + if (!toDeleteVms.isEmpty()) { + ret = ApplianceVmInventory.valueOf1(toDeleteVms); } } } else if (IpRangeVO.class.getSimpleName().equals(action.getParentIssuer())) { @@ -857,13 +891,32 @@ public List call() { } } } - for (ApvmCascadeFilterExtensionPoint ext : pluginRgty.getExtensionList(ApvmCascadeFilterExtensionPoint.class)) { - vmvos = ext.filterApplianceVmCascade(vmvos, action, action.getParentIssuer(), ipruuids, - toDeleteNics, toDeleteIps); + + List toDeleteVms = new ArrayList<>(); + Map> vmvosByType = vmvos.stream() + .collect(Collectors.groupingBy(ApplianceVmVO::getApplianceVmType)); + + for (Map.Entry> entry : vmvosByType.entrySet()) { + ApplianceVmType vmType = ApplianceVmType.valueOf(entry.getKey()); + List vmsOfType = entry.getValue(); + List vmNics = new ArrayList<>(); + List ips = new ArrayList<>(); + ApvmCascadeFilterExtensionPoint ext = apvmFacade.getApvmCascadeFilterExtensionPoint(vmType); + if (ext != null) { + vmsOfType = ext.filterApplianceVmCascade(vmsOfType, action, action.getParentIssuer(), ipruuids, + vmNics, ips); + if (!vmNics.isEmpty()) { + toDeleteNics.addAll(vmNics); + } + if (!ips.isEmpty()) { + toDeleteIps.addAll(ips); + } + } + toDeleteVms.addAll(vmsOfType); } - if (!vmvos.isEmpty()) { - ret = ApplianceVmInventory.valueOf1(vmvos); + if (!toDeleteVms.isEmpty()) { + ret = ApplianceVmInventory.valueOf1(toDeleteVms); } } else if (AccountVO.class.getSimpleName().equals(action.getParentIssuer())) { final List auuids = CollectionUtils.transformToList((List) action.getParentIssuerContext(), new Function() { diff --git a/plugin/applianceVm/src/main/java/org/zstack/appliancevm/ApplianceVmFacade.java b/plugin/applianceVm/src/main/java/org/zstack/appliancevm/ApplianceVmFacade.java index 261c1ee638..fa8411218c 100755 --- a/plugin/applianceVm/src/main/java/org/zstack/appliancevm/ApplianceVmFacade.java +++ b/plugin/applianceVm/src/main/java/org/zstack/appliancevm/ApplianceVmFacade.java @@ -43,4 +43,6 @@ public interface ApplianceVmFacade { void attachApplianceVmToHaGroup(String vmUuid, String haGroupUuid); void dettachVmInstanceFromAffinityGroup(String vmUuid); void detachVirtualRouterFromHaGroup(String vmUuid, String haGroupUuid); + + ApvmCascadeFilterExtensionPoint getApvmCascadeFilterExtensionPoint(ApplianceVmType applianceVmType); } 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 9ae61e10c7..4f760dde45 100755 --- a/plugin/applianceVm/src/main/java/org/zstack/appliancevm/ApplianceVmFacadeImpl.java +++ b/plugin/applianceVm/src/main/java/org/zstack/appliancevm/ApplianceVmFacadeImpl.java @@ -40,15 +40,12 @@ import org.zstack.network.service.MtuGetter; import org.zstack.header.vm.hooks.VmInstanceAfterCreateHook; import org.zstack.header.vm.hooks.VmInstanceAfterDestroyHook; -import org.zstack.header.vm.hooks.VmInstanceBeforeCreateHook; import org.zstack.header.vm.hooks.VmInstanceBeforeDestroyHook; import org.zstack.utils.CollectionUtils; import org.zstack.utils.DebugUtils; import org.zstack.utils.Utils; import org.zstack.utils.function.Function; import org.zstack.utils.logging.CLogger; -import org.zstack.utils.zsha2.ZSha2Helper; -import org.zstack.utils.zsha2.ZSha2Info; import javax.persistence.Query; import java.util.*; @@ -88,6 +85,8 @@ public class ApplianceVmFacadeImpl extends AbstractService implements ApplianceV private FlowChainBuilder createApplianceVmWorkFlowBuilder; private Map bootstrapInfoFlowFactories = new HashMap(); private Map l2NetworkGetVniExtensionPointMap = new HashMap<>(); + private Map apvmCascadeFilterExtensionPointMap = new HashMap<>(); + private List nicBootstrapExtensions = Collections.emptyList(); private String OWNER = String.format("ApplianceVm.%s", Platform.getManagementServerId()); @@ -224,6 +223,23 @@ private void populateExtensions() { l2NetworkGetVniExtensionPointMap.put(ext.getL2NetworkVniType(), ext); logger.debug(String.format("add new l2NetworkGetVniExtensionPoint, %s: %s", ext.getL2NetworkVniType(), ext.getClass().getCanonicalName())); } + + for (ApvmCascadeFilterExtensionPoint ext : pluginRgty.getExtensionList(ApvmCascadeFilterExtensionPoint.class)) { + ApplianceVmType type = ext.getApplianceVmType(); + ApvmCascadeFilterExtensionPoint old = apvmCascadeFilterExtensionPointMap.get(type); + if (old != null) { + throw new CloudRuntimeException(String.format("two extensions[%s, %s] declare ApvmCascadeFilterExtensionPoint for appliance vm type[%s]", old.getClass().getName(), ext.getClass().getName(), type)); + } + + apvmCascadeFilterExtensionPointMap.put(type, ext); + logger.debug(String.format("add new apvmCascadeFilterExtensionPoint, %s: %s", type, ext.getClass().getCanonicalName())); + + } + + nicBootstrapExtensions = pluginRgty.getExtensionList(ApplianceVmNicBootstrapExtensionPoint.class); + if (nicBootstrapExtensions == null) { + nicBootstrapExtensions = Collections.emptyList(); + } } private void deployAnsible() { @@ -337,6 +353,13 @@ private List reduceNic(List nics, VmNicInventory return ret; } + private void fillVfNicBootstrapInfo(VmNicInventory nic, ApplianceVmNicTO to) { + to.setBondMode("none"); + for (ApplianceVmNicBootstrapExtensionPoint ext : nicBootstrapExtensions) { + ext.fillNicBootstrapInfo(nic, to); + } + } + @Override public Map prepareBootstrapInformation(VmInstanceSpec spec) { VmNicInventory mgmtNic = null; @@ -376,6 +399,7 @@ public Map prepareBootstrapInformation(VmInstanceSpec spec) { mto.setCategory(l3NetworkVO.getCategory().toString()); mto.setL2type(l2NetworkVO.getType()); mto.setPhysicalInterface(l2NetworkVO.getPhysicalInterface()); + fillVfNicBootstrapInfo(mgmtNic, mto); if (l2NetworkGetVniExtensionPointMap == null || l2NetworkGetVniExtensionPointMap.isEmpty() || l2NetworkGetVniExtensionPointMap.get(l2NetworkVO.getType()) == null) { logger.debug("l2NetworkGetVniExtensionPointMap is null. skip to get vni"); @@ -414,6 +438,7 @@ public Map prepareBootstrapInformation(VmInstanceSpec spec) { t.setL2type(l2NetworkVO.getType()); t.setVni(l2NetworkGetVniExtensionPointMap.get(l2NetworkVO.getType()).getL2NetworkVni(l2NetworkVO.getUuid(), spec.getVmInventory().getHostUuid())); t.setPhysicalInterface(l2NetworkVO.getPhysicalInterface()); + fillVfNicBootstrapInfo(defaultRouteNic, t); t.setMtu(new MtuGetter().getMtu(l3NetworkVO.getUuid())); deviceId ++; extraTos.add(t); @@ -430,6 +455,7 @@ public Map prepareBootstrapInformation(VmInstanceSpec spec) { nto.setL2type(l2NetworkVO.getType()); nto.setVni(l2NetworkGetVniExtensionPointMap.get(l2NetworkVO.getType()).getL2NetworkVni(l2NetworkVO.getUuid(), spec.getVmInventory().getHostUuid())); nto.setPhysicalInterface(l2NetworkVO.getPhysicalInterface()); + fillVfNicBootstrapInfo(nic, nto); nto.setMtu(new MtuGetter().getMtu(l3NetworkVO.getUuid())); extraTos.add(nto); deviceId ++; @@ -622,9 +648,14 @@ public void attachApplianceVmToHaGroup(String vmUuid, String haGroupUuid) { } } + @Override public void detachVirtualRouterFromHaGroup(String vmUuid, String haGroupUuid) { for (ApplianceVmHaExtensionPoint ext : pluginRgty.getExtensionList(ApplianceVmHaExtensionPoint.class)) { ext.detachVirtualRouterFromHaGroup(vmUuid, haGroupUuid); } } + + public ApvmCascadeFilterExtensionPoint getApvmCascadeFilterExtensionPoint(ApplianceVmType type) { + return apvmCascadeFilterExtensionPointMap.get(type); + } } diff --git a/plugin/applianceVm/src/main/java/org/zstack/appliancevm/ApplianceVmHaStatus.java b/plugin/applianceVm/src/main/java/org/zstack/appliancevm/ApplianceVmHaStatus.java index 99a1fd4c7c..9fdf9da37c 100644 --- a/plugin/applianceVm/src/main/java/org/zstack/appliancevm/ApplianceVmHaStatus.java +++ b/plugin/applianceVm/src/main/java/org/zstack/appliancevm/ApplianceVmHaStatus.java @@ -3,5 +3,6 @@ public enum ApplianceVmHaStatus { NoHa, Master, - Backup + Backup, + Fault } diff --git a/plugin/applianceVm/src/main/java/org/zstack/appliancevm/ApplianceVmInventoryDoc_zh_cn.groovy b/plugin/applianceVm/src/main/java/org/zstack/appliancevm/ApplianceVmInventoryDoc_zh_cn.groovy index 18d5a20dbf..f8bce85f6b 100644 --- a/plugin/applianceVm/src/main/java/org/zstack/appliancevm/ApplianceVmInventoryDoc_zh_cn.groovy +++ b/plugin/applianceVm/src/main/java/org/zstack/appliancevm/ApplianceVmInventoryDoc_zh_cn.groovy @@ -43,6 +43,12 @@ doc { type "Integer" since "0.6" } + field { + name "haStatus" + desc "" + type "String" + since "5.4.2" + } field { name "uuid" desc "资源的UUID,唯一标示该资源" @@ -109,6 +115,12 @@ doc { type "String" since "0.6" } + field { + name "architecture" + desc "" + type "String" + since "5.4.2" + } field { name "defaultL3NetworkUuid" desc "" @@ -133,6 +145,12 @@ doc { type "Long" since "0.6" } + field { + name "reservedMemorySize" + desc "" + type "Long" + since "5.4.2" + } field { name "cpuNum" desc "" @@ -185,4 +203,10 @@ doc { since "0.6" clz VolumeInventory.class } + field { + name "guestOsType" + desc "" + type "String" + since "5.4.2" + } } diff --git a/plugin/applianceVm/src/main/java/org/zstack/appliancevm/ApplianceVmNicBootstrapExtensionPoint.java b/plugin/applianceVm/src/main/java/org/zstack/appliancevm/ApplianceVmNicBootstrapExtensionPoint.java new file mode 100644 index 0000000000..ce9173f169 --- /dev/null +++ b/plugin/applianceVm/src/main/java/org/zstack/appliancevm/ApplianceVmNicBootstrapExtensionPoint.java @@ -0,0 +1,7 @@ +package org.zstack.appliancevm; + +import org.zstack.header.vm.VmNicInventory; + +public interface ApplianceVmNicBootstrapExtensionPoint { + void fillNicBootstrapInfo(VmNicInventory nic, ApplianceVmNicTO nicTo); +} diff --git a/plugin/applianceVm/src/main/java/org/zstack/appliancevm/ApplianceVmNicTO.java b/plugin/applianceVm/src/main/java/org/zstack/appliancevm/ApplianceVmNicTO.java index 3f58eacd3a..c9905a7866 100755 --- a/plugin/applianceVm/src/main/java/org/zstack/appliancevm/ApplianceVmNicTO.java +++ b/plugin/applianceVm/src/main/java/org/zstack/appliancevm/ApplianceVmNicTO.java @@ -24,6 +24,7 @@ public class ApplianceVmNicTO { private Integer prefixLength; private String gateway6; private String addressMode; + private String bondMode; public ApplianceVmNicTO(VmNicInventory inv) { for (UsedIpInventory uip : inv.getUsedIps()) { @@ -178,4 +179,12 @@ public String getAddressMode() { public void setAddressMode(String addressMode) { this.addressMode = addressMode; } + + public String getBondMode() { + return bondMode; + } + + public void setBondMode(String bondMode) { + this.bondMode = bondMode; + } } diff --git a/plugin/applianceVm/src/main/java/org/zstack/appliancevm/ApplianceVmSubTypeFactory.java b/plugin/applianceVm/src/main/java/org/zstack/appliancevm/ApplianceVmSubTypeFactory.java index 0f4a9d892f..b0bc0470c7 100755 --- a/plugin/applianceVm/src/main/java/org/zstack/appliancevm/ApplianceVmSubTypeFactory.java +++ b/plugin/applianceVm/src/main/java/org/zstack/appliancevm/ApplianceVmSubTypeFactory.java @@ -10,4 +10,6 @@ public interface ApplianceVmSubTypeFactory { ApplianceVmVO persistApplianceVm(ApplianceVmSpec spec, ApplianceVmVO apvm); void removeApplianceVm(ApplianceVmSpec spec, ApplianceVmVO apvm); + + default void createApplianceNicSpec(ApplianceVmSpec spec) {} } diff --git a/plugin/applianceVm/src/main/java/org/zstack/appliancevm/ApvmCascadeFilterExtensionPoint.java b/plugin/applianceVm/src/main/java/org/zstack/appliancevm/ApvmCascadeFilterExtensionPoint.java index be9ab31b22..cd6d890359 100644 --- a/plugin/applianceVm/src/main/java/org/zstack/appliancevm/ApvmCascadeFilterExtensionPoint.java +++ b/plugin/applianceVm/src/main/java/org/zstack/appliancevm/ApvmCascadeFilterExtensionPoint.java @@ -3,16 +3,35 @@ import org.zstack.core.cascade.CascadeAction; import org.zstack.header.network.l3.UsedIpInventory; import org.zstack.header.vm.VmNicInventory; -import org.zstack.network.service.vip.VipInventory; import java.util.List; /** + * Appliance VM cascade deletion filter extension point - Factory pattern + * Each implementation handles cascade deletion logic for specific appliance VM type + * * Created by weiwang on 22/10/2017 */ public interface ApvmCascadeFilterExtensionPoint { + /** + * Filter appliance VMs that need to be cascade deleted + * + * @param applianceVmVOS appliance VM list to process + * @param action cascade action + * @param parentIssuer parent resource type + * @param parentIssuerUuids parent resource UUID list + * @param toDeleteNics nics to be deleted (output parameter) + * @param toDeleteIps IPs to be deleted (output parameter) + * @return filtered VM list to delete + */ List filterApplianceVmCascade(List applianceVmVOS, CascadeAction action, String parentIssuer, List parentIssuerUuids, List toDeleteNics, List toDeleteIps); + + /** + * Check if this factory supports the specified appliance VM type + * @return true if supported, false otherwise + */ + ApplianceVmType getApplianceVmType(); } diff --git a/plugin/cbd/src/main/java/org/zstack/cbd/CbdConstants.java b/plugin/cbd/src/main/java/org/zstack/cbd/CbdConstants.java deleted file mode 100644 index 4e96f6cf85..0000000000 --- a/plugin/cbd/src/main/java/org/zstack/cbd/CbdConstants.java +++ /dev/null @@ -1,12 +0,0 @@ -package org.zstack.cbd; - -import org.zstack.header.configuration.PythonClass; - -/** - * @author Xingwei Yu - * @date 2024/4/10 23:28 - */ -@PythonClass -public interface CbdConstants { - String MDS_PARAM_MDS_PORT = "mdsPort"; -} diff --git a/plugin/cbd/src/main/java/org/zstack/cbd/Config.java b/plugin/cbd/src/main/java/org/zstack/cbd/Config.java deleted file mode 100644 index 99a08cf62d..0000000000 --- a/plugin/cbd/src/main/java/org/zstack/cbd/Config.java +++ /dev/null @@ -1,28 +0,0 @@ -package org.zstack.cbd; - -import java.util.List; - -/** - * @author Xingwei Yu - * @date 2024/4/2 11:13 - */ -public class Config { - private List mdsUrls; - private String logicalPoolName; - - public List getMdsUrls() { - return mdsUrls; - } - - public void setMdsUrls(List mdsUrls) { - this.mdsUrls = mdsUrls; - } - - public String getLogicalPoolName() { - return logicalPoolName; - } - - public void setLogicalPoolName(String logicalPoolName) { - this.logicalPoolName = logicalPoolName; - } -} diff --git a/plugin/cbd/src/main/java/org/zstack/cbd/kvm/KvmCbdCommands.java b/plugin/cbd/src/main/java/org/zstack/cbd/kvm/KvmCbdCommands.java index 52653a0bc4..e761c33193 100644 --- a/plugin/cbd/src/main/java/org/zstack/cbd/kvm/KvmCbdCommands.java +++ b/plugin/cbd/src/main/java/org/zstack/cbd/kvm/KvmCbdCommands.java @@ -1,9 +1,9 @@ package org.zstack.cbd.kvm; -import org.zstack.cbd.MdsInfo; import org.zstack.kvm.KVMAgentCommands; import java.util.List; +import java.util.Map; /** * @author Xingwei Yu @@ -19,23 +19,10 @@ public static class AgentRsp { public String error; } - public static class KvmUpdateClientConfCmd extends AgentCmd { - private List mdsInfos; - - public List getMdsInfos() { - return mdsInfos; - } - - public void setMdsInfos(List mdsInfos) { - this.mdsInfos = mdsInfos; - } - } - public static class KvmSetupSelfFencerCmd extends AgentCmd { public long interval; public int maxAttempts; - public List coveringPaths; - public String heartbeatUrl; + public Map heartbeatPathByCoveringPaths; public int storageCheckerTimeout; public String hostUuid; public Integer hostId; diff --git a/plugin/cbd/src/main/java/org/zstack/cbd/kvm/KvmCbdNodeServer.java b/plugin/cbd/src/main/java/org/zstack/cbd/kvm/KvmCbdNodeServer.java index 006d726054..d53cfa3bb9 100644 --- a/plugin/cbd/src/main/java/org/zstack/cbd/kvm/KvmCbdNodeServer.java +++ b/plugin/cbd/src/main/java/org/zstack/cbd/kvm/KvmCbdNodeServer.java @@ -19,22 +19,22 @@ import org.zstack.header.host.HostInventory; import org.zstack.header.host.HostVO; import org.zstack.header.message.MessageReply; -import org.zstack.header.storage.addon.primary.HeartbeatVolumeTO; -import org.zstack.header.storage.addon.primary.PrimaryStorageNodeSvc; -import org.zstack.header.storage.addon.primary.ExternalPrimaryStorageHostRefVO; -import org.zstack.header.storage.addon.primary.ExternalPrimaryStorageHostRefVO_; +import org.zstack.header.storage.addon.primary.*; +import org.zstack.header.vm.VmInstanceInventory; +import org.zstack.header.vm.VmInstanceSpec; +import org.zstack.header.volume.VolumeInventory; import org.zstack.header.volume.VolumeProtocol; -import org.zstack.kvm.KVMAgentCommands; -import org.zstack.kvm.KVMHostAsyncHttpCallMsg; -import org.zstack.kvm.KVMHostAsyncHttpCallReply; -import org.zstack.kvm.KvmSetupSelfFencerExtensionPoint; +import org.zstack.kvm.*; import org.zstack.storage.addon.primary.ExternalHostIdGetter; import org.zstack.storage.addon.primary.ExternalPrimaryStorageFactory; import org.zstack.utils.DebugUtils; import org.zstack.utils.Utils; import org.zstack.utils.logging.CLogger; +import java.util.ArrayList; +import java.util.List; import java.util.Map; +import java.util.stream.Collectors; import static org.zstack.core.Platform.operr; @@ -42,7 +42,8 @@ * @author Xingwei Yu * @date 2024/4/9 16:22 */ -public class KvmCbdNodeServer implements Component, KvmSetupSelfFencerExtensionPoint { +public class KvmCbdNodeServer implements Component, KvmSetupSelfFencerExtensionPoint, KVMStartVmExtensionPoint, + KVMConvertVolumeExtensionPoint, KVMDetachVolumeExtensionPoint, KVMAttachVolumeExtensionPoint { private static final CLogger logger = Utils.getLogger(KvmCbdNodeServer.class); @Autowired @@ -74,7 +75,7 @@ public void kvmSetupSelfFencer(KvmSetupSelfFencerParam param, Completion complet FlowChain chain = FlowChainBuilder.newShareFlowChain(); chain.setName(String.format("setup-self-fencer-for-external-primary-storage-%s-on-kvm-%s", param.getPrimaryStorage().getUuid(), host.getUuid())); chain.then(new ShareFlow() { - HeartbeatVolumeTO heartbeatVol; + HeartbeatVolumeTopology heartbeatVolumeTopology; @Override public void setup() { @@ -102,10 +103,10 @@ public void fail(ErrorCode errorCode) { @Override public void run(FlowTrigger trigger, Map data) { - nodeSvc.activateHeartbeatVolume(host, new ReturnValueCompletion(trigger) { + nodeSvc.activateHeartbeatVolume(host, new ReturnValueCompletion(trigger) { @Override - public void success(HeartbeatVolumeTO returnValue) { - heartbeatVol = returnValue; + public void success(HeartbeatVolumeTopology topology) { + heartbeatVolumeTopology = topology; trigger.next(); } @@ -134,10 +135,13 @@ public void run(FlowTrigger trigger, Map data) { KvmSetupSelfFencerCmd cmd = new KvmSetupSelfFencerCmd(); cmd.interval = param.getInterval(); cmd.maxAttempts = param.getMaxAttempts(); - cmd.coveringPaths = heartbeatVol.getCoveringPaths(); - cmd.heartbeatUrl = heartbeatVol.getInstallPath(); + cmd.heartbeatPathByCoveringPaths = heartbeatVolumeTopology + .getHeartbeatVolumeByCoveringPaths().entrySet().stream().collect(Collectors.toMap( + Map.Entry::getKey, it -> it.getValue().getInstallPath() + )); cmd.storageCheckerTimeout = param.getStorageCheckerTimeout(); - cmd.heartbeatRequiredSpace = heartbeatVol.getHeartbeatRequiredSpace(); + cmd.heartbeatRequiredSpace = heartbeatVolumeTopology.getHeartbeatVolumeByCoveringPaths() + .values().iterator().next().getHeartbeatRequiredSpace(); cmd.hostUuid = param.getHostUuid(); cmd.hostId = ref.getHostId(); cmd.strategy = param.getStrategy(); @@ -220,4 +224,89 @@ public void run(MessageReply reply) { } }); } + + private PrimaryStorageNodeSvc getNodeService(VolumeInventory volumeInventory) { + String identity = volumeInventory.getInstallPath().split("://")[0]; + if (!extPsFactory.support(identity)) { + return null; + } + + return extPsFactory.getNodeSvc(volumeInventory.getPrimaryStorageUuid()); + } + + private VolumeTO convertVolumeIfNeeded(VolumeInventory volumeInventory, HostInventory host, VolumeTO volumeTO) { + if (!VolumeProtocol.CBD.name().equals(volumeInventory.getProtocol())) { + return volumeTO; + } + + PrimaryStorageNodeSvc nodeSvc = getNodeService(volumeInventory); + if (nodeSvc == null) { + return volumeTO; + } + + String path = nodeSvc.getActivePath(BaseVolumeInfo.valueOf(volumeInventory), host,false); + volumeTO.setInstallPath(path); + return volumeTO; + } + + @Override + public void beforeAttachVolume(KVMHostInventory host, VmInstanceInventory vm, VolumeInventory volume, KVMAgentCommands.AttachDataVolumeCmd cmd, Map data) { + cmd.setVolume(convertVolumeIfNeeded(volume, host, cmd.getVolume())); + } + + @Override + public void afterAttachVolume(KVMHostInventory host, VmInstanceInventory vm, VolumeInventory volume, KVMAgentCommands.AttachDataVolumeCmd cmd) { + } + + @Override + public void attachVolumeFailed(KVMHostInventory host, VmInstanceInventory vm, VolumeInventory volume, KVMAgentCommands.AttachDataVolumeCmd cmd, ErrorCode err, Map data) { + + } + + @Override + public VolumeTO convertVolumeIfNeed(KVMHostInventory host, VolumeInventory inventory, VolumeTO to) { + return convertVolumeIfNeeded(inventory, host, to); + } + + @Override + public void beforeDetachVolume(KVMHostInventory host, VmInstanceInventory vm, VolumeInventory volume, KVMAgentCommands.DetachDataVolumeCmd cmd) { + cmd.setVolume(convertVolumeIfNeeded(volume, host, cmd.getVolume())); + } + + @Override + public void afterDetachVolume(KVMHostInventory host, VmInstanceInventory vm, VolumeInventory volume, KVMAgentCommands.DetachDataVolumeCmd cmd) { + + } + + @Override + public void detachVolumeFailed(KVMHostInventory host, VmInstanceInventory vm, VolumeInventory volume, KVMAgentCommands.DetachDataVolumeCmd cmd, ErrorCode err) { + + } + + @Override + public void beforeStartVmOnKvm(KVMHostInventory host, VmInstanceSpec spec, KVMAgentCommands.StartVmCmd cmd) { + cmd.setRootVolume(convertVolumeIfNeeded(spec.getDestRootVolume(), host, cmd.getRootVolume())); + + List dtos = new ArrayList<>(); + for (VolumeTO to : cmd.getDataVolumes()) { + for (VolumeInventory vol : spec.getDestDataVolumes()) { + if (vol.getUuid().equals(to.getVolumeUuid())) { + dtos.add(convertVolumeIfNeeded(vol, host, to)); + break; + } + } + } + + cmd.setDataVolumes(dtos); + } + + @Override + public void startVmOnKvmSuccess(KVMHostInventory host, VmInstanceSpec spec) { + + } + + @Override + public void startVmOnKvmFailed(KVMHostInventory host, VmInstanceSpec spec, ErrorCode err) { + + } } 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 562067654c..00dcaebe02 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 @@ -1848,6 +1848,7 @@ public void run(MessageReply reply) { chain.done(new FlowDoneHandler(completion) { @Override public void handle(Map data) { + //TODO: replace with ReleasePrimaryStorageSpaceMsg IncreasePrimaryStorageCapacityMsg imsg = new IncreasePrimaryStorageCapacityMsg(); imsg.setPrimaryStorageUuid(self.getUuid()); imsg.setDiskSize(inv.getSize()); @@ -1944,6 +1945,7 @@ public void run(MessageReply reply) { chain.done(new FlowDoneHandler(coml) { @Override public void handle(Map data) { + // TODO: replace with ReleasePrimaryStorageSpaceMsg IncreasePrimaryStorageCapacityMsg imsg = new IncreasePrimaryStorageCapacityMsg(); imsg.setPrimaryStorageUuid(self.getUuid()); imsg.setDiskSize(inv.getSize()); @@ -2512,7 +2514,7 @@ public void run(final SyncTaskChain chain) { if (cache != null) { final CheckIsBitsExistingCmd cmd = new CheckIsBitsExistingCmd(); - cmd.setInstallPath(ImageCacheUtil.getImageCachePath(cache.toInventory())); + cmd.setInstallPath(ImageCacheUtil.getImageCachePath(cache.getInstallUrl())); httpCall(CHECK_BITS_PATH, cmd, CheckIsBitsExistingRsp.class, new ReturnValueCompletion(chain) { @Override public void success(CheckIsBitsExistingRsp returnValue) { @@ -2527,9 +2529,10 @@ public void success(CheckIsBitsExistingRsp returnValue) { q.add(ImageCacheVO_.imageUuid, Op.EQ, image.getInventory().getUuid()); ImageCacheVO cvo = q.find(); - IncreasePrimaryStorageCapacityMsg imsg = new IncreasePrimaryStorageCapacityMsg(); + ReleasePrimaryStorageSpaceMsg imsg = new ReleasePrimaryStorageSpaceMsg(); imsg.setDiskSize(cvo.getSize()); imsg.setPrimaryStorageUuid(cvo.getPrimaryStorageUuid()); + imsg.setAllocatedInstallUrl(cvo.getInstallUrl()); bus.makeTargetServiceIdByResourceUuid(imsg, PrimaryStorageConstant.SERVICE_ID, cvo.getPrimaryStorageUuid()); bus.send(imsg); dbf.remove(cvo); @@ -3320,7 +3323,8 @@ protected void handle(AskVolumeSnapshotCapabilityMsg msg) { if (VolumeType.Data.toString().equals(volumeType) || VolumeType.Root.toString().equals(volumeType)) { cap.setSupport(true); cap.setArrangementType(VolumeSnapshotArrangementType.INDIVIDUAL); - cap.setVolumePathFromInnerSnapshotRegex("^[^@]+"); + cap.setPlacementType(VolumeSnapshotCapability.VolumeSnapshotPlacementType.INTERNAL); + cap.setVolumePathFromInternalSnapshotRegex("^[^@]+"); } else if (VolumeType.Memory.toString().equals(volumeType)) { cap.setSupport(false); } else { @@ -4722,7 +4726,7 @@ private void deleteImageCacheOnPrimaryStorage(DeleteImageCacheOnPrimaryStorageMs DeleteImageCacheCmd cmd = new DeleteImageCacheCmd(); cmd.setFsId(getSelf().getFsid()); cmd.setUuid(self.getUuid()); - cmd.imagePath = msg.getInstallPath().split("@")[0]; + cmd.imagePath = getVolumePathFromSnapshot(msg.getInstallPath()); cmd.snapshotPath = msg.getInstallPath(); httpCall(DELETE_IMAGE_CACHE, cmd, AgentResponse.class, new ReturnValueCompletion(msg) { @Override @@ -5172,7 +5176,7 @@ public void setup() { boolean fastRevert = VolumeSnapshotGlobalConfig.ENABLE_FAST_REVERT.value(Boolean.class); String snapShotPath = msg.getSnapshot().getPrimaryStorageInstallPath(); // get volume path from snapshot path, just split @ - String volumePath = snapShotPath.split("@")[0]; + String volumePath = getVolumePathFromSnapshot(snapShotPath); final String newVolumePath = makeVolumeInstallPathByTargetPool(Platform.getUuid(), getTargetPoolNameFromAllocatedUrl(snapShotPath)); flow(new NoRollbackFlow() { @@ -5437,7 +5441,7 @@ private void deleteSnapshotOnPrimaryStorage(final DeleteSnapshotOnPrimaryStorage httpCall(DELETE_SNAPSHOT_PATH, cmd, DeleteSnapshotRsp.class, new ReturnValueCompletion(msg) { @Override public void success(DeleteSnapshotRsp returnValue) { - osdHelper.releaseAvailableCapWithRatio(msg.getSnapshot().getPrimaryStorageInstallPath(), msg.getSnapshot().getSize()); + osdHelper.releaseAvailableCapacity(msg.getSnapshot().getPrimaryStorageInstallPath(), msg.getSnapshot().getSize()); bus.reply(msg, reply); completion.done(); } @@ -6078,6 +6082,18 @@ private void handle(GetPrimaryStorageUsageReportMsg msg) { bus.reply(msg, reply); } + @Override + protected void handle(GetOwningVolumePathFromInternalSnapshotMsg msg) { + GetOwningVolumePathFromInternalSnapshotReply reply = new GetOwningVolumePathFromInternalSnapshotReply(); + if (msg.getSnapshotPaths() != null) { + for (String snapshotPath : msg.getSnapshotPaths()) { + reply.putOwningVolumePath(snapshotPath, getVolumePathFromSnapshot(snapshotPath)); + } + } + + bus.reply(msg, reply); + } + protected void handle(CleanUpStorageTrashOnPrimaryStorageMsg msg) { CleanUpStorageTrashOnPrimaryStorageReply reply = new CleanUpStorageTrashOnPrimaryStorageReply(); thdf.singleFlightSubmit(new SingleFlightTask(msg) @@ -6142,6 +6158,10 @@ private String makeCephPath(String originPath) { return String.format("ceph://%s", originPath); } + private static String getVolumePathFromSnapshot(String snapshotPath) { + return snapshotPath.split("@")[0]; + } + protected String getTargetPoolNameFromAllocatedUrl(String allocatedUrl) { if (allocatedUrl == null) { throw new OperationFailureException(operr("allocated url not found")); diff --git a/plugin/ceph/src/main/java/org/zstack/storage/ceph/primary/CephPrimaryStorageFactory.java b/plugin/ceph/src/main/java/org/zstack/storage/ceph/primary/CephPrimaryStorageFactory.java index cb7dde9c5c..a3906011ef 100755 --- a/plugin/ceph/src/main/java/org/zstack/storage/ceph/primary/CephPrimaryStorageFactory.java +++ b/plugin/ceph/src/main/java/org/zstack/storage/ceph/primary/CephPrimaryStorageFactory.java @@ -1249,10 +1249,12 @@ public void preReleaseVmResource(VmInstanceSpec spec, Completion completion) { } @Override - public String buildAllocatedInstallUrl(AllocatePrimaryStorageSpaceMsg msg, PrimaryStorageInventory psInv) { + public String allocateSpaceDryRun(AllocatePrimaryStorageSpaceMsg msg, PrimaryStorageInventory psInv) { if (msg.getRequiredInstallUri() != null) { CephRequiredUrlParser.InstallPath path = CephRequiredUrlParser.getInstallPathFromUri(msg.getRequiredInstallUri()); - checkCephPoolCapacityForNewVolume(path.poolName, msg.getSize(), psInv.getUuid()); + if (!msg.isForce()) { + checkCephPoolCapacityForNewVolume(path.poolName, msg.getSize(), psInv.getUuid()); + } return path.fullPath; } 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 ca72e1a08b..8092ce34d6 100644 --- a/plugin/expon/src/main/java/org/zstack/expon/ExponStorageController.java +++ b/plugin/expon/src/main/java/org/zstack/expon/ExponStorageController.java @@ -91,9 +91,10 @@ public class ExponStorageController implements PrimaryStorageControllerSvc, Prim VolumeSnapshotCapability scap = new VolumeSnapshotCapability(); scap.setSupport(true); scap.setArrangementType(VolumeSnapshotCapability.VolumeSnapshotArrangementType.INDIVIDUAL); + scap.setPlacementType(VolumeSnapshotCapability.VolumeSnapshotPlacementType.INTERNAL); scap.setSupportCreateOnHypervisor(false); scap.setSupportLazyDelete(true); - scap.setVolumePathFromInnerSnapshotRegex("^[^@]+"); + scap.setVolumePathFromInternalSnapshotRegex("^[^@]+"); capabilities.setSnapshotCapability(scap); capabilities.setSupportCloneFromVolume(false); capabilities.setSupportStorageQos(true); @@ -624,7 +625,7 @@ public void blacklist(String installPath, String protocol, HostInventory h, Comp } @Override - public synchronized void activateHeartbeatVolume(HostInventory h, ReturnValueCompletion comp) { + public synchronized void activateHeartbeatVolume(HostInventory h, ReturnValueCompletion comp) { String clientIqn = IscsiUtils.getHostInitiatorName(h.getUuid()); if (clientIqn == null) { throw new RuntimeException(String.format("cannot get host[uuid:%s] initiator name", h.getUuid())); @@ -661,7 +662,9 @@ public synchronized void activateHeartbeatVolume(HostInventory h, ReturnValueCom to.setHostId(getHostId(h)); to.setHeartbeatRequiredSpace(SizeUnit.MEGABYTE.toByte(1)); to.setCoveringPaths(Collections.singletonList(vhostSocketDir)); - comp.success(to); + HeartbeatVolumeTopology topology = new HeartbeatVolumeTopology(); + topology.setHeartbeatVolumeByCoveringPaths(Collections.singletonMap(vhostSocketDir, to)); + comp.success(topology); } // hardcode @@ -703,7 +706,7 @@ public void deactivateHeartbeatVolume(HostInventory h, Completion comp) { } @Override - public HeartbeatVolumeTO getHeartbeatVolumeActiveInfo(HostInventory h) { + public HeartbeatVolumeTopology getHeartbeatVolumeActiveInfo(HostInventory h) { String tianshuId = addonInfo.getClusters().get(0).getId(); List nodes = getIscsiServers(tianshuId); @@ -729,7 +732,10 @@ public HeartbeatVolumeTO getHeartbeatVolumeActiveInfo(HostInventory h) { to.setHostId(getHostId(h)); to.setHeartbeatRequiredSpace(SizeUnit.MEGABYTE.toByte(1)); to.setCoveringPaths(Collections.singletonList(vhostSocketDir)); - return to; + + HeartbeatVolumeTopology topology = new HeartbeatVolumeTopology(); + topology.setHeartbeatVolumeByCoveringPaths(Collections.singletonMap(vhostSocketDir, to)); + return topology; } private void deactivateVhost(String installPath, HostInventory h) { @@ -884,6 +890,26 @@ private void reloadDbInfo() { config = StringUtils.isEmpty(self.getConfig()) ? new ExponConfig() : JSONObjectUtil.toObject(self.getConfig(), ExponConfig.class); } + // TODO: add more not found handling when support multi pool + @Override + public void getCapacity(List locationUrl, ReturnValueCompletion comp) { + List pools = getSelfPools(); + StorageCapacity cap = new StorageCapacity(); + long total = pools.stream().mapToLong(FailureDomainModule::getValidSize).sum(); + long avail = total - pools.stream().mapToLong(FailureDomainModule::getRealDataSize).sum(); + cap.setAvailableCapacity(avail); + cap.setTotalCapacity(total); + for (String url : locationUrl) { + String poolName = getPoolNameFromPath(url); + FailureDomainModule pool = pools.stream().filter(it -> it.getFailureDomainName().equals(poolName)).findFirst().orElse(null); + if (pool != null) { + cap.putCapacity(url, pool.getValidSize() - pool.getRealDataSize(), pool.getValidSize()); + } + } + + comp.success(cap); + } + @Override public void reportCapacity(ReturnValueCompletion comp) { reloadDbInfo(); @@ -1309,8 +1335,8 @@ public void revertVolumeSnapshot(String snapshotInstallPath, ReturnValueCompleti } @Override - public void validateConfig(String config) { - + public String validateConfig(String config) { + return config; } @Override diff --git a/plugin/externalStorage/src/main/java/org/zstack/externalStorage/primary/ExternalPrimaryStorageAllocator.java b/plugin/externalStorage/src/main/java/org/zstack/externalStorage/primary/ExternalPrimaryStorageAllocator.java new file mode 100644 index 0000000000..99b5849d1f --- /dev/null +++ b/plugin/externalStorage/src/main/java/org/zstack/externalStorage/primary/ExternalPrimaryStorageAllocator.java @@ -0,0 +1,128 @@ +package org.zstack.externalStorage.primary; + +import groovy.lang.Tuple; +import org.apache.commons.collections.CollectionUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.zstack.compute.vm.VmAllocateHostAndPrimaryStorageFlow; +import org.zstack.compute.vm.VmAllocateHostFlow; +import org.zstack.core.db.Q; +import org.zstack.externalStorage.primary.kvm.ExternalPrimaryStorageKvmFactory; +import org.zstack.header.core.workflow.Flow; +import org.zstack.header.core.workflow.FlowChain; +import org.zstack.header.core.workflow.FlowTrigger; +import org.zstack.header.core.workflow.NoRollbackFlow; +import org.zstack.header.storage.addon.primary.PrimaryStorageControllerSvc; +import org.zstack.header.storage.addon.primary.StorageCapabilities; +import org.zstack.header.storage.primary.ImageCacheVO; +import org.zstack.header.storage.primary.ImageCacheVO_; +import org.zstack.header.vm.MarshalVmOperationFlowExtensionPoint; +import org.zstack.header.vm.VmInstanceConstant; +import org.zstack.header.vm.VmInstanceSpec; +import org.zstack.storage.addon.primary.ExternalPrimaryStorageFactory; +import org.zstack.storage.addon.primary.ExternalPrimaryStorageSpaceHelper; +import org.zstack.storage.addon.primary.ExternalPrimaryStorageSystemTags; +import org.zstack.storage.primary.ImageCacheUtil; +import org.zstack.utils.Utils; +import org.zstack.utils.logging.CLogger; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import static org.zstack.core.Platform.operr; + +public class ExternalPrimaryStorageAllocator implements MarshalVmOperationFlowExtensionPoint { + private static final CLogger logger = Utils.getLogger(ExternalPrimaryStorageAllocator.class); + + @Autowired + private ExternalPrimaryStorageFactory extPsFactory; + + @Override + public Flow marshalVmOperationFlow(String previousFlowName, String nextFlowName, FlowChain chain, VmInstanceSpec spec) { + if (VmAllocateHostAndPrimaryStorageFlow.class.getName().equals(nextFlowName)) { + if (spec.getCurrentVmOperation() != VmInstanceConstant.VmOperation.NewCreate || !spec.getImageSpec().relyOnImageCache()) { + return null; + } + + if (extPsFactory.getAllControllerSvcs().isEmpty()) { + return null; + } + + List candidatePsUuid = spec.getCandidatePrimaryStorageUuidsForRootVolume(); + List ts = null; + if (candidatePsUuid == null || candidatePsUuid.isEmpty()) { + ts = Q.New(ImageCacheVO.class).select(ImageCacheVO_.primaryStorageUuid, ImageCacheVO_.installUrl) + .eq(ImageCacheVO_.imageUuid, spec.getImageSpec().getInventory().getUuid()) + .listValues(); + candidatePsUuid = ts.stream().map(it -> (String) it.get(0)).distinct().collect(Collectors.toList()); + } + + // TODO only consider the situation that there is only one candidate primary storage such as fast create + if (candidatePsUuid.size() != 1) { + logger.warn(String.format("ExternalPrimaryStorageAllocator only supports one candidate primary storage, found candidates: %s", candidatePsUuid)); + return null; + } + + String requiredPsUuid = candidatePsUuid.get(0); + PrimaryStorageControllerSvc controller = extPsFactory.getControllerSvc(requiredPsUuid); + if (controller == null) { + return null; + } + StorageCapabilities cap = controller.reportCapabilities(); + if (!cap.isSupportMultiSpace() || cap.isSupportCloneFromAnotherSpace()) { + return null; + } + + List rootSysTags = spec.getRootVolumeSystemTags(); + List cacheInstallUrls = new ArrayList<>(); + if (ts != null) { + for (Tuple t : ts) { + if (requiredPsUuid.equals(t.get(0))) { + cacheInstallUrls.add(ImageCacheUtil.getImageCachePath((String) t.get(1))); + } + } + } else { + cacheInstallUrls = Q.New(ImageCacheVO.class).select(ImageCacheVO_.installUrl) + .eq(ImageCacheVO_.imageUuid, spec.getImageSpec().getInventory().getUuid()) + .eq(ImageCacheVO_.primaryStorageUuid, requiredPsUuid) + .listValues().stream().map(it -> ImageCacheUtil.getImageCachePath((String) it)).collect(Collectors.toList()); + } + if (cacheInstallUrls.isEmpty()) { + logger.warn(String.format("no candidate URLs found for image cache[uuid:%s] on primary storage[uuid:%s]", + spec.getImageSpec().getInventory().getUuid(), requiredPsUuid)); + return null; + } + + ExternalPrimaryStorageSpaceHelper helper = new ExternalPrimaryStorageSpaceHelper(requiredPsUuid, controller.getIdentity()); + List candidateUrls = cacheInstallUrls.stream() + .map(helper::getLocationSpaceUrl) + .collect(Collectors.toList()); + + String requiredUrlTag = rootSysTags == null ? null : + rootSysTags.stream().filter(ExternalPrimaryStorageSystemTags.REQUIRED_INSTALL_URL::isMatch).findFirst().orElse(null); + if (requiredUrlTag != null) { + String requiredUrl = ExternalPrimaryStorageSystemTags.REQUIRED_INSTALL_URL.getTokenByTag( + requiredUrlTag, ExternalPrimaryStorageSystemTags.REQUIRED_INSTALL_URL_TOKEN).replaceAll("/$", ""); + if (candidateUrls.contains(requiredUrl)) { + return null; + } else { + return new NoRollbackFlow() { + @Override + public void run(FlowTrigger trigger, Map data) { + trigger.fail(operr("creation relies on image cache[uuid:%s, locate urls: [%s]], cannot create other places.", spec.getImageSpec().getInventory().getUuid(), candidateUrls)); + + } + }; + } + } else { + spec.addRootVolumeSystemTag(ExternalPrimaryStorageSystemTags.REQUIRED_INSTALL_URL.instantiateTag( + Collections.singletonMap(ExternalPrimaryStorageSystemTags.REQUIRED_INSTALL_URL_TOKEN, candidateUrls.get(0))) + ); + } + } + + return null; + } +} diff --git a/plugin/externalStorage/src/main/java/org/zstack/externalStorage/primary/ExternalStorageFencerType.java b/plugin/externalStorage/src/main/java/org/zstack/externalStorage/primary/ExternalStorageFencerType.java index 50031d7b4e..5213c81482 100644 --- a/plugin/externalStorage/src/main/java/org/zstack/externalStorage/primary/ExternalStorageFencerType.java +++ b/plugin/externalStorage/src/main/java/org/zstack/externalStorage/primary/ExternalStorageFencerType.java @@ -8,12 +8,14 @@ * @author Xingwei Yu * @date 2024/8/21 10:38 */ +// TODO refactor it, use controller interface not this fencer type class public class ExternalStorageFencerType { private static Map types = Collections.synchronizedMap(new HashMap()); private final String identity; private final String protocol; + // TODO: refactor it, remove protocol public ExternalStorageFencerType(String identity, String protocol) { if (types.containsKey(identity)) { throw new IllegalArgumentException(String.format("duplicate ExternalStorageNodeServer for identity[%s]", identity)); 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 e8b55f2343..c6eb04a855 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 @@ -131,7 +131,12 @@ public void run(FlowTrigger trigger, Map data) { deployClient(context, extPss, new WhileDoneCompletion(trigger) { @Override public void done(ErrorCodeList errorCodeList) { - trigger.next(); + if (errorCodeList.getCauses().isEmpty()) { + trigger.next(); + } else { + // todo rollback + trigger.fail(errorCodeList.getCauses().get(0)); + } } }); } 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 2300f17cae..7daff5e7b4 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 @@ -39,7 +39,11 @@ import org.zstack.header.network.l2.L2NetworkInventory; import org.zstack.header.network.l2.L2NetworkVO; import org.zstack.header.network.l3.*; +import org.zstack.header.network.l3.SdnControllerUpdateDHCPMsg; +import org.zstack.header.network.sdncontroller.SdnControllerConstant; import org.zstack.header.network.service.*; +import org.zstack.network.l3.L3NetworkHelper; + import org.zstack.header.vm.*; import org.zstack.header.vm.VmAbnormalLifeCycleStruct.VmAbnormalLifeCycleOperation; import org.zstack.identity.AccountManager; @@ -363,21 +367,24 @@ public void fail(ErrorCode errorCode) { @Override public void run(FlowTrigger trigger, Map data) { - if (sdnDhcp == null) { + String sdnControllerUuid = L3NetworkHelper.getSdnControllerUuidFromL3Uuid(l3VO.getUuid()); + if (sdnControllerUuid == null) { trigger.next(); return; } - sdnDhcp.enableDhcp(Collections.singletonList(L3NetworkInventory.valueOf(l3VO)), - new Completion(trigger) { + SdnControllerUpdateDHCPMsg dmsg = new SdnControllerUpdateDHCPMsg(); + dmsg.setL3NetworkUuid(l3VO.getUuid()); + dmsg.setSdnControllerUuid(sdnControllerUuid); + bus.makeTargetServiceIdByResourceUuid(dmsg, SdnControllerConstant.SERVICE_ID, sdnControllerUuid); + bus.send(dmsg, new CloudBusCallBack(trigger) { @Override - public void success() { - trigger.next(); - } - - @Override - public void fail(ErrorCode errorCode) { - trigger.fail(errorCode); + public void run(MessageReply reply) { + if (!reply.isSuccess()) { + trigger.fail(reply.getError()); + } else { + trigger.next(); + } } }); } diff --git a/plugin/iscsi/src/main/java/org/zstack/iscsi/kvm/KvmIscsiNodeServer.java b/plugin/iscsi/src/main/java/org/zstack/iscsi/kvm/KvmIscsiNodeServer.java index 31dddaa078..5ed3af6d28 100644 --- a/plugin/iscsi/src/main/java/org/zstack/iscsi/kvm/KvmIscsiNodeServer.java +++ b/plugin/iscsi/src/main/java/org/zstack/iscsi/kvm/KvmIscsiNodeServer.java @@ -9,7 +9,6 @@ import org.zstack.core.db.Q; import org.zstack.core.workflow.FlowChainBuilder; import org.zstack.core.workflow.ShareFlow; -import org.zstack.externalStorage.primary.ExternalStorageConstant; import org.zstack.header.Component; import org.zstack.header.core.Completion; import org.zstack.header.core.ReturnValueCompletion; @@ -23,6 +22,7 @@ import org.zstack.header.message.MessageReply; import org.zstack.header.storage.addon.primary.BaseVolumeInfo; import org.zstack.header.storage.addon.primary.HeartbeatVolumeTO; +import org.zstack.header.storage.addon.primary.HeartbeatVolumeTopology; import org.zstack.header.storage.addon.primary.PrimaryStorageNodeSvc; import org.zstack.header.vm.VmInstanceInventory; import org.zstack.header.vm.VmInstanceMigrateExtensionPoint; @@ -213,10 +213,11 @@ public void setup() { @Override public void run(FlowTrigger trigger, Map data) { - nodeSvc.activateHeartbeatVolume(host, new ReturnValueCompletion(trigger) { + nodeSvc.activateHeartbeatVolume(host, new ReturnValueCompletion(trigger) { @Override - public void success(HeartbeatVolumeTO vol) { - heartbeatVol = vol; + public void success(HeartbeatVolumeTopology topology) { + // TODO handle multiple heartbeat volumes + heartbeatVol = topology.getHeartbeatVolumeByCoveringPaths().values().iterator().next(); trigger.next(); } 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 91e5d885bd..cf977cf23d 100755 --- a/plugin/kvm/src/main/java/org/zstack/kvm/KVMAgentCommands.java +++ b/plugin/kvm/src/main/java/org/zstack/kvm/KVMAgentCommands.java @@ -1,6 +1,7 @@ package org.zstack.kvm; import com.fasterxml.jackson.annotation.JsonAnySetter; +import org.jetbrains.annotations.NotNull; import org.zstack.core.upgrade.GrayUpgradeAgent; import org.zstack.core.upgrade.GrayVersion; import org.zstack.core.validation.ConditionalValidation; @@ -992,6 +993,17 @@ public void setMldVersion(Integer mldVersion) { public static class CreateBridgeResponse extends AgentResponse { } + public static class SetVmConsolePasswordLiveCmd extends AgentCommand implements Serializable { + private String vmUuid; + @NoLogging + private String password; + + public String getVmUuid() { return vmUuid; } + public void setVmUuid(String vmUuid) { this.vmUuid = vmUuid; } + public String getPassword() { return password; } + public void setPassword(String password) { this.password = password; } + } + public static class UpdateL2NetworkCmd extends AgentCommand { private String physicalInterfaceName; private String bridgeName; @@ -1208,6 +1220,7 @@ public static class NicTO extends BaseVirtualDeviceTO { // only for vf nic private String vlanId; private String pciDeviceAddress; + private List extraPciDeviceAddresses; // only for tf nic private String ipForTf; private String l2NetworkUuid; @@ -1315,6 +1328,14 @@ public void setPciDeviceAddress(String pciDeviceAddress) { this.pciDeviceAddress = pciDeviceAddress; } + public List getExtraPciDeviceAddresses() { + return extraPciDeviceAddresses; + } + + public void setExtraPciDeviceAddresses(List extraPciDeviceAddresses) { + this.extraPciDeviceAddresses = extraPciDeviceAddresses; + } + public Integer getMtu() { return mtu; } @@ -2289,6 +2310,9 @@ public static class StartVmCmd extends vdiCmd implements VmAddOnsCmd { @GrayVersion(value = "5.0.0") private List oemStrings = new ArrayList<>(); + @GrayVersion(value = "5.4.0") + private Long HostMinimumFreeMemorySize; + // TODO: only for test @GrayVersion(value = "5.0.0") private boolean useColoBinary; @@ -2297,6 +2321,9 @@ public static class StartVmCmd extends vdiCmd implements VmAddOnsCmd { @GrayVersion(value = "5.0.0") private Boolean qemu64BitPciMmioSetup; + @GrayVersion(value = "5.5.0") + private Boolean enableHygonSecurityElement; + public Boolean getQemu64BitPciMmioSetup() { return qemu64BitPciMmioSetup; } @@ -2500,6 +2527,15 @@ public boolean isEnableSecurityElement() { public void setEnableSecurityElement(boolean enableSecurityElement) { this.enableSecurityElement = enableSecurityElement; } + + public Boolean isEnableHygonSecurityElement() { + return enableHygonSecurityElement; + } + + public void setEnableHygonSecurityElement(Boolean enableHygonSecurityElement) { + this.enableHygonSecurityElement = enableHygonSecurityElement; + } + public boolean isUseNuma() { return useNuma; } @@ -2856,6 +2892,14 @@ public String getVmCpuVendorId() { public void setVmCpuVendorId(String vmCpuVendorId) { this.vmCpuVendorId = vmCpuVendorId; } + + public Long getHostMinimumFreeMemorySize() { + return HostMinimumFreeMemorySize; + } + + public void setHostMinimumFreeMemorySize(Long hostMinimumFreeMemorySize) { + HostMinimumFreeMemorySize = hostMinimumFreeMemorySize; + } } public static class StartVmResponse extends VmDevicesInfoResponse { @@ -4848,14 +4892,28 @@ public static class OvsAddPortCmd extends AgentCommand { public Boolean reInstall; @GrayVersion(value = "5.4.0") public Map nicMap = new HashMap<>(); + @GrayVersion(value = "5.4.0") + public Map nicVmInstanceUuidMap = new HashMap<>(); } public static class OvsAddPortRsp extends AgentResponse { } + public static class OvsSyncPortCmd extends AgentCommand { + @GrayVersion(value = "5.4.0") + public String vSwitchType; + @GrayVersion(value = "5.4.0") + public Map nicMap = new HashMap<>(); + @GrayVersion(value = "5.4.0") + public String vmUuid; + } + + public static class OvsSyncPortRsp extends AgentResponse { + } + public static class OvsDelPortCmd extends AgentCommand { @GrayVersion(value = "5.4.0") - public String vswitchType; + public String vSwitchType; @GrayVersion(value = "5.4.0") public Map nicMap = new HashMap<>(); } @@ -4863,6 +4921,55 @@ public static class OvsDelPortCmd extends AgentCommand { public static class OvsDelPortRsp extends AgentResponse { } + public static class OvsSetDbConnectionCmd extends AgentCommand { + @GrayVersion(value = "5.5.0") + public boolean refreshCache; + @GrayVersion(value = "5.5.0") + public List nodes; + } + + public static class OvsSetDbConnectionRsp extends AgentResponse { + } + + public static class OvsCheckPortCmd extends AgentCommand { + @GrayVersion(value = "5.4.0") + public String vSwitchType; + // TODO: only for test + @GrayVersion(value = "5.4.0") + public String hostUuid; + } + + public static class OvsCheckPortRsp extends AgentResponse { + //vm uuid to all of its nics in the ovs bridge of the host + @GrayVersion(value = "5.4.0") + public Map> vmNicsMap = new HashMap<>(); + //vnic name to vm uuid map + @GrayVersion(value = "5.4.0") + public Map vnicVmMap = new HashMap<>(); + @GrayVersion(value = "5.4.0") + public Map> lspRequestedChassisMap = new HashMap<>(); + } + + public static class OvsSetRequestedChassisCmd extends AgentCommand { + @GrayVersion(value = "5.4.0") + public String vSwitchType; + @GrayVersion(value = "5.4.0") + public Map> lspRequestedChassisMap = new HashMap<>(); + } + + public static class OvsSetRequestedChassisRsp extends AgentResponse {} + + public static class OvsSyncVmPortsCmd extends AgentCommand { + @GrayVersion(value = "5.4.0") + public String vSwitchType; + @GrayVersion(value = "5.4.0") + public Map nicVmInstanceUuidMap = new HashMap<>(); + @GrayVersion(value = "5.4.0") + public Map nicNamePciAddressMap = new HashMap<>(); + @GrayVersion(value = "5.4.0") + public Map nicNameDriverMap = new HashMap<>(); + } + public static class HardwareMonitorCmd extends KVMAgentCommands.AgentCommand { } 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 f40157764e..1b2df9f8f2 100755 --- a/plugin/kvm/src/main/java/org/zstack/kvm/KVMConstant.java +++ b/plugin/kvm/src/main/java/org/zstack/kvm/KVMConstant.java @@ -41,7 +41,11 @@ public interface KVMConstant { String KVM_START_OVS_SERVICE_PATH = "/network/ovn/start"; String KVM_STOP_OVS_SERVICE_PATH = "/network/ovn/stop"; String KVM_OVS_ADD_PORT_PATH = "/network/ovn/addport"; + String KVM_OVS_SYNC_PORT_PATH = "/network/ovn/syncports"; String KVM_OVS_DEL_PORT_PATH = "/network/ovn/delport"; + String KVM_OVS_SET_DB_CONNECTION_PATH = "/network/ovn/controller/setConnection"; + String KVM_OVS_CHECK_LOCAL_PORT_PATH = "/network/ovn/checklocalport"; + String KVM_OVS_SET_REQUESTED_CHASSIS_PATH = "/network/ovn/setrequestedchassis"; String KVM_ATTACH_ISO_PATH = "/vm/iso/attach"; String KVM_DETACH_ISO_PATH = "/vm/iso/detach"; String KVM_SYNC_VM_DEVICEINFO_PATH = "/sync/vm/deviceinfo"; @@ -65,6 +69,7 @@ public interface KVMConstant { String KVM_DETACH_NIC_PATH = "/vm/detachnic"; String KVM_CHANGE_NIC_STATE_PATH = "/vm/changenicstate"; String KVM_UPDATE_NIC_PATH = "/vm/updatenic"; + String KVM_SET_VF_NIC_MAC_PATH = "/vm/setvfnicmac"; String KVM_VM_CHECK_STATE = "/vm/checkstate"; String KVM_VM_UPDATE_PRIORITY_PATH = "/vm/priority"; String KVM_TAKE_VOLUME_SNAPSHOT_PATH = "/vm/volume/takesnapshot"; @@ -121,6 +126,7 @@ public interface KVMConstant { String KVM_BLOCK_COMMIT_VOLUME_PATH = "/vm/volume/blockcommit"; 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 KVM_HOST_IPSET_ATTACH_NIC_PATH = "/network/ipset/attach"; String KVM_HOST_IPSET_DETACH_NIC_PATH = "/network/ipset/detach"; diff --git a/plugin/kvm/src/main/java/org/zstack/kvm/KVMGlobalConfig.java b/plugin/kvm/src/main/java/org/zstack/kvm/KVMGlobalConfig.java index aa0fd787be..f4691e6fb0 100755 --- a/plugin/kvm/src/main/java/org/zstack/kvm/KVMGlobalConfig.java +++ b/plugin/kvm/src/main/java/org/zstack/kvm/KVMGlobalConfig.java @@ -140,4 +140,9 @@ public class KVMGlobalConfig { @GlobalConfigValidation public static GlobalConfig KVMAGENT_PHYSICAL_MEMORY_USAGE_HARD_LIMIT = new GlobalConfig(CATEGORY, "kvmagent.physicalmemory.usage.hardlimit"); + + @GlobalConfigDef(defaultValue = "0G", description = "minimum free memory size to start vm, size in GB") + @BindResourceConfig({HostVO.class, ClusterVO.class}) + public static GlobalConfig MINIMUM_MEMORY_SIZE_BEFORE_START_VM = new GlobalConfig(CATEGORY, "min.free.memory.size"); + } 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 ab8c29640f..c82a8ba8ae 100755 --- a/plugin/kvm/src/main/java/org/zstack/kvm/KVMHost.java +++ b/plugin/kvm/src/main/java/org/zstack/kvm/KVMHost.java @@ -565,13 +565,8 @@ void runBeforeAsyncJsonPostExts(Map header) { } } - if (commandStr.equals("{}")) { - commandStr = commandStr.replaceAll("\\}$", - String.format("\"%s\":%s}", KVMConstant.KVM_HOST_ADDONS, JSONObjectUtil.toJsonString(kvmHostAddon))); - } else { - commandStr = commandStr.replaceAll("\\}$", - String.format(",\"%s\":%s}", KVMConstant.KVM_HOST_ADDONS, JSONObjectUtil.toJsonString(kvmHostAddon))); - } + commandMap.put(KVMConstant.KVM_HOST_ADDONS, kvmHostAddon); + commandStr = JSONObjectUtil.toJsonString(commandMap); } } @@ -704,6 +699,8 @@ protected void handleLocalMessage(Message msg) { handle((TakeVmConsoleScreenshotMsg) msg); } else if (msg instanceof RestartKvmAgentMsg) { handle((RestartKvmAgentMsg) msg); + } else if (msg instanceof UpdateVmConsolePasswordOnHypervisorMsg) { + handle((UpdateVmConsolePasswordOnHypervisorMsg) msg); } else { super.handleLocalMessage(msg); } @@ -4369,6 +4366,27 @@ protected void startVm(final VmInstanceSpec spec, final NeedReplyMessage msg, fi cmd.setUseNuma(rcf.getResourceConfigValue(VmGlobalConfig.NUMA, spec.getVmInventory().getUuid(), Boolean.class)); setStartVmCpuTopology(spec, cmd, platform); + String value = KVMGlobalConfig.MINIMUM_MEMORY_SIZE_BEFORE_START_VM.value(); + value = value.toUpperCase(); + if (value.endsWith("GB")) { + value = value.substring(0, value.length() - 2); + } else if (value.endsWith("G")) { + value = value.substring(0, value.length() - 1); + } + + Long minMemSize = 0L; + try { + minMemSize = Long.parseLong(value); + // Convert GB to bytes (1GB = 1024 * 1024 * 1024 bytes) + minMemSize = minMemSize * 1024 * 1024 * 1024; + } catch (NumberFormatException e) { + logger.warn(String.format("Invalid memory size format: %s, using default", + KVMGlobalConfig.MINIMUM_MEMORY_SIZE_BEFORE_START_VM.value())); + } + if (minMemSize != 0L) { + cmd.setHostMinimumFreeMemorySize(minMemSize); + } + cmd.setImagePlatform(platform); cmd.setImageArchitecture(architecture); cmd.setVmName(spec.getVmInventory().getName()); @@ -4524,6 +4542,9 @@ protected void startVm(final VmInstanceSpec spec, final NeedReplyMessage msg, fi cmd.setConsolePassword(spec.getConsolePassword()); cmd.setUsbRedirect(spec.isUsbRedirect()); cmd.setEnableSecurityElement(spec.isEnableSecurityElement()); + if (spec.isEnableHygonSecurityElement() != null) { + cmd.setEnableHygonSecurityElement(spec.isEnableHygonSecurityElement()); + } cmd.setVDIMonitorNumber(Integer.valueOf(spec.getVDIMonitorNumber())); cmd.setVmPortOff(rcf.getResourceConfigValue(VmGlobalConfig.VM_PORT_OFF, spec.getVmInventory().getUuid(), Boolean.class)); cmd.setConsoleMode("vnc"); @@ -6893,4 +6914,69 @@ public void fail(ErrorCode errorCode) { } }); } + + private void handle(UpdateVmConsolePasswordOnHypervisorMsg msg) { + final UpdateVmConsolePasswordOnHypervisorReply reply = new UpdateVmConsolePasswordOnHypervisorReply(); + + thdf.singleFlightSubmit(new SingleFlightTask(msg) + .setSyncSignature(String.format("update-vm-%s-console-password-on-host-%s", msg.getVmInstanceUuid(), msg.getHostUuid())) + .run(completion -> { + doUpdateVmConsolePasswordOnHypervisor( + msg.getVmInstanceUuid(), + msg.getHostUuid(), + msg.getPassword(), + new ReturnValueCompletion(completion) { + @Override + public void success(UpdateVmConsolePasswordOnHypervisorReply returnValue) { + completion.success(returnValue); + } + + @Override + public void fail(ErrorCode errorCode) { + completion.fail(errorCode); + } + }); + }) + .done(result -> { + if (result.isSuccess()) { + bus.reply(msg, reply); + } else { + reply.setError(result.getErrorCode()); + bus.reply(msg, reply); + } + }) + ); + } + + private void doUpdateVmConsolePasswordOnHypervisor(String vmUuid, String hostUuid, String password, + ReturnValueCompletion completion) { + SetVmConsolePasswordLiveCmd cmd = new SetVmConsolePasswordLiveCmd(); + cmd.setVmUuid(vmUuid); + cmd.setPassword(password); + + KVMHostAsyncHttpCallMsg kmsg = new KVMHostAsyncHttpCallMsg(); + kmsg.setCommand(cmd); + kmsg.setHostUuid(hostUuid); + kmsg.setPath(KVMConstant.UPDATE_VM_CONSOLE_PASSWORD_PATH); + kmsg.setNoStatusCheck(true); + + bus.makeTargetServiceIdByResourceUuid(kmsg, HostConstant.SERVICE_ID, hostUuid); + bus.send(kmsg, new CloudBusCallBack(completion) { + @Override + public void run(MessageReply reply) { + if (!reply.isSuccess()) { + completion.fail(reply.getError()); + return; + } + + KVMHostAsyncHttpCallReply r = reply.castReply(); + AgentResponse rsp = r.toResponse(AgentResponse.class); + if (!rsp.isSuccess()) { + completion.fail(operr(rsp.getError())); + } else { + completion.success(new UpdateVmConsolePasswordOnHypervisorReply()); + } + } + }); + } } diff --git a/plugin/kvm/src/main/java/org/zstack/kvm/KvmSetupSelfFencerExtensionPoint.java b/plugin/kvm/src/main/java/org/zstack/kvm/KvmSetupSelfFencerExtensionPoint.java index 48ae2f6882..a202505f70 100755 --- a/plugin/kvm/src/main/java/org/zstack/kvm/KvmSetupSelfFencerExtensionPoint.java +++ b/plugin/kvm/src/main/java/org/zstack/kvm/KvmSetupSelfFencerExtensionPoint.java @@ -38,6 +38,8 @@ class KvmSetupSelfFencerParam { private PrimaryStorageInventory primaryStorage; private String strategy; private List fencers; + // all previous self-fencer configurations on the ps will be removed after applying the new one + private boolean flushPrevious = true; public String getHostUuid() { return hostUuid; @@ -94,6 +96,14 @@ public List getFencers() { public void setFencers(List fencers) { this.fencers = fencers; } + + public boolean isFlushPrevious() { + return flushPrevious; + } + + public void setFlushPrevious(boolean flushPrevious) { + this.flushPrevious = flushPrevious; + } } String kvmSetupSelfFencerStorageType(); diff --git a/plugin/localstorage/src/main/java/org/zstack/storage/primary/local/LocalStorageAllocatorFactory.java b/plugin/localstorage/src/main/java/org/zstack/storage/primary/local/LocalStorageAllocatorFactory.java index 9d84ec2a0f..3d3a2c7f47 100755 --- a/plugin/localstorage/src/main/java/org/zstack/storage/primary/local/LocalStorageAllocatorFactory.java +++ b/plugin/localstorage/src/main/java/org/zstack/storage/primary/local/LocalStorageAllocatorFactory.java @@ -16,6 +16,7 @@ import org.zstack.header.allocator.HostAllocatorSpec; import org.zstack.header.allocator.HostAllocatorStrategyExtensionPoint; import org.zstack.header.errorcode.OperationFailureException; +import org.zstack.header.exception.CloudRuntimeException; import org.zstack.header.host.HostInventory; import org.zstack.header.host.HostVO; import org.zstack.header.storage.primary.*; @@ -345,7 +346,7 @@ public String getHostUuidByResourceUuid(String primaryStorageUuid, String resUui } @Override - public String buildAllocatedInstallUrl(AllocatePrimaryStorageSpaceMsg msg, PrimaryStorageInventory psInv) { + public String allocateSpaceDryRun(AllocatePrimaryStorageSpaceMsg msg, PrimaryStorageInventory psInv) { String hostUuid = getHostUuidFromAllocateMsg(msg); if (hostUuid == null) { 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 c7b39fc161..5e4697ac8f 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 @@ -2672,6 +2672,7 @@ protected void handle(AskVolumeSnapshotCapabilityMsg msg) { String volumeType = msg.getVolume().getType(); if (VolumeType.Data.toString().equals(volumeType) || VolumeType.Root.toString().equals(volumeType)) { capability.setArrangementType(VolumeSnapshotArrangementType.CHAIN); + capability.setPlacementType(VolumeSnapshotCapability.VolumeSnapshotPlacementType.EXTERNAL); } else if (VolumeType.Memory.toString().equals(volumeType)) { capability.setArrangementType(VolumeSnapshotArrangementType.INDIVIDUAL); } else { diff --git a/plugin/nfsPrimaryStorage/src/main/java/org/zstack/storage/primary/nfs/NfsDownloadImageToCacheJob.java b/plugin/nfsPrimaryStorage/src/main/java/org/zstack/storage/primary/nfs/NfsDownloadImageToCacheJob.java index 3ba33c480f..cf56ff5e5a 100755 --- a/plugin/nfsPrimaryStorage/src/main/java/org/zstack/storage/primary/nfs/NfsDownloadImageToCacheJob.java +++ b/plugin/nfsPrimaryStorage/src/main/java/org/zstack/storage/primary/nfs/NfsDownloadImageToCacheJob.java @@ -256,7 +256,7 @@ public void handle(ErrorCode errCode, Map data) { private void useExistingCache(final ImageCacheVO cvo, final ReturnValueCompletion completion) { NfsPrimaryStorageBackend bkd = nfsFactory.getHypervisorBackend(nfsMgr.findHypervisorTypeByImageFormatAndPrimaryStorageUuid(image.getInventory().getFormat(), primaryStorage.getUuid())); - bkd.checkIsBitsExisting(primaryStorage, ImageCacheUtil.getImageCachePath(cvo.toInventory()), new ReturnValueCompletion(completion) { + bkd.checkIsBitsExisting(primaryStorage, ImageCacheUtil.getImageCachePath(cvo.getInstallUrl()), new ReturnValueCompletion(completion) { @Override public void success(Boolean returnValue) { if (returnValue) { 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 11e888024f..1a1f39a18c 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 @@ -1336,6 +1336,7 @@ protected void handle(AskVolumeSnapshotCapabilityMsg msg) { String volumeType = msg.getVolume().getType(); if (VolumeType.Data.toString().equals(volumeType) || VolumeType.Root.toString().equals(volumeType)) { capability.setArrangementType(VolumeSnapshotArrangementType.CHAIN); + capability.setPlacementType(VolumeSnapshotCapability.VolumeSnapshotPlacementType.EXTERNAL); } else if (VolumeType.Memory.toString().equals(volumeType)) { capability.setArrangementType(VolumeSnapshotArrangementType.INDIVIDUAL); } else { diff --git a/plugin/sdnController/src/main/java/org/zstack/sdnController/SdnControllerApiInterceptor.java b/plugin/sdnController/src/main/java/org/zstack/sdnController/SdnControllerApiInterceptor.java index 741a99cdb7..a9caed4b7e 100644 --- a/plugin/sdnController/src/main/java/org/zstack/sdnController/SdnControllerApiInterceptor.java +++ b/plugin/sdnController/src/main/java/org/zstack/sdnController/SdnControllerApiInterceptor.java @@ -15,9 +15,6 @@ import org.zstack.header.network.l3.L3NetworkVO; import org.zstack.header.network.l3.L3NetworkVO_; import org.zstack.header.network.sdncontroller.*; -import org.zstack.header.vm.APIAttachL3NetworkToVmMsg; -import org.zstack.header.vm.APIChangeVmNicNetworkMsg; -import org.zstack.header.vm.VmInstanceVO; import org.zstack.header.vm.VmNicVO; import org.zstack.network.l2.vxlan.vxlanNetwork.VxlanNetworkVO; import org.zstack.network.l2.vxlan.vxlanNetwork.VxlanNetworkVO_; @@ -61,8 +58,6 @@ public List getMessageClassToIntercept() { ret.add(APIAddVmNicToSecurityGroupMsg.class); ret.add(APISetVmNicSecurityGroupMsg.class); ret.add(APIAddSecurityGroupRuleMsg.class); - ret.add(APIAttachL3NetworkToVmMsg.class); - ret.add(APIChangeVmNicNetworkMsg.class); ret.add(APIPullSdnControllerTenantMsg.class); return ret; @@ -87,8 +82,6 @@ public APIMessage intercept(APIMessage msg) throws ApiMessageInterceptionExcepti validate((APISetVmNicSecurityGroupMsg) msg); } else if (msg instanceof APIAddSecurityGroupRuleMsg) { validate((APIAddSecurityGroupRuleMsg) msg); - } else if (msg instanceof APIChangeVmNicNetworkMsg) { - validate((APIChangeVmNicNetworkMsg) msg); } else if (msg instanceof APIPullSdnControllerTenantMsg) { validate((APIPullSdnControllerTenantMsg) msg); } else if (msg instanceof APIChangeSdnControllerMsg) { @@ -100,70 +93,6 @@ public APIMessage intercept(APIMessage msg) throws ApiMessageInterceptionExcepti return msg; } - private void validate(APIAttachL3NetworkToVmMsg msg) { - String sdnControlerUuid = L3NetworkHelper.getSdnControllerUuidFromL3Uuid(msg.getL3NetworkUuid()); - if (sdnControlerUuid == null) { - return; - } - - SdnControllerVO controllerVO = dbf.findByUuid(sdnControlerUuid, SdnControllerVO.class); - if (controllerVO == null) { - throw new ApiMessageInterceptionException(argerr("could not attach l3network to vm, " + - "because sdn controller[uuid:%s] is not find", sdnControlerUuid)); - } - - if (SdnControllerConstant.H3C_VCFC_CONTROLLER.equals(controllerVO.getVendorType()) && - SdnControllerConstant.H3C_VCFC_VENDOR_VERSION_V2.equals(controllerVO.getVendorVersion())) { - validateH3cTenantStatus(msg.getL3NetworkUuid(), sdnControlerUuid); - return; - } - - if (SdnControllerConstant.H3C_VCFC_CONTROLLER.equals(controllerVO.getVendorType())) { - return; - } - - VmInstanceVO vmVo = dbf.findByUuid(msg.getVmInstanceUuid(), VmInstanceVO.class); - boolean found = false; - for (SdnControllerHostRefVO ref : controllerVO.getHostRefVOS()) { - if (ref.getHostUuid().equals(vmVo.getHostUuid())) { - found = true; - break; - } - } - if (!found) { - throw new ApiMessageInterceptionException(argerr("could not attach l3network to vm, " + - "because host[uuid:%s] of vm is not attached to sdn controller[uuid:%s]", - vmVo.getHostUuid(), sdnControlerUuid)); - } - } - - private void validate(APIChangeVmNicNetworkMsg msg) { - String sdnControlerUuid = L3NetworkHelper.getSdnControllerUuidFromL3Uuid(msg.getDestL3NetworkUuid()); - if (sdnControlerUuid == null) { - return; - } - - SdnControllerVO controllerVO = dbf.findByUuid(sdnControlerUuid, SdnControllerVO.class); - if (controllerVO == null) { - throw new ApiMessageInterceptionException(argerr("could not change vmnic to l3network[uuid:%s], " + - "because sdn controller[uuid:%s] is not find", msg.getDestL3NetworkUuid(), sdnControlerUuid)); - } - - VmInstanceVO vmVo = dbf.findByUuid(msg.getVmInstanceUuid(), VmInstanceVO.class); - boolean found = false; - for (SdnControllerHostRefVO ref : controllerVO.getHostRefVOS()) { - if (ref.getHostUuid().equals(vmVo.getHostUuid())) { - found = true; - break; - } - } - if (!found) { - throw new ApiMessageInterceptionException(argerr("could not change vmnic to l3network[uuid:%s], " + - "because host[uuid:%s] of vm is not attached to sdn controller[uuid:%s]", - msg.getDestL3NetworkUuid(), vmVo.getHostUuid(), sdnControlerUuid)); - } - } - private void validate(APISetVmNicSecurityGroupMsg msg) { VmNicVO nicVO = dbf.findByUuid(msg.getVmNicUuid(), VmNicVO.class); String nicControllerUuid = L3NetworkHelper.getSdnControllerUuidFromL3Uuid(nicVO.getL3NetworkUuid()); 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 f4733f6a83..a193fded62 100644 --- a/plugin/sdnController/src/main/java/org/zstack/sdnController/SdnControllerBase.java +++ b/plugin/sdnController/src/main/java/org/zstack/sdnController/SdnControllerBase.java @@ -126,12 +126,54 @@ public void handleMessage(SdnControllerMessage msg) { handle((PullSdnControllerTenantMsg) msg); } else if (msg instanceof ReconnectSdnControllerMsg) { handle((ReconnectSdnControllerMsg) msg); + } else if (msg instanceof SyncSdnControllerDataMsg) { + handle((SyncSdnControllerDataMsg) msg); } else { SdnController controller = getSdnController(); controller.handleMessage(msg); } } + private void handle(SyncSdnControllerDataMsg msg) { + SyncSdnControllerDataReply reply = new SyncSdnControllerDataReply(); + // Run a sync chain that only syncs data, without touching connection status + thdf.chainSubmit(new ChainTask(reply) { + @Override + public String getSyncSignature() { + return getSdnControllerSignature(); + } + + @Override + public void run(SyncTaskChain chain) { + FlowChain flowChain = sdnMgr.getSyncChain(self); + flowChain.getData().put(SDN_CONTROLLER_UUID, self.getUuid()); + flowChain.setName(String.format("sync-sdn-controller-data-%s-%s", self.getUuid(), self.getName())); + + // Start the chain; flows in factory-provided chain should perform data sync operations + flowChain.done(new FlowDoneHandler(msg) { + @Override + public void handle(Map data) { + bus.reply(msg, reply); + chain.next(); + } + }).error(new FlowErrorHandler(msg) { + @Override + public void handle(ErrorCode errCode, Map data) { + SyncSdnControllerDataReply r = new SyncSdnControllerDataReply(); + r.setError(errCode); + bus.reply(msg, r); + chain.next(); + } + }).start(); + } + + @Override + public String getName() { + return String.format("sync-sdn-controller-data-%s", self.getUuid()); + } + }); + } + public void changeSdnControllerStatus(SdnControllerStatus status) { if (status == self.getStatus()) { return; 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 c9e939b63f..35bb7badea 100644 --- a/plugin/sdnController/src/main/java/org/zstack/sdnController/SdnControllerManagerImpl.java +++ b/plugin/sdnController/src/main/java/org/zstack/sdnController/SdnControllerManagerImpl.java @@ -637,6 +637,13 @@ public void preInstantiateVmResource(VmInstanceSpec spec, Completion 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; diff --git a/plugin/sdnController/src/main/java/org/zstack/sdnController/h3cVcfc/H3cVcfcSdnController.java b/plugin/sdnController/src/main/java/org/zstack/sdnController/h3cVcfc/H3cVcfcSdnController.java index f9afed355d..9ac04a5f08 100644 --- a/plugin/sdnController/src/main/java/org/zstack/sdnController/h3cVcfc/H3cVcfcSdnController.java +++ b/plugin/sdnController/src/main/java/org/zstack/sdnController/h3cVcfc/H3cVcfcSdnController.java @@ -15,6 +15,7 @@ import org.zstack.header.message.Message; import org.zstack.header.network.l2.APICreateL2NetworkMsg; import org.zstack.header.network.l2.L2NetworkInventory; +import org.zstack.header.network.l3.*; import org.zstack.header.network.sdncontroller.*; import org.zstack.header.rest.RESTFacade; import org.zstack.network.l2.vxlan.vxlanNetwork.L2VxlanNetworkInventory; @@ -221,6 +222,12 @@ public void handle(ErrorCode errCode, Map data) { public void handleMessage(SdnControllerMessage msg) { if (msg instanceof SdnControllerPingMsg) { handle((SdnControllerPingMsg)msg); + } else if (msg instanceof SdnControllerEnableDHCPMsg) { + handle((SdnControllerEnableDHCPMsg) msg); + } else if (msg instanceof SdnControllerDisableDHCPMsg) { + handle((SdnControllerDisableDHCPMsg) msg); + } else if (msg instanceof SdnControllerUpdateDHCPMsg) { + handle((SdnControllerUpdateDHCPMsg) msg); } else { bus.dealWithUnknownMessage((Message) msg); } @@ -499,6 +506,21 @@ public void getH3cControllerToken(Completion completion) { } } + void handle(SdnControllerEnableDHCPMsg msg) { + SdnControllerEnableDHCPReply reply = new SdnControllerEnableDHCPReply(); + bus.reply(msg, reply); + } + + void handle(SdnControllerDisableDHCPMsg msg) { + SdnControllerDisableDHCPReply reply = new SdnControllerDisableDHCPReply(); + bus.reply(msg, reply); + } + + void handle(SdnControllerUpdateDHCPMsg msg) { + SdnControllerUpdateDHCPReply reply = new SdnControllerUpdateDHCPReply(); + bus.reply(msg, reply); + } + void handle(SdnControllerPingMsg msg) { SdnControllerPingReply reply = new SdnControllerPingReply(); diff --git a/plugin/sdnController/src/main/java/org/zstack/sdnController/header/SyncSdnControllerDataMsg.java b/plugin/sdnController/src/main/java/org/zstack/sdnController/header/SyncSdnControllerDataMsg.java new file mode 100644 index 0000000000..299d71867d --- /dev/null +++ b/plugin/sdnController/src/main/java/org/zstack/sdnController/header/SyncSdnControllerDataMsg.java @@ -0,0 +1,22 @@ +package org.zstack.sdnController.header; + +import org.zstack.header.message.NeedReplyMessage; +import org.zstack.header.network.sdncontroller.SdnControllerMessage; + +public class SyncSdnControllerDataMsg extends NeedReplyMessage implements SdnControllerMessage { + private String controllerUuid; + + public String getControllerUuid() { + return controllerUuid; + } + + public void setControllerUuid(String controllerUuid) { + this.controllerUuid = controllerUuid; + } + + @Override + public String getSdnControllerUuid() { + return controllerUuid; + } +} + diff --git a/plugin/sdnController/src/main/java/org/zstack/sdnController/header/SyncSdnControllerDataReply.java b/plugin/sdnController/src/main/java/org/zstack/sdnController/header/SyncSdnControllerDataReply.java new file mode 100644 index 0000000000..eec719bfb5 --- /dev/null +++ b/plugin/sdnController/src/main/java/org/zstack/sdnController/header/SyncSdnControllerDataReply.java @@ -0,0 +1,7 @@ +package org.zstack.sdnController.header; + +import org.zstack.header.message.MessageReply; + +public class SyncSdnControllerDataReply extends MessageReply { +} + 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 a554238854..38aeef95cc 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 @@ -396,6 +396,7 @@ protected void handle(AskVolumeSnapshotCapabilityMsg msg) { String volumeType = msg.getVolume().getType(); if (VolumeType.Data.toString().equals(volumeType) || VolumeType.Root.toString().equals(volumeType)) { capability.setArrangementType(VolumeSnapshotArrangementType.CHAIN); + capability.setPlacementType(VolumeSnapshotCapability.VolumeSnapshotPlacementType.EXTERNAL); } else if (VolumeType.Memory.toString().equals(volumeType)) { capability.setArrangementType(VolumeSnapshotArrangementType.INDIVIDUAL); } else { 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 45a68537e3..ebcf1433be 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 @@ -56,7 +56,30 @@ public SugonSdnController(SdnControllerVO vo) { @Override public void handleMessage(SdnControllerMessage msg) { - bus.dealWithUnknownMessage((Message) msg); + if (msg instanceof SdnControllerEnableDHCPMsg) { + handMessage((SdnControllerEnableDHCPMsg) msg); + } else if (msg instanceof SdnControllerDisableDHCPMsg) { + handMessage((SdnControllerDisableDHCPMsg) msg); + } else if (msg instanceof SdnControllerUpdateDHCPMsg) { + handMessage((SdnControllerUpdateDHCPMsg) msg); + } else { + bus.dealWithUnknownMessage((Message) msg); + } + } + + void handMessage(SdnControllerEnableDHCPMsg msg) { + SdnControllerEnableDHCPReply reply = new SdnControllerEnableDHCPReply(); + bus.reply(msg, reply); + } + + void handMessage(SdnControllerDisableDHCPMsg msg) { + SdnControllerDisableDHCPReply reply = new SdnControllerDisableDHCPReply(); + bus.reply(msg, reply); + } + + void handMessage(SdnControllerUpdateDHCPMsg msg) { + SdnControllerUpdateDHCPReply reply = new SdnControllerUpdateDHCPReply(); + bus.reply(msg, reply); } @Override diff --git a/plugin/vhost/src/main/java/org/zstack/vhost/kvm/KvmVhostNodeServer.java b/plugin/vhost/src/main/java/org/zstack/vhost/kvm/KvmVhostNodeServer.java index 5b9cf5623e..4e7ed6425a 100644 --- a/plugin/vhost/src/main/java/org/zstack/vhost/kvm/KvmVhostNodeServer.java +++ b/plugin/vhost/src/main/java/org/zstack/vhost/kvm/KvmVhostNodeServer.java @@ -1,8 +1,10 @@ package org.zstack.vhost.kvm; +import javax.persistence.TypedQuery; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; +import org.zstack.compute.vm.VmGlobalConfig; import org.zstack.core.componentloader.PluginRegistry; +import org.zstack.core.db.DatabaseFacade; import org.zstack.header.Component; import org.zstack.header.errorcode.ErrorCode; import org.zstack.header.errorcode.OperationFailureException; @@ -15,6 +17,7 @@ import org.zstack.header.volume.VolumeProtocol; import org.zstack.header.volume.VolumeProtocolCapability; import org.zstack.kvm.*; +import org.zstack.resourceconfig.ResourceConfigFacade; import org.zstack.storage.addon.primary.ExternalPrimaryStorageFactory; import java.util.ArrayList; @@ -27,6 +30,10 @@ public class KvmVhostNodeServer implements Component, KVMStartVmExtensionPoint, KVMConvertVolumeExtensionPoint, KVMDetachVolumeExtensionPoint, KVMAttachVolumeExtensionPoint { @Autowired private ExternalPrimaryStorageFactory extPsFactory; + @Autowired + private DatabaseFacade dbf; + @Autowired + private ResourceConfigFacade rcf; private PluginRegistry pluginRgty; @@ -39,6 +46,21 @@ public class KvmVhostNodeServer implements Component, KVMStartVmExtensionPoint, capability.setSupportReadonly(false); } + private boolean needSupportVhostPrimaryStorage(String clusterUuid) { + String generateVhostConfig = VmGlobalConfig.GENERATE_CONFIG_VHOST_REQUIRED.value(String.class); + if (!"auto".equals(generateVhostConfig)) { + return Boolean.parseBoolean(generateVhostConfig); + } + String sql = "select count(ref) from PrimaryStorageClusterRefVO ref, PrimaryStorageOutputProtocolRefVO protoRef" + + " where ref.primaryStorageUuid = protoRef.primaryStorageUuid" + + " and ref.clusterUuid = :clusterUuid" + + " and protoRef.outputProtocol = :outputProtocol"; + TypedQuery q = dbf.getEntityManager().createQuery(sql, Long.class); + q.setParameter("clusterUuid", clusterUuid); + q.setParameter("outputProtocol", VolumeProtocol.Vhost.name()); + Long count = q.getSingleResult(); + return count != null && count > 0; + } @Override public void beforeStartVmOnKvm(KVMHostInventory host, VmInstanceSpec spec, KVMAgentCommands.StartVmCmd cmd) { @@ -54,13 +76,15 @@ public void beforeStartVmOnKvm(KVMHostInventory host, VmInstanceSpec spec, KVMAg } } - cmd.setDataVolumes(dtos); if (VolumeProtocol.Vhost.name().equals(spec.getDestRootVolume().getProtocol()) || - spec.getDestDataVolumes().stream().anyMatch(v -> VolumeProtocol.Vhost.name().equals(v.getProtocol()))) { + spec.getDestDataVolumes().stream().anyMatch(v -> VolumeProtocol.Vhost.name().equals(v.getProtocol())) || + needSupportVhostPrimaryStorage(host.getClusterUuid())) { cmd.setUseHugePage(true); cmd.setMemAccess("shared"); } + cmd.setDataVolumes(dtos); + // vhostuser disk not support readonly mode, so no iso. } @@ -130,10 +154,10 @@ public void beforeDetachVolume(KVMHostInventory host, VmInstanceInventory vm, Vo } @Override - public void afterDetachVolume(KVMHostInventory host, VmInstanceInventory vm, VolumeInventory volume, KVMAgentCommands.DetachDataVolumeCmd cmd) { } + public void afterDetachVolume(KVMHostInventory host, VmInstanceInventory vm, VolumeInventory volume, KVMAgentCommands.DetachDataVolumeCmd cmd) {} @Override - public void detachVolumeFailed(KVMHostInventory host, VmInstanceInventory vm, VolumeInventory volume, KVMAgentCommands.DetachDataVolumeCmd cmd, ErrorCode err) { } + public void detachVolumeFailed(KVMHostInventory host, VmInstanceInventory vm, VolumeInventory volume, KVMAgentCommands.DetachDataVolumeCmd cmd, ErrorCode err) {} @Override public void beforeAttachVolume(KVMHostInventory host, VmInstanceInventory vm, VolumeInventory volume, KVMAgentCommands.AttachDataVolumeCmd cmd, Map data) { 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 85287633e0..427a32cb6c 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 @@ -141,7 +141,7 @@ protected FlowChain getProvisionConfigChain() { } @Override - protected List createAfterConnectNewCreatedVirtualRouterFlows() { + protected List createAfterConnectNewCreatedFlows() { List flows = new ArrayList<>(); flows.add(new TrackVirtualRouterVmFlow()); return flows; @@ -945,6 +945,22 @@ public void attachNetworkService(String vrUuid, String networkServiceType, Strin public void detachNetworkService(String vrUuid, String networkServiceType, String l3NetworkUuid){ } + private void fillNicBondMode(VmNicInventory nicInventory, VirtualRouterCommands.NicInfo info) { + info.setBondMode("none"); + + List exts = pluginRgty.getExtensionList(ApplianceVmNicBootstrapExtensionPoint.class); + if (exts == null || exts.isEmpty()) { + return; + } + + ApplianceVmNicTO nicTO = new ApplianceVmNicTO(); + nicTO.setBondMode("none"); + for (ApplianceVmNicBootstrapExtensionPoint ext : exts) { + ext.fillNicBootstrapInfo(nicInventory, nicTO); + } + info.setBondMode(nicTO.getBondMode()); + } + public class virtualRouterAfterAttachNicFlow extends NoRollbackFlow { @Override public void run(FlowTrigger trigger, Map data) { @@ -987,6 +1003,7 @@ public void run(FlowTrigger trigger, Map data) { } info.setMtu(new MtuGetter().getMtu(l3NetworkVO.getUuid())); info.setState(nicInventory.getState()); + fillNicBondMode(nicInventory, info); cmd.setNics(Arrays.asList(info)); VirtualRouterAsyncHttpCallMsg cmsg = new VirtualRouterAsyncHttpCallMsg(); @@ -1314,6 +1331,7 @@ public void run(FlowTrigger trigger, Map data) { info.setGateway(nicInventory.getGateway()); info.setMac(nicInventory.getMac()); info.setNetmask(nicInventory.getNetmask()); + fillNicBondMode(nicInventory, info); cmd.setNics(Arrays.asList(info)); VirtualRouterAsyncHttpCallMsg cmsg = new VirtualRouterAsyncHttpCallMsg(); diff --git a/plugin/virtualRouterProvider/src/main/java/org/zstack/network/service/virtualrouter/VirtualRouterCommands.java b/plugin/virtualRouterProvider/src/main/java/org/zstack/network/service/virtualrouter/VirtualRouterCommands.java index 3d9f963605..6b167a0b89 100755 --- a/plugin/virtualRouterProvider/src/main/java/org/zstack/network/service/virtualrouter/VirtualRouterCommands.java +++ b/plugin/virtualRouterProvider/src/main/java/org/zstack/network/service/virtualrouter/VirtualRouterCommands.java @@ -196,6 +196,7 @@ public static class NicInfo { private String gateway6; private String addressMode; private String state; + private String bondMode; public String getIp() { return ip; @@ -315,6 +316,14 @@ public String getState() { public void setState(String state) { this.state = state; } + + public String getBondMode() { + return bondMode; + } + + public void setBondMode(String bondMode) { + this.bondMode = bondMode; + } } public static class ConfigureNicCmd extends AgentCommand { 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 6d47951e25..e5880b3f83 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 @@ -2033,7 +2033,7 @@ protected List scripts() { }.execute(); } - private List applianceVmsToBeDeleted(List applianceVmVOS, List deletedUuids) { + public List applianceVmsToBeDeleted(List applianceVmVOS, List deletedUuids) { List vos = new ArrayList<>(); for (ApplianceVmVO vo : applianceVmVOS) { VirtualRouterVmVO vo_dbf = dbf.findByUuid(vo.getUuid(), VirtualRouterVmVO.class); @@ -2057,7 +2057,7 @@ private List applianceVmsToBeDeleted(List applianc return vos; } - List applianceVmsAdditionalPublicNic(List applianceVmVOS, List parentIssuerUuids) { + public List applianceVmsAdditionalPublicNic(List applianceVmVOS, List parentIssuerUuids) { List toDeleteNics = new ArrayList<>(); for (ApplianceVmVO vo : applianceVmVOS) { VirtualRouterVmVO vr_dbf = dbf.findByUuid(vo.getUuid(), VirtualRouterVmVO.class); @@ -2132,7 +2132,7 @@ public void done(ErrorCodeList errorCodeList) { }); } - List applianceVmsToDeleteNicByIpRanges(List applianceVmVOS, List iprUuids) { + public List applianceVmsToDeleteNicByIpRanges(List applianceVmVOS, List iprUuids) { List toDeleteNics = new ArrayList<>(); for (ApplianceVmVO vo : applianceVmVOS) { for (VmNicVO nic : vo.getVmNics()) { @@ -2159,7 +2159,7 @@ List applianceVmsToDeleteNicByIpRanges(List applianceVmV return toDeleteNics; } - private List applianceVmsToBeDeletedByIpRanges(List applianceVmVOS, List iprUuids) { + public List applianceVmsToBeDeletedByIpRanges(List applianceVmVOS, List iprUuids) { List toDeleted = new ArrayList<>(); List l3Uuids = Q.New(IpRangeVO.class).in(IpRangeVO_.uuid, iprUuids).select(IpRangeVO_.l3NetworkUuid).listValues(); for (ApplianceVmVO vos : applianceVmVOS) { @@ -2215,6 +2215,11 @@ public List filterApplianceVmCascade(List applianc } } + @Override + public ApplianceVmType getApplianceVmType() { + return ApplianceVmType.valueOf(VirtualRouterConstant.VIRTUAL_ROUTER_VM_TYPE); + } + private void reconenctVirtualRouter(String vrUUid, boolean statusChange) { ReconnectVirtualRouterVmMsg msg = new ReconnectVirtualRouterVmMsg(); msg.setVirtualRouterVmUuid(vrUUid); @@ -2713,19 +2718,69 @@ public void run(MessageReply reply) { } private List findVipsOnVirtualRouter(List vfNics, String vrUuid) { - List vipUuids = SQL.New("select vip.uuid from VipVO vip, VipPeerL3NetworkRefVO ref " + - "where ref.vipUuid = vip.uuid " + - "and (ref.l3NetworkUuid in (:l3NetworkUuids) " + - "or vip.l3NetworkUuid in (:l3NetworkUuids))") - .param("l3NetworkUuids", vfNics.stream().map(VmNicInventory::getL3NetworkUuid).collect(Collectors.toList())) - .list(); + List l3Uuids = vfNics.stream().map(VmNicInventory::getL3NetworkUuid).collect(Collectors.toList()); + List l3Networks = Q.New(L3NetworkVO.class).in(L3NetworkVO_.uuid, l3Uuids).list(); + + /* separate private l3 and public/system l3 by category */ + List guestL3Uuids = l3Networks.stream() + .filter(l3 -> L3NetworkCategory.Private.equals(l3.getCategory())) + .map(L3NetworkVO::getUuid) + .collect(Collectors.toList()); + /* public and system l3 are both treated as public l3, because they are shared resources among VRs */ + List publicL3Uuids = l3Networks.stream() + .filter(l3 -> L3NetworkCategory.Public.equals(l3.getCategory()) || + L3NetworkCategory.System.equals(l3.getCategory())) + .map(L3NetworkVO::getUuid) + .collect(Collectors.toList()); + + Set vipUuids = new HashSet<>(); + + /* for guest vf nics, find vips bindingto these l3 networks as peerL3 */ + if (!guestL3Uuids.isEmpty()) { + List guestVipUuids = SQL.New("select vip.uuid from VipVO vip, VipPeerL3NetworkRefVO ref " + + "where ref.vipUuid = vip.uuid " + + "and ref.l3NetworkUuid in (:l3NetworkUuids)") + .param("l3NetworkUuids", guestL3Uuids) + .list(); + vipUuids.addAll(guestVipUuids); + } + + /* for public vf nics, find vips bindingto this vr and bindingto these l3 networks as public l3 */ + if (!publicL3Uuids.isEmpty()) { + List publicVipUuids = SQL.New("select vip.uuid from VipVO vip, VirtualRouterVipVO ref " + + "where ref.uuid = vip.uuid " + + "and ref.virtualRouterVmUuid = :vrUuid " + + "and vip.l3NetworkUuid in (:l3NetworkUuids)") + .param("vrUuid", vrUuid) + .param("l3NetworkUuids", publicL3Uuids) + .list(); + vipUuids.addAll(publicVipUuids); + + String haUuid = haBackend.getVirtualRouterHaUuid(vrUuid); + if (haUuid != null) { + List haVipUuids = SQL.New("select vip.uuid from VipVO vip, VpcHaGroupNetworkServiceRefVO ref " + + "where ref.networkServiceUuid = vip.uuid " + + "and ref.vpcHaRouterUuid = :haUuid " + + "and ref.networkServiceName = :vipType " + + "and vip.l3NetworkUuid in (:l3NetworkUuids)") + .param("haUuid", haUuid) + .param("vipType", VipVO.class.getSimpleName()) + .param("l3NetworkUuids", publicL3Uuids) + .list(); + vipUuids.addAll(haVipUuids); + } + } + + if (vipUuids.isEmpty()) { + return new ArrayList<>(); + } - vipUuids = getVirtualRouterVips(vrUuid, vipUuids); - if (vipUuids == null || vipUuids.isEmpty()) { + List filteredVipUuids = getVirtualRouterVips(vrUuid, new ArrayList<>(vipUuids)); + if (filteredVipUuids == null || filteredVipUuids.isEmpty()) { return new ArrayList<>(); } - List vips = Q.New(VipVO.class).in(VipVO_.uuid, vipUuids).list(); + List vips = Q.New(VipVO.class).in(VipVO_.uuid, filteredVipUuids).list(); VirtualRouterVmInventory vr = VirtualRouterVmInventory.valueOf((VirtualRouterVmVO) Q.New(VirtualRouterVmVO.class).eq(VirtualRouterVmVO_.uuid, vrUuid).find()); diff --git a/plugin/virtualRouterProvider/src/main/java/org/zstack/network/service/virtualrouter/lb/VirtualRouterLoadBalancerBackend.java b/plugin/virtualRouterProvider/src/main/java/org/zstack/network/service/virtualrouter/lb/VirtualRouterLoadBalancerBackend.java index c08db61161..3ee3d33449 100755 --- a/plugin/virtualRouterProvider/src/main/java/org/zstack/network/service/virtualrouter/lb/VirtualRouterLoadBalancerBackend.java +++ b/plugin/virtualRouterProvider/src/main/java/org/zstack/network/service/virtualrouter/lb/VirtualRouterLoadBalancerBackend.java @@ -953,6 +953,16 @@ public int compare(LoadBalancerServerGroupServerIpInventory r1, LoadBalancerServ } } if (addIp) { + // Check if VR has a NIC connected to this L3 network + if (vr != null) { + boolean vrHasL3Network = vr.getVmNics().stream() + .anyMatch(vrNic -> usedIpInventory.getL3NetworkUuid().equals(vrNic.getL3NetworkUuid())); + if (!vrHasL3Network) { + logger.warn(String.format("VR[uuid:%s] has no NIC connected to L3Network[uuid:%s], " + + "skip backend server IP[%s]", vr.getUuid(), usedIpInventory.getL3NetworkUuid(), usedIpInventory.getIp())); + continue; + } + } ips.add(usedIpInventory.getIp()); params.add(String.format("balancerWeight::%s::%s", usedIpInventory.getIp(), nicRef.getWeight())); backendServers.add(new LbTO.BackendServer(usedIpInventory.getIp(), nicRef.getWeight())); @@ -2572,7 +2582,12 @@ private List getLoadBalancersByL3Networks(String l3Uuid, boo LoadBalancerStruct struct = new LoadBalancerStruct(); LoadBalancerVO lb = dbf.findByUuid(e.getKey(), LoadBalancerVO.class); struct.setLb(LoadBalancerInventory.valueOf(lb)); - struct.setVip(VipInventory.valueOf(dbf.findByUuid(lb.getVipUuid(), VipVO.class))); + if (lb.getVipUuid() != null) { + struct.setVip(VipInventory.valueOf(dbf.findByUuid(lb.getVipUuid(), VipVO.class))); + } + if (lb.getIpv6VipUuid() != null) { + struct.setIpv6Vip(VipInventory.valueOf(dbf.findByUuid(lb.getIpv6VipUuid(), VipVO.class))); + } struct.setListenerServerGroupMap(new HashMap<>()); List serverGroupUuids = new ArrayList<>(); diff --git a/plugin/virtualRouterProvider/src/main/java/org/zstack/network/service/virtualrouter/vyos/VyosVmFactory.java b/plugin/virtualRouterProvider/src/main/java/org/zstack/network/service/virtualrouter/vyos/VyosVmFactory.java index 17d62cc88b..69aa5b0155 100644 --- a/plugin/virtualRouterProvider/src/main/java/org/zstack/network/service/virtualrouter/vyos/VyosVmFactory.java +++ b/plugin/virtualRouterProvider/src/main/java/org/zstack/network/service/virtualrouter/vyos/VyosVmFactory.java @@ -2,13 +2,21 @@ import org.springframework.beans.factory.annotation.Autowired; import org.zstack.appliancevm.ApplianceVmType; +import org.zstack.appliancevm.ApplianceVmVO; +import org.zstack.appliancevm.ApvmCascadeFilterExtensionPoint; +import org.zstack.core.cascade.CascadeAction; import org.zstack.core.db.DatabaseFacade; +import org.zstack.header.network.l3.IpRangeVO; +import org.zstack.header.network.l3.L3NetworkVO; +import org.zstack.header.network.l3.UsedIpInventory; import org.zstack.header.network.service.NetworkServiceType; +import org.zstack.header.vm.VmNicInventory; import org.zstack.network.service.lb.LoadBalancerConstants; import org.zstack.network.service.vip.VipGetUsedPortRangeExtensionPoint; import org.zstack.network.service.vip.VipVO; import org.zstack.network.service.virtualrouter.VirtualRouterGlobalConfig; import org.zstack.network.service.virtualrouter.VirtualRouterGlobalProperty; +import org.zstack.network.service.virtualrouter.VirtualRouterManagerImpl; import org.zstack.utils.RangeSet; import org.zstack.utils.Utils; import org.zstack.utils.VipUseForList; @@ -20,12 +28,14 @@ /** * Created by weiwang on 19/09/2017 */ -public class VyosVmFactory extends VyosVmBaseFactory implements VipGetUsedPortRangeExtensionPoint { +public class VyosVmFactory extends VyosVmBaseFactory implements VipGetUsedPortRangeExtensionPoint, ApvmCascadeFilterExtensionPoint { private static final CLogger logger = Utils.getLogger(VyosVmFactory.class); public static ApplianceVmType applianceVmType = new ApplianceVmType(VyosConstants.VYOS_VM_TYPE); @Autowired private DatabaseFacade dbf; + @Autowired + private VirtualRouterManagerImpl vrMgr; @Override public ApplianceVmType getApplianceVmType() { @@ -60,4 +70,31 @@ public RangeSet getVipUsePortRange(String vipUuid, String protocol, VipUseForLis return portRangeList; } + + @Override + public List filterApplianceVmCascade(List applianceVmVOS, CascadeAction action, + String parentIssuer, + List parentIssuerUuids, + List toDeleteNics, + List toDeleteIps) { + logger.debug(String.format("filter appliance vm type %s with parentIssuer [type: %s, uuids: %s]", + VyosConstants.VYOS_VM_TYPE, parentIssuer, parentIssuerUuids)); + + if (parentIssuer.equals(L3NetworkVO.class.getSimpleName())) { + List vos = vrMgr.applianceVmsToBeDeleted(applianceVmVOS, parentIssuerUuids); + + applianceVmVOS.removeAll(vos); + toDeleteNics.addAll(vrMgr.applianceVmsAdditionalPublicNic(applianceVmVOS, parentIssuerUuids)); + + return vos; + } else if (parentIssuer.equals(IpRangeVO.class.getSimpleName())) { + List vos = vrMgr.applianceVmsToBeDeletedByIpRanges(applianceVmVOS, parentIssuerUuids); + applianceVmVOS.removeAll(vos); + toDeleteNics.addAll(VmNicInventory.valueOf(vrMgr.applianceVmsToDeleteNicByIpRanges(applianceVmVOS, parentIssuerUuids))); + + return vos; + } else { + return applianceVmVOS; + } + } } 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 a43a9eaa6c..4fb920421a 100644 --- a/plugin/xinfini/src/main/java/org/zstack/xinfini/XInfiniStorageController.java +++ b/plugin/xinfini/src/main/java/org/zstack/xinfini/XInfiniStorageController.java @@ -97,9 +97,10 @@ private String getVhostSocketDir() { VolumeSnapshotCapability scap = new VolumeSnapshotCapability(); scap.setSupport(true); scap.setArrangementType(VolumeSnapshotCapability.VolumeSnapshotArrangementType.INDIVIDUAL); + scap.setPlacementType(VolumeSnapshotCapability.VolumeSnapshotPlacementType.INTERNAL); scap.setSupportCreateOnHypervisor(false); scap.setSupportLazyDelete(false); - scap.setVolumePathFromInnerSnapshotRegex("^[^@]+"); + scap.setVolumePathFromInternalSnapshotRegex("^[^@]+"); capabilities.setSnapshotCapability(scap); capabilities.setSupportCloneFromVolume(false); capabilities.setSupportStorageQos(false); @@ -413,7 +414,7 @@ public void deployClient(HostInventory h, Completion comp) { } @Override - public synchronized void activateHeartbeatVolume(HostInventory h, ReturnValueCompletion comp) { + public synchronized void activateHeartbeatVolume(HostInventory h, ReturnValueCompletion comp) { String clientIqn = IscsiUtils.getHostInitiatorName(h.getUuid()); if (clientIqn == null) { throw new RuntimeException(String.format("cannot get host[uuid:%s] initiator name", h.getUuid())); @@ -430,7 +431,10 @@ public synchronized void activateHeartbeatVolume(HostInventory h, ReturnValueCom to.setHostId(apiHelper.queryBdcByIp(h.getManagementIp()).getSpec().getId()); to.setHeartbeatRequiredSpace(SizeUnit.MEGABYTE.toByte(1)); to.setCoveringPaths(Collections.singletonList(getVhostSocketDir())); - comp.success(to); + + HeartbeatVolumeTopology topology = new HeartbeatVolumeTopology(); + topology.setHeartbeatVolumeByCoveringPaths(Collections.singletonMap(getVhostSocketDir(), to)); + comp.success(topology); } @Override @@ -459,7 +463,7 @@ public void deactivateHeartbeatVolume(HostInventory h, Completion comp) { } @Override - public HeartbeatVolumeTO getHeartbeatVolumeActiveInfo(HostInventory h) { + public HeartbeatVolumeTopology getHeartbeatVolumeActiveInfo(HostInventory h) { VolumeModule heartbeatVol = apiHelper.queryVolumeByName(iscsiHeartbeatVolumeName); if (heartbeatVol == null) { throw new RuntimeException("heartbeat volume not found"); @@ -476,7 +480,10 @@ public HeartbeatVolumeTO getHeartbeatVolumeActiveInfo(HostInventory h) { to.setHostId(apiHelper.queryBdcByIp(h.getManagementIp()).getSpec().getId()); to.setHeartbeatRequiredSpace(SizeUnit.MEGABYTE.toByte(1)); to.setCoveringPaths(Collections.singletonList(getVhostSocketDir())); - return to; + + HeartbeatVolumeTopology topology = new HeartbeatVolumeTopology(); + topology.setHeartbeatVolumeByCoveringPaths(Collections.singletonMap(getVhostSocketDir(), to)); + return topology; } private VolumeModule getVolumeModule(BaseVolumeInfo vol) { @@ -557,6 +564,30 @@ private void reloadDbInfo() { config = StringUtils.isEmpty(self.getConfig()) ? new XInfiniConfig() : JSONObjectUtil.toObject(self.getConfig(), XInfiniConfig.class); } + // TODO: add more not found handling when support multi pool + @Override + public void getCapacity(List requiredUrls, ReturnValueCompletion comp) { + Map pools = refreshPoolCapacity() + .stream() + .filter(it -> config.getPoolIds().contains(it.getId())) + .collect(Collectors.toMap(XInfiniAddonInfo.Pool::getId, it -> it)); + + long total = pools.values().stream().mapToLong(XInfiniAddonInfo.Pool::getTotalCapacity).sum(); + long avail = pools.values().stream().mapToLong(XInfiniAddonInfo.Pool::getAvailableCapacity).sum(); + StorageCapacity cap = new StorageCapacity(); + cap.setAvailableCapacity(avail); + cap.setTotalCapacity(total); + + for (String url : requiredUrls) { + int poolId = getPoolIdFromPath(url); + XInfiniAddonInfo.Pool pool = pools.get(poolId); + if (pool != null) { + cap.putCapacity(url, pool.getAvailableCapacity(), pool.getTotalCapacity()); + } + } + comp.success(cap); + } + @Override public void reportCapacity(ReturnValueCompletion comp) { reloadDbInfo(); @@ -1008,8 +1039,8 @@ public void revertVolumeSnapshot(String snapshotInstallPath, ReturnValueCompleti } @Override - public void validateConfig(String config) { - + public String validateConfig(String config) { + return config; } @Override diff --git a/plugin/cbd/src/main/java/org/zstack/cbd/AddonInfo.java b/plugin/zbs/src/main/java/org/zstack/storage/zbs/AddonInfo.java similarity index 84% rename from plugin/cbd/src/main/java/org/zstack/cbd/AddonInfo.java rename to plugin/zbs/src/main/java/org/zstack/storage/zbs/AddonInfo.java index c08f5c37c6..fba2dd72a6 100644 --- a/plugin/cbd/src/main/java/org/zstack/cbd/AddonInfo.java +++ b/plugin/zbs/src/main/java/org/zstack/storage/zbs/AddonInfo.java @@ -1,4 +1,4 @@ -package org.zstack.cbd; +package org.zstack.storage.zbs; import java.util.ArrayList; import java.util.List; @@ -35,4 +35,8 @@ public List getLogicalPoolInfos() { public void setLogicalPoolInfos(List logicalPoolInfos) { this.logicalPoolInfos = logicalPoolInfos; } + + public void addLogicalPoolInfo(LogicalPoolInfo logicalPoolInfo) { + this.logicalPoolInfos.add(logicalPoolInfo); + } } diff --git a/plugin/cbd/src/main/java/org/zstack/cbd/ClusterInfo.java b/plugin/zbs/src/main/java/org/zstack/storage/zbs/ClusterInfo.java similarity index 92% rename from plugin/cbd/src/main/java/org/zstack/cbd/ClusterInfo.java rename to plugin/zbs/src/main/java/org/zstack/storage/zbs/ClusterInfo.java index 6907f7e7e0..2f0e21d950 100644 --- a/plugin/cbd/src/main/java/org/zstack/cbd/ClusterInfo.java +++ b/plugin/zbs/src/main/java/org/zstack/storage/zbs/ClusterInfo.java @@ -1,4 +1,4 @@ -package org.zstack.cbd; +package org.zstack.storage.zbs; /** * @author Xingwei Yu diff --git a/plugin/zbs/src/main/java/org/zstack/storage/zbs/Config.java b/plugin/zbs/src/main/java/org/zstack/storage/zbs/Config.java new file mode 100644 index 0000000000..ca7d1c2406 --- /dev/null +++ b/plugin/zbs/src/main/java/org/zstack/storage/zbs/Config.java @@ -0,0 +1,61 @@ +package org.zstack.storage.zbs; + + +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +/** + * @author Xingwei Yu + * @date 2024/4/2 11:13 + */ +public class Config { + public static class Pool { + public String logicalName; + public String aliasName; + + public Pool(String logicalName, String aliasName) { + this.logicalName = logicalName; + this.aliasName = aliasName; + } + + public Pool() {} + } + + private List mdsUrls; + private List pools; + private String logicalPoolName; + private transient List poolNames; + + public List getMdsUrls() { + return mdsUrls; + } + + public void setMdsUrls(List mdsUrls) { + this.mdsUrls = mdsUrls; + } + + public String getLogicalPoolName() { + return logicalPoolName; + } + + public void setLogicalPoolName(String logicalPoolName) { + this.logicalPoolName = logicalPoolName; + } + + public void setPools(List pools) { + this.pools = pools; + poolNames = getPoolNames(); + } + + public List getPools() { + return pools; + } + + public List getPoolNames() { + if (poolNames == null) { + poolNames = pools == null ? Collections.emptyList() : pools.stream().map(pool -> pool.logicalName).collect(Collectors.toList()); + } + return poolNames; + } +} diff --git a/plugin/cbd/src/main/java/org/zstack/cbd/LogicalPoolInfo.java b/plugin/zbs/src/main/java/org/zstack/storage/zbs/LogicalPoolInfo.java similarity index 77% rename from plugin/cbd/src/main/java/org/zstack/cbd/LogicalPoolInfo.java rename to plugin/zbs/src/main/java/org/zstack/storage/zbs/LogicalPoolInfo.java index 8725ca0aaa..4a3a5411db 100644 --- a/plugin/cbd/src/main/java/org/zstack/cbd/LogicalPoolInfo.java +++ b/plugin/zbs/src/main/java/org/zstack/storage/zbs/LogicalPoolInfo.java @@ -1,4 +1,4 @@ -package org.zstack.cbd; +package org.zstack.storage.zbs; /** * @author Xingwei Yu @@ -170,4 +170,28 @@ public void setZoneNum(int zoneNum) { this.zoneNum = zoneNum; } } + + public static LogicalPoolInfo valueOf(ZbsListPoolResult.LogicalPoolInfo logicalPoolInfo) { + if (logicalPoolInfo == null) { + return null; + } + + LogicalPoolInfo info = new LogicalPoolInfo(); + info.setAllocatedSize(logicalPoolInfo.getAllocatedSize()); + info.setCapacity(logicalPoolInfo.getCapacity()); + info.setCreateTime(logicalPoolInfo.getCreateTime()); + info.setLogicalPoolID(logicalPoolInfo.getLogicalPoolID()); + info.setLogicalPoolName(logicalPoolInfo.getLogicalPoolName()); + info.setPhysicalPoolID(logicalPoolInfo.getPhysicalPoolID()); + info.setPhysicalPoolName(logicalPoolInfo.getPhysicalPoolName()); + info.setQuota(logicalPoolInfo.getQuota()); + info.setRawUsedSize(logicalPoolInfo.getRawUsedSize()); + info.setRawWalUsedSize(logicalPoolInfo.getRawWalUsedSize()); + info.setType(logicalPoolInfo.getType()); + info.setUsedSize(logicalPoolInfo.getUsedSize()); + info.setUserPolicy(logicalPoolInfo.getUserPolicy()); + info.setAllocateStatus(logicalPoolInfo.getAllocateStatus()); + return info; + + } } diff --git a/plugin/cbd/src/main/java/org/zstack/cbd/MdsInfo.java b/plugin/zbs/src/main/java/org/zstack/storage/zbs/MdsInfo.java similarity index 73% rename from plugin/cbd/src/main/java/org/zstack/cbd/MdsInfo.java rename to plugin/zbs/src/main/java/org/zstack/storage/zbs/MdsInfo.java index a41fff0930..4085e6657a 100644 --- a/plugin/cbd/src/main/java/org/zstack/cbd/MdsInfo.java +++ b/plugin/zbs/src/main/java/org/zstack/storage/zbs/MdsInfo.java @@ -1,6 +1,9 @@ -package org.zstack.cbd; +package org.zstack.storage.zbs; +import java.util.Collection; +import java.util.List; import java.util.Objects; +import java.util.stream.Collectors; /** * @author Xingwei Yu @@ -78,4 +81,18 @@ public MdsStatus getStatus() { public void setStatus(MdsStatus status) { this.status = status; } + + public static MdsInfo valueOf(String mdsUrl) { + MdsUri uri = new MdsUri(mdsUrl); + MdsInfo mdsInfo = new MdsInfo(); + mdsInfo.setUsername(uri.getUsername()); + mdsInfo.setPassword(uri.getPassword()); + mdsInfo.setPort(uri.getSshPort()); + mdsInfo.setAddr(uri.getHostname()); + return mdsInfo; + } + + public static List valueOf(Collection mdsUrls) { + return mdsUrls.stream().map(MdsInfo::valueOf).collect(Collectors.toList()); + } } diff --git a/plugin/cbd/src/main/java/org/zstack/cbd/MdsStatus.java b/plugin/zbs/src/main/java/org/zstack/storage/zbs/MdsStatus.java similarity index 80% rename from plugin/cbd/src/main/java/org/zstack/cbd/MdsStatus.java rename to plugin/zbs/src/main/java/org/zstack/storage/zbs/MdsStatus.java index 7ed70af64c..279d2605eb 100644 --- a/plugin/cbd/src/main/java/org/zstack/cbd/MdsStatus.java +++ b/plugin/zbs/src/main/java/org/zstack/storage/zbs/MdsStatus.java @@ -1,4 +1,4 @@ -package org.zstack.cbd; +package org.zstack.storage.zbs; /** * @author Xingwei Yu diff --git a/plugin/cbd/src/main/java/org/zstack/cbd/MdsUri.java b/plugin/zbs/src/main/java/org/zstack/storage/zbs/MdsUri.java similarity index 95% rename from plugin/cbd/src/main/java/org/zstack/cbd/MdsUri.java rename to plugin/zbs/src/main/java/org/zstack/storage/zbs/MdsUri.java index 9fef3451b0..9fa1e00f38 100644 --- a/plugin/cbd/src/main/java/org/zstack/cbd/MdsUri.java +++ b/plugin/zbs/src/main/java/org/zstack/storage/zbs/MdsUri.java @@ -1,4 +1,4 @@ -package org.zstack.cbd; +package org.zstack.storage.zbs; import org.apache.http.NameValuePair; import org.apache.http.client.utils.URLEncodedUtils; @@ -30,8 +30,10 @@ public class MdsUri { private static final Integer DEFAULT_SSH_PORT = 22; private static List allowedQueryParameter; + + private static final String MDS_PARAM_MDS_PORT = "mdsPort"; static { - allowedQueryParameter = list(CbdConstants.MDS_PARAM_MDS_PORT); + allowedQueryParameter = list(MDS_PARAM_MDS_PORT); } public static String getQueryValue(URI uri, String name) { @@ -90,7 +92,7 @@ public MdsUri(String url) { " in format of %s", url, MDS_URL_FORMAT) ); } - String v = getQueryValue(uri, CbdConstants.MDS_PARAM_MDS_PORT); + String v = getQueryValue(uri, MDS_PARAM_MDS_PORT); mdsPort = v == null ? mdsPort : Integer.parseInt(v); } catch (URISyntaxException e) { throw new CloudRuntimeException(e); diff --git a/plugin/zbs/src/main/java/org/zstack/storage/zbs/ZbsConstants.java b/plugin/zbs/src/main/java/org/zstack/storage/zbs/ZbsConstants.java index 8f547cfeb2..9d69ca21b4 100644 --- a/plugin/zbs/src/main/java/org/zstack/storage/zbs/ZbsConstants.java +++ b/plugin/zbs/src/main/java/org/zstack/storage/zbs/ZbsConstants.java @@ -13,8 +13,7 @@ public interface ZbsConstants { String ZBS_PS_ALLOW_PORTS = "7763"; String ZBS_HEARTBEAT_VOLUME_NAME = "zbs_zstack_heartbeat"; long ZBS_HEARTBEAT_VOLUME_SIZE_IN_GIGABYTE = 1; - String ZBS_CBD_LUN_PATH_FORMAT = "cbd:%s/%s/%s"; - String ZBS_CBD_PREFIX_SCHEME = "cbd://"; + String SCHEME_PREFIX = "zbs://"; Integer PRIMARY_STORAGE_MDS_MAXIMUM_PING_FAILURE = 3; String VOLUME_PHYSICAL_BLOCK_SIZE = "4096"; String MEGABYTE_SUPPORTED_VERSION = "1.6.1"; diff --git a/plugin/zbs/src/main/java/org/zstack/storage/zbs/ZbsHelper.java b/plugin/zbs/src/main/java/org/zstack/storage/zbs/ZbsHelper.java index 7af981c519..3484be39c2 100644 --- a/plugin/zbs/src/main/java/org/zstack/storage/zbs/ZbsHelper.java +++ b/plugin/zbs/src/main/java/org/zstack/storage/zbs/ZbsHelper.java @@ -7,25 +7,40 @@ import org.zstack.utils.VersionComparator; import org.zstack.utils.data.SizeUnit; +import java.util.function.Function; + /** * @author Xingwei Yu * @date 2024/4/9 17:50 */ public class ZbsHelper { - public static void configUrl(String psUuid) { - String psUrl = ZbsConstants.ZBS_CBD_PREFIX_SCHEME + psUuid; - if (!psUrl.equals(Q.New(PrimaryStorageVO.class).select(PrimaryStorageVO_.url).eq(PrimaryStorageVO_.uuid, psUuid).findValue())) { - SQL.New(PrimaryStorageVO.class).set(PrimaryStorageVO_.url, psUrl).eq(PrimaryStorageVO_.uuid, psUuid).update(); - } + // cbdPath: cbd:physical_pool/logical_pool/volume_id + public static String convertCbdPathToZbsPath(String cbdPath) { + return cbdPath.replaceFirst(".+?/", "zbs://"); + } + + public static String convertZbsPathToCbdPath(String zbsPath, Function physicalPoolGetter) { + String logicalPool = getPoolFromVolumePath(zbsPath); + String physicalPool = physicalPoolGetter.apply(logicalPool); + return zbsPath.replaceFirst("zbs://", String.format("cbd:%s/", physicalPool)); } public static String buildHeartbeatVolumePath(String logicalPool) { - return String.format("cbd:%s_physical/%s/%s", logicalPool, logicalPool, ZbsConstants.ZBS_HEARTBEAT_VOLUME_NAME); + return String.format("zbs://%s/%s", logicalPool, ZbsConstants.ZBS_HEARTBEAT_VOLUME_NAME); } - public static String buildVolumePath(String physicalPool, String logicalPool, String volId) { + public static String buildPoolPath(String logicalPool) { + return String.format("zbs://%s", logicalPool); + } + + public static String buildVolumePath(String logicalPool, String volId) { String base = volId.replace("-", ""); - return String.format(ZbsConstants.ZBS_CBD_LUN_PATH_FORMAT, physicalPool, logicalPool, base); + return String.format("zbs://%s/%s", logicalPool, base); + } + + public static String getPoolFromVolumePath(String path) { + String[] parts = path.replace("zbs://", "").split("/"); + return parts[0]; } public static String getVolumeFromSnapshotPath(String path) { diff --git a/plugin/zbs/src/main/java/org/zstack/storage/zbs/ZbsListPoolResult.java b/plugin/zbs/src/main/java/org/zstack/storage/zbs/ZbsListPoolResult.java new file mode 100644 index 0000000000..6a7b2f106c --- /dev/null +++ b/plugin/zbs/src/main/java/org/zstack/storage/zbs/ZbsListPoolResult.java @@ -0,0 +1,277 @@ +package org.zstack.storage.zbs; + +import java.util.List; + +/** + * example: + * { + * "error": { + * "code": 0, + * "message": "success" + * }, + * "result": [ + * { + * "statusCode": 0, + * "logicalPoolInfos": [ + * { + * "logicalPoolID": 6, + * "logicalPoolName": "pool-4676f61e5c4c456891cc3ec22ef118c3", + * "physicalPoolID": 6, + * "physicalPoolName": "pool-4676f61e5c4c456891cc3ec22ef118c3_physical", + * "type": 0, + * "createTime": 1765855781, + * "redundanceAndPlaceMentPolicy": "eyJjb3B5c2V0TnVtIjoyMDAsInJlcGxpY2FOdW0iOjMsInpvbmVOdW0iOjN9Cg==", + * "userPolicy": "eyJwb2xpY3kiIDogMX0=", + * "allocateStatus": 0, + * "capacity": 390607142912, + * "usedSize": 2617245696, + * "allocatedSize": 4294967296, + * "rawUsedSize": 7851737088, + * "rawWalUsedSize": 533196800, + * "quota": 0, + * "ioPriority": 0 + * } + * ] + * }, + * { + * "statusCode": 0, + * "logicalPoolInfos": [ + * { + * "logicalPoolID": 5, + * "logicalPoolName": "pool-a65b5d3a96f44dfc95971a4fa8032a4f", + * "physicalPoolID": 5, + * "physicalPoolName": "pool-a65b5d3a96f44dfc95971a4fa8032a4f_physical", + * "type": 0, + * "createTime": 1765855755, + * "redundanceAndPlaceMentPolicy": "eyJjb3B5c2V0TnVtIjoyMDAsInJlcGxpY2FOdW0iOjMsInpvbmVOdW0iOjN9Cg==", + * "userPolicy": "eyJwb2xpY3kiIDogMX0=", + * "allocateStatus": 0, + * "capacity": 390607142912, + * "usedSize": 3162505216, + * "allocatedSize": 9663676416, + * "rawUsedSize": 9487515648, + * "rawWalUsedSize": 608768000, + * "quota": 0, + * "ioPriority": 0 + * } + * ] + * } + * ] + * } + */ + + +public class ZbsListPoolResult { + private ErrorInfo error; + private List result; + + public ErrorInfo getError() { + return error; + } + + public void setError(ErrorInfo error) { + this.error = error; + } + + public List getResult() { + return result; + } + + public void setResult(List result) { + this.result = result; + } + + public static class ErrorInfo { + private int code; + private String message; + + public int getCode() { + return code; + } + + public void setCode(int code) { + this.code = code; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + } + + public static class Result { + private int statusCode; + private List logicalPoolInfos; + + public int getStatusCode() { + return statusCode; + } + + public void setStatusCode(int statusCode) { + this.statusCode = statusCode; + } + + public List getLogicalPoolInfos() { + return logicalPoolInfos; + } + + public void setLogicalPoolInfos(List logicalPoolInfos) { + this.logicalPoolInfos = logicalPoolInfos; + } + } + + public boolean isSuccess() { + return error == null || error.getCode() == 0; + } + + public static class LogicalPoolInfo { + private int logicalPoolID; + private String logicalPoolName; + private int physicalPoolID; + private String physicalPoolName; + private int type; + private long createTime; + private String redundanceAndPlaceMentPolicy; + private String userPolicy; + private int allocateStatus; + private long capacity; + private long usedSize; + private long allocatedSize; + private long rawUsedSize; + private long rawWalUsedSize; + private long quota; + private int ioPriority; + + public int getLogicalPoolID() { + return logicalPoolID; + } + + public void setLogicalPoolID(int logicalPoolID) { + this.logicalPoolID = logicalPoolID; + } + + public String getLogicalPoolName() { + return logicalPoolName; + } + + public void setLogicalPoolName(String logicalPoolName) { + this.logicalPoolName = logicalPoolName; + } + + public int getPhysicalPoolID() { + return physicalPoolID; + } + + public void setPhysicalPoolID(int physicalPoolID) { + this.physicalPoolID = physicalPoolID; + } + + + public String getPhysicalPoolName() { + return physicalPoolName; + } + + public void setPhysicalPoolName(String physicalPoolName) { + this.physicalPoolName = physicalPoolName; + } + + public int getType() { + return type; + } + + public void setType(int type) { + this.type = type; + } + + public long getCreateTime() { + return createTime; + } + + public void setCreateTime(long createTime) { + this.createTime = createTime; + } + + public String getRedundanceAndPlaceMentPolicy() { + return redundanceAndPlaceMentPolicy; + } + + public void setRedundanceAndPlaceMentPolicy(String redundanceAndPlaceMentPolicy) { + this.redundanceAndPlaceMentPolicy = redundanceAndPlaceMentPolicy; + } + + public String getUserPolicy() { + return userPolicy; + } + + public void setUserPolicy(String userPolicy) { + this.userPolicy = userPolicy; + } + + public int getAllocateStatus() { + return allocateStatus; + } + + public void setAllocateStatus(int allocateStatus) { + this.allocateStatus = allocateStatus; + } + + public long getCapacity() { + return capacity; + } + + public void setCapacity(long capacity) { + this.capacity = capacity; + } + + public long getUsedSize() { + return usedSize; + } + + public void setUsedSize(long usedSize) { + this.usedSize = usedSize; + } + + public long getAllocatedSize() { + return allocatedSize; + } + + public void setAllocatedSize(long allocatedSize) { + this.allocatedSize = allocatedSize; + } + + public long getRawUsedSize() { + return rawUsedSize; + } + + public void setRawUsedSize(long rawUsedSize) { + this.rawUsedSize = rawUsedSize; + } + + public long getRawWalUsedSize() { + return rawWalUsedSize; + } + + public void setRawWalUsedSize(long rawWalUsedSize) { + this.rawWalUsedSize = rawWalUsedSize; + } + + public long getQuota() { + return quota; + } + + public void setQuota(long quota) { + this.quota = quota; + } + + public int getIoPriority() { + return ioPriority; + } + + public void setIoPriority(int ioPriority) { + this.ioPriority = ioPriority; + } + } +} diff --git a/plugin/zbs/src/main/java/org/zstack/storage/zbs/ZbsMdsBase.java b/plugin/zbs/src/main/java/org/zstack/storage/zbs/ZbsMdsBase.java index 1d4f286233..ecdd3d65e1 100644 --- a/plugin/zbs/src/main/java/org/zstack/storage/zbs/ZbsMdsBase.java +++ b/plugin/zbs/src/main/java/org/zstack/storage/zbs/ZbsMdsBase.java @@ -3,8 +3,6 @@ import org.springframework.beans.factory.annotation.Autowire; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Configurable; -import org.zstack.cbd.ClusterInfo; -import org.zstack.cbd.MdsInfo; import org.zstack.core.db.DatabaseFacade; import org.zstack.header.core.Completion; import org.zstack.header.core.ReturnValueCompletion; diff --git a/plugin/zbs/src/main/java/org/zstack/storage/zbs/ZbsPrimaryStorageMdsBase.java b/plugin/zbs/src/main/java/org/zstack/storage/zbs/ZbsPrimaryStorageMdsBase.java index 81309d4364..cdcef665eb 100644 --- a/plugin/zbs/src/main/java/org/zstack/storage/zbs/ZbsPrimaryStorageMdsBase.java +++ b/plugin/zbs/src/main/java/org/zstack/storage/zbs/ZbsPrimaryStorageMdsBase.java @@ -1,9 +1,6 @@ package org.zstack.storage.zbs; import org.springframework.beans.factory.annotation.Autowired; -import org.zstack.cbd.ClusterInfo; -import org.zstack.cbd.MdsInfo; -import org.zstack.cbd.MdsStatus; import org.zstack.compute.host.HostGlobalConfig; import org.zstack.core.CoreGlobalProperty; import org.zstack.core.Platform; 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 dd1861e58f..1812808c2a 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 @@ -4,26 +4,27 @@ import org.springframework.beans.factory.annotation.Autowire; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Configurable; -import org.zstack.cbd.*; import org.zstack.cbd.kvm.CbdHeartbeatVolumeTO; import org.zstack.cbd.kvm.CbdVolumeTo; import org.zstack.compute.host.HostGlobalConfig; import org.zstack.core.CoreGlobalProperty; +import org.zstack.core.ansible.AnsibleGlobalProperty; import org.zstack.core.asyncbatch.While; import org.zstack.core.cloudbus.CloudBus; import org.zstack.core.cloudbus.CloudBusCallBack; import org.zstack.core.db.DatabaseFacade; +import org.zstack.core.db.Q; import org.zstack.core.db.SQL; import org.zstack.core.workflow.FlowChainBuilder; import org.zstack.core.workflow.ShareFlow; import org.zstack.header.HasThreadContext; +import org.zstack.header.apimediator.ApiMessageInterceptionException; import org.zstack.header.core.*; import org.zstack.header.core.workflow.*; import org.zstack.header.errorcode.ErrorCode; import org.zstack.header.errorcode.ErrorCodeList; import org.zstack.header.errorcode.OperationFailureException; import org.zstack.header.errorcode.SysErrors; -import org.zstack.header.exception.CloudRuntimeException; import org.zstack.header.host.HostAO_; import org.zstack.header.host.HostConstant; import org.zstack.header.host.HostInventory; @@ -54,9 +55,13 @@ import java.net.URI; import java.net.URISyntaxException; import java.util.*; +import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.TimeUnit; +import java.util.function.Predicate; import java.util.stream.Collectors; +import java.util.stream.Stream; +import static org.zstack.core.Platform.argerr; import static org.zstack.core.Platform.operr; import static org.zstack.storage.zbs.ZbsHelper.*; @@ -81,6 +86,8 @@ public class ZbsStorageController implements PrimaryStorageControllerSvc, Primar private AddonInfo addonInfo; private Config config; + private Map physicalPoolByLogicalPool = new ConcurrentHashMap<>(); + public static final String DEPLOY_CLIENT_PATH = "/zbs/primarystorage/client/deploy"; public static final String GET_CAPACITY_PATH = "/zbs/primarystorage/capacity"; public static final String GET_FACTS_PATH = "/zbs/primarystorage/facts"; @@ -99,6 +106,7 @@ public class ZbsStorageController implements PrimaryStorageControllerSvc, Primar public static final String ROLLBACK_SNAPSHOT_PATH = "/zbs/primarystorage/snapshot/rollback"; public static final String CHECK_HOST_STORAGE_CONNECTION_PATH = "/zbs/primarystorage/check/host/connection"; public static final String GET_VOLUME_CLIENTS_PATH = "/zbs/primarystorage/volume/clients"; + public static final String UPDATE_HOST_DEPENDENCY_PATH = "/zbs/primarystorage/host/updatedependency"; private static final StorageCapabilities capabilities = new StorageCapabilities(); @@ -106,14 +114,17 @@ public class ZbsStorageController implements PrimaryStorageControllerSvc, Primar VolumeSnapshotCapability scap = new VolumeSnapshotCapability(); scap.setSupport(true); scap.setArrangementType(VolumeSnapshotCapability.VolumeSnapshotArrangementType.INDIVIDUAL); + scap.setPlacementType(VolumeSnapshotCapability.VolumeSnapshotPlacementType.INTERNAL); scap.setSupportCreateOnHypervisor(false); scap.setSupportLazyDelete(false); - scap.setVolumePathFromInnerSnapshotRegex("^[^@]+"); + scap.setVolumePathFromInternalSnapshotRegex("^[^@]+"); capabilities.setSnapshotCapability(scap); capabilities.setSupportShareableVolume(true); capabilities.setSupportCloneFromVolume(false); + capabilities.setSupportCloneFromAnotherSpace(false); capabilities.setSupportStorageQos(false); capabilities.setSupportLiveExpandVolume(false); + capabilities.setSupportMultiSpace(true); capabilities.setSupportedImageFormats(Collections.singletonList(ImageConstant.RAW_FORMAT_STRING)); capabilities.setDefaultIsoActiveProtocol(VolumeProtocol.CBD); capabilities.setDefaultImageExportProtocol(VolumeProtocol.NBD); @@ -122,6 +133,7 @@ public class ZbsStorageController implements PrimaryStorageControllerSvc, Primar @Override public void activate(BaseVolumeInfo v, HostInventory h, boolean shareable, ReturnValueCompletion comp) { if (VolumeProtocol.CBD.toString().equals(v.getProtocol())) { + comp.success(new CbdVolumeTo()); return; } @@ -147,7 +159,11 @@ public void blacklist(String installPath, String protocol, HostInventory h, Comp @Override public String getActivePath(BaseVolumeInfo v, HostInventory h, boolean shareable) { - return null; + if (VolumeProtocol.CBD.toString().equals(v.getProtocol())) { + return convertZbsPathToCbdPath(v.getInstallPath(), this::getPhysicalPoolName); + } else { + throw new OperationFailureException(operr("not supported protocol[%s] for active", v.getProtocol())); + } } @Override @@ -187,55 +203,136 @@ public List getActiveVolumesLocation(HostInventory h) { @Override public void deployClient(HostInventory h, Completion comp) { - KVMHostVO host = org.zstack.core.db.Q.New(KVMHostVO.class).eq(KVMHostVO_.uuid, h.getUuid()).find(); - if (host == null) { - comp.fail(operr("cannot found kvm host[uuid:%s], unable to deploy client", h.getUuid())); - return; - } - - DeployClientCmd cmd = new DeployClientCmd(); - cmd.setIp(h.getManagementIp()); - cmd.setPort(host.getPort()); - cmd.setUsername(host.getUsername()); - cmd.setPassword(host.getPassword()); - httpCall(DEPLOY_CLIENT_PATH, cmd, DeployClientRsp.class, new ReturnValueCompletion(comp) { + FlowChain chain = FlowChainBuilder.newShareFlowChain(); + chain.setName(String.format("deploy-zbs-client-on-host-%s", h.getUuid())); + chain.then(new ShareFlow() { @Override - public void success(DeployClientRsp returnValue) { - comp.success(); - } + public void setup() { + flow(new NoRollbackFlow() { + String __name__ = "deploy-client"; - @Override - public void fail(ErrorCode errorCode) { - comp.fail(errorCode); + @Override + public void run(FlowTrigger trigger, Map data) { + KVMHostVO host = Q.New(KVMHostVO.class).eq(KVMHostVO_.uuid, h.getUuid()).find(); + if (host == null) { + trigger.fail(operr("cannot found kvm host[uuid:%s], unable to deploy client", h.getUuid())); + return; + } + + DeployClientCmd cmd = new DeployClientCmd(); + cmd.setIp(h.getManagementIp()); + cmd.setPort(host.getPort()); + cmd.setUsername(host.getUsername()); + cmd.setPassword(host.getPassword()); + httpCall(DEPLOY_CLIENT_PATH, cmd, DeployClientRsp.class, new ReturnValueCompletion(trigger) { + @Override + public void success(DeployClientRsp returnValue) { + trigger.next(); + } + + @Override + public void fail(ErrorCode errorCode) { + trigger.fail(errorCode); + } + }); + } + }); + + flow(new NoRollbackFlow() { + String __name__ = "update-host-client-dependency"; + + @Override + public void run(FlowTrigger trigger, Map data) { + UpdateHostDependencyCmd cmd = new UpdateHostDependencyCmd(); + cmd.updatePackages = "libcbd"; + cmd.zstackRepo = AnsibleGlobalProperty.ZSTACK_REPO; + + KVMHostAsyncHttpCallMsg msg = new KVMHostAsyncHttpCallMsg(); + msg.setCommand(cmd); + msg.setHostUuid(h.getUuid()); + msg.setPath(UPDATE_HOST_DEPENDENCY_PATH); + msg.setNoStatusCheck(true); + bus.makeTargetServiceIdByResourceUuid(msg, HostConstant.SERVICE_ID, msg.getHostUuid()); + bus.send(msg, new CloudBusCallBack(trigger) { + @Override + public void run(MessageReply reply) { + if (!reply.isSuccess()) { + trigger.fail(reply.getError()); + return; + } + + KVMHostAsyncHttpCallReply hreply = reply.castReply(); + UpdateHostDependencyRsp rsp = hreply.toResponse(UpdateHostDependencyRsp.class); + if (!rsp.isSuccess()) { + trigger.fail(operr(rsp.getError())); + return; + } + + trigger.next(); + } + }); + } + }); + + done(new FlowDoneHandler(comp) { + @Override + public void handle(Map data) { + comp.success(); + } + }); + + error(new FlowErrorHandler(comp) { + @Override + public void handle(ErrorCode errCode, Map data) { + comp.fail(errCode); + } + }); } - }); + }).start(); } @Override - public synchronized void activateHeartbeatVolume(HostInventory h, ReturnValueCompletion comp) { + public synchronized void activateHeartbeatVolume(HostInventory h, ReturnValueCompletion completion) { if (config == null) { reloadDbInfo(); } - CreateVolumeCmd cmd = new CreateVolumeCmd(); - cmd.setLogicalPool(config.getLogicalPoolName()); - cmd.setVolume(ZbsConstants.ZBS_HEARTBEAT_VOLUME_NAME); - cmd.setSize(ZbsConstants.ZBS_HEARTBEAT_VOLUME_SIZE_IN_GIGABYTE); - cmd.setSkipIfExisting(true); + // TODO: split by physical pool not logical pool, handle logical pool deletion + HeartbeatVolumeTopology topology = new HeartbeatVolumeTopology(); + new While<>(config.getPoolNames()).each((poolName, comp) -> { + CreateVolumeCmd cmd = new CreateVolumeCmd(); + cmd.setLogicalPool(poolName); + cmd.setVolume(ZbsConstants.ZBS_HEARTBEAT_VOLUME_NAME); + cmd.setSize(ZbsConstants.ZBS_HEARTBEAT_VOLUME_SIZE_IN_GIGABYTE); + cmd.setSkipIfExisting(true); - httpCall(CREATE_VOLUME_PATH, cmd, CreateVolumeRsp.class, new ReturnValueCompletion(comp) { - @Override - public void success(CreateVolumeRsp returnValue) { - CbdHeartbeatVolumeTO to = new CbdHeartbeatVolumeTO(); - to.setInstallPath(returnValue.installPath); - to.setHeartbeatRequiredSpace(SizeUnit.MEGABYTE.toByte(1)); - to.setCoveringPaths(Collections.singletonList(config.getLogicalPoolName())); - comp.success(to); - } + httpCall(CREATE_VOLUME_PATH, cmd, CreateVolumeRsp.class, new ReturnValueCompletion(comp) { + @Override + public void success(CreateVolumeRsp returnValue) { + CbdHeartbeatVolumeTO to = new CbdHeartbeatVolumeTO(); + String zbsPath = returnValue.installPath; + to.setInstallPath(ZbsHelper.convertZbsPathToCbdPath(zbsPath, ZbsStorageController.this::getPhysicalPoolName)); + to.setHeartbeatRequiredSpace(SizeUnit.MEGABYTE.toByte(1)); + to.setCoveringPaths(config.getPoolNames()); + topology.putHeartbeatVolume(poolName, to); + comp.done(); + } + @Override + public void fail(ErrorCode errorCode) { + comp.addError(errorCode); + comp.allDone(); + } + }); + }).run(new WhileDoneCompletion(completion) { @Override - public void fail(ErrorCode errorCode) { - comp.fail(errorCode); + public void done(ErrorCodeList errorCodeList) { + if (!errorCodeList.getCauses().isEmpty()) { + completion.fail(errorCodeList.getCauses().get(0)); + return; + } + + completion.success(topology); } }); } @@ -246,17 +343,27 @@ public void deactivateHeartbeatVolume(HostInventory h, Completion comp) { } @Override - public HeartbeatVolumeTO getHeartbeatVolumeActiveInfo(HostInventory h) { + public HeartbeatVolumeTopology getHeartbeatVolumeActiveInfo(HostInventory h) { if (config == null) { reloadDbInfo(); } - CbdHeartbeatVolumeTO to = new CbdHeartbeatVolumeTO(); - to.setInstallPath(buildHeartbeatVolumePath(config.getLogicalPoolName())); - to.setHeartbeatRequiredSpace(SizeUnit.MEGABYTE.toByte(1)); - to.setCoveringPaths(Collections.singletonList(config.getLogicalPoolName())); + HeartbeatVolumeTopology topology = new HeartbeatVolumeTopology(); + Map map = new HashMap<>(); + for (String poolName : config.getPoolNames()) { + String zbsPath = buildHeartbeatVolumePath(poolName); + + String cbdPath = ZbsHelper.convertZbsPathToCbdPath(zbsPath, this::getPhysicalPoolName); + CbdHeartbeatVolumeTO to = new CbdHeartbeatVolumeTO(); + to.setInstallPath(cbdPath); + to.setHeartbeatRequiredSpace(SizeUnit.MEGABYTE.toByte(1)); + to.setCoveringPaths(config.getPoolNames()); + + map.put(poolName, to); + } - return to; + topology.setHeartbeatVolumeByCoveringPaths(map); + return topology; } @Override @@ -268,7 +375,7 @@ public String getIdentity() { public void connect(String cfg, String url, ReturnValueCompletion completion) { AddonInfo newAddonInfo = new AddonInfo(); Config current = JSONObjectUtil.toObject(cfg, Config.class); - List mdsInfos = parseMdsInfos(current.getMdsUrls()); + List mdsInfos = MdsInfo.valueOf(current.getMdsUrls()); newAddonInfo.setMdsInfos(mdsInfos); final List mdsList = CollectionUtils.transformToList(newAddonInfo.getMdsInfos(), ZbsPrimaryStorageMdsBase::new); @@ -357,7 +464,7 @@ public void fail(ErrorCode errorCode) { flow(new NoRollbackFlow() { String __name__ = "deploy-client"; - List refs = org.zstack.core.db.Q.New(PrimaryStorageClusterRefVO.class) + List refs = Q.New(PrimaryStorageClusterRefVO.class) .eq(PrimaryStorageClusterRefVO_.primaryStorageUuid, self.getUuid()) .list(); @@ -372,12 +479,12 @@ public void run(FlowTrigger trigger, Map data) { .map(PrimaryStorageClusterRefVO::getClusterUuid) .collect(Collectors.toList()); - List hosts = org.zstack.core.db.Q.New(HostVO.class) + List hosts = Q.New(HostVO.class) .in(HostAO_.clusterUuid, clusterUuids) .list(); new While<>(hosts).each((h, comp) -> { - KVMHostVO host = org.zstack.core.db.Q.New(KVMHostVO.class).eq(KVMHostVO_.uuid, h.getUuid()).find(); + KVMHostVO host = Q.New(KVMHostVO.class).eq(KVMHostVO_.uuid, h.getUuid()).find(); if (host == null) { comp.addError(operr("cannot found kvm host[uuid:%s], unable to deploy client", h.getUuid())); comp.allDone(); @@ -418,7 +525,6 @@ public void done(ErrorCodeList errorCodeList) { done(new FlowDoneHandler(completion) { @Override public void handle(Map data) { - configUrl(self.getUuid()); addonInfo = newAddonInfo; completion.success(JSONObjectUtil.rehashObject(newAddonInfo, LinkedHashMap.class)); } @@ -478,12 +584,21 @@ public void done(ErrorCodeList errorCodeList) { }); } + @Override + public void getCapacity(List requiredUrls, ReturnValueCompletion comp) { + List poolNames = requiredUrls.stream().map(ZbsHelper::getPoolFromVolumePath).collect(Collectors.toList()); + getPoolCapacities(poolNames, comp); + } + @Override public void reportCapacity(ReturnValueCompletion comp) { reloadDbInfo(); + getPoolCapacities(config.getPoolNames(), comp); + } + private void getPoolCapacities(List poolNames, ReturnValueCompletion comp) { GetCapacityCmd cmd = new GetCapacityCmd(); - cmd.setLogicalPool(config.getLogicalPoolName()); + cmd.logicalPoolNames = poolNames; httpCall(GET_CAPACITY_PATH, cmd, GetCapacityRsp.class, new ReturnValueCompletion(comp) { @Override @@ -502,6 +617,9 @@ public void success(GetCapacityRsp returnValue) { cap.setTotalCapacity(total); cap.setAvailableCapacity(avail); cap.setHealthy(StorageHealthy.Ok); + for (LogicalPoolInfo pool : logicalPoolInfos) { + cap.putCapacity(buildPoolPath(pool.getLogicalPoolName()), pool.getCapacity() - pool.getUsedSize(), pool.getCapacity()); + } comp.success(cap); } @@ -514,14 +632,26 @@ public void fail(ErrorCode errorCode) { @Override public void reportHealthy(ReturnValueCompletion comp) { + // TODO: more accurate healthy report + getPoolCapacities(config.getPoolNames(), new ReturnValueCompletion(comp) { + @Override + public void success(StorageCapacity returnValue) { + comp.success(StorageHealthy.Ok); + } + @Override + public void fail(ErrorCode errorCode) { + comp.success(StorageHealthy.Unknown); + } + }); } @Override public void reportNodeHealthy(HostInventory host, ReturnValueCompletion comp) { CheckHostStorageConnectionCmd cmd = new CheckHostStorageConnectionCmd(); cmd.setHostUuid(host.getUuid()); - cmd.setPath(buildHeartbeatVolumePath(config.getLogicalPoolName())); + String zbsHbPath = buildHeartbeatVolumePath(config.getLogicalPoolName()); + cmd.setPath(ZbsHelper.convertZbsPathToCbdPath(zbsHbPath, this::getPhysicalPoolName)); KVMHostAsyncHttpCallMsg msg = new KVMHostAsyncHttpCallMsg(); msg.setCommand(cmd); @@ -553,30 +683,38 @@ public StorageCapabilities reportCapabilities() { @Override public String allocateSpace(AllocateSpaceSpec aspec) { - if (config == null) { + if (config == null || addonInfo == null) { reloadDbInfo(); } - // TODO allocate pool - LogicalPoolInfo logicalPoolInfo = allocateFreePool(aspec.getSize()); + Predicate p = aspec.getRequiredUrl() == null ? null : it -> { + String pool = getPoolFromVolumePath(aspec.getRequiredUrl()); + return StringUtils.equals(pool, it.getLogicalPoolName()); + }; + + LogicalPoolInfo logicalPoolInfo = allocateFreePool(aspec.getSize(), p); if (logicalPoolInfo == null) { - throw new OperationFailureException(operr("no available logical pool with enough space[%d]", aspec.getSize())); + throw new OperationFailureException(operr("no available logical pool with enough space[%d] and required url: %s", + aspec.getSize(), aspec.getRequiredUrl())); } - return buildVolumePath("", config.getLogicalPoolName(), ""); + return buildPoolPath(logicalPoolInfo.getLogicalPoolName()); } - private LogicalPoolInfo allocateFreePool(long size) { + private LogicalPoolInfo allocateFreePool(long size, Predicate filter) { List logicalPoolInfos = getSelfPools(); - return logicalPoolInfos.stream().filter(it -> it.getCapacity() - it.getUsedSize() > size) - .max(Comparator.comparingLong(it -> it.getCapacity() - it.getUsedSize())) + Stream s = logicalPoolInfos.stream().filter(it -> it.getCapacity() - it.getUsedSize() > size); + if (filter != null) { + s = s.filter(filter); + } + + return s.max(Comparator.comparingLong(it -> it.getCapacity() - it.getUsedSize())) .orElse(null); } private List getSelfPools() { - String configLogicalPoolName = config.getLogicalPoolName(); List logicalPoolInfos = addonInfo.getLogicalPoolInfos(); - logicalPoolInfos.removeIf(it -> !configLogicalPoolName.equals(it.getLogicalPoolName())); + logicalPoolInfos.removeIf(it -> !config.getPoolNames().contains(it.getLogicalPoolName())); return logicalPoolInfos; } @@ -585,11 +723,13 @@ public void createVolume(CreateVolumeSpec v, ReturnValueCompletion reloadDbInfo(); CreateVolumeCmd cmd = new CreateVolumeCmd(); - cmd.setLogicalPool(config.getLogicalPoolName()); cmd.setVolume(v.getName()); cmd.setUnit(getSizeUnit(addonInfo.getClusterInfo().getVersion())); cmd.setSize(alignSizeTo(v.getSize(), cmd.getUnit())); cmd.setSkipIfExisting(true); + String poolName = v.getAllocatedUrl() != null ? getPoolFromVolumePath(v.getAllocatedUrl()) : + allocateFreePool(cmd.getSize(), null).getLogicalPoolName(); + cmd.setLogicalPool(poolName); httpCall(CREATE_VOLUME_PATH, cmd, CreateVolumeRsp.class, new ReturnValueCompletion(comp) { @Override @@ -672,7 +812,7 @@ public boolean skip(Map data) { @Override public void run(FlowTrigger trigger, Map data) { ExpandVolumeCmd cmd = new ExpandVolumeCmd(); - cmd.setPath(stats.getInstallPath()); + cmd.setPath(convertZbsPathToCbdPath(stats.getInstallPath(), ZbsStorageController.this::getPhysicalPoolName)); cmd.setUnit(getSizeUnit(addonInfo.getClusterInfo().getVersion())); cmd.setSize(alignSizeTo(dst.getSize(), cmd.getUnit())); @@ -713,7 +853,9 @@ public void copyVolume(String srcInstallPath, CreateVolumeSpec dst, ReturnValueC CopyCmd cmd = new CopyCmd(); cmd.setPath(srcInstallPath); cmd.setDstVolume(dst.getName()); - cmd.setDstSize(dst.getSize() / (1L << 30)); + if (dst.getAllocatedUrl() != null) { + cmd.setDstPool(getPoolFromVolumePath(dst.getAllocatedUrl())); + } httpCall(COPY_PATH, cmd, CopyRsp.class, new ReturnValueCompletion(comp) { @Override @@ -782,9 +924,11 @@ public void fail(ErrorCode errorCode) { } @Override - public void batchStats(Collection installPath, ReturnValueCompletion> comp) { + public void batchStats(Collection installPaths, ReturnValueCompletion> comp) { BatchQueryVolumeCmd cmd = new BatchQueryVolumeCmd(); - cmd.setInstallPaths(installPath); + + cmd.setInstallPaths(installPaths.stream().map(it -> convertZbsPathToCbdPath(it, this::getPhysicalPoolName)) + .collect(Collectors.toList())); httpCall(BATCH_QUERY_VOLUME_PATH, cmd, BatchQueryVolumeRsp.class, new ReturnValueCompletion(comp) { @Override @@ -985,28 +1129,47 @@ public void fail(ErrorCode errorCode) { } @Override - public void validateConfig(String config) { + public String validateConfig(String config) throws ApiMessageInterceptionException { Config old = JSONObjectUtil.toObject(self.getConfig(), Config.class); Config current = JSONObjectUtil.toObject(config, Config.class); + if (current.getLogicalPoolName() == null && !CollectionUtils.isEmpty(current.getPools())) { + if (current.getPoolNames().contains(old.getLogicalPoolName())) { + current.setLogicalPoolName(old.getLogicalPoolName()); + } else { + current.setLogicalPoolName(current.getPoolNames().get(0)); + } + } + + if (current.getLogicalPoolName() != null && CollectionUtils.isEmpty(current.getPools())) { + current.setPools(Arrays.asList(new Config.Pool(current.getLogicalPoolName(), null))); + } if (current.getLogicalPoolName().contains("/")) { - throw new CloudRuntimeException(String.format("invalid logical pool name[%s]", current.getLogicalPoolName())); + throw new ApiMessageInterceptionException(argerr("invalid logical pool name[%s]", current.getLogicalPoolName())); } - if (current.getMdsUrls().isEmpty()) { - throw new OperationFailureException(operr("ensure at least one MDS is configured")); + if (!current.getPoolNames().contains(current.getLogicalPoolName())) { + throw new ApiMessageInterceptionException(argerr("invalid pool name[%s]", current.getLogicalPoolName())); } - List newMdsInfos = parseMdsInfos(current.getMdsUrls()); + if (CollectionUtils.isEmpty(current.getPoolNames())) { + throw new ApiMessageInterceptionException(argerr("ensure at least one pool is configured")); + } + + if (CollectionUtils.isEmpty(current.getMdsUrls())) { + throw new ApiMessageInterceptionException(argerr("ensure at least one MDS is configured")); + } + + List newMdsInfos = MdsInfo.valueOf(current.getMdsUrls()); List duplicateMdsInfos = newMdsInfos.stream().collect(Collectors.groupingBy(MdsInfo::getAddr)) .values().stream().filter(addr -> addr.size() > 1).flatMap(List::stream).collect(Collectors.toList()); if (!duplicateMdsInfos.isEmpty()) { - throw new OperationFailureException(operr("do not allow to add duplicate MDS[%s]", + throw new ApiMessageInterceptionException(argerr("do not allow to add duplicate MDS[%s]", duplicateMdsInfos.stream().map(MdsInfo::getAddr).distinct().collect(Collectors.joining(", ")) )); } - List oldMdsInfos = parseMdsInfos(old.getMdsUrls()); + List oldMdsInfos = MdsInfo.valueOf(old.getMdsUrls()); List changedMdsInfos = newMdsInfos.stream().filter(n -> oldMdsInfos.stream().noneMatch(o -> o.equals(n))).collect(Collectors.toList()); if (!changedMdsInfos.isEmpty() && !CoreGlobalProperty.UNIT_TEST_ON) { List mdsList = CollectionUtils.transformToList(changedMdsInfos, ZbsPrimaryStorageMdsBase::new); @@ -1015,6 +1178,7 @@ public void validateConfig(String config) { base.checkStorageHealth(); } } + return JSONObjectUtil.toJsonString(current); } @Override @@ -1057,18 +1221,21 @@ private void reloadDbInfo() { self = dbf.reload(self); addonInfo = StringUtils.isEmpty(self.getAddonInfo()) ? new AddonInfo() : JSONObjectUtil.toObject(self.getAddonInfo(), AddonInfo.class); config = StringUtils.isEmpty(self.getConfig()) ? new Config() : JSONObjectUtil.toObject(self.getConfig(), Config.class); + physicalPoolByLogicalPool = addonInfo.getLogicalPoolInfos().stream() + .collect(Collectors.toMap(LogicalPoolInfo::getLogicalPoolName, LogicalPoolInfo::getPhysicalPoolName) ); } - private List parseMdsInfos(List mdsUrls) { - return mdsUrls.stream().map(mdsUrl -> { - MdsUri uri = new MdsUri(mdsUrl); - MdsInfo mdsInfo = new MdsInfo(); - mdsInfo.setUsername(uri.getUsername()); - mdsInfo.setPassword(uri.getPassword()); - mdsInfo.setPort(uri.getSshPort()); - mdsInfo.setAddr(uri.getHostname()); - return mdsInfo; - }).collect(Collectors.toList()); + protected String getPhysicalPoolName(String logicalPoolName) { + if (physicalPoolByLogicalPool.containsKey(logicalPoolName)) { + return physicalPoolByLogicalPool.get(logicalPoolName); + } else { + reloadDbInfo(); + String physicalPool = physicalPoolByLogicalPool.get(logicalPoolName); + if (physicalPool == null) { + throw new OperationFailureException(operr("cannot find physical pool for logical pool[%s]", logicalPoolName)); + } + return physicalPool; + } } protected T syncHttpCall(final String path, final AgentCommand cmd, final Class retClass) { @@ -1143,6 +1310,10 @@ HttpCaller setTargetMds(String mdsAddr) { } private void prepareCmd() { + if (cmd instanceof VolumeCommand) { + String cbdPath = convertZbsPathToCbdPath(((VolumeCommand) cmd).getPath(), ZbsStorageController.this::getPhysicalPoolName); + ((VolumeCommand) cmd).setPath(cbdPath); + } cmd.setUuid(self.getUuid()); } @@ -1200,6 +1371,13 @@ private void doCall() { ReturnValueCompletion completion = new ReturnValueCompletion(callback) { @Override public void success(T ret) { + if (ret instanceof VolumeResponse) { + String path = ((VolumeResponse) ret).installPath; + if (path != null && path.startsWith("cbd:")) { + ((VolumeResponse) ret).installPath = ZbsHelper.convertCbdPathToZbsPath(path); + } + } + callback.success(ret); } @@ -1241,64 +1419,10 @@ public void setSize(long size) { } } - public static class CopyRsp extends AgentResponse { - private String installPath; - private long size; - private long actualSize; - - public String getInstallPath() { - return installPath; - } - - public void setInstallPath(String installPath) { - this.installPath = installPath; - } - - public long getSize() { - return size; - } - - public void setSize(long size) { - this.size = size; - } - - public long getActualSize() { - return actualSize; - } - - public void setActualSize(long actualSize) { - this.actualSize = actualSize; - } + public static class CopyRsp extends VolumeResponse { } - public static class RollbackSnapshotRsp extends AgentResponse { - private String installPath; - private long size; - private long actualSize; - - public String getInstallPath() { - return installPath; - } - - public void setInstallPath(String installPath) { - this.installPath = installPath; - } - - public long getSize() { - return size; - } - - public void setSize(long size) { - this.size = size; - } - - public long getActualSize() { - return actualSize; - } - - public void setActualSize(long actualSize) { - this.actualSize = actualSize; - } + public static class RollbackSnapshotRsp extends VolumeResponse { } public static class DeleteSnapshotRsp extends AgentResponse { @@ -1372,97 +1496,16 @@ public void setPort(int port) { } } - public static class CloneVolumeRsp extends AgentResponse { - private long size; - private long actualSize; - private String installPath; - - public long getSize() { - return size; - } - - public void setSize(long size) { - this.size = size; - } - - public long getActualSize() { - return actualSize; - } - - public void setActualSize(long actualSize) { - this.actualSize = actualSize; - } - - public String getInstallPath() { - return installPath; - } - - public void setInstallPath(String installPath) { - this.installPath = installPath; - } + public static class CloneVolumeRsp extends VolumeResponse { } - public static class CreateSnapshotRsp extends AgentResponse { - private String installPath; - private long size; - private long actualSize; - - public String getInstallPath() { - return installPath; - } - - public void setInstallPath(String installPath) { - this.installPath = installPath; - } - - public long getSize() { - return size; - } - - public void setSize(long size) { - this.size = size; - } - - public long getActualSize() { - return actualSize; - } - - public void setActualSize(long actualSize) { - this.actualSize = actualSize; - } + public static class CreateSnapshotRsp extends VolumeResponse { } public static class DeleteVolumeRsp extends AgentResponse { } - public static class CreateVolumeRsp extends AgentResponse { - private String installPath; - private long size; - private long actualSize; - - public String getInstallPath() { - return installPath; - } - - public void setInstallPath(String installPath) { - this.installPath = installPath; - } - - public long getSize() { - return size; - } - - public void setSize(long size) { - this.size = size; - } - - public long getActualSize() { - return actualSize; - } - - public void setActualSize(long actualSize) { - this.actualSize = actualSize; - } + public static class CreateVolumeRsp extends VolumeResponse { } public static class GetCapacityRsp extends AgentResponse { @@ -1493,18 +1536,9 @@ public void setPath(String path) { } } - public static class CopyCmd extends AgentCommand implements HasThreadContext { - private String path; + public static class CopyCmd extends VolumeCommand implements HasThreadContext { private String dstVolume; - private long dstSize; - - public String getPath() { - return path; - } - - public void setPath(String path) { - this.path = path; - } + private String dstPool; public String getDstVolume() { return dstVolume; @@ -1514,61 +1548,25 @@ public void setDstVolume(String dstVolume) { this.dstVolume = dstVolume; } - public long getDstSize() { - return dstSize; + public void setDstPool(String dstPool) { + this.dstPool = dstPool; } - public void setDstSize(long dstSize) { - this.dstSize = dstSize; + public String getDstPool() { + return dstPool; } } - public static class RollbackSnapshotCmd extends AgentCommand { - private String path; - - public String getPath() { - return path; - } - - public void setPath(String path) { - this.path = path; - } + public static class RollbackSnapshotCmd extends VolumeCommand { } - public static class DeleteSnapshotCmd extends AgentCommand { - private String path; - - public String getPath() { - return path; - } - - public void setPath(String path) { - this.path = path; - } + public static class DeleteSnapshotCmd extends VolumeCommand { } - public static class QueryVolumeCmd extends AgentCommand { - private String path; - - public String getPath() { - return path; - } - - public void setPath(String path) { - this.path = path; - } + public static class QueryVolumeCmd extends VolumeCommand { } - public static class FlattenVolumeCmd extends AgentCommand { - private String path; - - public String getPath() { - return path; - } - - public void setPath(String path) { - this.path = path; - } + public static class FlattenVolumeCmd extends VolumeCommand { } public static class BatchQueryVolumeCmd extends AgentCommand { @@ -1604,18 +1602,9 @@ public void setPort(int port) { } } - public static class CbdToNbdCmd extends AgentCommand { - private String path; + public static class CbdToNbdCmd extends VolumeCommand { private String portRange; - public String getPath() { - return path; - } - - public void setPath(String path) { - this.path = path; - } - public String getPortRange() { return portRange; } @@ -1625,18 +1614,9 @@ public void setPortRange(String portRange) { } } - public static class CloneVolumeCmd extends AgentCommand { - private String path; + public static class CloneVolumeCmd extends VolumeCommand { private String dstVolume; - public String getPath() { - return path; - } - - public void setPath(String path) { - this.path = path; - } - public String getDstVolume() { return dstVolume; } @@ -1646,19 +1626,10 @@ public void setDstVolume(String dstVolume) { } } - public static class CreateSnapshotCmd extends AgentCommand { - private String path; + public static class CreateSnapshotCmd extends VolumeCommand { private String snapshot; private boolean skipOnExisting; - public String getPath() { - return path; - } - - public void setPath(String path) { - this.path = path; - } - public String getSnapshot() { return snapshot; } @@ -1676,18 +1647,9 @@ public void setSkipOnExisting(boolean skipOnExisting) { } } - public static class DeleteVolumeCmd extends AgentCommand { - private String path; + public static class DeleteVolumeCmd extends VolumeCommand { private boolean force; - public String getPath() { - return path; - } - - public void setPath(String path) { - this.path = path; - } - public boolean isForce() { return force; } @@ -1697,16 +1659,7 @@ public void setForce(boolean force) { } } - public static class GetVolumeClientsCmd extends AgentCommand { - private String path; - - public String getPath() { - return path; - } - - public void setPath(String path) { - this.path = path; - } + public static class GetVolumeClientsCmd extends VolumeCommand { } public static class ClientInfo { @@ -1766,6 +1719,14 @@ public String getUnit() { public void setUnit(String unit) { this.unit = unit; } + + public long getSizeInBytes() { + if (unit != null && unit.toLowerCase().startsWith("m")) { + return SizeUnit.MEGABYTE.toByte(size); + } else { + return size; + } + } } public static class CreateVolumeCmd extends SizeCmd { @@ -1799,14 +1760,14 @@ public void setSkipIfExisting(boolean skipIfExisting) { } public static class GetCapacityCmd extends AgentCommand { - private String logicalPool; + private List logicalPoolNames; - public String getLogicalPool() { - return logicalPool; + public List getLogicalPoolNames() { + return logicalPoolNames; } - public void setLogicalPool(String logicalPool) { - this.logicalPool = logicalPool; + public void setLogicalPoolNames(List logicalPoolNames) { + this.logicalPoolNames = logicalPoolNames; } } @@ -1873,9 +1834,8 @@ public void setVersion(String version) { public static class GetFactsCmd extends AgentCommand { } - public static class CheckHostStorageConnectionCmd extends AgentCommand { + public static class CheckHostStorageConnectionCmd extends VolumeCommand { public String hostUuid; - private String path; public String getHostUuid() { return hostUuid; @@ -1884,17 +1844,59 @@ public String getHostUuid() { public void setHostUuid(String hostUuid) { this.hostUuid = hostUuid; } + } + + public static class CheckHostStorageConnectionRsp extends AgentResponse { + } + + public static abstract class VolumeCommand extends AgentCommand { + protected String path; + + public void setPath(String path) { + this.path = path; + } public String getPath() { return path; } + } - public void setPath(String path) { - this.path = path; + public static abstract class VolumeResponse extends AgentResponse { + protected String installPath; + protected long size; + protected long actualSize; + + public void setInstallPath(String installPath) { + this.installPath = installPath; + } + + public String getInstallPath() { + return installPath; + } + + public long getSize() { + return size; + } + + public void setSize(long size) { + this.size = size; + } + + public long getActualSize() { + return actualSize; + } + + public void setActualSize(long actualSize) { + this.actualSize = actualSize; } } - public static class CheckHostStorageConnectionRsp extends AgentResponse { + public static class UpdateHostDependencyCmd extends AgentCommand { + public String updatePackages; + public String zstackRepo; + } + + public static class UpdateHostDependencyRsp extends AgentResponse { } public static class AgentResponse extends ZbsMdsBase.AgentResponse { @@ -1907,4 +1909,11 @@ public ZbsStorageController(ExternalPrimaryStorageVO self) { this.self = self; this.reloadDbInfo(); } + + public ZbsStorageController(String config) { + this.self = new ExternalPrimaryStorageVO(); + this.self.setConfig(config); + this.config = StringUtils.isEmpty(self.getConfig()) ? new Config() : JSONObjectUtil.toObject(self.getConfig(), Config.class); + this.addonInfo = new AddonInfo(); + } } diff --git a/plugin/zbs/src/main/java/org/zstack/storage/zbs/ZbsStorageFactory.java b/plugin/zbs/src/main/java/org/zstack/storage/zbs/ZbsStorageFactory.java index 43c95e77e7..0602c4dea8 100644 --- a/plugin/zbs/src/main/java/org/zstack/storage/zbs/ZbsStorageFactory.java +++ b/plugin/zbs/src/main/java/org/zstack/storage/zbs/ZbsStorageFactory.java @@ -3,6 +3,7 @@ import org.apache.commons.collections.CollectionUtils; import org.apache.commons.lang.StringUtils; import org.springframework.beans.factory.annotation.Autowired; +import org.zstack.core.ansible.SshFileMd5Checker; import org.zstack.core.cloudbus.CloudBus; import org.zstack.core.db.Q; import org.zstack.core.trash.StorageTrash; @@ -18,8 +19,13 @@ import org.zstack.header.volume.VolumeProtocol; import org.zstack.header.volume.VolumeVO; import org.zstack.header.volume.VolumeVO_; +import org.zstack.utils.ShellResult; +import org.zstack.utils.ShellUtils; import org.zstack.utils.Utils; +import org.zstack.utils.gson.JSONObjectUtil; import org.zstack.utils.logging.CLogger; +import org.zstack.utils.ssh.Ssh; +import org.zstack.utils.ssh.SshResult; import java.util.LinkedHashMap; import java.util.List; @@ -34,15 +40,10 @@ * @author Xingwei Yu * @date 2024/3/21 11:56 */ -public class ZbsStorageFactory implements ExternalPrimaryStorageSvcBuilder, BackupStorageSelector, VolumeSnapshotAfterDeleteExtensionPoint { +public class ZbsStorageFactory implements ExternalPrimaryStorageSvcBuilder, BackupStorageSelector { private static CLogger logger = Utils.getLogger(ZbsStorageFactory.class); public static final ExternalStorageFencerType fencerType = new ExternalStorageFencerType(ZbsConstants.IDENTITY, VolumeProtocol.CBD.toString()); - @Autowired - private CloudBus bus; - @Autowired - private StorageTrash trash; - private List preferBackupStorageTypes; @Override @@ -57,7 +58,53 @@ public PrimaryStorageNodeSvc buildNodeSvc(ExternalPrimaryStorageVO vo) { @Override public void discover(String url, String config, ReturnValueCompletion completion) { - completion.fail(operr("zbs not support discover yet")); + AddonInfo addonInfo = new AddonInfo(); + + Config conf = JSONObjectUtil.toObject(config, Config.class); + + if (CollectionUtils.isEmpty(conf.getMdsUrls())) { + completion.fail(operr("mdsUrls cannot be null or empty")); + return; + } + + String errInfo = ""; + for (MdsInfo mdsInfo : MdsInfo.valueOf(conf.getMdsUrls())) { + Ssh ssh = new Ssh(); + ssh.setUsername(mdsInfo.getUsername()) + .setPassword(mdsInfo.getPassword()).setPort(mdsInfo.getPort()) + .setHostname(mdsInfo.getAddr()) + .setTimeout(5); + try { + ssh.sudoCommand("/usr/bin/zbs list logical-pool --format json"); + SshResult ret = ssh.run(); + if (ret.getReturnCode() != 0) { + errInfo += String.format("failed to list logical pools from MDS[%s], because %s\n", mdsInfo.getAddr(), ret.getStderr()); + continue; + } + + ssh.reset(); + + String poolStr = ret.getStdout(); + ZbsListPoolResult result = JSONObjectUtil.toObject(poolStr, ZbsListPoolResult.class); + if (!result.isSuccess()) { + errInfo += String.format("failed to list logical pools from MDS[%s], because %s\n", mdsInfo.getAddr(), result.getError().getMessage()); + continue; + } + + for (ZbsListPoolResult.Result poolRet : result.getResult()) { + if (poolRet.getStatusCode() == 0) { + poolRet.getLogicalPoolInfos().forEach(it -> + addonInfo.addLogicalPoolInfo(LogicalPoolInfo.valueOf(it))); + } + } + completion.success(JSONObjectUtil.rehashObject(addonInfo, LinkedHashMap.class)); + return; + } finally { + ssh.close(); + } + } + + completion.fail(operr("unable to discover logical pools from all MDSs, details: %s", errInfo)); } public void setPreferBackupStorageTypes(List preferBackupStorageTypes) { @@ -73,39 +120,4 @@ public List getPreferBackupStorageTypes() { public String getIdentity() { return ZbsConstants.IDENTITY; } - - @Override - public void volumeSnapshotAfterDeleteExtensionPoint(VolumeSnapshotInventory snapshot, NoErrorCompletion completion) { - completion.done(); - } - - private boolean isCbdProtocol(String volumeUuid) { - return Q.New(VolumeVO.class).eq(VolumeVO_.protocol, VolumeProtocol.CBD.toString()).eq(VolumeVO_.uuid, volumeUuid).isExists(); - } - - @Override - public void volumeSnapshotAfterCleanUpExtensionPoint(String volumeUuid, List snapshots) { - if (CollectionUtils.isEmpty(snapshots) || !isCbdProtocol(volumeUuid)) { - return; - } - - Set volumeInstallPaths = snapshots.stream().map(s -> getVolumeFromSnapshotPath(s.getPrimaryStorageInstallPath())) - .collect(Collectors.toSet()); - if (volumeInstallPaths.isEmpty()) { - return; - } - - volumeInstallPaths.forEach(volumeInstallPath -> { - String details = trash.makeSureInstallPathNotUsed(volumeInstallPath, VolumeVO.class.getSimpleName()); - - if (StringUtils.isBlank(details)) { - logger.debug(String.format("delete volume[InstallPath:%s] after cleaning up snapshots", volumeInstallPath)); - DeleteVolumeBitsOnPrimaryStorageMsg msg = new DeleteVolumeBitsOnPrimaryStorageMsg(); - msg.setPrimaryStorageUuid(snapshots.get(0).getPrimaryStorageUuid()); - msg.setInstallPath(volumeInstallPath); - bus.makeTargetServiceIdByResourceUuid(msg, PrimaryStorageConstant.SERVICE_ID, snapshots.get(0).getPrimaryStorageUuid()); - bus.send(msg); - } - }); - } } diff --git a/rest/src/main/resources/scripts/RestDocumentationGenerator.groovy b/rest/src/main/resources/scripts/RestDocumentationGenerator.groovy index 3bad534aa2..c11a35e40a 100755 --- a/rest/src/main/resources/scripts/RestDocumentationGenerator.groovy +++ b/rest/src/main/resources/scripts/RestDocumentationGenerator.groovy @@ -832,6 +832,7 @@ class RestDocumentationGenerator implements DocumentGenerator { && 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 } } diff --git a/sdk/src/main/java/SourceClassMap.java b/sdk/src/main/java/SourceClassMap.java index 976ae5d4e4..4bbd9238f9 100644 --- a/sdk/src/main/java/SourceClassMap.java +++ b/sdk/src/main/java/SourceClassMap.java @@ -445,6 +445,9 @@ public class SourceClassMap { put("org.zstack.header.zwatch.AuditDataV2", "org.zstack.sdk.AuditDataV2"); put("org.zstack.hybrid.account.HybridAccountInventory", "org.zstack.sdk.HybridAccountInventory"); put("org.zstack.hybrid.core.HybridType", "org.zstack.sdk.HybridType"); + put("org.zstack.hygon.HygonCcpDeviceInventory", "org.zstack.sdk.HygonCcpDeviceInventory"); + put("org.zstack.hygon.HygonDeviceState", "org.zstack.sdk.HygonDeviceState"); + put("org.zstack.hygon.HygonDeviceType", "org.zstack.sdk.HygonDeviceType"); put("org.zstack.iam2.api.APIGetIAM2VirtualIDAPIPermissionMsg$APIPermissionStruct", "org.zstack.sdk.iam2.api.APIPermissionStruct"); put("org.zstack.iam2.api.APIGetIAM2VirtualIDAPIPermissionReply$Permission", "org.zstack.sdk.iam2.api.Permission"); put("org.zstack.iam2.api.Attribute", "org.zstack.sdk.iam2.api.Attribute"); @@ -504,6 +507,7 @@ public class SourceClassMap { put("org.zstack.license.header.server.LicenseAuthorizedCapacityServerUsageView", "org.zstack.sdk.license.header.server.LicenseAuthorizedCapacityServerUsageView"); put("org.zstack.license.header.server.LicenseAuthorizedCapacityUsageDetailView", "org.zstack.sdk.license.header.server.LicenseAuthorizedCapacityUsageDetailView"); put("org.zstack.license.header.server.LicenseAuthorizedNodeInventory", "org.zstack.sdk.license.header.server.LicenseAuthorizedNodeInventory"); + put("org.zstack.license.header.server.LicenseUsageDetailView", "org.zstack.sdk.license.header.server.LicenseUsageDetailView"); put("org.zstack.license.header.server.LicenseUsageView", "org.zstack.sdk.license.header.server.LicenseUsageView"); put("org.zstack.license.header.server.TotalLicenseAuthorizedCapacityView", "org.zstack.sdk.license.header.server.TotalLicenseAuthorizedCapacityView"); put("org.zstack.log.server.LogCategory", "org.zstack.sdk.LogCategory"); @@ -551,6 +555,7 @@ public class SourceClassMap { put("org.zstack.network.l2.vxlan.vxlanNetwork.L2VxlanNetworkInventory", "org.zstack.sdk.L2VxlanNetworkInventory"); put("org.zstack.network.l2.vxlan.vxlanNetworkPool.L2VxlanNetworkPoolInventory", "org.zstack.sdk.L2VxlanNetworkPoolInventory"); put("org.zstack.network.l2.vxlan.vxlanNetworkPool.VniRangeInventory", "org.zstack.sdk.VniRangeInventory"); + put("org.zstack.network.ovn.OvnControllerInventory", "org.zstack.sdk.OvnControllerInventory"); put("org.zstack.network.ovn.OvnControllerVmInstanceInventory", "org.zstack.sdk.OvnControllerVmInstanceInventory"); put("org.zstack.network.ovn.OvnControllerVmOfferingInventory", "org.zstack.sdk.OvnControllerVmOfferingInventory"); put("org.zstack.network.securitygroup.SecurityGroupIngressRuleTO", "org.zstack.sdk.SecurityGroupIngressRuleTO"); @@ -560,6 +565,14 @@ public class SourceClassMap { put("org.zstack.network.securitygroup.VmNicSecurityPolicyInventory", "org.zstack.sdk.VmNicSecurityPolicyInventory"); put("org.zstack.network.service.eip.EipInventory", "org.zstack.sdk.EipInventory"); put("org.zstack.network.service.flat.IpStatisticData", "org.zstack.sdk.IpStatisticData"); + put("org.zstack.network.service.header.nfvinstgroup.NfvInstClusterStatus", "org.zstack.sdk.NfvInstClusterStatus"); + put("org.zstack.network.service.header.nfvinstgroup.NfvInstGroupConfigTaskInventory", "org.zstack.sdk.NfvInstGroupConfigTaskInventory"); + put("org.zstack.network.service.header.nfvinstgroup.NfvInstGroupConstants$FuncType", "org.zstack.sdk.FuncType"); + put("org.zstack.network.service.header.nfvinstgroup.NfvInstGroupConstants$InstType", "org.zstack.sdk.InstType"); + put("org.zstack.network.service.header.nfvinstgroup.NfvInstGroupOperationMode", "org.zstack.sdk.NfvInstGroupOperationMode"); + put("org.zstack.network.service.header.nfvinstgroup.NfvInstGroupStatus", "org.zstack.sdk.NfvInstGroupStatus"); + put("org.zstack.network.service.header.nfvinstgroup.NfvInstInventory", "org.zstack.sdk.NfvInstInventory"); + put("org.zstack.network.service.header.nfvinstgroup.NfvInstOfferingInventory", "org.zstack.sdk.NfvInstOfferingInventory"); put("org.zstack.network.service.lb.APIChangeAccessControlListServerGroupEvent$LoadBalancerListerAcl", "org.zstack.sdk.LoadBalancerListerAcl"); put("org.zstack.network.service.lb.CertificateInventory", "org.zstack.sdk.CertificateInventory"); put("org.zstack.network.service.lb.LoadBalancerInventory", "org.zstack.sdk.LoadBalancerInventory"); @@ -571,6 +584,10 @@ public class SourceClassMap { put("org.zstack.network.service.lb.LoadBalancerServerGroupInventory", "org.zstack.sdk.LoadBalancerServerGroupInventory"); put("org.zstack.network.service.lb.LoadBalancerServerGroupServerIpInventory", "org.zstack.sdk.LoadBalancerServerGroupServerIpInventory"); put("org.zstack.network.service.lb.LoadBalancerServerGroupVmNicRefInventory", "org.zstack.sdk.LoadBalancerServerGroupVmNicRefInventory"); + put("org.zstack.network.service.nfvinstgroup.NfvInstGroupInventory", "org.zstack.sdk.NfvInstGroupInventory"); + put("org.zstack.network.service.nfvinstgroup.NfvInstGroupL3NetworkRefInventory", "org.zstack.sdk.NfvInstGroupL3NetworkRefInventory"); + put("org.zstack.network.service.nfvinstgroup.NfvInstGroupMonitorIpInventory", "org.zstack.sdk.NfvInstGroupMonitorIpInventory"); + put("org.zstack.network.service.nfvinstgroup.NfvInstGroupNetworkServiceRefInventory", "org.zstack.sdk.NfvInstGroupNetworkServiceRefInventory"); put("org.zstack.network.service.portforwarding.PortForwardingRuleInventory", "org.zstack.sdk.PortForwardingRuleInventory"); put("org.zstack.network.service.slb.SlbGroupInventory", "org.zstack.sdk.SlbGroupInventory"); put("org.zstack.network.service.slb.SlbGroupL3NetworkRefInventory", "org.zstack.sdk.SlbGroupL3NetworkRefInventory"); @@ -1059,6 +1076,7 @@ public class SourceClassMap { put("org.zstack.sdk.FlowCounter", "org.zstack.header.flowMeter.FlowCounter"); put("org.zstack.sdk.FlowMeterInventory", "org.zstack.header.flowMeter.FlowMeterInventory"); put("org.zstack.sdk.FreeIpInventory", "org.zstack.header.network.l3.FreeIpInventory"); + put("org.zstack.sdk.FuncType", "org.zstack.network.service.header.nfvinstgroup.NfvInstGroupConstants$FuncType"); put("org.zstack.sdk.GarbageCollectorInventory", "org.zstack.core.gc.GarbageCollectorInventory"); put("org.zstack.sdk.GlobalConfigInventory", "org.zstack.core.config.GlobalConfigInventory"); put("org.zstack.sdk.GlobalConfigOptions", "org.zstack.core.config.GlobalConfigOptions"); @@ -1103,6 +1121,9 @@ public class SourceClassMap { put("org.zstack.sdk.HybridEipAddressInventory", "org.zstack.header.hybrid.network.eip.HybridEipAddressInventory"); put("org.zstack.sdk.HybridEipStatus", "org.zstack.header.hybrid.network.eip.HybridEipStatus"); put("org.zstack.sdk.HybridType", "org.zstack.hybrid.core.HybridType"); + put("org.zstack.sdk.HygonCcpDeviceInventory", "org.zstack.hygon.HygonCcpDeviceInventory"); + put("org.zstack.sdk.HygonDeviceState", "org.zstack.hygon.HygonDeviceState"); + put("org.zstack.sdk.HygonDeviceType", "org.zstack.hygon.HygonDeviceType"); put("org.zstack.sdk.HypervisorVersionState", "org.zstack.kvm.hypervisor.datatype.HypervisorVersionState"); put("org.zstack.sdk.IPsecConnectionInventory", "org.zstack.ipsec.IPsecConnectionInventory"); put("org.zstack.sdk.IPsecL3NetworkRefInventory", "org.zstack.ipsec.IPsecL3NetworkRefInventory"); @@ -1124,6 +1145,7 @@ public class SourceClassMap { put("org.zstack.sdk.InfoSecSecretResourcePoolInventory", "org.zstack.crypto.securitymachine.thirdparty.infoSec.InfoSecSecretResourcePoolInventory"); put("org.zstack.sdk.InfoSecSecurityMachineInventory", "org.zstack.crypto.securitymachine.thirdparty.infoSec.InfoSecSecurityMachineInventory"); put("org.zstack.sdk.InputType", "org.zstack.abstraction.OptionType$InputType"); + put("org.zstack.sdk.InstType", "org.zstack.network.service.header.nfvinstgroup.NfvInstGroupConstants$InstType"); put("org.zstack.sdk.InstallPathRecycleInventory", "org.zstack.header.core.trash.InstallPathRecycleInventory"); put("org.zstack.sdk.InstanceOfferingInventory", "org.zstack.header.configuration.InstanceOfferingInventory"); put("org.zstack.sdk.InvocationRecord", "org.zstack.guesttools.InvocationRecord"); @@ -1246,6 +1268,16 @@ public class SourceClassMap { put("org.zstack.sdk.NetworkRouterFlowMeterRefInventory", "org.zstack.header.flowMeter.NetworkRouterFlowMeterRefInventory"); put("org.zstack.sdk.NetworkServiceL3NetworkRefInventory", "org.zstack.header.network.service.NetworkServiceL3NetworkRefInventory"); put("org.zstack.sdk.NetworkServiceProviderInventory", "org.zstack.header.network.service.NetworkServiceProviderInventory"); + put("org.zstack.sdk.NfvInstClusterStatus", "org.zstack.network.service.header.nfvinstgroup.NfvInstClusterStatus"); + put("org.zstack.sdk.NfvInstGroupConfigTaskInventory", "org.zstack.network.service.header.nfvinstgroup.NfvInstGroupConfigTaskInventory"); + put("org.zstack.sdk.NfvInstGroupInventory", "org.zstack.network.service.nfvinstgroup.NfvInstGroupInventory"); + put("org.zstack.sdk.NfvInstGroupL3NetworkRefInventory", "org.zstack.network.service.nfvinstgroup.NfvInstGroupL3NetworkRefInventory"); + put("org.zstack.sdk.NfvInstGroupMonitorIpInventory", "org.zstack.network.service.nfvinstgroup.NfvInstGroupMonitorIpInventory"); + put("org.zstack.sdk.NfvInstGroupNetworkServiceRefInventory", "org.zstack.network.service.nfvinstgroup.NfvInstGroupNetworkServiceRefInventory"); + put("org.zstack.sdk.NfvInstGroupOperationMode", "org.zstack.network.service.header.nfvinstgroup.NfvInstGroupOperationMode"); + put("org.zstack.sdk.NfvInstGroupStatus", "org.zstack.network.service.header.nfvinstgroup.NfvInstGroupStatus"); + put("org.zstack.sdk.NfvInstInventory", "org.zstack.network.service.header.nfvinstgroup.NfvInstInventory"); + put("org.zstack.sdk.NfvInstOfferingInventory", "org.zstack.network.service.header.nfvinstgroup.NfvInstOfferingInventory"); put("org.zstack.sdk.NginxRedirectRule", "org.zstack.ai.NginxRedirectRule"); put("org.zstack.sdk.NicTO", "org.zstack.kvm.KVMAgentCommands$NicTO"); put("org.zstack.sdk.NormalIpRangeInventory", "org.zstack.header.network.l3.NormalIpRangeInventory"); @@ -1272,6 +1304,7 @@ public class SourceClassMap { put("org.zstack.sdk.OvfOSInfo", "org.zstack.ovf.datatype.OvfOSInfo"); put("org.zstack.sdk.OvfSystemInfo", "org.zstack.ovf.datatype.OvfSystemInfo"); put("org.zstack.sdk.OvfVolumeInfo", "org.zstack.ovf.datatype.OvfVolumeInfo"); + put("org.zstack.sdk.OvnControllerInventory", "org.zstack.network.ovn.OvnControllerInventory"); put("org.zstack.sdk.OvnControllerVmInstanceInventory", "org.zstack.network.ovn.OvnControllerVmInstanceInventory"); put("org.zstack.sdk.OvnControllerVmOfferingInventory", "org.zstack.network.ovn.OvnControllerVmOfferingInventory"); put("org.zstack.sdk.PacketsForwardType", "org.zstack.vpcfirewall.entity.PacketsForwardType"); @@ -1622,6 +1655,7 @@ public class SourceClassMap { put("org.zstack.sdk.license.header.server.LicenseAuthorizedCapacityServerUsageView", "org.zstack.license.header.server.LicenseAuthorizedCapacityServerUsageView"); put("org.zstack.sdk.license.header.server.LicenseAuthorizedCapacityUsageDetailView", "org.zstack.license.header.server.LicenseAuthorizedCapacityUsageDetailView"); put("org.zstack.sdk.license.header.server.LicenseAuthorizedNodeInventory", "org.zstack.license.header.server.LicenseAuthorizedNodeInventory"); + 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.sns.SNSAliyunSmsEndpointInventory", "org.zstack.sns.SNSAliyunSmsEndpointInventory"); diff --git a/sdk/src/main/java/org/zstack/sdk/AddL3NetworkToGroupAction.java b/sdk/src/main/java/org/zstack/sdk/AddL3NetworkToGroupAction.java new file mode 100644 index 0000000000..6debe67663 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/AddL3NetworkToGroupAction.java @@ -0,0 +1,110 @@ +package org.zstack.sdk; + +import java.util.HashMap; +import java.util.Map; +import org.zstack.sdk.*; + +public class AddL3NetworkToGroupAction 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.AddL3NetworkToGroupResult value; + + public Result throwExceptionIfError() { + if (error != null) { + throw new ApiException( + String.format("error[code: %s, description: %s, details: %s]", error.code, error.description, error.details) + ); + } + + return this; + } + } + + @Param(required = true, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String nfvInstGroupUuid; + + @Param(required = true, maxLength = 255, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String networkServiceUuid; + + @Param(required = true, nonempty = true, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String frontEndL3NetworkUuid; + + @Param(required = true, nonempty = true, nullElements = false, emptyString = true, noTrim = false) + public java.util.List backendL3NetworkUuids; + + @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.AddL3NetworkToGroupResult value = res.getResult(org.zstack.sdk.AddL3NetworkToGroupResult.class); + ret.value = value == null ? new org.zstack.sdk.AddL3NetworkToGroupResult() : 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 = "/nfvinstgroup/group/{nfvInstGroupUuid}/service/{networkServiceUuid}"; + info.needSession = true; + info.needPoll = true; + info.parameterName = "params"; + return info; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/AddL3NetworkToGroupResult.java b/sdk/src/main/java/org/zstack/sdk/AddL3NetworkToGroupResult.java new file mode 100644 index 0000000000..1978cd77ee --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/AddL3NetworkToGroupResult.java @@ -0,0 +1,7 @@ +package org.zstack.sdk; + + + +public class AddL3NetworkToGroupResult { + +} diff --git a/sdk/src/main/java/org/zstack/sdk/AddModelAction.java b/sdk/src/main/java/org/zstack/sdk/AddModelAction.java index 2dc39539fb..a43fcee825 100644 --- a/sdk/src/main/java/org/zstack/sdk/AddModelAction.java +++ b/sdk/src/main/java/org/zstack/sdk/AddModelAction.java @@ -61,6 +61,12 @@ public Result throwExceptionIfError() { @Param(required = false, nonempty = false, nullElements = false, emptyString = true, noTrim = false) public java.util.List modelServiceUuids; + @Param(required = false, maxLength = 255, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String recommendedGpuNum; + + @Param(required = false, maxLength = 512, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String gpuConstraintDescription; + @Param(required = false) public java.lang.String resourceUuid; diff --git a/sdk/src/main/java/org/zstack/sdk/AddModelServiceAction.java b/sdk/src/main/java/org/zstack/sdk/AddModelServiceAction.java index 01d2193ea6..3062782ee5 100644 --- a/sdk/src/main/java/org/zstack/sdk/AddModelServiceAction.java +++ b/sdk/src/main/java/org/zstack/sdk/AddModelServiceAction.java @@ -55,6 +55,12 @@ public Result throwExceptionIfError() { @Param(required = true, nonempty = false, nullElements = false, emptyString = true, noTrim = false) public java.lang.String startCommand; + @Param(required = false, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String containerCommand; + + @Param(required = false, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String containerArgs; + @Param(required = false, nonempty = false, nullElements = false, emptyString = true, noTrim = false) public java.lang.String pythonVersion; diff --git a/sdk/src/main/java/org/zstack/sdk/AttachNfvInstToGroupAction.java b/sdk/src/main/java/org/zstack/sdk/AttachNfvInstToGroupAction.java new file mode 100644 index 0000000000..fd8e59ca2d --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/AttachNfvInstToGroupAction.java @@ -0,0 +1,104 @@ +package org.zstack.sdk; + +import java.util.HashMap; +import java.util.Map; +import org.zstack.sdk.*; + +public class AttachNfvInstToGroupAction 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.AttachNfvInstToGroupResult value; + + public Result throwExceptionIfError() { + if (error != null) { + throw new ApiException( + String.format("error[code: %s, description: %s, details: %s]", error.code, error.description, error.details) + ); + } + + return this; + } + } + + @Param(required = true, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String groupUuid; + + @Param(required = true, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String nfvInstUuid; + + @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.AttachNfvInstToGroupResult value = res.getResult(org.zstack.sdk.AttachNfvInstToGroupResult.class); + ret.value = value == null ? new org.zstack.sdk.AttachNfvInstToGroupResult() : 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 = "/nfvinstgroup/group/{groupUuid}/instances/{nfvInstUuid}/actions"; + info.needSession = true; + info.needPoll = true; + info.parameterName = "attachNfvInstToGroup"; + return info; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/AttachNfvInstToGroupResult.java b/sdk/src/main/java/org/zstack/sdk/AttachNfvInstToGroupResult.java new file mode 100644 index 0000000000..06f1ad1a31 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/AttachNfvInstToGroupResult.java @@ -0,0 +1,14 @@ +package org.zstack.sdk; + +import org.zstack.sdk.NfvInstGroupInventory; + +public class AttachNfvInstToGroupResult { + public NfvInstGroupInventory inventory; + public void setInventory(NfvInstGroupInventory inventory) { + this.inventory = inventory; + } + public NfvInstGroupInventory getInventory() { + return this.inventory; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/ChangeNfvInstGroupOperationModeAction.java b/sdk/src/main/java/org/zstack/sdk/ChangeNfvInstGroupOperationModeAction.java new file mode 100644 index 0000000000..216987116a --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/ChangeNfvInstGroupOperationModeAction.java @@ -0,0 +1,104 @@ +package org.zstack.sdk; + +import java.util.HashMap; +import java.util.Map; +import org.zstack.sdk.*; + +public class ChangeNfvInstGroupOperationModeAction 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.ChangeNfvInstGroupOperationModeResult value; + + public Result throwExceptionIfError() { + if (error != null) { + throw new ApiException( + String.format("error[code: %s, description: %s, details: %s]", error.code, error.description, error.details) + ); + } + + return this; + } + } + + @Param(required = true, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String uuid; + + @Param(required = true, validValues = {"Normal","Maintenance"}, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String operationMode; + + @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.ChangeNfvInstGroupOperationModeResult value = res.getResult(org.zstack.sdk.ChangeNfvInstGroupOperationModeResult.class); + ret.value = value == null ? new org.zstack.sdk.ChangeNfvInstGroupOperationModeResult() : 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 = "/nfvinstgroup/group/{uuid}/actions"; + info.needSession = true; + info.needPoll = true; + info.parameterName = "changeNfvInstGroupOperationMode"; + return info; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/ChangeNfvInstGroupOperationModeResult.java b/sdk/src/main/java/org/zstack/sdk/ChangeNfvInstGroupOperationModeResult.java new file mode 100644 index 0000000000..8547853342 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/ChangeNfvInstGroupOperationModeResult.java @@ -0,0 +1,14 @@ +package org.zstack.sdk; + +import org.zstack.sdk.NfvInstGroupInventory; + +public class ChangeNfvInstGroupOperationModeResult { + public NfvInstGroupInventory inventory; + public void setInventory(NfvInstGroupInventory inventory) { + this.inventory = inventory; + } + public NfvInstGroupInventory getInventory() { + return this.inventory; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/CloneModelServiceAction.java b/sdk/src/main/java/org/zstack/sdk/CloneModelServiceAction.java index 37bad5494f..d8a876b518 100644 --- a/sdk/src/main/java/org/zstack/sdk/CloneModelServiceAction.java +++ b/sdk/src/main/java/org/zstack/sdk/CloneModelServiceAction.java @@ -49,6 +49,12 @@ public Result throwExceptionIfError() { @Param(required = false, nonempty = false, nullElements = false, emptyString = true, noTrim = false) public java.lang.String startCommand; + @Param(required = false, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String containerCommand; + + @Param(required = false, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String containerArgs; + @Param(required = false, nonempty = false, nullElements = false, emptyString = true, noTrim = false) public java.lang.String pythonVersion; diff --git a/sdk/src/main/java/org/zstack/sdk/CreateNfvInstAction.java b/sdk/src/main/java/org/zstack/sdk/CreateNfvInstAction.java new file mode 100644 index 0000000000..c120ee97ec --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/CreateNfvInstAction.java @@ -0,0 +1,122 @@ +package org.zstack.sdk; + +import java.util.HashMap; +import java.util.Map; +import org.zstack.sdk.*; + +public class CreateNfvInstAction 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.CreateNfvInstResult value; + + public Result throwExceptionIfError() { + if (error != null) { + throw new ApiException( + String.format("error[code: %s, description: %s, details: %s]", error.code, error.description, error.details) + ); + } + + return this; + } + } + + @Param(required = true, maxLength = 255, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String name; + + @Param(required = true, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String nfvInstGroupUuid; + + @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, noTrim = false) + public java.lang.String zoneUuid; + + @Param(required = false, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String clusterUuid; + + @Param(required = false, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String hostUuid; + + @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.CreateNfvInstResult value = res.getResult(org.zstack.sdk.CreateNfvInstResult.class); + ret.value = value == null ? new org.zstack.sdk.CreateNfvInstResult() : 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 = "/nfvinstgroup/inst"; + info.needSession = true; + info.needPoll = true; + info.parameterName = "params"; + return info; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/CreateNfvInstGroupAction.java b/sdk/src/main/java/org/zstack/sdk/CreateNfvInstGroupAction.java new file mode 100644 index 0000000000..3055d319f1 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/CreateNfvInstGroupAction.java @@ -0,0 +1,152 @@ +package org.zstack.sdk; + +import java.util.HashMap; +import java.util.Map; +import org.zstack.sdk.*; + +public class CreateNfvInstGroupAction 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.CreateNfvInstGroupResult value; + + public Result throwExceptionIfError() { + if (error != null) { + throw new ApiException( + String.format("error[code: %s, description: %s, details: %s]", error.code, error.description, error.details) + ); + } + + 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 = {"KVM"}, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String instType; + + @Param(required = true, validValues = {"DEDICATED_SLB","OVN_SDN_CONTROLLER"}, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String funcType; + + @Param(required = false, nonempty = true, nullElements = false, emptyString = true, noTrim = false) + public java.util.List monitorIps; + + @Param(required = true, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String nfvInstOfferingUuid; + + @Param(required = false, nonempty = true, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String frontEndL3NetworkUuid; + + @Param(required = false, nonempty = true, nullElements = false, emptyString = true, noTrim = false) + public java.util.List backendL3NetworkUuids; + + @Param(required = false, maxLength = 128, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String netOsDistro; + + @Param(required = false, maxLength = 128, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String baseOsDistro; + + @Param(required = false, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String vipUuid; + + @Param(required = false, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String ipv6VipUuid; + + @Param(required = false, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String primaryStorageUuid; + + @Param(required = false, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String primaryStoragePoolUuid; + + @Param(required = false, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String clusterUuid; + + @Param(required = false, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String zoneUuid; + + @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.CreateNfvInstGroupResult value = res.getResult(org.zstack.sdk.CreateNfvInstGroupResult.class); + ret.value = value == null ? new org.zstack.sdk.CreateNfvInstGroupResult() : 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 = "/nfvinstgroup/group"; + info.needSession = true; + info.needPoll = true; + info.parameterName = "params"; + return info; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/CreateNfvInstGroupResult.java b/sdk/src/main/java/org/zstack/sdk/CreateNfvInstGroupResult.java new file mode 100644 index 0000000000..906a877947 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/CreateNfvInstGroupResult.java @@ -0,0 +1,14 @@ +package org.zstack.sdk; + +import org.zstack.sdk.NfvInstGroupInventory; + +public class CreateNfvInstGroupResult { + public NfvInstGroupInventory inventory; + public void setInventory(NfvInstGroupInventory inventory) { + this.inventory = inventory; + } + public NfvInstGroupInventory getInventory() { + return this.inventory; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/CreateNfvInstOfferingAction.java b/sdk/src/main/java/org/zstack/sdk/CreateNfvInstOfferingAction.java new file mode 100644 index 0000000000..33267766ff --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/CreateNfvInstOfferingAction.java @@ -0,0 +1,137 @@ +package org.zstack.sdk; + +import java.util.HashMap; +import java.util.Map; +import org.zstack.sdk.*; + +public class CreateNfvInstOfferingAction 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.CreateInstanceOfferingResult value; + + public Result throwExceptionIfError() { + if (error != null) { + throw new ApiException( + String.format("error[code: %s, description: %s, details: %s]", error.code, error.description, error.details) + ); + } + + return this; + } + } + + @Param(required = true, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String zoneUuid; + + @Param(required = true, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String managementNetworkUuid; + + @Param(required = true, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String imageUuid; + + @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, numberRange = {1L,1024L}, noTrim = false) + public int cpuNum = 0; + + @Param(required = true, nonempty = false, nullElements = false, emptyString = true, numberRange = {1L,9223372036854775807L}, numberRangeUnit = {"byte", "bytes"}, noTrim = false) + public long memorySize = 0L; + + @Param(required = false, nonempty = false, nullElements = false, emptyString = true, numberRange = {0L,9223372036854775807L}, numberRangeUnit = {"byte", "bytes"}, noTrim = false) + public long reservedMemorySize = 0L; + + @Param(required = false) + public java.lang.String allocatorStrategy; + + @Param(required = false) + public int sortKey = 0; + + @Param(required = false) + public java.lang.String type; + + @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.CreateInstanceOfferingResult value = res.getResult(org.zstack.sdk.CreateInstanceOfferingResult.class); + ret.value = value == null ? new org.zstack.sdk.CreateInstanceOfferingResult() : 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 = "/instance-offerings/nfvinst"; + info.needSession = true; + info.needPoll = true; + info.parameterName = "params"; + return info; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/CreateNfvInstResult.java b/sdk/src/main/java/org/zstack/sdk/CreateNfvInstResult.java new file mode 100644 index 0000000000..adf8ae3f1a --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/CreateNfvInstResult.java @@ -0,0 +1,14 @@ +package org.zstack.sdk; + +import org.zstack.sdk.NfvInstInventory; + +public class CreateNfvInstResult { + public NfvInstInventory inventory; + public void setInventory(NfvInstInventory inventory) { + this.inventory = inventory; + } + public NfvInstInventory getInventory() { + return this.inventory; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/CreateSlbInstanceAction.java b/sdk/src/main/java/org/zstack/sdk/CreateSlbInstanceAction.java index 7019e2c999..4be292428e 100644 --- a/sdk/src/main/java/org/zstack/sdk/CreateSlbInstanceAction.java +++ b/sdk/src/main/java/org/zstack/sdk/CreateSlbInstanceAction.java @@ -43,6 +43,12 @@ public Result throwExceptionIfError() { @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 primaryStorageUuidForRootVolume; + + @Param(required = false, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.util.List rootVolumeSystemTags; + @Param(required = false) public java.lang.String resourceUuid; diff --git a/sdk/src/main/java/org/zstack/sdk/DeleteModelEvaluationTasksResult.java b/sdk/src/main/java/org/zstack/sdk/DeleteModelEvaluationTasksResult.java index 5d1619bb4e..9da05d4467 100644 --- a/sdk/src/main/java/org/zstack/sdk/DeleteModelEvaluationTasksResult.java +++ b/sdk/src/main/java/org/zstack/sdk/DeleteModelEvaluationTasksResult.java @@ -3,5 +3,12 @@ public class DeleteModelEvaluationTasksResult { + public java.util.List results; + public void setResults(java.util.List results) { + this.results = results; + } + public java.util.List getResults() { + return this.results; + } } diff --git a/sdk/src/main/java/org/zstack/sdk/DeleteNfvInstGroupAction.java b/sdk/src/main/java/org/zstack/sdk/DeleteNfvInstGroupAction.java new file mode 100644 index 0000000000..87d07827ae --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/DeleteNfvInstGroupAction.java @@ -0,0 +1,104 @@ +package org.zstack.sdk; + +import java.util.HashMap; +import java.util.Map; +import org.zstack.sdk.*; + +public class DeleteNfvInstGroupAction 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.DeleteNfvInstGroupResult value; + + public Result throwExceptionIfError() { + if (error != null) { + throw new ApiException( + String.format("error[code: %s, description: %s, details: %s]", error.code, error.description, error.details) + ); + } + + 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.DeleteNfvInstGroupResult value = res.getResult(org.zstack.sdk.DeleteNfvInstGroupResult.class); + ret.value = value == null ? new org.zstack.sdk.DeleteNfvInstGroupResult() : 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 = "/nfvinstgroup/group/{uuid}"; + info.needSession = true; + info.needPoll = true; + info.parameterName = ""; + return info; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/DeleteNfvInstGroupResult.java b/sdk/src/main/java/org/zstack/sdk/DeleteNfvInstGroupResult.java new file mode 100644 index 0000000000..f453cb866a --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/DeleteNfvInstGroupResult.java @@ -0,0 +1,7 @@ +package org.zstack.sdk; + + + +public class DeleteNfvInstGroupResult { + +} diff --git a/sdk/src/main/java/org/zstack/sdk/DeployAppDevelopmentServiceAction.java b/sdk/src/main/java/org/zstack/sdk/DeployAppDevelopmentServiceAction.java index 536310c17d..2ab7e2b846 100644 --- a/sdk/src/main/java/org/zstack/sdk/DeployAppDevelopmentServiceAction.java +++ b/sdk/src/main/java/org/zstack/sdk/DeployAppDevelopmentServiceAction.java @@ -79,6 +79,12 @@ public Result throwExceptionIfError() { @Param(required = false, nonempty = false, nullElements = false, emptyString = true, noTrim = false) public java.lang.Integer serviceBootUptime; + @Param(required = false, maxLength = 255, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String serviceLivez; + + @Param(required = false, maxLength = 255, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String serviceReadyz; + @Param(required = false, nonempty = false, nullElements = false, emptyString = true, noTrim = false) public java.lang.String rootDiskOfferingUuid; diff --git a/sdk/src/main/java/org/zstack/sdk/DeployModelEvalServiceAction.java b/sdk/src/main/java/org/zstack/sdk/DeployModelEvalServiceAction.java index dd3c2933a1..bf4c6abc18 100644 --- a/sdk/src/main/java/org/zstack/sdk/DeployModelEvalServiceAction.java +++ b/sdk/src/main/java/org/zstack/sdk/DeployModelEvalServiceAction.java @@ -130,6 +130,12 @@ public Result throwExceptionIfError() { @Param(required = false, nonempty = false, nullElements = false, emptyString = true, noTrim = false) public java.lang.Integer serviceBootUptime; + @Param(required = false, maxLength = 255, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String serviceLivez; + + @Param(required = false, maxLength = 255, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String serviceReadyz; + @Param(required = false, nonempty = false, nullElements = false, emptyString = true, noTrim = false) public java.lang.String rootDiskOfferingUuid; diff --git a/sdk/src/main/java/org/zstack/sdk/DeployModelServiceAction.java b/sdk/src/main/java/org/zstack/sdk/DeployModelServiceAction.java index 9c73bee8da..61ee415881 100644 --- a/sdk/src/main/java/org/zstack/sdk/DeployModelServiceAction.java +++ b/sdk/src/main/java/org/zstack/sdk/DeployModelServiceAction.java @@ -79,6 +79,12 @@ public Result throwExceptionIfError() { @Param(required = false, nonempty = false, nullElements = false, emptyString = true, noTrim = false) public java.lang.Integer serviceBootUptime; + @Param(required = false, maxLength = 255, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String serviceLivez; + + @Param(required = false, maxLength = 255, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String serviceReadyz; + @Param(required = false, nonempty = false, nullElements = false, emptyString = true, noTrim = false) public java.lang.String rootDiskOfferingUuid; diff --git a/sdk/src/main/java/org/zstack/sdk/DetachNfvInstFromGroupAction.java b/sdk/src/main/java/org/zstack/sdk/DetachNfvInstFromGroupAction.java new file mode 100644 index 0000000000..06a5eaebc7 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/DetachNfvInstFromGroupAction.java @@ -0,0 +1,104 @@ +package org.zstack.sdk; + +import java.util.HashMap; +import java.util.Map; +import org.zstack.sdk.*; + +public class DetachNfvInstFromGroupAction 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.DetachNfvInstFromGroupResult value; + + public Result throwExceptionIfError() { + if (error != null) { + throw new ApiException( + String.format("error[code: %s, description: %s, details: %s]", error.code, error.description, error.details) + ); + } + + return this; + } + } + + @Param(required = true, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String groupUuid; + + @Param(required = true, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String nfvInstUuid; + + @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.DetachNfvInstFromGroupResult value = res.getResult(org.zstack.sdk.DetachNfvInstFromGroupResult.class); + ret.value = value == null ? new org.zstack.sdk.DetachNfvInstFromGroupResult() : 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 = "/nfvinstgroup/group/{groupUuid}/instances/{nfvInstUuid}/actions"; + info.needSession = true; + info.needPoll = true; + info.parameterName = "detachNfvInstFromGroup"; + return info; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/DetachNfvInstFromGroupResult.java b/sdk/src/main/java/org/zstack/sdk/DetachNfvInstFromGroupResult.java new file mode 100644 index 0000000000..677e458513 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/DetachNfvInstFromGroupResult.java @@ -0,0 +1,14 @@ +package org.zstack.sdk; + +import org.zstack.sdk.NfvInstGroupInventory; + +public class DetachNfvInstFromGroupResult { + public NfvInstGroupInventory inventory; + public void setInventory(NfvInstGroupInventory inventory) { + this.inventory = inventory; + } + public NfvInstGroupInventory getInventory() { + return this.inventory; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/FuncType.java b/sdk/src/main/java/org/zstack/sdk/FuncType.java new file mode 100644 index 0000000000..51c1cd4f5d --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/FuncType.java @@ -0,0 +1,5 @@ +package org.zstack.sdk; + +public enum FuncType { + OVN_SDN_CONTROLLER, +} diff --git a/sdk/src/main/java/org/zstack/sdk/GenerateHygonMdevDevicesAction.java b/sdk/src/main/java/org/zstack/sdk/GenerateHygonMdevDevicesAction.java new file mode 100644 index 0000000000..32bf219601 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/GenerateHygonMdevDevicesAction.java @@ -0,0 +1,104 @@ +package org.zstack.sdk; + +import java.util.HashMap; +import java.util.Map; +import org.zstack.sdk.*; + +public class GenerateHygonMdevDevicesAction 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.GenerateHygonMdevDevicesResult value; + + public Result throwExceptionIfError() { + if (error != null) { + throw new ApiException( + String.format("error[code: %s, description: %s, details: %s]", error.code, error.description, error.details) + ); + } + + return this; + } + } + + @Param(required = true, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String hostUuid; + + @Param(required = true, nonempty = false, nullElements = false, emptyString = true, numberRange = {1L,1024L}, noTrim = false) + public java.lang.Integer maxQemuNum; + + @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.GenerateHygonMdevDevicesResult value = res.getResult(org.zstack.sdk.GenerateHygonMdevDevicesResult.class); + ret.value = value == null ? new org.zstack.sdk.GenerateHygonMdevDevicesResult() : 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 = "/hygon-devices/{hostUuid}/actions"; + info.needSession = true; + info.needPoll = true; + info.parameterName = "generateHygonMdevDevices"; + return info; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/GenerateHygonMdevDevicesResult.java b/sdk/src/main/java/org/zstack/sdk/GenerateHygonMdevDevicesResult.java new file mode 100644 index 0000000000..e8ee3052e9 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/GenerateHygonMdevDevicesResult.java @@ -0,0 +1,7 @@ +package org.zstack.sdk; + + + +public class GenerateHygonMdevDevicesResult { + +} diff --git a/sdk/src/main/java/org/zstack/sdk/GenerateModelMetadataAction.java b/sdk/src/main/java/org/zstack/sdk/GenerateModelMetadataAction.java index 9d52805be3..435e738b09 100644 --- a/sdk/src/main/java/org/zstack/sdk/GenerateModelMetadataAction.java +++ b/sdk/src/main/java/org/zstack/sdk/GenerateModelMetadataAction.java @@ -12,7 +12,7 @@ public class GenerateModelMetadataAction extends AbstractAction { public static class Result { public ErrorCode error; - public org.zstack.sdk.DeployModelServiceResult value; + public org.zstack.sdk.GenerateModelMetadataResult value; public Result throwExceptionIfError() { if (error != null) { @@ -63,8 +63,8 @@ private Result makeResult(ApiResult res) { return ret; } - org.zstack.sdk.DeployModelServiceResult value = res.getResult(org.zstack.sdk.DeployModelServiceResult.class); - ret.value = value == null ? new org.zstack.sdk.DeployModelServiceResult() : value; + org.zstack.sdk.GenerateModelMetadataResult value = res.getResult(org.zstack.sdk.GenerateModelMetadataResult.class); + ret.value = value == null ? new org.zstack.sdk.GenerateModelMetadataResult() : value; return ret; } diff --git a/sdk/src/main/java/org/zstack/sdk/GetTwoFactorAuthenticationSecretAction.java b/sdk/src/main/java/org/zstack/sdk/GetTwoFactorAuthenticationSecretAction.java index 7968d3fe2b..6023de4803 100644 --- a/sdk/src/main/java/org/zstack/sdk/GetTwoFactorAuthenticationSecretAction.java +++ b/sdk/src/main/java/org/zstack/sdk/GetTwoFactorAuthenticationSecretAction.java @@ -31,7 +31,7 @@ public Result throwExceptionIfError() { @Param(required = true, nonempty = true, nullElements = false, emptyString = true, noTrim = false) public java.lang.String password; - @Param(required = true, validValues = {"account","iam2"}, nonempty = true, nullElements = false, emptyString = true, noTrim = false) + @Param(required = true, validValues = {"account","iam2","iam2-ldap"}, nonempty = true, nullElements = false, emptyString = true, noTrim = false) public java.lang.String type; @Param(required = false, nonempty = false, nullElements = false, emptyString = true, noTrim = false) diff --git a/sdk/src/main/java/org/zstack/sdk/GpuDeviceInventory.java b/sdk/src/main/java/org/zstack/sdk/GpuDeviceInventory.java index c45b9f27ba..587c9cbeae 100644 --- a/sdk/src/main/java/org/zstack/sdk/GpuDeviceInventory.java +++ b/sdk/src/main/java/org/zstack/sdk/GpuDeviceInventory.java @@ -44,6 +44,14 @@ public java.lang.String getGpuType() { return this.gpuType; } + public java.lang.String gpuStatus; + public void setGpuStatus(java.lang.String gpuStatus) { + this.gpuStatus = gpuStatus; + } + public java.lang.String getGpuStatus() { + return this.gpuStatus; + } + public GpuAllocateStatus allocateStatus; public void setAllocateStatus(GpuAllocateStatus allocateStatus) { this.allocateStatus = allocateStatus; diff --git a/sdk/src/main/java/org/zstack/sdk/GpuDeviceSpecInventory.java b/sdk/src/main/java/org/zstack/sdk/GpuDeviceSpecInventory.java index 24d0532f3c..e043f206e5 100644 --- a/sdk/src/main/java/org/zstack/sdk/GpuDeviceSpecInventory.java +++ b/sdk/src/main/java/org/zstack/sdk/GpuDeviceSpecInventory.java @@ -12,4 +12,20 @@ public java.lang.Long getMemory() { return this.memory; } + public java.lang.String gpuType; + public void setGpuType(java.lang.String gpuType) { + this.gpuType = gpuType; + } + public java.lang.String getGpuType() { + return this.gpuType; + } + + public java.lang.Boolean isolated; + public void setIsolated(java.lang.Boolean isolated) { + this.isolated = isolated; + } + public java.lang.Boolean getIsolated() { + return this.isolated; + } + } diff --git a/sdk/src/main/java/org/zstack/sdk/GpuVendor.java b/sdk/src/main/java/org/zstack/sdk/GpuVendor.java index ef07274374..d5f4842085 100644 --- a/sdk/src/main/java/org/zstack/sdk/GpuVendor.java +++ b/sdk/src/main/java/org/zstack/sdk/GpuVendor.java @@ -1,11 +1,11 @@ package org.zstack.sdk; public enum GpuVendor { - INTEL, + Intel, AMD, NVIDIA, - HAIGUANG, - HUAWEI, - TIANSHU, - OTHER, + Haiguang, + Huawei, + TianShu, + Other, } diff --git a/sdk/src/main/java/org/zstack/sdk/HygonCcpDeviceInventory.java b/sdk/src/main/java/org/zstack/sdk/HygonCcpDeviceInventory.java new file mode 100644 index 0000000000..fead1fac8f --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/HygonCcpDeviceInventory.java @@ -0,0 +1,112 @@ +package org.zstack.sdk; + +import org.zstack.sdk.HygonDeviceType; +import org.zstack.sdk.HygonDeviceState; + +public class HygonCcpDeviceInventory { + + 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 hostUuid; + public void setHostUuid(java.lang.String hostUuid) { + this.hostUuid = hostUuid; + } + public java.lang.String getHostUuid() { + return this.hostUuid; + } + + public java.lang.String pciBdf; + public void setPciBdf(java.lang.String pciBdf) { + this.pciBdf = pciBdf; + } + public java.lang.String getPciBdf() { + return this.pciBdf; + } + + public HygonDeviceType deviceType; + public void setDeviceType(HygonDeviceType deviceType) { + this.deviceType = deviceType; + } + public HygonDeviceType getDeviceType() { + return this.deviceType; + } + + public java.lang.String deviceId; + public void setDeviceId(java.lang.String deviceId) { + this.deviceId = deviceId; + } + public java.lang.String getDeviceId() { + return this.deviceId; + } + + public java.lang.String driverStatus; + public void setDriverStatus(java.lang.String driverStatus) { + this.driverStatus = driverStatus; + } + public java.lang.String getDriverStatus() { + return this.driverStatus; + } + + public java.lang.Boolean isMasterPsp; + public void setIsMasterPsp(java.lang.Boolean isMasterPsp) { + this.isMasterPsp = isMasterPsp; + } + public java.lang.Boolean getIsMasterPsp() { + return this.isMasterPsp; + } + + public java.lang.Integer vendorIdx; + public void setVendorIdx(java.lang.Integer vendorIdx) { + this.vendorIdx = vendorIdx; + } + public java.lang.Integer getVendorIdx() { + return this.vendorIdx; + } + + public HygonDeviceState state; + public void setState(HygonDeviceState state) { + this.state = state; + } + public HygonDeviceState 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/HygonDeviceState.java b/sdk/src/main/java/org/zstack/sdk/HygonDeviceState.java new file mode 100644 index 0000000000..3e50b7c458 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/HygonDeviceState.java @@ -0,0 +1,6 @@ +package org.zstack.sdk; + +public enum HygonDeviceState { + Enabled, + Disabled, +} diff --git a/sdk/src/main/java/org/zstack/sdk/HygonDeviceType.java b/sdk/src/main/java/org/zstack/sdk/HygonDeviceType.java new file mode 100644 index 0000000000..2784ddf741 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/HygonDeviceType.java @@ -0,0 +1,6 @@ +package org.zstack.sdk; + +public enum HygonDeviceType { + NTBCCP, + PSPCCP, +} diff --git a/sdk/src/main/java/org/zstack/sdk/InstType.java b/sdk/src/main/java/org/zstack/sdk/InstType.java new file mode 100644 index 0000000000..401d988a3b --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/InstType.java @@ -0,0 +1,7 @@ +package org.zstack.sdk; + +public enum InstType { + KVM, + CONTAINER, + HOST, +} diff --git a/sdk/src/main/java/org/zstack/sdk/MatchModelServiceTemplateWithModelAction.java b/sdk/src/main/java/org/zstack/sdk/MatchModelServiceTemplateWithModelAction.java index 7d6d97cb2c..be243bba4d 100644 --- a/sdk/src/main/java/org/zstack/sdk/MatchModelServiceTemplateWithModelAction.java +++ b/sdk/src/main/java/org/zstack/sdk/MatchModelServiceTemplateWithModelAction.java @@ -88,6 +88,12 @@ public Result throwExceptionIfError() { @Param(required = false, nonempty = false, nullElements = false, emptyString = true, noTrim = false) public java.lang.Integer serviceBootUptime; + @Param(required = false, maxLength = 255, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String serviceLivez; + + @Param(required = false, maxLength = 255, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String serviceReadyz; + @Param(required = false, nonempty = false, nullElements = false, emptyString = true, noTrim = false) public java.lang.String rootDiskOfferingUuid; diff --git a/sdk/src/main/java/org/zstack/sdk/MdevDeviceSpecInventory.java b/sdk/src/main/java/org/zstack/sdk/MdevDeviceSpecInventory.java index 0360c59dbd..c3b2fc5b0e 100644 --- a/sdk/src/main/java/org/zstack/sdk/MdevDeviceSpecInventory.java +++ b/sdk/src/main/java/org/zstack/sdk/MdevDeviceSpecInventory.java @@ -77,4 +77,12 @@ public java.sql.Timestamp getLastOpDate() { return this.lastOpDate; } + public java.lang.Integer maxAvailableDevicesPerHost; + public void setMaxAvailableDevicesPerHost(java.lang.Integer maxAvailableDevicesPerHost) { + this.maxAvailableDevicesPerHost = maxAvailableDevicesPerHost; + } + public java.lang.Integer getMaxAvailableDevicesPerHost() { + return this.maxAvailableDevicesPerHost; + } + } diff --git a/sdk/src/main/java/org/zstack/sdk/MdevDeviceType.java b/sdk/src/main/java/org/zstack/sdk/MdevDeviceType.java index a2ff1befcc..cb58e93b76 100644 --- a/sdk/src/main/java/org/zstack/sdk/MdevDeviceType.java +++ b/sdk/src/main/java/org/zstack/sdk/MdevDeviceType.java @@ -6,4 +6,5 @@ public enum MdevDeviceType { GPU_Processing_Accelerators, GPU_Co_Processor, GPU_3D_Controller, + GPU_Communication_Controller, } diff --git a/sdk/src/main/java/org/zstack/sdk/ModelInventory.java b/sdk/src/main/java/org/zstack/sdk/ModelInventory.java index a2ff03462f..ec46d527ee 100644 --- a/sdk/src/main/java/org/zstack/sdk/ModelInventory.java +++ b/sdk/src/main/java/org/zstack/sdk/ModelInventory.java @@ -116,6 +116,22 @@ public java.lang.Long getMinGpuMemory() { return this.minGpuMemory; } + public java.util.List recommendedGpuNum; + public void setRecommendedGpuNum(java.util.List recommendedGpuNum) { + this.recommendedGpuNum = recommendedGpuNum; + } + public java.util.List getRecommendedGpuNum() { + return this.recommendedGpuNum; + } + + public java.lang.String gpuConstraintDescription; + public void setGpuConstraintDescription(java.lang.String gpuConstraintDescription) { + this.gpuConstraintDescription = gpuConstraintDescription; + } + public java.lang.String getGpuConstraintDescription() { + return this.gpuConstraintDescription; + } + public java.lang.String versionSemver; public void setVersionSemver(java.lang.String versionSemver) { this.versionSemver = versionSemver; diff --git a/sdk/src/main/java/org/zstack/sdk/ModelService.java b/sdk/src/main/java/org/zstack/sdk/ModelService.java index 60c82ea684..cc765e6749 100644 --- a/sdk/src/main/java/org/zstack/sdk/ModelService.java +++ b/sdk/src/main/java/org/zstack/sdk/ModelService.java @@ -172,6 +172,22 @@ public java.lang.Integer getServiceBootUptime() { return this.serviceBootUptime; } + public java.lang.String serviceLivez; + public void setServiceLivez(java.lang.String serviceLivez) { + this.serviceLivez = serviceLivez; + } + public java.lang.String getServiceLivez() { + return this.serviceLivez; + } + + public java.lang.String serviceReadyz; + public void setServiceReadyz(java.lang.String serviceReadyz) { + this.serviceReadyz = serviceReadyz; + } + public java.lang.String getServiceReadyz() { + return this.serviceReadyz; + } + public java.lang.String rootDiskOfferingUuid; public void setRootDiskOfferingUuid(java.lang.String rootDiskOfferingUuid) { this.rootDiskOfferingUuid = rootDiskOfferingUuid; diff --git a/sdk/src/main/java/org/zstack/sdk/ModelServiceInstanceGroupInventory.java b/sdk/src/main/java/org/zstack/sdk/ModelServiceInstanceGroupInventory.java index 8720f3ff25..25ad17e970 100644 --- a/sdk/src/main/java/org/zstack/sdk/ModelServiceInstanceGroupInventory.java +++ b/sdk/src/main/java/org/zstack/sdk/ModelServiceInstanceGroupInventory.java @@ -108,4 +108,12 @@ public java.lang.String getYaml() { return this.yaml; } + public java.util.List supportMetrics; + public void setSupportMetrics(java.util.List supportMetrics) { + this.supportMetrics = supportMetrics; + } + public java.util.List getSupportMetrics() { + return this.supportMetrics; + } + } diff --git a/sdk/src/main/java/org/zstack/sdk/ModelServiceInventory.java b/sdk/src/main/java/org/zstack/sdk/ModelServiceInventory.java index a588313c06..3b0d649572 100644 --- a/sdk/src/main/java/org/zstack/sdk/ModelServiceInventory.java +++ b/sdk/src/main/java/org/zstack/sdk/ModelServiceInventory.java @@ -148,6 +148,22 @@ public java.lang.String getStartCommand() { return this.startCommand; } + public java.lang.String containerCommand; + public void setContainerCommand(java.lang.String containerCommand) { + this.containerCommand = containerCommand; + } + public java.lang.String getContainerCommand() { + return this.containerCommand; + } + + public java.lang.String containerArgs; + public void setContainerArgs(java.lang.String containerArgs) { + this.containerArgs = containerArgs; + } + public java.lang.String getContainerArgs() { + return this.containerArgs; + } + public boolean supportDistributed; public void setSupportDistributed(boolean supportDistributed) { this.supportDistributed = supportDistributed; diff --git a/sdk/src/main/java/org/zstack/sdk/NfvInstClusterStatus.java b/sdk/src/main/java/org/zstack/sdk/NfvInstClusterStatus.java new file mode 100644 index 0000000000..f096486270 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/NfvInstClusterStatus.java @@ -0,0 +1,12 @@ +package org.zstack.sdk; + +public enum NfvInstClusterStatus { + Follower, + Candidate, + Leader, + Joining, + Leaving, + Unknown, + Available, + Unavailable, +} diff --git a/sdk/src/main/java/org/zstack/sdk/NfvInstGroupConfigTaskInventory.java b/sdk/src/main/java/org/zstack/sdk/NfvInstGroupConfigTaskInventory.java new file mode 100644 index 0000000000..eb1ef267ed --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/NfvInstGroupConfigTaskInventory.java @@ -0,0 +1,71 @@ +package org.zstack.sdk; + + + +public class NfvInstGroupConfigTaskInventory { + + public long id; + public void setId(long id) { + this.id = id; + } + public long getId() { + return this.id; + } + + public java.lang.String nfvInstGroupUuid; + public void setNfvInstGroupUuid(java.lang.String nfvInstGroupUuid) { + this.nfvInstGroupUuid = nfvInstGroupUuid; + } + public java.lang.String getNfvInstGroupUuid() { + return this.nfvInstGroupUuid; + } + + public int configVersion; + public void setConfigVersion(int configVersion) { + this.configVersion = configVersion; + } + public int getConfigVersion() { + return this.configVersion; + } + + public java.lang.String serviceUuid; + public void setServiceUuid(java.lang.String serviceUuid) { + this.serviceUuid = serviceUuid; + } + public java.lang.String getServiceUuid() { + return this.serviceUuid; + } + + public java.lang.String taskName; + public void setTaskName(java.lang.String taskName) { + this.taskName = taskName; + } + public java.lang.String getTaskName() { + return this.taskName; + } + + public java.lang.String taskData; + public void setTaskData(java.lang.String taskData) { + this.taskData = taskData; + } + public java.lang.String getTaskData() { + return this.taskData; + } + + public java.lang.String path; + public void setPath(java.lang.String path) { + this.path = path; + } + public java.lang.String getPath() { + return this.path; + } + + public boolean checkStatus; + public void setCheckStatus(boolean checkStatus) { + this.checkStatus = checkStatus; + } + public boolean getCheckStatus() { + return this.checkStatus; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/NfvInstGroupInventory.java b/sdk/src/main/java/org/zstack/sdk/NfvInstGroupInventory.java new file mode 100644 index 0000000000..ff44f5c5e3 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/NfvInstGroupInventory.java @@ -0,0 +1,210 @@ +package org.zstack.sdk; + +import org.zstack.sdk.InstType; +import org.zstack.sdk.FuncType; +import org.zstack.sdk.NfvInstGroupStatus; +import org.zstack.sdk.NfvInstGroupOperationMode; + +public class NfvInstGroupInventory { + + 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 uuid; + public void setUuid(java.lang.String uuid) { + this.uuid = uuid; + } + public java.lang.String getUuid() { + return this.uuid; + } + + 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 nfvInstOfferingUuid; + public void setNfvInstOfferingUuid(java.lang.String nfvInstOfferingUuid) { + this.nfvInstOfferingUuid = nfvInstOfferingUuid; + } + public java.lang.String getNfvInstOfferingUuid() { + return this.nfvInstOfferingUuid; + } + + public InstType instType; + public void setInstType(InstType instType) { + this.instType = instType; + } + public InstType getInstType() { + return this.instType; + } + + public FuncType funcType; + public void setFuncType(FuncType funcType) { + this.funcType = funcType; + } + public FuncType getFuncType() { + return this.funcType; + } + + public int configVersion; + public void setConfigVersion(int configVersion) { + this.configVersion = configVersion; + } + public int getConfigVersion() { + return this.configVersion; + } + + public java.lang.String netOsDistro; + public void setNetOsDistro(java.lang.String netOsDistro) { + this.netOsDistro = netOsDistro; + } + public java.lang.String getNetOsDistro() { + return this.netOsDistro; + } + + public java.lang.String baseOsDistro; + public void setBaseOsDistro(java.lang.String baseOsDistro) { + this.baseOsDistro = baseOsDistro; + } + public java.lang.String getBaseOsDistro() { + return this.baseOsDistro; + } + + public NfvInstGroupStatus status; + public void setStatus(NfvInstGroupStatus status) { + this.status = status; + } + public NfvInstGroupStatus getStatus() { + return this.status; + } + + public java.lang.String statusDetail; + public void setStatusDetail(java.lang.String statusDetail) { + this.statusDetail = statusDetail; + } + public java.lang.String getStatusDetail() { + return this.statusDetail; + } + + public NfvInstGroupOperationMode operationMode; + public void setOperationMode(NfvInstGroupOperationMode operationMode) { + this.operationMode = operationMode; + } + public NfvInstGroupOperationMode getOperationMode() { + return this.operationMode; + } + + 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.List instances; + public void setInstances(java.util.List instances) { + this.instances = instances; + } + public java.util.List getInstances() { + return this.instances; + } + + public java.util.List monitors; + public void setMonitors(java.util.List monitors) { + this.monitors = monitors; + } + public java.util.List getMonitors() { + return this.monitors; + } + + public java.util.List services; + public void setServices(java.util.List services) { + this.services = services; + } + public java.util.List getServices() { + return this.services; + } + + public java.util.List configTasks; + public void setConfigTasks(java.util.List configTasks) { + this.configTasks = configTasks; + } + public java.util.List getConfigTasks() { + return this.configTasks; + } + + public java.util.List l3Networks; + public void setL3Networks(java.util.List l3Networks) { + this.l3Networks = l3Networks; + } + public java.util.List getL3Networks() { + return this.l3Networks; + } + + public java.lang.String vipUuid; + public void setVipUuid(java.lang.String vipUuid) { + this.vipUuid = vipUuid; + } + public java.lang.String getVipUuid() { + return this.vipUuid; + } + + public java.lang.String ipv6VipUuid; + public void setIpv6VipUuid(java.lang.String ipv6VipUuid) { + this.ipv6VipUuid = ipv6VipUuid; + } + public java.lang.String getIpv6VipUuid() { + return this.ipv6VipUuid; + } + + public java.lang.String primaryStorageUuid; + public void setPrimaryStorageUuid(java.lang.String primaryStorageUuid) { + this.primaryStorageUuid = primaryStorageUuid; + } + public java.lang.String getPrimaryStorageUuid() { + return this.primaryStorageUuid; + } + + public java.lang.String primaryStoragePoolUuid; + public void setPrimaryStoragePoolUuid(java.lang.String primaryStoragePoolUuid) { + this.primaryStoragePoolUuid = primaryStoragePoolUuid; + } + public java.lang.String getPrimaryStoragePoolUuid() { + return this.primaryStoragePoolUuid; + } + + public java.lang.String clusterUuid; + public void setClusterUuid(java.lang.String clusterUuid) { + this.clusterUuid = clusterUuid; + } + public java.lang.String getClusterUuid() { + return this.clusterUuid; + } + + public java.lang.String zoneUuid; + public void setZoneUuid(java.lang.String zoneUuid) { + this.zoneUuid = zoneUuid; + } + public java.lang.String getZoneUuid() { + return this.zoneUuid; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/NfvInstGroupL3NetworkRefInventory.java b/sdk/src/main/java/org/zstack/sdk/NfvInstGroupL3NetworkRefInventory.java new file mode 100644 index 0000000000..803c948a30 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/NfvInstGroupL3NetworkRefInventory.java @@ -0,0 +1,71 @@ +package org.zstack.sdk; + + + +public class NfvInstGroupL3NetworkRefInventory { + + public java.lang.String nfvInstGroupUuid; + public void setNfvInstGroupUuid(java.lang.String nfvInstGroupUuid) { + this.nfvInstGroupUuid = nfvInstGroupUuid; + } + public java.lang.String getNfvInstGroupUuid() { + return this.nfvInstGroupUuid; + } + + public java.lang.String networkServiceUuid; + public void setNetworkServiceUuid(java.lang.String networkServiceUuid) { + this.networkServiceUuid = networkServiceUuid; + } + public java.lang.String getNetworkServiceUuid() { + return this.networkServiceUuid; + } + + public java.lang.String l3NetworkUuid; + public void setL3NetworkUuid(java.lang.String l3NetworkUuid) { + this.l3NetworkUuid = l3NetworkUuid; + } + public java.lang.String getL3NetworkUuid() { + return this.l3NetworkUuid; + } + + public java.lang.String l3NetworkCategory; + public void setL3NetworkCategory(java.lang.String l3NetworkCategory) { + this.l3NetworkCategory = l3NetworkCategory; + } + public java.lang.String getL3NetworkCategory() { + return this.l3NetworkCategory; + } + + public java.lang.String l3NetworkType; + public void setL3NetworkType(java.lang.String l3NetworkType) { + this.l3NetworkType = l3NetworkType; + } + public java.lang.String getL3NetworkType() { + return this.l3NetworkType; + } + + 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.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/NfvInstGroupMonitorIpInventory.java b/sdk/src/main/java/org/zstack/sdk/NfvInstGroupMonitorIpInventory.java new file mode 100644 index 0000000000..d6fe52906a --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/NfvInstGroupMonitorIpInventory.java @@ -0,0 +1,47 @@ +package org.zstack.sdk; + + + +public class NfvInstGroupMonitorIpInventory { + + public java.lang.Long id; + public void setId(java.lang.Long id) { + this.id = id; + } + public java.lang.Long getId() { + return this.id; + } + + public java.lang.String nfvInstGroupUuid; + public void setNfvInstGroupUuid(java.lang.String nfvInstGroupUuid) { + this.nfvInstGroupUuid = nfvInstGroupUuid; + } + public java.lang.String getNfvInstGroupUuid() { + return this.nfvInstGroupUuid; + } + + public java.lang.String monitorIp; + public void setMonitorIp(java.lang.String monitorIp) { + this.monitorIp = monitorIp; + } + public java.lang.String getMonitorIp() { + return this.monitorIp; + } + + 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/NfvInstGroupNetworkServiceRefInventory.java b/sdk/src/main/java/org/zstack/sdk/NfvInstGroupNetworkServiceRefInventory.java new file mode 100644 index 0000000000..43b5a53c68 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/NfvInstGroupNetworkServiceRefInventory.java @@ -0,0 +1,55 @@ +package org.zstack.sdk; + + + +public class NfvInstGroupNetworkServiceRefInventory { + + public java.lang.Long id; + public void setId(java.lang.Long id) { + this.id = id; + } + public java.lang.Long getId() { + return this.id; + } + + public java.lang.String nfvInstGroupUuid; + public void setNfvInstGroupUuid(java.lang.String nfvInstGroupUuid) { + this.nfvInstGroupUuid = nfvInstGroupUuid; + } + public java.lang.String getNfvInstGroupUuid() { + return this.nfvInstGroupUuid; + } + + public java.lang.String networkServiceName; + public void setNetworkServiceName(java.lang.String networkServiceName) { + this.networkServiceName = networkServiceName; + } + public java.lang.String getNetworkServiceName() { + return this.networkServiceName; + } + + public java.lang.String networkServiceUuid; + public void setNetworkServiceUuid(java.lang.String networkServiceUuid) { + this.networkServiceUuid = networkServiceUuid; + } + public java.lang.String getNetworkServiceUuid() { + return this.networkServiceUuid; + } + + 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/NfvInstGroupOperationMode.java b/sdk/src/main/java/org/zstack/sdk/NfvInstGroupOperationMode.java new file mode 100644 index 0000000000..1c692e49f1 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/NfvInstGroupOperationMode.java @@ -0,0 +1,6 @@ +package org.zstack.sdk; + +public enum NfvInstGroupOperationMode { + Normal, + Maintenance, +} diff --git a/sdk/src/main/java/org/zstack/sdk/NfvInstGroupStatus.java b/sdk/src/main/java/org/zstack/sdk/NfvInstGroupStatus.java new file mode 100644 index 0000000000..fc9c165afa --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/NfvInstGroupStatus.java @@ -0,0 +1,9 @@ +package org.zstack.sdk; + +public enum NfvInstGroupStatus { + Initializing, + Healthy, + Degraded, + Operating, + Unavailable, +} diff --git a/sdk/src/main/java/org/zstack/sdk/NfvInstInventory.java b/sdk/src/main/java/org/zstack/sdk/NfvInstInventory.java new file mode 100644 index 0000000000..d84863093a --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/NfvInstInventory.java @@ -0,0 +1,55 @@ +package org.zstack.sdk; + + + +public class NfvInstInventory extends org.zstack.sdk.ApplianceVmInventory { + + public int configVersion; + public void setConfigVersion(int configVersion) { + this.configVersion = configVersion; + } + public int getConfigVersion() { + return this.configVersion; + } + + public java.lang.String nfvInstGroupUuid; + public void setNfvInstGroupUuid(java.lang.String nfvInstGroupUuid) { + this.nfvInstGroupUuid = nfvInstGroupUuid; + } + public java.lang.String getNfvInstGroupUuid() { + return this.nfvInstGroupUuid; + } + + public java.lang.String netOsDistro; + public void setNetOsDistro(java.lang.String netOsDistro) { + this.netOsDistro = netOsDistro; + } + public java.lang.String getNetOsDistro() { + return this.netOsDistro; + } + + public java.lang.String baseOsDistro; + public void setBaseOsDistro(java.lang.String baseOsDistro) { + this.baseOsDistro = baseOsDistro; + } + public java.lang.String getBaseOsDistro() { + return this.baseOsDistro; + } + + public java.lang.String clusterStatus; + public void setClusterStatus(java.lang.String clusterStatus) { + this.clusterStatus = clusterStatus; + } + public java.lang.String getClusterStatus() { + return this.clusterStatus; + } + + public java.lang.String statusDetail; + public void setStatusDetail(java.lang.String statusDetail) { + this.statusDetail = statusDetail; + } + public java.lang.String getStatusDetail() { + return this.statusDetail; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/NfvInstOfferingInventory.java b/sdk/src/main/java/org/zstack/sdk/NfvInstOfferingInventory.java new file mode 100644 index 0000000000..42f92383fa --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/NfvInstOfferingInventory.java @@ -0,0 +1,31 @@ +package org.zstack.sdk; + + + +public class NfvInstOfferingInventory extends org.zstack.sdk.InstanceOfferingInventory { + + public java.lang.String managementNetworkUuid; + public void setManagementNetworkUuid(java.lang.String managementNetworkUuid) { + this.managementNetworkUuid = managementNetworkUuid; + } + public java.lang.String getManagementNetworkUuid() { + return this.managementNetworkUuid; + } + + 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 imageUuid; + public void setImageUuid(java.lang.String imageUuid) { + this.imageUuid = imageUuid; + } + public java.lang.String getImageUuid() { + return this.imageUuid; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/NicTO.java b/sdk/src/main/java/org/zstack/sdk/NicTO.java index 2dc95ea852..6eecb1466a 100644 --- a/sdk/src/main/java/org/zstack/sdk/NicTO.java +++ b/sdk/src/main/java/org/zstack/sdk/NicTO.java @@ -149,6 +149,14 @@ public java.lang.String getPciDeviceAddress() { return this.pciDeviceAddress; } + public java.util.List extraPciDeviceAddresses; + public void setExtraPciDeviceAddresses(java.util.List extraPciDeviceAddresses) { + this.extraPciDeviceAddresses = extraPciDeviceAddresses; + } + public java.util.List getExtraPciDeviceAddresses() { + return this.extraPciDeviceAddresses; + } + public java.lang.String ipForTf; public void setIpForTf(java.lang.String ipForTf) { this.ipForTf = ipForTf; diff --git a/sdk/src/main/java/org/zstack/sdk/OvnControllerInventory.java b/sdk/src/main/java/org/zstack/sdk/OvnControllerInventory.java new file mode 100644 index 0000000000..7b5a4d9504 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/OvnControllerInventory.java @@ -0,0 +1,15 @@ +package org.zstack.sdk; + + + +public class OvnControllerInventory extends org.zstack.sdk.SdnControllerInventory { + + public boolean remoteOvn; + public void setRemoteOvn(boolean remoteOvn) { + this.remoteOvn = remoteOvn; + } + public boolean getRemoteOvn() { + return this.remoteOvn; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/OvnControllerVmInstanceInventory.java b/sdk/src/main/java/org/zstack/sdk/OvnControllerVmInstanceInventory.java index 3a68e782b2..dcee2e7aaf 100644 --- a/sdk/src/main/java/org/zstack/sdk/OvnControllerVmInstanceInventory.java +++ b/sdk/src/main/java/org/zstack/sdk/OvnControllerVmInstanceInventory.java @@ -1,8 +1,24 @@ package org.zstack.sdk; +import org.zstack.sdk.NfvInstClusterStatus; +import org.zstack.sdk.NfvInstClusterStatus; +public class OvnControllerVmInstanceInventory extends org.zstack.sdk.NfvInstInventory { -public class OvnControllerVmInstanceInventory extends org.zstack.sdk.ApplianceVmInventory { + public NfvInstClusterStatus nbClusterStatus; + public void setNbClusterStatus(NfvInstClusterStatus nbClusterStatus) { + this.nbClusterStatus = nbClusterStatus; + } + public NfvInstClusterStatus getNbClusterStatus() { + return this.nbClusterStatus; + } + public NfvInstClusterStatus sbClusterStatus; + public void setSbClusterStatus(NfvInstClusterStatus sbClusterStatus) { + this.sbClusterStatus = sbClusterStatus; + } + public NfvInstClusterStatus getSbClusterStatus() { + return this.sbClusterStatus; + } } diff --git a/sdk/src/main/java/org/zstack/sdk/PciDeviceInventory.java b/sdk/src/main/java/org/zstack/sdk/PciDeviceInventory.java index 7dec375572..06e7e5885c 100644 --- a/sdk/src/main/java/org/zstack/sdk/PciDeviceInventory.java +++ b/sdk/src/main/java/org/zstack/sdk/PciDeviceInventory.java @@ -185,6 +185,14 @@ public java.lang.String getRev() { return this.rev; } + public java.lang.String dependentDevices; + public void setDependentDevices(java.lang.String dependentDevices) { + this.dependentDevices = dependentDevices; + } + public java.lang.String getDependentDevices() { + return this.dependentDevices; + } + 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/PciDeviceSpecInventory.java b/sdk/src/main/java/org/zstack/sdk/PciDeviceSpecInventory.java index 99b34405fe..6bead4ce0d 100644 --- a/sdk/src/main/java/org/zstack/sdk/PciDeviceSpecInventory.java +++ b/sdk/src/main/java/org/zstack/sdk/PciDeviceSpecInventory.java @@ -157,4 +157,12 @@ public java.sql.Timestamp getLastOpDate() { return this.lastOpDate; } + public java.lang.Integer maxAvailableDevicesPerHost; + public void setMaxAvailableDevicesPerHost(java.lang.Integer maxAvailableDevicesPerHost) { + this.maxAvailableDevicesPerHost = maxAvailableDevicesPerHost; + } + public java.lang.Integer getMaxAvailableDevicesPerHost() { + return this.maxAvailableDevicesPerHost; + } + } diff --git a/sdk/src/main/java/org/zstack/sdk/PciDeviceType.java b/sdk/src/main/java/org/zstack/sdk/PciDeviceType.java index 2d6cc7a4ba..a81359354f 100644 --- a/sdk/src/main/java/org/zstack/sdk/PciDeviceType.java +++ b/sdk/src/main/java/org/zstack/sdk/PciDeviceType.java @@ -8,6 +8,7 @@ public enum PciDeviceType { GPU_3D_Controller, GPU_Processing_Accelerators, GPU_Co_Processor, + GPU_Communication_Controller, Ethernet_Controller, Audio_Controller, USB_Controller, diff --git a/sdk/src/main/java/org/zstack/sdk/PrimaryStorageMigrateVmAction.java b/sdk/src/main/java/org/zstack/sdk/PrimaryStorageMigrateVmAction.java index 60e8edc102..49641300f2 100644 --- a/sdk/src/main/java/org/zstack/sdk/PrimaryStorageMigrateVmAction.java +++ b/sdk/src/main/java/org/zstack/sdk/PrimaryStorageMigrateVmAction.java @@ -52,6 +52,9 @@ public Result throwExceptionIfError() { @Param(required = false, nonempty = false, nullElements = false, emptyString = true, noTrim = false) public long bandwidth = 0L; + @Param(required = false, validValues = {"Specified","FollowVolume","FollowDestPrimaryStorage"}, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String volumeProvisioningStrategy = "FollowDestPrimaryStorage"; + @Param(required = false) public java.util.List systemTags; diff --git a/sdk/src/main/java/org/zstack/sdk/PrimaryStorageMigrateVolumeAction.java b/sdk/src/main/java/org/zstack/sdk/PrimaryStorageMigrateVolumeAction.java index ed88a0bd61..7ed53f5ebc 100644 --- a/sdk/src/main/java/org/zstack/sdk/PrimaryStorageMigrateVolumeAction.java +++ b/sdk/src/main/java/org/zstack/sdk/PrimaryStorageMigrateVolumeAction.java @@ -31,6 +31,9 @@ public Result throwExceptionIfError() { @Param(required = true, nonempty = false, nullElements = false, emptyString = true, noTrim = false) public java.lang.String dstPrimaryStorageUuid; + @Param(required = false, validValues = {"Specified","FollowVolume","FollowDestPrimaryStorage"}, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String volumeProvisioningStrategy = "FollowDestPrimaryStorage"; + @Param(required = false) public java.util.List systemTags; diff --git a/sdk/src/main/java/org/zstack/sdk/ProvisionNfvInstConfigAction.java b/sdk/src/main/java/org/zstack/sdk/ProvisionNfvInstConfigAction.java new file mode 100644 index 0000000000..700bce6a76 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/ProvisionNfvInstConfigAction.java @@ -0,0 +1,101 @@ +package org.zstack.sdk; + +import java.util.HashMap; +import java.util.Map; +import org.zstack.sdk.*; + +public class ProvisionNfvInstConfigAction 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.ProvisionNfvInstConfigResult value; + + public Result throwExceptionIfError() { + if (error != null) { + throw new ApiException( + String.format("error[code: %s, description: %s, details: %s]", error.code, error.description, error.details) + ); + } + + return this; + } + } + + @Param(required = true, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String vmInstanceUuid; + + @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.ProvisionNfvInstConfigResult value = res.getResult(org.zstack.sdk.ProvisionNfvInstConfigResult.class); + ret.value = value == null ? new org.zstack.sdk.ProvisionNfvInstConfigResult() : 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/appliances/nfvinst/{vmInstanceUuid}/provision"; + info.needSession = true; + info.needPoll = true; + info.parameterName = "provisionNfvInstConfig"; + return info; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/ProvisionNfvInstConfigResult.java b/sdk/src/main/java/org/zstack/sdk/ProvisionNfvInstConfigResult.java new file mode 100644 index 0000000000..273aa07417 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/ProvisionNfvInstConfigResult.java @@ -0,0 +1,14 @@ +package org.zstack.sdk; + +import org.zstack.sdk.ApplianceVmInventory; + +public class ProvisionNfvInstConfigResult { + public ApplianceVmInventory inventory; + public void setInventory(ApplianceVmInventory inventory) { + this.inventory = inventory; + } + public ApplianceVmInventory getInventory() { + return this.inventory; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/ProvisionNfvInstGroupAction.java b/sdk/src/main/java/org/zstack/sdk/ProvisionNfvInstGroupAction.java new file mode 100644 index 0000000000..c26afa190f --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/ProvisionNfvInstGroupAction.java @@ -0,0 +1,101 @@ +package org.zstack.sdk; + +import java.util.HashMap; +import java.util.Map; +import org.zstack.sdk.*; + +public class ProvisionNfvInstGroupAction 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.ProvisionNfvInstGroupResult value; + + public Result throwExceptionIfError() { + if (error != null) { + throw new ApiException( + String.format("error[code: %s, description: %s, details: %s]", error.code, error.description, error.details) + ); + } + + 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.ProvisionNfvInstGroupResult value = res.getResult(org.zstack.sdk.ProvisionNfvInstGroupResult.class); + ret.value = value == null ? new org.zstack.sdk.ProvisionNfvInstGroupResult() : 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 = "/nfvinstgroup/group/{uuid}/actions"; + info.needSession = true; + info.needPoll = true; + info.parameterName = "provisionNfvInstGroup"; + return info; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/ProvisionNfvInstGroupResult.java b/sdk/src/main/java/org/zstack/sdk/ProvisionNfvInstGroupResult.java new file mode 100644 index 0000000000..c73096795c --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/ProvisionNfvInstGroupResult.java @@ -0,0 +1,14 @@ +package org.zstack.sdk; + +import org.zstack.sdk.NfvInstGroupInventory; + +public class ProvisionNfvInstGroupResult { + public NfvInstGroupInventory inventory; + public void setInventory(NfvInstGroupInventory inventory) { + this.inventory = inventory; + } + public NfvInstGroupInventory getInventory() { + return this.inventory; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/QueryHygonDeviceAction.java b/sdk/src/main/java/org/zstack/sdk/QueryHygonDeviceAction.java new file mode 100644 index 0000000000..e7526e87cd --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/QueryHygonDeviceAction.java @@ -0,0 +1,75 @@ +package org.zstack.sdk; + +import java.util.HashMap; +import java.util.Map; +import org.zstack.sdk.*; + +public class QueryHygonDeviceAction 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.QueryHygonDeviceResult value; + + public Result throwExceptionIfError() { + if (error != null) { + throw new ApiException( + String.format("error[code: %s, description: %s, details: %s]", error.code, error.description, error.details) + ); + } + + return this; + } + } + + + + private Result makeResult(ApiResult res) { + Result ret = new Result(); + if (res.error != null) { + ret.error = res.error; + return ret; + } + + org.zstack.sdk.QueryHygonDeviceResult value = res.getResult(org.zstack.sdk.QueryHygonDeviceResult.class); + ret.value = value == null ? new org.zstack.sdk.QueryHygonDeviceResult() : 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 = "/hygon-devices"; + info.needSession = true; + info.needPoll = false; + info.parameterName = ""; + return info; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/QueryHygonDeviceResult.java b/sdk/src/main/java/org/zstack/sdk/QueryHygonDeviceResult.java new file mode 100644 index 0000000000..7ec08b4948 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/QueryHygonDeviceResult.java @@ -0,0 +1,22 @@ +package org.zstack.sdk; + + + +public class QueryHygonDeviceResult { + 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/QueryNfvInstAction.java b/sdk/src/main/java/org/zstack/sdk/QueryNfvInstAction.java new file mode 100644 index 0000000000..99f1c66b11 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/QueryNfvInstAction.java @@ -0,0 +1,75 @@ +package org.zstack.sdk; + +import java.util.HashMap; +import java.util.Map; +import org.zstack.sdk.*; + +public class QueryNfvInstAction 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.QueryNfvInstResult value; + + public Result throwExceptionIfError() { + if (error != null) { + throw new ApiException( + String.format("error[code: %s, description: %s, details: %s]", error.code, error.description, error.details) + ); + } + + return this; + } + } + + + + private Result makeResult(ApiResult res) { + Result ret = new Result(); + if (res.error != null) { + ret.error = res.error; + return ret; + } + + org.zstack.sdk.QueryNfvInstResult value = res.getResult(org.zstack.sdk.QueryNfvInstResult.class); + ret.value = value == null ? new org.zstack.sdk.QueryNfvInstResult() : 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/appliances/nfvinst"; + info.needSession = true; + info.needPoll = false; + info.parameterName = ""; + return info; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/QueryNfvInstGroupAction.java b/sdk/src/main/java/org/zstack/sdk/QueryNfvInstGroupAction.java new file mode 100644 index 0000000000..a04db2a92d --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/QueryNfvInstGroupAction.java @@ -0,0 +1,75 @@ +package org.zstack.sdk; + +import java.util.HashMap; +import java.util.Map; +import org.zstack.sdk.*; + +public class QueryNfvInstGroupAction 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.QueryNfvInstGroupResult value; + + public Result throwExceptionIfError() { + if (error != null) { + throw new ApiException( + String.format("error[code: %s, description: %s, details: %s]", error.code, error.description, error.details) + ); + } + + return this; + } + } + + + + private Result makeResult(ApiResult res) { + Result ret = new Result(); + if (res.error != null) { + ret.error = res.error; + return ret; + } + + org.zstack.sdk.QueryNfvInstGroupResult value = res.getResult(org.zstack.sdk.QueryNfvInstGroupResult.class); + ret.value = value == null ? new org.zstack.sdk.QueryNfvInstGroupResult() : 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 = "/nfvinstgroup/group"; + info.needSession = true; + info.needPoll = false; + info.parameterName = ""; + return info; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/QueryNfvInstGroupResult.java b/sdk/src/main/java/org/zstack/sdk/QueryNfvInstGroupResult.java new file mode 100644 index 0000000000..25fa3ebffa --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/QueryNfvInstGroupResult.java @@ -0,0 +1,22 @@ +package org.zstack.sdk; + + + +public class QueryNfvInstGroupResult { + 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/QueryNfvInstOfferingAction.java b/sdk/src/main/java/org/zstack/sdk/QueryNfvInstOfferingAction.java new file mode 100644 index 0000000000..da56a1e225 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/QueryNfvInstOfferingAction.java @@ -0,0 +1,75 @@ +package org.zstack.sdk; + +import java.util.HashMap; +import java.util.Map; +import org.zstack.sdk.*; + +public class QueryNfvInstOfferingAction 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.QueryNfvInstOfferingResult value; + + public Result throwExceptionIfError() { + if (error != null) { + throw new ApiException( + String.format("error[code: %s, description: %s, details: %s]", error.code, error.description, error.details) + ); + } + + return this; + } + } + + + + private Result makeResult(ApiResult res) { + Result ret = new Result(); + if (res.error != null) { + ret.error = res.error; + return ret; + } + + org.zstack.sdk.QueryNfvInstOfferingResult value = res.getResult(org.zstack.sdk.QueryNfvInstOfferingResult.class); + ret.value = value == null ? new org.zstack.sdk.QueryNfvInstOfferingResult() : 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 = "/instance-offerings/nfvinst"; + info.needSession = true; + info.needPoll = false; + info.parameterName = ""; + return info; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/QueryNfvInstOfferingResult.java b/sdk/src/main/java/org/zstack/sdk/QueryNfvInstOfferingResult.java new file mode 100644 index 0000000000..544d8b36ed --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/QueryNfvInstOfferingResult.java @@ -0,0 +1,22 @@ +package org.zstack.sdk; + + + +public class QueryNfvInstOfferingResult { + 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/QueryNfvInstResult.java b/sdk/src/main/java/org/zstack/sdk/QueryNfvInstResult.java new file mode 100644 index 0000000000..361b8130fa --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/QueryNfvInstResult.java @@ -0,0 +1,22 @@ +package org.zstack.sdk; + + + +public class QueryNfvInstResult { + 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/QueryOvnControllerAction.java b/sdk/src/main/java/org/zstack/sdk/QueryOvnControllerAction.java new file mode 100644 index 0000000000..8ced685f21 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/QueryOvnControllerAction.java @@ -0,0 +1,75 @@ +package org.zstack.sdk; + +import java.util.HashMap; +import java.util.Map; +import org.zstack.sdk.*; + +public class QueryOvnControllerAction 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.QueryOvnControllerResult value; + + public Result throwExceptionIfError() { + if (error != null) { + throw new ApiException( + String.format("error[code: %s, description: %s, details: %s]", error.code, error.description, error.details) + ); + } + + return this; + } + } + + + + private Result makeResult(ApiResult res) { + Result ret = new Result(); + if (res.error != null) { + ret.error = res.error; + return ret; + } + + org.zstack.sdk.QueryOvnControllerResult value = res.getResult(org.zstack.sdk.QueryOvnControllerResult.class); + ret.value = value == null ? new org.zstack.sdk.QueryOvnControllerResult() : 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 = "/ovn-controllers"; + info.needSession = true; + info.needPoll = false; + info.parameterName = ""; + return info; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/QueryOvnControllerResult.java b/sdk/src/main/java/org/zstack/sdk/QueryOvnControllerResult.java new file mode 100644 index 0000000000..f146fb9042 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/QueryOvnControllerResult.java @@ -0,0 +1,22 @@ +package org.zstack.sdk; + + + +public class QueryOvnControllerResult { + 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/QueryOvnControllerVmInstanceAction.java b/sdk/src/main/java/org/zstack/sdk/QueryOvnControllerVmInstanceAction.java new file mode 100644 index 0000000000..46e2d887fb --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/QueryOvnControllerVmInstanceAction.java @@ -0,0 +1,75 @@ +package org.zstack.sdk; + +import java.util.HashMap; +import java.util.Map; +import org.zstack.sdk.*; + +public class QueryOvnControllerVmInstanceAction 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.QueryOvnControllerVmInstanceResult value; + + public Result throwExceptionIfError() { + if (error != null) { + throw new ApiException( + String.format("error[code: %s, description: %s, details: %s]", error.code, error.description, error.details) + ); + } + + return this; + } + } + + + + private Result makeResult(ApiResult res) { + Result ret = new Result(); + if (res.error != null) { + ret.error = res.error; + return ret; + } + + org.zstack.sdk.QueryOvnControllerVmInstanceResult value = res.getResult(org.zstack.sdk.QueryOvnControllerVmInstanceResult.class); + ret.value = value == null ? new org.zstack.sdk.QueryOvnControllerVmInstanceResult() : 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/appliances/ovn-controller"; + info.needSession = true; + info.needPoll = false; + info.parameterName = ""; + return info; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/QueryOvnControllerVmInstanceResult.java b/sdk/src/main/java/org/zstack/sdk/QueryOvnControllerVmInstanceResult.java new file mode 100644 index 0000000000..f0051c0e6b --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/QueryOvnControllerVmInstanceResult.java @@ -0,0 +1,22 @@ +package org.zstack.sdk; + + + +public class QueryOvnControllerVmInstanceResult { + 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/ReconnectNfvInstAction.java b/sdk/src/main/java/org/zstack/sdk/ReconnectNfvInstAction.java new file mode 100644 index 0000000000..47379eb43d --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/ReconnectNfvInstAction.java @@ -0,0 +1,101 @@ +package org.zstack.sdk; + +import java.util.HashMap; +import java.util.Map; +import org.zstack.sdk.*; + +public class ReconnectNfvInstAction 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.ReconnectNfvInstResult value; + + public Result throwExceptionIfError() { + if (error != null) { + throw new ApiException( + String.format("error[code: %s, description: %s, details: %s]", error.code, error.description, error.details) + ); + } + + return this; + } + } + + @Param(required = true, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String vmInstanceUuid; + + @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.ReconnectNfvInstResult value = res.getResult(org.zstack.sdk.ReconnectNfvInstResult.class); + ret.value = value == null ? new org.zstack.sdk.ReconnectNfvInstResult() : 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/appliances/nfvinst/{vmInstanceUuid}/actions"; + info.needSession = true; + info.needPoll = true; + info.parameterName = "reconnectNfvInst"; + return info; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/ReconnectNfvInstResult.java b/sdk/src/main/java/org/zstack/sdk/ReconnectNfvInstResult.java new file mode 100644 index 0000000000..74b0f10a6b --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/ReconnectNfvInstResult.java @@ -0,0 +1,14 @@ +package org.zstack.sdk; + +import org.zstack.sdk.ApplianceVmInventory; + +public class ReconnectNfvInstResult { + public ApplianceVmInventory inventory; + public void setInventory(ApplianceVmInventory inventory) { + this.inventory = inventory; + } + public ApplianceVmInventory getInventory() { + return this.inventory; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/ResetTwoFactorAuthenticationSecretAction.java b/sdk/src/main/java/org/zstack/sdk/ResetTwoFactorAuthenticationSecretAction.java index ce0a61a40a..f3633f18b7 100644 --- a/sdk/src/main/java/org/zstack/sdk/ResetTwoFactorAuthenticationSecretAction.java +++ b/sdk/src/main/java/org/zstack/sdk/ResetTwoFactorAuthenticationSecretAction.java @@ -31,7 +31,7 @@ public Result throwExceptionIfError() { @Param(required = true, nonempty = true, nullElements = false, emptyString = true, noTrim = false) public java.lang.String password; - @Param(required = true, validValues = {"account","iam2"}, nonempty = true, nullElements = false, emptyString = true, noTrim = false) + @Param(required = true, validValues = {"account","iam2","iam2-ldap"}, nonempty = true, nullElements = false, emptyString = true, noTrim = false) public java.lang.String type; @Param(required = false, nonempty = false, nullElements = false, emptyString = true, noTrim = false) diff --git a/sdk/src/main/java/org/zstack/sdk/SetVmInstanceHygonMdevAction.java b/sdk/src/main/java/org/zstack/sdk/SetVmInstanceHygonMdevAction.java new file mode 100644 index 0000000000..2e28156ae6 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/SetVmInstanceHygonMdevAction.java @@ -0,0 +1,104 @@ +package org.zstack.sdk; + +import java.util.HashMap; +import java.util.Map; +import org.zstack.sdk.*; + +public class SetVmInstanceHygonMdevAction 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.SetVmInstanceHygonMdevResult value; + + public Result throwExceptionIfError() { + if (error != null) { + throw new ApiException( + String.format("error[code: %s, description: %s, details: %s]", error.code, error.description, error.details) + ); + } + + return this; + } + } + + @Param(required = true, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String uuid; + + @Param(required = true, validValues = {"true","false"}, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String hygonSecurityElementEnable; + + @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.SetVmInstanceHygonMdevResult value = res.getResult(org.zstack.sdk.SetVmInstanceHygonMdevResult.class); + ret.value = value == null ? new org.zstack.sdk.SetVmInstanceHygonMdevResult() : 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 = "/vm-instances/{uuid}/hygon-mdev"; + info.needSession = true; + info.needPoll = true; + info.parameterName = "params"; + return info; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/SetVmInstanceHygonMdevResult.java b/sdk/src/main/java/org/zstack/sdk/SetVmInstanceHygonMdevResult.java new file mode 100644 index 0000000000..03b0c8ee04 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/SetVmInstanceHygonMdevResult.java @@ -0,0 +1,7 @@ +package org.zstack.sdk; + + + +public class SetVmInstanceHygonMdevResult { + +} diff --git a/sdk/src/main/java/org/zstack/sdk/SyncNfvInstGroupAction.java b/sdk/src/main/java/org/zstack/sdk/SyncNfvInstGroupAction.java new file mode 100644 index 0000000000..0b6504ba3a --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/SyncNfvInstGroupAction.java @@ -0,0 +1,101 @@ +package org.zstack.sdk; + +import java.util.HashMap; +import java.util.Map; +import org.zstack.sdk.*; + +public class SyncNfvInstGroupAction 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.SyncNfvInstGroupResult value; + + public Result throwExceptionIfError() { + if (error != null) { + throw new ApiException( + String.format("error[code: %s, description: %s, details: %s]", error.code, error.description, error.details) + ); + } + + 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.SyncNfvInstGroupResult value = res.getResult(org.zstack.sdk.SyncNfvInstGroupResult.class); + ret.value = value == null ? new org.zstack.sdk.SyncNfvInstGroupResult() : 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 = "/nfvinstgroup/group/{uuid}/actions"; + info.needSession = true; + info.needPoll = true; + info.parameterName = "syncNfvInstGroup"; + return info; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/SyncNfvInstGroupResult.java b/sdk/src/main/java/org/zstack/sdk/SyncNfvInstGroupResult.java new file mode 100644 index 0000000000..3bf973cbc9 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/SyncNfvInstGroupResult.java @@ -0,0 +1,14 @@ +package org.zstack.sdk; + +import org.zstack.sdk.NfvInstGroupInventory; + +public class SyncNfvInstGroupResult { + public NfvInstGroupInventory inventory; + public void setInventory(NfvInstGroupInventory inventory) { + this.inventory = inventory; + } + public NfvInstGroupInventory getInventory() { + return this.inventory; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/UngenerateHygonMdevDevicesAction.java b/sdk/src/main/java/org/zstack/sdk/UngenerateHygonMdevDevicesAction.java new file mode 100644 index 0000000000..bb355602a1 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/UngenerateHygonMdevDevicesAction.java @@ -0,0 +1,101 @@ +package org.zstack.sdk; + +import java.util.HashMap; +import java.util.Map; +import org.zstack.sdk.*; + +public class UngenerateHygonMdevDevicesAction 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.UngenerateHygonMdevDevicesResult value; + + public Result throwExceptionIfError() { + if (error != null) { + throw new ApiException( + String.format("error[code: %s, description: %s, details: %s]", error.code, error.description, error.details) + ); + } + + return this; + } + } + + @Param(required = true, 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; + + @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.UngenerateHygonMdevDevicesResult value = res.getResult(org.zstack.sdk.UngenerateHygonMdevDevicesResult.class); + ret.value = value == null ? new org.zstack.sdk.UngenerateHygonMdevDevicesResult() : 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 = "/hygon-devices/{hostUuid}/actions"; + info.needSession = true; + info.needPoll = true; + info.parameterName = "ungenerateHygonMdevDevices"; + return info; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/UngenerateHygonMdevDevicesResult.java b/sdk/src/main/java/org/zstack/sdk/UngenerateHygonMdevDevicesResult.java new file mode 100644 index 0000000000..cd83aa57ea --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/UngenerateHygonMdevDevicesResult.java @@ -0,0 +1,7 @@ +package org.zstack.sdk; + + + +public class UngenerateHygonMdevDevicesResult { + +} diff --git a/sdk/src/main/java/org/zstack/sdk/UpdateConsolePasswordAction.java b/sdk/src/main/java/org/zstack/sdk/UpdateConsolePasswordAction.java new file mode 100644 index 0000000000..c3398dbbe0 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/UpdateConsolePasswordAction.java @@ -0,0 +1,104 @@ +package org.zstack.sdk; + +import java.util.HashMap; +import java.util.Map; +import org.zstack.sdk.*; + +public class UpdateConsolePasswordAction 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.UpdateConsolePasswordResult value; + + public Result throwExceptionIfError() { + if (error != null) { + throw new ApiException( + String.format("error[code: %s, description: %s, details: %s]", error.code, error.description, error.details) + ); + } + + return this; + } + } + + @Param(required = true, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String uuid; + + @Param(required = true, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String password; + + @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.UpdateConsolePasswordResult value = res.getResult(org.zstack.sdk.UpdateConsolePasswordResult.class); + ret.value = value == null ? new org.zstack.sdk.UpdateConsolePasswordResult() : 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/{uuid}/actions"; + info.needSession = true; + info.needPoll = true; + info.parameterName = "updateConsolePassword"; + return info; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/UpdateConsolePasswordResult.java b/sdk/src/main/java/org/zstack/sdk/UpdateConsolePasswordResult.java new file mode 100644 index 0000000000..1462e8ae7d --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/UpdateConsolePasswordResult.java @@ -0,0 +1,14 @@ +package org.zstack.sdk; + +import org.zstack.sdk.VmInstanceInventory; + +public class UpdateConsolePasswordResult { + public VmInstanceInventory inventory; + public void setInventory(VmInstanceInventory inventory) { + this.inventory = inventory; + } + public VmInstanceInventory 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 057e11a49a..1d440e5787 100644 --- a/sdk/src/main/java/org/zstack/sdk/UpdateModelAction.java +++ b/sdk/src/main/java/org/zstack/sdk/UpdateModelAction.java @@ -46,6 +46,12 @@ public Result throwExceptionIfError() { @Param(required = false, nonempty = false, nullElements = false, emptyString = true, noTrim = false) public java.util.List modelClassifications; + @Param(required = false, maxLength = 255, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String recommendedGpuNum; + + @Param(required = false, maxLength = 512, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String gpuConstraintDescription; + @Param(required = false) public java.util.List systemTags; diff --git a/sdk/src/main/java/org/zstack/sdk/UpdateModelServiceAction.java b/sdk/src/main/java/org/zstack/sdk/UpdateModelServiceAction.java index cc8d685257..131e4e3b9f 100644 --- a/sdk/src/main/java/org/zstack/sdk/UpdateModelServiceAction.java +++ b/sdk/src/main/java/org/zstack/sdk/UpdateModelServiceAction.java @@ -49,6 +49,12 @@ public Result throwExceptionIfError() { @Param(required = false, nonempty = false, nullElements = false, emptyString = true, noTrim = false) public java.lang.String startCommand; + @Param(required = false, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String containerCommand; + + @Param(required = false, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String containerArgs; + @Param(required = false, nonempty = false, nullElements = false, emptyString = true, noTrim = false) public java.lang.String pythonVersion; diff --git a/sdk/src/main/java/org/zstack/sdk/UpdateModelServiceInstanceGroupAction.java b/sdk/src/main/java/org/zstack/sdk/UpdateModelServiceInstanceGroupAction.java index 0862c561bf..18e3b18309 100644 --- a/sdk/src/main/java/org/zstack/sdk/UpdateModelServiceInstanceGroupAction.java +++ b/sdk/src/main/java/org/zstack/sdk/UpdateModelServiceInstanceGroupAction.java @@ -40,6 +40,15 @@ public Result throwExceptionIfError() { @Param(required = false, nonempty = false, nullElements = false, emptyString = true, noTrim = false) public java.util.Map startupParameters; + @Param(required = false, maxLength = 255, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String serviceLivez; + + @Param(required = false, maxLength = 255, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String serviceReadyz; + + @Param(required = false, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.Integer serviceBootupTime; + @Param(required = false) public java.util.List systemTags; diff --git a/sdk/src/main/java/org/zstack/sdk/UpdateNfvInstGroupAction.java b/sdk/src/main/java/org/zstack/sdk/UpdateNfvInstGroupAction.java new file mode 100644 index 0000000000..a6bd5fbcf6 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/UpdateNfvInstGroupAction.java @@ -0,0 +1,107 @@ +package org.zstack.sdk; + +import java.util.HashMap; +import java.util.Map; +import org.zstack.sdk.*; + +public class UpdateNfvInstGroupAction 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.UpdateNfvInstGroupResult value; + + public Result throwExceptionIfError() { + if (error != null) { + throw new ApiException( + String.format("error[code: %s, description: %s, details: %s]", error.code, error.description, error.details) + ); + } + + 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) + 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.UpdateNfvInstGroupResult value = res.getResult(org.zstack.sdk.UpdateNfvInstGroupResult.class); + ret.value = value == null ? new org.zstack.sdk.UpdateNfvInstGroupResult() : 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 = "/nfvinstgroup/group/{uuid}/actions"; + info.needSession = true; + info.needPoll = true; + info.parameterName = "updateNfvInstGroup"; + return info; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/UpdateNfvInstGroupResult.java b/sdk/src/main/java/org/zstack/sdk/UpdateNfvInstGroupResult.java new file mode 100644 index 0000000000..b58ee147be --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/UpdateNfvInstGroupResult.java @@ -0,0 +1,14 @@ +package org.zstack.sdk; + +import org.zstack.sdk.NfvInstGroupInventory; + +public class UpdateNfvInstGroupResult { + public NfvInstGroupInventory inventory; + public void setInventory(NfvInstGroupInventory inventory) { + this.inventory = inventory; + } + public NfvInstGroupInventory getInventory() { + return this.inventory; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/UpdateNfvInstProvisionConfigAction.java b/sdk/src/main/java/org/zstack/sdk/UpdateNfvInstProvisionConfigAction.java new file mode 100644 index 0000000000..c89a64d662 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/UpdateNfvInstProvisionConfigAction.java @@ -0,0 +1,101 @@ +package org.zstack.sdk; + +import java.util.HashMap; +import java.util.Map; +import org.zstack.sdk.*; + +public class UpdateNfvInstProvisionConfigAction 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.UpdateNfvInstProvisionConfigResult value; + + public Result throwExceptionIfError() { + if (error != null) { + throw new ApiException( + String.format("error[code: %s, description: %s, details: %s]", error.code, error.description, error.details) + ); + } + + return this; + } + } + + @Param(required = true, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String vmInstanceUuid; + + @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.UpdateNfvInstProvisionConfigResult value = res.getResult(org.zstack.sdk.UpdateNfvInstProvisionConfigResult.class); + ret.value = value == null ? new org.zstack.sdk.UpdateNfvInstProvisionConfigResult() : 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/appliances/nfvinst/{vmInstanceUuid}/provision/update"; + info.needSession = true; + info.needPoll = true; + info.parameterName = "updateNfvInstProvisionConfig"; + return info; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/UpdateNfvInstProvisionConfigResult.java b/sdk/src/main/java/org/zstack/sdk/UpdateNfvInstProvisionConfigResult.java new file mode 100644 index 0000000000..466ab13f06 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/UpdateNfvInstProvisionConfigResult.java @@ -0,0 +1,14 @@ +package org.zstack.sdk; + +import org.zstack.sdk.ApplianceVmInventory; + +public class UpdateNfvInstProvisionConfigResult { + public ApplianceVmInventory inventory; + public void setInventory(ApplianceVmInventory inventory) { + this.inventory = inventory; + } + public ApplianceVmInventory getInventory() { + return this.inventory; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/VmVfNicInventory.java b/sdk/src/main/java/org/zstack/sdk/VmVfNicInventory.java index 1a25f664e0..e008576b36 100644 --- a/sdk/src/main/java/org/zstack/sdk/VmVfNicInventory.java +++ b/sdk/src/main/java/org/zstack/sdk/VmVfNicInventory.java @@ -20,4 +20,12 @@ public java.lang.String getHaState() { return this.haState; } + public java.lang.String secondaryPciDeviceUuid; + public void setSecondaryPciDeviceUuid(java.lang.String secondaryPciDeviceUuid) { + this.secondaryPciDeviceUuid = secondaryPciDeviceUuid; + } + public java.lang.String getSecondaryPciDeviceUuid() { + return this.secondaryPciDeviceUuid; + } + } diff --git a/sdk/src/main/java/org/zstack/sdk/license/api/server/RequestLicenseCapacityAction.java b/sdk/src/main/java/org/zstack/sdk/license/api/server/RequestLicenseCapacityAction.java index 0f42eedfe4..8e632d9428 100644 --- a/sdk/src/main/java/org/zstack/sdk/license/api/server/RequestLicenseCapacityAction.java +++ b/sdk/src/main/java/org/zstack/sdk/license/api/server/RequestLicenseCapacityAction.java @@ -40,6 +40,9 @@ public Result throwExceptionIfError() { @Param(required = true, nonempty = false, nullElements = false, emptyString = true, noTrim = false) public java.lang.String licenseType; + @Param(required = false, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String resourceInfo; + @Param(required = false) public java.util.List systemTags; diff --git a/sdk/src/main/java/org/zstack/sdk/license/header/server/LicenseAuthorizedCapacityInventory.java b/sdk/src/main/java/org/zstack/sdk/license/header/server/LicenseAuthorizedCapacityInventory.java index cb5184b020..744932d801 100644 --- a/sdk/src/main/java/org/zstack/sdk/license/header/server/LicenseAuthorizedCapacityInventory.java +++ b/sdk/src/main/java/org/zstack/sdk/license/header/server/LicenseAuthorizedCapacityInventory.java @@ -28,6 +28,14 @@ public java.lang.String getResourceUuid() { return this.resourceUuid; } + public java.lang.String resourceInfo; + public void setResourceInfo(java.lang.String resourceInfo) { + this.resourceInfo = resourceInfo; + } + public java.lang.String getResourceInfo() { + return this.resourceInfo; + } + public java.lang.String quotaType; public void setQuotaType(java.lang.String quotaType) { this.quotaType = quotaType; diff --git a/sdk/src/main/java/org/zstack/sdk/license/header/server/LicenseUsageDetailView.java b/sdk/src/main/java/org/zstack/sdk/license/header/server/LicenseUsageDetailView.java new file mode 100644 index 0000000000..53bca0260b --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/license/header/server/LicenseUsageDetailView.java @@ -0,0 +1,31 @@ +package org.zstack.sdk.license.header.server; + + + +public class LicenseUsageDetailView { + + public java.lang.String usedBy; + public void setUsedBy(java.lang.String usedBy) { + this.usedBy = usedBy; + } + public java.lang.String getUsedBy() { + return this.usedBy; + } + + public long usage; + public void setUsage(long usage) { + this.usage = usage; + } + public long getUsage() { + return this.usage; + } + + public java.lang.String resourceInfo; + public void setResourceInfo(java.lang.String resourceInfo) { + this.resourceInfo = resourceInfo; + } + public java.lang.String getResourceInfo() { + return this.resourceInfo; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/license/header/server/LicenseUsageView.java b/sdk/src/main/java/org/zstack/sdk/license/header/server/LicenseUsageView.java index dd713fdddf..d6d3611251 100644 --- a/sdk/src/main/java/org/zstack/sdk/license/header/server/LicenseUsageView.java +++ b/sdk/src/main/java/org/zstack/sdk/license/header/server/LicenseUsageView.java @@ -36,4 +36,12 @@ public long getAvailable() { return this.available; } + public java.util.List usageDetails; + public void setUsageDetails(java.util.List usageDetails) { + this.usageDetails = usageDetails; + } + public java.util.List getUsageDetails() { + return this.usageDetails; + } + } diff --git a/sdk/src/main/java/org/zstack/sdk/license/header/server/TotalLicenseAuthorizedCapacityView.java b/sdk/src/main/java/org/zstack/sdk/license/header/server/TotalLicenseAuthorizedCapacityView.java index 7860523e8b..582857bcae 100644 --- a/sdk/src/main/java/org/zstack/sdk/license/header/server/TotalLicenseAuthorizedCapacityView.java +++ b/sdk/src/main/java/org/zstack/sdk/license/header/server/TotalLicenseAuthorizedCapacityView.java @@ -45,4 +45,12 @@ public java.util.List getAddOns() { return this.addOns; } + public java.util.Map extensions; + public void setExtensions(java.util.Map extensions) { + this.extensions = extensions; + } + public java.util.Map getExtensions() { + return this.extensions; + } + } 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 a4c639c9bd..45cf8612a3 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 @@ -155,6 +155,7 @@ protected void handle(AskVolumeSnapshotCapabilityMsg msg) { AskVolumeSnapshotCapabilityReply reply = new AskVolumeSnapshotCapabilityReply(); VolumeSnapshotCapability capability = new VolumeSnapshotCapability(); capability.setArrangementType(VolumeSnapshotArrangementType.CHAIN); + capability.setPlacementType(VolumeSnapshotCapability.VolumeSnapshotPlacementType.EXTERNAL); capability.setSupport(true); reply.setCapability(capability); bus.reply(msg, reply); diff --git a/storage/src/main/java/org/zstack/storage/addon/primary/BlockExternalPrimaryStorageBackend.java b/storage/src/main/java/org/zstack/storage/addon/primary/BlockExternalPrimaryStorageBackend.java index 4641315ed6..dc2cfa760b 100644 --- a/storage/src/main/java/org/zstack/storage/addon/primary/BlockExternalPrimaryStorageBackend.java +++ b/storage/src/main/java/org/zstack/storage/addon/primary/BlockExternalPrimaryStorageBackend.java @@ -3,6 +3,10 @@ import org.zstack.header.storage.primary.*; import org.zstack.header.volume.block.GetAccessPathMsg; +/** + * do not match external primary storage design. + */ +@Deprecated public interface BlockExternalPrimaryStorageBackend { String getType(); diff --git a/storage/src/main/java/org/zstack/storage/addon/primary/BlockExternalPrimaryStorageFactory.java b/storage/src/main/java/org/zstack/storage/addon/primary/BlockExternalPrimaryStorageFactory.java index 2c561cc03a..7c1b5839ef 100644 --- a/storage/src/main/java/org/zstack/storage/addon/primary/BlockExternalPrimaryStorageFactory.java +++ b/storage/src/main/java/org/zstack/storage/addon/primary/BlockExternalPrimaryStorageFactory.java @@ -1,11 +1,13 @@ package org.zstack.storage.addon.primary; -import org.zstack.header.host.HostInventory; -import org.zstack.header.storage.addon.primary.BaseVolumeInfo; import org.zstack.header.storage.primary.PrimaryStorageVO; import java.util.Map; +/** + * do not match external primary storage design. + */ +@Deprecated public interface BlockExternalPrimaryStorageFactory { String getType(); 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 05bea4ba5f..b650356c7d 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 @@ -55,6 +55,8 @@ import org.zstack.utils.logging.CLogger; import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import java.util.stream.Collectors; import static org.zstack.core.Platform.operr; @@ -180,9 +182,10 @@ private void handle(APIUpdateExternalPrimaryStorageMsg msg) { externalVO.setDefaultProtocol(msg.getDefaultProtocol()); } boolean needReconnect = false; + String oldConfig = externalVO.getConfig(); if (msg.getConfig() != null) { - controller.validateConfig(msg.getConfig()); - externalVO.setConfig(msg.getConfig()); + String config = controller.validateConfig(msg.getConfig()); + externalVO.setConfig(config); needReconnect = true; } externalVO = dbf.updateAndRefresh(externalVO); @@ -198,7 +201,13 @@ public void run(MessageReply reply) { evt.setError(reply.getError()); } else { self = dbf.reload(self); - evt.setInventory(externalVO.toInventory()); + ExternalPrimaryStorageInventory inv = externalVO.toInventory(); + evt.setInventory(inv); + + // TODO: use controller not extension point + for (UpdatePrimaryStorageExtensionPoint ext : pluginRgty.getExtensionList(UpdatePrimaryStorageExtensionPoint.class)) { + ext.afterUpdatePrimaryStorage(inv); + } } bus.publish(evt); @@ -334,7 +343,7 @@ public void setup() { @Override public void run(final FlowTrigger trigger, Map data) { - downloadImageCache(msg.getTemplateSpec().getInventory(), new ReturnValueCompletion(trigger) { + downloadImageCache(msg.getTemplateSpec().getInventory(), spec.getAllocatedUrl(), new ReturnValueCompletion(trigger) { @Override public void success(ImageCacheInventory returnValue) { pathInCache = ImageCacheUtil.getImageCachePath(returnValue); @@ -770,7 +779,9 @@ private void createImageCacheFromSnapshot(CreateImageCacheFromVolumeSnapshotOnPr ImageCacheInventory inventory; - ImageInventory image = msg.getImageInventory(); + final ImageInventory image = msg.getImageInventory(); + + final String requiredUrlTag = msg.getSystemTag(ExternalPrimaryStorageSystemTags.REQUIRED_INSTALL_URL::isMatch); @Override public void setup() { @@ -783,6 +794,11 @@ public void run(FlowTrigger trigger, Map data) { spec.setName(buildImageName(image.getUuid())); spec.setUuid(msg.getImageInventory().getUuid()); spec.setSize(msg.getImageInventory().getSize()); + if (requiredUrlTag != null) { + String requiredUrl = ExternalPrimaryStorageSystemTags.REQUIRED_INSTALL_URL.getTokenByTag( + requiredUrlTag, ExternalPrimaryStorageSystemTags.REQUIRED_INSTALL_URL_TOKEN); + spec.setAllocatedUrl(requiredUrl); + } controller.copyVolume(msg.getVolumeSnapshot().getPrimaryStorageInstallPath(), spec, new ReturnValueCompletion(trigger) { @Override public void success(VolumeStats dst) { @@ -1154,7 +1170,7 @@ public void fail(ErrorCode errorCode) { }); } - private void downloadImageCache(ImageInventory image, ReturnValueCompletion completion) { + private void downloadImageCache(ImageInventory image, String allocatedUrl, ReturnValueCompletion completion) { thdf.chainSubmit(new ChainTask(completion) { @Override public String getSyncSignature() { @@ -1163,7 +1179,7 @@ public String getSyncSignature() { @Override public void run(SyncTaskChain chain) { - doDownloadImageCache(image, new ReturnValueCompletion(chain) { + doDownloadImageCache(image, allocatedUrl, new ReturnValueCompletion(chain) { @Override public void success(ImageCacheInventory returnValue) { completion.success(returnValue); @@ -1185,19 +1201,24 @@ public String getName() { }); } - private void doDownloadImageCache(ImageInventory image, ReturnValueCompletion completion) { + private void doDownloadImageCache(ImageInventory image, String allocatedUrl, ReturnValueCompletion completion) { CreateVolumeSpec spec = new CreateVolumeSpec(); spec.setUuid(image.getUuid()); spec.setName(buildImageName(image.getUuid())); + spec.setAllocatedUrl(allocatedUrl); - ImageCacheVO cache = Q.New(ImageCacheVO.class) + List caches = Q.New(ImageCacheVO.class) .eq(ImageCacheVO_.primaryStorageUuid, self.getUuid()) .eq(ImageCacheVO_.imageUuid, image.getUuid()) - .find(); - if (cache != null) { - // TODO check exists in ps - completion.success(ImageCacheInventory.valueOf(cache)); - return; + .list(); + + for (ImageCacheVO cache : caches) { + ImageCacheInventory inv = cache.toInventory(); + // TODO: suppose that path always starts with allocatedUrl + if (allocatedUrl != null && ImageCacheUtil.getImageCachePath(inv).startsWith(allocatedUrl)) { + completion.success(inv); + return; + } } downloadImageTo(image, spec, ImageCacheVO.class.getSimpleName(), new ReturnValueCompletion(completion) { @@ -1427,6 +1448,7 @@ protected void handle(GetInstallPathForDataVolumeDownloadMsg msg) { AllocateSpaceSpec aspec = new AllocateSpaceSpec(); aspec.setSize(msg.getImage().getSize()); aspec.setPurpose(PrimaryStorageAllocationPurpose.CreateDataVolume); + aspec.setRequiredUrl(msg.getAllocatedInstallUrl()); String installPath = controller.allocateSpace(aspec); reply.setInstallPath(installPath); @@ -1565,6 +1587,8 @@ protected void handle(DeleteVolumeOnPrimaryStorageMsg msg) { trashVolume(msg.getVolume().getInstallPath(), msg.getVolume().getProtocol(), force, new Completion(msg) { @Override public void success() { + ExternalPrimaryStorageSpaceCapacityHelper helper = new ExternalPrimaryStorageSpaceCapacityHelper(self.getUuid(), controller.getIdentity()); + helper.releaseAvailableCapWithRatio(msg.getVolume().getInstallPath(), msg.getVolume().getSize()); bus.reply(msg, reply); } @@ -1615,7 +1639,12 @@ public void fail(ErrorCode errorCode) { @Override protected void handle(DownloadIsoToPrimaryStorageMsg msg) { DownloadIsoToPrimaryStorageReply reply = new DownloadIsoToPrimaryStorageReply(); - downloadImageCache(msg.getIsoSpec().getInventory(), new ReturnValueCompletion(msg) { + String urlTag = msg.getSystemTag(ExternalPrimaryStorageSystemTags.REQUIRED_INSTALL_URL::isMatch); + String allocatedUrl = urlTag == null ? null : + ExternalPrimaryStorageSystemTags.REQUIRED_INSTALL_URL.getTokenByTag(urlTag, + ExternalPrimaryStorageSystemTags.REQUIRED_INSTALL_URL_TOKEN); + + downloadImageCache(msg.getIsoSpec().getInventory(), allocatedUrl, new ReturnValueCompletion(msg) { @Override public void success(ImageCacheInventory cache) { String isoProtocol = controller.reportCapabilities().getDefaultIsoActiveProtocol() != null @@ -1772,6 +1801,8 @@ protected void handle(DeleteSnapshotOnPrimaryStorageMsg msg) { controller.deleteSnapshot(msg.getSnapshot().getPrimaryStorageInstallPath(), new Completion(msg) { @Override public void success() { + ExternalPrimaryStorageSpaceCapacityHelper helper = new ExternalPrimaryStorageSpaceCapacityHelper(self.getUuid(), controller.getIdentity()); + helper.releaseAvailableCapacity(msg.getSnapshot().getPrimaryStorageInstallPath(), msg.getSnapshot().getSize()); bus.reply(msg, reply); } @@ -1826,7 +1857,7 @@ public void run(final FlowTrigger trigger, Map data) { } ImageInventory image = ImageInventory.valueOf(ivo); - downloadImageCache(image, new ReturnValueCompletion(trigger) { + downloadImageCache(image, msg.getAllocatedInstallUrl(), new ReturnValueCompletion(trigger) { @Override public void success(ImageCacheInventory returnValue) { installUrl = returnValue.getInstallUrl(); @@ -1866,12 +1897,18 @@ public void fail(ErrorCode errorCode) { }); flow(new NoRollbackFlow() { - // TODO: hardcode for expon final String __name__ = "delete-origin-root-volume-which-has-no-snapshot"; + @Override + public boolean skip(Map data) { + return controller.reportCapabilities().getSnapshotCapability() + .getPlacementType() != VolumeSnapshotCapability.VolumeSnapshotPlacementType.INTERNAL; + } + @Override public void run(FlowTrigger trigger, Map data) { boolean hasSnapshot = Q.New(VolumeSnapshotVO.class) + .eq(VolumeSnapshotVO_.volumeUuid, msg.getVolume().getUuid()) .like(VolumeSnapshotVO_.primaryStorageInstallPath, String.format("%s%%", msg.getVolume().getInstallPath())) .isExists(); if (!hasSnapshot) { @@ -1920,6 +1957,30 @@ protected void handle(AskInstallPathForNewSnapshotMsg msg) { bus.reply(msg, reply); } + @Override + protected void handle(GetOwningVolumePathFromInternalSnapshotMsg msg) { + GetOwningVolumePathFromInternalSnapshotReply reply = new GetOwningVolumePathFromInternalSnapshotReply(); + if (msg.getSnapshotPaths() != null) { + VolumeSnapshotCapability scap = controller.reportCapabilities().getSnapshotCapability(); + if (scap.getPlacementType() == VolumeSnapshotCapability.VolumeSnapshotPlacementType.INTERNAL) { + Pattern pattern = Pattern.compile(scap.getVolumePathFromInternalSnapshotRegex()); + for (String snapshotPath : msg.getSnapshotPaths()) { + Matcher matcher = pattern.matcher(snapshotPath); + if (matcher.find()) { + String volumePath = matcher.group(); + reply.putOwningVolumePath(snapshotPath, volumePath); + } else { + reply.setError(operr("cannot find owning volume path from internal snapshot path[%s], " + + "because the regex[%s] does not match the snapshot path", snapshotPath, scap.getVolumePathFromInternalSnapshotRegex())); + break; + } + } + } + } + + bus.reply(msg, reply); + } + @Override protected void handle(GetPrimaryStorageResourceLocationMsg msg) { bus.reply(msg, new GetPrimaryStorageResourceLocationReply()); @@ -1932,15 +1993,19 @@ protected void handle(CheckVolumeSnapshotOperationOnPrimaryStorageMsg msg) { @Override protected void connectHook(ConnectParam param, Completion completion) { - controller.validateConfig(externalVO.getConfig()); - controller.connect(externalVO.getConfig(), self.getUrl(), new ReturnValueCompletion(completion) { + String config = controller.validateConfig(externalVO.getConfig()); + controller.connect(config, self.getUrl(), new ReturnValueCompletion(completion) { @Override public void success(LinkedHashMap addonInfo) { if (param.isNewAdded()) { controller.onFirstAdditionConfigure(new NopeCompletion()); } + SQL.New(ExternalPrimaryStorageVO.class).eq(ExternalPrimaryStorageVO_.uuid, self.getUuid()) .set(ExternalPrimaryStorageVO_.addonInfo, JSONObjectUtil.toJsonString(addonInfo)) + .set(ExternalPrimaryStorageVO_.config, config) + .set(ExternalPrimaryStorageVO_.url, StringUtils.isEmpty(self.getUrl()) ? + externalVO.getIdentity() + "://" + self.getUuid() : self.getUrl()) .update(); controller.setTrashExpireTime(PrimaryStorageGlobalConfig.TRASH_EXPIRATION_TIME.value(Integer.class), new NopeCompletion()); pingHook(completion); @@ -1999,6 +2064,8 @@ public void success(StorageCapacity capacity) { return cap; }); + + new ExternalPrimaryStorageSpaceCapacityHelper(externalVO).updateStorageSpace(capacity); trigger.next(); } else { trigger.fail(operr("storage is not healthy:%s", capacity.getHealthy().toString())); diff --git a/storage/src/main/java/org/zstack/storage/addon/primary/ExternalPrimaryStorageChangeVolumeProcessingMethodExtension.java b/storage/src/main/java/org/zstack/storage/addon/primary/ExternalPrimaryStorageChangeVolumeProcessingMethodExtension.java deleted file mode 100644 index 09dbccb01b..0000000000 --- a/storage/src/main/java/org/zstack/storage/addon/primary/ExternalPrimaryStorageChangeVolumeProcessingMethodExtension.java +++ /dev/null @@ -1,31 +0,0 @@ -package org.zstack.storage.addon.primary; - -import org.zstack.core.db.Q; -import org.zstack.header.storage.primary.PrimaryStorageConstant; -import org.zstack.header.storage.primary.PrimaryStorageVO; -import org.zstack.header.storage.primary.PrimaryStorageVO_; -import org.zstack.header.storage.snapshot.VolumeSnapshotVO; -import org.zstack.header.storage.snapshot.VolumeSnapshotVO_; -import org.zstack.header.volume.VolumeDeletionPolicyManager; -import org.zstack.header.volume.VolumeInventory; -import org.zstack.storage.volume.ChangeVolumeProcessingMethodExtensionPoint; - -/** - * @author Xingwei Yu - * @date 2024/10/23 16:07 - */ -public class ExternalPrimaryStorageChangeVolumeProcessingMethodExtension implements ChangeVolumeProcessingMethodExtensionPoint { - @Override - public VolumeDeletionPolicyManager.VolumeDeletionPolicy getTransientVolumeDeletionPolicy(VolumeInventory transientVolume) { - String psType = Q.New(PrimaryStorageVO.class).eq(PrimaryStorageVO_.uuid, transientVolume.getPrimaryStorageUuid()).select(PrimaryStorageVO_.type).findValue(); - if (!psType.equals(PrimaryStorageConstant.EXTERNAL_PRIMARY_STORAGE_TYPE)) { - return null; - } - boolean hasSnapshots = Q.New(VolumeSnapshotVO.class).eq(VolumeSnapshotVO_.primaryStorageUuid, transientVolume.getPrimaryStorageUuid()) - .like(VolumeSnapshotVO_.primaryStorageInstallPath, String.format("%s@%%", transientVolume.getInstallPath())).isExists(); - if (!hasSnapshots) { - return VolumeDeletionPolicyManager.VolumeDeletionPolicy.Direct; - } - return VolumeDeletionPolicyManager.VolumeDeletionPolicy.DBOnly; - } -} diff --git a/storage/src/main/java/org/zstack/storage/addon/primary/ExternalPrimaryStorageFactory.java b/storage/src/main/java/org/zstack/storage/addon/primary/ExternalPrimaryStorageFactory.java index 6b21ab8325..8e715f6a6f 100644 --- a/storage/src/main/java/org/zstack/storage/addon/primary/ExternalPrimaryStorageFactory.java +++ b/storage/src/main/java/org/zstack/storage/addon/primary/ExternalPrimaryStorageFactory.java @@ -1,6 +1,9 @@ package org.zstack.storage.addon.primary; +import org.apache.commons.lang.StringUtils; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.transaction.annotation.Propagation; +import org.springframework.transaction.annotation.Transactional; import org.zstack.core.Platform; import org.zstack.core.asyncbatch.While; import org.zstack.core.cloudbus.CloudBus; @@ -11,6 +14,7 @@ import org.zstack.core.db.DatabaseFacade; import org.zstack.core.db.Q; import org.zstack.core.singleflight.MultiNodeSingleFlightImpl; +import org.zstack.core.trash.StorageTrash; import org.zstack.core.workflow.FlowChainBuilder; import org.zstack.header.Component; import org.zstack.header.apimediator.ApiMessageInterceptionException; @@ -38,17 +42,22 @@ import org.zstack.header.vm.*; import org.zstack.header.vm.cdrom.VmCdRomVO; import org.zstack.header.vm.cdrom.VmCdRomVO_; +import org.zstack.header.volume.VolumeDeletionPolicyManager; import org.zstack.header.volume.VolumeInventory; import org.zstack.header.volume.VolumeVO; +import org.zstack.header.volume.VolumeVO_; import org.zstack.header.volume.block.BlockVolumeVO; import org.zstack.storage.addon.backup.ExternalBackupStorageFactory; import org.zstack.storage.primary.PrimaryStorageFeatureAllocatorExtensionPoint; import org.zstack.storage.snapshot.MarkRootVolumeAsSnapshotExtension; +import org.zstack.storage.volume.ChangeVolumeProcessingMethodExtensionPoint; import org.zstack.utils.CollectionUtils; import org.zstack.utils.Utils; import org.zstack.utils.logging.CLogger; import java.util.*; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import java.util.stream.Collectors; import static org.zstack.core.Platform.argerr; @@ -58,7 +67,9 @@ public class ExternalPrimaryStorageFactory implements PrimaryStorageFactory, Com PreVmInstantiateResourceExtensionPoint, VmReleaseResourceExtensionPoint, VmAttachVolumeExtensionPoint, VmDetachVolumeExtensionPoint, BeforeTakeLiveSnapshotsOnVolumes, CreateTemplateFromVolumeSnapshotExtensionPoint, MarkRootVolumeAsSnapshotExtension, VmInstanceMigrateExtensionPoint, - ManagementNodeChangeListener, PrimaryStorageFeatureAllocatorExtensionPoint, HostResizeVolumeExtensionPoint { + ManagementNodeChangeListener, PrimaryStorageFeatureAllocatorExtensionPoint, HostResizeVolumeExtensionPoint, + VolumeSnapshotAfterDeleteExtensionPoint, ChangeVolumeProcessingMethodExtensionPoint, + RecalculatePrimaryStorageCapacityExtensionPoint { private static final CLogger logger = Utils.getLogger(ExternalBackupStorageFactory.class); public static PrimaryStorageType type = new PrimaryStorageType(PrimaryStorageConstant.EXTERNAL_PRIMARY_STORAGE_TYPE); @@ -81,6 +92,8 @@ public class ExternalPrimaryStorageFactory implements PrimaryStorageFactory, Com protected CloudBus bus; @Autowired protected EventFacade evtf; + @Autowired + protected StorageTrash trash; static { type.setSupportHeartbeatFile(true); @@ -164,38 +177,87 @@ public boolean stop() { return false; } + private String getRequiredUrl(ExternalPrimaryStorageSpaceCapacityHelper helper, AllocatePrimaryStorageSpaceMsg msg) { + if (msg.getRequiredInstallUri() != null) { + String url = msg.getRequiredInstallUri(); + if (!url.startsWith("volume://")) { + return url; + } + + String volUuid = url.substring("volume://".length()); + String volumePath = Q.New(VolumeVO.class).eq(VolumeVO_.uuid, volUuid).select(VolumeVO_.installPath).findValue(); + if (volumePath == null) { + throw new OperationFailureException( + Platform.operr("cannot find volume[uuid:%s] install path", volUuid) + ); + } + + return helper.getLocationSpaceUrl(volumePath); + } + + String requiredSystag = msg.getSystemTag(ExternalPrimaryStorageSystemTags.REQUIRED_INSTALL_URL::isMatch); + if (requiredSystag != null) { + return ExternalPrimaryStorageSystemTags.REQUIRED_INSTALL_URL.getTokenByTag(requiredSystag, + ExternalPrimaryStorageSystemTags.REQUIRED_INSTALL_URL_TOKEN); + } + + return null; + } + @Override - public String buildAllocatedInstallUrl(AllocatePrimaryStorageSpaceMsg msg, PrimaryStorageInventory psInv) { + public String allocateSpaceDryRun(AllocatePrimaryStorageSpaceMsg msg, PrimaryStorageInventory psInv) { PrimaryStorageControllerSvc controller = controllers.get(psInv.getUuid()); if (controller == null) { return psInv.getUrl(); } - AllocateSpaceSpec aspec = new AllocateSpaceSpec(); - aspec.setDryRun(true); - aspec.setSize(msg.getSize()); - aspec.setRequiredUrl(msg.getRequiredInstallUri()); - return controller.allocateSpace(aspec); + ExternalPrimaryStorageSpaceCapacityHelper helper = new ExternalPrimaryStorageSpaceCapacityHelper(psInv.getUuid(), controller.getIdentity()); + String requiredUrl = getRequiredUrl(helper, msg); + + // TODO: remove it + if (!controller.reportCapabilities().isSupportMultiSpace()) { + AllocateSpaceSpec aspec = new AllocateSpaceSpec(); + aspec.setDryRun(true); + aspec.setSize(msg.getSize()); + aspec.setRequiredUrl(requiredUrl); + return controller.allocateSpace(aspec); + } + + if (requiredUrl != null) { + if (msg.isForce() || helper.checkVirtualSizeByRatio(requiredUrl, msg.getSize())) { + return requiredUrl; + } else { + return null; + } + } + + // return max available capacity space + return helper.findMostSuitableSpace(msg.getSize(), Comparator.comparingLong(ExternalPrimaryStorageSpaceVO::getAvailableCapacity).reversed()); } @Override + @Transactional(propagation = Propagation.MANDATORY) public long reserveCapacity(AllocatePrimaryStorageSpaceMsg msg, String allocatedInstallUrl, long size, String psUuid) { PrimaryStorageControllerSvc controller = controllers.get(psUuid); - if (controller == null) { + if (controller == null || !controller.reportCapabilities().isSupportMultiSpace()) { return size; } - AllocateSpaceSpec aspec = new AllocateSpaceSpec(); - aspec.setDryRun(false); - aspec.setSize(msg.getSize()); - aspec.setRequiredUrl(msg.getRequiredInstallUri()); - controller.allocateSpace(aspec); + ExternalPrimaryStorageSpaceCapacityHelper helper = new ExternalPrimaryStorageSpaceCapacityHelper(psUuid, controller.getIdentity()); + helper.reserveAvailableCapacity(allocatedInstallUrl, size); return size; } @Override + @Transactional(propagation = Propagation.MANDATORY) public void releaseCapacity(String allocatedInstallUrl, long size, String psUuid) { + PrimaryStorageControllerSvc controller = controllers.get(psUuid); + if (controller == null || !controller.reportCapabilities().isSupportMultiSpace()) { + return; + } + ExternalPrimaryStorageSpaceCapacityHelper helper = new ExternalPrimaryStorageSpaceCapacityHelper(psUuid, controller.getIdentity()); + helper.releaseAvailableCapacity(allocatedInstallUrl, size); } @Override @@ -265,6 +327,10 @@ public void validateStorageProtocol(String protocol) { } } + public List getAllControllerSvcs() { + return new ArrayList<>(controllers.values()); + } + public PrimaryStorageControllerSvc getControllerSvc(String primaryStorageUuid) { return controllers.get(primaryStorageUuid); } @@ -1001,4 +1067,86 @@ public HostResizeVolumeStruct beforeKvmHostResizeVolume(HostResizeVolumeStruct s struct.setSize(controller.alignSize(struct.getSize())); return struct; } + + @Override + public void volumeSnapshotAfterDeleteExtensionPoint(VolumeSnapshotInventory snapshot, NoErrorCompletion completion) { + completion.done(); + } + + + @Override + public void volumeSnapshotAfterCleanUpExtensionPoint(String volumeUuid, List snapshots) { + if (CollectionUtils.isEmpty(snapshots)) { + return; + } + + String psUuid = snapshots.get(0).getPrimaryStorageUuid(); + PrimaryStorageControllerSvc controller = controllers.get(psUuid); + if (controller == null) { + return; + } + + VolumeSnapshotCapability snapCap = controller.reportCapabilities().getSnapshotCapability(); + if (snapCap.getPlacementType() != VolumeSnapshotCapability.VolumeSnapshotPlacementType.INTERNAL) { + return; + } + + Pattern pattern = Pattern.compile(snapCap.getVolumePathFromInternalSnapshotRegex()); + Set volumeInstallPaths = snapshots.stream().map(s -> { + Matcher matcher = pattern.matcher(s.getPrimaryStorageInstallPath()); + if (matcher.find()) { + return matcher.group(); + } else { + logger.warn(String.format("cannot find volume install path from internal snapshot install path[%s] " + + "by regex[%s], skip deleting volume bits on primary storage", s.getPrimaryStorageInstallPath(), + snapCap.getVolumePathFromInternalSnapshotRegex())); + return null; + } + }).filter(Objects::nonNull).collect(Collectors.toSet()); + + volumeInstallPaths.forEach(volumeInstallPath -> { + String details = trash.makeSureInstallPathNotUsed(volumeInstallPath, VolumeVO.class.getSimpleName()); + + if (StringUtils.isBlank(details)) { + logger.debug(String.format("delete volume[InstallPath:%s] after cleaning up snapshots", volumeInstallPath)); + DeleteVolumeBitsOnPrimaryStorageMsg msg = new DeleteVolumeBitsOnPrimaryStorageMsg(); + msg.setPrimaryStorageUuid(snapshots.get(0).getPrimaryStorageUuid()); + msg.setInstallPath(volumeInstallPath); + bus.makeTargetServiceIdByResourceUuid(msg, PrimaryStorageConstant.SERVICE_ID, snapshots.get(0).getPrimaryStorageUuid()); + bus.send(msg); + } + }); + } + + @Override + public VolumeDeletionPolicyManager.VolumeDeletionPolicy getTransientVolumeDeletionPolicy(VolumeInventory transientVolume) { + PrimaryStorageControllerSvc controllerSvc = controllers.get(transientVolume.getPrimaryStorageUuid()); + if (controllerSvc == null || controllerSvc.reportCapabilities().getSnapshotCapability() + .getPlacementType() != VolumeSnapshotCapability.VolumeSnapshotPlacementType.INTERNAL) { + return null; + } + + boolean hasSnapshots = Q.New(VolumeSnapshotVO.class).eq(VolumeSnapshotVO_.primaryStorageUuid, transientVolume.getPrimaryStorageUuid()) + .like(VolumeSnapshotVO_.primaryStorageInstallPath, String.format("%s@%%", transientVolume.getInstallPath())).isExists(); + if (!hasSnapshots) { + return VolumeDeletionPolicyManager.VolumeDeletionPolicy.Direct; + } + return VolumeDeletionPolicyManager.VolumeDeletionPolicy.DBOnly; + } + + public String getPrimaryStorageTypeForRecalculateCapacityExtensionPoint() { + return type.toString(); + } + + @Override + public void afterRecalculatePrimaryStorageCapacity(RecalculatePrimaryStorageCapacityStruct struct) { + PrimaryStorageControllerSvc controller = controllers.get(struct.getPrimaryStorageUuid()); + if (controller == null || !controller.reportCapabilities().isSupportMultiSpace()) { + return; + } + new ExternalPrimaryStorageSpaceCapacityHelper(struct.getPrimaryStorageUuid(), controller.getIdentity()).recalculateAvailableCapacity(); + } + + @Override + public void beforeRecalculatePrimaryStorageCapacity(RecalculatePrimaryStorageCapacityStruct struct) {} } diff --git a/storage/src/main/java/org/zstack/storage/addon/primary/ExternalPrimaryStorageSpaceCapacityHelper.java b/storage/src/main/java/org/zstack/storage/addon/primary/ExternalPrimaryStorageSpaceCapacityHelper.java new file mode 100644 index 0000000000..9fa5f2269b --- /dev/null +++ b/storage/src/main/java/org/zstack/storage/addon/primary/ExternalPrimaryStorageSpaceCapacityHelper.java @@ -0,0 +1,285 @@ +package org.zstack.storage.addon.primary; + +import org.apache.commons.collections.CollectionUtils; +import org.springframework.beans.factory.annotation.Autowire; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Configurable; +import org.springframework.transaction.annotation.Transactional; +import org.zstack.core.Platform; +import org.zstack.core.db.DatabaseFacade; +import org.zstack.core.db.DeadlockAutoRestart; +import org.zstack.core.db.Q; +import org.zstack.core.db.SQL; +import org.zstack.header.errorcode.OperationFailureException; +import org.zstack.header.storage.addon.StorageCapacity; +import org.zstack.header.storage.addon.primary.ExternalPrimaryStorageSpaceVO; +import org.zstack.header.storage.addon.primary.ExternalPrimaryStorageSpaceVO_; +import org.zstack.header.storage.addon.primary.ExternalPrimaryStorageVO; +import org.zstack.header.storage.primary.ImageCacheVO; +import org.zstack.header.storage.primary.ImageCacheVO_; +import org.zstack.header.storage.primary.PrimaryStorageOverProvisioningManager; +import org.zstack.header.storage.snapshot.VolumeSnapshotVO; +import org.zstack.header.storage.snapshot.VolumeSnapshotVO_; +import org.zstack.header.volume.VolumeVO; +import org.zstack.header.volume.VolumeVO_; +import org.zstack.storage.primary.PrimaryStorageCapacityChecker; +import org.zstack.utils.Utils; +import org.zstack.utils.logging.CLogger; +import org.zstack.utils.stopwatch.StopWatch; + +import java.util.*; +import java.util.stream.Collectors; + +import static java.util.Arrays.asList; +import static org.zstack.core.Platform.operr; + + +@Configurable(preConstruction = true, autowire = Autowire.BY_TYPE) +public class ExternalPrimaryStorageSpaceCapacityHelper extends ExternalPrimaryStorageSpaceHelper { + @Autowired + protected PrimaryStorageOverProvisioningManager ratioMgr; + @Autowired + protected ExternalPrimaryStorageFactory extFactory; + @Autowired + protected DatabaseFacade dbf; + + + private static final CLogger logger = Utils.getLogger(ExternalPrimaryStorageSpaceCapacityHelper.class); + + private String primaryStorageUuid; + private String spaceName; + private Map storageSpacesByUrl; + + public ExternalPrimaryStorageSpaceCapacityHelper(ExternalPrimaryStorageVO ps) { + super(ps); + this.primaryStorageUuid = ps.getUuid(); + this.spaceName = ps.getIdentity(); + } + + public ExternalPrimaryStorageSpaceCapacityHelper(String psUuid, String identity) { + super(psUuid, identity); + this.primaryStorageUuid = psUuid; + spaceName = identity; + } + + protected void updateStorageSpace(StorageCapacity cap) { + if (cap.getCapacitiesByLocationUrl() == null || cap.getCapacitiesByLocationUrl().isEmpty()) { + return; + } + + List beforeSpaces = Q.New(ExternalPrimaryStorageSpaceVO.class) + .eq(ExternalPrimaryStorageSpaceVO_.primaryStorageUuid, primaryStorageUuid) + .list(); + + Map beforeSpacesByUrl = beforeSpaces.stream() + .collect(Collectors.toMap(ExternalPrimaryStorageSpaceVO::getLocationUrl, it -> it)); + List toPersistSpaces = new ArrayList<>(); + List toRemoveSpaces = new ArrayList<>(); + + for (Map.Entry e : cap.getCapacitiesByLocationUrl().entrySet()) { + String locationUrl = e.getKey(); + StorageCapacity.Capacity capacity = e.getValue(); + ExternalPrimaryStorageSpaceVO spaceVO = beforeSpacesByUrl.get(locationUrl); + if (spaceVO == null) { + spaceVO = new ExternalPrimaryStorageSpaceVO(); + spaceVO.setUuid(Platform.getUuidFromBytes((primaryStorageUuid + locationUrl).getBytes())); + spaceVO.setPrimaryStorageUuid(primaryStorageUuid); + spaceVO.setLocationUrl(locationUrl.replaceAll("/$", "")); + spaceVO.setTotalPhysicalCapacity(capacity.total); + spaceVO.setAvailablePhysicalCapacity(capacity.available); + spaceVO.setTotalCapacity(capacity.total); + spaceVO.setAvailableCapacity(capacity.available); + toPersistSpaces.add(spaceVO); + } else { + spaceVO.setTotalPhysicalCapacity(capacity.total); + spaceVO.setAvailablePhysicalCapacity(capacity.available); + spaceVO.setTotalCapacity(capacity.total); + } + } + + for (Iterator> it = beforeSpacesByUrl.entrySet().iterator(); it.hasNext(); ) { + Map.Entry entry = it.next(); + if (!cap.getCapacitiesByLocationUrl().containsKey(entry.getKey())) { + toRemoveSpaces.add(entry.getValue()); + it.remove(); + } + } + + if (!toRemoveSpaces.isEmpty()) { + dbf.removeCollection(toRemoveSpaces, ExternalPrimaryStorageSpaceVO.class); + } + if (!toPersistSpaces.isEmpty()) { + dbf.persistCollection(toPersistSpaces); + } + dbf.updateCollection(beforeSpacesByUrl.values()); + } + + private ExternalPrimaryStorageSpaceVO getSpaceFromInstallUrl(String installPath) { + Map spacesByUrl = getStorageSpacesByUrl(); + String spaceUrl = spacesByUrl.keySet().stream().filter(installPath::startsWith) + .findFirst().orElseThrow(() -> new OperationFailureException(operr("cannot find storage space for installPath[%s]", installPath))); + return spacesByUrl.get(spaceUrl); + } + + @DeadlockAutoRestart + public void releaseAvailableCapWithRatio(String installPath, long size) { + long ratioSize = ratioMgr.calculateByRatio(primaryStorageUuid, size); + _release(installPath, ratioSize); + } + + @DeadlockAutoRestart + public void releaseAvailableCapacity(String installPath, long size) { + _release(installPath, size); + } + + @Transactional + protected void _release(String installPath, long size) { + if (installPath == null) { + logger.debug(String.format("no install path found, skip release %s capacity", spaceName)); + return; + } + + ExternalPrimaryStorageSpaceVO space = getSpaceFromInstallUrl(installPath); + space.setAvailableCapacity(space.getAvailableCapacity() + size); + if (space.getAvailableCapacity() > space.getTotalPhysicalCapacity()) { + logger.warn(String.format("invalid space[locationUrl:%s] capacity after release size %s, available capacity[%s] > total capacity[%s], " + + "try to reconnect ps to recalculate pool capacity", + space.getLocationUrl(), size, space.getAvailableCapacity(), space.getTotalPhysicalCapacity())); + } + + dbf.getEntityManager().merge(space); + logger.debug(String.format("ps space [%s] release capacity: %s, updated: %s", + space.getLocationUrl(), size, space.getAvailableCapacity())); + } + + @DeadlockAutoRestart + public long reserveAvailableCapacity(String installPath, long size) { + return _reserve(installPath, size); + } + + @Transactional + protected long _reserve(String installPath, long size) { + if (installPath == null) { + logger.debug(String.format("no install path found, skip reserve %s capacity", spaceName)); + return 0; + } + + + ExternalPrimaryStorageSpaceVO space = getSpaceFromInstallUrl(installPath); + long originAvailableCapacity = space.getAvailableCapacity(); + if (originAvailableCapacity < size) { + throw new OperationFailureException(operr("required space[locationUrl:%s] cannot satisfy conditions [availableSize > %s bytes], " + + "current available size %s", space.getLocationUrl(), size, originAvailableCapacity)); + } + + space.setAvailableCapacity(space.getAvailableCapacity() - size); + dbf.getEntityManager().merge(space); + + logger.debug(String.format("%s[%s] reserve capacity: %s, origin: %s, updated: %s", + spaceName, space.getLocationUrl(), size, originAvailableCapacity, space.getAvailableCapacity())); + return originAvailableCapacity; + } + + public void recalculateAvailableCapacity() { + Map spacesByUrl = getStorageSpacesByUrl(); + Map usedCapBySpaceUrl = spacesByUrl.keySet().stream() + .collect(Collectors.toMap(url -> url, url -> 0L )); + + StopWatch watch = Utils.getStopWatch(); + watch.start(); + + // 1. calculate used capacity from volumes + long total = Q.New(VolumeVO.class).eq(VolumeVO_.primaryStorageUuid, primaryStorageUuid).count(); + SQL.New("select vol from VolumeVO vol" + + " where primaryStorageUuid = :psUuid", VolumeVO.class) + .param("psUuid", primaryStorageUuid) + .limit(1000) + .paginate(total, vos -> { + for (Object v : vos) { + VolumeVO vo = (VolumeVO) v; + if (vo.getInstallPath() != null) { + ExternalPrimaryStorageSpaceVO space = getSpaceFromInstallUrl(vo.getInstallPath()); + usedCapBySpaceUrl.compute(space.getLocationUrl(), (k, usedCap) -> usedCap + vo.getSize()); + } + } + }); + + for (String key : usedCapBySpaceUrl.keySet()) { + usedCapBySpaceUrl.compute(key, (k, usedCap) -> ratioMgr.calculateByRatio(primaryStorageUuid, usedCap)); + } + + // 2. calculate used capacity from image caches + total = Q.New(ImageCacheVO.class).eq(ImageCacheVO_.primaryStorageUuid, primaryStorageUuid).count(); + SQL.New("select img from ImageCacheVO img" + + " where primaryStorageUuid = :psUuid", ImageCacheVO.class) + .param("psUuid", primaryStorageUuid) + .limit(1000) + .paginate(total, imgs -> { + for (Object i : imgs) { + ImageCacheVO img = (ImageCacheVO) i; + if (img.getInstallUrl() != null) { + ExternalPrimaryStorageSpaceVO space = getSpaceFromInstallUrl(img.getInstallUrl()); + usedCapBySpaceUrl.compute(space.getLocationUrl(), (k, usedCap) -> usedCap + img.getSize()); + } + } + }); + + + // 3. calculate used capacity from snapshots + total = Q.New(VolumeSnapshotVO.class).eq(VolumeSnapshotVO_.primaryStorageUuid, primaryStorageUuid).count(); + SQL.New("select snap from VolumeSnapshotVO snap" + + " where primaryStorageUuid = :psUuid", VolumeSnapshotVO.class) + .param("psUuid", primaryStorageUuid) + .limit(1000) + .paginate(total, snaps -> { + for (Object s : snaps) { + VolumeSnapshotVO snap = (VolumeSnapshotVO) s; + if (snap.getPrimaryStorageInstallPath() != null) { + ExternalPrimaryStorageSpaceVO space = getSpaceFromInstallUrl(snap.getPrimaryStorageInstallPath()); + usedCapBySpaceUrl.compute(space.getLocationUrl(), (k, usedCap) -> usedCap + snap.getSize()); + } + } + }); + + watch.stop(); + logger.info(String.format("it takes %d ms to recalculate external primary storage [%s] space used capacity", + watch.getLapse(), primaryStorageUuid)); + + // 4. update available capacity + for (Map.Entry e : spacesByUrl.entrySet()) { + String url = e.getKey(); + ExternalPrimaryStorageSpaceVO space = e.getValue(); + long usedCap = usedCapBySpaceUrl.get(url); + long availableCap = space.getTotalPhysicalCapacity() - usedCap; + space.setAvailableCapacity(availableCap); + logger.info(String.format("recalculated external primary storage [%s] space [%s] available capacity: %s, used capacity: %s, total capacity: %s", + primaryStorageUuid, url, availableCap, usedCap, space.getTotalPhysicalCapacity())); + } + + dbf.updateCollection(spacesByUrl.values()); + } + + public boolean checkVirtualSizeByRatio(String requiredInstallUrl, long requiredSize) { + ExternalPrimaryStorageSpaceVO space = getSpaceFromInstallUrl(requiredInstallUrl); + return PrimaryStorageCapacityChecker.New(primaryStorageUuid, + space.getAvailableCapacity(), space.getTotalPhysicalCapacity(), space.getAvailablePhysicalCapacity()) + .checkRequiredSize(requiredSize); + } + + public String findMostSuitableSpace(long requiredSize, Comparator comparator) { + Map spacesByUrl = getStorageSpacesByUrl(); + List suitableSpaces = spacesByUrl.values().stream() + .filter(space -> PrimaryStorageCapacityChecker.New(primaryStorageUuid, + space.getAvailableCapacity(), space.getTotalPhysicalCapacity(), space.getAvailablePhysicalCapacity()) + .checkRequiredSize(requiredSize)) + .collect(Collectors.toList()); + if (CollectionUtils.isEmpty(suitableSpaces)) { + return null; + } + + suitableSpaces.sort(comparator); + return suitableSpaces.get(0).getLocationUrl(); + } + + +} diff --git a/storage/src/main/java/org/zstack/storage/addon/primary/ExternalPrimaryStorageSpaceHelper.java b/storage/src/main/java/org/zstack/storage/addon/primary/ExternalPrimaryStorageSpaceHelper.java new file mode 100644 index 0000000000..ee176db224 --- /dev/null +++ b/storage/src/main/java/org/zstack/storage/addon/primary/ExternalPrimaryStorageSpaceHelper.java @@ -0,0 +1,56 @@ +package org.zstack.storage.addon.primary; + +import org.apache.commons.collections.CollectionUtils; +import org.zstack.core.db.Q; +import org.zstack.header.errorcode.OperationFailureException; +import org.zstack.header.storage.addon.primary.ExternalPrimaryStorageSpaceVO; +import org.zstack.header.storage.addon.primary.ExternalPrimaryStorageSpaceVO_; +import org.zstack.header.storage.addon.primary.ExternalPrimaryStorageVO; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + +import static org.zstack.core.Platform.operr; + +public class ExternalPrimaryStorageSpaceHelper { + protected String primaryStorageUuid; + protected String spaceName; + protected Map storageSpacesByUrl; + + public ExternalPrimaryStorageSpaceHelper(ExternalPrimaryStorageVO ps) { + super(); + this.primaryStorageUuid = ps.getUuid(); + this.spaceName = ps.getIdentity(); + } + + public ExternalPrimaryStorageSpaceHelper(String psUuid, String identity) { + this.primaryStorageUuid = psUuid; + spaceName = identity; + } + + public Map getStorageSpacesByUrl() { + if (storageSpacesByUrl == null) { + List spaces = Q.New(ExternalPrimaryStorageSpaceVO.class) + .eq(ExternalPrimaryStorageSpaceVO_.primaryStorageUuid, primaryStorageUuid) + .list(); + if (CollectionUtils.isEmpty(spaces)) { + storageSpacesByUrl = new HashMap<>(); + } else { + storageSpacesByUrl = spaces.stream() + .collect(Collectors.toMap(ExternalPrimaryStorageSpaceVO::getLocationUrl, it -> it)); + spaceName += (" " + spaces.get(0).getType()); + } + } + return storageSpacesByUrl; + } + + // TODO: add cache for db result + public String getLocationSpaceUrl(String installUrl) { + Set spaceUrls = getStorageSpacesByUrl().keySet(); + return spaceUrls.stream().filter(installUrl::startsWith).findFirst() + .orElseThrow(() -> new OperationFailureException(operr("cannot find storage space for installUrl[%s]", installUrl))); + } +} diff --git a/storage/src/main/java/org/zstack/storage/addon/primary/ExternalPrimaryStorageSystemTags.java b/storage/src/main/java/org/zstack/storage/addon/primary/ExternalPrimaryStorageSystemTags.java new file mode 100644 index 0000000000..3ffca439ee --- /dev/null +++ b/storage/src/main/java/org/zstack/storage/addon/primary/ExternalPrimaryStorageSystemTags.java @@ -0,0 +1,13 @@ +package org.zstack.storage.addon.primary; + +import org.zstack.header.cluster.ClusterVO; +import org.zstack.header.tag.TagDefinition; +import org.zstack.tag.EphemeralPatternSystemTag; + +@TagDefinition +public class ExternalPrimaryStorageSystemTags { + public static String REQUIRED_INSTALL_URL_TOKEN = "requiredInstallUrl"; + public static EphemeralPatternSystemTag REQUIRED_INSTALL_URL = new EphemeralPatternSystemTag( + String.format("required::installUrl::{%s}", REQUIRED_INSTALL_URL_TOKEN), + ClusterVO.class); +} \ No newline at end of file diff --git a/storage/src/main/java/org/zstack/storage/primary/ImageCacheUtil.java b/storage/src/main/java/org/zstack/storage/primary/ImageCacheUtil.java index bdae91b21f..3c835bf738 100644 --- a/storage/src/main/java/org/zstack/storage/primary/ImageCacheUtil.java +++ b/storage/src/main/java/org/zstack/storage/primary/ImageCacheUtil.java @@ -23,10 +23,14 @@ public static String getImageCachePath(ImageInventory image, Function e -> + def cmd = JSONObjectUtil.toObject(e.body, KVMAgentCommands.StartVmCmd.class) + assert cmd.useHugePage + assert cmd.memAccess == "shared" + return rsp + } + + VmGlobalConfig.GENERATE_CONFIG_VHOST_REQUIRED.updateValue("auto") + + def vm1 = createVmInstance { + name = "vm" + instanceOfferingUuid = instanceOffering.uuid + rootDiskOfferingUuid = diskOffering.uuid + imageUuid = image.uuid + l3NetworkUuids = [l3.uuid] + primaryStorageUuidForRootVolume = sblk.uuid + } as VmInstanceInventory + + VmGlobalConfig.GENERATE_CONFIG_VHOST_REQUIRED.updateValue("true") + + def vm2 = createVmInstance { + name = "vm" + instanceOfferingUuid = instanceOffering.uuid + rootDiskOfferingUuid = diskOffering.uuid + imageUuid = image.uuid + l3NetworkUuids = [l3.uuid] + primaryStorageUuidForRootVolume = sblk.uuid + } as VmInstanceInventory + + detachPrimaryStorageFromCluster { + primaryStorageUuid = sblk.uuid + clusterUuid = cluster.getUuid() + } + + deletePrimaryStorage { + uuid = sblk.uuid + } + + VmGlobalConfig.GENERATE_CONFIG_VHOST_REQUIRED.updateValue("false") + def vm3 = createVmInstance { + name = "vm" + instanceOfferingUuid = instanceOffering.uuid + rootDiskOfferingUuid = diskOffering.uuid + imageUuid = image.uuid + l3NetworkUuids = [l3.uuid] + } as VmInstanceInventory + + deleteVm(vm1.uuid) + deleteVm(vm2.uuid) + deleteVm(vm3.uuid) + } + void testDeletePs() { assert MultiNodeSingleFlightImpl.getExecutor(ps.uuid) != null 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 5fc8f14aa9..b546772215 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 @@ -3,16 +3,22 @@ package org.zstack.test.integration.storage.primary.addon.zbs import org.springframework.http.HttpEntity import org.zstack.core.db.Q import org.zstack.header.storage.addon.primary.ExternalPrimaryStorageVO +import org.zstack.header.storage.addon.primary.ExternalPrimaryStorageSpaceVO import org.zstack.header.storage.addon.primary.ExternalPrimaryStorageVO_ +import org.zstack.header.storage.addon.primary.ExternalPrimaryStorageSpaceVO_ +import org.zstack.header.storage.primary.PrimaryStorageCapacityVO +import org.zstack.header.storage.primary.PrimaryStorageCapacityVO_ import org.zstack.header.storage.primary.PrimaryStorageHostRefVO import org.zstack.header.storage.primary.PrimaryStorageHostRefVO_ import org.zstack.header.storage.primary.PrimaryStorageStatus -import org.zstack.cbd.MdsUri -import org.zstack.kvm.KVMAgentCommands +import org.zstack.storage.zbs.MdsUri import org.zstack.sdk.* +import org.zstack.storage.addon.primary.ExternalPrimaryStorageSystemTags import org.zstack.storage.primary.PrimaryStorageGlobalConfig import org.zstack.header.storage.primary.PrimaryStorageHostStatus import org.zstack.storage.volume.VolumeGlobalConfig +import org.zstack.storage.zbs.AddonInfo +import org.zstack.storage.zbs.Config import org.zstack.storage.zbs.ZbsConstants import org.zstack.storage.zbs.ZbsPrimaryStorageMdsBase import org.zstack.storage.zbs.ZbsStorageController @@ -136,7 +142,7 @@ class ZbsPrimaryStorageCase extends SubCase { identity = "zbs" defaultOutputProtocol = "CBD" config = "{\"mdsUrls\":[\"root:password@127.0.1.1\",\"root:password@127.0.1.2\",\"root:password@127.0.1.3\"],\"logicalPoolName\":\"lpool1\"}" - url = "fake url" + url = "zbs" } attachBackupStorage("sftp") @@ -218,6 +224,14 @@ class ZbsPrimaryStorageCase extends SubCase { } } + expect(AssertionError.class) { + updateExternalPrimaryStorage { + uuid = ps.uuid + config = "{\"mdsUrls\":[\"root:password@127.0.1.1\",\"root:password@127.0.1.1\"]}" + } + } + + updateExternalPrimaryStorage { uuid = ps.uuid config = "{\"mdsUrls\":[\"root:password@127.0.1.1\",\"root:password@127.0.1.2\"],\"logicalPoolName\":\"lpool1\"}" @@ -250,6 +264,41 @@ class ZbsPrimaryStorageCase extends SubCase { .eq(ExternalPrimaryStorageVO_.uuid, ps.uuid) .findValue() assert addonInfo.contains("127.0.1.3") + + + assert Q.New(ExternalPrimaryStorageSpaceVO.class) + .eq(ExternalPrimaryStorageSpaceVO_.primaryStorageUuid, ps.uuid) + .count() == 1 + // update multi pools + // Config.Pool + updateExternalPrimaryStorage { + uuid = ps.uuid + config = "{\"mdsUrls\":[\"root:password@127.0.1.1\",\"root:password@127.0.1.2\",\"root:password@127.0.1.3\"]," + + "\"pools\":[{\"logicalName\":\"lpool1\"}, {\"logicalName\":\"lpool2\"}]}" + } + + assert Q.New(ExternalPrimaryStorageSpaceVO.class) + .eq(ExternalPrimaryStorageSpaceVO_.primaryStorageUuid, ps.uuid) + .count() == 2 + + retryInSecs { + Config config = JSONObjectUtil.toObject( + Q.New(ExternalPrimaryStorageVO.class) + .select(ExternalPrimaryStorageVO_.config) + .eq(ExternalPrimaryStorageVO_.uuid, ps.uuid) + .findValue(), + Config.class) + AddonInfo info = JSONObjectUtil.toObject( + Q.New(ExternalPrimaryStorageVO.class) + .select(ExternalPrimaryStorageVO_.addonInfo) + .eq(ExternalPrimaryStorageVO_.uuid, ps.uuid) + .findValue(), + AddonInfo.class) + assert config.pools.size() == 2 + assert info.logicalPoolInfos.size() == 2 + assert config.poolNames.containsAll(["lpool1", "lpool2"]) + assert info.logicalPoolInfos.collect { it.logicalPoolName }.containsAll(["lpool1", "lpool2"]) + } } void testDefaultConfig() { @@ -269,7 +318,6 @@ class ZbsPrimaryStorageCase extends SubCase { ps = queryPrimaryStorage {}[0] as ExternalPrimaryStorageInventory assert ps.name == "test-zbs-new-name" - assert ps.url == ZbsConstants.ZBS_CBD_PREFIX_SCHEME + ps.uuid reconnectPrimaryStorage { uuid = ps.uuid @@ -321,7 +369,12 @@ class ZbsPrimaryStorageCase extends SubCase { def addonInfo = Q.New(ExternalPrimaryStorageVO.class).select(ExternalPrimaryStorageVO_.addonInfo).eq(ExternalPrimaryStorageVO_.uuid, ps.uuid).findValue() - assert addonInfo == "{\"clusterInfo\":{\"uuid\":\"123456789\",\"version\":\"1.6.1-for-test\"},\"mdsInfos\":[{\"username\":\"root\",\"password\":\"password\",\"port\":22,\"addr\":\"127.0.1.1\",\"externalAddr\":\"127.0.0.1\",\"status\":\"Connected\"},{\"username\":\"root\",\"password\":\"password\",\"port\":22,\"addr\":\"127.0.1.2\",\"externalAddr\":\"127.0.0.1\",\"status\":\"Connected\"},{\"username\":\"root\",\"password\":\"password\",\"port\":22,\"addr\":\"127.0.1.3\",\"externalAddr\":\"127.0.0.1\",\"status\":\"Connected\"}],\"logicalPoolInfos\":[{\"physicalPoolID\":1,\"redundanceAndPlaceMentPolicy\":{\"copysetNum\":300,\"replicaNum\":3,\"zoneNum\":3},\"logicalPoolID\":1,\"usedSize\":322961408,\"quota\":0,\"createTime\":1735875794,\"type\":0,\"rawWalUsedSize\":0,\"allocateStatus\":0,\"rawUsedSize\":968884224,\"physicalPoolName\":\"pool1\",\"capacity\":579933831168,\"logicalPoolName\":\"lpool1\",\"userPolicy\":\"eyJwb2xpY3kiIDogMX0=\",\"allocatedSize\":3221225472}]}" + assert addonInfo == "{\"clusterInfo\":{\"uuid\":\"123456789\",\"version\":\"1.6.1-for-test\"}," + + "\"mdsInfos\":[{\"username\":\"root\",\"password\":\"password\",\"port\":22,\"addr\":\"127.0.1.1\",\"externalAddr\":\"127.0.0.1\",\"status\":\"Connected\"}," + + "{\"username\":\"root\",\"password\":\"password\",\"port\":22,\"addr\":\"127.0.1.2\",\"externalAddr\":\"127.0.0.1\",\"status\":\"Connected\"}," + + "{\"username\":\"root\",\"password\":\"password\",\"port\":22,\"addr\":\"127.0.1.3\",\"externalAddr\":\"127.0.0.1\",\"status\":\"Connected\"}]," + + "\"logicalPoolInfos\":[{\"physicalPoolID\":1,\"redundanceAndPlaceMentPolicy\":{\"copysetNum\":300,\"replicaNum\":3,\"zoneNum\":3},\"logicalPoolID\":1,\"usedSize\":322961408,\"quota\":0,\"createTime\":1735875794,\"type\":0,\"rawWalUsedSize\":0,\"allocateStatus\":0,\"rawUsedSize\":968884224,\"physicalPoolName\":\"pool1\",\"capacity\":579933831168,\"logicalPoolName\":\"lpool1\",\"userPolicy\":\"eyJwb2xpY3kiIDogMX0=\",\"allocatedSize\":3221225472}," + + "{\"physicalPoolID\":2,\"redundanceAndPlaceMentPolicy\":{\"copysetNum\":300,\"replicaNum\":3,\"zoneNum\":3},\"logicalPoolID\":2,\"usedSize\":123456789,\"quota\":0,\"createTime\":1735875794,\"type\":0,\"rawWalUsedSize\":0,\"allocateStatus\":0,\"rawUsedSize\":123456789,\"physicalPoolName\":\"pool2\",\"capacity\":579933831168,\"logicalPoolName\":\"lpool2\",\"userPolicy\":\"eyJwb2xpY3kiIDogMX0=\",\"allocatedSize\":987654321}]}" env.afterSimulator(ZbsPrimaryStorageMdsBase.PING_PATH) { rsp, HttpEntity e -> def cmd = JSONObjectUtil.toObject(e.body, ZbsPrimaryStorageMdsBase.PingCmd.class) @@ -338,7 +391,12 @@ class ZbsPrimaryStorageCase extends SubCase { addonInfo = Q.New(ExternalPrimaryStorageVO.class).select(ExternalPrimaryStorageVO_.addonInfo).eq(ExternalPrimaryStorageVO_.uuid, ps.uuid).findValue() - assert addonInfo == "{\"clusterInfo\":{\"uuid\":\"123456789\",\"version\":\"1.6.1-for-test\"},\"mdsInfos\":[{\"username\":\"root\",\"password\":\"password\",\"port\":22,\"addr\":\"127.0.1.1\",\"externalAddr\":\"127.0.0.1\",\"status\":\"Disconnected\"},{\"username\":\"root\",\"password\":\"password\",\"port\":22,\"addr\":\"127.0.1.2\",\"externalAddr\":\"127.0.0.1\",\"status\":\"Connected\"},{\"username\":\"root\",\"password\":\"password\",\"port\":22,\"addr\":\"127.0.1.3\",\"externalAddr\":\"127.0.0.1\",\"status\":\"Connected\"}],\"logicalPoolInfos\":[{\"physicalPoolID\":1,\"redundanceAndPlaceMentPolicy\":{\"copysetNum\":300,\"replicaNum\":3,\"zoneNum\":3},\"logicalPoolID\":1,\"usedSize\":322961408,\"quota\":0,\"createTime\":1735875794,\"type\":0,\"rawWalUsedSize\":0,\"allocateStatus\":0,\"rawUsedSize\":968884224,\"physicalPoolName\":\"pool1\",\"capacity\":579933831168,\"logicalPoolName\":\"lpool1\",\"userPolicy\":\"eyJwb2xpY3kiIDogMX0=\",\"allocatedSize\":3221225472}]}" + assert addonInfo == "{\"clusterInfo\":{\"uuid\":\"123456789\",\"version\":\"1.6.1-for-test\"}," + + "\"mdsInfos\":[{\"username\":\"root\",\"password\":\"password\",\"port\":22,\"addr\":\"127.0.1.1\",\"externalAddr\":\"127.0.0.1\",\"status\":\"Disconnected\"}," + + "{\"username\":\"root\",\"password\":\"password\",\"port\":22,\"addr\":\"127.0.1.2\",\"externalAddr\":\"127.0.0.1\",\"status\":\"Connected\"}," + + "{\"username\":\"root\",\"password\":\"password\",\"port\":22,\"addr\":\"127.0.1.3\",\"externalAddr\":\"127.0.0.1\",\"status\":\"Connected\"}]," + + "\"logicalPoolInfos\":[{\"physicalPoolID\":1,\"redundanceAndPlaceMentPolicy\":{\"copysetNum\":300,\"replicaNum\":3,\"zoneNum\":3},\"logicalPoolID\":1,\"usedSize\":322961408,\"quota\":0,\"createTime\":1735875794,\"type\":0,\"rawWalUsedSize\":0,\"allocateStatus\":0,\"rawUsedSize\":968884224,\"physicalPoolName\":\"pool1\",\"capacity\":579933831168,\"logicalPoolName\":\"lpool1\",\"userPolicy\":\"eyJwb2xpY3kiIDogMX0=\",\"allocatedSize\":3221225472}," + + "{\"physicalPoolID\":2,\"redundanceAndPlaceMentPolicy\":{\"copysetNum\":300,\"replicaNum\":3,\"zoneNum\":3},\"logicalPoolID\":2,\"usedSize\":123456789,\"quota\":0,\"createTime\":1735875794,\"type\":0,\"rawWalUsedSize\":0,\"allocateStatus\":0,\"rawUsedSize\":123456789,\"physicalPoolName\":\"pool2\",\"capacity\":579933831168,\"logicalPoolName\":\"lpool2\",\"userPolicy\":\"eyJwb2xpY3kiIDogMX0=\",\"allocatedSize\":987654321}]}" assert Q.New(ExternalPrimaryStorageVO.class).select(ExternalPrimaryStorageVO_.status).eq(ExternalPrimaryStorageVO_.uuid, ps.uuid).findValue() == PrimaryStorageStatus.Connected @@ -363,7 +421,12 @@ class ZbsPrimaryStorageCase extends SubCase { addonInfo = Q.New(ExternalPrimaryStorageVO.class).select(ExternalPrimaryStorageVO_.addonInfo).eq(ExternalPrimaryStorageVO_.uuid, ps.uuid).findValue() - assert addonInfo == "{\"clusterInfo\":{\"uuid\":\"123456789\",\"version\":\"1.6.1-for-test\"},\"mdsInfos\":[{\"username\":\"root\",\"password\":\"password\",\"port\":22,\"addr\":\"127.0.1.1\",\"externalAddr\":\"127.0.0.1\",\"status\":\"Disconnected\"},{\"username\":\"root\",\"password\":\"password\",\"port\":22,\"addr\":\"127.0.1.2\",\"externalAddr\":\"127.0.0.1\",\"status\":\"Disconnected\"},{\"username\":\"root\",\"password\":\"password\",\"port\":22,\"addr\":\"127.0.1.3\",\"externalAddr\":\"127.0.0.1\",\"status\":\"Disconnected\"}],\"logicalPoolInfos\":[{\"physicalPoolID\":1,\"redundanceAndPlaceMentPolicy\":{\"copysetNum\":300,\"replicaNum\":3,\"zoneNum\":3},\"logicalPoolID\":1,\"usedSize\":322961408,\"quota\":0,\"createTime\":1735875794,\"type\":0,\"rawWalUsedSize\":0,\"allocateStatus\":0,\"rawUsedSize\":968884224,\"physicalPoolName\":\"pool1\",\"capacity\":579933831168,\"logicalPoolName\":\"lpool1\",\"userPolicy\":\"eyJwb2xpY3kiIDogMX0=\",\"allocatedSize\":3221225472}]}" + assert addonInfo == "{\"clusterInfo\":{\"uuid\":\"123456789\",\"version\":\"1.6.1-for-test\"}," + + "\"mdsInfos\":[{\"username\":\"root\",\"password\":\"password\",\"port\":22,\"addr\":\"127.0.1.1\",\"externalAddr\":\"127.0.0.1\",\"status\":\"Disconnected\"}," + + "{\"username\":\"root\",\"password\":\"password\",\"port\":22,\"addr\":\"127.0.1.2\",\"externalAddr\":\"127.0.0.1\",\"status\":\"Disconnected\"}," + + "{\"username\":\"root\",\"password\":\"password\",\"port\":22,\"addr\":\"127.0.1.3\",\"externalAddr\":\"127.0.0.1\",\"status\":\"Disconnected\"}]," + + "\"logicalPoolInfos\":[{\"physicalPoolID\":1,\"redundanceAndPlaceMentPolicy\":{\"copysetNum\":300,\"replicaNum\":3,\"zoneNum\":3},\"logicalPoolID\":1,\"usedSize\":322961408,\"quota\":0,\"createTime\":1735875794,\"type\":0,\"rawWalUsedSize\":0,\"allocateStatus\":0,\"rawUsedSize\":968884224,\"physicalPoolName\":\"pool1\",\"capacity\":579933831168,\"logicalPoolName\":\"lpool1\",\"userPolicy\":\"eyJwb2xpY3kiIDogMX0=\",\"allocatedSize\":3221225472}," + + "{\"physicalPoolID\":2,\"redundanceAndPlaceMentPolicy\":{\"copysetNum\":300,\"replicaNum\":3,\"zoneNum\":3},\"logicalPoolID\":2,\"usedSize\":123456789,\"quota\":0,\"createTime\":1735875794,\"type\":0,\"rawWalUsedSize\":0,\"allocateStatus\":0,\"rawUsedSize\":123456789,\"physicalPoolName\":\"pool2\",\"capacity\":579933831168,\"logicalPoolName\":\"lpool2\",\"userPolicy\":\"eyJwb2xpY3kiIDogMX0=\",\"allocatedSize\":987654321}]}" assert Q.New(ExternalPrimaryStorageVO.class).select(ExternalPrimaryStorageVO_.status).eq(ExternalPrimaryStorageVO_.uuid, ps.uuid).findValue() == PrimaryStorageStatus.Disconnected @@ -377,13 +440,26 @@ class ZbsPrimaryStorageCase extends SubCase { } void testDataVolumeLifecycle() { + long usedCapPoolBefore = getUsedCapacity("lpool2") + long usedCapPsBefore = getUsedCapacity() vol = createDataVolume { name = "test" diskOfferingUuid = diskOffering.uuid primaryStorageUuid = ps.uuid + systemTags = [ExternalPrimaryStorageSystemTags.REQUIRED_INSTALL_URL.instantiateTag( + Collections.singletonMap(ExternalPrimaryStorageSystemTags.REQUIRED_INSTALL_URL_TOKEN, "zbs://lpool2"))] + } as VolumeInventory + assert getUsedCapacity("lpool2") == usedCapPoolBefore + vol.size + assert getUsedCapacity() == usedCapPsBefore + vol.size + assert vol.installPath.startsWith("zbs://lpool2") deleteVolume(vol.uuid) + + retryInSecs { + assert getUsedCapacity("lpool2") == usedCapPoolBefore + assert getUsedCapacity() == usedCapPsBefore + } } void testNegativeScenario() { @@ -512,4 +588,21 @@ class ZbsPrimaryStorageCase extends SubCase { uuid = volUuid } } + + long getUsedCapacity(String poolName) { + ExternalPrimaryStorageSpaceVO spaceVO = Q.New(ExternalPrimaryStorageSpaceVO.class) + .eq(ExternalPrimaryStorageSpaceVO_.primaryStorageUuid, ps.uuid) + .eq(ExternalPrimaryStorageSpaceVO_.locationUrl, "zbs://" + poolName) + .find() + + return spaceVO.totalCapacity - spaceVO.availableCapacity + } + + long getUsedCapacity() { + PrimaryStorageCapacityVO cap = Q.New(PrimaryStorageCapacityVO.class) + .eq(PrimaryStorageCapacityVO_.uuid, ps.uuid) + .find() + + return cap.totalCapacity - cap.availableCapacity + } } diff --git a/testlib/src/main/java/org/zstack/testlib/ApiHelper.groovy b/testlib/src/main/java/org/zstack/testlib/ApiHelper.groovy index 34cf02a9ff..745e26949e 100644 --- a/testlib/src/main/java/org/zstack/testlib/ApiHelper.groovy +++ b/testlib/src/main/java/org/zstack/testlib/ApiHelper.groovy @@ -1853,6 +1853,33 @@ abstract class ApiHelper { } + def addL3NetworkToGroup(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.AddL3NetworkToGroupAction.class) Closure c) { + def a = new org.zstack.sdk.AddL3NetworkToGroupAction() + 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 addLdapServer(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.AddLdapServerAction.class) Closure c) { def a = new org.zstack.sdk.AddLdapServerAction() a.sessionId = Test.currentEnvSpec?.session?.uuid @@ -3986,6 +4013,33 @@ abstract class ApiHelper { } + def attachNfvInstToGroup(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.AttachNfvInstToGroupAction.class) Closure c) { + def a = new org.zstack.sdk.AttachNfvInstToGroupAction() + 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 attachNicToBonding(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.AttachNicToBondingAction.class) Closure c) { def a = new org.zstack.sdk.AttachNicToBondingAction() a.sessionId = Test.currentEnvSpec?.session?.uuid @@ -5957,6 +6011,33 @@ abstract class ApiHelper { } + def changeNfvInstGroupOperationMode(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.ChangeNfvInstGroupOperationModeAction.class) Closure c) { + def a = new org.zstack.sdk.ChangeNfvInstGroupOperationModeAction() + 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 changePortForwardingRuleState(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.ChangePortForwardingRuleStateAction.class) Closure c) { def a = new org.zstack.sdk.ChangePortForwardingRuleStateAction() a.sessionId = Test.currentEnvSpec?.session?.uuid @@ -10331,6 +10412,87 @@ abstract class ApiHelper { } + def createNfvInst(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.CreateNfvInstAction.class) Closure c) { + def a = new org.zstack.sdk.CreateNfvInstAction() + 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 createNfvInstGroup(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.CreateNfvInstGroupAction.class) Closure c) { + def a = new org.zstack.sdk.CreateNfvInstGroupAction() + 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 createNfvInstOffering(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.CreateNfvInstOfferingAction.class) Closure c) { + def a = new org.zstack.sdk.CreateNfvInstOfferingAction() + 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 createOAuthClient(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.CreateOAuthClientAction.class) Closure c) { def a = new org.zstack.sdk.CreateOAuthClientAction() a.sessionId = Test.currentEnvSpec?.session?.uuid @@ -15677,6 +15839,33 @@ abstract class ApiHelper { } + def deleteNfvInstGroup(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.DeleteNfvInstGroupAction.class) Closure c) { + def a = new org.zstack.sdk.DeleteNfvInstGroupAction() + 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 deleteNicQos(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.DeleteNicQosAction.class) Closure c) { def a = new org.zstack.sdk.DeleteNicQosAction() a.sessionId = Test.currentEnvSpec?.session?.uuid @@ -18647,6 +18836,33 @@ abstract class ApiHelper { } + def detachNfvInstFromGroup(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.DetachNfvInstFromGroupAction.class) Closure c) { + def a = new org.zstack.sdk.DetachNfvInstFromGroupAction() + 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 detachNicFromBonding(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.DetachNicFromBondingAction.class) Closure c) { def a = new org.zstack.sdk.DetachNicFromBondingAction() a.sessionId = Test.currentEnvSpec?.session?.uuid @@ -19997,6 +20213,33 @@ abstract class ApiHelper { } + def generateHygonMdevDevices(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.GenerateHygonMdevDevicesAction.class) Closure c) { + def a = new org.zstack.sdk.GenerateHygonMdevDevicesAction() + 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 generateMdevDevices(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.GenerateMdevDevicesAction.class) Closure c) { def a = new org.zstack.sdk.GenerateMdevDevicesAction() a.sessionId = Test.currentEnvSpec?.session?.uuid @@ -27827,8 +28070,8 @@ abstract class ApiHelper { } - def provisionSlbInstance(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.ProvisionSlbInstanceAction.class) Closure c) { - def a = new org.zstack.sdk.ProvisionSlbInstanceAction() + def provisionNfvInstConfig(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.ProvisionNfvInstConfigAction.class) Closure c) { + def a = new org.zstack.sdk.ProvisionNfvInstConfigAction() a.sessionId = Test.currentEnvSpec?.session?.uuid c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a @@ -27854,8 +28097,8 @@ abstract class ApiHelper { } - def provisionVirtualRouterConfig(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.ProvisionVirtualRouterConfigAction.class) Closure c) { - def a = new org.zstack.sdk.ProvisionVirtualRouterConfigAction() + def provisionNfvInstGroup(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.ProvisionNfvInstGroupAction.class) Closure c) { + def a = new org.zstack.sdk.ProvisionNfvInstGroupAction() a.sessionId = Test.currentEnvSpec?.session?.uuid c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a @@ -27881,8 +28124,8 @@ abstract class ApiHelper { } - def publishApp(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.PublishAppAction.class) Closure c) { - def a = new org.zstack.sdk.PublishAppAction() + def provisionSlbInstance(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.ProvisionSlbInstanceAction.class) Closure c) { + def a = new org.zstack.sdk.ProvisionSlbInstanceAction() a.sessionId = Test.currentEnvSpec?.session?.uuid c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a @@ -27908,8 +28151,8 @@ abstract class ApiHelper { } - def pullSdnControllerTenant(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.PullSdnControllerTenantAction.class) Closure c) { - def a = new org.zstack.sdk.PullSdnControllerTenantAction() + def provisionVirtualRouterConfig(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.ProvisionVirtualRouterConfigAction.class) Closure c) { + def a = new org.zstack.sdk.ProvisionVirtualRouterConfigAction() a.sessionId = Test.currentEnvSpec?.session?.uuid c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a @@ -27935,8 +28178,8 @@ abstract class ApiHelper { } - def pushLicenseAddOnsUsage(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.PushLicenseAddOnsUsageAction.class) Closure c) { - def a = new org.zstack.sdk.PushLicenseAddOnsUsageAction() + def publishApp(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.PublishAppAction.class) Closure c) { + def a = new org.zstack.sdk.PublishAppAction() a.sessionId = Test.currentEnvSpec?.session?.uuid c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a @@ -27962,15 +28205,13 @@ abstract class ApiHelper { } - def queryAccessControlList(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.QueryAccessControlListAction.class) Closure c) { - def a = new org.zstack.sdk.QueryAccessControlListAction() + def pullSdnControllerTenant(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.PullSdnControllerTenantAction.class) Closure c) { + def a = new org.zstack.sdk.PullSdnControllerTenantAction() a.sessionId = Test.currentEnvSpec?.session?.uuid c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - a.conditions = a.conditions.collect { it.toString() } - if (System.getProperty("apipath") != null) { if (a.apiId == null) { @@ -27991,15 +28232,13 @@ abstract class ApiHelper { } - def queryAccessControlRule(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.QueryAccessControlRuleAction.class) Closure c) { - def a = new org.zstack.sdk.QueryAccessControlRuleAction() + def pushLicenseAddOnsUsage(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.PushLicenseAddOnsUsageAction.class) Closure c) { + def a = new org.zstack.sdk.PushLicenseAddOnsUsageAction() a.sessionId = Test.currentEnvSpec?.session?.uuid c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - a.conditions = a.conditions.collect { it.toString() } - if (System.getProperty("apipath") != null) { if (a.apiId == null) { @@ -28020,8 +28259,66 @@ abstract class ApiHelper { } - def queryAccessKey(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.QueryAccessKeyAction.class) Closure c) { - def a = new org.zstack.sdk.QueryAccessKeyAction() + def queryAccessControlList(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.QueryAccessControlListAction.class) Closure c) { + def a = new org.zstack.sdk.QueryAccessControlListAction() + a.sessionId = Test.currentEnvSpec?.session?.uuid + c.resolveStrategy = Closure.OWNER_FIRST + c.delegate = a + c() + + a.conditions = a.conditions.collect { it.toString() } + + + if (System.getProperty("apipath") != null) { + if (a.apiId == null) { + a.apiId = Platform.uuid + } + + def tracker = new ApiPathTracker(a.apiId) + def out = errorOut(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 queryAccessControlRule(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.QueryAccessControlRuleAction.class) Closure c) { + def a = new org.zstack.sdk.QueryAccessControlRuleAction() + a.sessionId = Test.currentEnvSpec?.session?.uuid + c.resolveStrategy = Closure.OWNER_FIRST + c.delegate = a + c() + + a.conditions = a.conditions.collect { it.toString() } + + + if (System.getProperty("apipath") != null) { + if (a.apiId == null) { + a.apiId = Platform.uuid + } + + def tracker = new ApiPathTracker(a.apiId) + def out = errorOut(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 queryAccessKey(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.QueryAccessKeyAction.class) Closure c) { + def a = new org.zstack.sdk.QueryAccessKeyAction() a.sessionId = Test.currentEnvSpec?.session?.uuid c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a @@ -31239,6 +31536,35 @@ abstract class ApiHelper { } + def queryHygonDevice(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.QueryHygonDeviceAction.class) Closure c) { + def a = new org.zstack.sdk.QueryHygonDeviceAction() + a.sessionId = Test.currentEnvSpec?.session?.uuid + c.resolveStrategy = Closure.OWNER_FIRST + c.delegate = a + c() + + a.conditions = a.conditions.collect { it.toString() } + + + if (System.getProperty("apipath") != null) { + if (a.apiId == null) { + a.apiId = Platform.uuid + } + + def tracker = new ApiPathTracker(a.apiId) + def out = errorOut(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 queryIAM2LdapBinding(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.QueryIAM2LdapBindingAction.class) Closure c) { def a = new org.zstack.sdk.QueryIAM2LdapBindingAction() a.sessionId = Test.currentEnvSpec?.session?.uuid @@ -32863,6 +33189,93 @@ abstract class ApiHelper { } + def queryNfvInst(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.QueryNfvInstAction.class) Closure c) { + def a = new org.zstack.sdk.QueryNfvInstAction() + a.sessionId = Test.currentEnvSpec?.session?.uuid + c.resolveStrategy = Closure.OWNER_FIRST + c.delegate = a + c() + + a.conditions = a.conditions.collect { it.toString() } + + + if (System.getProperty("apipath") != null) { + if (a.apiId == null) { + a.apiId = Platform.uuid + } + + def tracker = new ApiPathTracker(a.apiId) + def out = errorOut(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 queryNfvInstGroup(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.QueryNfvInstGroupAction.class) Closure c) { + def a = new org.zstack.sdk.QueryNfvInstGroupAction() + a.sessionId = Test.currentEnvSpec?.session?.uuid + c.resolveStrategy = Closure.OWNER_FIRST + c.delegate = a + c() + + a.conditions = a.conditions.collect { it.toString() } + + + if (System.getProperty("apipath") != null) { + if (a.apiId == null) { + a.apiId = Platform.uuid + } + + def tracker = new ApiPathTracker(a.apiId) + def out = errorOut(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 queryNfvInstOffering(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.QueryNfvInstOfferingAction.class) Closure c) { + def a = new org.zstack.sdk.QueryNfvInstOfferingAction() + a.sessionId = Test.currentEnvSpec?.session?.uuid + c.resolveStrategy = Closure.OWNER_FIRST + c.delegate = a + c() + + a.conditions = a.conditions.collect { it.toString() } + + + if (System.getProperty("apipath") != null) { + if (a.apiId == null) { + a.apiId = Platform.uuid + } + + def tracker = new ApiPathTracker(a.apiId) + def out = errorOut(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 queryNvmeLun(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.QueryNvmeLunAction.class) Closure c) { def a = new org.zstack.sdk.QueryNvmeLunAction() a.sessionId = Test.currentEnvSpec?.session?.uuid @@ -32979,6 +33392,64 @@ abstract class ApiHelper { } + def queryOvnController(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.QueryOvnControllerAction.class) Closure c) { + def a = new org.zstack.sdk.QueryOvnControllerAction() + a.sessionId = Test.currentEnvSpec?.session?.uuid + c.resolveStrategy = Closure.OWNER_FIRST + c.delegate = a + c() + + a.conditions = a.conditions.collect { it.toString() } + + + if (System.getProperty("apipath") != null) { + if (a.apiId == null) { + a.apiId = Platform.uuid + } + + def tracker = new ApiPathTracker(a.apiId) + def out = errorOut(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 queryOvnControllerVmInstance(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.QueryOvnControllerVmInstanceAction.class) Closure c) { + def a = new org.zstack.sdk.QueryOvnControllerVmInstanceAction() + a.sessionId = Test.currentEnvSpec?.session?.uuid + c.resolveStrategy = Closure.OWNER_FIRST + c.delegate = a + c() + + a.conditions = a.conditions.collect { it.toString() } + + + if (System.getProperty("apipath") != null) { + if (a.apiId == null) { + a.apiId = Platform.uuid + } + + def tracker = new ApiPathTracker(a.apiId) + def out = errorOut(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 queryPciDevice(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.QueryPciDeviceAction.class) Closure c) { def a = new org.zstack.sdk.QueryPciDeviceAction() a.sessionId = Test.currentEnvSpec?.session?.uuid @@ -36636,6 +37107,33 @@ abstract class ApiHelper { } + def reconnectNfvInst(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.ReconnectNfvInstAction.class) Closure c) { + def a = new org.zstack.sdk.ReconnectNfvInstAction() + 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 reconnectPrimaryStorage(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.ReconnectPrimaryStorageAction.class) Closure c) { def a = new org.zstack.sdk.ReconnectPrimaryStorageAction() a.sessionId = Test.currentEnvSpec?.session?.uuid @@ -39471,6 +39969,33 @@ abstract class ApiHelper { } + def setVmInstanceHygonMdev(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.SetVmInstanceHygonMdevAction.class) Closure c) { + def a = new org.zstack.sdk.SetVmInstanceHygonMdevAction() + 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 setVmMonitorNumber(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.SetVmMonitorNumberAction.class) Closure c) { def a = new org.zstack.sdk.SetVmMonitorNumberAction() a.sessionId = Test.currentEnvSpec?.session?.uuid @@ -41010,6 +41535,33 @@ abstract class ApiHelper { } + def syncNfvInstGroup(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.SyncNfvInstGroupAction.class) Closure c) { + def a = new org.zstack.sdk.SyncNfvInstGroupAction() + 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 syncPrimaryStorageCapacity(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.SyncPrimaryStorageCapacityAction.class) Closure c) { def a = new org.zstack.sdk.SyncPrimaryStorageCapacityAction() a.sessionId = Test.currentEnvSpec?.session?.uuid @@ -41442,6 +41994,33 @@ abstract class ApiHelper { } + def ungenerateHygonMdevDevices(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.UngenerateHygonMdevDevicesAction.class) Closure c) { + def a = new org.zstack.sdk.UngenerateHygonMdevDevicesAction() + 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 ungenerateMdevDevices(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.UngenerateMdevDevicesAction.class) Closure c) { def a = new org.zstack.sdk.UngenerateMdevDevicesAction() a.sessionId = Test.currentEnvSpec?.session?.uuid @@ -43035,6 +43614,33 @@ abstract class ApiHelper { } + def updateConsolePassword(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.UpdateConsolePasswordAction.class) Closure c) { + def a = new org.zstack.sdk.UpdateConsolePasswordAction() + 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 updateConsoleProxyAgent(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.UpdateConsoleProxyAgentAction.class) Closure c) { def a = new org.zstack.sdk.UpdateConsoleProxyAgentAction() a.sessionId = Test.currentEnvSpec?.session?.uuid @@ -44952,6 +45558,60 @@ abstract class ApiHelper { } + def updateNfvInstGroup(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.UpdateNfvInstGroupAction.class) Closure c) { + def a = new org.zstack.sdk.UpdateNfvInstGroupAction() + 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 updateNfvInstProvisionConfig(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.UpdateNfvInstProvisionConfigAction.class) Closure c) { + def a = new org.zstack.sdk.UpdateNfvInstProvisionConfigAction() + 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 updateOAuthClient(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.UpdateOAuthClientAction.class) Closure c) { def a = new org.zstack.sdk.UpdateOAuthClientAction() a.sessionId = Test.currentEnvSpec?.session?.uuid diff --git a/testlib/src/main/java/org/zstack/testlib/ExternalPrimaryStorageSpec.groovy b/testlib/src/main/java/org/zstack/testlib/ExternalPrimaryStorageSpec.groovy index 356a9641f1..ca2b74ea49 100644 --- a/testlib/src/main/java/org/zstack/testlib/ExternalPrimaryStorageSpec.groovy +++ b/testlib/src/main/java/org/zstack/testlib/ExternalPrimaryStorageSpec.groovy @@ -1,9 +1,8 @@ package org.zstack.testlib import org.springframework.http.HttpEntity -import org.zstack.cbd.LogicalPoolInfo +import org.zstack.storage.zbs.LogicalPoolInfo import org.zstack.cbd.kvm.KvmCbdCommands -import org.zstack.kvm.KVMAgentCommands import org.zstack.sdk.PrimaryStorageInventory import org.zstack.storage.zbs.ZbsPrimaryStorageMdsBase import org.zstack.storage.zbs.ZbsStorageController @@ -71,6 +70,13 @@ class ExternalPrimaryStorageSpec extends PrimaryStorageSpec { return rsp } + simulator(ZbsStorageController.UPDATE_HOST_DEPENDENCY_PATH) { HttpEntity e, EnvSpec spec -> + def rsp = new ZbsStorageController.UpdateHostDependencyRsp() + rsp.success = true + + return rsp + } + simulator(ZbsStorageController.GET_FACTS_PATH) { HttpEntity e, EnvSpec spec -> ZbsStorageController.GetFactsCmd cmd = JSONObjectUtil.toObject(e.body, ZbsStorageController.GetFactsCmd.class) ExternalPrimaryStorageSpec zspec = spec.specByUuid(cmd.uuid) @@ -117,13 +123,31 @@ class ExternalPrimaryStorageSpec extends PrimaryStorageSpec { logicalPoolInfo.setRawUsedSize(968884224); logicalPoolInfo.setPhysicalPoolName("pool1"); logicalPoolInfo.setCapacity(579933831168); - logicalPoolInfo.setLogicalPoolName(cmd.logicalPool); + logicalPoolInfo.setLogicalPoolName(cmd.logicalPoolNames[0]); logicalPoolInfo.setUserPolicy("eyJwb2xpY3kiIDogMX0="); logicalPoolInfo.setAllocatedSize(3221225472); List logicalPoolInfos = new ArrayList<>() logicalPoolInfos.add(logicalPoolInfo) + logicalPoolInfos.add(new LogicalPoolInfo( + physicalPoolID: 2, + logicalPoolID: 2, + logicalPoolName: "lpool2", + physicalPoolName: "pool2", + capacity: 579933831168, + usedSize: 123456789, + allocatedSize: 987654321, + quota: 0, + createTime: 1735875794, + type: 0, + rawWalUsedSize: 0, + allocateStatus: 0, + rawUsedSize: 123456789, + redundanceAndPlaceMentPolicy: redundanceAndPlaceMentPolicy, + userPolicy: "eyJwb2xpY3kiIDogMX0=" + )) + def rsp = new ZbsStorageController.GetCapacityRsp() rsp.setLogicalPoolInfos(logicalPoolInfos) @@ -136,7 +160,7 @@ class ExternalPrimaryStorageSpec extends PrimaryStorageSpec { assert zspec != null: "cannot found zbs primary storage[uuid:${cmd.uuid}], check your environment()." def rsp = new ZbsStorageController.CreateVolumeRsp() - rsp.setSize(actualSize) + rsp.setSize(cmd.getSizeInBytes()) rsp.setActualSize(actualSize) rsp.setInstallPath(String.format("cbd:pool1/%s/%s", cmd.logicalPool, cmd.volume)) @@ -203,7 +227,12 @@ class ExternalPrimaryStorageSpec extends PrimaryStorageSpec { assert zspec != null: "cannot found zbs primary storage[uuid:${cmd.uuid}], check your environment()." def rsp = new ZbsStorageController.CopyRsp() - rsp.setInstallPath(cmd.path.replaceAll("([^/]+)\$", cmd.dstVolume)) + if (cmd.dstPool != null) { + // lpool1 physical pool is pool1 + rsp.installPath = "cbd:${cmd.dstPool.substring(1)}/${cmd.dstPool}/${cmd.dstVolume}" + } else { + rsp.setInstallPath(cmd.path.replaceAll("([^/]+)\$", cmd.dstVolume)) + } rsp.setSize(actualSize) return rsp diff --git a/testlib/src/main/java/org/zstack/testlib/KVMSimulator.groovy b/testlib/src/main/java/org/zstack/testlib/KVMSimulator.groovy index 6e77c2dfed..81bd88ac6b 100755 --- a/testlib/src/main/java/org/zstack/testlib/KVMSimulator.groovy +++ b/testlib/src/main/java/org/zstack/testlib/KVMSimulator.groovy @@ -463,6 +463,22 @@ class KVMSimulator implements Simulator { return new KVMAgentCommands.AgentResponse() } + spec.simulator(KVMConstant.KVM_OVS_CHECK_LOCAL_PORT_PATH) { + return new KVMAgentCommands.OvsCheckPortRsp() + } + + spec.simulator(KVMConstant.KVM_OVS_SYNC_PORT_PATH) { + return new KVMAgentCommands.OvsSyncPortRsp() + } + + spec.simulator(KVMConstant.KVM_OVS_SET_REQUESTED_CHASSIS_PATH) { + return new KVMAgentCommands.OvsSetRequestedChassisRsp() + } + + spec.simulator(KVMConstant.KVM_OVS_SET_DB_CONNECTION_PATH) { + return new KVMAgentCommands.OvsSetDbConnectionRsp() + } + spec.simulator(KVMConstant.KVM_SYNC_VM_DEVICEINFO_PATH) { HttpEntity e -> SyncVmDeviceInfoCmd cmd = JSONObjectUtil.toObject(e.body, SyncVmDeviceInfoCmd.class) def rsp = new SyncVmDeviceInfoResponse() diff --git a/testlib/src/main/java/org/zstack/testlib/VipSpec.groovy b/testlib/src/main/java/org/zstack/testlib/VipSpec.groovy new file mode 100644 index 0000000000..8490372cdc --- /dev/null +++ b/testlib/src/main/java/org/zstack/testlib/VipSpec.groovy @@ -0,0 +1,57 @@ +package org.zstack.testlib + +import org.zstack.sdk.VipInventory +import org.zstack.sdk.VmNicInventory + +/** + * Created by shixin.ruan on 2025/12/10. + */ +class VipSpec extends Spec implements HasSession { + @SpecParam(required = true) + String name + @SpecParam(required = true) + String l3NetworkUuid + @SpecParam + String description + @SpecParam + String requiredIp + + VipInventory inventory + + VipSpec(EnvSpec envSpec) { + super(envSpec) + } + + SpecID create(String uuid, String sessionId) { + inventory = createVip { + delegate.resourceUuid = uuid + delegate.name = name + delegate.l3NetworkUuid = l3NetworkUuid + delegate.description = description + delegate.requiredIp = requiredIp + delegate.userTags = userTags + delegate.systemTags = systemTags + delegate.sessionId = sessionId + } + + postCreate { + inventory = queryVip { + conditions=["uuid=${inventory.uuid}".toString()] + }[0] + } + + return id(name, inventory.uuid) + } + + @Override + void delete(String sessionId) { + if (inventory != null) { + deleteVip { + delegate.uuid = inventory.uuid + delegate.sessionId = sessionId + } + + inventory = null + } + } +} diff --git a/testlib/src/main/java/org/zstack/testlib/ZoneSpec.groovy b/testlib/src/main/java/org/zstack/testlib/ZoneSpec.groovy index 9d78316d8d..0404637ddb 100755 --- a/testlib/src/main/java/org/zstack/testlib/ZoneSpec.groovy +++ b/testlib/src/main/java/org/zstack/testlib/ZoneSpec.groovy @@ -139,6 +139,15 @@ class ZoneSpec extends Spec { return spec } + VipSpec vip(@DelegatesTo(strategy = Closure.DELEGATE_FIRST, value = VipSpec.class) Closure c) { + def spec = new VipSpec(envSpec) + c.delegate = spec + c.resolveStrategy = Closure.DELEGATE_FIRST + c() + addChild(spec) + return spec + } + EipSpec eip(@DelegatesTo(strategy = Closure.DELEGATE_FIRST, value = EipSpec.class) Closure c) { def spec = new EipSpec(envSpec) c.delegate = spec