From aa3fc922da3ccc20d3fac0e5d6fba2eda7092a33 Mon Sep 17 00:00:00 2001 From: "haoyu.ding" Date: Wed, 4 Feb 2026 11:24:42 +0800 Subject: [PATCH] [utils]: Network group high availability strategy DBImpact Resolves: ZSTAC-81413 Change-Id: I6a7574656467636e686377756f716d67707a7063 --- conf/db/upgrade/V5.5.12__schema.sql | 41 ++++++ .../java/org/zstack/kvm/KVMAgentCommands.java | 45 ++++++ .../main/java/org/zstack/kvm/KVMConstant.java | 3 + sdk/src/main/java/SourceClassMap.java | 2 + .../sdk/ChangeHaNetworkGroupStateAction.java | 104 +++++++++++++ .../sdk/ChangeHaNetworkGroupStateResult.java | 14 ++ .../sdk/CreateHaNetworkGroupAction.java | 122 ++++++++++++++++ .../sdk/CreateHaNetworkGroupResult.java | 14 ++ .../sdk/DeleteHaNetworkGroupAction.java | 104 +++++++++++++ .../sdk/DeleteHaNetworkGroupResult.java | 7 + .../zstack/sdk/HaNetworkGroupInventory.java | 95 ++++++++++++ .../zstack/sdk/QueryHaNetworkGroupAction.java | 75 ++++++++++ .../zstack/sdk/QueryHaNetworkGroupResult.java | 22 +++ .../sdk/UpdateHaNetworkGroupAction.java | 113 +++++++++++++++ .../sdk/UpdateHaNetworkGroupResult.java | 14 ++ .../simulator/kvm/KVMSimulatorConfig.java | 3 + .../simulator/kvm/KVMSimulatorController.java | 32 ++++ .../java/org/zstack/testlib/ApiHelper.groovy | 137 ++++++++++++++++++ .../org/zstack/testlib/KVMSimulator.groovy | 12 ++ .../CloudOperationsErrorCode.java | 32 ++++ 20 files changed, 991 insertions(+) create mode 100644 conf/db/upgrade/V5.5.12__schema.sql create mode 100644 sdk/src/main/java/org/zstack/sdk/ChangeHaNetworkGroupStateAction.java create mode 100644 sdk/src/main/java/org/zstack/sdk/ChangeHaNetworkGroupStateResult.java create mode 100644 sdk/src/main/java/org/zstack/sdk/CreateHaNetworkGroupAction.java create mode 100644 sdk/src/main/java/org/zstack/sdk/CreateHaNetworkGroupResult.java create mode 100644 sdk/src/main/java/org/zstack/sdk/DeleteHaNetworkGroupAction.java create mode 100644 sdk/src/main/java/org/zstack/sdk/DeleteHaNetworkGroupResult.java create mode 100644 sdk/src/main/java/org/zstack/sdk/HaNetworkGroupInventory.java create mode 100644 sdk/src/main/java/org/zstack/sdk/QueryHaNetworkGroupAction.java create mode 100644 sdk/src/main/java/org/zstack/sdk/QueryHaNetworkGroupResult.java create mode 100644 sdk/src/main/java/org/zstack/sdk/UpdateHaNetworkGroupAction.java create mode 100644 sdk/src/main/java/org/zstack/sdk/UpdateHaNetworkGroupResult.java diff --git a/conf/db/upgrade/V5.5.12__schema.sql b/conf/db/upgrade/V5.5.12__schema.sql new file mode 100644 index 00000000000..3ce1c8ece0e --- /dev/null +++ b/conf/db/upgrade/V5.5.12__schema.sql @@ -0,0 +1,41 @@ +CREATE TABLE IF NOT EXISTS `zstack`.`HaNetworkGroupVO` ( + `uuid` VARCHAR(32) NOT NULL UNIQUE COMMENT 'uuid', + `name` VARCHAR(255) NOT NULL, + `description` VARCHAR(2048) DEFAULT NULL, + `clusterUuid` VARCHAR(32) NOT NULL, + `type` VARCHAR(128) NOT NULL, + `minAvailableCount` INT(10) NOT NULL DEFAULT 1, + `configVersion` BIGINT UNSIGNED NOT NULL DEFAULT 0, + `state` VARCHAR(32) NOT NULL DEFAULT 'Enabled', + `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`), + CONSTRAINT `fkHaNetworkGroupVOClusterEO` FOREIGN KEY (`clusterUuid`) REFERENCES `zstack`.`ClusterEO` (`uuid`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE IF NOT EXISTS `zstack`.`HaNetworkGroupL3NetworkRefVO` ( + `uuid` VARCHAR(32) NOT NULL UNIQUE COMMENT 'uuid', + `haNetworkGroupUuid` VARCHAR(32) NOT NULL, + `l3NetworkUuid` VARCHAR(32) NOT NULL, + `lastOpDate` TIMESTAMP NOT NULL DEFAULT '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 `idxHaNetworkGroupL3NetworkRefVOhaNetworkGroupUuid` (`haNetworkGroupUuid`), + INDEX `idxHaNetworkGroupL3NetworkRefVOl3NetworkUuid` (`l3NetworkUuid`), + CONSTRAINT `fkHaNetworkGroupL3NetworkRefVOHaNetworkGroupVO` FOREIGN KEY (`haNetworkGroupUuid`) REFERENCES `zstack`.`HaNetworkGroupVO` (`uuid`) ON DELETE CASCADE, + CONSTRAINT `fkHaNetworkGroupL3NetworkRefVOL3NetworkEO` FOREIGN KEY (`l3NetworkUuid`) REFERENCES `zstack`.`L3NetworkEO` (`uuid`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +CREATE TABLE IF NOT EXISTS `zstack`.`HostHaNetworkGroupStatusVO` ( + `uuid` VARCHAR(32) NOT NULL UNIQUE COMMENT 'uuid', + `hostUuid` VARCHAR(32) NOT NULL, + `networkGroupUuid` VARCHAR(32) NOT NULL, + `status` VARCHAR(32) NOT NULL DEFAULT 'Unknown', + `lastOpDate` TIMESTAMP NOT NULL DEFAULT '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 `idxHostHaNetworkGroupStatusVOhostUuid` (`hostUuid`), + INDEX `idxHostHaNetworkGroupStatusVOnetworkGroupUuid` (`networkGroupUuid`), + CONSTRAINT `fkHostHaNetworkGroupStatusVOHostEO` FOREIGN KEY (`hostUuid`) REFERENCES `zstack`.`HostEO` (`uuid`) ON DELETE CASCADE, + CONSTRAINT `fkHostHaNetworkGroupStatusVOHaNetworkGroupVO` FOREIGN KEY (`networkGroupUuid`) REFERENCES `zstack`.`HaNetworkGroupVO` (`uuid`) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8; 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 a8a1378288b..66bc586997e 100755 --- a/plugin/kvm/src/main/java/org/zstack/kvm/KVMAgentCommands.java +++ b/plugin/kvm/src/main/java/org/zstack/kvm/KVMAgentCommands.java @@ -1014,6 +1014,41 @@ public static class SetVmConsolePasswordLiveCmd extends AgentCommand implements public void setPassword(String password) { this.password = password; } } + public static class UpdateVmEnableHaLiveCmd extends AgentCommand implements Serializable { + private String vmUuid; + @GrayVersion(value = "5.5.12") + private Boolean enableHa; + + public String getVmUuid() { + return vmUuid; + } + + public void setVmUuid(String vmUuid) { + this.vmUuid = vmUuid; + } + + public Boolean getEnableHa() { + return enableHa; + } + + public void setEnableHa(Boolean enableHa) { + this.enableHa = enableHa; + } + } + + public static class ReconcileVmEnableHaOnHostCmd extends AgentCommand implements Serializable { + @GrayVersion(value = "5.5.12") + private List neverStopVmUuids; + + public List getNeverStopVmUuids() { + return neverStopVmUuids; + } + + public void setNeverStopVmUuids(List neverStopVmUuids) { + this.neverStopVmUuids = neverStopVmUuids; + } + } + public static class UpdateL2NetworkCmd extends AgentCommand { private String physicalInterfaceName; private String bridgeName; @@ -2236,6 +2271,8 @@ public static class StartVmCmd extends vdiCmd implements VmAddOnsCmd { private String nestedVirtualization; @GrayVersion(value = "5.0.0") private String hostManagementIp; + @GrayVersion(value = "5.5.12") + private Boolean enableHa; @GrayVersion(value = "5.0.0") private String clock; @GrayVersion(value = "5.0.0") @@ -2714,6 +2751,14 @@ public void setHostManagementIp(String hostManagementIp) { this.hostManagementIp = hostManagementIp; } + public Boolean getEnableHa() { + return enableHa; + } + + public void setEnableHa(Boolean enableHa) { + this.enableHa = enableHa; + } + public VolumeTO getRootVolume() { return rootVolume; } 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 1b2df9f8f2a..6b6901de4d1 100755 --- a/plugin/kvm/src/main/java/org/zstack/kvm/KVMConstant.java +++ b/plugin/kvm/src/main/java/org/zstack/kvm/KVMConstant.java @@ -127,6 +127,9 @@ public interface KVMConstant { String KVM_BLOCK_PULL_VOLUME_PATH = "/vm/volume/blockpull"; String TAKE_VM_CONSOLE_SCREENSHOT_PATH = "/vm/console/screenshot"; String UPDATE_VM_CONSOLE_PASSWORD_PATH = "/host/vm/updateConsolePassword/live"; + String UPDATE_VM_ENABLE_HA_LIVE_PATH = "/host/vm/updateEnableHa/live"; + String RECONCILE_VM_ENABLE_HA_LIVE_PATH = "/host/vm/reconcileEnableHa/live"; + String HA_NETWORK_GROUP_SYNC_PATH = "/ha/networkgroup/sync"; String KVM_HOST_IPSET_ATTACH_NIC_PATH = "/network/ipset/attach"; String KVM_HOST_IPSET_DETACH_NIC_PATH = "/network/ipset/detach"; diff --git a/sdk/src/main/java/SourceClassMap.java b/sdk/src/main/java/SourceClassMap.java index 4bbd9238f98..227acb8e9aa 100644 --- a/sdk/src/main/java/SourceClassMap.java +++ b/sdk/src/main/java/SourceClassMap.java @@ -178,6 +178,7 @@ public class SourceClassMap { put("org.zstack.guesttools.GuestVmScriptInventory", "org.zstack.sdk.GuestVmScriptInventory"); put("org.zstack.guesttools.InvocationRecord", "org.zstack.sdk.InvocationRecord"); put("org.zstack.guesttools.InvocationRecordDetail", "org.zstack.sdk.InvocationRecordDetail"); + put("org.zstack.ha.HaNetworkGroupInventory", "org.zstack.sdk.HaNetworkGroupInventory"); put("org.zstack.ha.HaStrategyConditionInventory", "org.zstack.sdk.HaStrategyConditionInventory"); put("org.zstack.header.acl.AccessControlListEntryInventory", "org.zstack.sdk.AccessControlListEntryInventory"); put("org.zstack.header.acl.AccessControlListInventory", "org.zstack.sdk.AccessControlListInventory"); @@ -1092,6 +1093,7 @@ public class SourceClassMap { put("org.zstack.sdk.GuestVmScriptExecutedRecordInventory", "org.zstack.guesttools.GuestVmScriptExecutedRecordInventory"); put("org.zstack.sdk.GuestVmScriptInventory", "org.zstack.guesttools.GuestVmScriptInventory"); put("org.zstack.sdk.H3cSdnControllerTenantInventory", "org.zstack.sdnController.header.H3cSdnControllerTenantInventory"); + put("org.zstack.sdk.HaNetworkGroupInventory", "org.zstack.ha.HaNetworkGroupInventory"); put("org.zstack.sdk.HaStrategyConditionInventory", "org.zstack.ha.HaStrategyConditionInventory"); put("org.zstack.sdk.HaiTaiSecretResourcePoolInventory", "org.zstack.crypto.securitymachine.thirdparty.haitai.HaiTaiSecretResourcePoolInventory"); put("org.zstack.sdk.HardwareL2VxlanNetworkInventory", "org.zstack.sdnController.header.HardwareL2VxlanNetworkInventory"); diff --git a/sdk/src/main/java/org/zstack/sdk/ChangeHaNetworkGroupStateAction.java b/sdk/src/main/java/org/zstack/sdk/ChangeHaNetworkGroupStateAction.java new file mode 100644 index 00000000000..81cd9a1925c --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/ChangeHaNetworkGroupStateAction.java @@ -0,0 +1,104 @@ +package org.zstack.sdk; + +import java.util.HashMap; +import java.util.Map; +import org.zstack.sdk.*; + +public class ChangeHaNetworkGroupStateAction extends AbstractAction { + + private static final HashMap parameterMap = new HashMap<>(); + + private static final HashMap nonAPIParameterMap = new HashMap<>(); + + public static class Result { + public ErrorCode error; + public org.zstack.sdk.ChangeHaNetworkGroupStateResult value; + + public Result throwExceptionIfError() { + if (error != null) { + throw new ApiException( + String.format("error[code: %s, description: %s, details: %s, globalErrorCode: %s]", error.code, error.description, error.details, error.globalErrorCode) + ); + } + + return this; + } + } + + @Param(required = true, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String uuid; + + @Param(required = true, validValues = {"enable","disable"}, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String stateEvent; + + @Param(required = false) + public java.util.List systemTags; + + @Param(required = false) + public java.util.List userTags; + + @Param(required = false) + public String sessionId; + + @Param(required = false) + public String accessKeyId; + + @Param(required = false) + public String accessKeySecret; + + @Param(required = false) + public String requestIp; + + @NonAPIParam + public long timeout = -1; + + @NonAPIParam + public long pollingInterval = -1; + + + private Result makeResult(ApiResult res) { + Result ret = new Result(); + if (res.error != null) { + ret.error = res.error; + return ret; + } + + org.zstack.sdk.ChangeHaNetworkGroupStateResult value = res.getResult(org.zstack.sdk.ChangeHaNetworkGroupStateResult.class); + ret.value = value == null ? new org.zstack.sdk.ChangeHaNetworkGroupStateResult() : value; + + return ret; + } + + public Result call() { + ApiResult res = ZSClient.call(this); + return makeResult(res); + } + + public void call(final Completion completion) { + ZSClient.call(this, new InternalCompletion() { + @Override + public void complete(ApiResult res) { + completion.complete(makeResult(res)); + } + }); + } + + protected Map getParameterMap() { + return parameterMap; + } + + protected Map getNonAPIParameterMap() { + return nonAPIParameterMap; + } + + protected RestInfo getRestInfo() { + RestInfo info = new RestInfo(); + info.httpMethod = "PUT"; + info.path = "/ha/network-groups/{uuid}/actions"; + info.needSession = true; + info.needPoll = true; + info.parameterName = "changeHaNetworkGroupState"; + return info; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/ChangeHaNetworkGroupStateResult.java b/sdk/src/main/java/org/zstack/sdk/ChangeHaNetworkGroupStateResult.java new file mode 100644 index 00000000000..b579aa5771d --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/ChangeHaNetworkGroupStateResult.java @@ -0,0 +1,14 @@ +package org.zstack.sdk; + +import org.zstack.sdk.HaNetworkGroupInventory; + +public class ChangeHaNetworkGroupStateResult { + public HaNetworkGroupInventory inventory; + public void setInventory(HaNetworkGroupInventory inventory) { + this.inventory = inventory; + } + public HaNetworkGroupInventory getInventory() { + return this.inventory; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/CreateHaNetworkGroupAction.java b/sdk/src/main/java/org/zstack/sdk/CreateHaNetworkGroupAction.java new file mode 100644 index 00000000000..afd25614e98 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/CreateHaNetworkGroupAction.java @@ -0,0 +1,122 @@ +package org.zstack.sdk; + +import java.util.HashMap; +import java.util.Map; +import org.zstack.sdk.*; + +public class CreateHaNetworkGroupAction extends AbstractAction { + + private static final HashMap parameterMap = new HashMap<>(); + + private static final HashMap nonAPIParameterMap = new HashMap<>(); + + public static class Result { + public ErrorCode error; + public org.zstack.sdk.CreateHaNetworkGroupResult value; + + public Result throwExceptionIfError() { + if (error != null) { + throw new ApiException( + String.format("error[code: %s, description: %s, details: %s, globalErrorCode: %s]", error.code, error.description, error.details, error.globalErrorCode) + ); + } + + return this; + } + } + + @Param(required = true, maxLength = 255, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String name; + + @Param(required = false, maxLength = 2048, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String description; + + @Param(required = true, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String clusterUuid; + + @Param(required = true, validValues = {"Flat","Public"}, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String type; + + @Param(required = true, nonempty = false, nullElements = false, emptyString = true, numberRange = {1L,2147483647L}, noTrim = false) + public int minAvailableCount = 0; + + @Param(required = true, nonempty = true, nullElements = false, emptyString = true, noTrim = false) + public java.util.List l3NetworkUuids; + + @Param(required = false) + public java.lang.String resourceUuid; + + @Param(required = false, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.util.List tagUuids; + + @Param(required = false) + public java.util.List systemTags; + + @Param(required = false) + public java.util.List userTags; + + @Param(required = false) + public String sessionId; + + @Param(required = false) + public String accessKeyId; + + @Param(required = false) + public String accessKeySecret; + + @Param(required = false) + public String requestIp; + + @NonAPIParam + public long timeout = -1; + + @NonAPIParam + public long pollingInterval = -1; + + + private Result makeResult(ApiResult res) { + Result ret = new Result(); + if (res.error != null) { + ret.error = res.error; + return ret; + } + + org.zstack.sdk.CreateHaNetworkGroupResult value = res.getResult(org.zstack.sdk.CreateHaNetworkGroupResult.class); + ret.value = value == null ? new org.zstack.sdk.CreateHaNetworkGroupResult() : value; + + return ret; + } + + public Result call() { + ApiResult res = ZSClient.call(this); + return makeResult(res); + } + + public void call(final Completion completion) { + ZSClient.call(this, new InternalCompletion() { + @Override + public void complete(ApiResult res) { + completion.complete(makeResult(res)); + } + }); + } + + protected Map getParameterMap() { + return parameterMap; + } + + protected Map getNonAPIParameterMap() { + return nonAPIParameterMap; + } + + protected RestInfo getRestInfo() { + RestInfo info = new RestInfo(); + info.httpMethod = "POST"; + info.path = "/ha/network-groups"; + info.needSession = true; + info.needPoll = true; + info.parameterName = "params"; + return info; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/CreateHaNetworkGroupResult.java b/sdk/src/main/java/org/zstack/sdk/CreateHaNetworkGroupResult.java new file mode 100644 index 00000000000..64326458698 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/CreateHaNetworkGroupResult.java @@ -0,0 +1,14 @@ +package org.zstack.sdk; + +import org.zstack.sdk.HaNetworkGroupInventory; + +public class CreateHaNetworkGroupResult { + public HaNetworkGroupInventory inventory; + public void setInventory(HaNetworkGroupInventory inventory) { + this.inventory = inventory; + } + public HaNetworkGroupInventory getInventory() { + return this.inventory; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/DeleteHaNetworkGroupAction.java b/sdk/src/main/java/org/zstack/sdk/DeleteHaNetworkGroupAction.java new file mode 100644 index 00000000000..1738b04a0e0 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/DeleteHaNetworkGroupAction.java @@ -0,0 +1,104 @@ +package org.zstack.sdk; + +import java.util.HashMap; +import java.util.Map; +import org.zstack.sdk.*; + +public class DeleteHaNetworkGroupAction extends AbstractAction { + + private static final HashMap parameterMap = new HashMap<>(); + + private static final HashMap nonAPIParameterMap = new HashMap<>(); + + public static class Result { + public ErrorCode error; + public org.zstack.sdk.DeleteHaNetworkGroupResult value; + + public Result throwExceptionIfError() { + if (error != null) { + throw new ApiException( + String.format("error[code: %s, description: %s, details: %s, globalErrorCode: %s]", error.code, error.description, error.details, error.globalErrorCode) + ); + } + + return this; + } + } + + @Param(required = true, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String uuid; + + @Param(required = false) + public java.lang.String deleteMode = "Permissive"; + + @Param(required = false) + public java.util.List systemTags; + + @Param(required = false) + public java.util.List userTags; + + @Param(required = false) + public String sessionId; + + @Param(required = false) + public String accessKeyId; + + @Param(required = false) + public String accessKeySecret; + + @Param(required = false) + public String requestIp; + + @NonAPIParam + public long timeout = -1; + + @NonAPIParam + public long pollingInterval = -1; + + + private Result makeResult(ApiResult res) { + Result ret = new Result(); + if (res.error != null) { + ret.error = res.error; + return ret; + } + + org.zstack.sdk.DeleteHaNetworkGroupResult value = res.getResult(org.zstack.sdk.DeleteHaNetworkGroupResult.class); + ret.value = value == null ? new org.zstack.sdk.DeleteHaNetworkGroupResult() : value; + + return ret; + } + + public Result call() { + ApiResult res = ZSClient.call(this); + return makeResult(res); + } + + public void call(final Completion completion) { + ZSClient.call(this, new InternalCompletion() { + @Override + public void complete(ApiResult res) { + completion.complete(makeResult(res)); + } + }); + } + + protected Map getParameterMap() { + return parameterMap; + } + + protected Map getNonAPIParameterMap() { + return nonAPIParameterMap; + } + + protected RestInfo getRestInfo() { + RestInfo info = new RestInfo(); + info.httpMethod = "DELETE"; + info.path = "/ha/network-groups/{uuid}"; + info.needSession = true; + info.needPoll = true; + info.parameterName = ""; + return info; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/DeleteHaNetworkGroupResult.java b/sdk/src/main/java/org/zstack/sdk/DeleteHaNetworkGroupResult.java new file mode 100644 index 00000000000..602e0408c62 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/DeleteHaNetworkGroupResult.java @@ -0,0 +1,7 @@ +package org.zstack.sdk; + + + +public class DeleteHaNetworkGroupResult { + +} diff --git a/sdk/src/main/java/org/zstack/sdk/HaNetworkGroupInventory.java b/sdk/src/main/java/org/zstack/sdk/HaNetworkGroupInventory.java new file mode 100644 index 00000000000..2a2ce9b44e8 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/HaNetworkGroupInventory.java @@ -0,0 +1,95 @@ +package org.zstack.sdk; + + + +public class HaNetworkGroupInventory { + + public java.lang.String uuid; + public void setUuid(java.lang.String uuid) { + this.uuid = uuid; + } + public java.lang.String getUuid() { + return this.uuid; + } + + public java.lang.String name; + public void setName(java.lang.String name) { + this.name = name; + } + public java.lang.String getName() { + return this.name; + } + + public java.lang.String description; + public void setDescription(java.lang.String description) { + this.description = description; + } + public java.lang.String getDescription() { + return this.description; + } + + public java.lang.String clusterUuid; + public void setClusterUuid(java.lang.String clusterUuid) { + this.clusterUuid = clusterUuid; + } + public java.lang.String getClusterUuid() { + return this.clusterUuid; + } + + public java.lang.String type; + public void setType(java.lang.String type) { + this.type = type; + } + public java.lang.String getType() { + return this.type; + } + + public int minAvailableCount; + public void setMinAvailableCount(int minAvailableCount) { + this.minAvailableCount = minAvailableCount; + } + public int getMinAvailableCount() { + return this.minAvailableCount; + } + + public java.lang.Long configVersion; + public void setConfigVersion(java.lang.Long configVersion) { + this.configVersion = configVersion; + } + public java.lang.Long getConfigVersion() { + return this.configVersion; + } + + public java.lang.String state; + public void setState(java.lang.String state) { + this.state = state; + } + public java.lang.String getState() { + return this.state; + } + + public java.sql.Timestamp createDate; + public void setCreateDate(java.sql.Timestamp createDate) { + this.createDate = createDate; + } + public java.sql.Timestamp getCreateDate() { + return this.createDate; + } + + public java.sql.Timestamp lastOpDate; + public void setLastOpDate(java.sql.Timestamp lastOpDate) { + this.lastOpDate = lastOpDate; + } + public java.sql.Timestamp getLastOpDate() { + return this.lastOpDate; + } + + public java.util.Set l3NetworkUuids; + public void setL3NetworkUuids(java.util.Set l3NetworkUuids) { + this.l3NetworkUuids = l3NetworkUuids; + } + public java.util.Set getL3NetworkUuids() { + return this.l3NetworkUuids; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/QueryHaNetworkGroupAction.java b/sdk/src/main/java/org/zstack/sdk/QueryHaNetworkGroupAction.java new file mode 100644 index 00000000000..f358fa563ef --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/QueryHaNetworkGroupAction.java @@ -0,0 +1,75 @@ +package org.zstack.sdk; + +import java.util.HashMap; +import java.util.Map; +import org.zstack.sdk.*; + +public class QueryHaNetworkGroupAction extends QueryAction { + + private static final HashMap parameterMap = new HashMap<>(); + + private static final HashMap nonAPIParameterMap = new HashMap<>(); + + public static class Result { + public ErrorCode error; + public org.zstack.sdk.QueryHaNetworkGroupResult value; + + public Result throwExceptionIfError() { + if (error != null) { + throw new ApiException( + String.format("error[code: %s, description: %s, details: %s, globalErrorCode: %s]", error.code, error.description, error.details, error.globalErrorCode) + ); + } + + return this; + } + } + + + + private Result makeResult(ApiResult res) { + Result ret = new Result(); + if (res.error != null) { + ret.error = res.error; + return ret; + } + + org.zstack.sdk.QueryHaNetworkGroupResult value = res.getResult(org.zstack.sdk.QueryHaNetworkGroupResult.class); + ret.value = value == null ? new org.zstack.sdk.QueryHaNetworkGroupResult() : value; + + return ret; + } + + public Result call() { + ApiResult res = ZSClient.call(this); + return makeResult(res); + } + + public void call(final Completion completion) { + ZSClient.call(this, new InternalCompletion() { + @Override + public void complete(ApiResult res) { + completion.complete(makeResult(res)); + } + }); + } + + protected Map getParameterMap() { + return parameterMap; + } + + protected Map getNonAPIParameterMap() { + return nonAPIParameterMap; + } + + protected RestInfo getRestInfo() { + RestInfo info = new RestInfo(); + info.httpMethod = "GET"; + info.path = "/ha/network-groups"; + info.needSession = true; + info.needPoll = false; + info.parameterName = ""; + return info; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/QueryHaNetworkGroupResult.java b/sdk/src/main/java/org/zstack/sdk/QueryHaNetworkGroupResult.java new file mode 100644 index 00000000000..b865e2ded08 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/QueryHaNetworkGroupResult.java @@ -0,0 +1,22 @@ +package org.zstack.sdk; + + + +public class QueryHaNetworkGroupResult { + public java.util.List inventories; + public void setInventories(java.util.List inventories) { + this.inventories = inventories; + } + public java.util.List getInventories() { + return this.inventories; + } + + public java.lang.Long total; + public void setTotal(java.lang.Long total) { + this.total = total; + } + public java.lang.Long getTotal() { + return this.total; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/UpdateHaNetworkGroupAction.java b/sdk/src/main/java/org/zstack/sdk/UpdateHaNetworkGroupAction.java new file mode 100644 index 00000000000..6bbc6dc2350 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/UpdateHaNetworkGroupAction.java @@ -0,0 +1,113 @@ +package org.zstack.sdk; + +import java.util.HashMap; +import java.util.Map; +import org.zstack.sdk.*; + +public class UpdateHaNetworkGroupAction extends AbstractAction { + + private static final HashMap parameterMap = new HashMap<>(); + + private static final HashMap nonAPIParameterMap = new HashMap<>(); + + public static class Result { + public ErrorCode error; + public org.zstack.sdk.UpdateHaNetworkGroupResult value; + + public Result throwExceptionIfError() { + if (error != null) { + throw new ApiException( + String.format("error[code: %s, description: %s, details: %s, globalErrorCode: %s]", error.code, error.description, error.details, error.globalErrorCode) + ); + } + + return this; + } + } + + @Param(required = true, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String uuid; + + @Param(required = false, maxLength = 255, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String name; + + @Param(required = false, maxLength = 2048, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.lang.String description; + + @Param(required = false, nonempty = false, nullElements = false, emptyString = true, numberRange = {1L,2147483647L}, noTrim = false) + public java.lang.Integer minAvailableCount; + + @Param(required = false, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + public java.util.List l3NetworkUuids; + + @Param(required = false) + public java.util.List systemTags; + + @Param(required = false) + public java.util.List userTags; + + @Param(required = false) + public String sessionId; + + @Param(required = false) + public String accessKeyId; + + @Param(required = false) + public String accessKeySecret; + + @Param(required = false) + public String requestIp; + + @NonAPIParam + public long timeout = -1; + + @NonAPIParam + public long pollingInterval = -1; + + + private Result makeResult(ApiResult res) { + Result ret = new Result(); + if (res.error != null) { + ret.error = res.error; + return ret; + } + + org.zstack.sdk.UpdateHaNetworkGroupResult value = res.getResult(org.zstack.sdk.UpdateHaNetworkGroupResult.class); + ret.value = value == null ? new org.zstack.sdk.UpdateHaNetworkGroupResult() : value; + + return ret; + } + + public Result call() { + ApiResult res = ZSClient.call(this); + return makeResult(res); + } + + public void call(final Completion completion) { + ZSClient.call(this, new InternalCompletion() { + @Override + public void complete(ApiResult res) { + completion.complete(makeResult(res)); + } + }); + } + + protected Map getParameterMap() { + return parameterMap; + } + + protected Map getNonAPIParameterMap() { + return nonAPIParameterMap; + } + + protected RestInfo getRestInfo() { + RestInfo info = new RestInfo(); + info.httpMethod = "PUT"; + info.path = "/ha/network-groups/{uuid}"; + info.needSession = true; + info.needPoll = true; + info.parameterName = "updateHaNetworkGroup"; + return info; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/UpdateHaNetworkGroupResult.java b/sdk/src/main/java/org/zstack/sdk/UpdateHaNetworkGroupResult.java new file mode 100644 index 00000000000..d2294f92d05 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/UpdateHaNetworkGroupResult.java @@ -0,0 +1,14 @@ +package org.zstack.sdk; + +import org.zstack.sdk.HaNetworkGroupInventory; + +public class UpdateHaNetworkGroupResult { + public HaNetworkGroupInventory inventory; + public void setInventory(HaNetworkGroupInventory inventory) { + this.inventory = inventory; + } + public HaNetworkGroupInventory getInventory() { + return this.inventory; + } + +} diff --git a/simulator/simulatorImpl/src/main/java/org/zstack/simulator/kvm/KVMSimulatorConfig.java b/simulator/simulatorImpl/src/main/java/org/zstack/simulator/kvm/KVMSimulatorConfig.java index 4a1cfaa1798..caf1b3f9960 100755 --- a/simulator/simulatorImpl/src/main/java/org/zstack/simulator/kvm/KVMSimulatorConfig.java +++ b/simulator/simulatorImpl/src/main/java/org/zstack/simulator/kvm/KVMSimulatorConfig.java @@ -85,6 +85,9 @@ public class KVMSimulatorConfig { public volatile boolean vmSyncSuccess = true; public List hardenVmConsoleCmds = new ArrayList(); public List deleteVmConsoleFirewallCmds = new ArrayList(); + public List updateVmEnableHaLiveCmds = new ArrayList(); + public List reconcileVmEnableHaOnHostCmds = new ArrayList(); + public List syncHaNetworkGroupConfigCmds = new ArrayList(); public Map takeSnapshotCmdSize = new HashMap(); } diff --git a/simulator/simulatorImpl/src/main/java/org/zstack/simulator/kvm/KVMSimulatorController.java b/simulator/simulatorImpl/src/main/java/org/zstack/simulator/kvm/KVMSimulatorController.java index 802fffbd702..e97b9d02c2d 100755 --- a/simulator/simulatorImpl/src/main/java/org/zstack/simulator/kvm/KVMSimulatorController.java +++ b/simulator/simulatorImpl/src/main/java/org/zstack/simulator/kvm/KVMSimulatorController.java @@ -705,6 +705,38 @@ private void getVncPort(HttpEntity entity) { replyer.reply(entity, rsp); } + @RequestMapping(value = KVMConstant.UPDATE_VM_ENABLE_HA_LIVE_PATH, method = RequestMethod.POST) + private @ResponseBody String updateVmEnableHaLive(HttpServletRequest req) { + HttpEntity entity = restf.httpServletRequestToHttpEntity(req); + UpdateVmEnableHaLiveCmd cmd = JSONObjectUtil.toObject(entity.getBody(), UpdateVmEnableHaLiveCmd.class); + synchronized (config.updateVmEnableHaLiveCmds) { + config.updateVmEnableHaLiveCmds.add(cmd); + } + replyer.reply(entity, new AgentResponse()); + return null; + } + + @RequestMapping(value = KVMConstant.RECONCILE_VM_ENABLE_HA_LIVE_PATH, method = RequestMethod.POST) + private @ResponseBody String reconcileVmEnableHaOnHost(HttpServletRequest req) { + HttpEntity entity = restf.httpServletRequestToHttpEntity(req); + ReconcileVmEnableHaOnHostCmd cmd = JSONObjectUtil.toObject(entity.getBody(), ReconcileVmEnableHaOnHostCmd.class); + synchronized (config.reconcileVmEnableHaOnHostCmds) { + config.reconcileVmEnableHaOnHostCmds.add(cmd); + } + replyer.reply(entity, new AgentResponse()); + return null; + } + + @RequestMapping(value = KVMConstant.HA_NETWORK_GROUP_SYNC_PATH, method = RequestMethod.POST) + private @ResponseBody String syncHaNetworkGroupConfig(HttpServletRequest req) { + HttpEntity entity = restf.httpServletRequestToHttpEntity(req); + synchronized (config.syncHaNetworkGroupConfigCmds) { + config.syncHaNetworkGroupConfigCmds.add(entity.getBody()); + } + replyer.reply(entity, new AgentResponse()); + return null; + } + @RequestMapping(value=KVMConstant.KVM_LOGOUT_ISCSI_PATH, method=RequestMethod.POST) private @ResponseBody String logoutIscsiTarget(HttpServletRequest req) throws InterruptedException { HttpEntity entity = restf.httpServletRequestToHttpEntity(req); diff --git a/testlib/src/main/java/org/zstack/testlib/ApiHelper.groovy b/testlib/src/main/java/org/zstack/testlib/ApiHelper.groovy index f8470e35bd3..04fc768932a 100644 --- a/testlib/src/main/java/org/zstack/testlib/ApiHelper.groovy +++ b/testlib/src/main/java/org/zstack/testlib/ApiHelper.groovy @@ -5606,6 +5606,33 @@ abstract class ApiHelper { } + def changeHaNetworkGroupState(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.ChangeHaNetworkGroupStateAction.class) Closure c) { + def a = new org.zstack.sdk.ChangeHaNetworkGroupStateAction() + a.sessionId = Test.currentEnvSpec?.session?.uuid + c.resolveStrategy = Closure.OWNER_FIRST + c.delegate = a + c() + + + if (System.getProperty("apipath") != null) { + if (a.apiId == null) { + a.apiId = Platform.uuid + } + + def tracker = new ApiPathTracker(a.apiId) + def out = errorOut(a.call()) + def path = tracker.getApiPath() + if (!path.isEmpty()) { + Test.apiPaths[a.class.name] = path.join(" --->\n") + } + + return out + } else { + return errorOut(a.call()) + } + } + + def changeHostNetworkInterfaceLldpMode(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.ChangeHostNetworkInterfaceLldpModeAction.class) Closure c) { def a = new org.zstack.sdk.ChangeHostNetworkInterfaceLldpModeAction() a.sessionId = Test.currentEnvSpec?.session?.uuid @@ -9602,6 +9629,33 @@ abstract class ApiHelper { } + def createHaNetworkGroup(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.CreateHaNetworkGroupAction.class) Closure c) { + def a = new org.zstack.sdk.CreateHaNetworkGroupAction() + a.sessionId = Test.currentEnvSpec?.session?.uuid + c.resolveStrategy = Closure.OWNER_FIRST + c.delegate = a + c() + + + if (System.getProperty("apipath") != null) { + if (a.apiId == null) { + a.apiId = Platform.uuid + } + + def tracker = new ApiPathTracker(a.apiId) + def out = errorOut(a.call()) + def path = tracker.getApiPath() + if (!path.isEmpty()) { + Test.apiPaths[a.class.name] = path.join(" --->\n") + } + + return out + } else { + return errorOut(a.call()) + } + } + + def createHaiTaiSecretResourcePool(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.CreateHaiTaiSecretResourcePoolAction.class) Closure c) { def a = new org.zstack.sdk.CreateHaiTaiSecretResourcePoolAction() a.sessionId = Test.currentEnvSpec?.session?.uuid @@ -14732,6 +14786,33 @@ abstract class ApiHelper { } + def deleteHaNetworkGroup(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.DeleteHaNetworkGroupAction.class) Closure c) { + def a = new org.zstack.sdk.DeleteHaNetworkGroupAction() + a.sessionId = Test.currentEnvSpec?.session?.uuid + c.resolveStrategy = Closure.OWNER_FIRST + c.delegate = a + c() + + + if (System.getProperty("apipath") != null) { + if (a.apiId == null) { + a.apiId = Platform.uuid + } + + def tracker = new ApiPathTracker(a.apiId) + def out = errorOut(a.call()) + def path = tracker.getApiPath() + if (!path.isEmpty()) { + Test.apiPaths[a.class.name] = path.join(" --->\n") + } + + return out + } else { + return errorOut(a.call()) + } + } + + def deleteHost(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.DeleteHostAction.class) Closure c) { def a = new org.zstack.sdk.DeleteHostAction() a.sessionId = Test.currentEnvSpec?.session?.uuid @@ -31329,6 +31410,35 @@ abstract class ApiHelper { } + def queryHaNetworkGroup(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.QueryHaNetworkGroupAction.class) Closure c) { + def a = new org.zstack.sdk.QueryHaNetworkGroupAction() + a.sessionId = Test.currentEnvSpec?.session?.uuid + c.resolveStrategy = Closure.OWNER_FIRST + c.delegate = a + c() + + a.conditions = a.conditions.collect { it.toString() } + + + if (System.getProperty("apipath") != null) { + if (a.apiId == null) { + a.apiId = Platform.uuid + } + + def tracker = new ApiPathTracker(a.apiId) + def out = errorOut(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 queryHost(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.QueryHostAction.class) Closure c) { def a = new org.zstack.sdk.QueryHostAction() a.sessionId = Test.currentEnvSpec?.session?.uuid @@ -44532,6 +44642,33 @@ abstract class ApiHelper { } + def updateHaNetworkGroup(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.UpdateHaNetworkGroupAction.class) Closure c) { + def a = new org.zstack.sdk.UpdateHaNetworkGroupAction() + a.sessionId = Test.currentEnvSpec?.session?.uuid + c.resolveStrategy = Closure.OWNER_FIRST + c.delegate = a + c() + + + if (System.getProperty("apipath") != null) { + if (a.apiId == null) { + a.apiId = Platform.uuid + } + + def tracker = new ApiPathTracker(a.apiId) + def out = errorOut(a.call()) + def path = tracker.getApiPath() + if (!path.isEmpty()) { + Test.apiPaths[a.class.name] = path.join(" --->\n") + } + + return out + } else { + return errorOut(a.call()) + } + } + + def updateHaStrategyCondition(@DelegatesTo(strategy = Closure.OWNER_FIRST, value = org.zstack.sdk.UpdateHaStrategyConditionAction.class) Closure c) { def a = new org.zstack.sdk.UpdateHaStrategyConditionAction() a.sessionId = Test.currentEnvSpec?.session?.uuid diff --git a/testlib/src/main/java/org/zstack/testlib/KVMSimulator.groovy b/testlib/src/main/java/org/zstack/testlib/KVMSimulator.groovy index 81bd88ac6bf..7653ef3d701 100755 --- a/testlib/src/main/java/org/zstack/testlib/KVMSimulator.groovy +++ b/testlib/src/main/java/org/zstack/testlib/KVMSimulator.groovy @@ -691,5 +691,17 @@ class KVMSimulator implements Simulator { spec.simulator(KVMConstant.KVM_HOST_IPSET_SYNC_PATH) { return new KVMAgentCommands.AgentResponse() } + + spec.simulator(KVMConstant.UPDATE_VM_ENABLE_HA_LIVE_PATH) { + return new KVMAgentCommands.AgentResponse() + } + + spec.simulator(KVMConstant.RECONCILE_VM_ENABLE_HA_LIVE_PATH) { + return new KVMAgentCommands.AgentResponse() + } + + spec.simulator(KVMConstant.HA_NETWORK_GROUP_SYNC_PATH) { + return new KVMAgentCommands.AgentResponse() + } } } diff --git a/utils/src/main/java/org/zstack/utils/clouderrorcode/CloudOperationsErrorCode.java b/utils/src/main/java/org/zstack/utils/clouderrorcode/CloudOperationsErrorCode.java index a0f09d4f1e9..37be98cf482 100644 --- a/utils/src/main/java/org/zstack/utils/clouderrorcode/CloudOperationsErrorCode.java +++ b/utils/src/main/java/org/zstack/utils/clouderrorcode/CloudOperationsErrorCode.java @@ -1858,6 +1858,38 @@ public class CloudOperationsErrorCode { public static final String ORG_ZSTACK_HA_10018 = "ORG_ZSTACK_HA_10018"; + public static final String ORG_ZSTACK_HA_10019 = "ORG_ZSTACK_HA_10019"; + + public static final String ORG_ZSTACK_HA_10020 = "ORG_ZSTACK_HA_10020"; + + public static final String ORG_ZSTACK_HA_10021 = "ORG_ZSTACK_HA_10021"; + + public static final String ORG_ZSTACK_HA_10022 = "ORG_ZSTACK_HA_10022"; + + public static final String ORG_ZSTACK_HA_10023 = "ORG_ZSTACK_HA_10023"; + + public static final String ORG_ZSTACK_HA_10024 = "ORG_ZSTACK_HA_10024"; + + public static final String ORG_ZSTACK_HA_10025 = "ORG_ZSTACK_HA_10025"; + + public static final String ORG_ZSTACK_HA_10026 = "ORG_ZSTACK_HA_10026"; + + public static final String ORG_ZSTACK_HA_10027 = "ORG_ZSTACK_HA_10027"; + + public static final String ORG_ZSTACK_HA_10028 = "ORG_ZSTACK_HA_10028"; + + public static final String ORG_ZSTACK_HA_10029 = "ORG_ZSTACK_HA_10029"; + + public static final String ORG_ZSTACK_HA_10030 = "ORG_ZSTACK_HA_10030"; + + public static final String ORG_ZSTACK_HA_10031 = "ORG_ZSTACK_HA_10031"; + + public static final String ORG_ZSTACK_HA_10032 = "ORG_ZSTACK_HA_10032"; + + public static final String ORG_ZSTACK_HA_10033 = "ORG_ZSTACK_HA_10033"; + + public static final String ORG_ZSTACK_HA_10034 = "ORG_ZSTACK_HA_10034"; + public static final String ORG_ZSTACK_NETWORK_SERVICE_SLB_10000 = "ORG_ZSTACK_NETWORK_SERVICE_SLB_10000"; public static final String ORG_ZSTACK_NETWORK_SERVICE_SLB_10001 = "ORG_ZSTACK_NETWORK_SERVICE_SLB_10001";