Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions conf/db/upgrade/V5.5.22__schema.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
CREATE TABLE IF NOT EXISTS `zstack`.`HaNetworkGroupVO` (
`uuid` VARCHAR(32) NOT NULL UNIQUE COMMENT 'uuid',
`name` VARCHAR(255) NOT NULL,
`description` VARCHAR(2048) DEFAULT NULL,
`type` VARCHAR(128) NOT NULL,
`minAvailableCount` INT(10) NOT NULL DEFAULT 1,
`state` VARCHAR(32) NOT NULL DEFAULT 'Enabled',
`lastOpDate` TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP,
`createDate` TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00',
Comment on lines +8 to +9
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

修复非法零时间默认值,避免升级脚本在严格模式下失败

Line 8、Line 9、Line 17、Line 18、Line 31、Line 32 使用了 DEFAULT '0000-00-00 00:00:00',这在 MySQL 8/GreatSQL 常见严格 SQL 模式下会导致 DDL 执行失败,属于升级阻断问题。

🛠️ 建议修复 diff
 CREATE TABLE IF NOT EXISTS `zstack`.`HaNetworkGroupVO` (
@@
-    `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',
+    `lastOpDate` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+    `createDate` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
@@
 CREATE TABLE IF NOT EXISTS `zstack`.`HaNetworkGroupL3NetworkRefVO` (
@@
-    `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',
+    `lastOpDate` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+    `createDate` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
@@
 CREATE TABLE IF NOT EXISTS `zstack`.`HostHaNetworkGroupStatusVO` (
@@
-    `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',
+    `lastOpDate` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+    `createDate` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,

As per coding guidelines **/*.sql: Do not use DEFAULT 0000-00-00 00:00:00, use DEFAULT CURRENT_TIMESTAMP instead.

Also applies to: 17-18, 31-32

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@conf/db/upgrade/V5.5.22__schema.sql` around lines 8 - 9, Replace the invalid
zero-datetime defaults with CURRENT_TIMESTAMP: update the column definitions
that use `DEFAULT '0000-00-00 00:00:00'` (e.g., `lastOpDate`, `createDate` and
the other two occurrences) to use `DEFAULT CURRENT_TIMESTAMP` (and keep `ON
UPDATE CURRENT_TIMESTAMP` only on columns that should auto-update, e.g.,
`lastOpDate`), ensuring the NOT NULL semantics remain intact so the DDL will
succeed in strict SQL modes.

PRIMARY KEY (`uuid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE IF NOT EXISTS `zstack`.`HaNetworkGroupL3NetworkRefVO` (
`uuid` VARCHAR(32) NOT NULL UNIQUE COMMENT 'uuid',
`haNetworkGroupUuid` VARCHAR(32) NOT NULL,
`l3NetworkUuid` VARCHAR(32) NOT NULL,
`lastOpDate` TIMESTAMP NOT NULL DEFAULT '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`),
UNIQUE INDEX `ukHaNetworkGroupL3NetworkRefVOl3NetworkUuid` (`l3NetworkUuid`),
CONSTRAINT `fkHaNetworkGroupL3NetworkRefVOHaNetworkGroupVO` FOREIGN KEY (`haNetworkGroupUuid`) REFERENCES `zstack`.`HaNetworkGroupVO` (`uuid`) ON DELETE CASCADE,
CONSTRAINT `fkHaNetworkGroupL3NetworkRefVOL3NetworkEO` FOREIGN KEY (`l3NetworkUuid`) REFERENCES `zstack`.`L3NetworkEO` (`uuid`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE IF NOT EXISTS `zstack`.`HostHaNetworkGroupStatusVO` (
`uuid` VARCHAR(32) NOT NULL UNIQUE COMMENT 'uuid',
`hostUuid` VARCHAR(32) NOT NULL,
`networkGroupUuid` VARCHAR(32) NOT NULL,
`status` VARCHAR(32) NOT NULL DEFAULT 'Unknown',
`lastOpDate` TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00' ON UPDATE CURRENT_TIMESTAMP,
`createDate` TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00',
PRIMARY KEY (`uuid`),
UNIQUE INDEX `ukHostHaNetworkGroupStatusVOHostUuidNetworkGroupUuid` (`hostUuid`, `networkGroupUuid`),
INDEX `idxHostHaNetworkGroupStatusVOhostUuid` (`hostUuid`),
INDEX `idxHostHaNetworkGroupStatusVOnetworkGroupUuid` (`networkGroupUuid`),
CONSTRAINT `fkHostHaNetworkGroupStatusVOHostEO` FOREIGN KEY (`hostUuid`) REFERENCES `zstack`.`HostEO` (`uuid`) ON DELETE CASCADE,
CONSTRAINT `fkHostHaNetworkGroupStatusVOHaNetworkGroupVO` FOREIGN KEY (`networkGroupUuid`) REFERENCES `zstack`.`HaNetworkGroupVO` (`uuid`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE IF NOT EXISTS `zstack`.`HaNetworkGroupGlobalConfigVersionVO` (
`name` VARCHAR(64) NOT NULL,
`version` BIGINT UNSIGNED NOT NULL DEFAULT 0,
PRIMARY KEY (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT IGNORE INTO `zstack`.`HaNetworkGroupGlobalConfigVersionVO` (`name`, `version`)
VALUES ('ha-network-group', 0);
46 changes: 46 additions & 0 deletions plugin/kvm/src/main/java/org/zstack/kvm/KVMAgentCommands.java
Original file line number Diff line number Diff line change
Expand Up @@ -1014,6 +1014,42 @@ public static class SetVmConsolePasswordLiveCmd extends AgentCommand implements
public void setPassword(String password) { this.password = password; }
}

public static class SetupVmHaEnabledMetadataLiveCmd extends AgentCommand implements Serializable {
@GrayVersion(value = "5.5.6")
private String vmUuid;
@GrayVersion(value = "5.5.6")
private Boolean enableHa;

public String getVmUuid() {
return vmUuid;
}

public void setVmUuid(String vmUuid) {
this.vmUuid = vmUuid;
}

public Boolean getEnableHa() {
return enableHa;
}

public void setEnableHa(Boolean enableHa) {
this.enableHa = enableHa;
}
}

public static class ReconcileVmHaEnabledMetadataLiveCmd extends AgentCommand implements Serializable {
@GrayVersion(value = "5.5.6")
private List<String> neverStopVmUuids;

public List<String> getNeverStopVmUuids() {
return neverStopVmUuids;
}

public void setNeverStopVmUuids(List<String> neverStopVmUuids) {
this.neverStopVmUuids = neverStopVmUuids;
}
}

public static class UpdateL2NetworkCmd extends AgentCommand {
private String physicalInterfaceName;
private String bridgeName;
Expand Down Expand Up @@ -2236,6 +2272,8 @@ public static class StartVmCmd extends vdiCmd implements VmAddOnsCmd {
private String nestedVirtualization;
@GrayVersion(value = "5.0.0")
private String hostManagementIp;
@GrayVersion(value = "5.5.6")
private Boolean enableHa;
@GrayVersion(value = "5.0.0")
private String clock;
@GrayVersion(value = "5.0.0")
Expand Down Expand Up @@ -2726,6 +2764,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;
}
Expand Down
3 changes: 3 additions & 0 deletions plugin/kvm/src/main/java/org/zstack/kvm/KVMConstant.java
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,9 @@ public interface KVMConstant {
String KVM_BLOCK_PULL_VOLUME_PATH = "/vm/volume/blockpull";
String TAKE_VM_CONSOLE_SCREENSHOT_PATH = "/vm/console/screenshot";
String UPDATE_VM_CONSOLE_PASSWORD_PATH = "/host/vm/updateConsolePassword/live";
String SETUP_VM_HA_ENABLED_METADATA_LIVE_PATH = "/host/vm/setupHaEnabledMetadata/live";
String RECONCILE_VM_HA_ENABLED_METADATA_LIVE_PATH = "/host/vm/reconcileHaEnabledMetadata/live";
String HA_NETWORK_GROUP_SYNC_PATH = "/ha/networkgroup/sync";

String KVM_HOST_IPSET_ATTACH_NIC_PATH = "/network/ipset/attach";
String KVM_HOST_IPSET_DETACH_NIC_PATH = "/network/ipset/detach";
Expand Down
2 changes: 2 additions & 0 deletions sdk/src/main/java/SourceClassMap.java
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,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");
Expand Down Expand Up @@ -1122,6 +1123,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");
Expand Down
104 changes: 104 additions & 0 deletions sdk/src/main/java/org/zstack/sdk/ChangeHaNetworkGroupStateAction.java
Original file line number Diff line number Diff line change
@@ -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<String, Parameter> parameterMap = new HashMap<>();

private static final HashMap<String, Parameter> 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<Result> completion) {
ZSClient.call(this, new InternalCompletion() {
@Override
public void complete(ApiResult res) {
completion.complete(makeResult(res));
}
});
}

protected Map<String, Parameter> getParameterMap() {
return parameterMap;
}

protected Map<String, Parameter> 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;
}

}
Original file line number Diff line number Diff line change
@@ -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;
}

}
119 changes: 119 additions & 0 deletions sdk/src/main/java/org/zstack/sdk/CreateHaNetworkGroupAction.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
package org.zstack.sdk;

import java.util.HashMap;
import java.util.Map;
import org.zstack.sdk.*;

public class CreateHaNetworkGroupAction extends AbstractAction {

private static final HashMap<String, Parameter> parameterMap = new HashMap<>();

private static final HashMap<String, Parameter> nonAPIParameterMap = new HashMap<>();

public static class Result {
public ErrorCode error;
public org.zstack.sdk.CreateHaNetworkGroupResult value;

public Result throwExceptionIfError() {
if (error != null) {
throw new ApiException(
String.format("error[code: %s, description: %s, details: %s, globalErrorCode: %s]", error.code, error.description, error.details, error.globalErrorCode)
);
}

return this;
}
}

@Param(required = true, maxLength = 255, nonempty = false, nullElements = false, emptyString = true, noTrim = false)
public java.lang.String name;

@Param(required = false, maxLength = 2048, nonempty = false, nullElements = false, emptyString = true, noTrim = false)
public java.lang.String description;

@Param(required = true, validValues = {"Flat","Public"}, nonempty = false, nullElements = false, emptyString = true, noTrim = false)
public java.lang.String type;

@Param(required = true, nonempty = false, nullElements = false, emptyString = true, numberRange = {1L,2147483647L}, noTrim = false)
public int minAvailableCount = 0;

@Param(required = true, nonempty = true, nullElements = false, emptyString = true, noTrim = false)
public java.util.List l3NetworkUuids;

@Param(required = false)
public java.lang.String resourceUuid;

@Param(required = false, nonempty = false, nullElements = false, emptyString = true, noTrim = false)
public java.util.List tagUuids;

@Param(required = false)
public java.util.List systemTags;

@Param(required = false)
public java.util.List userTags;

@Param(required = false)
public String sessionId;

@Param(required = false)
public String accessKeyId;

@Param(required = false)
public String accessKeySecret;

@Param(required = false)
public String requestIp;

@NonAPIParam
public long timeout = -1;

@NonAPIParam
public long pollingInterval = -1;


private Result makeResult(ApiResult res) {
Result ret = new Result();
if (res.error != null) {
ret.error = res.error;
return ret;
}

org.zstack.sdk.CreateHaNetworkGroupResult value = res.getResult(org.zstack.sdk.CreateHaNetworkGroupResult.class);
ret.value = value == null ? new org.zstack.sdk.CreateHaNetworkGroupResult() : value;

return ret;
}

public Result call() {
ApiResult res = ZSClient.call(this);
return makeResult(res);
}

public void call(final Completion<Result> completion) {
ZSClient.call(this, new InternalCompletion() {
@Override
public void complete(ApiResult res) {
completion.complete(makeResult(res));
}
});
}

protected Map<String, Parameter> getParameterMap() {
return parameterMap;
}

protected Map<String, Parameter> 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;
}

}
14 changes: 14 additions & 0 deletions sdk/src/main/java/org/zstack/sdk/CreateHaNetworkGroupResult.java
Original file line number Diff line number Diff line change
@@ -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;
}

}
Loading