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
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package org.zstack.header.storage.addon;

public abstract class StorageResource {
protected String installPath;
protected Long size;
protected Long actualSize;
protected String parentUri;

public String getInstallPath() {
return installPath;
}

public void setInstallPath(String installPath) {
this.installPath = installPath;
}

public Long getSize() {
return size;
}

public void setSize(long size) {
this.size = size;
}

public Long getResourceActualSize() {
return actualSize;
}

public void setActualSize(Long actualSize) {
this.actualSize = actualSize;
}

public void setActualSize(long actualSize) {
this.actualSize = actualSize;
}

public String getParentUri() {
return parentUri;
}

public void setParentUri(String parentUri) {
this.parentUri = parentUri;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ public interface PrimaryStorageControllerSvc {
void flattenVolume(String installPath, ReturnValueCompletion<VolumeStats>comp);

// support uri or path
void stats(String installPath, ReturnValueCompletion<VolumeStats> comp);
void stats(String installPath, ReturnValueCompletion<StorageResource> comp);

void batchStats(Collection<String> installPath, ReturnValueCompletion<List<VolumeStats>> comp);

Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,9 @@
package org.zstack.header.storage.snapshot;

public class VolumeSnapshotStats {
private String installPath;
private long actualSize;

public String getInstallPath() {
return installPath;
}

public void setInstallPath(String installPath) {
this.installPath = installPath;
}
import org.zstack.header.storage.addon.StorageResource;

public class VolumeSnapshotStats extends StorageResource {
public long getActualSize() {
return actualSize;
}

public void setActualSize(long actualSize) {
this.actualSize = actualSize;
return actualSize == null ? 0L : actualSize;
}
}
39 changes: 3 additions & 36 deletions header/src/main/java/org/zstack/header/volume/VolumeStats.java
Original file line number Diff line number Diff line change
@@ -1,14 +1,9 @@
package org.zstack.header.volume;

public class VolumeStats {
protected String installPath;
import org.zstack.header.storage.addon.StorageResource;

public class VolumeStats extends StorageResource {
protected String format;
protected Long actualSize;
protected Long size;
/**
* The parent uri of the volume, vendor://pool/path@snapshot or snapshot://uuid
*/
protected String parentUri;

// TODO(shenjin): remove it
@Deprecated
Expand All @@ -29,30 +24,10 @@ public VolumeStats(String installPath, Long actualSize, Long size) {
public VolumeStats() {
}

public String getInstallPath() {
return installPath;
}

public void setInstallPath(String installPath) {
this.installPath = installPath;
}

public Long getActualSize() {
return actualSize;
}

public void setActualSize(Long actualSize) {
this.actualSize = actualSize;
}

public Long getSize() {
return size;
}

public void setSize(long size) {
this.size = size;
}

public void setFormat(String format) {
this.format = format;
}
Expand All @@ -61,14 +36,6 @@ public String getFormat() {
return format;
}

public void setParentUri(String parentUri) {
this.parentUri = parentUri;
}

public String getParentUri() {
return parentUri;
}

@Deprecated
public String getRunStatus() {
return runStatus;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1143,18 +1143,32 @@ public void fail(ErrorCode errorCode) {
@Override
public void flattenVolume(String installPath, ReturnValueCompletion<VolumeStats> comp) {
// TODO flatten snapshot
stats(installPath, comp);
comp.success(getVolumeStats(installPath));
}

@Override
public void stats(String installPath, ReturnValueCompletion<VolumeStats> comp) {
public void stats(String installPath, ReturnValueCompletion<StorageResource> comp) {
if (installPath.contains("@")) {
VolumeSnapshotModule snap = apiHelper.getVolumeSnapshot(getSnapIdFromPath(installPath));
VolumeSnapshotStats stats = new VolumeSnapshotStats();
stats.setInstallPath(installPath);
stats.setSize(snap.getSnapSize());
stats.setActualSize(snap.getDataSize());
comp.success(stats);
return;
}

comp.success(getVolumeStats(installPath));
}

private VolumeStats getVolumeStats(String installPath) {
VolumeModule vol = apiHelper.getVolume(getVolIdFromPath(installPath));
VolumeStats stats = new VolumeStats();
stats.setInstallPath(installPath);
stats.setSize(vol.getVolumeSize());
stats.setActualSize(vol.getDataSize());
stats.setFormat(VolumeConstant.VOLUME_FORMAT_RAW);
comp.success(stats);
return stats;
}
Comment on lines 1149 to 1172

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check whether Expon's VolumeModule exposes a backing snapshot id equivalent to XInfini's getBsSnapId()
ast-grep run --pattern 'class VolumeModule { $$$ }' --lang java plugin/expon
rg -n 'class VolumeModule' -A40 plugin/expon

Repository: MatheMatrix/zstack

Length of output: 4089


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect Expon volume/snapshot models and the parent-chain logic referenced by the comment.
files=(
  plugin/expon/src/main/java/org/zstack/expon/sdk/volume/VolumeModule.java
  plugin/expon/src/main/java/org/zstack/expon/sdk/volume/snapshot/VolumeSnapshotModule.java
  plugin/expon/src/main/java/org/zstack/storage/primary/ExternalPrimaryStorage.java
  plugin/expon/src/main/java/org/zstack/expon/ExponStorageController.java
  plugin/xinfini/src/main/java/org/zstack/xinfini/XInfiniStorageController.java
)

for f in "${files[@]}"; do
  echo "===== $f ====="
  if [ -f "$f" ]; then
    wc -l "$f"
    echo "--- outline ---"
    ast-grep outline "$f" --view expanded | sed -n '1,220p'
  else
    echo "MISSING"
  fi
  echo
done

Repository: MatheMatrix/zstack

Length of output: 9477


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Search for any parentUri / backing snapshot related fields or accessors in Expon SDK and controller code.
rg -n "parentUri|getParentUri|getBsSnapId|backing|snapshot" plugin/expon/src/main/java plugin/xinfini/src/main/java plugin/storage/src/main/java 2>/dev/null || true

Repository: MatheMatrix/zstack

Length of output: 11651


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Read the exact implementation slices around the relevant methods.
sed -n '1138,1180p' plugin/expon/src/main/java/org/zstack/expon/ExponStorageController.java
printf '\n===== XInfini =====\n'
sed -n '1120,1185p' plugin/xinfini/src/main/java/org/zstack/xinfini/XInfiniStorageController.java
printf '\n===== ExternalPrimaryStorage =====\n'
rg -n "getParentChain|parentUri" plugin/storage/src/main/java/org/zstack/storage/primary/ExternalPrimaryStorage.java

Repository: MatheMatrix/zstack

Length of output: 2964


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Find the parent-chain implementation and any callers to see whether Expon stats are expected to provide parentUri.
rg -n "getParentChain\\(|parentUri == null|setParentUri\\(|getParentUri\\(" plugin -g '*.java'

Repository: MatheMatrix/zstack

Length of output: 1594


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the parent-chain traversal logic and the storage stats interface.
files=(
  plugin/storage/src/main/java/org/zstack/storage/primary/ExternalPrimaryStorage.java
  plugin/storage/src/main/java/org/zstack/storage/primary/ExternalPrimaryStorageFactory.java
  plugin/storage/src/main/java/org/zstack/storage/primary/ExternalPrimaryStorageBase.java
)

for f in "${files[@]}"; do
  if [ -f "$f" ]; then
    echo "===== $f ====="
    wc -l "$f"
    rg -n "getParentChain|parentUri|StorageResource|VolumeStats|VolumeSnapshotStats" "$f"
  fi
done

Repository: MatheMatrix/zstack

Length of output: 156


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Locate the file that contains the parent-chain logic.
fd -a 'ExternalPrimaryStorage.java|ExternalPrimaryStorageBase.java|ExternalPrimaryStorageFactory.java' plugin

Repository: MatheMatrix/zstack

Length of output: 156


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Search the entire repository for the parent-chain implementation and related stats logic.
rg -n "getParentChain\\(|parentUri == null|setParentUri\\(|getParentUri\\(" .

Repository: MatheMatrix/zstack

Length of output: 2600


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect Expon snapshot/volume SDK models and the API helper getter to see whether a backing parent can be derived.
for f in \
  plugin/expon/src/main/java/org/zstack/expon/sdk/volume/VolumeSnapshotModule.java \
  plugin/expon/src/main/java/org/zstack/expon/sdk/volume/VolumeModule.java \
  plugin/expon/src/main/java/org/zstack/expon/ExponApiHelper.java
do
  echo "===== $f ====="
  wc -l "$f"
  echo "--- outline ---"
  ast-grep outline "$f" --view expanded | sed -n '1,220p'
  echo
done

Repository: MatheMatrix/zstack

Length of output: 10359


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Read the relevant Expon slices around getVolumeStats(), stats(), and any snapshot/volume parent handling nearby.
sed -n '1138,1180p' plugin/expon/src/main/java/org/zstack/expon/ExponStorageController.java
printf '\n===== VolumeSnapshotModule =====\n'
sed -n '1,220p' plugin/expon/src/main/java/org/zstack/expon/sdk/volume/VolumeSnapshotModule.java
printf '\n===== ExponApiHelper#getVolumeSnapshot =====\n'
rg -n "public VolumeSnapshotModule getVolumeSnapshot|public VolumeModule getVolume\\(" -A25 -B5 plugin/expon/src/main/java/org/zstack/expon/ExponApiHelper.java

Repository: MatheMatrix/zstack

Length of output: 7474


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Look for any Expon field or method that could identify a volume's backing snapshot / clone source.
rg -n "bsSnapId|backing|clone|source snapshot|sourceSnapshot|parentUri" plugin/expon/src/main/java/org/zstack/expon -g '*.java'

Repository: MatheMatrix/zstack

Length of output: 2237


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the Expon volume/snapshot API payload shapes to see whether source/backing info is available anywhere else.
sed -n '1,220p' plugin/expon/src/main/java/org/zstack/expon/sdk/volume/GetVolumeResponse.java
printf '\n===== GetVolumeSnapshotResponse =====\n'
sed -n '1,220p' plugin/expon/src/main/java/org/zstack/expon/sdk/volume/GetVolumeSnapshotResponse.java
printf '\n===== GetVolumeSnapshotRequest =====\n'
sed -n '1,220p' plugin/expon/src/main/java/org/zstack/expon/sdk/volume/GetVolumeSnapshotRequest.java

Repository: MatheMatrix/zstack

Length of output: 3825


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect Expon path builders and whether snapshot stats could be linked to a volume path directly.
rg -n "buildExponVolumePath|buildExponSnapshotPath|getSnapIdFromPath|getVolIdFromPath|setParentUri\\(" plugin/expon/src/main/java/org/zstack/expon/ExponStorageController.java
sed -n '1,260p' plugin/expon/src/main/java/org/zstack/expon/ExponStorageController.java | sed -n '1,220p'

Repository: MatheMatrix/zstack

Length of output: 11971


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Read the helper methods around install path construction and path parsing in ExponStorageController.
sed -n '1,220p' plugin/expon/src/main/java/org/zstack/expon/ExponStorageController.java

Repository: MatheMatrix/zstack

Length of output: 9374


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Check whether Expon already has a volume-path helper and how clone/snapshot methods populate parentUri.
rg -n "buildExponVolumePath|buildExponSnapshotPath|setParentUri\\(" plugin/expon/src/main/java/org/zstack/expon/ExponStorageController.java
printf '\n===== clone / snapshot slices =====\n'
sed -n '1096,1338p' plugin/expon/src/main/java/org/zstack/expon/ExponStorageController.java

Repository: MatheMatrix/zstack

Length of output: 10106


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Inspect the parent-chain traversal to confirm what parentUri is used for.
sed -n '1688,1745p' storage/src/main/java/org/zstack/storage/addon/primary/ExternalPrimaryStorage.java

Repository: MatheMatrix/zstack

Length of output: 2508


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Check whether Expon's snapshot response fields can be mapped to a parent storage path.
rg -n "getVolumeId\\(|buildExponPath\\(|buildExponSnapshotPath\\(" plugin/expon/src/main/java/org/zstack/expon/ExponStorageController.java plugin/expon/src/main/java/org/zstack/expon/ExponNameHelper.java
sed -n '1,220p' plugin/expon/src/main/java/org/zstack/expon/ExponNameHelper.java

Repository: MatheMatrix/zstack

Length of output: 3853


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Look for any helper that can reconstruct a volume path from a volume ID, which would be needed to set parentUri for snapshots.
rg -n "buildExponPath\\(|buildExponSnapshotPath\\(" plugin/expon/src/main/java/org/zstack/expon -g '*.java'

Repository: MatheMatrix/zstack

Length of output: 1567


补上快照 parentUri
stats() 的快照分支已经能从 snap.getPoolName() / snap.getVolumeId() 还原父卷路径,但现在没设置 parentUrigetParentChain() 会在这一层直接截断。

🤖 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 `@plugin/expon/src/main/java/org/zstack/expon/ExponStorageController.java`
around lines 1149 - 1172, 在 ExponStorageController.stats 的快照分支中补充 parentUri:使用
snap.getPoolName() 和 snap.getVolumeId() 还原父卷路径并设置到 VolumeSnapshotStats,确保
getParentChain() 能继续遍历父卷;保持现有快照统计字段和普通卷分支不变。


@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import org.zstack.core.retry.RetryCondition;
import org.zstack.header.core.Completion;
import org.zstack.header.errorcode.OperationFailureException;
import org.zstack.header.errorcode.SysErrors;
import org.zstack.header.volume.VolumeConfigs;
import org.zstack.header.volume.VolumeVO;
import org.zstack.header.volume.VolumeVO_;
Expand Down Expand Up @@ -36,6 +37,7 @@
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static org.zstack.core.Platform.err;
import static org.zstack.core.Platform.operr;
import static org.zstack.utils.clouderrorcode.CloudOperationsErrorCode.*;

Expand Down Expand Up @@ -102,6 +104,11 @@ public <T extends XInfiniResponse> void call(XInfiniRequest req, Completion comp
}

public void errorOut(XInfiniResponse rsp) {
if (rsp.resourceIsDeleted()) {
throw new OperationFailureException(err(ORG_ZSTACK_XINFINI_10002, SysErrors.RESOURCE_NOT_FOUND,
"xinfini request failed, message: %s.", rsp.getMessage()));
}

if (!rsp.isSuccess()) {
throw new OperationFailureException(operr(ORG_ZSTACK_XINFINI_10002, "xinfini request failed, message: %s.", rsp.getMessage()));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -851,15 +851,31 @@ public void flattenVolume(String installPath, ReturnValueCompletion<VolumeStats>
}

@Override
public void stats(String installPath, ReturnValueCompletion<VolumeStats> comp) {
public void stats(String installPath, ReturnValueCompletion<StorageResource> comp) {
if (installPath.contains("@")) {
VolumeSnapshotModule snapshot = apiHelper.getVolumeSnapshot(getSnapIdFromPath(installPath));
VolumeSnapshotStats stats = new VolumeSnapshotStats();
long size = SizeUnit.MEGABYTE.toByte(snapshot.getSpec().getSizeMb());
stats.setInstallPath(installPath);
stats.setSize(size);
stats.setActualSize(size);
stats.setParentUri(getParentUri(apiHelper.getVolume(snapshot.getSpec().getBsVolumeId())));
comp.success(stats);
return;
}

comp.success(getVolumeStats(installPath));
}

private VolumeStats getVolumeStats(String installPath) {
VolumeModule vol = apiHelper.getVolume(getVolIdFromPath(installPath));
VolumeStats stats = new VolumeStats();
stats.setInstallPath(installPath);
stats.setSize(SizeUnit.MEGABYTE.toByte(vol.getSpec().getSizeMb()));
stats.setActualSize(vol.getStatus().getAllocatedSizeByte());
stats.setFormat(VolumeConstant.VOLUME_FORMAT_RAW);
stats.setParentUri(getParentUri(vol));
comp.success(stats);
return stats;
}

private String getParentUri(VolumeModule vol) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1315,19 +1315,21 @@ public void fail(ErrorCode errorCode) {
}

@Override
public void stats(String installPath, ReturnValueCompletion<VolumeStats> comp) {
public void stats(String installPath, ReturnValueCompletion<StorageResource> comp) {
QueryVolumeCmd cmd = new QueryVolumeCmd();
cmd.setPath(installPath);

httpCall(QUERY_VOLUME_PATH, cmd, QueryVolumeRsp.class, new ReturnValueCompletion<QueryVolumeRsp>(comp) {
@Override
public void success(QueryVolumeRsp returnValue) {
VolumeStats stats = new VolumeStats();
StorageResource stats = installPath.contains("@") ? new VolumeSnapshotStats() : new VolumeStats();
stats.setInstallPath(installPath);
stats.setSize(returnValue.getSize());
stats.setActualSize(returnValue.getActualSize());
stats.setFormat(VolumeConstant.VOLUME_FORMAT_RAW);
stats.setParentUri(ZbsHelper.normalizeToZbsPath(returnValue.getParentUri()));
if (stats instanceof VolumeStats) {
((VolumeStats) stats).setFormat(VolumeConstant.VOLUME_FORMAT_RAW);
}
comp.success(stats);
}

Expand Down
Loading