From 241090b39a4988e735b8cfc3a5fbca92db55f528 Mon Sep 17 00:00:00 2001 From: "ye.zou" Date: Tue, 10 Mar 2026 15:28:42 +0800 Subject: [PATCH 1/2] [longjob]: standardize LongJob progress detail format Add LongJobProgressDetail POJO and LongJobProgressDetailBuilder to normalize opaque progress data into unified typed structure. Three opaque formats parsed: VM migration, AI download, unknown. DB schema unchanged. Agent-side migration deferred to Phase 2. Resolves: ZSTAC-82318 Change-Id: I70d60ff5e6c8f659f55770e2fbbe56781b238fd5 --- .../core/progress/ProgressReportService.java | 3 + .../progress/APIGetTaskProgressReply.java | 12 + .../core/progress/LongJobProgressDetail.java | 135 ++++++++++ .../LongJobProgressDetailBuilder.java | 249 ++++++++++++++++++ .../core/progress/TaskProgressInventory.java | 10 + .../LongJobProgressNotificationMessage.java | 14 + .../org/zstack/sdk/LongJobProgressDetail.java | 95 +++++++ .../org/zstack/sdk/TaskProgressInventory.java | 8 + 8 files changed, 526 insertions(+) create mode 100644 header/src/main/java/org/zstack/header/core/progress/LongJobProgressDetail.java create mode 100644 header/src/main/java/org/zstack/header/core/progress/LongJobProgressDetailBuilder.java create mode 100644 sdk/src/main/java/org/zstack/sdk/LongJobProgressDetail.java diff --git a/core/src/main/java/org/zstack/core/progress/ProgressReportService.java b/core/src/main/java/org/zstack/core/progress/ProgressReportService.java index bab9acc163a..dc9d93ea241 100755 --- a/core/src/main/java/org/zstack/core/progress/ProgressReportService.java +++ b/core/src/main/java/org/zstack/core/progress/ProgressReportService.java @@ -225,6 +225,9 @@ private TaskProgressInventory inventory(TaskProgressVO vo) { if (!StringUtils.isEmpty(vo.getArguments())) { inv.setArguments(vo.getArguments()); } + + inv.setProgressDetail(LongJobProgressDetailBuilder.fromTaskProgressVO(vo)); + return inv; } diff --git a/header/src/main/java/org/zstack/header/core/progress/APIGetTaskProgressReply.java b/header/src/main/java/org/zstack/header/core/progress/APIGetTaskProgressReply.java index 44e27d0b8e3..880e8cda1a8 100755 --- a/header/src/main/java/org/zstack/header/core/progress/APIGetTaskProgressReply.java +++ b/header/src/main/java/org/zstack/header/core/progress/APIGetTaskProgressReply.java @@ -6,6 +6,7 @@ import java.util.List; import static java.util.Arrays.asList; + /** * Created by xing5 on 2017/3/21. */ @@ -29,6 +30,17 @@ public static APIGetTaskProgressReply __example__() { inv.setTaskUuid("931102503f64436ea649939ff3957406"); inv.setTime(DocUtils.date); inv.setType("Task"); + + LongJobProgressDetail detail = new LongJobProgressDetail(); + detail.setPercent(42); + detail.setStage("downloading"); + detail.setState("running"); + detail.setProcessedBytes(440401920L); + detail.setTotalBytes(1073741824L); + detail.setSpeedBytesPerSecond(10485760L); + detail.setEstimatedRemainingSeconds(60L); + inv.setProgressDetail(detail); + msg.setInventories(asList(inv)); return msg; } diff --git a/header/src/main/java/org/zstack/header/core/progress/LongJobProgressDetail.java b/header/src/main/java/org/zstack/header/core/progress/LongJobProgressDetail.java new file mode 100644 index 00000000000..d27dc05cc4c --- /dev/null +++ b/header/src/main/java/org/zstack/header/core/progress/LongJobProgressDetail.java @@ -0,0 +1,135 @@ +package org.zstack.header.core.progress; + +import java.util.Map; + +/** + * Standardized LongJob progress detail, parsed from TaskProgressVO.opaque. + * + * All fields are optional (nullable). Callers should null-check before use. + * This is a pure read-only view — the database schema (TaskProgressVO) is unchanged. + */ +public class LongJobProgressDetail { + /** Progress percentage 0-100, if known. */ + private Integer percent; + + /** Human-readable stage label, e.g. "downloading", "extracting". */ + private String stage; + + /** State identifier, e.g. "running", "paused". */ + private String state; + + /** Human-readable reason for current state. */ + private String stateReason; + + /** Bytes already processed. */ + private Long processedBytes; + + /** Total bytes to process. */ + private Long totalBytes; + + /** Items already processed (e.g. files, chunks). */ + private Long processedItems; + + /** Total items to process. */ + private Long totalItems; + + /** Transfer speed in bytes/s. */ + private Long speedBytesPerSecond; + + /** Estimated remaining time in seconds. */ + private Long estimatedRemainingSeconds; + + /** + * Catch-all for any opaque fields that don't map to the standard schema. + * Preserves unknown keys so no data is silently dropped. + */ + private Map extra; + + public Integer getPercent() { + return percent; + } + + public void setPercent(Integer percent) { + this.percent = percent; + } + + public String getStage() { + return stage; + } + + public void setStage(String stage) { + this.stage = stage; + } + + public String getState() { + return state; + } + + public void setState(String state) { + this.state = state; + } + + public String getStateReason() { + return stateReason; + } + + public void setStateReason(String stateReason) { + this.stateReason = stateReason; + } + + public Long getProcessedBytes() { + return processedBytes; + } + + public void setProcessedBytes(Long processedBytes) { + this.processedBytes = processedBytes; + } + + public Long getTotalBytes() { + return totalBytes; + } + + public void setTotalBytes(Long totalBytes) { + this.totalBytes = totalBytes; + } + + public Long getProcessedItems() { + return processedItems; + } + + public void setProcessedItems(Long processedItems) { + this.processedItems = processedItems; + } + + public Long getTotalItems() { + return totalItems; + } + + public void setTotalItems(Long totalItems) { + this.totalItems = totalItems; + } + + public Long getSpeedBytesPerSecond() { + return speedBytesPerSecond; + } + + public void setSpeedBytesPerSecond(Long speedBytesPerSecond) { + this.speedBytesPerSecond = speedBytesPerSecond; + } + + public Long getEstimatedRemainingSeconds() { + return estimatedRemainingSeconds; + } + + public void setEstimatedRemainingSeconds(Long estimatedRemainingSeconds) { + this.estimatedRemainingSeconds = estimatedRemainingSeconds; + } + + public Map getExtra() { + return extra; + } + + public void setExtra(Map extra) { + this.extra = extra; + } +} diff --git a/header/src/main/java/org/zstack/header/core/progress/LongJobProgressDetailBuilder.java b/header/src/main/java/org/zstack/header/core/progress/LongJobProgressDetailBuilder.java new file mode 100644 index 00000000000..18a436fc280 --- /dev/null +++ b/header/src/main/java/org/zstack/header/core/progress/LongJobProgressDetailBuilder.java @@ -0,0 +1,249 @@ +package org.zstack.header.core.progress; + +import org.zstack.utils.Utils; +import org.zstack.utils.gson.JSONObjectUtil; +import org.zstack.utils.logging.CLogger; + +import java.util.HashMap; +import java.util.Map; + +/** + * Parses TaskProgressVO.opaque (free-form JSON) into a typed LongJobProgressDetail. + * + * Three known opaque formats are handled: + * Format 1 — VM migration: {"remain":N, "total":N, "speed":N, "remaining_migration_time":N} + * Format 2 — AI download: {"data": ""} where the inner JSON has + * {state, progress:{percent,downloaded_bytes,total_bytes, + * speed_bytes_per_second,estimated_remaining_seconds, + * downloaded_files,total_files,stage}, state_reason} + * Format 3 — unknown: entire map goes into LongJobProgressDetail.extra + * + * Each format is tried independently. Failures in one format don't affect others. + */ +public class LongJobProgressDetailBuilder { + private static final CLogger logger = Utils.getLogger(LongJobProgressDetailBuilder.class); + + private LongJobProgressDetailBuilder() {} + + /** + * Build a LongJobProgressDetail from a TaskProgressVO. + * Returns null if opaque is null/empty or all parsers fail. + */ + public static LongJobProgressDetail fromTaskProgressVO(TaskProgressVO vo) { + if (vo == null || vo.getOpaque() == null || vo.getOpaque().isEmpty()) { + return null; + } + + Map raw; + try { + raw = JSONObjectUtil.toObject(vo.getOpaque(), HashMap.class); + } catch (Exception e) { + logger.trace("LongJobProgressDetailBuilder: opaque is not a JSON object, skipping: " + vo.getOpaque(), e); + return null; + } + + if (raw == null || raw.isEmpty()) { + return null; + } + + // Try Format 2 first: AI download wraps everything under "data" key + if (raw.containsKey("data")) { + LongJobProgressDetail detail = tryParseAiDownloadFormat(raw); + if (detail != null) { + return detail; + } + } + + // Try Format 1: VM migration with remain/total/speed keys + if (raw.containsKey("remain") && raw.containsKey("total")) { + LongJobProgressDetail detail = tryParseVmMigrationFormat(raw); + if (detail != null) { + return detail; + } + } + + // Format 3: unknown — put everything into extra + return parseAsExtra(raw); + } + + /** + * Format 1: VM migration opaque + * {"remain": 1234567, "total": 9999999, "speed": 102400, "remaining_migration_time": 30} + * remain = bytes still to transfer; processed = total - remain + */ + private static LongJobProgressDetail tryParseVmMigrationFormat(Map raw) { + try { + LongJobProgressDetail detail = new LongJobProgressDetail(); + detail.setStage("migrating"); + + Number total = toNumber(raw.get("total")); + Number remain = toNumber(raw.get("remain")); + Number speed = toNumber(raw.get("speed")); + Number remainingTime = toNumber(raw.get("remaining_migration_time")); + + if (total != null) { + detail.setTotalBytes(total.longValue()); + } + if (total != null && remain != null) { + long processed = Math.max(0L, total.longValue() - remain.longValue()); + detail.setProcessedBytes(processed); + if (total.longValue() > 0) { + detail.setPercent((int) Math.min(100, Math.round(processed * 100.0 / total.longValue()))); + } + } + if (speed != null) { + detail.setSpeedBytesPerSecond(speed.longValue()); + } + if (remainingTime != null) { + detail.setEstimatedRemainingSeconds(remainingTime.longValue()); + } + + // Carry over any unrecognized keys into extra + Map extra = new HashMap<>(raw); + extra.remove("remain"); + extra.remove("total"); + extra.remove("speed"); + extra.remove("remaining_migration_time"); + if (!extra.isEmpty()) { + detail.setExtra(extra); + } + + return detail; + } catch (Exception e) { + logger.trace("LongJobProgressDetailBuilder: failed to parse VM migration format", e); + return null; + } + } + + /** + * Format 2: AI download opaque + * {"data": "{\"state\":\"downloading\", \"progress\":{\"percent\":42, \"processedBytes\":N, ...}}"} + * The "data" value is a JSON string (double-encoded). + */ + private static LongJobProgressDetail tryParseAiDownloadFormat(Map raw) { + try { + Object dataVal = raw.get("data"); + if (dataVal == null) { + return null; + } + + Map inner; + if (dataVal instanceof String) { + // double-encoded JSON string + inner = JSONObjectUtil.toObject((String) dataVal, HashMap.class); + } else if (dataVal instanceof Map) { + inner = (Map) dataVal; + } else { + return null; + } + + if (inner == null) { + return null; + } + + LongJobProgressDetail detail = new LongJobProgressDetail(); + + // state field + Object stateVal = inner.get("state"); + if (stateVal instanceof String) { + detail.setState((String) stateVal); + } + + // progress sub-object + Object progressVal = inner.get("progress"); + if (progressVal instanceof Map) { + Map progress = (Map) progressVal; + + Number percent = toNumber(progress.get("percent")); + if (percent != null) { + detail.setPercent((int) Math.round(percent.doubleValue())); + } + + // AI agent uses snake_case field names + Number processedBytes = toNumber(progress.get("downloaded_bytes")); + if (processedBytes != null) { + detail.setProcessedBytes(processedBytes.longValue()); + } + + Number totalBytes = toNumber(progress.get("total_bytes")); + if (totalBytes != null) { + detail.setTotalBytes(totalBytes.longValue()); + } + + Number speed = toNumber(progress.get("speed_bytes_per_second")); + if (speed != null) { + detail.setSpeedBytesPerSecond(speed.longValue()); + } + + Number eta = toNumber(progress.get("estimated_remaining_seconds")); + if (eta != null) { + detail.setEstimatedRemainingSeconds(eta.longValue()); + } + + Number processedFiles = toNumber(progress.get("downloaded_files")); + if (processedFiles != null) { + detail.setProcessedItems(processedFiles.longValue()); + } + + Number totalFiles = toNumber(progress.get("total_files")); + if (totalFiles != null) { + detail.setTotalItems(totalFiles.longValue()); + } + + Object stage = progress.get("stage"); + if (stage instanceof String) { + detail.setStage((String) stage); + } + + // remaining progress fields go into extra + Map extraProgress = new HashMap<>(progress); + extraProgress.remove("percent"); + extraProgress.remove("downloaded_bytes"); + extraProgress.remove("total_bytes"); + extraProgress.remove("speed_bytes_per_second"); + extraProgress.remove("estimated_remaining_seconds"); + extraProgress.remove("downloaded_files"); + extraProgress.remove("total_files"); + extraProgress.remove("stage"); + if (!extraProgress.isEmpty()) { + detail.setExtra(extraProgress); + } + } + + // stateReason field — can be String or Map (structured reason with code/description) + Object stateReason = inner.get("state_reason"); + if (stateReason instanceof String) { + detail.setStateReason((String) stateReason); + } else if (stateReason instanceof Map) { + detail.setStateReason(JSONObjectUtil.toJsonString(stateReason)); + } + + return detail; + } catch (Exception e) { + logger.trace("LongJobProgressDetailBuilder: failed to parse AI download format", e); + return null; + } + } + + /** + * Format 3: unknown — preserve the entire map as extra for UI passthrough. + */ + private static LongJobProgressDetail parseAsExtra(Map raw) { + LongJobProgressDetail detail = new LongJobProgressDetail(); + detail.setExtra(new HashMap<>(raw)); + return detail; + } + + private static Number toNumber(Object val) { + if (val instanceof Number) { + return (Number) val; + } + if (val instanceof String) { + try { + return Double.parseDouble((String) val); + } catch (NumberFormatException ignored) { + } + } + return null; + } +} diff --git a/header/src/main/java/org/zstack/header/core/progress/TaskProgressInventory.java b/header/src/main/java/org/zstack/header/core/progress/TaskProgressInventory.java index aa8c0f6db7e..b86dcb50eef 100755 --- a/header/src/main/java/org/zstack/header/core/progress/TaskProgressInventory.java +++ b/header/src/main/java/org/zstack/header/core/progress/TaskProgressInventory.java @@ -18,6 +18,8 @@ public class TaskProgressInventory { private Long time; private List subTasks; private String arguments; + /** Typed progress detail parsed from opaque. Null when opaque is absent or unrecognized. */ + private LongJobProgressDetail progressDetail; public TaskProgressInventory() { } @@ -105,4 +107,12 @@ public Long getTime() { public void setTime(Long time) { this.time = time; } + + public LongJobProgressDetail getProgressDetail() { + return progressDetail; + } + + public void setProgressDetail(LongJobProgressDetail progressDetail) { + this.progressDetail = progressDetail; + } } diff --git a/header/src/main/java/org/zstack/header/longjob/LongJobProgressNotificationMessage.java b/header/src/main/java/org/zstack/header/longjob/LongJobProgressNotificationMessage.java index 802f3b2b3fa..84b9aaf6ef9 100644 --- a/header/src/main/java/org/zstack/header/longjob/LongJobProgressNotificationMessage.java +++ b/header/src/main/java/org/zstack/header/longjob/LongJobProgressNotificationMessage.java @@ -1,5 +1,7 @@ package org.zstack.header.longjob; +import org.zstack.header.core.progress.LongJobProgressDetail; +import org.zstack.header.core.progress.LongJobProgressDetailBuilder; import org.zstack.header.core.progress.TaskProgressInventory; import org.zstack.header.core.progress.TaskProgressVO; @@ -23,6 +25,8 @@ public enum EventType { private Integer progress; /** Full progress detail; optional, BFF current version only needs {@link #getProgress()}. */ private TaskProgressInventory taskProgress; + /** Standardized progress detail parsed from opaque; null when opaque is absent. */ + private LongJobProgressDetail progressDetail; private EventType eventType; private Long timestamp; @@ -68,6 +72,14 @@ public void setTimestamp(Long timestamp) { this.timestamp = timestamp; } + public LongJobProgressDetail getProgressDetail() { + return progressDetail; + } + + public void setProgressDetail(LongJobProgressDetail progressDetail) { + this.progressDetail = progressDetail; + } + public static LongJobProgressNotificationMessage stateChanged(LongJobVO vo) { LongJobProgressNotificationMessage msg = new LongJobProgressNotificationMessage(); msg.longJob = LongJobInventory.valueOf(vo); @@ -85,7 +97,9 @@ public static LongJobProgressNotificationMessage progressUpdated(LongJobVO vo, T if (progressVO.getContent() != null) { inv.setContent(progressVO.getContent()); } + inv.setProgressDetail(LongJobProgressDetailBuilder.fromTaskProgressVO(progressVO)); msg.taskProgress = inv; + msg.progressDetail = inv.getProgressDetail(); msg.eventType = EventType.PROGRESS_UPDATED; msg.timestamp = System.currentTimeMillis(); return msg; diff --git a/sdk/src/main/java/org/zstack/sdk/LongJobProgressDetail.java b/sdk/src/main/java/org/zstack/sdk/LongJobProgressDetail.java new file mode 100644 index 00000000000..365f535bc45 --- /dev/null +++ b/sdk/src/main/java/org/zstack/sdk/LongJobProgressDetail.java @@ -0,0 +1,95 @@ +package org.zstack.sdk; + + + +public class LongJobProgressDetail { + + public java.lang.Integer percent; + public void setPercent(java.lang.Integer percent) { + this.percent = percent; + } + public java.lang.Integer getPercent() { + return this.percent; + } + + public java.lang.String stage; + public void setStage(java.lang.String stage) { + this.stage = stage; + } + public java.lang.String getStage() { + return this.stage; + } + + 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.lang.String stateReason; + public void setStateReason(java.lang.String stateReason) { + this.stateReason = stateReason; + } + public java.lang.String getStateReason() { + return this.stateReason; + } + + public java.lang.Long processedBytes; + public void setProcessedBytes(java.lang.Long processedBytes) { + this.processedBytes = processedBytes; + } + public java.lang.Long getProcessedBytes() { + return this.processedBytes; + } + + public java.lang.Long totalBytes; + public void setTotalBytes(java.lang.Long totalBytes) { + this.totalBytes = totalBytes; + } + public java.lang.Long getTotalBytes() { + return this.totalBytes; + } + + public java.lang.Long processedItems; + public void setProcessedItems(java.lang.Long processedItems) { + this.processedItems = processedItems; + } + public java.lang.Long getProcessedItems() { + return this.processedItems; + } + + public java.lang.Long totalItems; + public void setTotalItems(java.lang.Long totalItems) { + this.totalItems = totalItems; + } + public java.lang.Long getTotalItems() { + return this.totalItems; + } + + public java.lang.Long speedBytesPerSecond; + public void setSpeedBytesPerSecond(java.lang.Long speedBytesPerSecond) { + this.speedBytesPerSecond = speedBytesPerSecond; + } + public java.lang.Long getSpeedBytesPerSecond() { + return this.speedBytesPerSecond; + } + + public java.lang.Long estimatedRemainingSeconds; + public void setEstimatedRemainingSeconds(java.lang.Long estimatedRemainingSeconds) { + this.estimatedRemainingSeconds = estimatedRemainingSeconds; + } + public java.lang.Long getEstimatedRemainingSeconds() { + return this.estimatedRemainingSeconds; + } + + public java.util.LinkedHashMap extra; + public void setExtra(java.util.LinkedHashMap extra) { + this.extra = extra; + } + public java.util.LinkedHashMap getExtra() { + return this.extra; + } + +} diff --git a/sdk/src/main/java/org/zstack/sdk/TaskProgressInventory.java b/sdk/src/main/java/org/zstack/sdk/TaskProgressInventory.java index 31d427d23d4..e22f11655f7 100644 --- a/sdk/src/main/java/org/zstack/sdk/TaskProgressInventory.java +++ b/sdk/src/main/java/org/zstack/sdk/TaskProgressInventory.java @@ -76,4 +76,12 @@ public java.lang.String getArguments() { return this.arguments; } + public org.zstack.sdk.LongJobProgressDetail progressDetail; + public void setProgressDetail(org.zstack.sdk.LongJobProgressDetail progressDetail) { + this.progressDetail = progressDetail; + } + public org.zstack.sdk.LongJobProgressDetail getProgressDetail() { + return this.progressDetail; + } + } From cb554df47283c96023ebbe917333e1f24e5199f1 Mon Sep 17 00:00:00 2001 From: "ye.zou" Date: Wed, 11 Mar 2026 20:24:28 +0800 Subject: [PATCH 2/2] [sdk]: update SDK files for LongJobProgressDetail Resolves: ZSTAC-82318 Change-Id: I8931c4207547b836b522c9b5cea2db807a032d5c --- .../LongJobProgressDetailBuilder.java | 23 +++++++++++++++---- .../core/progress/TaskProgressInventory.java | 2 +- sdk/src/main/java/SourceClassMap.java | 2 ++ .../org/zstack/sdk/LongJobProgressDetail.java | 6 ++--- .../org/zstack/sdk/TaskProgressInventory.java | 8 +++---- 5 files changed, 29 insertions(+), 12 deletions(-) diff --git a/header/src/main/java/org/zstack/header/core/progress/LongJobProgressDetailBuilder.java b/header/src/main/java/org/zstack/header/core/progress/LongJobProgressDetailBuilder.java index 18a436fc280..4c9a09b2580 100644 --- a/header/src/main/java/org/zstack/header/core/progress/LongJobProgressDetailBuilder.java +++ b/header/src/main/java/org/zstack/header/core/progress/LongJobProgressDetailBuilder.java @@ -142,6 +142,7 @@ private static LongJobProgressDetail tryParseAiDownloadFormat(Map extra = new HashMap<>(); // state field Object stateVal = inner.get("state"); @@ -156,7 +157,7 @@ private static LongJobProgressDetail tryParseAiDownloadFormat(Map extraInner = new HashMap<>(inner); + extraInner.remove("state"); + extraInner.remove("progress"); + extraInner.remove("state_reason"); + extra.putAll(extraInner); + + // preserve unknown keys from raw outer-level + Map extraRaw = new HashMap<>(raw); + extraRaw.remove("data"); + extra.putAll(extraRaw); + + if (!extra.isEmpty()) { + detail.setExtra(extra); + } + return detail; } catch (Exception e) { logger.trace("LongJobProgressDetailBuilder: failed to parse AI download format", e); diff --git a/header/src/main/java/org/zstack/header/core/progress/TaskProgressInventory.java b/header/src/main/java/org/zstack/header/core/progress/TaskProgressInventory.java index b86dcb50eef..b945d270292 100755 --- a/header/src/main/java/org/zstack/header/core/progress/TaskProgressInventory.java +++ b/header/src/main/java/org/zstack/header/core/progress/TaskProgressInventory.java @@ -18,7 +18,7 @@ public class TaskProgressInventory { private Long time; private List subTasks; private String arguments; - /** Typed progress detail parsed from opaque. Null when opaque is absent or unrecognized. */ + /** Typed progress detail parsed from opaque. Null when opaque is absent or parsing fails. */ private LongJobProgressDetail progressDetail; public TaskProgressInventory() { diff --git a/sdk/src/main/java/SourceClassMap.java b/sdk/src/main/java/SourceClassMap.java index 46a1ce8c961..b5ea0d48dea 100644 --- a/sdk/src/main/java/SourceClassMap.java +++ b/sdk/src/main/java/SourceClassMap.java @@ -247,6 +247,7 @@ public class SourceClassMap { put("org.zstack.header.core.external.service.ExternalServiceCapabilities", "org.zstack.sdk.ExternalServiceCapabilities"); put("org.zstack.header.core.external.service.ExternalServiceInventory", "org.zstack.sdk.ExternalServiceInventory"); put("org.zstack.header.core.progress.ChainInfo", "org.zstack.sdk.ChainInfo"); + put("org.zstack.header.core.progress.LongJobProgressDetail", "org.zstack.sdk.LongJobProgressDetail"); put("org.zstack.header.core.progress.PendingTaskInfo", "org.zstack.sdk.PendingTaskInfo"); put("org.zstack.header.core.progress.RunningTaskInfo", "org.zstack.sdk.RunningTaskInfo"); put("org.zstack.header.core.progress.TaskInfo", "org.zstack.sdk.TaskInfo"); @@ -1208,6 +1209,7 @@ public class SourceClassMap { put("org.zstack.sdk.LogType", "org.zstack.log.server.LogType"); put("org.zstack.sdk.LoginAuthenticationProcedureDesc", "org.zstack.header.identity.login.LoginAuthenticationProcedureDesc"); put("org.zstack.sdk.LongJobInventory", "org.zstack.header.longjob.LongJobInventory"); + put("org.zstack.sdk.LongJobProgressDetail", "org.zstack.header.core.progress.LongJobProgressDetail"); put("org.zstack.sdk.LongJobState", "org.zstack.header.longjob.LongJobState"); put("org.zstack.sdk.LunInventory", "org.zstack.header.storageDevice.LunInventory"); put("org.zstack.sdk.MaaSUsage", "org.zstack.ai.message.MaaSUsage"); diff --git a/sdk/src/main/java/org/zstack/sdk/LongJobProgressDetail.java b/sdk/src/main/java/org/zstack/sdk/LongJobProgressDetail.java index 365f535bc45..c37bc20795b 100644 --- a/sdk/src/main/java/org/zstack/sdk/LongJobProgressDetail.java +++ b/sdk/src/main/java/org/zstack/sdk/LongJobProgressDetail.java @@ -84,11 +84,11 @@ public java.lang.Long getEstimatedRemainingSeconds() { return this.estimatedRemainingSeconds; } - public java.util.LinkedHashMap extra; - public void setExtra(java.util.LinkedHashMap extra) { + public java.util.Map extra; + public void setExtra(java.util.Map extra) { this.extra = extra; } - public java.util.LinkedHashMap getExtra() { + public java.util.Map getExtra() { return this.extra; } diff --git a/sdk/src/main/java/org/zstack/sdk/TaskProgressInventory.java b/sdk/src/main/java/org/zstack/sdk/TaskProgressInventory.java index e22f11655f7..6bec468e66f 100644 --- a/sdk/src/main/java/org/zstack/sdk/TaskProgressInventory.java +++ b/sdk/src/main/java/org/zstack/sdk/TaskProgressInventory.java @@ -1,6 +1,6 @@ package org.zstack.sdk; - +import org.zstack.sdk.LongJobProgressDetail; public class TaskProgressInventory { @@ -76,11 +76,11 @@ public java.lang.String getArguments() { return this.arguments; } - public org.zstack.sdk.LongJobProgressDetail progressDetail; - public void setProgressDetail(org.zstack.sdk.LongJobProgressDetail progressDetail) { + public LongJobProgressDetail progressDetail; + public void setProgressDetail(LongJobProgressDetail progressDetail) { this.progressDetail = progressDetail; } - public org.zstack.sdk.LongJobProgressDetail getProgressDetail() { + public LongJobProgressDetail getProgressDetail() { return this.progressDetail; }