Skip to content
Closed
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
21 changes: 21 additions & 0 deletions conf/db/upgrade/V5.5.12__schema.sql
Original file line number Diff line number Diff line change
Expand Up @@ -99,3 +99,24 @@ CREATE TABLE IF NOT EXISTS `zstack`.`VmInstanceDGpuStrategyVO` (
CONSTRAINT `fk_vm_dgpu_strategy_device`
FOREIGN KEY (`gpuDeviceUuid`) REFERENCES `zstack`.`PciDeviceVO`(`uuid`) ON DELETE SET NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ZSTAC-83157: VM model mount feature
CREATE TABLE IF NOT EXISTS `zstack`.`VmModelMountVO` (
`uuid` VARCHAR(32) NOT NULL,
`vmInstanceUuid` VARCHAR(32) NOT NULL,
`modelUuid` VARCHAR(32) NOT NULL,
`modelName` VARCHAR(256) DEFAULT NULL,
`mountPath` VARCHAR(512) NOT NULL,
`sourcePath` VARCHAR(1024) NOT NULL,
`status` VARCHAR(32) NOT NULL,
`hostUuid` VARCHAR(32) DEFAULT NULL,
`accountUuid` VARCHAR(32) DEFAULT NULL,
`createDate` TIMESTAMP NOT NULL DEFAULT '0000-00-00 00:00:00',
`lastOpDate` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`uuid`),
UNIQUE KEY `uk_vm_mountpath` (`vmInstanceUuid`, `mountPath`(255)),
CONSTRAINT `fk_vm_model_mount_vm`
FOREIGN KEY (`vmInstanceUuid`) REFERENCES `zstack`.`VmInstanceEO`(`uuid`) ON DELETE CASCADE,
CONSTRAINT `fk_vm_model_mount_model`
FOREIGN KEY (`modelUuid`) REFERENCES `zstack`.`ModelVO`(`uuid`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
14 changes: 13 additions & 1 deletion conf/i18n/globalErrorCodeMapping/global-error-zh_CN.json
Original file line number Diff line number Diff line change
Expand Up @@ -4720,5 +4720,17 @@
"ORG_ZSTACK_VPCFIREWALL_10035": "无法添加防火墙规则[%d]因为%s",
"ORG_ZSTACK_DGPU_10010": "未找到可用的 dGPU AddOn License,请为 dGPU 产品申请并上传对应授权。",
"ORG_ZSTACK_DGPU_10011": "dGPU 产品的 AddOn License 已过期,请及时续期。",
"ORG_ZSTACK_DGPU_10012": "dGPU 授权 GPU 数量不足。License 允许 %d 个 GPU,当前已使用 %d 个,其他节点共享使用 %d 个,本次还需要 %d 个。"
"ORG_ZSTACK_DGPU_10012": "dGPU 授权 GPU 数量不足。License 允许 %d 个 GPU,当前已使用 %d 个,其他节点共享使用 %d 个,本次还需要 %d 个。",
"ORG_ZSTACK_AI_10138": "虚拟机[uuid:%s]未找到",
"ORG_ZSTACK_AI_10139": "模型[uuid:%s]未找到",
"ORG_ZSTACK_AI_10140": "虚拟机[uuid:%s]必须处于运行状态才能挂载模型,当前状态: %s",
"ORG_ZSTACK_AI_10141": "虚拟机[uuid:%s]未运行在任何主机上",
"ORG_ZSTACK_AI_10142": "模型[uuid:%s]属于账户[%s]但虚拟机[uuid:%s]属于账户[%s],无法跨账户挂载模型",
"ORG_ZSTACK_AI_10143": "模型中心[uuid:%s]未找到",
"ORG_ZSTACK_AI_10144": "挂载路径[%s]已被虚拟机[uuid:%s]上的另一个挂载[uuid:%s]使用",
"ORG_ZSTACK_AI_10145": "挂载路径[%s]不允许,不能挂载到系统目录",
"ORG_ZSTACK_AI_10146": "模型安装路径[%s]无效,预期格式: file:///root/bentoml/models/<path>",
"ORG_ZSTACK_AI_10147": "挂载记录[uuid:%s]未找到",
"ORG_ZSTACK_AI_10148": "挂载记录[uuid:%s]未处于已挂载状态,当前状态: %s",
"ORG_ZSTACK_AI_10149": "挂载模型到虚拟机失败: %s"
}
5 changes: 5 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 @@ -96,6 +96,11 @@ public interface KVMConstant {
String CLEAN_FIRMWARE_FLASH = "/clean/firmware/flash";
String FSTRIM_VM_PATH = "/vm/fstrim";

// ZSTAC-83157: virtiofs model mount paths
String KVM_VIRTIOFS_ATTACH_PATH = "/virtiofs/attach";
String KVM_VIRTIOFS_DETACH_PATH = "/virtiofs/detach";
String KVM_MODEL_CENTER_MOUNT_PATH = "/modelcenter/mount";

String ISO_TO = "kvm.isoto";
String ANSIBLE_PLAYBOOK_NAME = "kvm.py";
String ANSIBLE_MODULE_PATH = "ansible/kvm";
Expand Down
4 changes: 4 additions & 0 deletions sdk/src/main/java/SourceClassMap.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ public class SourceClassMap {
put("org.zstack.ai.entity.ModelServiceRefInventory", "org.zstack.sdk.ModelServiceRefInventory");
put("org.zstack.ai.entity.ModelServiceTemplateInventory", "org.zstack.sdk.ModelServiceTemplateInventory");
put("org.zstack.ai.entity.TrainedModelRecordInventory", "org.zstack.sdk.TrainedModelRecordInventory");
put("org.zstack.ai.entity.VmModelMountInventory", "org.zstack.sdk.VmModelMountInventory");
put("org.zstack.ai.entity.VmModelMountStatus", "org.zstack.sdk.VmModelMountStatus");
put("org.zstack.ai.message.ArchitectureImageMapping", "org.zstack.sdk.ArchitectureImageMapping");
put("org.zstack.ai.message.MaaSUsage", "org.zstack.sdk.MaaSUsage");
put("org.zstack.ai.message.ModelCenterServiceInventory", "org.zstack.sdk.ModelCenterServiceInventory");
Expand Down Expand Up @@ -1545,6 +1547,8 @@ public class SourceClassMap {
put("org.zstack.sdk.VmInstancePciDeviceSpecRefInventory", "org.zstack.pciDevice.specification.pci.VmInstancePciDeviceSpecRefInventory");
put("org.zstack.sdk.VmMemoryBillingInventory", "org.zstack.billing.generator.vm.memory.VmMemoryBillingInventory");
put("org.zstack.sdk.VmMemorySpendingDetails", "org.zstack.billing.spendingcalculator.vm.VmMemorySpendingDetails");
put("org.zstack.sdk.VmModelMountInventory", "org.zstack.ai.entity.VmModelMountInventory");
put("org.zstack.sdk.VmModelMountStatus", "org.zstack.ai.entity.VmModelMountStatus");
put("org.zstack.sdk.VmNicBandwidthSpendingDetails", "org.zstack.billing.spendingcalculator.vmnic.VmNicBandwidthSpendingDetails");
put("org.zstack.sdk.VmNicInventory", "org.zstack.header.vm.VmNicInventory");
put("org.zstack.sdk.VmNicSecurityGroupRefInventory", "org.zstack.network.securitygroup.VmNicSecurityGroupRefInventory");
Expand Down
107 changes: 107 additions & 0 deletions sdk/src/main/java/org/zstack/sdk/MountModelToVmInstanceAction.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package org.zstack.sdk;

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

public class MountModelToVmInstanceAction 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.MountModelToVmInstanceResult 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 vmInstanceUuid;

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

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

@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.MountModelToVmInstanceResult value = res.getResult(org.zstack.sdk.MountModelToVmInstanceResult.class);
ret.value = value == null ? new org.zstack.sdk.MountModelToVmInstanceResult() : 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 = "/vm-model-mounts";
info.needSession = true;
info.needPoll = true;
info.parameterName = "params";
return info;
}

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

import org.zstack.sdk.VmModelMountInventory;

public class MountModelToVmInstanceResult {
public VmModelMountInventory inventory;
public void setInventory(VmModelMountInventory inventory) {
this.inventory = inventory;
}
public VmModelMountInventory getInventory() {
return this.inventory;
}

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

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

public class QueryVmModelMountAction extends QueryAction {

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.QueryVmModelMountResult 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;
}
}



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

org.zstack.sdk.QueryVmModelMountResult value = res.getResult(org.zstack.sdk.QueryVmModelMountResult.class);
ret.value = value == null ? new org.zstack.sdk.QueryVmModelMountResult() : 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 = "GET";
info.path = "/vm-model-mounts";
info.needSession = true;
info.needPoll = false;
info.parameterName = "";
return info;
}

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



public class QueryVmModelMountResult {
public java.util.List inventories;
public void setInventories(java.util.List inventories) {
this.inventories = inventories;
}
public java.util.List getInventories() {
return this.inventories;
}

public java.lang.Long total;
public void setTotal(java.lang.Long total) {
this.total = total;
}
public java.lang.Long getTotal() {
return this.total;
}

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

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

public class UnmountModelFromVmInstanceAction 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.UnmountModelFromVmInstanceResult 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 = 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.UnmountModelFromVmInstanceResult value = res.getResult(org.zstack.sdk.UnmountModelFromVmInstanceResult.class);
ret.value = value == null ? new org.zstack.sdk.UnmountModelFromVmInstanceResult() : 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 = "DELETE";
info.path = "/vm-model-mounts/{uuid}";
info.needSession = true;
info.needPoll = true;
info.parameterName = "";
return info;
}

}
Loading