mirror of
https://github.com/yunionio/cloudpods.git
synced 2026-08-30 17:13:08 +08:00
Automated cherry pick of #24194: Fix(llm): some mistakes, use CmpId & InstantModelId insteadof SvrId & ModelId (#24205)
* fix(llm): some mistakes * fix(llm): use CmpId instead of SvrId * fix(llm): instant_model use id instead of modelId --------- Co-authored-by: cwz <cwz_eikoh@163.com>
This commit is contained in:
+4
-3
@@ -48,15 +48,16 @@ type LLMBaseListDetails struct {
|
||||
|
||||
type MountedModelInfo struct {
|
||||
FullName string `json:"fullname"` // 模型全名,如: qwen3:8b
|
||||
Id string `json:"id"` // 模型ID,如: 500a1f067a9f
|
||||
ModelId string `json:"model_id"` // 模型ID,如: 500a1f067a9f
|
||||
Id string `json:"id"` // 秒装包的 ID 主键
|
||||
}
|
||||
|
||||
type LLMListDetails struct {
|
||||
LLMBaseListDetails
|
||||
|
||||
LLMSku string
|
||||
LLMSku string `json:"llm_sku"`
|
||||
|
||||
MountedModels []MountedModelInfo
|
||||
MountedModels []MountedModelInfo `json:"mounted_models"`
|
||||
}
|
||||
|
||||
type LLMBaseCreateInput struct {
|
||||
|
||||
@@ -116,6 +116,8 @@ type LLMSkuDetails struct {
|
||||
ImageLabel string
|
||||
ImageName string
|
||||
|
||||
MountedModelDetails []MountedModelInfo `json:"mounted_model_details"`
|
||||
|
||||
Template string `json:"template"`
|
||||
}
|
||||
|
||||
|
||||
@@ -102,9 +102,9 @@ func (o *ollama) GetContainerSpec(ctx context.Context, llm *models.SLLM, image *
|
||||
{
|
||||
Disk: &commonapi.ContainerVolumeMountDisk{
|
||||
SubDirectory: api.LLM_OLLAMA,
|
||||
Overlay: &commonapi.ContainerVolumeMountDiskOverlay{
|
||||
LowerDir: []string{api.LLM_OLLAMA_HOST_PATH},
|
||||
},
|
||||
// Overlay: &commonapi.ContainerVolumeMountDiskOverlay{
|
||||
// LowerDir: []string{api.LLM_OLLAMA_HOST_PATH},
|
||||
// },
|
||||
PostOverlay: postOverlays,
|
||||
Index: &diskIndex,
|
||||
},
|
||||
@@ -396,7 +396,6 @@ func (o *ollama) GetProbedInstantModelsExt(ctx context.Context, userCred mcclien
|
||||
return nil, errors.Wrap(err, "get llm container")
|
||||
}
|
||||
|
||||
// get all effective models
|
||||
getModels := "ollama list" // NAME ID SIZE MODIFIED
|
||||
modelsOutput, err := exec(ctx, lc.CmpId, getModels, 10)
|
||||
if err != nil {
|
||||
@@ -404,25 +403,35 @@ func (o *ollama) GetProbedInstantModelsExt(ctx context.Context, userCred mcclien
|
||||
}
|
||||
lines := strings.Split(strings.TrimSpace(modelsOutput), "\n")
|
||||
|
||||
models := make(map[string]api.LLMInternalInstantMdlInfo, len(lines)-1)
|
||||
modelsMap := make(map[string]api.LLMInternalInstantMdlInfo, len(lines)-1)
|
||||
for i := 1; i < len(lines); i++ {
|
||||
fields := strings.Fields(lines[i])
|
||||
if len(fields) > 2 {
|
||||
if len(mdlIds) > 0 && !utils.IsInStringArray(fields[1], mdlIds) {
|
||||
if len(fields) < 3 {
|
||||
continue
|
||||
}
|
||||
ollamaId := fields[1]
|
||||
modelName, modelTag, _ := llm.GetLargeLanguageModelName(fields[0])
|
||||
instMdl, _ := models.GetInstantModelManager().FindInstantModel(ollamaId, modelTag, true)
|
||||
var key string
|
||||
if instMdl != nil {
|
||||
key = instMdl.Id
|
||||
if len(mdlIds) > 0 && !utils.IsInStringArray(key, mdlIds) {
|
||||
continue
|
||||
}
|
||||
modelName, modelTag, _ := llm.GetLargeLanguageModelName(fields[0])
|
||||
models[fields[1]] = api.LLMInternalInstantMdlInfo{
|
||||
Name: modelName,
|
||||
Tag: modelTag,
|
||||
ModelId: fields[1],
|
||||
// Modified: fields[3],
|
||||
} else {
|
||||
key = ollamaId
|
||||
if len(mdlIds) > 0 {
|
||||
continue
|
||||
}
|
||||
}
|
||||
modelsMap[key] = api.LLMInternalInstantMdlInfo{
|
||||
Name: modelName,
|
||||
Tag: modelTag,
|
||||
ModelId: ollamaId,
|
||||
}
|
||||
}
|
||||
|
||||
// for each model, get manifests file, find blobs, calculate size
|
||||
for modelId, model := range models {
|
||||
for key, model := range modelsMap {
|
||||
manifests, err := getManifests(ctx, lc.CmpId, model.Name, model.Tag)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "get manifests")
|
||||
@@ -433,10 +442,10 @@ func (o *ollama) GetProbedInstantModelsExt(ctx context.Context, userCred mcclien
|
||||
model.Size += layer.Size
|
||||
model.Blobs = append(model.Blobs, layer.Digest)
|
||||
}
|
||||
models[modelId] = model
|
||||
modelsMap[key] = model
|
||||
}
|
||||
|
||||
return models, nil
|
||||
return modelsMap, nil
|
||||
}
|
||||
|
||||
func (o *ollama) ValidateMounts(mounts []string, mdlName string, mdlTag string) ([]string, error) {
|
||||
|
||||
@@ -271,10 +271,11 @@ func (man *SInstantModelManager) FetchCustomizeColumns(
|
||||
LlmId: llmInstModel.LlmId,
|
||||
LlmName: llm.Name,
|
||||
}
|
||||
if _, ok := modelMountedByMap[llmInstModel.ModelId]; !ok {
|
||||
modelMountedByMap[llmInstModel.ModelId] = make([]apis.MountedByLLMInfo, 0)
|
||||
instantModelId := llmInstModel.InstantModelId
|
||||
if _, ok := modelMountedByMap[instantModelId]; !ok {
|
||||
modelMountedByMap[instantModelId] = make([]apis.MountedByLLMInfo, 0)
|
||||
}
|
||||
modelMountedByMap[llmInstModel.ModelId] = append(modelMountedByMap[llmInstModel.ModelId], info)
|
||||
modelMountedByMap[instantModelId] = append(modelMountedByMap[instantModelId], info)
|
||||
}
|
||||
|
||||
for i := range res {
|
||||
@@ -286,7 +287,7 @@ func (man *SInstantModelManager) FetchCustomizeColumns(
|
||||
res[i].CacheCount = status.CacheCount
|
||||
res[i].CachedCount = status.CachedCount
|
||||
}
|
||||
if mountedBy, ok := modelMountedByMap[instModel.ModelId]; ok {
|
||||
if mountedBy, ok := modelMountedByMap[instModel.Id]; ok {
|
||||
res[i].MountedByLLMs = mountedBy
|
||||
}
|
||||
|
||||
@@ -530,7 +531,7 @@ func (man *SInstantModelManager) GetInstantModelById(id string) (*SInstantModel,
|
||||
return obj.(*SInstantModel), nil
|
||||
}
|
||||
|
||||
func (man *SInstantModelManager) findInstantModel(mdlId, tag string, isEnabled bool) (*SInstantModel, error) {
|
||||
func (man *SInstantModelManager) FindInstantModel(mdlId, tag string, isEnabled bool) (*SInstantModel, error) {
|
||||
q := man.Query().Equals("model_id", mdlId).Equals("status", imageapi.IMAGE_STATUS_ACTIVE)
|
||||
if isEnabled {
|
||||
q = q.IsTrue("enabled")
|
||||
@@ -667,7 +668,8 @@ func (model *SInstantModel) PerformPrivate(
|
||||
func (model *SInstantModel) ValidateDeleteCondition(ctx context.Context, info jsonutils.JSONObject) error {
|
||||
if model.Enabled.IsTrue() {
|
||||
for _, man := range []MountedModelModelManager{GetLLMSkuManager(), GetVolumeManager()} {
|
||||
used, err := man.IsPremountedModelName(model.ModelName + ":" + model.ModelTag + "-" + model.ModelId)
|
||||
// volume/sku 存储格式为 modelFullName-instantModelId
|
||||
used, err := man.IsPremountedModelName(model.ModelName + ":" + model.ModelTag + "-" + model.Id)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "IsPremountedModelName")
|
||||
}
|
||||
|
||||
@@ -145,8 +145,8 @@ func (man *SLLMManager) FetchCustomizeColumns(
|
||||
ids[idx] = llm.Id
|
||||
skuIds[idx] = llm.LLMSkuId
|
||||
imgIds[idx] = llm.LLMImageId
|
||||
if !utils.IsInArray(llm.SvrId, serverIds) {
|
||||
serverIds = append(serverIds, llm.SvrId)
|
||||
if !utils.IsInArray(llm.CmpId, serverIds) {
|
||||
serverIds = append(serverIds, llm.CmpId)
|
||||
}
|
||||
if len(llm.NetworkId) > 0 {
|
||||
networkIds = append(networkIds, llm.NetworkId)
|
||||
@@ -165,7 +165,7 @@ func (man *SLLMManager) FetchCustomizeColumns(
|
||||
for i, id := range ids {
|
||||
if id == volume.LLMId {
|
||||
res[i].Volume = api.Volume{
|
||||
Id: volume.Id,
|
||||
Id: volume.CmpId,
|
||||
Name: volume.Name,
|
||||
TemplateId: volume.TemplateId,
|
||||
StorageType: volume.StorageType,
|
||||
@@ -262,7 +262,7 @@ func (man *SLLMManager) FetchCustomizeColumns(
|
||||
for i := range llms {
|
||||
llmStatus := api.LLM_STATUS_UNKNOWN
|
||||
llm := llms[i]
|
||||
if guest, ok := serverMap[llm.SvrId]; ok {
|
||||
if guest, ok := serverMap[llm.CmpId]; ok {
|
||||
// find guest
|
||||
if len(guest.Containers) == 0 {
|
||||
llmStatus = api.LLM_LLM_STATUS_NO_CONTAINER
|
||||
|
||||
@@ -44,7 +44,7 @@ type SLLMBase struct {
|
||||
db.SVirtualResourceBase
|
||||
db.SEnabledResourceBase
|
||||
|
||||
SvrId string `width:"128" charset:"ascii" nullable:"true" list:"user"`
|
||||
CmpId string `width:"128" charset:"ascii" nullable:"true" list:"user"`
|
||||
LLMIp string `width:"20" charset:"ascii" nullable:"true" list:"user"`
|
||||
// Hypervisor string `width:"128" charset:"ascii" nullable:"true" list:"user"`
|
||||
Priority int `nullable:"false" default:"100" list:"user"`
|
||||
@@ -298,7 +298,7 @@ func (man *SLLMBaseManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQue
|
||||
}
|
||||
|
||||
func (llm *SLLMBase) GetServer(ctx context.Context) (*computeapi.ServerDetails, error) {
|
||||
return cloudutil.GetServer(ctx, llm.SvrId)
|
||||
return cloudutil.GetServer(ctx, llm.CmpId)
|
||||
}
|
||||
|
||||
func (llm *SLLMBase) GetVolume() (*SVolume, error) {
|
||||
@@ -353,7 +353,7 @@ func (llm *SLLMBase) RealDelete(ctx context.Context, userCred mcclient.TokenCred
|
||||
}
|
||||
|
||||
func (llm *SLLMBase) ServerDelete(ctx context.Context, userCred mcclient.TokenCredential, s *mcclient.ClientSession) error {
|
||||
if len(llm.SvrId) == 0 {
|
||||
if len(llm.CmpId) == 0 {
|
||||
return nil
|
||||
}
|
||||
server, err := llm.GetServer(ctx)
|
||||
@@ -367,12 +367,12 @@ func (llm *SLLMBase) ServerDelete(ctx context.Context, userCred mcclient.TokenCr
|
||||
if server.DisableDelete != nil && *server.DisableDelete {
|
||||
// update to allow delete
|
||||
s2 := auth.GetSession(ctx, userCred, "")
|
||||
_, err = compute.Servers.Update(s2, llm.SvrId, jsonutils.Marshal(map[string]interface{}{"disable_delete": false}))
|
||||
_, err = compute.Servers.Update(s2, llm.CmpId, jsonutils.Marshal(map[string]interface{}{"disable_delete": false}))
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "update server to delete")
|
||||
}
|
||||
}
|
||||
_, err = compute.Servers.DeleteWithParam(s, llm.SvrId, jsonutils.Marshal(map[string]interface{}{
|
||||
_, err = compute.Servers.DeleteWithParam(s, llm.CmpId, jsonutils.Marshal(map[string]interface{}{
|
||||
"override_pending_delete": true,
|
||||
}), nil)
|
||||
if err != nil {
|
||||
@@ -382,7 +382,7 @@ func (llm *SLLMBase) ServerDelete(ctx context.Context, userCred mcclient.TokenCr
|
||||
}
|
||||
|
||||
func (llm *SLLMBase) WaitDelete(ctx context.Context, userCred mcclient.TokenCredential, timeoutSecs int) error {
|
||||
return cloudutil.WaitDelete[computeapi.ServerDetails](ctx, &compute.Servers, llm.SvrId, timeoutSecs)
|
||||
return cloudutil.WaitDelete[computeapi.ServerDetails](ctx, &compute.Servers, llm.CmpId, timeoutSecs)
|
||||
}
|
||||
|
||||
func (llm *SLLMBase) getImage(imageId string) (*SLLMImage, error) {
|
||||
@@ -394,5 +394,5 @@ func (llm *SLLMBase) getImage(imageId string) (*SLLMImage, error) {
|
||||
}
|
||||
|
||||
func (llm *SLLMBase) WaitServerStatus(ctx context.Context, userCred mcclient.TokenCredential, targetStatus []string, timeoutSecs int) (*computeapi.ServerDetails, error) {
|
||||
return cloudutil.WaitServerStatus(ctx, llm.SvrId, targetStatus, timeoutSecs)
|
||||
return cloudutil.WaitServerStatus(ctx, llm.CmpId, targetStatus, timeoutSecs)
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ import (
|
||||
"fmt"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/util/seclib"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/apis"
|
||||
computeapi "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
@@ -45,7 +44,8 @@ func GetLLMBasePodCreateInput(
|
||||
|
||||
data.VcpuCount = skuBase.Cpu
|
||||
data.VmemSize = skuBase.Memory + 1
|
||||
data.Name = input.Name + "-" + seclib.RandomPassword(6)
|
||||
// data.Name = input.Name + "-" + seclib.RandomPassword(6)
|
||||
data.Name = input.Name
|
||||
|
||||
// disks
|
||||
data.Disks = make([]*computeapi.DiskConfig, 0)
|
||||
|
||||
@@ -44,10 +44,9 @@ type SLLMInstantModel struct {
|
||||
db.SResourceBase
|
||||
db.SStatusResourceBase
|
||||
|
||||
// InstantModelId string `name:"model_id" width:"128" charset:"ascii" nullable:"false" list:"user" primary:"true"`
|
||||
LlmId string `width:"128" charset:"ascii" nullable:"false" list:"user" primary:"true"`
|
||||
// Model ID, large language model's ID, referring to special model, such as qwen3:8b
|
||||
ModelId string `name:"model_id" width:"128" charset:"ascii" nullable:"false" list:"user" primary:"true"`
|
||||
// InstantModelId instant model 主键 id(SInstantModel.Id)
|
||||
InstantModelId string `name:"model_id" width:"128" charset:"ascii" nullable:"false" list:"user" primary:"true"`
|
||||
|
||||
// Model Tag
|
||||
Tag string `width:"64" charset:"utf8" nullable:"true" list:"user"`
|
||||
@@ -58,8 +57,8 @@ type SLLMInstantModel struct {
|
||||
// IsSystem tristate.TriState `list:"user"`
|
||||
}
|
||||
|
||||
func (man *SLLMInstantModelManager) fetchLLMInstantModel(llmId string, mdlId string) (*SLLMInstantModel, error) {
|
||||
q := man.RawQuery().Equals("llm_id", llmId).Equals("model_id", mdlId)
|
||||
func (man *SLLMInstantModelManager) fetchLLMInstantModel(llmId string, instantModelId string) (*SLLMInstantModel, error) {
|
||||
q := man.RawQuery().Equals("llm_id", llmId).Equals("model_id", instantModelId)
|
||||
llmInstantModel := SLLMInstantModel{}
|
||||
err := q.First(&llmInstantModel)
|
||||
if err != nil {
|
||||
@@ -79,15 +78,15 @@ func (man *SLLMInstantModelManager) getDeletedModelIds(llmId string) ([]string,
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Query")
|
||||
}
|
||||
modelIds := make([]string, len(llmInstantModel))
|
||||
instantModelIds := make([]string, len(llmInstantModel))
|
||||
for i := range llmInstantModel {
|
||||
modelIds[i] = llmInstantModel[i].ModelId
|
||||
instantModelIds[i] = llmInstantModel[i].InstantModelId
|
||||
}
|
||||
return modelIds, nil
|
||||
return instantModelIds, nil
|
||||
}
|
||||
|
||||
func (man *SLLMInstantModelManager) updateInstantModel(ctx context.Context, llmId string, mdlId string, mdlName string, tag string, probed, mounted *bool) (*SLLMInstantModel, error) {
|
||||
mdl, err := man.fetchLLMInstantModel(llmId, mdlId)
|
||||
func (man *SLLMInstantModelManager) updateInstantModel(ctx context.Context, llmId string, instantModelId string, mdlName string, tag string, probed, mounted *bool) (*SLLMInstantModel, error) {
|
||||
mdl, err := man.fetchLLMInstantModel(llmId, instantModelId)
|
||||
if err != nil && errors.Cause(err) != errors.ErrNotFound {
|
||||
return nil, errors.Wrap(err, "updateInstantModel")
|
||||
}
|
||||
@@ -105,9 +104,9 @@ func (man *SLLMInstantModelManager) updateInstantModel(ctx context.Context, llmI
|
||||
if mdl == nil {
|
||||
// if no such app
|
||||
mdl = &SLLMInstantModel{
|
||||
LlmId: llmId,
|
||||
ModelId: mdlId,
|
||||
ModelName: mdlName,
|
||||
LlmId: llmId,
|
||||
InstantModelId: instantModelId,
|
||||
ModelName: mdlName,
|
||||
// IsSystem: tristate.None,
|
||||
// Entry: entry,
|
||||
}
|
||||
@@ -200,7 +199,7 @@ func (man *SLLMInstantModelManager) filterModels(q *sqlchemy.SQuery, isProbed, i
|
||||
}
|
||||
|
||||
func (mdl *SLLMInstantModel) FindInstantModel(isInstall bool) (*SInstantModel, error) {
|
||||
instMdl, err := GetInstantModelManager().findInstantModel(mdl.ModelId, mdl.Tag, isInstall)
|
||||
instMdl, err := GetInstantModelManager().GetInstantModelById(mdl.InstantModelId)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "FindInstantModel")
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ func (llm *SLLM) GetInstantModelSizeGb() float64 {
|
||||
}
|
||||
totalSizeGb := 0.0
|
||||
for _, model := range models {
|
||||
instModel, _ := GetInstantModelManager().findInstantModel(model.ModelId, model.Tag, false)
|
||||
instModel, _ := GetInstantModelManager().GetInstantModelById(model.InstantModelId)
|
||||
if instModel == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -90,27 +90,26 @@ func (llm *SLLM) getProbedMountedInstantModels(ctx context.Context, userCred mcc
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "llm.getMountedInstantModels")
|
||||
}
|
||||
for mdlId := range mounted {
|
||||
if _, ok := mdlMap[mdlId]; ok {
|
||||
mdlMap[mdlId].Mounted = true
|
||||
for instantModelId := range mounted {
|
||||
if _, ok := mdlMap[instantModelId]; ok {
|
||||
mdlMap[instantModelId].Mounted = true
|
||||
} else {
|
||||
mdlMap[mdlId] = &sInstantModelStatus{
|
||||
LLMInternalInstantMdlInfo: apis.LLMInternalInstantMdlInfo{
|
||||
ModelId: mdlId,
|
||||
},
|
||||
Mounted: true,
|
||||
// 仅 mounted 未 probed 时无 ollama model id,ModelId 留空
|
||||
mdlMap[instantModelId] = &sInstantModelStatus{
|
||||
LLMInternalInstantMdlInfo: apis.LLMInternalInstantMdlInfo{},
|
||||
Mounted: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
return mdlMap, nil
|
||||
}
|
||||
|
||||
func (llm *SLLM) uninstallInstantModel(ctx context.Context, userCred mcclient.TokenCredential, mdlId string) error {
|
||||
func (llm *SLLM) uninstallInstantModel(ctx context.Context, userCred mcclient.TokenCredential, instantModelId string) error {
|
||||
boolFalse := false
|
||||
// uninstalled
|
||||
probed := &boolFalse
|
||||
mounted := &boolFalse
|
||||
_, err := GetLLMInstantModelManager().updateInstantModel(ctx, llm.Id, mdlId, "", "", probed, mounted)
|
||||
_, err := GetLLMInstantModelManager().updateInstantModel(ctx, llm.Id, instantModelId, "", "", probed, mounted)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "uninstallPackage")
|
||||
}
|
||||
@@ -119,7 +118,7 @@ func (llm *SLLM) uninstallInstantModel(ctx context.Context, userCred mcclient.To
|
||||
|
||||
func findInstantModelWithModelInfo(allModels []SLLMInstantModel, mdl apis.ModelInfo) *SLLMInstantModel {
|
||||
for i := range allModels {
|
||||
if allModels[i].ModelId == mdl.ModelId {
|
||||
if allModels[i].InstantModelId == mdl.Id {
|
||||
return &allModels[i]
|
||||
}
|
||||
}
|
||||
@@ -157,7 +156,7 @@ func isImageInUnmountModels(imageId string, mdls []SLLMInstantModel) (bool, erro
|
||||
return false, nil
|
||||
}
|
||||
for i := range mdls {
|
||||
if mdls[i].ModelId == instMdl.ModelId {
|
||||
if mdls[i].InstantModelId == instMdl.Id {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
@@ -188,15 +187,15 @@ func (llm *SLLM) RefreshInstantModels(ctx context.Context, userCred mcclient.Tok
|
||||
mdl := models[i]
|
||||
var probed *bool
|
||||
var mounted *bool
|
||||
if status, ok := mdlMap[mdl.ModelId]; ok {
|
||||
if status, ok := mdlMap[mdl.InstantModelId]; ok {
|
||||
// probed
|
||||
probed = &status.Probed
|
||||
mounted = &status.Mounted
|
||||
_, err = GetLLMInstantModelManager().updateInstantModel(ctx, llm.Id, mdl.ModelId, status.Name, status.Tag, probed, mounted)
|
||||
delete(mdlMap, mdl.ModelId)
|
||||
_, err = GetLLMInstantModelManager().updateInstantModel(ctx, llm.Id, mdl.InstantModelId, status.Name, status.Tag, probed, mounted)
|
||||
delete(mdlMap, mdl.InstantModelId)
|
||||
} else {
|
||||
// uninstalled
|
||||
err = llm.uninstallInstantModel(ctx, userCred, mdl.ModelId)
|
||||
err = llm.uninstallInstantModel(ctx, userCred, mdl.InstantModelId)
|
||||
}
|
||||
if err != nil {
|
||||
errs = append(errs, err)
|
||||
@@ -204,8 +203,8 @@ func (llm *SLLM) RefreshInstantModels(ctx context.Context, userCred mcclient.Tok
|
||||
}
|
||||
|
||||
if len(mdlMap) > 0 {
|
||||
for mdlId, status := range mdlMap {
|
||||
_, err := GetLLMInstantModelManager().updateInstantModel(ctx, llm.Id, mdlId, status.Name, status.Tag, &status.Probed, &status.Mounted)
|
||||
for instantModelId, status := range mdlMap {
|
||||
_, err := GetLLMInstantModelManager().updateInstantModel(ctx, llm.Id, instantModelId, status.Name, status.Tag, &status.Probed, &status.Mounted)
|
||||
if err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
@@ -260,7 +259,7 @@ func (llm *SLLM) PerformQuickModels(ctx context.Context, userCred mcclient.Token
|
||||
}
|
||||
}
|
||||
} else {
|
||||
mdl, err := GetInstantModelManager().findInstantModel(input.Models[i].ModelId, input.Models[i].Tag, true)
|
||||
mdl, err := GetInstantModelManager().FindInstantModel(input.Models[i].ModelId, input.Models[i].Tag, true)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "findInstantModel %s %s", input.Models[i].ModelId, input.Models[i].Tag)
|
||||
}
|
||||
@@ -274,7 +273,7 @@ func (llm *SLLM) PerformQuickModels(ctx context.Context, userCred mcclient.Token
|
||||
}
|
||||
}
|
||||
if !apis.IsLLMContainerType(input.Models[i].LlmType) || apis.LLMContainerType(input.Models[i].LlmType) != llm.GetLLMContainerDriver().GetType() {
|
||||
errs = append(errs, errors.Wrapf(httperrors.ErrInvalidStatus, "model %s is not of type %s", input.Models[i].ModelId, llm.GetLLMContainerDriver().GetType()))
|
||||
errs = append(errs, errors.Wrapf(httperrors.ErrInvalidStatus, "model %s is not of type %s", input.Models[i].Id, llm.GetLLMContainerDriver().GetType()))
|
||||
}
|
||||
}
|
||||
if len(errs) > 0 {
|
||||
@@ -348,7 +347,7 @@ func (llm *SLLM) FetchModelsFullName(isProbed, isMounted *bool) ([]string, error
|
||||
}
|
||||
mdlFullNames := make([]string, len(models))
|
||||
for idx, mdl := range models {
|
||||
mdlFullNames[idx] = mdl.ModelName + ":" + mdl.Tag + "-" + mdl.ModelId
|
||||
mdlFullNames[idx] = mdl.ModelName + ":" + mdl.Tag + "-" + mdl.InstantModelId
|
||||
}
|
||||
return mdlFullNames, nil
|
||||
}
|
||||
@@ -366,9 +365,15 @@ func (llm *SLLM) FetchMountedModelInfo() ([]apis.MountedModelInfo, error) {
|
||||
}
|
||||
result := make([]apis.MountedModelInfo, len(models))
|
||||
for idx, mdl := range models {
|
||||
instMdl, _ := GetInstantModelManager().GetInstantModelById(mdl.InstantModelId)
|
||||
modelIdForDisplay := ""
|
||||
if instMdl != nil {
|
||||
modelIdForDisplay = instMdl.ModelId
|
||||
}
|
||||
result[idx] = apis.MountedModelInfo{
|
||||
FullName: mdl.ModelName + ":" + mdl.Tag,
|
||||
Id: mdl.ModelId,
|
||||
ModelId: modelIdForDisplay,
|
||||
Id: mdl.InstantModelId,
|
||||
}
|
||||
}
|
||||
return result, nil
|
||||
@@ -428,7 +433,7 @@ func (llm *SLLM) RequestUnmountModel(ctx context.Context, userCred mcclient.Toke
|
||||
|
||||
var modelIds []string
|
||||
for i := range unmountModels {
|
||||
modelIds = append(modelIds, unmountModels[i].ModelId)
|
||||
modelIds = append(modelIds, unmountModels[i].InstantModelId)
|
||||
}
|
||||
return modelIds, unmountOverlays, nil
|
||||
}
|
||||
@@ -459,7 +464,7 @@ func (llm *SLLM) RequestMountModels(ctx context.Context, userCred mcclient.Token
|
||||
log.Errorf("preinstallPackage fail %s", err)
|
||||
}
|
||||
}
|
||||
mdlIds = append(mdlIds, model.ModelId)
|
||||
mdlIds = append(mdlIds, model.InstantModelId)
|
||||
}
|
||||
targetDirs := make([]string, 0)
|
||||
for i := range overlays {
|
||||
@@ -610,9 +615,9 @@ func (llm *SLLM) UpdateVolumeMountedModelFullNames(mdlFullNames []string) error
|
||||
}
|
||||
|
||||
type mdlFullNameInfo struct {
|
||||
ModelId string
|
||||
ModelFullName string
|
||||
IsMounted bool
|
||||
InstantModelId string // instant model 主键 id
|
||||
ModelFullName string
|
||||
IsMounted bool
|
||||
}
|
||||
|
||||
func (llm *SLLM) UpdateMountedModelFullNames(ctx context.Context, userCred mcclient.TokenCredential, mdlinfos []string, isReset bool, imageId string, skuId string) error {
|
||||
@@ -620,9 +625,9 @@ func (llm *SLLM) UpdateMountedModelFullNames(ctx context.Context, userCred mccli
|
||||
for i := range mdlinfos {
|
||||
parts := strings.Split(mdlinfos[i], "@")
|
||||
mdlFullNameInfos[parts[0]] = &mdlFullNameInfo{
|
||||
ModelId: parts[0],
|
||||
ModelFullName: parts[1],
|
||||
IsMounted: false,
|
||||
InstantModelId: parts[0],
|
||||
ModelFullName: parts[1],
|
||||
IsMounted: false,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -646,15 +651,15 @@ func (llm *SLLM) UpdateMountedModelFullNames(ctx context.Context, userCred mccli
|
||||
return errors.Wrap(err, "FetchByIdOrName")
|
||||
}
|
||||
instantModle := instMdl.(*SInstantModel)
|
||||
if !isReset && slices.Contains(deletedModelIds, instantModle.ModelId) {
|
||||
if !isReset && slices.Contains(deletedModelIds, instantModle.Id) {
|
||||
// if not reset, and the model is deleted, skip it
|
||||
continue
|
||||
}
|
||||
if _, ok := mdlFullNameInfos[instantModle.ModelId]; !ok {
|
||||
mdlFullNameInfos[instantModle.ModelId] = &mdlFullNameInfo{
|
||||
ModelId: instantModle.ModelId,
|
||||
ModelFullName: instantModle.ModelName + ":" + instantModle.ModelTag,
|
||||
IsMounted: false,
|
||||
if _, ok := mdlFullNameInfos[instantModle.Id]; !ok {
|
||||
mdlFullNameInfos[instantModle.Id] = &mdlFullNameInfo{
|
||||
InstantModelId: instantModle.Id,
|
||||
ModelFullName: instantModle.ModelName + ":" + instantModle.ModelTag,
|
||||
IsMounted: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -668,15 +673,15 @@ func (llm *SLLM) UpdateMountedModelFullNames(ctx context.Context, userCred mccli
|
||||
}
|
||||
for i := range mountedModels {
|
||||
find := false
|
||||
if _, ok := mdlFullNameInfos[mountedModels[i].ModelId]; ok {
|
||||
if _, ok := mdlFullNameInfos[mountedModels[i].InstantModelId]; ok {
|
||||
find = true
|
||||
mdlFullNameInfos[mountedModels[i].ModelId].IsMounted = true
|
||||
mdlFullNameInfos[mountedModels[i].InstantModelId].IsMounted = true
|
||||
}
|
||||
if isReset && !find {
|
||||
// remove instant model not in mdlInfos
|
||||
mountedModel := mountedModels[i]
|
||||
log.Debugf("UpdateMountedModelFullNames remove model %s", mountedModel.ModelId)
|
||||
_, err := GetLLMInstantModelManager().updateInstantModel(ctx, llm.Id, mountedModel.ModelId, "", "", &boolFalse, &boolFalse)
|
||||
log.Debugf("UpdateMountedModelFullNames remove model %s", mountedModel.InstantModelId)
|
||||
_, err := GetLLMInstantModelManager().updateInstantModel(ctx, llm.Id, mountedModel.InstantModelId, "", "", &boolFalse, &boolFalse)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "remove instant model")
|
||||
}
|
||||
@@ -685,10 +690,10 @@ func (llm *SLLM) UpdateMountedModelFullNames(ctx context.Context, userCred mccli
|
||||
|
||||
installModelFullNames := make([]string, 0)
|
||||
for _, mdlFullNameInfo := range mdlFullNameInfos {
|
||||
installModelFullNames = append(installModelFullNames, fmt.Sprintf("%s-%s", mdlFullNameInfo.ModelFullName, mdlFullNameInfo.ModelId))
|
||||
installModelFullNames = append(installModelFullNames, fmt.Sprintf("%s-%s", mdlFullNameInfo.ModelFullName, mdlFullNameInfo.InstantModelId))
|
||||
if !mdlFullNameInfo.IsMounted {
|
||||
modelName, modelTag, _ := llm.GetLargeLanguageModelName(mdlFullNameInfo.ModelFullName)
|
||||
_, err := GetLLMInstantModelManager().updateInstantModel(ctx, llm.Id, mdlFullNameInfo.ModelId, modelName, modelTag, &boolFalse, &boolTrue)
|
||||
_, err := GetLLMInstantModelManager().updateInstantModel(ctx, llm.Id, mdlFullNameInfo.InstantModelId, modelName, modelTag, &boolFalse, &boolTrue)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "install model")
|
||||
}
|
||||
@@ -735,9 +740,9 @@ func (llm *SLLM) getMountingModelsPostOverlay(ctx context.Context, input apis.LL
|
||||
continue
|
||||
}
|
||||
}
|
||||
model, err := GetLLMInstantModelManager().updateInstantModel(ctx, llm.Id, mdl.ModelId, mdl.DisplayName, mdl.Tag, nil, nil)
|
||||
model, err := GetLLMInstantModelManager().updateInstantModel(ctx, llm.Id, mdl.Id, mdl.DisplayName, mdl.Tag, nil, nil)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrapf(err, "updateInstantModel %s", mdl.ModelId)
|
||||
return nil, nil, errors.Wrapf(err, "updateInstantModel %s", mdl.Id)
|
||||
}
|
||||
models = append(models, *model)
|
||||
}
|
||||
|
||||
@@ -41,17 +41,23 @@ func (llm *SLLM) PerformSaveInstantModel(
|
||||
return nil, httperrors.NewInvalidStatusError("LLM is not running")
|
||||
}
|
||||
|
||||
mdlInfos, err := llm.getProbedInstantModelsExt(ctx, userCred, input.ModelId)
|
||||
mdlInfos, err := llm.getProbedInstantModelsExt(ctx, userCred)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "getProbedPackagesExt")
|
||||
}
|
||||
|
||||
mdlInfo, ok := mdlInfos[input.ModelId]
|
||||
if !ok {
|
||||
var mdlInfo *api.LLMInternalInstantMdlInfo
|
||||
for _, info := range mdlInfos {
|
||||
if info.ModelId == input.ModelId {
|
||||
mdlInfo = &info
|
||||
break
|
||||
}
|
||||
}
|
||||
if mdlInfo == nil {
|
||||
return nil, httperrors.NewBadRequestError("ModelId %s not found", input.ModelId)
|
||||
}
|
||||
|
||||
mountDirs, err := llm.detectModelPaths(ctx, userCred, mdlInfo)
|
||||
mountDirs, err := llm.detectModelPaths(ctx, userCred, *mdlInfo)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "detectModelPaths")
|
||||
}
|
||||
@@ -144,7 +150,7 @@ func (llm *SLLM) DoSaveModelImage(ctx context.Context, userCred mcclient.TokenCr
|
||||
|
||||
saveImageInput := computeapi.ContainerSaveVolumeMountToImageInput{
|
||||
GenerateName: input.ModelFullName,
|
||||
Notes: fmt.Sprintf("instance model image for %s(%s)", input.ModelId, instantModel.ModelName+":"+instantModel.ModelTag),
|
||||
Notes: fmt.Sprintf("instance model image for %s(%s)", instantModel.ModelId, instantModel.ModelName+":"+instantModel.ModelTag),
|
||||
Index: 0,
|
||||
Dirs: saveDirs,
|
||||
UsedByPostOverlay: true,
|
||||
|
||||
@@ -109,6 +109,7 @@ func (manager *SLLMSkuManager) FetchCustomizeColumns(
|
||||
}{}
|
||||
q.All(&details)
|
||||
res := make([]api.LLMSkuDetails, len(objs))
|
||||
mountedModelIds := make([]string, 0)
|
||||
for i, sku := range skus {
|
||||
res[i].SharableVirtualResourceDetails = virows[i]
|
||||
for _, v := range details {
|
||||
@@ -117,6 +118,34 @@ func (manager *SLLMSkuManager) FetchCustomizeColumns(
|
||||
break
|
||||
}
|
||||
}
|
||||
if len(sku.MountedModels) > 0 {
|
||||
mountedModelIds = append(mountedModelIds, sku.MountedModels...)
|
||||
}
|
||||
}
|
||||
|
||||
// fetch mounted models
|
||||
if len(mountedModelIds) > 0 {
|
||||
instModels := make(map[string]SInstantModel)
|
||||
err := db.FetchModelObjectsByIds(GetInstantModelManager(), "id", mountedModelIds, &instModels)
|
||||
if err != nil {
|
||||
log.Errorf("FetchModelObjectsByIds InstantModelManager fail %s", err)
|
||||
} else {
|
||||
for i, sku := range skus {
|
||||
if len(sku.MountedModels) > 0 {
|
||||
res[i].MountedModelDetails = make([]api.MountedModelInfo, 0)
|
||||
for _, modelId := range sku.MountedModels {
|
||||
if instModel, ok := instModels[modelId]; ok {
|
||||
info := api.MountedModelInfo{
|
||||
Id: instModel.Id,
|
||||
ModelId: instModel.ModelId,
|
||||
FullName: instModel.ModelName + ":" + instModel.ModelTag,
|
||||
}
|
||||
res[i].MountedModelDetails = append(res[i].MountedModelDetails, info)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
images := make(map[string]SLLMImage)
|
||||
|
||||
@@ -62,7 +62,7 @@ type SVolume struct {
|
||||
TemplateId string `width:"128" charset:"ascii" nullable:"true" list:"user" create:"admin_optional" update:"user"`
|
||||
// size in MB
|
||||
SizeMB int `nullable:"false" default:"0" create:"optional" list:"user" update:"user"`
|
||||
SvrId string `width:"128" charset:"ascii" nullable:"true" list:"user"`
|
||||
CmpId string `width:"128" charset:"ascii" nullable:"true" list:"user"`
|
||||
Containers api.ContainerVolumeRelations `charset:"utf8" nullable:"true" list:"user" create:"optional"`
|
||||
}
|
||||
|
||||
@@ -106,17 +106,17 @@ func (volume *SVolume) UpdateMountedModelFullNames(mountModels []string) error {
|
||||
}
|
||||
|
||||
func (volume *SVolume) GetDisk(ctx context.Context) (*computeapi.DiskDetails, error) {
|
||||
if len(volume.SvrId) == 0 {
|
||||
if len(volume.CmpId) == 0 {
|
||||
return nil, errors.ErrInvalidStatus
|
||||
}
|
||||
s := auth.GetAdminSession(ctx, "")
|
||||
disk := computeapi.DiskDetails{}
|
||||
resp, err := compute.Disks.GetById(s, volume.SvrId, jsonutils.Marshal(map[string]interface{}{
|
||||
resp, err := compute.Disks.GetById(s, volume.CmpId, jsonutils.Marshal(map[string]interface{}{
|
||||
"scope": "max",
|
||||
}))
|
||||
if err != nil {
|
||||
if httputils.ErrorCode(err) == 404 {
|
||||
return nil, errors.Wrapf(errors.ErrNotFound, "GetById %s", volume.SvrId)
|
||||
return nil, errors.Wrapf(errors.ErrNotFound, "GetById %s", volume.CmpId)
|
||||
}
|
||||
return nil, errors.Wrap(err, "fetch disk")
|
||||
}
|
||||
|
||||
@@ -56,10 +56,10 @@ func (task *DifyCreateTask) OnInit(ctx context.Context, obj db.IStandaloneModel,
|
||||
}
|
||||
|
||||
db.Update(dify, func() error {
|
||||
dify.SvrId = serverId
|
||||
dify.CmpId = serverId
|
||||
return nil
|
||||
})
|
||||
dify.SvrId = serverId
|
||||
dify.CmpId = serverId
|
||||
return nil
|
||||
})
|
||||
// var expectStatus []string
|
||||
@@ -91,7 +91,7 @@ func (task *DifyCreateTask) OnDifyRefreshStatusComplete(ctx context.Context, dif
|
||||
// 创建磁盘
|
||||
for _, disk := range server.DisksInfo {
|
||||
volume := models.SVolume{}
|
||||
volume.SvrId = disk.Id
|
||||
volume.CmpId = disk.Id
|
||||
volume.LLMId = dify.Id
|
||||
volume.SizeMB = disk.SizeMb
|
||||
volume.Name = disk.Name
|
||||
|
||||
@@ -33,7 +33,7 @@ func (task *DifyDeleteTask) OnInit(ctx context.Context, obj db.IStandaloneModel,
|
||||
dify := obj.(*models.SDify)
|
||||
dify.SetStatus(ctx, task.UserCred, api.LLM_STATUS_DELETING, "start delete")
|
||||
|
||||
if len(dify.SvrId) == 0 {
|
||||
if len(dify.CmpId) == 0 {
|
||||
task.OnDifyRefreshStatusComplete(ctx, dify, nil)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ func (t *DifyStartTask) requestStart(ctx context.Context, dify *models.SDify) {
|
||||
t.SetStage("OnStarted", nil)
|
||||
s := auth.GetSession(ctx, t.GetUserCred(), options.Options.Region)
|
||||
err := s.WithTaskCallback(t.GetId(), func() error {
|
||||
_, err := compute.Servers.PerformAction(s, dify.SvrId, "start", nil)
|
||||
_, err := compute.Servers.PerformAction(s, dify.CmpId, "start", nil)
|
||||
return err
|
||||
})
|
||||
if err != nil {
|
||||
|
||||
@@ -57,7 +57,7 @@ func (task *DifyStopTask) OnInit(ctx context.Context, obj db.IStandaloneModel, b
|
||||
task.SetStage("OnStopComplete", nil)
|
||||
s := auth.GetSession(ctx, task.UserCred, "")
|
||||
s.WithTaskCallback(task.GetId(), func() error {
|
||||
_, err = compute.Servers.PerformAction(s, dify.SvrId, "stop", nil)
|
||||
_, err = compute.Servers.PerformAction(s, dify.CmpId, "stop", nil)
|
||||
return err
|
||||
})
|
||||
if err != nil {
|
||||
|
||||
@@ -56,10 +56,10 @@ func (task *LLMCreateTask) OnInit(ctx context.Context, obj db.IStandaloneModel,
|
||||
}
|
||||
|
||||
db.Update(llm, func() error {
|
||||
llm.SvrId = serverId
|
||||
llm.CmpId = serverId
|
||||
return nil
|
||||
})
|
||||
llm.SvrId = serverId
|
||||
llm.CmpId = serverId
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
@@ -99,7 +99,7 @@ func (task *LLMCreateTask) OnLLMRefreshStatusComplete(ctx context.Context, llm *
|
||||
// 创建磁盘
|
||||
for _, disk := range server.DisksInfo {
|
||||
volume := models.SVolume{}
|
||||
volume.SvrId = disk.Id
|
||||
volume.CmpId = disk.Id
|
||||
volume.LLMId = llm.Id
|
||||
volume.SizeMB = disk.SizeMb
|
||||
volume.Name = disk.Name
|
||||
|
||||
@@ -34,7 +34,7 @@ func (task *LLMDeleteTask) OnInit(ctx context.Context, obj db.IStandaloneModel,
|
||||
llm := obj.(*models.SLLM)
|
||||
llm.SetStatus(ctx, task.UserCred, api.LLM_STATUS_DELETING, "start delete")
|
||||
|
||||
if len(llm.SvrId) == 0 {
|
||||
if len(llm.CmpId) == 0 {
|
||||
task.OnLLMRefreshStatusComplete(ctx, llm, nil)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ func (t *LLMStartTask) requestStart(ctx context.Context, llm *models.SLLM) {
|
||||
t.SetStage("OnStarted", nil)
|
||||
s := auth.GetSession(ctx, t.GetUserCred(), options.Options.Region)
|
||||
err := s.WithTaskCallback(t.GetId(), func() error {
|
||||
_, err := compute.Servers.PerformAction(s, llm.SvrId, "start", nil)
|
||||
_, err := compute.Servers.PerformAction(s, llm.CmpId, "start", nil)
|
||||
return err
|
||||
})
|
||||
if err != nil {
|
||||
|
||||
@@ -57,7 +57,7 @@ func (task *LLMStopTask) OnInit(ctx context.Context, obj db.IStandaloneModel, bo
|
||||
task.SetStage("OnStopComplete", nil)
|
||||
s := auth.GetSession(ctx, task.UserCred, "")
|
||||
err = s.WithTaskCallback(task.GetId(), func() error {
|
||||
_, err = compute.Servers.PerformAction(s, llm.SvrId, "stop", nil)
|
||||
_, err = compute.Servers.PerformAction(s, llm.CmpId, "stop", nil)
|
||||
return err
|
||||
})
|
||||
if err != nil {
|
||||
|
||||
@@ -51,7 +51,7 @@ func (task *LLMSyncStatusTask) OnInit(ctx context.Context, obj db.IStandaloneMod
|
||||
task.setLLMStatus(ctx, llm, apis.LLM_STATUS_SYNCSTATUS, "LLMSyncStatusTask.OnInit")
|
||||
|
||||
s := auth.GetSession(ctx, task.UserCred, "")
|
||||
_, err := compute.Servers.PerformAction(s, llm.SvrId, "syncstatus", nil)
|
||||
_, err := compute.Servers.PerformAction(s, llm.CmpId, "syncstatus", nil)
|
||||
if err != nil {
|
||||
task.taskFailed(ctx, llm, err.Error())
|
||||
return
|
||||
@@ -93,7 +93,7 @@ func (task *LLMSyncStatusTask) OnInit(ctx context.Context, obj db.IStandaloneMod
|
||||
IsForce: true,
|
||||
TimeoutSecs: 10,
|
||||
}
|
||||
_, err := compute.Servers.PerformAction(s, llm.SvrId, "stop", jsonutils.Marshal(params))
|
||||
_, err := compute.Servers.PerformAction(s, llm.CmpId, "stop", jsonutils.Marshal(params))
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "ServerStop")
|
||||
}
|
||||
|
||||
@@ -40,12 +40,12 @@ func (volumeDeleteTask *VolumeDeleteTask) taskComplete(ctx context.Context, volu
|
||||
|
||||
func (volumeDeleteTask *VolumeDeleteTask) OnInit(ctx context.Context, obj db.IStandaloneModel, body jsonutils.JSONObject) {
|
||||
volume := obj.(*models.SVolume)
|
||||
if len(volume.SvrId) == 0 {
|
||||
if len(volume.CmpId) == 0 {
|
||||
volumeDeleteTask.taskComplete(ctx, volume)
|
||||
return
|
||||
}
|
||||
s := auth.GetSession(ctx, volumeDeleteTask.UserCred, "")
|
||||
_, err := compute.Disks.Delete(s, volume.SvrId, nil)
|
||||
_, err := compute.Disks.Delete(s, volume.CmpId, nil)
|
||||
if err != nil {
|
||||
if httputils.ErrorCode(err) == 404 {
|
||||
volumeDeleteTask.taskComplete(ctx, volume)
|
||||
@@ -55,7 +55,7 @@ func (volumeDeleteTask *VolumeDeleteTask) OnInit(ctx context.Context, obj db.ISt
|
||||
return
|
||||
}
|
||||
for i := 0; i < 60; i++ {
|
||||
_, err := compute.Disks.GetById(s, volume.SvrId, jsonutils.Marshal(map[string]interface{}{
|
||||
_, err := compute.Disks.GetById(s, volume.CmpId, jsonutils.Marshal(map[string]interface{}{
|
||||
"scope": "max",
|
||||
}))
|
||||
if err != nil {
|
||||
|
||||
@@ -1,137 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# 脚本: Ollama 模型安全下载器
|
||||
# 描述: 此脚本根据输入的模型名称(例如 "qwen3:8b")安全地下载 Ollama 模型文件。
|
||||
# 它使用临时文件进行下载,并在成功后重命名,以防止文件损坏。
|
||||
#
|
||||
# 用法: ./download_model.sh <模型名称:标签>
|
||||
# 示例: ./download_model.sh qwen3:8b
|
||||
|
||||
# --- 配置 ---
|
||||
|
||||
# Ollama 注册表的基础 URL
|
||||
LLM_OLLAMA_LIBRARY_BASE_URL="https://registry.ollama.ai/v2/library"
|
||||
# 模型在主机上保存的基础路径
|
||||
LLM_OLLAMA_HOST_PATH="/opt/ollama-models"
|
||||
# 主机上的清单目录
|
||||
LLM_OLLAMA_HOST_MANIFESTS_DIR="/manifests"
|
||||
# 主机上的 blob 目录
|
||||
LLM_OLLAMA_HOST_BLOBS_DIR="/blobs"
|
||||
|
||||
# --- 脚本 ---
|
||||
|
||||
# 检查是否提供了模型名称作为参数
|
||||
if [ -z "$1" ]; then
|
||||
echo "错误:未提供模型名称。"
|
||||
echo "用法: $0 <模型名称:标签>"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 从输入参数中解析模型名称和标签
|
||||
MODEL_FULL_NAME=$1
|
||||
MODEL_NAME=$(echo "$MODEL_FULL_NAME" | cut -d':' -f1)
|
||||
MODEL_TAG=$(echo "$MODEL_FULL_NAME" | cut -d':' -f2)
|
||||
|
||||
# 检查模型名称和标签是否已成功解析
|
||||
if [ "$MODEL_NAME" == "$MODEL_TAG" ] || [ -z "$MODEL_TAG" ]; then
|
||||
echo "错误:模型名称格式无效。应为 '名称:标签' (例如 'qwen3:8b')。"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "开始安全下载模型: $MODEL_FULL_NAME"
|
||||
echo "----------------------------------------"
|
||||
|
||||
# --- 1. 下载清单文件 ---
|
||||
|
||||
# 创建清单文件要保存的目录 (如果不存在)
|
||||
MANIFEST_DIR="$LLM_OLLAMA_HOST_PATH$LLM_OLLAMA_HOST_MANIFESTS_DIR"
|
||||
mkdir -p "$MANIFEST_DIR"
|
||||
|
||||
# 构造清单文件的 URL、最终路径和临时路径
|
||||
MANIFEST_SUFFIX_URL="$MODEL_NAME/manifests/$MODEL_TAG"
|
||||
MANIFEST_URL="$LLM_OLLAMA_LIBRARY_BASE_URL/$MANIFEST_SUFFIX_URL"
|
||||
MANIFEST_FILE_PATH="$MANIFEST_DIR/$MODEL_NAME-$MODEL_TAG"
|
||||
MANIFEST_FILE_PATH_TMP="${MANIFEST_FILE_PATH}.tmp"
|
||||
|
||||
echo "步骤 1: 正在从 $MANIFEST_URL 下载清单..."
|
||||
|
||||
# 检查最终文件是否已存在,如果存在则跳过
|
||||
if [ -f "$MANIFEST_FILE_PATH" ]; then
|
||||
echo "清单文件已存在,跳过下载。"
|
||||
else
|
||||
# 使用 wget 下载到临时文件
|
||||
wget --quiet --show-progress -O "$MANIFEST_FILE_PATH_TMP" "$MANIFEST_URL"
|
||||
# 检查 wget 的退出状态
|
||||
if [ $? -eq 0 ]; then
|
||||
# 如果成功,重命名临时文件
|
||||
mv "$MANIFEST_FILE_PATH_TMP" "$MANIFEST_FILE_PATH"
|
||||
echo "清单已成功下载到: $MANIFEST_FILE_PATH"
|
||||
else
|
||||
# 如果失败,打印错误并删除临时文件
|
||||
echo "错误:下载清单失败。请检查模型名称是否正确以及网络连接。"
|
||||
rm -f "$MANIFEST_FILE_PATH_TMP"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "----------------------------------------"
|
||||
|
||||
# --- 2. 从清单中提取 Blob 的摘要 (digest) ---
|
||||
|
||||
echo "步骤 2: 正在从清单文件中解析 blob 摘要..."
|
||||
# 使用 grep 和 sed 通过正则表达式提取所有 blob 的 digest
|
||||
BLOBS=$(grep -o '"digest":"sha256:[^"]*' "$MANIFEST_FILE_PATH" | sed 's/"digest":"//')
|
||||
|
||||
if [ -z "$BLOBS" ]; then
|
||||
echo "警告:在清单文件中未找到任何 blob 摘要。"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "已找到以下 blobs:"
|
||||
echo "$BLOBS"
|
||||
echo "----------------------------------------"
|
||||
|
||||
# --- 3. 下载所有 Blob 文件 ---
|
||||
|
||||
echo "步骤 3: 正在下载所有 blob 文件..."
|
||||
# 创建 blob 文件要保存的目录 (如果不存在)
|
||||
BLOBS_DIR="$LLM_OLLAMA_HOST_PATH$LLM_OLLAMA_HOST_BLOBS_DIR"
|
||||
mkdir -p "$BLOBS_DIR"
|
||||
|
||||
# 逐行遍历所有提取出的 blob 摘要
|
||||
for BLOB in $BLOBS; do
|
||||
# 将 blob 摘要中的 "sha256:" 替换为 "sha256-" 以用作文件名
|
||||
BLOB_FILENAME=$(echo "$BLOB" | sed 's/sha256:/sha256-/')
|
||||
BLOB_FILE_PATH="$BLOBS_DIR/$BLOB_FILENAME"
|
||||
BLOB_FILE_PATH_TMP="${BLOB_FILE_PATH}.tmp"
|
||||
|
||||
# 如果最终文件已经存在,则跳过下载
|
||||
if [ -f "$BLOB_FILE_PATH" ]; then
|
||||
echo " 文件已存在, 跳过下载: $BLOB_FILENAME"
|
||||
continue
|
||||
fi
|
||||
|
||||
# 构造 blob 的下载 URL
|
||||
BLOB_URL="$LLM_OLLAMA_LIBRARY_BASE_URL/$MODEL_NAME/blobs/$BLOB"
|
||||
|
||||
echo " 正在下载 $BLOB..."
|
||||
# 使用 wget 下载 blob 到临时文件
|
||||
wget --quiet --show-progress -O "$BLOB_FILE_PATH_TMP" "$BLOB_URL"
|
||||
|
||||
# 检查 wget 的退出状态
|
||||
if [ $? -eq 0 ]; then
|
||||
# 如果成功,重命名临时文件
|
||||
mv "$BLOB_FILE_PATH_TMP" "$BLOB_FILE_PATH"
|
||||
echo " 已成功保存到: $BLOB_FILE_PATH"
|
||||
else
|
||||
# 如果失败,打印错误并删除临时文件
|
||||
echo " 错误:下载 blob $BLOB 失败。已从 $BLOB_URL 尝试下载。"
|
||||
rm -f "$BLOB_FILE_PATH_TMP"
|
||||
# 如果希望在任何一个 blob 下载失败时立即中止整个脚本,请取消下一行的注释
|
||||
# exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
echo "----------------------------------------"
|
||||
echo "所有任务已完成。"
|
||||
echo "模型 '$MODEL_FULL_NAME' 已成功下载到 '$LLM_OLLAMA_HOST_PATH'。"
|
||||
Reference in New Issue
Block a user