diff --git a/conf/db/upgrade/V5.5.38__schema.sql b/conf/db/upgrade/V5.5.38__schema.sql index 64c997dc430..16f092dee8a 100644 --- a/conf/db/upgrade/V5.5.38__schema.sql +++ b/conf/db/upgrade/V5.5.38__schema.sql @@ -1,7 +1,7 @@ CREATE TABLE IF NOT EXISTS `NetworkSecurityPolicyScheduleVO` ( `uuid` varchar(32) NOT NULL, `name` varchar(255) NOT NULL, - `description` varchar(2048) DEFAULT NULL, + `description` varchar(255) DEFAULT NULL, `resourceType` varchar(32) NOT NULL, `resourceUuid` varchar(32) NOT NULL, `timeType` varchar(32) NOT NULL, diff --git a/plugin/networkSecurityPolicySchedule/src/main/java/org/zstack/networksecuritypolicyschedule/APICreateNetworkSecurityPolicyScheduleEvent.java b/plugin/networkSecurityPolicySchedule/src/main/java/org/zstack/networksecuritypolicyschedule/APICreateNetworkSecurityPolicyScheduleEvent.java index a5f3d8e309e..401abce2850 100644 --- a/plugin/networkSecurityPolicySchedule/src/main/java/org/zstack/networksecuritypolicyschedule/APICreateNetworkSecurityPolicyScheduleEvent.java +++ b/plugin/networkSecurityPolicySchedule/src/main/java/org/zstack/networksecuritypolicyschedule/APICreateNetworkSecurityPolicyScheduleEvent.java @@ -21,4 +21,11 @@ public NetworkSecurityPolicyScheduleInventory getInventory() { public void setInventory(NetworkSecurityPolicyScheduleInventory inventory) { this.inventory = inventory; } + + public static APICreateNetworkSecurityPolicyScheduleEvent __example__() { + APICreateNetworkSecurityPolicyScheduleEvent event = + new APICreateNetworkSecurityPolicyScheduleEvent(); + event.setInventory(NetworkSecurityPolicyScheduleInventory.__example__()); + return event; + } } diff --git a/plugin/networkSecurityPolicySchedule/src/main/java/org/zstack/networksecuritypolicyschedule/APICreateNetworkSecurityPolicyScheduleMsg.java b/plugin/networkSecurityPolicySchedule/src/main/java/org/zstack/networksecuritypolicyschedule/APICreateNetworkSecurityPolicyScheduleMsg.java index bab05b803cf..c004ac3c130 100644 --- a/plugin/networkSecurityPolicySchedule/src/main/java/org/zstack/networksecuritypolicyschedule/APICreateNetworkSecurityPolicyScheduleMsg.java +++ b/plugin/networkSecurityPolicySchedule/src/main/java/org/zstack/networksecuritypolicyschedule/APICreateNetworkSecurityPolicyScheduleMsg.java @@ -7,6 +7,7 @@ import org.zstack.header.rest.RestRequest; import org.zstack.header.vo.ResourceVO; +import java.util.Arrays; import java.util.List; @Action(category = NetworkSecurityPolicyScheduleConstant.ACTION_CATEGORY) @@ -20,7 +21,7 @@ public class APICreateNetworkSecurityPolicyScheduleMsg extends APIMessage { @APIParam(maxLength = 255, emptyString = false) private String name; - @APIParam(required = false, maxLength = 2048) + @APIParam(required = false, maxLength = 255) private String description; @APIParam(validValues = { @@ -140,4 +141,22 @@ public List getWeekDays() { public void setWeekDays(List weekDays) { this.weekDays = weekDays; } + + public static APICreateNetworkSecurityPolicyScheduleMsg __example__() { + APICreateNetworkSecurityPolicyScheduleMsg msg = + new APICreateNetworkSecurityPolicyScheduleMsg(); + msg.setName("office-hours"); + msg.setDescription("Weekday office hours"); + msg.setResourceType( + NetworkSecurityPolicyScheduleConstant.SECURITY_GROUP_RESOURCE_TYPE); + msg.setResourceUuid(uuid()); + msg.setTimeType("UTC"); + msg.setRepeatType("Weekly"); + msg.setStartDate("2026-01-01"); + msg.setEndDate("2026-12-31"); + msg.setStartTime("09:00"); + msg.setEndTime("18:00"); + msg.setWeekDays(Arrays.asList(1, 2, 3, 4, 5)); + return msg; + } } diff --git a/plugin/networkSecurityPolicySchedule/src/main/java/org/zstack/networksecuritypolicyschedule/APIDeleteNetworkSecurityPolicyScheduleEvent.java b/plugin/networkSecurityPolicySchedule/src/main/java/org/zstack/networksecuritypolicyschedule/APIDeleteNetworkSecurityPolicyScheduleEvent.java index c61e31fa001..0bce7d8b8ab 100644 --- a/plugin/networkSecurityPolicySchedule/src/main/java/org/zstack/networksecuritypolicyschedule/APIDeleteNetworkSecurityPolicyScheduleEvent.java +++ b/plugin/networkSecurityPolicySchedule/src/main/java/org/zstack/networksecuritypolicyschedule/APIDeleteNetworkSecurityPolicyScheduleEvent.java @@ -11,4 +11,8 @@ public APIDeleteNetworkSecurityPolicyScheduleEvent() { public APIDeleteNetworkSecurityPolicyScheduleEvent(String apiId) { super(apiId); } + + public static APIDeleteNetworkSecurityPolicyScheduleEvent __example__() { + return new APIDeleteNetworkSecurityPolicyScheduleEvent(); + } } diff --git a/plugin/networkSecurityPolicySchedule/src/main/java/org/zstack/networksecuritypolicyschedule/APIDeleteNetworkSecurityPolicyScheduleMsg.java b/plugin/networkSecurityPolicySchedule/src/main/java/org/zstack/networksecuritypolicyschedule/APIDeleteNetworkSecurityPolicyScheduleMsg.java index c06bff359af..9aa9ffcf932 100644 --- a/plugin/networkSecurityPolicySchedule/src/main/java/org/zstack/networksecuritypolicyschedule/APIDeleteNetworkSecurityPolicyScheduleMsg.java +++ b/plugin/networkSecurityPolicySchedule/src/main/java/org/zstack/networksecuritypolicyschedule/APIDeleteNetworkSecurityPolicyScheduleMsg.java @@ -26,4 +26,11 @@ public String getUuid() { public void setUuid(String uuid) { this.uuid = uuid; } + + public static APIDeleteNetworkSecurityPolicyScheduleMsg __example__() { + APIDeleteNetworkSecurityPolicyScheduleMsg msg = + new APIDeleteNetworkSecurityPolicyScheduleMsg(); + msg.setUuid(uuid()); + return msg; + } } diff --git a/plugin/networkSecurityPolicySchedule/src/main/java/org/zstack/networksecuritypolicyschedule/APIGetNetworkSecurityPolicyScheduleMsg.java b/plugin/networkSecurityPolicySchedule/src/main/java/org/zstack/networksecuritypolicyschedule/APIGetNetworkSecurityPolicyScheduleMsg.java index ba7e0a342b8..a6d0121dd04 100644 --- a/plugin/networkSecurityPolicySchedule/src/main/java/org/zstack/networksecuritypolicyschedule/APIGetNetworkSecurityPolicyScheduleMsg.java +++ b/plugin/networkSecurityPolicySchedule/src/main/java/org/zstack/networksecuritypolicyschedule/APIGetNetworkSecurityPolicyScheduleMsg.java @@ -24,4 +24,11 @@ public String getResourceUuid() { public void setResourceUuid(String resourceUuid) { this.resourceUuid = resourceUuid; } + + public static APIGetNetworkSecurityPolicyScheduleMsg __example__() { + APIGetNetworkSecurityPolicyScheduleMsg msg = + new APIGetNetworkSecurityPolicyScheduleMsg(); + msg.setResourceUuid(uuid()); + return msg; + } } diff --git a/plugin/networkSecurityPolicySchedule/src/main/java/org/zstack/networksecuritypolicyschedule/APIGetNetworkSecurityPolicyScheduleMsgDoc_zh_cn.groovy b/plugin/networkSecurityPolicySchedule/src/main/java/org/zstack/networksecuritypolicyschedule/APIGetNetworkSecurityPolicyScheduleMsgDoc_zh_cn.groovy index d73bfaab49c..a7dfed4fcfd 100644 --- a/plugin/networkSecurityPolicySchedule/src/main/java/org/zstack/networksecuritypolicyschedule/APIGetNetworkSecurityPolicyScheduleMsgDoc_zh_cn.groovy +++ b/plugin/networkSecurityPolicySchedule/src/main/java/org/zstack/networksecuritypolicyschedule/APIGetNetworkSecurityPolicyScheduleMsgDoc_zh_cn.groovy @@ -1,7 +1,6 @@ package org.zstack.networksecuritypolicyschedule import org.zstack.networksecuritypolicyschedule.APIGetNetworkSecurityPolicyScheduleReply -import org.zstack.header.message.APISyncCallMessage doc { title "GetNetworkSecurityPolicySchedule" @@ -18,9 +17,38 @@ doc { clz APIGetNetworkSecurityPolicyScheduleMsg.class - desc """null""" + desc """""" - params APISyncCallMessage.class + params { + + column { + name "resourceUuid" + enclosedIn "" + desc "资源UUID" + location "query" + type "String" + optional false + since "5.5.38" + } + column { + name "systemTags" + enclosedIn "" + desc "系统标签" + location "query" + type "List" + optional true + since "5.5.38" + } + column { + name "userTags" + enclosedIn "" + desc "用户标签" + location "query" + type "List" + optional true + since "5.5.38" + } + } } response { diff --git a/plugin/networkSecurityPolicySchedule/src/main/java/org/zstack/networksecuritypolicyschedule/APIGetNetworkSecurityPolicyScheduleReply.java b/plugin/networkSecurityPolicySchedule/src/main/java/org/zstack/networksecuritypolicyschedule/APIGetNetworkSecurityPolicyScheduleReply.java index ba9c80c04f0..f3e21a458e1 100644 --- a/plugin/networkSecurityPolicySchedule/src/main/java/org/zstack/networksecuritypolicyschedule/APIGetNetworkSecurityPolicyScheduleReply.java +++ b/plugin/networkSecurityPolicySchedule/src/main/java/org/zstack/networksecuritypolicyschedule/APIGetNetworkSecurityPolicyScheduleReply.java @@ -3,6 +3,7 @@ import org.zstack.header.message.APIReply; import org.zstack.header.rest.RestResponse; +import java.util.Collections; import java.util.List; @RestResponse(allTo = "inventories") @@ -16,4 +17,12 @@ public List getInventories() { public void setInventories(List inventories) { this.inventories = inventories; } + + public static APIGetNetworkSecurityPolicyScheduleReply __example__() { + APIGetNetworkSecurityPolicyScheduleReply reply = + new APIGetNetworkSecurityPolicyScheduleReply(); + reply.setInventories(Collections.singletonList( + NetworkSecurityPolicyScheduleInventory.__example__())); + return reply; + } } diff --git a/plugin/networkSecurityPolicySchedule/src/main/java/org/zstack/networksecuritypolicyschedule/APISetNetworkSecurityPolicyScheduleEvent.java b/plugin/networkSecurityPolicySchedule/src/main/java/org/zstack/networksecuritypolicyschedule/APISetNetworkSecurityPolicyScheduleEvent.java index 54ed1548e24..3b4c6f6ac06 100644 --- a/plugin/networkSecurityPolicySchedule/src/main/java/org/zstack/networksecuritypolicyschedule/APISetNetworkSecurityPolicyScheduleEvent.java +++ b/plugin/networkSecurityPolicySchedule/src/main/java/org/zstack/networksecuritypolicyschedule/APISetNetworkSecurityPolicyScheduleEvent.java @@ -11,4 +11,8 @@ public APISetNetworkSecurityPolicyScheduleEvent() { public APISetNetworkSecurityPolicyScheduleEvent(String apiId) { super(apiId); } + + public static APISetNetworkSecurityPolicyScheduleEvent __example__() { + return new APISetNetworkSecurityPolicyScheduleEvent(); + } } diff --git a/plugin/networkSecurityPolicySchedule/src/main/java/org/zstack/networksecuritypolicyschedule/APISetNetworkSecurityPolicyScheduleMsg.java b/plugin/networkSecurityPolicySchedule/src/main/java/org/zstack/networksecuritypolicyschedule/APISetNetworkSecurityPolicyScheduleMsg.java index ddf12a2d334..9c8e235aa3a 100644 --- a/plugin/networkSecurityPolicySchedule/src/main/java/org/zstack/networksecuritypolicyschedule/APISetNetworkSecurityPolicyScheduleMsg.java +++ b/plugin/networkSecurityPolicySchedule/src/main/java/org/zstack/networksecuritypolicyschedule/APISetNetworkSecurityPolicyScheduleMsg.java @@ -50,4 +50,14 @@ public String getResourceUuid() { public void setResourceUuid(String resourceUuid) { this.resourceUuid = resourceUuid; } + + public static APISetNetworkSecurityPolicyScheduleMsg __example__() { + APISetNetworkSecurityPolicyScheduleMsg msg = + new APISetNetworkSecurityPolicyScheduleMsg(); + msg.setScheduleUuid(uuid()); + msg.setResourceType( + NetworkSecurityPolicyScheduleConstant.SECURITY_GROUP_RESOURCE_TYPE); + msg.setResourceUuid(uuid()); + return msg; + } } diff --git a/plugin/networkSecurityPolicySchedule/src/main/java/org/zstack/networksecuritypolicyschedule/APIUpdateNetworkSecurityPolicyScheduleEvent.java b/plugin/networkSecurityPolicySchedule/src/main/java/org/zstack/networksecuritypolicyschedule/APIUpdateNetworkSecurityPolicyScheduleEvent.java index fdf1ad3e1f0..e2d569e2885 100644 --- a/plugin/networkSecurityPolicySchedule/src/main/java/org/zstack/networksecuritypolicyschedule/APIUpdateNetworkSecurityPolicyScheduleEvent.java +++ b/plugin/networkSecurityPolicySchedule/src/main/java/org/zstack/networksecuritypolicyschedule/APIUpdateNetworkSecurityPolicyScheduleEvent.java @@ -21,4 +21,11 @@ public NetworkSecurityPolicyScheduleInventory getInventory() { public void setInventory(NetworkSecurityPolicyScheduleInventory inventory) { this.inventory = inventory; } + + public static APIUpdateNetworkSecurityPolicyScheduleEvent __example__() { + APIUpdateNetworkSecurityPolicyScheduleEvent event = + new APIUpdateNetworkSecurityPolicyScheduleEvent(); + event.setInventory(NetworkSecurityPolicyScheduleInventory.__example__()); + return event; + } } diff --git a/plugin/networkSecurityPolicySchedule/src/main/java/org/zstack/networksecuritypolicyschedule/APIUpdateNetworkSecurityPolicyScheduleMsg.java b/plugin/networkSecurityPolicySchedule/src/main/java/org/zstack/networksecuritypolicyschedule/APIUpdateNetworkSecurityPolicyScheduleMsg.java index 332b2992c4f..12efd58a538 100644 --- a/plugin/networkSecurityPolicySchedule/src/main/java/org/zstack/networksecuritypolicyschedule/APIUpdateNetworkSecurityPolicyScheduleMsg.java +++ b/plugin/networkSecurityPolicySchedule/src/main/java/org/zstack/networksecuritypolicyschedule/APIUpdateNetworkSecurityPolicyScheduleMsg.java @@ -6,6 +6,7 @@ import org.zstack.header.message.APIParam; import org.zstack.header.rest.RestRequest; +import java.util.Arrays; import java.util.List; @Action(category = NetworkSecurityPolicyScheduleConstant.ACTION_CATEGORY) @@ -22,7 +23,7 @@ public class APIUpdateNetworkSecurityPolicyScheduleMsg extends APIMessage { @APIParam(maxLength = 255, emptyString = false) private String name; - @APIParam(required = false, maxLength = 2048) + @APIParam(required = false, maxLength = 255) private String description; @APIParam(validValues = {"Local", "UTC"}) @@ -126,4 +127,19 @@ public void setWeekDays(List weekDays) { this.weekDays = weekDays; } + public static APIUpdateNetworkSecurityPolicyScheduleMsg __example__() { + APIUpdateNetworkSecurityPolicyScheduleMsg msg = + new APIUpdateNetworkSecurityPolicyScheduleMsg(); + msg.setUuid(uuid()); + msg.setName("office-hours"); + msg.setDescription("Weekday office hours"); + msg.setTimeType("UTC"); + msg.setRepeatType("Weekly"); + msg.setStartDate("2026-01-01"); + msg.setEndDate("2026-12-31"); + msg.setStartTime("09:00"); + msg.setEndTime("18:00"); + msg.setWeekDays(Arrays.asList(1, 2, 3, 4, 5)); + return msg; + } } diff --git a/plugin/networkSecurityPolicySchedule/src/main/java/org/zstack/networksecuritypolicyschedule/NetworkSecurityPolicyScheduleApiInterceptor.java b/plugin/networkSecurityPolicySchedule/src/main/java/org/zstack/networksecuritypolicyschedule/NetworkSecurityPolicyScheduleApiInterceptor.java index 78c42babccb..63d05e37f56 100644 --- a/plugin/networkSecurityPolicySchedule/src/main/java/org/zstack/networksecuritypolicyschedule/NetworkSecurityPolicyScheduleApiInterceptor.java +++ b/plugin/networkSecurityPolicySchedule/src/main/java/org/zstack/networksecuritypolicyschedule/NetworkSecurityPolicyScheduleApiInterceptor.java @@ -18,7 +18,6 @@ import java.util.Collections; import java.util.HashSet; import java.util.List; -import java.util.Objects; import java.util.Set; import static org.zstack.core.Platform.argerr; @@ -138,18 +137,7 @@ private void validate(APISetNetworkSecurityPolicyScheduleMsg msg) { if (msg.getScheduleUuid() == null) { return; } - NetworkSecurityPolicyScheduleVO schedule = validateScheduleOwner( - msg.getScheduleUuid(), msg.getResourceType(), msg.getResourceUuid()); - if (!Objects.equals( - scheduleUuidOf(msg.getResourceType(), msg.getResourceUuid()), - msg.getScheduleUuid()) - && !NetworkSecurityPolicyScheduleTime.valueOf(schedule) - .hasRemainingSchedule(scheduleFacade.now())) { - throw new ApiMessageInterceptionException(argerr( - ORG_ZSTACK_NETWORKSECURITYPOLICYSCHEDULE_10007, - "network security policy schedule[uuid:%s] has no remaining active minute", - msg.getScheduleUuid())); - } + validateScheduleOwner(msg.getScheduleUuid(), msg.getResourceType(), msg.getResourceUuid()); } private NetworkSecurityPolicyScheduleTime validateTime( @@ -323,10 +311,6 @@ private void validateScheduleOwner(NetworkSecurityPolicyScheduleVO schedule, } } - private String scheduleUuidOf(String resourceType, String resourceUuid) { - return resourceBackend(resourceType).getScheduleUuid(resourceUuid); - } - private NetworkSecurityPolicyScheduleResourceBackend resourceBackend(String resourceType) { NetworkSecurityPolicyScheduleResourceBackend backend = backendRegistry.getBackend(resourceType); if (backend == null) { diff --git a/plugin/networkSecurityPolicySchedule/src/main/java/org/zstack/networksecuritypolicyschedule/NetworkSecurityPolicyScheduleInventory.java b/plugin/networkSecurityPolicySchedule/src/main/java/org/zstack/networksecuritypolicyschedule/NetworkSecurityPolicyScheduleInventory.java index 8e7c3c52a0b..d123420942a 100644 --- a/plugin/networkSecurityPolicySchedule/src/main/java/org/zstack/networksecuritypolicyschedule/NetworkSecurityPolicyScheduleInventory.java +++ b/plugin/networkSecurityPolicySchedule/src/main/java/org/zstack/networksecuritypolicyschedule/NetworkSecurityPolicyScheduleInventory.java @@ -25,6 +25,7 @@ public class NetworkSecurityPolicyScheduleInventory { private String startTime; private String endTime; private List weekDays; + private boolean effective; private boolean expired; private Timestamp createDate; private Timestamp lastOpDate; @@ -33,6 +34,29 @@ public static NetworkSecurityPolicyScheduleInventory valueOf(NetworkSecurityPoli return valueOf(vo, Instant.now()); } + public static NetworkSecurityPolicyScheduleInventory __example__() { + NetworkSecurityPolicyScheduleInventory inventory = + new NetworkSecurityPolicyScheduleInventory(); + inventory.setUuid("4c4aa4f9b7254d76b48ad99f6a20c9ee"); + inventory.setName("office-hours"); + inventory.setDescription("Weekday office hours"); + inventory.setResourceType( + NetworkSecurityPolicyScheduleConstant.SECURITY_GROUP_RESOURCE_TYPE); + inventory.setResourceUuid("f1a72f89f9624c92a84cbd07347be003"); + inventory.setTimeType("UTC"); + inventory.setRepeatType("Weekly"); + inventory.setStartDate("2026-01-01"); + inventory.setEndDate("2026-12-31"); + inventory.setStartTime("09:00"); + inventory.setEndTime("18:00"); + inventory.setWeekDays(Arrays.asList(1, 2, 3, 4, 5)); + inventory.setEffective(true); + inventory.setExpired(false); + inventory.setCreateDate(Timestamp.valueOf("2026-01-01 00:00:00")); + inventory.setLastOpDate(Timestamp.valueOf("2026-01-01 00:00:00")); + return inventory; + } + public static NetworkSecurityPolicyScheduleInventory valueOf(NetworkSecurityPolicyScheduleVO vo, Instant now) { NetworkSecurityPolicyScheduleInventory inventory = new NetworkSecurityPolicyScheduleInventory(); inventory.uuid = vo.getUuid(); @@ -49,7 +73,9 @@ public static NetworkSecurityPolicyScheduleInventory valueOf(NetworkSecurityPoli inventory.endTime = vo.getEndTime().toLocalTime() .truncatedTo(ChronoUnit.MINUTES).toString(); inventory.weekDays = toWeekDays(vo.getWeekDays()); - inventory.expired = !NetworkSecurityPolicyScheduleTime.valueOf(vo).hasRemainingSchedule(now); + NetworkSecurityPolicyScheduleTime time = NetworkSecurityPolicyScheduleTime.valueOf(vo); + inventory.effective = time.isInSchedule(now); + inventory.expired = !time.hasRemainingSchedule(now); inventory.createDate = vo.getCreateDate(); inventory.lastOpDate = vo.getLastOpDate(); return inventory; @@ -175,6 +201,14 @@ public void setWeekDays(List weekDays) { this.weekDays = weekDays; } + public boolean isEffective() { + return effective; + } + + public void setEffective(boolean effective) { + this.effective = effective; + } + public boolean isExpired() { return expired; } diff --git a/plugin/networkSecurityPolicySchedule/src/main/java/org/zstack/networksecuritypolicyschedule/NetworkSecurityPolicyScheduleInventoryDoc_zh_cn.groovy b/plugin/networkSecurityPolicySchedule/src/main/java/org/zstack/networksecuritypolicyschedule/NetworkSecurityPolicyScheduleInventoryDoc_zh_cn.groovy index 74e1889a58c..e1922a9faf6 100644 --- a/plugin/networkSecurityPolicySchedule/src/main/java/org/zstack/networksecuritypolicyschedule/NetworkSecurityPolicyScheduleInventoryDoc_zh_cn.groovy +++ b/plugin/networkSecurityPolicySchedule/src/main/java/org/zstack/networksecuritypolicyschedule/NetworkSecurityPolicyScheduleInventoryDoc_zh_cn.groovy @@ -77,6 +77,12 @@ doc { type "List" since "5.5.38" } + field { + name "effective" + desc "当前分钟是否处于生效时间段" + type "boolean" + since "5.5.38" + } field { name "expired" desc "从当前分钟起是否已不存在未来生效时间" diff --git a/plugin/networkSecurityPolicySchedule/src/main/java/org/zstack/networksecuritypolicyschedule/NetworkSecurityPolicyScheduleManagerImpl.java b/plugin/networkSecurityPolicySchedule/src/main/java/org/zstack/networksecuritypolicyschedule/NetworkSecurityPolicyScheduleManagerImpl.java index 03d08228d9f..ce038322811 100644 --- a/plugin/networkSecurityPolicySchedule/src/main/java/org/zstack/networksecuritypolicyschedule/NetworkSecurityPolicyScheduleManagerImpl.java +++ b/plugin/networkSecurityPolicySchedule/src/main/java/org/zstack/networksecuritypolicyschedule/NetworkSecurityPolicyScheduleManagerImpl.java @@ -45,7 +45,6 @@ import static org.zstack.core.Platform.err; import static org.zstack.core.Platform.operr; import static org.zstack.utils.clouderrorcode.CloudOperationsErrorCode.ORG_ZSTACK_NETWORKSECURITYPOLICYSCHEDULE_10006; -import static org.zstack.utils.clouderrorcode.CloudOperationsErrorCode.ORG_ZSTACK_NETWORKSECURITYPOLICYSCHEDULE_10007; import static org.zstack.utils.clouderrorcode.CloudOperationsErrorCode.ORG_ZSTACK_NETWORKSECURITYPOLICYSCHEDULE_10010; import static org.zstack.utils.clouderrorcode.CloudOperationsErrorCode.ORG_ZSTACK_NETWORKSECURITYPOLICYSCHEDULE_10011; @@ -347,14 +346,6 @@ public void run(FlowTrigger trigger, Map data) { msg.getResourceType(), msg.getResourceUuid())); return; } - if (!NetworkSecurityPolicyScheduleTime.valueOf(vo) - .hasRemainingSchedule(scheduleFacade.now())) { - trigger.fail(argerr( - ORG_ZSTACK_NETWORKSECURITYPOLICYSCHEDULE_10007, - "network security policy schedule[uuid:%s] has no remaining active minute", - msg.getScheduleUuid())); - return; - } trigger.next(); } }); diff --git a/plugin/networkSecurityPolicySchedule/src/main/java/org/zstack/networksecuritypolicyschedule/NetworkSecurityPolicyScheduleVO.java b/plugin/networkSecurityPolicySchedule/src/main/java/org/zstack/networksecuritypolicyschedule/NetworkSecurityPolicyScheduleVO.java index cd9692a438d..fbe9d4b256c 100644 --- a/plugin/networkSecurityPolicySchedule/src/main/java/org/zstack/networksecuritypolicyschedule/NetworkSecurityPolicyScheduleVO.java +++ b/plugin/networkSecurityPolicySchedule/src/main/java/org/zstack/networksecuritypolicyschedule/NetworkSecurityPolicyScheduleVO.java @@ -24,7 +24,7 @@ public class NetworkSecurityPolicyScheduleVO { @Column private String name; - @Column(length = 2048) + @Column private String description; @Column diff --git a/sdk/src/main/java/org/zstack/sdk/CreateNetworkSecurityPolicyScheduleAction.java b/sdk/src/main/java/org/zstack/sdk/CreateNetworkSecurityPolicyScheduleAction.java index cdaf6aecd19..5f47a8dfc9c 100644 --- a/sdk/src/main/java/org/zstack/sdk/CreateNetworkSecurityPolicyScheduleAction.java +++ b/sdk/src/main/java/org/zstack/sdk/CreateNetworkSecurityPolicyScheduleAction.java @@ -28,7 +28,7 @@ public Result throwExceptionIfError() { @Param(required = true, maxLength = 255, nonempty = false, nullElements = false, emptyString = false, noTrim = false) public java.lang.String name; - @Param(required = false, maxLength = 2048, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + @Param(required = false, maxLength = 255, nonempty = false, nullElements = false, emptyString = true, noTrim = false) public java.lang.String description; @Param(required = true, validValues = {"SecurityGroup","VpcFirewallRuleSet"}, nonempty = false, nullElements = false, emptyString = true, noTrim = false) diff --git a/sdk/src/main/java/org/zstack/sdk/NetworkSecurityPolicyScheduleInventory.java b/sdk/src/main/java/org/zstack/sdk/NetworkSecurityPolicyScheduleInventory.java index d08aaba1cc9..eb2d8300a11 100644 --- a/sdk/src/main/java/org/zstack/sdk/NetworkSecurityPolicyScheduleInventory.java +++ b/sdk/src/main/java/org/zstack/sdk/NetworkSecurityPolicyScheduleInventory.java @@ -100,6 +100,14 @@ public java.util.List getWeekDays() { return this.weekDays; } + public boolean effective; + public void setEffective(boolean effective) { + this.effective = effective; + } + public boolean getEffective() { + return this.effective; + } + public boolean expired; public void setExpired(boolean expired) { this.expired = expired; diff --git a/sdk/src/main/java/org/zstack/sdk/UpdateNetworkSecurityPolicyScheduleAction.java b/sdk/src/main/java/org/zstack/sdk/UpdateNetworkSecurityPolicyScheduleAction.java index 427c85e0463..1a496ed9075 100644 --- a/sdk/src/main/java/org/zstack/sdk/UpdateNetworkSecurityPolicyScheduleAction.java +++ b/sdk/src/main/java/org/zstack/sdk/UpdateNetworkSecurityPolicyScheduleAction.java @@ -31,7 +31,7 @@ public Result throwExceptionIfError() { @Param(required = true, maxLength = 255, nonempty = false, nullElements = false, emptyString = false, noTrim = false) public java.lang.String name; - @Param(required = false, maxLength = 2048, nonempty = false, nullElements = false, emptyString = true, noTrim = false) + @Param(required = false, maxLength = 255, nonempty = false, nullElements = false, emptyString = true, noTrim = false) public java.lang.String description; @Param(required = true, validValues = {"Local","UTC"}, nonempty = false, nullElements = false, emptyString = true, noTrim = false) diff --git a/test/src/test/groovy/org/zstack/test/integration/networksecuritypolicyschedule/NetworkSecurityPolicyScheduleApiCase.groovy b/test/src/test/groovy/org/zstack/test/integration/networksecuritypolicyschedule/NetworkSecurityPolicyScheduleApiCase.groovy index aa777bca57c..bb276d538de 100644 --- a/test/src/test/groovy/org/zstack/test/integration/networksecuritypolicyschedule/NetworkSecurityPolicyScheduleApiCase.groovy +++ b/test/src/test/groovy/org/zstack/test/integration/networksecuritypolicyschedule/NetworkSecurityPolicyScheduleApiCase.groovy @@ -75,6 +75,7 @@ class NetworkSecurityPolicyScheduleApiCase extends SubCase { String resourceType, String resourceUuid, Map overrides = [:], String sessionId = null) { Map fields = [ name: "office-hours", + description: null, resourceType: resourceType, resourceUuid: resourceUuid, timeType: "UTC", @@ -88,6 +89,7 @@ class NetworkSecurityPolicyScheduleApiCase extends SubCase { fields.putAll(overrides) return new CreateNetworkSecurityPolicyScheduleAction( name: fields.name, + description: fields.description, resourceType: fields.resourceType, resourceUuid: fields.resourceUuid, timeType: fields.timeType, @@ -216,7 +218,9 @@ class NetworkSecurityPolicyScheduleApiCase extends SubCase { weekDays = [3] } as NetworkSecurityPolicyScheduleInventory - assert !upcoming.expired && !active.expired && !laterWeekly.expired + assert !upcoming.effective && !upcoming.expired : "upcoming status mismatch" + assert active.effective && !active.expired : "active status mismatch" + assert !laterWeekly.effective && !laterWeekly.expired : "later weekly status mismatch" NetworkSecurityPolicyScheduleInventory expired = updateNetworkSecurityPolicySchedule { uuid = upcoming.uuid @@ -228,21 +232,25 @@ class NetworkSecurityPolicyScheduleApiCase extends SubCase { startTime = "06:00" endTime = "07:00" } as NetworkSecurityPolicyScheduleInventory - assert expired.expired + assert !expired.effective && expired.expired : "expired status mismatch" Map queried = getSchedules(securityGroup.uuid).collectEntries { [(it.uuid): it] } - assert queried[upcoming.uuid].expired && - !queried[active.uuid].expired && - !queried[laterWeekly.uuid].expired + assert !queried[upcoming.uuid].effective && queried[upcoming.uuid].expired : + "queried expired status mismatch" + assert queried[active.uuid].effective && !queried[active.uuid].expired : + "queried active status mismatch" + assert !queried[laterWeekly.uuid].effective && !queried[laterWeekly.uuid].expired : + "queried future status mismatch" scheduleFacade.setClock(Clock.fixed( Instant.parse("2026-08-06T00:00:00Z"), ZoneOffset.UTC)) List allExpired = getSchedules(securityGroup.uuid) - assert allExpired.size() == 3 && allExpired.every { it.expired } + assert allExpired.size() == 3 && allExpired.every { it.expired && !it.effective } : + "all schedules should be expired and ineffective" scheduleFacade.setClock(Clock.fixed( Instant.parse("2026-07-29T08:00:00Z"), ZoneOffset.UTC)) @@ -448,8 +456,33 @@ class NetworkSecurityPolicyScheduleApiCase extends SubCase { unsetSchedule(securityGroup.uuid) SetNetworkSecurityPolicyScheduleAction.Result expiredSet = setScheduleResult( schedule.uuid, "SecurityGroup", securityGroup.uuid) - assert expiredSet.error != null && - scheduleUuidOf(securityGroup.uuid) == null + assert expiredSet.error == null && scheduleUuidOf(securityGroup.uuid) == schedule.uuid : + "expired schedule should remain bindable" + unsetSchedule(securityGroup.uuid) + } + + void testDescriptionLength() { + SecurityGroupInventory securityGroup = createSecurityGroup { + name = "schedule-description-length-sg" + ipVersion = 4 + } as SecurityGroupInventory + String accepted = "a" * 255 + + CreateNetworkSecurityPolicyScheduleAction.Result created = createScheduleResult( + "SecurityGroup", securityGroup.uuid, [description: accepted]) + assert created.error == null && created.value.inventory.description == accepted : + "255-character description should be accepted" + + expect(ApiException.class) { + createScheduleResult("SecurityGroup", securityGroup.uuid, [description: "a" * 256]) + } + expect(ApiException.class) { + updateScheduleResult(created.value.inventory, [description: "a" * 256]) + } + + deleteNetworkSecurityPolicySchedule { + uuid = created.value.inventory.uuid + } } void testMultipleSchedulesPerResource() { @@ -651,6 +684,7 @@ class NetworkSecurityPolicyScheduleApiCase extends SubCase { testExpiredStatus() testSecurityGroupScheduleLifecycle() testCreateApiValidation() + testDescriptionLength() testRejectUninstalledResourceBackend() testUpdateApiValidation() testMultipleSchedulesPerResource() diff --git a/test/src/test/groovy/org/zstack/test/integration/networksecuritypolicyschedule/SecurityGroupScheduledActivationCase.groovy b/test/src/test/groovy/org/zstack/test/integration/networksecuritypolicyschedule/SecurityGroupScheduledActivationCase.groovy index b65eaa3aee1..565f93cd5b2 100644 --- a/test/src/test/groovy/org/zstack/test/integration/networksecuritypolicyschedule/SecurityGroupScheduledActivationCase.groovy +++ b/test/src/test/groovy/org/zstack/test/integration/networksecuritypolicyschedule/SecurityGroupScheduledActivationCase.groovy @@ -1069,6 +1069,71 @@ class SecurityGroupScheduledActivationCase extends SubCase { } } + void testBindExpiredSchedule() { + scanTask.stop() + scheduleFacade.setClock(Clock.fixed( + Instant.parse("2026-07-30T08:00:00Z"), ZoneOffset.UTC)) + L3NetworkInventory l3 = env.inventoryByName("l3") as L3NetworkInventory + VmInstanceInventory vm = env.inventoryByName("vm3") as VmInstanceInventory + String existingPort = "16600" + String addedPort = "16601" + SecurityGroupInventory securityGroup = createSecurityGroupWithRule( + "expired-schedule-security-group", existingPort, l3) + List commands = + recordVmNicRuleCommands([vm.vmNics[0].uuid]) + addVmNicsAndWaitForRuleApply( + securityGroup.uuid, [vm.vmNics[0].uuid], commands, 1) + + NetworkSecurityPolicyScheduleInventory schedule = createNetworkSecurityPolicySchedule { + name = "expired-security-group-schedule" + resourceType = "SecurityGroup" + resourceUuid = securityGroup.uuid + timeType = "UTC" + repeatType = "Once" + startDate = "2026-07-30" + endDate = "2026-07-30" + startTime = "09:00" + endTime = "10:00" + } as NetworkSecurityPolicyScheduleInventory + + commands.clear() + scheduleFacade.setClock(Clock.fixed( + Instant.parse("2026-07-30T10:00:00Z"), ZoneOffset.UTC)) + setSchedule(schedule, securityGroup.uuid) + retryInSecs { + assert commands.size() == 1 : "expired bind refresh count: ${commands.size()}" + assert !containsRule(commands.last(), securityGroup.uuid, existingPort) : + "expired bind retained port ${existingPort}" + } + + commands.clear() + addSecurityGroupRule { + securityGroupUuid = securityGroup.uuid + delegate.rules = [new SecurityGroupRuleAO( + type: "Ingress", + ipVersion: 4, + protocol: "TCP", + dstPortRange: addedPort, + srcIpRange: "10.0.0.0/24", + state: "Enabled" + )] + } + retryInSecs { + assert commands.size() == 1 : "expired rule refresh count: ${commands.size()}" + assert !containsRule(commands.last(), securityGroup.uuid, existingPort) : + "expired schedule restored port ${existingPort}" + assert !containsRule(commands.last(), securityGroup.uuid, addedPort) : + "expired schedule enabled port ${addedPort}" + } + + deleteNetworkSecurityPolicySchedule { + uuid = schedule.uuid + } + deleteSecurityGroup { + uuid = securityGroup.uuid + } + } + @Override void test() { env.create { @@ -1085,6 +1150,7 @@ class SecurityGroupScheduledActivationCase extends SubCase { testConcurrentStateChange() testHostRefreshFailure() testSdnRuleCalculation() + testBindExpiredSchedule() } } } diff --git a/testlib/src/main/java/org/zstack/testlib/ApiHelper.groovy b/testlib/src/main/java/org/zstack/testlib/ApiHelper.groovy index 2ce3a3b8d54..37468fde7ea 100644 --- a/testlib/src/main/java/org/zstack/testlib/ApiHelper.groovy +++ b/testlib/src/main/java/org/zstack/testlib/ApiHelper.groovy @@ -21,20 +21,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -10715,20 +10715,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -16250,20 +16250,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -24485,20 +24485,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -24539,20 +24539,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -40830,20 +40830,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -47121,20 +47121,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -47337,20 +47337,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -48687,7 +48687,7 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { @@ -52177,20 +52177,20 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + if (System.getProperty("apipath") != null) { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call()) @@ -56370,7 +56370,7 @@ abstract class ApiHelper { c.resolveStrategy = Closure.OWNER_FIRST c.delegate = a c() - + a.conditions = a.conditions.collect { it.toString() } @@ -56378,14 +56378,14 @@ abstract class ApiHelper { if (a.apiId == null) { a.apiId = Platform.uuid } - + def tracker = new ApiPathTracker(a.apiId) def out = errorOut(a.call()) def path = tracker.getApiPath() if (!path.isEmpty()) { Test.apiPaths[a.class.name] = path.join(" --->\n") } - + return out } else { return errorOut(a.call())