resource_query_adapter.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493
  1. // Copyright 2019 Yunion
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package adapters
  15. import (
  16. "context"
  17. "fmt"
  18. "yunion.io/x/jsonutils"
  19. "yunion.io/x/log"
  20. "yunion.io/x/onecloud/pkg/mcclient/modules/compute"
  21. "yunion.io/x/onecloud/pkg/mcclient/modules/image"
  22. "yunion.io/x/onecloud/pkg/mcp-server/models"
  23. )
  24. // ListCloudRegions 查询 Cloudpods 中的区域列表
  25. func (a CloudpodsAdapter) ListCloudRegions(ctx context.Context, limit int, offset int, search string, provider string, ak string, sk string) (*models.CloudregionListResponse, error) {
  26. // 获取 Cloudpods 会话
  27. session, err := a.getSession(ctx, ak, sk)
  28. if err != nil {
  29. return nil, err
  30. }
  31. // 构造查询参数
  32. params := jsonutils.NewDict()
  33. if limit > 0 {
  34. // 设置查询结果数量限制
  35. params.Set("limit", jsonutils.NewInt(int64(limit)))
  36. }
  37. if offset > 0 {
  38. // 设置查询偏移量
  39. params.Set("offset", jsonutils.NewInt(int64(offset)))
  40. }
  41. if search != "" {
  42. // 设置搜索关键字
  43. params.Set("search", jsonutils.NewString(search))
  44. }
  45. if provider != "" {
  46. // 设置云提供商过滤条件
  47. providers := jsonutils.NewArray()
  48. providers.Add(jsonutils.NewString(provider))
  49. params.Set("providers", providers)
  50. }
  51. // 调用 Cloudpods API 查询区域列表
  52. result, err := compute.Cloudregions.List(session, params)
  53. if err != nil {
  54. return nil, err
  55. }
  56. // 构造响应数据
  57. response := &models.CloudregionListResponse{
  58. Limit: int64(limit),
  59. Offset: int64(offset),
  60. Cloudregions: make([]models.CloudregionDetails, 0),
  61. Total: int64(result.Total),
  62. }
  63. // 遍历查询结果,将数据转换为响应格式
  64. for _, data := range result.Data {
  65. region := models.CloudregionDetails{}
  66. if err := data.Unmarshal(&region); err != nil {
  67. // 如果数据转换失败,记录警告日志并跳过该条数据
  68. log.Warningf("Failed to unmarshal cloudregion details: %s", err)
  69. continue
  70. }
  71. response.Cloudregions = append(response.Cloudregions, region)
  72. }
  73. return response, nil
  74. }
  75. // ListVPCs 查询 Cloudpods 中的 VPC 列表
  76. func (a *CloudpodsAdapter) ListVPCs(ctx context.Context, limit int, offset int, search string, cloudregionId string, ak string, sk string) (*models.VpcListResponse, error) {
  77. // 获取 Cloudpods 会话
  78. session, err := a.getSession(ctx, ak, sk)
  79. if err != nil {
  80. return nil, err
  81. }
  82. // 构造查询参数
  83. params := jsonutils.NewDict()
  84. if limit > 0 {
  85. // 设置查询结果数量限制
  86. params.Set("limit", jsonutils.NewInt(int64(limit)))
  87. }
  88. if offset > 0 {
  89. // 设置查询偏移量
  90. params.Set("offset", jsonutils.NewInt(int64(offset)))
  91. }
  92. if search != "" {
  93. // 设置搜索关键字
  94. params.Set("search", jsonutils.NewString(search))
  95. }
  96. if cloudregionId != "" {
  97. // 设置云区域 ID 过滤条件
  98. cloudregionIds := jsonutils.NewArray()
  99. cloudregionIds.Add(jsonutils.NewString(cloudregionId))
  100. params.Set("cloudregion_id", cloudregionIds)
  101. }
  102. // 调用 Cloudpods API 查询 VPC 列表
  103. result, err := compute.Vpcs.List(session, params)
  104. if err != nil {
  105. return nil, fmt.Errorf("failed to list vpcs: %w", err)
  106. }
  107. // 构造响应数据
  108. response := &models.VpcListResponse{
  109. Limit: int64(limit),
  110. Offset: int64(offset),
  111. Vpcs: make([]models.VpcDetails, 0),
  112. Total: int64(result.Total),
  113. }
  114. // 遍历查询结果,将数据转换为响应格式
  115. for _, data := range result.Data {
  116. vpc := models.VpcDetails{}
  117. if err := data.Unmarshal(&vpc); err != nil {
  118. // 如果数据转换失败,记录警告日志并跳过该条数据
  119. log.Warningf("Failed to unmarshal vpc details: %s", err)
  120. continue
  121. }
  122. response.Vpcs = append(response.Vpcs, vpc)
  123. }
  124. return response, nil
  125. }
  126. // ListNetworks 查询 Cloudpods 中的网络列表
  127. func (a *CloudpodsAdapter) ListNetworks(ctx context.Context, limit int, offset int, search string, vpcId string, ak string, sk string) (*models.NetworkListResponse, error) {
  128. // 获取 Cloudpods 会话
  129. session, err := a.getSession(ctx, ak, sk)
  130. if err != nil {
  131. return nil, err
  132. }
  133. // 构造查询参数
  134. params := jsonutils.NewDict()
  135. if limit > 0 {
  136. // 设置查询结果数量限制
  137. params.Set("limit", jsonutils.NewInt(int64(limit)))
  138. }
  139. if offset > 0 {
  140. // 设置查询偏移量
  141. params.Set("offset", jsonutils.NewInt(int64(offset)))
  142. }
  143. if search != "" {
  144. // 设置搜索关键字
  145. params.Set("search", jsonutils.NewString(search))
  146. }
  147. if vpcId != "" {
  148. // 设置 VPC ID 过滤条件
  149. //vpcIds := jsonutils.NewArray()
  150. //vpcIds.Add(jsonutils.NewString(vpcId))
  151. //params.Set("vpc_id", vpcIds)
  152. params.Set("vpc_id", jsonutils.NewString(vpcId))
  153. }
  154. // 调用 Cloudpods API 查询网络列表
  155. result, err := compute.Networks.List(session, params)
  156. if err != nil {
  157. return nil, fmt.Errorf("failed to list networks: %w", err)
  158. }
  159. // 构造响应数据
  160. response := &models.NetworkListResponse{
  161. Limit: int64(limit),
  162. Offset: int64(offset),
  163. Networks: make([]models.NetworkDetails, 0),
  164. Total: int64(result.Total),
  165. }
  166. // 遍历查询结果,将数据转换为响应格式
  167. for _, data := range result.Data {
  168. network := models.NetworkDetails{}
  169. if err := data.Unmarshal(&network); err != nil {
  170. // 如果数据转换失败,记录警告日志并跳过该条数据
  171. log.Warningf("Failed to unmarshal network details: %s", err)
  172. continue
  173. }
  174. response.Networks = append(response.Networks, network)
  175. }
  176. return response, nil
  177. }
  178. // ListImages 查询 Cloudpods 中的镜像列表
  179. func (a *CloudpodsAdapter) ListImages(ctx context.Context, limit int, offset int, search string, osTypes []string, ak string, sk string) (*models.ImageListResponse, error) {
  180. // 获取 Cloudpods 会话
  181. session, err := a.getSession(ctx, ak, sk)
  182. if err != nil {
  183. return nil, err
  184. }
  185. // 构造查询参数
  186. params := jsonutils.NewDict()
  187. if limit > 0 {
  188. // 设置查询结果数量限制
  189. params.Set("limit", jsonutils.NewInt(int64(limit)))
  190. }
  191. if offset > 0 {
  192. // 设置查询偏移量
  193. params.Set("offset", jsonutils.NewInt(int64(offset)))
  194. }
  195. if search != "" {
  196. // 设置搜索关键字
  197. params.Set("search", jsonutils.NewString(search))
  198. }
  199. if len(osTypes) > 0 {
  200. // 设置操作系统类型过滤条件
  201. osTypesArray := jsonutils.NewArray()
  202. for _, osType := range osTypes {
  203. osTypesArray.Add(jsonutils.NewString(osType))
  204. }
  205. params.Set("os_types", osTypesArray)
  206. }
  207. // 调用 Cloudpods API 查询镜像列表
  208. result, err := image.Images.List(session, params)
  209. if err != nil {
  210. return nil, fmt.Errorf("failed to list images: %w", err)
  211. }
  212. // 构造响应数据
  213. response := &models.ImageListResponse{
  214. Limit: int64(limit),
  215. Offset: int64(offset),
  216. Images: make([]models.ImageDetails, 0),
  217. Total: int64(result.Total),
  218. }
  219. // 遍历查询结果,将数据转换为响应格式
  220. for _, data := range result.Data {
  221. image := models.ImageDetails{}
  222. if err := data.Unmarshal(&image); err != nil {
  223. // 如果数据转换失败,记录警告日志并跳过该条数据
  224. log.Warningf("Failed to unmarshal image details: %s", err)
  225. continue
  226. }
  227. response.Images = append(response.Images, image)
  228. }
  229. return response, nil
  230. }
  231. // ListServerSkus 查询 Cloudpods 中的服务器规格列表
  232. func (a *CloudpodsAdapter) ListServerSkus(ctx context.Context, limit int, offset int, search string, cloudregionIds []string, zoneIds []string, cpuCoreCount []string, memorySizeMB []string, providers []string, cpuArch []string, ak string, sk string) (*models.ServerSkuListResponse, error) {
  233. // 获取 Cloudpods 会话
  234. session, err := a.getSession(ctx, ak, sk)
  235. if err != nil {
  236. return nil, err
  237. }
  238. // 构造查询参数
  239. params := jsonutils.NewDict()
  240. if limit > 0 {
  241. // 设置查询结果数量限制
  242. params.Set("limit", jsonutils.NewInt(int64(limit)))
  243. }
  244. if offset > 0 {
  245. // 设置查询偏移量
  246. params.Set("offset", jsonutils.NewInt(int64(offset)))
  247. }
  248. if search != "" {
  249. // 设置搜索关键字
  250. params.Set("search", jsonutils.NewString(search))
  251. }
  252. if len(cloudregionIds) > 0 {
  253. // 设置云区域 ID 过滤条件
  254. cloudregionIdArray := jsonutils.NewArray()
  255. for _, id := range cloudregionIds {
  256. cloudregionIdArray.Add(jsonutils.NewString(id))
  257. }
  258. params.Set("cloudregion_id", cloudregionIdArray)
  259. }
  260. if len(zoneIds) > 0 {
  261. // 设置可用区 ID 过滤条件
  262. zoneIdArray := jsonutils.NewArray()
  263. for _, id := range zoneIds {
  264. zoneIdArray.Add(jsonutils.NewString(id))
  265. }
  266. params.Set("zone_ids", zoneIdArray)
  267. }
  268. if len(cpuCoreCount) > 0 {
  269. // 设置 CPU 核心数过滤条件
  270. cpuCoreArray := jsonutils.NewArray()
  271. for _, count := range cpuCoreCount {
  272. cpuCoreArray.Add(jsonutils.NewString(count))
  273. }
  274. params.Set("cpu_core_count", cpuCoreArray)
  275. }
  276. if len(memorySizeMB) > 0 {
  277. // 设置内存大小过滤条件
  278. memoryArray := jsonutils.NewArray()
  279. for _, size := range memorySizeMB {
  280. memoryArray.Add(jsonutils.NewString(size))
  281. }
  282. params.Set("memory_size_mb", memoryArray)
  283. }
  284. if len(providers) > 0 {
  285. // 设置提供商过滤条件
  286. providerArray := jsonutils.NewArray()
  287. for _, provider := range providers {
  288. providerArray.Add(jsonutils.NewString(provider))
  289. }
  290. params.Set("providers", providerArray)
  291. }
  292. if len(cpuArch) > 0 {
  293. // 设置 CPU 架构过滤条件
  294. cpuArchArray := jsonutils.NewArray()
  295. for _, arch := range cpuArch {
  296. cpuArchArray.Add(jsonutils.NewString(arch))
  297. }
  298. params.Set("cpu_arch", cpuArchArray)
  299. }
  300. // 调用 Cloudpods API 查询服务器规格列表
  301. result, err := compute.ServerSkus.List(session, params)
  302. if err != nil {
  303. return nil, fmt.Errorf("failed to list server skus: %w", err)
  304. }
  305. // 构造响应数据
  306. response := &models.ServerSkuListResponse{
  307. Limit: int64(limit),
  308. Offset: int64(offset),
  309. Serverskus: make([]models.ServerSkuDetails, 0),
  310. Total: int64(result.Total),
  311. }
  312. // 遍历查询结果,将数据转换为响应格式
  313. for _, data := range result.Data {
  314. sku := models.ServerSkuDetails{}
  315. if err := data.Unmarshal(&sku); err != nil {
  316. // 如果数据转换失败,记录警告日志并跳过该条数据
  317. log.Warningf("Failed to unmarshal server sku details: %s", err)
  318. continue
  319. }
  320. response.Serverskus = append(response.Serverskus, sku)
  321. }
  322. return response, nil
  323. }
  324. // ListStorages 查询 Cloudpods 中的存储列表
  325. func (a *CloudpodsAdapter) ListStorages(ctx context.Context, limit int, offset int, search string, cloudregionIds []string, zoneIds []string, providers []string, storageTypes []string, hostId string, ak string, sk string) (*models.StorageListResponse, error) {
  326. // 获取 Cloudpods 会话
  327. session, err := a.getSession(ctx, ak, sk)
  328. if err != nil {
  329. return nil, err
  330. }
  331. // 构造查询参数
  332. params := jsonutils.NewDict()
  333. if limit > 0 {
  334. // 设置查询结果数量限制
  335. params.Set("limit", jsonutils.NewInt(int64(limit)))
  336. }
  337. if offset > 0 {
  338. // 设置查询偏移量
  339. params.Set("offset", jsonutils.NewInt(int64(offset)))
  340. }
  341. if search != "" {
  342. // 设置搜索关键字
  343. params.Set("search", jsonutils.NewString(search))
  344. }
  345. if len(cloudregionIds) > 0 {
  346. // 设置云区域 ID 过滤条件
  347. cloudregionIdArray := jsonutils.NewArray()
  348. for _, id := range cloudregionIds {
  349. cloudregionIdArray.Add(jsonutils.NewString(id))
  350. }
  351. params.Set("cloudregion_id", cloudregionIdArray)
  352. }
  353. if len(zoneIds) > 0 {
  354. // 设置可用区 ID 过滤条件
  355. zoneIdArray := jsonutils.NewArray()
  356. for _, id := range zoneIds {
  357. zoneIdArray.Add(jsonutils.NewString(id))
  358. }
  359. params.Set("zone_ids", zoneIdArray)
  360. }
  361. if len(providers) > 0 {
  362. // 设置提供商过滤条件
  363. providerArray := jsonutils.NewArray()
  364. for _, provider := range providers {
  365. providerArray.Add(jsonutils.NewString(provider))
  366. }
  367. params.Set("providers", providerArray)
  368. }
  369. if len(storageTypes) > 0 {
  370. // 设置存储类型过滤条件
  371. for _, storageType := range storageTypes {
  372. params.Set("storage_type", jsonutils.NewString(storageType))
  373. break
  374. }
  375. }
  376. if hostId != "" {
  377. // 设置主机 ID 过滤条件
  378. params.Set("host_id", jsonutils.NewString(hostId))
  379. }
  380. // 调用 Cloudpods API 查询存储列表
  381. result, err := compute.Storages.List(session, params)
  382. if err != nil {
  383. return nil, fmt.Errorf("failed to list storages: %w", err)
  384. }
  385. // 构造响应数据
  386. response := &models.StorageListResponse{
  387. Limit: int64(limit),
  388. Offset: int64(offset),
  389. Storages: make([]models.StorageDetails, 0),
  390. Total: int64(result.Total),
  391. }
  392. // 遍历查询结果,将数据转换为响应格式
  393. for _, data := range result.Data {
  394. storage := models.StorageDetails{}
  395. if err := data.Unmarshal(&storage); err != nil {
  396. // 如果数据转换失败,记录警告日志并跳过该条数据
  397. log.Warningf("Failed to unmarshal storage details: %s", err)
  398. continue
  399. }
  400. response.Storages = append(response.Storages, storage)
  401. }
  402. return response, nil
  403. }
  404. // ListServers 查询 Cloudpods 中的服务器列表
  405. func (a *CloudpodsAdapter) ListServers(ctx context.Context, limit int, offset int, search string, status string, ak string, sk string) (*models.ServerListResponse, error) {
  406. // 获取 Cloudpods 会话
  407. session, err := a.getSession(ctx, ak, sk)
  408. if err != nil {
  409. return nil, err
  410. }
  411. // 构造查询参数
  412. params := jsonutils.NewDict()
  413. if limit > 0 {
  414. // 设置查询结果数量限制
  415. params.Set("limit", jsonutils.NewInt(int64(limit)))
  416. }
  417. if offset > 0 {
  418. // 设置查询偏移量
  419. params.Set("offset", jsonutils.NewInt(int64(offset)))
  420. }
  421. if search != "" {
  422. // 设置搜索关键字
  423. params.Set("search", jsonutils.NewString(search))
  424. }
  425. if status != "" {
  426. // 设置服务器状态过滤条件
  427. params.Set("status", jsonutils.NewString(status))
  428. }
  429. // 调用 Cloudpods API 查询服务器列表
  430. result, err := compute.Servers.List(session, params)
  431. if err != nil {
  432. return nil, fmt.Errorf("failed to list servers: %w", err)
  433. }
  434. // 构造响应数据
  435. response := &models.ServerListResponse{
  436. Limit: int64(limit),
  437. Offset: int64(offset),
  438. Servers: make([]models.ServerDetails, 0),
  439. Total: int64(result.Total),
  440. }
  441. // 遍历查询结果,将数据转换为响应格式
  442. for _, data := range result.Data {
  443. server := models.ServerDetails{}
  444. if err := data.Unmarshal(&server); err != nil {
  445. // 如果数据转换失败,记录警告日志并跳过该条数据
  446. log.Warningf("Failed to unmarshal server details: %s", err)
  447. continue
  448. }
  449. response.Servers = append(response.Servers, server)
  450. }
  451. return response, nil
  452. }