llm.go 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098
  1. package models
  2. import (
  3. "context"
  4. "database/sql"
  5. "fmt"
  6. "strings"
  7. "yunion.io/x/jsonutils"
  8. "yunion.io/x/log"
  9. "yunion.io/x/pkg/errors"
  10. "yunion.io/x/pkg/utils"
  11. "yunion.io/x/sqlchemy"
  12. commonapi "yunion.io/x/onecloud/pkg/apis"
  13. computeapi "yunion.io/x/onecloud/pkg/apis/compute"
  14. api "yunion.io/x/onecloud/pkg/apis/llm"
  15. "yunion.io/x/onecloud/pkg/apis/notify"
  16. notifyapi "yunion.io/x/onecloud/pkg/apis/notify"
  17. "yunion.io/x/onecloud/pkg/cloudcommon/db"
  18. "yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
  19. "yunion.io/x/onecloud/pkg/cloudcommon/notifyclient"
  20. "yunion.io/x/onecloud/pkg/httperrors"
  21. "yunion.io/x/onecloud/pkg/llm/options"
  22. llmutils "yunion.io/x/onecloud/pkg/llm/utils"
  23. "yunion.io/x/onecloud/pkg/mcclient"
  24. "yunion.io/x/onecloud/pkg/mcclient/auth"
  25. "yunion.io/x/onecloud/pkg/mcclient/modules/compute"
  26. baseoptions "yunion.io/x/onecloud/pkg/mcclient/options"
  27. computeoptions "yunion.io/x/onecloud/pkg/mcclient/options/compute"
  28. "yunion.io/x/onecloud/pkg/util/stringutils2"
  29. )
  30. var llmManager *SLLMManager
  31. func init() {
  32. GetLLMManager()
  33. }
  34. func GetLLMManager() *SLLMManager {
  35. if llmManager != nil {
  36. return llmManager
  37. }
  38. llmManager = &SLLMManager{
  39. SLLMBaseManager: NewSLLMBaseManager(
  40. SLLM{},
  41. "llms_tbl",
  42. "llm",
  43. "llms",
  44. ),
  45. }
  46. llmManager.SetVirtualObject(llmManager)
  47. return llmManager
  48. }
  49. type SLLMManager struct {
  50. SLLMBaseManager
  51. }
  52. type SLLM struct {
  53. SLLMBase
  54. LLMSkuId string `width:"128" charset:"ascii" nullable:"false" list:"user" create:"required"`
  55. LLMImageId string `width:"128" charset:"ascii" nullable:"false" list:"user" create:"required"`
  56. // 秒装应用配额(可安装的总容量限制)
  57. InstantModelQuotaGb int `list:"user" update:"user" create:"optional" default:"0" nullable:"false"`
  58. // LLMSpec overrides/extends sku LLMSpec when building container; merged with sku.LLMSpec (llm priority).
  59. LLMSpec *api.LLMSpec `json:"llm_spec,omitempty" length:"long" list:"user" create:"optional" update:"user"`
  60. }
  61. // CustomizeCreate saves Dify customized envs from create input when present.
  62. func (llm *SLLM) CustomizeCreate(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data jsonutils.JSONObject) error {
  63. if err := llm.SLLMBase.CustomizeCreate(ctx, userCred, ownerId, query, data); err != nil {
  64. return err
  65. }
  66. return nil
  67. }
  68. func (man *SLLMManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, input *api.LLMCreateInput) (*api.LLMCreateInput, error) {
  69. var err error
  70. input.LLMBaseCreateInput, err = man.SLLMBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.LLMBaseCreateInput)
  71. if err != nil {
  72. return input, errors.Wrap(err, "validate LLMBaseCreateInput")
  73. }
  74. sku, err := GetLLMSkuManager().FetchByIdOrName(ctx, userCred, input.LLMSkuId)
  75. if err != nil {
  76. return input, errors.Wrap(err, "fetch LLMSku")
  77. }
  78. lSku := sku.(*SLLMSku)
  79. input.LLMSkuId = lSku.Id
  80. input.LLMImageId = lSku.GetLLMImageId()
  81. if input.LLMSpec != nil {
  82. drv := lSku.GetLLMContainerDriver()
  83. spec, err := drv.ValidateLLMCreateSpec(ctx, userCred, lSku, input.LLMSpec)
  84. if err != nil {
  85. return input, errors.Wrap(err, "validate LLM create spec")
  86. }
  87. input.LLMSpec = spec
  88. }
  89. return input, nil
  90. }
  91. func (man *SLLMManager) BatchCreateValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, input api.LLMCreateInput) (*jsonutils.JSONDict, error) {
  92. data, err := man.ValidateCreateData(ctx, userCred, ownerId, query, &input)
  93. if err != nil {
  94. return nil, err
  95. }
  96. return data.JSON(data), nil
  97. }
  98. func (man *SLLMManager) ListItemFilter(ctx context.Context, q *sqlchemy.SQuery, userCred mcclient.TokenCredential, input api.LLMListInput) (*sqlchemy.SQuery, error) {
  99. q, err := man.SLLMBaseManager.ListItemFilter(ctx, q, userCred, input.LLMBaseListInput)
  100. if err != nil {
  101. return q, errors.Wrap(err, "VirtualResourceBaseManager.ListItemFilter")
  102. }
  103. if len(input.LLMSku) > 0 {
  104. skuObj, err := GetLLMSkuManager().FetchByIdOrName(ctx, userCred, input.LLMSku)
  105. if err != nil {
  106. if errors.Cause(err) == sql.ErrNoRows {
  107. return nil, httperrors.NewResourceNotFoundError2(GetLLMSkuManager().KeywordPlural(), input.LLMSku)
  108. } else {
  109. return nil, errors.Wrap(err, "GetLLMSkuManager.FetchByIdOrName")
  110. }
  111. }
  112. q = q.Equals("llm_sku_id", skuObj.GetId())
  113. }
  114. if len(input.LLMImage) > 0 {
  115. imgObj, err := GetLLMImageManager().FetchByIdOrName(ctx, userCred, input.LLMImage)
  116. if err != nil {
  117. if errors.Cause(err) == sql.ErrNoRows {
  118. return nil, httperrors.NewResourceNotFoundError2(GetLLMImageManager().KeywordPlural(), input.LLMImage)
  119. } else {
  120. return nil, errors.Wrap(err, "LLMImageManager.FetchByIdOrName")
  121. }
  122. }
  123. q = q.Equals("llm_image_id", imgObj.GetId())
  124. }
  125. if len(input.LLMType) > 0 {
  126. skuQ := GetLLMSkuManager().Query().SubQuery()
  127. q = q.Join(skuQ, sqlchemy.Equals(q.Field("llm_sku_id"), skuQ.Field("id")))
  128. q = q.Filter(sqlchemy.Equals(skuQ.Field("llm_type"), input.LLMType))
  129. }
  130. if len(input.LLMTypes) > 0 {
  131. skuQ := GetLLMSkuManager().Query().SubQuery()
  132. q = q.Join(skuQ, sqlchemy.Equals(q.Field("llm_sku_id"), skuQ.Field("id")))
  133. q = q.Filter(sqlchemy.In(skuQ.Field("llm_type"), input.LLMTypes))
  134. }
  135. return q, nil
  136. }
  137. func (man *SLLMManager) FetchCustomizeColumns(
  138. ctx context.Context,
  139. userCred mcclient.TokenCredential,
  140. query jsonutils.JSONObject,
  141. objs []interface{},
  142. fields stringutils2.SSortedStrings,
  143. isList bool,
  144. ) []api.LLMListDetails {
  145. virtRows := man.SVirtualResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
  146. llms := []SLLM{}
  147. jsonutils.Update(&llms, objs)
  148. res := make([]api.LLMListDetails, len(objs))
  149. for i := 0; i < len(res); i++ {
  150. res[i].VirtualResourceDetails = virtRows[i]
  151. }
  152. ids := make([]string, len(llms))
  153. skuIds := make([]string, len(llms))
  154. imgIds := make([]string, len(llms))
  155. serverIds := []string{}
  156. networkIds := []string{}
  157. for idx, llm := range llms {
  158. ids[idx] = llm.Id
  159. skuIds[idx] = llm.LLMSkuId
  160. imgIds[idx] = llm.LLMImageId
  161. if !utils.IsInArray(llm.CmpId, serverIds) {
  162. serverIds = append(serverIds, llm.CmpId)
  163. }
  164. if len(llm.NetworkId) > 0 {
  165. networkIds = append(networkIds, llm.NetworkId)
  166. }
  167. mountedModelInfo, _ := llm.FetchMountedModelInfo()
  168. res[idx].MountedModels = mountedModelInfo
  169. res[idx].NetworkType = llm.NetworkType
  170. res[idx].NetworkId = llm.NetworkId
  171. }
  172. // fetch volume
  173. volumeQ := GetVolumeManager().Query().In("llm_Id", ids)
  174. volumes := []SVolume{}
  175. db.FetchModelObjects(GetVolumeManager(), volumeQ, &volumes)
  176. for _, volume := range volumes {
  177. for i, id := range ids {
  178. if id == volume.LLMId {
  179. res[i].Volume = api.Volume{
  180. Id: volume.CmpId,
  181. Name: volume.Name,
  182. TemplateId: volume.TemplateId,
  183. StorageType: volume.StorageType,
  184. SizeMB: volume.SizeMB,
  185. }
  186. }
  187. }
  188. }
  189. // fetch sku
  190. skus := make(map[string]SLLMSku)
  191. err := db.FetchModelObjectsByIds(GetLLMSkuManager(), "id", skuIds, &skus)
  192. if err == nil {
  193. for i := range llms {
  194. if sku, ok := skus[llms[i].LLMSkuId]; ok {
  195. res[i].LLMSku = sku.Name
  196. res[i].LLMType = sku.LLMType
  197. res[i].VcpuCount = sku.Cpu
  198. res[i].VmemSizeMb = sku.Memory
  199. res[i].Devices = sku.Devices
  200. if llms[i].BandwidthMb != 0 {
  201. res[i].EffectBandwidthMbps = llms[i].BandwidthMb
  202. } else {
  203. res[i].EffectBandwidthMbps = sku.Bandwidth
  204. }
  205. }
  206. }
  207. } else {
  208. log.Errorf("FetchModelObjectsByIds LLMSkuManager fail %s", err)
  209. }
  210. // fetch image
  211. images := make(map[string]SLLMImage)
  212. err = db.FetchModelObjectsByIds(GetLLMImageManager(), "id", imgIds, &images)
  213. if err == nil {
  214. for i := range llms {
  215. if image, ok := images[llms[i].LLMImageId]; ok {
  216. res[i].LLMImage = image.Name
  217. res[i].LLMImageLable = image.ImageLabel
  218. res[i].LLMImageName = image.ImageName
  219. }
  220. }
  221. } else {
  222. log.Errorf("FetchModelObjectsByIds GetLLMImageManager fail %s", err)
  223. }
  224. // fetch network
  225. if len(networkIds) > 0 {
  226. networks, err := fetchNetworks(ctx, userCred, networkIds)
  227. if err == nil {
  228. for i, llm := range llms {
  229. if net, ok := networks[llm.NetworkId]; ok {
  230. res[i].Network = net.Name
  231. }
  232. }
  233. } else {
  234. log.Errorf("fail to retrieve network info %s", err)
  235. }
  236. }
  237. // fetch host
  238. if len(serverIds) > 0 {
  239. // allow query cmp server
  240. serverMap := make(map[string]computeapi.ServerDetails)
  241. s := auth.GetAdminSession(ctx, options.Options.Region)
  242. params := computeoptions.ServerListOptions{}
  243. limit := 1000
  244. params.Limit = &limit
  245. details := true
  246. params.Details = &details
  247. params.Scope = "maxallowed"
  248. offset := 0
  249. for offset < len(serverIds) {
  250. lastIdx := offset + limit
  251. if lastIdx > len(serverIds) {
  252. lastIdx = len(serverIds)
  253. }
  254. params.Id = serverIds[offset:lastIdx]
  255. results, err := compute.Servers.List(s, jsonutils.Marshal(params))
  256. if err != nil {
  257. log.Errorf("query servers fails %s", err)
  258. break
  259. } else {
  260. offset = lastIdx
  261. for i := range results.Data {
  262. guest := computeapi.ServerDetails{}
  263. err := results.Data[i].Unmarshal(&guest)
  264. if err == nil {
  265. serverMap[guest.Id] = guest
  266. }
  267. }
  268. }
  269. }
  270. for i := range llms {
  271. llmStatus := api.LLM_STATUS_UNKNOWN
  272. llm := llms[i]
  273. if guest, ok := serverMap[llm.CmpId]; ok {
  274. // find guest
  275. if len(guest.Containers) == 0 {
  276. llmStatus = api.LLM_LLM_STATUS_NO_CONTAINER
  277. } else {
  278. llmCtr := guest.Containers[0]
  279. if llmCtr == nil {
  280. llmStatus = api.LLM_LLM_STATUS_NO_CONTAINER
  281. } else {
  282. llmStatus = llmCtr.Status
  283. }
  284. }
  285. res[i].Server = guest.Name
  286. res[i].StartTime = guest.LastStartAt
  287. res[i].Host = guest.Host
  288. res[i].HostId = guest.HostId
  289. res[i].HostAccessIp = guest.HostAccessIp
  290. res[i].HostEIP = guest.HostEIP
  291. res[i].Zone = guest.Zone
  292. res[i].ZoneId = guest.ZoneId
  293. res[i].VcpuCount = guest.VcpuCount
  294. res[i].VmemSizeMb = guest.VmemSize
  295. adbMappedPort := -1
  296. // for j := range res[i].AccessInfo {
  297. // res[i].AccessInfo[j].DesktopIp = guest.IPs
  298. // res[i].AccessInfo[j].ServerIp = guest.HostAccessIp
  299. // res[i].AccessInfo[j].PublicIp = guest.HostEIP
  300. // /*if res[i].AccessInfo[j].ListenPort == api.DESKTOP_ADB_PORT {
  301. // adbMappedPort = res[i].AccessInfo[j].AccessPort
  302. // }*/
  303. // }
  304. if adbMappedPort >= 0 {
  305. res[i].AdbAccess = fmt.Sprintf("%s:%d", guest.HostAccessIp, adbMappedPort)
  306. if len(res[i].HostEIP) > 0 {
  307. res[i].AdbPublic = fmt.Sprintf("%s:%d", guest.HostEIP, adbMappedPort)
  308. }
  309. }
  310. } else {
  311. llmStatus = api.LLM_LLM_STATUS_NO_SERVER
  312. }
  313. res[i].LLMStatus = llmStatus
  314. }
  315. }
  316. return res
  317. }
  318. func (lm *SLLMManager) OnCreateComplete(ctx context.Context, items []db.IModel, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data []jsonutils.JSONObject) {
  319. parentTaskId, _ := data[0].GetString("parent_task_id")
  320. err := runBatchCreateTask(ctx, items, userCred, data, "LLMBatchCreateTask", parentTaskId)
  321. if err != nil {
  322. for i := range items {
  323. llm := items[i].(*SLLM)
  324. llm.SetStatus(ctx, userCred, api.LLM_STATUS_CREATE_FAIL, err.Error())
  325. }
  326. }
  327. }
  328. func runBatchCreateTask(
  329. ctx context.Context,
  330. items []db.IModel,
  331. userCred mcclient.TokenCredential,
  332. data []jsonutils.JSONObject,
  333. taskName string,
  334. parentTaskId string,
  335. ) error {
  336. taskItems := make([]db.IStandaloneModel, len(items))
  337. for i, t := range items {
  338. taskItems[i] = t.(db.IStandaloneModel)
  339. }
  340. params := jsonutils.NewDict()
  341. params.Set("data", jsonutils.NewArray(data...))
  342. task, err := taskman.TaskManager.NewParallelTask(ctx, taskName, taskItems, userCred, params, parentTaskId, "")
  343. if err != nil {
  344. return errors.Wrapf(err, "NewParallelTask %s", taskName)
  345. }
  346. return task.ScheduleRun(nil)
  347. }
  348. func (llm *SLLM) CustomizeDelete(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) error {
  349. return llm.StartDeleteTask(ctx, userCred, "")
  350. }
  351. func (llm *SLLM) GetLLMSku(skuId string) (*SLLMSku, error) {
  352. if len(skuId) == 0 {
  353. skuId = llm.LLMSkuId
  354. }
  355. sku, err := GetLLMSkuManager().FetchById(skuId)
  356. if err != nil {
  357. return nil, errors.Wrap(err, "fetch LLMSku")
  358. }
  359. return sku.(*SLLMSku), nil
  360. }
  361. func (llm *SLLM) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.LLMUpdateInput) (api.LLMUpdateInput, error) {
  362. var err error
  363. input.VirtualResourceBaseUpdateInput, err = llm.SLLMBase.SVirtualResourceBase.ValidateUpdateData(ctx, userCred, query, input.VirtualResourceBaseUpdateInput)
  364. if err != nil {
  365. return input, errors.Wrap(err, "validate VirtualResourceBaseUpdateInput")
  366. }
  367. if input.LLMSpec == nil {
  368. return input, nil
  369. }
  370. sku, err := llm.GetLLMSku(llm.LLMSkuId)
  371. if err != nil {
  372. return input, errors.Wrap(err, "fetch LLMSku")
  373. }
  374. drv := sku.GetLLMContainerDriver()
  375. spec, err := drv.ValidateLLMUpdateSpec(ctx, userCred, llm, input.LLMSpec)
  376. if err != nil {
  377. return input, errors.Wrap(err, "validate LLM update spec")
  378. }
  379. input.LLMSpec = spec
  380. return input, nil
  381. }
  382. func (llm *SLLM) GetLargeLanguageModelName(name string) (modelName string, modelTag string, err error) {
  383. if name == "" {
  384. return "", "", errors.Wrap(errors.ErrInvalidStatus, "model name is empty")
  385. }
  386. parts := strings.Split(name, ":")
  387. modelName = parts[0]
  388. modelTag = "latest"
  389. if len(parts) == 2 {
  390. modelTag = parts[1]
  391. }
  392. return
  393. }
  394. func (llm *SLLM) GetLLMImage() (*SLLMImage, error) {
  395. return llm.getImage(llm.LLMImageId)
  396. }
  397. func (llm *SLLM) GetLLMSContainer(ctx context.Context) (*computeapi.SContainer, error) {
  398. llmCtr, err := llm.GetLLMContainer()
  399. if err != nil {
  400. return nil, errors.Wrap(err, "GetLLMContainer")
  401. }
  402. return llmCtr.GetSContainer(ctx)
  403. }
  404. func (llm *SLLM) GetLLMContainer() (*SLLMContainer, error) {
  405. return GetLLMContainerManager().FetchByLLMId(llm.Id)
  406. }
  407. func (llm *SLLM) SyncLLMContainer(ctx context.Context, userCred mcclient.TokenCredential, server *computeapi.ServerDetails) (*SLLMContainer, error) {
  408. curCtr, _ := llm.GetLLMContainer()
  409. if curCtr != nil {
  410. return curCtr, nil
  411. }
  412. drv := llm.GetLLMContainerDriver()
  413. ctr, err := drv.GetPrimaryContainer(ctx, llm, server.Containers)
  414. if err != nil {
  415. return nil, errors.Wrap(err, "GetPrimaryContainer")
  416. }
  417. llmCtr, err := GetLLMContainerManager().CreateOnLLM(ctx, userCred, llm.GetOwnerId(), llm, ctr.Id, ctr.Name)
  418. if nil != err {
  419. return nil, errors.Wrapf(err, "create llm container on llm %s", ctr.Id)
  420. }
  421. return llmCtr, nil
  422. }
  423. func (llm *SLLM) GetLLMContainerDriver() ILLMContainerDriver {
  424. sku, _ := llm.GetLLMSku(llm.LLMSkuId)
  425. return sku.GetLLMContainerDriver()
  426. }
  427. func (llm *SLLM) StartCreateTask(ctx context.Context, userCred mcclient.TokenCredential, input api.LLMCreateInput, parentTaskId string) error {
  428. llm.SetStatus(ctx, userCred, commonapi.STATUS_CREATING, "")
  429. params := jsonutils.Marshal(input).(*jsonutils.JSONDict)
  430. var err = func() error {
  431. task, err := taskman.TaskManager.NewTask(ctx, "LLMCreateTask", llm, userCred, params, parentTaskId, "", nil)
  432. if err != nil {
  433. return errors.Wrapf(err, "NewTask")
  434. }
  435. return task.ScheduleRun(params)
  436. }()
  437. if err != nil {
  438. llm.SetStatus(ctx, userCred, api.LLM_STATUS_CREATE_FAIL, err.Error())
  439. return err
  440. }
  441. return nil
  442. }
  443. func (llm *SLLM) StartPullModelTask(ctx context.Context, userCred mcclient.TokenCredential, input *jsonutils.JSONDict, parentTaskId string) error {
  444. task, err := taskman.TaskManager.NewTask(ctx, "LLMPullModelTask", llm, userCred, input, parentTaskId, "", nil)
  445. if err != nil {
  446. return errors.Wrapf(err, "NewTask")
  447. }
  448. return task.ScheduleRun(nil)
  449. }
  450. func (llm *SLLM) StartDeleteTask(ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string) error {
  451. llm.SetStatus(ctx, userCred, api.LLM_STATUS_START_DELETE, "StartDeleteTask")
  452. task, err := taskman.TaskManager.NewTask(ctx, "LLMDeleteTask", llm, userCred, nil, parentTaskId, "", nil)
  453. if err != nil {
  454. return err
  455. }
  456. return task.ScheduleRun(nil)
  457. }
  458. func (llm *SLLM) ServerCreate(ctx context.Context, userCred mcclient.TokenCredential, s *mcclient.ClientSession, input *api.LLMCreateInput) (string, error) {
  459. sku, err := llm.GetLLMSku(llm.LLMSkuId)
  460. if nil != err {
  461. return "", errors.Wrap(err, "GetLLMSku")
  462. }
  463. llmImage, err := llm.GetLLMImage()
  464. if nil != err {
  465. return "", errors.Wrap(err, "GetLLMImage")
  466. }
  467. data, err := GetLLMPodCreateInput(ctx, userCred, input, llm, sku, llmImage, "")
  468. if nil != err {
  469. return "", errors.Wrap(err, "GetPodCreateInput")
  470. }
  471. log.Infoln("PodCreateInput Data: ", jsonutils.Marshal(data).String())
  472. resp, err := compute.Servers.Create(s, jsonutils.Marshal(data))
  473. if nil != err {
  474. return "", errors.Wrap(err, "Servers.Create")
  475. }
  476. id, err := resp.GetString("id")
  477. if nil != err {
  478. return "", errors.Wrap(err, "resp.GetString")
  479. }
  480. return id, nil
  481. }
  482. func (llm *SLLM) PerformStart(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
  483. // can't start while it's already running
  484. if utils.IsInStringArray(llm.Status, computeapi.VM_RUNNING_STATUS) {
  485. return nil, errors.Wrapf(errors.ErrInvalidStatus, "llm id: %s status: %s", llm.Id, llm.Status)
  486. }
  487. _, err := llm.GetVolume()
  488. if err != nil {
  489. if errors.Cause(err) == sql.ErrNoRows {
  490. return nil, errors.Wrapf(errors.ErrNotSupported, "llm id: %s missing volume", llm.Id)
  491. }
  492. return nil, errors.Wrap(err, "GetVolume")
  493. }
  494. taskinput := &api.LLMRestartTaskInput{
  495. LLMId: llm.Id,
  496. LLMStatus: api.LLM_STATUS_READY,
  497. }
  498. _, err = llm.StartRestartTask(ctx, userCred, taskinput, "")
  499. if err != nil {
  500. return nil, errors.Wrap(err, "StartRestartTask")
  501. }
  502. return nil, nil
  503. }
  504. func (d *SLLM) StartStartTaskInternal(ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string) error {
  505. d.SetStatus(ctx, userCred, computeapi.VM_STARTING, "")
  506. task, err := taskman.TaskManager.NewTask(ctx, "LLMStartTask", d, userCred, nil, parentTaskId, "", nil)
  507. if err != nil {
  508. return errors.Wrapf(err, "NewTask")
  509. }
  510. return task.ScheduleRun(nil)
  511. }
  512. func (llm *SLLM) StartStartTask(ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string) error {
  513. task, err := taskman.TaskManager.NewTask(ctx, "LLMStartTask", llm, userCred, nil, parentTaskId, "", nil)
  514. if err != nil {
  515. return errors.Wrap(err, "NewTask")
  516. }
  517. return task.ScheduleRun(nil)
  518. }
  519. func (llm *SLLM) PerformStop(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
  520. if llm.Status == computeapi.VM_READY {
  521. return nil, errors.Wrapf(errors.ErrInvalidStatus, "llm id: %s status: %s", llm.Id, llm.Status)
  522. }
  523. llm.SetStatus(ctx, userCred, computeapi.VM_START_STOP, "perform stop")
  524. err := llm.StartLLMStopTask(ctx, userCred, "")
  525. if err != nil {
  526. return nil, errors.Wrap(err, "StartStopTask")
  527. }
  528. return nil, nil
  529. }
  530. func (llm *SLLM) ValidateRestartInput(ctx context.Context, userCred mcclient.TokenCredential, input *api.LLMRestartInput) (*api.LLMRestartTaskInput, error) {
  531. if len(llm.CmpId) == 0 {
  532. return nil, errors.Wrap(errors.ErrInvalidStatus, "empty cmp_id")
  533. }
  534. srv, err := llm.GetServer(ctx)
  535. if err != nil {
  536. return nil, errors.Wrap(err, "GetServer")
  537. }
  538. if (llm.Status != api.LLM_STATUS_READY && llm.Status != api.LLM_STATUS_RUNNING) || (srv.Status != computeapi.VM_READY && !utils.IsInArray(srv.Status, computeapi.VM_RUNNING_STATUS)) {
  539. return nil, errors.Wrapf(errors.ErrInvalidStatus, "invalid llm status %s", llm.Status)
  540. }
  541. sku, err := llm.GetLLMSku(llm.LLMSkuId)
  542. if err != nil {
  543. return nil, errors.Wrap(err, "GetLLMSku")
  544. }
  545. return &api.LLMRestartTaskInput{
  546. ImageId: sku.GetLLMImageId(),
  547. }, nil
  548. }
  549. func (llm *SLLM) PerformRestart(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input *api.LLMRestartInput) (jsonutils.JSONObject, error) {
  550. taskInput, err := llm.ValidateRestartInput(ctx, userCred, input)
  551. if err != nil {
  552. return nil, errors.Wrap(err, "ValidateRestartInput")
  553. }
  554. _, err = llm.StartRestartTask(ctx, userCred, taskInput, "")
  555. if err != nil {
  556. return nil, errors.Wrap(err, "StartRestartTask")
  557. }
  558. return nil, nil
  559. }
  560. func (llm *SLLM) StartRestartTask(ctx context.Context, userCred mcclient.TokenCredential, params *api.LLMRestartTaskInput, parentTaskId string) (*taskman.STask, error) {
  561. key := "perform_restart"
  562. if params.ResetDataDisk {
  563. key = "perform_reset"
  564. }
  565. llm.SetStatus(ctx, userCred, api.LLM_STATUS_START_RESTART, key)
  566. taskName := "LLMRestartTask"
  567. if params.ResetDataDisk {
  568. taskName = "LLMResetTask"
  569. }
  570. params.LLMId = llm.Id
  571. task, err := taskman.TaskManager.NewTask(ctx, taskName, llm, userCred, jsonutils.Marshal(params).(*jsonutils.JSONDict), parentTaskId, "", nil)
  572. if err != nil {
  573. return nil, errors.Wrap(err, "NewTask")
  574. }
  575. if err := task.ScheduleRun(nil); err != nil {
  576. return nil, errors.Wrap(err, "ScheduleRun")
  577. }
  578. return task, nil
  579. }
  580. func (llm *SLLM) PerformReset(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input *api.LLMRestartInput) (jsonutils.JSONObject, error) {
  581. taskInput, err := llm.ValidateRestartInput(ctx, userCred, input)
  582. if err != nil {
  583. return nil, errors.Wrap(err, "ValidateRestartInput")
  584. }
  585. _, err = llm.StartResetTask(ctx, userCred, taskInput, "")
  586. if err != nil {
  587. return nil, errors.Wrap(err, "StartRestartTask")
  588. }
  589. return nil, nil
  590. }
  591. func (llm *SLLM) StartResetTask(ctx context.Context, userCred mcclient.TokenCredential, params *api.LLMRestartTaskInput, parentTaskId string) (*taskman.STask, error) {
  592. llm.SetStatus(ctx, userCred, api.LLM_STATUS_START_RESTART, "perform_reset")
  593. task, err := taskman.TaskManager.NewTask(ctx, "LLMResetTask", llm, userCred, jsonutils.Marshal(params).(*jsonutils.JSONDict), parentTaskId, "", nil)
  594. if err != nil {
  595. return nil, errors.Wrapf(err, "NewTask")
  596. }
  597. if err := task.ScheduleRun(nil); err != nil {
  598. return nil, errors.Wrap(err, "ScheduleRun")
  599. }
  600. return task, nil
  601. }
  602. func (llm *SLLM) NotifyRequest(ctx context.Context, userCred mcclient.TokenCredential, action notify.SAction, model jsonutils.JSONObject, success bool) {
  603. obj := func(ctx context.Context, details *jsonutils.JSONDict) {}
  604. if model != nil {
  605. obj = func(ctx context.Context, details *jsonutils.JSONDict) {
  606. details.Set("customize_details", model)
  607. }
  608. }
  609. notifyclient.EventNotify(ctx, userCred, notifyclient.SEventNotifyParam{
  610. Obj: llm,
  611. Action: action,
  612. ObjDetailsDecorator: obj,
  613. IsFail: !success,
  614. ResourceType: notifyapi.TOPIC_RESOURCE_LLM,
  615. })
  616. }
  617. func (llm *SLLM) StartLLMStopTask(ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string) error {
  618. task, err := taskman.TaskManager.NewTask(ctx, "LLMStopTask", llm, userCred, nil, parentTaskId, "", nil)
  619. if err != nil {
  620. return errors.Wrap(err, "NewTask")
  621. }
  622. err = task.ScheduleRun(nil)
  623. if err != nil {
  624. return errors.Wrap(err, "ScheduleRun")
  625. }
  626. return nil
  627. }
  628. func (llm *SLLM) ValidateDeleteCondition(ctx context.Context, info jsonutils.JSONObject) error {
  629. if err := llm.SLLMBase.ValidateDeleteCondition(ctx, info); err != nil {
  630. return err
  631. }
  632. // Check for associated MCPAgents
  633. cnt, err := GetMCPAgentManager().Query().Equals("llm_id", llm.Id).CountWithError()
  634. if err != nil {
  635. return errors.Wrap(err, "GetMCPAgentManager().Query().CountWithError")
  636. }
  637. if cnt > 0 {
  638. return httperrors.NewConflictError("LLM is being used by %d MCPAgents", cnt)
  639. }
  640. return nil
  641. }
  642. func (llm *SLLM) WaitContainerStatus(ctx context.Context, userCred mcclient.TokenCredential, targetStatus []string, timeoutSecs int) (*computeapi.SContainer, error) {
  643. llmCtr, err := llm.GetLLMContainer()
  644. if err != nil {
  645. return nil, errors.Wrap(err, "GetLLMContainer")
  646. }
  647. return llmutils.WaitContainerStatus(ctx, llmCtr.CmpId, targetStatus, timeoutSecs)
  648. }
  649. func (llm *SLLM) PerformSyncstatus(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data api.LLMSyncStatusInput) (jsonutils.JSONObject, error) {
  650. llm.SetStatus(ctx, userCred, api.LLM_STATUS_START_SYNCSTATUS, "perform syncstatus")
  651. err := llm.StartSyncStatusTask(ctx, userCred, "")
  652. if err != nil {
  653. return nil, errors.Wrap(err, "StartSyncStatusTask")
  654. }
  655. return nil, nil
  656. }
  657. func (llm *SLLM) StartSyncStatusTask(ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string) error {
  658. task, err := taskman.TaskManager.NewTask(ctx, "LLMSyncStatusTask", llm, userCred, nil, parentTaskId, "")
  659. if err != nil {
  660. return errors.Wrap(err, "NewTask")
  661. }
  662. err = task.ScheduleRun(nil)
  663. if err != nil {
  664. return errors.Wrap(err, "ScheduleRun")
  665. }
  666. return nil
  667. }
  668. func (llm *SLLM) FindAccessInfos(protocol string) ([]SAccessInfo, error) {
  669. q := GetAccessInfoManager().Query()
  670. q = q.Equals("llm_id", llm.Id)
  671. if protocol != "" {
  672. q = q.Equals("protocol", protocol)
  673. }
  674. accessInfos := make([]SAccessInfo, 0)
  675. err := db.FetchModelObjects(GetAccessInfoManager(), q, &accessInfos)
  676. if err != nil {
  677. return nil, errors.Wrap(err, "FetchModelObjects")
  678. }
  679. if len(accessInfos) == 0 {
  680. return nil, errors.ErrNotFound
  681. }
  682. return accessInfos, nil
  683. }
  684. func (llm *SLLM) FindAllAccessInfos() ([]SAccessInfo, error) {
  685. return llm.FindAccessInfos("")
  686. }
  687. func (llm *SLLM) FindAccessInfoByEnv(protocol string, envKey string) (*SAccessInfo, error) {
  688. ainfos, err := llm.FindAccessInfos(protocol)
  689. if err != nil {
  690. return nil, errors.Wrapf(err, "FindAccessInfo by env %s", envKey)
  691. }
  692. for _, ainfo := range ainfos {
  693. for _, env := range ainfo.PortMappingEnvs {
  694. if env.Key == envKey {
  695. return &ainfo, nil
  696. }
  697. }
  698. }
  699. return nil, errors.ErrNotFound
  700. }
  701. func (llm *SLLM) getHostAccessIp(ctx context.Context, isPublic bool) (string, error) {
  702. server, err := llm.GetServer(ctx)
  703. if err != nil {
  704. return "", errors.Wrap(err, "GetServer")
  705. }
  706. if isPublic {
  707. return server.HostEIP, nil
  708. }
  709. return server.HostAccessIp, nil
  710. }
  711. func (llm *SLLM) GetHostEIP(ctx context.Context) (string, error) {
  712. return llm.getHostAccessIp(ctx, true)
  713. }
  714. type LLMAccessInfoInput struct {
  715. HostInternalIp string
  716. HostPublicIp string
  717. ServerIp string
  718. AccessInfos []SAccessInfo
  719. }
  720. func (llm *SLLM) GetLLMAccessInfoInput(ctx context.Context, userCred mcclient.TokenCredential) (*LLMAccessInfoInput, error) {
  721. accessInfos, _ := llm.FindAllAccessInfos()
  722. server, err := llm.GetServer(ctx)
  723. if err != nil {
  724. return nil, errors.Wrap(err, "GetServer")
  725. }
  726. hostInternalIp := server.HostAccessIp
  727. hostPublicIp := server.HostEIP
  728. ips := strings.Split(strings.TrimSpace(server.IPs), ",")
  729. if len(ips) == 0 || len(strings.TrimSpace(ips[0])) == 0 {
  730. return nil, errors.Error("server IPs is empty")
  731. }
  732. serverIp := strings.TrimSpace(ips[0])
  733. return &LLMAccessInfoInput{
  734. HostInternalIp: hostInternalIp,
  735. HostPublicIp: hostPublicIp,
  736. ServerIp: serverIp,
  737. AccessInfos: accessInfos,
  738. }, nil
  739. }
  740. func (llm *SLLM) GetLLMAccessUrlInfo(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) (*api.LLMAccessUrlInfo, error) {
  741. if llm.CmpId == "" {
  742. return nil, nil
  743. }
  744. input, err := llm.GetLLMAccessInfoInput(ctx, userCred)
  745. if err != nil {
  746. return nil, errors.Wrap(err, "GetLLMAccessInfoInput")
  747. }
  748. return llm.GetLLMContainerDriver().GetLLMAccessUrlInfo(ctx, userCred, llm, input)
  749. }
  750. func GetLLMAccessUrlInfo(ctx context.Context, userCred mcclient.TokenCredential, llm *SLLM, input *LLMAccessInfoInput, protocol string, defaultPort int) (*api.LLMAccessUrlInfo, error) {
  751. port := defaultPort
  752. accessUrl := input.ServerIp
  753. hasPortMapping := false
  754. if len(input.AccessInfos) != 0 {
  755. hasPortMapping = true
  756. aInfo := input.AccessInfos[0]
  757. port = aInfo.AccessPort
  758. accessUrl = input.HostInternalIp
  759. if input.HostPublicIp != "" {
  760. accessUrl = input.HostPublicIp
  761. }
  762. }
  763. ret := &api.LLMAccessUrlInfo{
  764. LoginUrl: fmt.Sprintf("%s://%s:%d", protocol, accessUrl, port),
  765. }
  766. if hasPortMapping {
  767. ret.InternalUrl = fmt.Sprintf("%s://%s:%d", protocol, input.HostInternalIp, port)
  768. if input.HostPublicIp != "" {
  769. ret.PublicUrl = fmt.Sprintf("%s://%s:%d", protocol, input.HostPublicIp, port)
  770. }
  771. }
  772. return ret, nil
  773. }
  774. func (llm *SLLM) GetDetailsLoginInfo(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) (*api.LLMAccessInfo, error) {
  775. if llm.CmpId == "" {
  776. return nil, nil
  777. }
  778. accessUrl, err := llm.GetLLMAccessUrlInfo(ctx, userCred, query)
  779. if err != nil {
  780. return nil, errors.Wrap(err, "GetLLMAccessUrlInfo")
  781. }
  782. output := &api.LLMAccessInfo{
  783. LLMAccessUrlInfo: *accessUrl,
  784. }
  785. drv := llm.GetLLMContainerDriver()
  786. if loginInfoDrv, ok := drv.(ILLMContainerLoginInfo); ok {
  787. info, err := loginInfoDrv.GetLoginInfo(ctx, userCred, llm)
  788. if err != nil {
  789. return nil, errors.Wrap(err, "GetLoginInfo")
  790. }
  791. if info != nil {
  792. if info.Username != "" {
  793. output.Username = info.Username
  794. }
  795. if info.Password != "" {
  796. output.Password = info.Password
  797. }
  798. if len(info.Extra) > 0 {
  799. output.Extra = info.Extra
  800. }
  801. }
  802. }
  803. return output, nil
  804. }
  805. func fetchNetworks(ctx context.Context, userCred mcclient.TokenCredential, networkIds []string) (map[string]computeapi.NetworkDetails, error) {
  806. s := auth.GetSession(ctx, userCred, "")
  807. params := computeoptions.ServerListOptions{}
  808. params.Id = networkIds
  809. limit := len(networkIds)
  810. params.Limit = &limit
  811. params.Scope = "maxallowed"
  812. results, err := compute.Networks.List(s, jsonutils.Marshal(params))
  813. if err != nil {
  814. return nil, errors.Wrap(err, "Networks.List")
  815. }
  816. networks := make(map[string]computeapi.NetworkDetails)
  817. for i := range results.Data {
  818. net := computeapi.NetworkDetails{}
  819. err := results.Data[i].Unmarshal(&net)
  820. if err == nil {
  821. networks[net.Id] = net
  822. }
  823. }
  824. return networks, nil
  825. }
  826. func (man *SLLMManager) GetAvailableNetwork(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) (jsonutils.JSONObject, error) {
  827. s := auth.GetSession(ctx, userCred, "")
  828. ret := jsonutils.NewDict()
  829. q := jsonutils.NewDict()
  830. if query != nil {
  831. q.Update(query)
  832. }
  833. q.Set("server_type", jsonutils.NewString(string(computeapi.NETWORK_TYPE_HOSTLOCAL)))
  834. q.Set("is_auto_alloc", jsonutils.NewBool(true))
  835. q.Set("status", jsonutils.NewString(computeapi.NETWORK_STATUS_AVAILABLE))
  836. q.Set("limit", jsonutils.NewInt(1))
  837. result, err := compute.Networks.List(s, q)
  838. if err == nil && result.Total > 0 {
  839. ret.Add(jsonutils.NewInt(int64(result.Total)), "auto_alloc_network_hostlocal_count")
  840. }
  841. q.Set("server_type", jsonutils.NewString(string(computeapi.NETWORK_TYPE_GUEST)))
  842. q.Set("vpc_id", jsonutils.NewString(computeapi.DEFAULT_VPC_ID))
  843. resultGuest, err := compute.Networks.List(s, q)
  844. if err == nil && resultGuest.Total > 0 {
  845. ret.Add(jsonutils.NewInt(int64(resultGuest.Total)), "auto_alloc_network_guest_count")
  846. }
  847. return ret, nil
  848. }
  849. func (man *SLLMManager) performProviderModels(ctx context.Context, input api.LLMProviderModelsInput) (*api.LLMProviderModelsOutput, error) {
  850. input.URL = strings.TrimSpace(input.URL)
  851. if input.URL == "" {
  852. return nil, httperrors.NewMissingParameterError("url")
  853. }
  854. if input.ProviderType == "" {
  855. return nil, httperrors.NewMissingParameterError("provider_type")
  856. }
  857. if !api.IsLLMClientType(string(input.ProviderType)) {
  858. return nil, httperrors.NewInputParameterError("invalid provider_type %q", input.ProviderType)
  859. }
  860. drv, err := GetLLMClientDriverWithError(input.ProviderType)
  861. if err != nil {
  862. return nil, httperrors.NewNotSupportedError("provider_type %q is not supported", input.ProviderType)
  863. }
  864. modelLister, ok := drv.(ILLMClientModelLister)
  865. if !ok {
  866. return nil, httperrors.NewNotSupportedError("provider_type %q does not support listing models", input.ProviderType)
  867. }
  868. models, err := modelLister.ListModels(ctx, input.URL)
  869. if err != nil {
  870. return nil, httperrors.NewBadGatewayError("list models from %q via %q: %v", input.ProviderType, input.URL, err)
  871. }
  872. return &api.LLMProviderModelsOutput{
  873. ProviderType: input.ProviderType,
  874. URL: input.URL,
  875. Models: models,
  876. }, nil
  877. }
  878. func (man *SLLMManager) GetProviderModels(ctx context.Context, _ mcclient.TokenCredential, query jsonutils.JSONObject) (*api.LLMProviderModelsOutput, error) {
  879. input := api.LLMProviderModelsInput{}
  880. if query != nil {
  881. if err := query.Unmarshal(&input); err != nil {
  882. return nil, errors.Wrap(err, "unmarshal provider models input")
  883. }
  884. }
  885. return man.performProviderModels(ctx, input)
  886. }
  887. func (man *SLLMManager) PerformProviderModels(ctx context.Context, _ mcclient.TokenCredential, query jsonutils.JSONObject, input api.LLMProviderModelsInput) (*api.LLMProviderModelsOutput, error) {
  888. if input.URL == "" && query != nil {
  889. if err := query.Unmarshal(&input); err != nil {
  890. return nil, errors.Wrap(err, "unmarshal provider models query")
  891. }
  892. }
  893. return man.performProviderModels(ctx, input)
  894. }
  895. func (llm *SLLM) StartBindVolumeTask(ctx context.Context, userCred mcclient.TokenCredential, volumeId string, autoStart bool, parenentTaskId string) (*taskman.STask, error) {
  896. llm.SetStatus(ctx, userCred, api.LLM_STATUS_START_BIND, "perform bind volume")
  897. params := api.LLMVolumeInput{
  898. LLMId: llm.Id,
  899. VolumeId: volumeId,
  900. AutoStart: autoStart,
  901. }
  902. task, err := taskman.TaskManager.NewTask(ctx, "LLMAttachTask", llm, userCred, jsonutils.Marshal(params).(*jsonutils.JSONDict), parenentTaskId, "", nil)
  903. if err != nil {
  904. return nil, errors.Wrap(err, "NewTask")
  905. }
  906. err = task.ScheduleRun(nil)
  907. if err != nil {
  908. return nil, errors.Wrap(err, "ScheduleRun")
  909. }
  910. return task, nil
  911. }
  912. func (llm *SLLM) ChangeServerNetworkConfig(ctx context.Context, bandwidth int, whitePrefixes []string, noSync bool) error {
  913. s := auth.GetAdminSession(ctx, options.Options.Region)
  914. params := baseoptions.BaseListOptions{}
  915. params.Scope = "max"
  916. limit := 0
  917. params.Limit = &limit
  918. serverNicObjs, err := compute.Servernetworks.ListDescendent(s, llm.CmpId, jsonutils.Marshal(params))
  919. if err != nil {
  920. return errors.Wrap(err, "compute.Servernetworks.ListDescendent")
  921. } else if len(serverNicObjs.Data) == 0 {
  922. return errors.Wrap(httperrors.ErrEmptyRequest, "compute.Servernetworks.ListDescendent")
  923. }
  924. gns := computeapi.GuestnetworkDetails{}
  925. err = serverNicObjs.Data[0].Unmarshal(&gns)
  926. if err != nil {
  927. return errors.Wrap(err, "Unmarshal GuestnetworkDetails")
  928. }
  929. if gns.BwLimit != bandwidth {
  930. // need to change bandwidth
  931. params := computeapi.ServerChangeBandwidthInput{}
  932. params.Mac = gns.MacAddr
  933. params.Index = 0
  934. params.Bandwidth = bandwidth
  935. params.NoSync = &noSync
  936. _, err := compute.Servers.PerformAction(s, llm.CmpId, "change-bandwidth", jsonutils.Marshal(params))
  937. if err != nil {
  938. return errors.Wrap(err, "compute.Servers.PerformAction change-bandwidth")
  939. }
  940. }
  941. /*if len(adbWhitePrefixes) > 0 {
  942. for _, pm := range gns.PortMappings {
  943. if pm.Port == apis.PHONE_ADB_PORT {
  944. // verify adb port remote ips
  945. remoteIps := stringutils2.NewSortedStrings(pm.RemoteIps)
  946. remoteIps2 := stringutils2.NewSortedStrings(adbWhitePrefixes)
  947. if !stringutils2.Equals(remoteIps, remoteIps2) {
  948. // need to update remote Ips
  949. params := computeapi.GuestnetworkUpdateInput{}
  950. for i := range gns.PortMappings {
  951. npm := gns.PortMappings[i]
  952. if gns.PortMappings[i].Port == apis.PHONE_ADB_PORT {
  953. npm.RemoteIps = adbWhitePrefixes
  954. }
  955. params.PortMappings = append(params.PortMappings, npm)
  956. }
  957. _, err := compute.Servernetworks.Update(s, gns.GuestId, gns.NetworkId, nil, jsonutils.Marshal(params))
  958. if err != nil {
  959. return errors.Wrap(err, "Servernetworks.Update")
  960. }
  961. }
  962. break
  963. }
  964. }
  965. }*/
  966. return nil
  967. }
  968. func (llm *SLLM) PerformNetConfig(
  969. ctx context.Context,
  970. userCred mcclient.TokenCredential,
  971. query jsonutils.JSONObject,
  972. input api.LLMChangeNetworkInput,
  973. ) (jsonutils.JSONObject, error) {
  974. err := llm.ChangeServerNetworkConfig(ctx, input.BandwidthMb, input.WhitePrefxies, false)
  975. if err != nil {
  976. return nil, errors.Wrap(err, "changeServerNetworkConfig")
  977. }
  978. if llm.BandwidthMb != input.BandwidthMb {
  979. _, err := db.Update(llm, func() error {
  980. llm.BandwidthMb = input.BandwidthMb
  981. return nil
  982. })
  983. if err != nil {
  984. return nil, errors.Wrap(err, "update")
  985. }
  986. }
  987. return nil, nil
  988. }
  989. func (llm *SLLM) purgeModelList() error {
  990. return GetLLMInstantModelManager().purgeModelList(llm.Id)
  991. }