hostutils.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  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 hostutils
  15. import (
  16. "context"
  17. "fmt"
  18. "net/http"
  19. "os"
  20. "path"
  21. "yunion.io/x/jsonutils"
  22. "yunion.io/x/log"
  23. "yunion.io/x/pkg/appctx"
  24. "yunion.io/x/pkg/util/regutils"
  25. "yunion.io/x/onecloud/pkg/apis"
  26. computeapi "yunion.io/x/onecloud/pkg/apis/compute"
  27. hostapi "yunion.io/x/onecloud/pkg/apis/host"
  28. "yunion.io/x/onecloud/pkg/appsrv"
  29. "yunion.io/x/onecloud/pkg/cloudcommon/consts"
  30. "yunion.io/x/onecloud/pkg/cloudcommon/workmanager"
  31. "yunion.io/x/onecloud/pkg/hostman/hostinfo/hostbridge"
  32. "yunion.io/x/onecloud/pkg/hostman/hostutils/kubelet"
  33. "yunion.io/x/onecloud/pkg/hostman/isolated_device"
  34. "yunion.io/x/onecloud/pkg/hostman/options"
  35. "yunion.io/x/onecloud/pkg/httperrors"
  36. "yunion.io/x/onecloud/pkg/mcclient"
  37. "yunion.io/x/onecloud/pkg/mcclient/auth"
  38. "yunion.io/x/onecloud/pkg/mcclient/modulebase"
  39. modules "yunion.io/x/onecloud/pkg/mcclient/modules/compute"
  40. "yunion.io/x/onecloud/pkg/mcclient/modules/k8s"
  41. "yunion.io/x/onecloud/pkg/util/cgrouputils/cpuset"
  42. "yunion.io/x/onecloud/pkg/util/fileutils2"
  43. "yunion.io/x/onecloud/pkg/util/pod"
  44. )
  45. type SContainerCpufreqSimulateConfig struct {
  46. CpuinfoMaxFreq int `json:"cpuinfo_max_freq"`
  47. CpuinfoMinFreq int `json:"cpuinfo_min_freq"`
  48. CpuinfoCurFreq int `json:"cpuinfo_cur_freq"`
  49. CpuinfoTransitionLatency int `json:"cpuinfo_transition_latency"`
  50. ScalingDriver string `json:"scaling_driver"`
  51. ScalingGovernors string `json:"scaling_governor"`
  52. ScalingMaxFreq int `json:"scaling_max_freq"`
  53. ScalingMinFreq int `json:"scaling_min_freq"`
  54. ScalingCurFreq int `json:"scaling_cur_freq"`
  55. ScalingSetspeed string `json:"scaling_setspeed"`
  56. ScalingAvailableGovernors string `json:"scaling_available_governors"`
  57. }
  58. type IGuestManager interface {
  59. GetImageDeps(storageType string) []string
  60. }
  61. type IHost interface {
  62. GetZoneId() string
  63. GetHostId() string
  64. GetMasterIp() string
  65. GetCpuArchitecture() string
  66. GetKernelVersion() string
  67. IsAarch64() bool
  68. IsX8664() bool
  69. IsRiscv64() bool
  70. GetHostTopology() *hostapi.HostTopology
  71. GetReservedCpusInfo() (*cpuset.CPUSet, *cpuset.CPUSet)
  72. GetReservedMemMb() int
  73. IsHugepagesEnabled() bool
  74. HugepageSizeKb() int
  75. IsSchedulerNumaAllocateEnabled() bool
  76. CpuCmtBound() float32
  77. MemCmtBound() float32
  78. IsKvmSupport() bool
  79. IsNestedVirtualization() bool
  80. PutHostOnline() error
  81. StartDHCPServer()
  82. GetBridgeDev(bridge string) hostbridge.IBridgeDriver
  83. GetIsolatedDeviceManager() isolated_device.IsolatedDeviceManager
  84. // SyncRootPartitionUsedCapacity() error
  85. GetKubeletConfig() kubelet.KubeletConfig
  86. // containerd related methods
  87. IsContainerHost() bool
  88. GetContainerRuntimeEndpoint() string
  89. GetCRI() pod.CRI
  90. GetContainerCPUMap() *pod.HostContainerCPUMap
  91. GetContainerCpufreqSimulateConfig() *jsonutils.JSONDict
  92. OnCatalogChanged(catalog mcclient.KeystoneServiceCatalogV3)
  93. OnHostFilesChanged(hostfiles []computeapi.SHostFile) error
  94. SetIGuestManager(guestman IGuestManager)
  95. GetIGuestManager() IGuestManager
  96. OnGuestLoadingComplete()
  97. }
  98. func GetComputeSession(ctx context.Context) *mcclient.ClientSession {
  99. return auth.GetAdminSession(ctx, consts.GetRegion())
  100. }
  101. func GetK8sSession(ctx context.Context) *mcclient.ClientSession {
  102. return auth.GetAdminSession(ctx, consts.GetRegion())
  103. }
  104. func GetImageSession(ctx context.Context) *mcclient.ClientSession {
  105. return auth.AdminSession(ctx, consts.GetRegion(), consts.GetZone(), "")
  106. }
  107. func TaskFailed(ctx context.Context, reason string) {
  108. if taskId := ctx.Value(appctx.APP_CONTEXT_KEY_TASK_ID); taskId != nil {
  109. modules.ComputeTasks.TaskFailed2(GetComputeSession(ctx), taskId.(string), reason)
  110. } else {
  111. log.Errorf("Reqeuest task failed missing task id, with reason(%s)", reason)
  112. }
  113. }
  114. func TaskFailed2(ctx context.Context, reason string, params *jsonutils.JSONDict) {
  115. if taskId := ctx.Value(appctx.APP_CONTEXT_KEY_TASK_ID); taskId != nil {
  116. modules.ComputeTasks.TaskFailed3(GetComputeSession(ctx), taskId.(string), reason, params)
  117. } else {
  118. log.Errorf("Reqeuest task failed missing task id, with reason(%s)", reason)
  119. }
  120. }
  121. func TaskComplete(ctx context.Context, params jsonutils.JSONObject) {
  122. if taskId := ctx.Value(appctx.APP_CONTEXT_KEY_TASK_ID); taskId != nil {
  123. modules.ComputeTasks.TaskComplete(GetComputeSession(ctx), taskId.(string), params)
  124. } else {
  125. log.Errorln("Reqeuest task complete missing task id")
  126. }
  127. }
  128. func K8sTaskFailed(ctx context.Context, reason string) {
  129. if taskId := ctx.Value(appctx.APP_CONTEXT_KEY_TASK_ID); taskId != nil {
  130. k8s.KubeTasks.TaskFailed2(GetK8sSession(ctx), taskId.(string), reason)
  131. } else {
  132. log.Errorf("Reqeuest k8s task failed missing task id, with reason(%s)", reason)
  133. }
  134. }
  135. func K8sTaskComplete(ctx context.Context, params jsonutils.JSONObject) {
  136. if taskId := ctx.Value(appctx.APP_CONTEXT_KEY_TASK_ID); taskId != nil {
  137. k8s.KubeTasks.TaskComplete(GetK8sSession(ctx), taskId.(string), params)
  138. } else {
  139. log.Errorln("Reqeuest k8s task complete missing task id")
  140. }
  141. }
  142. func GetWireOfIp(ctx context.Context, params jsonutils.JSONObject) (jsonutils.JSONObject, error) {
  143. res, err := modules.Networks.List(GetComputeSession(ctx), params)
  144. if err != nil {
  145. return nil, err
  146. }
  147. if len(res.Data) == 1 {
  148. wireId, _ := res.Data[0].GetString("wire_id")
  149. return GetWireInfo(ctx, wireId)
  150. } else {
  151. return nil, fmt.Errorf("Fail to get network info: no networks")
  152. }
  153. }
  154. func GetWireInfo(ctx context.Context, wireId string) (jsonutils.JSONObject, error) {
  155. return modules.Wires.Get(GetComputeSession(ctx), wireId, nil)
  156. }
  157. func RemoteStoragecacheCacheImage(ctx context.Context, storagecacheId, imageId, status, spath string) (jsonutils.JSONObject, error) {
  158. var query = jsonutils.NewDict()
  159. query.Set("auto_create", jsonutils.JSONTrue)
  160. var params = jsonutils.NewDict()
  161. params.Set("status", jsonutils.NewString(status))
  162. params.Set("path", jsonutils.NewString(spath))
  163. return modules.Storagecachedimages.Update(GetComputeSession(ctx),
  164. storagecacheId, imageId, query, params)
  165. }
  166. func UpdateResourceStatus(ctx context.Context, man modulebase.IResourceManager, id string, statusInput *apis.PerformStatusInput) (jsonutils.JSONObject, error) {
  167. return man.PerformAction(GetComputeSession(ctx), id, "status", jsonutils.Marshal(statusInput))
  168. }
  169. func UpdateContainerStatus(ctx context.Context, cid string, statusInput *computeapi.ContainerPerformStatusInput) (jsonutils.JSONObject, error) {
  170. return modules.Containers.PerformAction(GetComputeSession(ctx), cid, "status", jsonutils.Marshal(statusInput))
  171. }
  172. func UpdateServerStatus(ctx context.Context, sid string, statusInput *apis.PerformStatusInput) (jsonutils.JSONObject, error) {
  173. return UpdateResourceStatus(ctx, &modules.Servers, sid, statusInput)
  174. }
  175. func UpdateServerContainersStatus(ctx context.Context, sid string, input *computeapi.ServerPerformStatusInput) (jsonutils.JSONObject, error) {
  176. return modules.Servers.PerformAction(GetComputeSession(ctx), sid, "status", jsonutils.Marshal(input))
  177. }
  178. func UpdateServerProgress(ctx context.Context, sid string, progress, progressMbps float64) (jsonutils.JSONObject, error) {
  179. params := map[string]float64{
  180. "progress": progress,
  181. "progress_mbps": progressMbps,
  182. }
  183. return modules.Servers.Update(GetComputeSession(ctx), sid, jsonutils.Marshal(params))
  184. }
  185. func UploadGuestStatus(ctx context.Context, sid string, resp *computeapi.HostUploadGuestStatusInput) (jsonutils.JSONObject, error) {
  186. return modules.Servers.PerformAction(GetComputeSession(ctx), sid, "upload-status", jsonutils.Marshal(resp))
  187. }
  188. func UploadGuestsStatus(ctx context.Context, resp *computeapi.HostUploadGuestsStatusInput) (jsonutils.JSONObject, error) {
  189. return modules.Servers.PerformClassAction(GetComputeSession(ctx), "upload-status", jsonutils.Marshal(resp))
  190. }
  191. func IsGuestDir(f os.FileInfo, serversPath string) bool {
  192. if !regutils.MatchUUID(f.Name()) {
  193. return false
  194. }
  195. if !f.Mode().IsDir() && f.Mode()&os.ModeSymlink == 0 {
  196. return false
  197. }
  198. descFile := path.Join(serversPath, f.Name(), "desc")
  199. if !fileutils2.Exists(descFile) {
  200. return false
  201. }
  202. return true
  203. }
  204. func ResponseOk(ctx context.Context, w http.ResponseWriter) {
  205. Response(ctx, w, map[string]string{"result": "ok"})
  206. }
  207. func Response(ctx context.Context, w http.ResponseWriter, res interface{}) {
  208. if taskId := ctx.Value(appctx.APP_CONTEXT_KEY_TASK_ID); taskId != nil {
  209. w.Header().Set("X-Request-Id", taskId.(string))
  210. }
  211. switch res.(type) {
  212. case string:
  213. appsrv.Send(w, res.(string))
  214. case jsonutils.JSONObject:
  215. appsrv.SendJSON(w, res.(jsonutils.JSONObject))
  216. case error:
  217. httperrors.GeneralServerError(ctx, w, res.(error))
  218. default:
  219. appsrv.SendStruct(w, res)
  220. }
  221. }
  222. var (
  223. wm *workmanager.SWorkManager
  224. imageCacheW *workmanager.SWorkManager
  225. backupW *workmanager.SWorkManager
  226. k8sWm *workmanager.SWorkManager
  227. imagePreCacheW *workmanager.SWorkManager
  228. ParamsError = fmt.Errorf("Delay task parse params error")
  229. )
  230. func GetWorkManager() *workmanager.SWorkManager {
  231. return wm
  232. }
  233. func DelayTask(ctx context.Context, task workmanager.DelayTaskFunc, params interface{}) {
  234. wm.DelayTask(ctx, task, params)
  235. }
  236. func DelayImageCacheTask(ctx context.Context, task workmanager.DelayTaskFunc, params interface{}) {
  237. imageCacheW.DelayTask(ctx, task, params)
  238. }
  239. func DelayImagePreCacheTask(ctx context.Context, task workmanager.DelayTaskFunc, params interface{}) {
  240. imagePreCacheW.DelayTask(ctx, task, params)
  241. }
  242. func DelayBackupTask(ctx context.Context, task workmanager.DelayTaskFunc, params interface{}) {
  243. backupW.DelayTask(ctx, task, params)
  244. }
  245. func DelayKubeTask(ctx context.Context, task workmanager.DelayTaskFunc, params interface{}) {
  246. k8sWm.DelayTask(ctx, task, params)
  247. }
  248. func DelayTaskWithoutReqctx(ctx context.Context, task workmanager.DelayTaskFunc, params interface{}) {
  249. wm.DelayTaskWithoutReqctx(ctx, task, params)
  250. }
  251. func DelayTaskWithWorker(
  252. ctx context.Context, task workmanager.DelayTaskFunc,
  253. params interface{}, worker *appsrv.SWorkerManager,
  254. ) {
  255. wm.DelayTaskWithWorker(ctx, task, params, worker)
  256. }
  257. func InitWorkerManager() {
  258. InitWorkerManagerWithCount(options.HostOptions.DefaultRequestWorkerCount)
  259. initImageCacheWorkerManager()
  260. }
  261. func initImageCacheWorkerManager() {
  262. imageCacheW = workmanager.NewWorkManger("ImageCacheDelayTaskWorkers", TaskFailed, TaskComplete, options.HostOptions.ImageCacheWorkerCount)
  263. imagePreCacheW = workmanager.NewWorkManger("ImagePrefetchCacheDelayTaskWorkers", TaskFailed, TaskComplete, options.HostOptions.ImageCacheWorkerCount)
  264. }
  265. func initBackupWorkerManager() {
  266. backupW = workmanager.NewWorkManger("BackupDelayTaskWorkers", TaskFailed, TaskComplete, options.HostOptions.BackupTaskWorkerCount)
  267. }
  268. func InitWorkerManagerWithCount(count int) {
  269. wm = workmanager.NewWorkManger("GeneralDelayedTaskWorkers", TaskFailed, TaskComplete, count)
  270. }
  271. func InitK8sWorkerManager() {
  272. k8sWm = workmanager.NewWorkManger("K8sDelayedTaskWorkers", K8sTaskFailed, K8sTaskComplete, options.HostOptions.DefaultRequestWorkerCount)
  273. }
  274. func Init() {
  275. InitWorkerManager()
  276. InitK8sWorkerManager()
  277. initBackupWorkerManager()
  278. }