-
Notifications
You must be signed in to change notification settings - Fork 0
<feature>[vm]: optimize the statistics method of OS running time on virtual machines #4096
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: zsv_5.1.0
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,90 @@ | ||
| package org.zstack.compute.vm; | ||
|
|
||
| import org.apache.commons.lang.StringUtils; | ||
| import org.zstack.core.db.Q; | ||
| import org.zstack.core.db.SQL; | ||
| import org.zstack.header.vm.VmInstanceState; | ||
| import org.zstack.header.vm.VmInstanceVO; | ||
| import org.zstack.header.vm.VmInstanceVO_; | ||
|
|
||
| import java.sql.Timestamp; | ||
| import java.time.LocalDateTime; | ||
| import java.time.format.DateTimeFormatter; | ||
| import java.time.format.DateTimeParseException; | ||
|
|
||
| public class VmBootTimeUtils { | ||
| public static final String STOPPED_UPTIME = "0"; | ||
| public static final String UNKNOWN_UPTIME = ""; | ||
| private static final DateTimeFormatter BOOT_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); | ||
|
|
||
| public static boolean isBootTimeValidState(VmInstanceState state) { | ||
| return state != null && state != VmInstanceState.Stopped && state != VmInstanceState.Destroyed; | ||
| } | ||
|
|
||
| public String getBootTime(String vmUuid) { | ||
| if (StringUtils.isBlank(vmUuid)) { | ||
| return null; | ||
| } | ||
|
|
||
| Timestamp bootTime = Q.New(VmInstanceVO.class) | ||
| .select(VmInstanceVO_.bootTime) | ||
| .eq(VmInstanceVO_.uuid, vmUuid) | ||
| .findValue(); | ||
| return formatBootTime(bootTime); | ||
| } | ||
|
|
||
| public void resetBootTime(String vmUuid) { | ||
| if (StringUtils.isBlank(vmUuid)) { | ||
| return; | ||
| } | ||
|
|
||
| SQL.New(VmInstanceVO.class) | ||
| .eq(VmInstanceVO_.uuid, vmUuid) | ||
| .set(VmInstanceVO_.bootTime, Timestamp.valueOf(LocalDateTime.now())) | ||
| .update(); | ||
| } | ||
|
|
||
| public void clearBootTime(String vmUuid) { | ||
| if (StringUtils.isBlank(vmUuid)) { | ||
| return; | ||
| } | ||
|
|
||
| SQL.New(VmInstanceVO.class) | ||
| .eq(VmInstanceVO_.uuid, vmUuid) | ||
| .set(VmInstanceVO_.bootTime, (Timestamp) null) | ||
| .update(); | ||
| } | ||
|
|
||
| public void backfillBootTimeIfMissing(String vmUuid, String hostUptime) { | ||
| Timestamp bootTime = parseBootTime(hostUptime); | ||
| if (StringUtils.isBlank(vmUuid) || bootTime == null) { | ||
| return; | ||
| } | ||
|
|
||
| SQL.New(VmInstanceVO.class) | ||
| .eq(VmInstanceVO_.uuid, vmUuid) | ||
| .isNull(VmInstanceVO_.bootTime) | ||
| .set(VmInstanceVO_.bootTime, bootTime) | ||
| .update(); | ||
| } | ||
|
|
||
| private static String formatBootTime(Timestamp bootTime) { | ||
| if (bootTime == null) { | ||
| return null; | ||
| } | ||
|
|
||
| return bootTime.toLocalDateTime().format(BOOT_TIME_FORMATTER); | ||
| } | ||
|
|
||
| private static Timestamp parseBootTime(String bootTime) { | ||
| if (StringUtils.isBlank(bootTime)) { | ||
| return null; | ||
| } | ||
|
|
||
| try { | ||
| return Timestamp.valueOf(LocalDateTime.parse(bootTime, BOOT_TIME_FORMATTER)); | ||
| } catch (DateTimeParseException ignored) { | ||
| return null; | ||
| } | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -151,6 +151,7 @@ public class VmInstanceBase extends AbstractVmInstance { | |
| protected String syncThreadName; | ||
| private final static StaticIpOperator ipOperator = new StaticIpOperator(); | ||
| private final static VmConfigSyncHelper vmConfigSyncHelper = new VmConfigSyncHelper(); | ||
| private final static VmBootTimeUtils vmBootTimeUtils = new VmBootTimeUtils(); | ||
|
|
||
| private void detachTpmKeyProviderBestEffort(String tpmUuid) { | ||
| if (tpmUuid == null) { | ||
|
|
@@ -381,6 +382,7 @@ protected void scripts() { | |
| } | ||
|
|
||
| self.setState(state); | ||
| self.setBootTime(getBootTimeAfterStateChanged(bs, state, getCurrentBootTimeForStateChange())); | ||
| self = merge(self); | ||
| } | ||
| }; | ||
|
|
@@ -419,6 +421,35 @@ public void run(VmStateChangedExtensionPoint ext) { | |
| return self; | ||
| } | ||
|
|
||
| private Timestamp getCurrentBootTimeForStateChange() { | ||
| if (self.getBootTime() != null) { | ||
| return self.getBootTime(); | ||
| } | ||
|
|
||
| return Q.New(VmInstanceVO.class) | ||
| .select(VmInstanceVO_.bootTime) | ||
| .eq(VmInstanceVO_.uuid, self.getUuid()) | ||
| .findValue(); | ||
| } | ||
|
|
||
| private Timestamp getBootTimeAfterStateChanged(VmInstanceState oldState, VmInstanceState newState, Timestamp currentBootTime) { | ||
| if (!VmBootTimeUtils.isBootTimeValidState(newState)) { | ||
| return null; | ||
| } | ||
|
|
||
| if (newState != VmInstanceState.Running) { | ||
| return currentBootTime; | ||
| } | ||
|
|
||
| if (oldState == VmInstanceState.Starting | ||
| || oldState == VmInstanceState.Rebooting | ||
| || (oldState == VmInstanceState.Resuming && currentBootTime == null)) { | ||
| return Timestamp.valueOf(LocalDateTime.now()); | ||
| } | ||
|
|
||
| return currentBootTime; | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
| } | ||
|
|
||
| @Override | ||
| @MessageSafe | ||
| public void handleMessage(final Message msg) { | ||
|
|
@@ -3724,6 +3755,13 @@ public void done(ErrorCodeList errorCodeList) { | |
| private void handle(APIGetVmUptimeMsg msg) { | ||
| APIGetVmUptimeReply reply = new APIGetVmUptimeReply(); | ||
|
|
||
| String uptime = StringUtils.defaultString(vmBootTimeUtils.getBootTime(self.getUuid()), VmBootTimeUtils.UNKNOWN_UPTIME); | ||
| if (StringUtils.isNotEmpty(uptime)) { | ||
| reply.setUptime(uptime); | ||
| bus.reply(msg, reply); | ||
| return; | ||
| } | ||
|
|
||
| GetVmUptimeMsg gmsg = new GetVmUptimeMsg(); | ||
| gmsg.setVmInstanceUuid(self.getUuid()); | ||
| gmsg.setHostUuid(self.getHostUuid()); | ||
|
|
@@ -3732,12 +3770,12 @@ private void handle(APIGetVmUptimeMsg msg) { | |
| bus.send(gmsg, new CloudBusCallBack(msg) { | ||
| @Override | ||
| public void run(MessageReply r) { | ||
| if (!r.isSuccess()) { | ||
| reply.setSuccess(false); | ||
| reply.setError(r.getError()); | ||
| } else { | ||
| if (r.isSuccess()) { | ||
| GetVmUptimeReply re = (GetVmUptimeReply) r; | ||
| reply.setUptime(re.getUptime()); | ||
| vmBootTimeUtils.backfillBootTimeIfMissing(self.getUuid(), re.getUptime()); | ||
| reply.setUptime(StringUtils.defaultString(vmBootTimeUtils.getBootTime(self.getUuid()), VmBootTimeUtils.UNKNOWN_UPTIME)); | ||
|
Comment on lines
3758
to
+3776
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
这里两条成功路径最终都执行 🤖 Prompt for AI Agents
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Comment from taiyue.chen: 这边upTime实际返回就是bootTime,没有问题。 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
🐰🤔 ✏️ Learnings added
🧠 Learnings used |
||
| } else { | ||
| reply.setUptime(VmBootTimeUtils.UNKNOWN_UPTIME); | ||
| } | ||
| bus.reply(msg, reply); | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -36,3 +36,37 @@ SET src.`type` = IF(ldap.serverType IN ('OpenLdap', 'WindowsAD'), ldap.serverTyp | |
| WHERE src.`type` = 'ldap'; | ||
|
|
||
| CALL INSERT_COLUMN('ThirdPartyAccountSourceVO', 'updateAccountStrategies', 'varchar(255)', 0, '', 'createAccountStrategy'); | ||
|
|
||
| -- Feature: VM boot time | ZSV-12297 | ||
|
|
||
| CALL INSERT_COLUMN('VmInstanceEO', 'bootTime', 'timestamp NULL', 1, NULL, 'state'); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 补齐升级场景的历史数据回填策略。 Line 42 仅新增了可空 As per coding guidelines “Upgrading scene has been carefully handled”. 🤖 Prompt for AI Agents
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Comment from taiyue.chen: 这个会在后面兜底时,自动去各个机器上查询其状态进行回填。所以,这边无需这么操作。 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
确认代码中存在兜底路径:当 需要注意的是,这是按需(request-triggered)的惰性回填,而非升级时的主动回填:
如果产品侧和 UI 侧对这个"首次查询延迟"行为可接受,则当前方案是合理的。 |
||
|
|
||
| CREATE OR REPLACE VIEW `zstack`.`VmInstanceVO` AS | ||
| SELECT uuid, | ||
| name, | ||
| description, | ||
| zoneUuid, | ||
| clusterUuid, | ||
| imageUuid, | ||
| hostUuid, | ||
| internalId, | ||
| lastHostUuid, | ||
| instanceOfferingUuid, | ||
| rootVolumeUuid, | ||
| defaultL3NetworkUuid, | ||
| type, | ||
| hypervisorType, | ||
| cpuNum, | ||
| cpuSpeed, | ||
| memorySize, | ||
| reservedMemorySize, | ||
| platform, | ||
| guestOsType, | ||
| allocatorStrategy, | ||
| createDate, | ||
| lastOpDate, | ||
| state, | ||
| architecture, | ||
| bootTime | ||
| FROM `zstack`.`VmInstanceEO` | ||
| WHERE deleted IS NULL; | ||
Uh oh!
There was an error while loading. Please reload this page.