guestman.go 61 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068
  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 guestman
  15. import (
  16. "bytes"
  17. "context"
  18. "encoding/base64"
  19. "encoding/json"
  20. "fmt"
  21. "net/http"
  22. "os"
  23. "path"
  24. "path/filepath"
  25. "runtime/debug"
  26. "strconv"
  27. "strings"
  28. "sync"
  29. "time"
  30. "yunion.io/x/jsonutils"
  31. "yunion.io/x/log"
  32. "yunion.io/x/pkg/errors"
  33. "yunion.io/x/pkg/util/clock"
  34. "yunion.io/x/pkg/util/seclib"
  35. "yunion.io/x/pkg/utils"
  36. "yunion.io/x/onecloud/pkg/apis"
  37. "yunion.io/x/onecloud/pkg/apis/compute"
  38. hostapi "yunion.io/x/onecloud/pkg/apis/host"
  39. "yunion.io/x/onecloud/pkg/appsrv"
  40. "yunion.io/x/onecloud/pkg/hostman/container/prober"
  41. "yunion.io/x/onecloud/pkg/hostman/container/snapshot_service"
  42. "yunion.io/x/onecloud/pkg/hostman/guestman/arch"
  43. "yunion.io/x/onecloud/pkg/hostman/guestman/desc"
  44. fwd "yunion.io/x/onecloud/pkg/hostman/guestman/forwarder"
  45. fwdpb "yunion.io/x/onecloud/pkg/hostman/guestman/forwarder/api"
  46. "yunion.io/x/onecloud/pkg/hostman/guestman/pod/pleg"
  47. "yunion.io/x/onecloud/pkg/hostman/guestman/pod/runtime"
  48. "yunion.io/x/onecloud/pkg/hostman/guestman/pod/statusman"
  49. "yunion.io/x/onecloud/pkg/hostman/guestman/types"
  50. deployapi "yunion.io/x/onecloud/pkg/hostman/hostdeployer/apis"
  51. "yunion.io/x/onecloud/pkg/hostman/hostinfo"
  52. "yunion.io/x/onecloud/pkg/hostman/hostinfo/hostconsts"
  53. "yunion.io/x/onecloud/pkg/hostman/hostutils"
  54. "yunion.io/x/onecloud/pkg/hostman/monitor"
  55. "yunion.io/x/onecloud/pkg/hostman/options"
  56. "yunion.io/x/onecloud/pkg/hostman/storageman"
  57. "yunion.io/x/onecloud/pkg/hostman/storageman/lvmutils"
  58. "yunion.io/x/onecloud/pkg/hostman/storageman/remotefile"
  59. "yunion.io/x/onecloud/pkg/httperrors"
  60. "yunion.io/x/onecloud/pkg/mcclient"
  61. modules "yunion.io/x/onecloud/pkg/mcclient/modules/compute"
  62. "yunion.io/x/onecloud/pkg/util/cgrouputils"
  63. "yunion.io/x/onecloud/pkg/util/cgrouputils/cpuset"
  64. "yunion.io/x/onecloud/pkg/util/fileutils2"
  65. "yunion.io/x/onecloud/pkg/util/netutils2"
  66. "yunion.io/x/onecloud/pkg/util/pod"
  67. "yunion.io/x/onecloud/pkg/util/procutils"
  68. "yunion.io/x/onecloud/pkg/util/timeutils2"
  69. )
  70. var (
  71. LAST_USED_PORT = 0
  72. LAST_USED_NBD_SERVER_PORT = 0
  73. LAST_USED_MIGRATE_PORT = 0
  74. NbdWorker *appsrv.SWorkerManager
  75. )
  76. const (
  77. VNC_PORT_BASE = 5900
  78. GUEST_RUNNING = compute.VM_RUNNING
  79. GUEST_BLOCK_STREAM = compute.VM_BLOCK_STREAM
  80. GUEST_BLOCK_STREAM_FAIL = compute.VM_BLOCK_STREAM_FAIL
  81. GUEST_SUSPEND = compute.VM_SUSPEND
  82. GUSET_STOPPED = "stopped"
  83. GUEST_NOT_FOUND = "notfound"
  84. )
  85. type SGuestManager struct {
  86. host hostutils.IHost
  87. ServersPath string
  88. Servers *sync.Map
  89. CandidateServers map[string]GuestRuntimeInstance
  90. UnknownServers *sync.Map
  91. ServersLock *sync.Mutex
  92. portsInUse *sync.Map
  93. // guests nics traffics lock
  94. TrafficLock *sync.Mutex
  95. GuestStartWorker *appsrv.SWorkerManager
  96. isLoaded bool
  97. // dirty servers chan
  98. dirtyServers []GuestRuntimeInstance
  99. dirtyServersChan chan struct{}
  100. qemuMachineCpuMax map[string]uint
  101. qemuMaxMem int
  102. hostagentNumaAllocate bool
  103. cpuSet *CpuSetCounter
  104. pythonPath string
  105. // container related members
  106. containerProbeManager prober.Manager
  107. enableDirtyRecoveryFeature bool
  108. containerRuntimeManager runtime.Runtime
  109. pleg pleg.PodLifecycleEventGenerator
  110. podCache runtime.Cache
  111. cpufreqSimulateManager *SCpuFreqRealTimeSimulateManager
  112. }
  113. func NewGuestManager(host hostutils.IHost, serversPath string, workerCnt int) (*SGuestManager, error) {
  114. // init nbd worker
  115. NbdWorker = appsrv.NewWorkerManager("nbd_worker", workerCnt, appsrv.DEFAULT_BACKLOG, false)
  116. manager := &SGuestManager{}
  117. manager.host = host
  118. host.SetIGuestManager(manager)
  119. manager.ServersPath = serversPath
  120. manager.Servers = new(sync.Map)
  121. manager.portsInUse = new(sync.Map)
  122. manager.CandidateServers = make(map[string]GuestRuntimeInstance, 0)
  123. manager.UnknownServers = new(sync.Map)
  124. manager.ServersLock = &sync.Mutex{}
  125. manager.TrafficLock = &sync.Mutex{}
  126. manager.GuestStartWorker = appsrv.NewWorkerManager("GuestStart", 1, appsrv.DEFAULT_BACKLOG, false)
  127. // manager.StartCpusetBalancer()
  128. manager.dirtyServersChan = make(chan struct{})
  129. manager.dirtyServers = make([]GuestRuntimeInstance, 0)
  130. manager.qemuMachineCpuMax = make(map[string]uint, 0)
  131. err := procutils.NewCommand("mkdir", "-p", manager.QemuLogDir()).Run()
  132. if err != nil {
  133. return nil, errors.Wrap(err, "mkdir qemu log dir")
  134. }
  135. if manager.host.IsContainerHost() {
  136. statusman.GetManager().Start()
  137. manager.startContainerProbeManager()
  138. runtimeMan, err := runtime.NewRuntimeManager(manager.GetCRI())
  139. if err != nil {
  140. return nil, errors.Wrap(err, "new container runtime manager")
  141. }
  142. manager.podCache = runtime.NewCache()
  143. manager.containerRuntimeManager = runtimeMan
  144. manager.pleg = pleg.NewGenericPLEG(runtimeMan, pleg.ChannelCapacity, pleg.RelistPeriod, manager.podCache, clock.RealClock{})
  145. manager.pleg.Start()
  146. go func() {
  147. if err := manager.startContainerdSnapshotService(); err != nil {
  148. log.Fatalf("start containerd snapshot service: %s", err)
  149. }
  150. }()
  151. if options.HostOptions.EnableRealtimeCpufreqSimulate {
  152. cpufreqConfig := manager.host.GetContainerCpufreqSimulateConfig()
  153. if cpufreqConfig != nil {
  154. maxFreq, _ := cpufreqConfig.Int("scaling_max_freq")
  155. minFreq, _ := cpufreqConfig.Int("scaling_min_freq")
  156. interval := options.HostOptions.RealtimeCpufreqSimulateInterval
  157. manager.cpufreqSimulateManager = newCpuFreqRealTimeSimulateManager(interval, maxFreq, minFreq)
  158. }
  159. }
  160. }
  161. return manager, nil
  162. }
  163. func (h *SGuestManager) startContainerdSnapshotService() error {
  164. root := filepath.Join(options.HostOptions.ServersPath, "containerd_snapshots")
  165. err := snapshot_service.StartService(h, root)
  166. if err != nil {
  167. return errors.Wrap(err, "new snapshot service")
  168. }
  169. return nil
  170. }
  171. func (h *SGuestManager) GetContainerManager(serverId string) (snapshot_service.ISnapshotContainerManager, error) {
  172. pod, ok := h.GetServer(serverId)
  173. if !ok {
  174. return nil, errors.Wrapf(httperrors.ErrNotFound, "server %s not found", serverId)
  175. }
  176. return pod.(snapshot_service.ISnapshotContainerManager), nil
  177. }
  178. func (m *SGuestManager) startContainerSyncLoop() {
  179. if m.host.IsContainerHost() {
  180. go func() {
  181. m.syncContainerLoop(m.pleg.Watch())
  182. }()
  183. if !options.HostOptions.DisableReconcileContainer {
  184. go func() {
  185. m.reconcileContainerLoop(m.podCache)
  186. }()
  187. }
  188. StartContainerLogRotateLoop(m)
  189. }
  190. }
  191. func (m *SGuestManager) getMachineVirtMaxCpus() uint {
  192. if m.host.IsAarch64() {
  193. return arch.ARM_MAX_CPUS
  194. } else if m.host.IsRiscv64() {
  195. return arch.RISCV_MAX_CPUS
  196. }
  197. return 0
  198. }
  199. func (m *SGuestManager) InitQemuMaxCpus(machineCaps []monitor.MachineInfo, kvmMaxCpus uint) {
  200. m.qemuMachineCpuMax[compute.VM_MACHINE_TYPE_PC] = arch.X86_MAX_CPUS
  201. m.qemuMachineCpuMax[compute.VM_MACHINE_TYPE_Q35] = arch.X86_MAX_CPUS
  202. m.qemuMachineCpuMax[compute.VM_MACHINE_TYPE_VIRT] = m.getMachineVirtMaxCpus()
  203. if len(machineCaps) == 0 {
  204. return
  205. }
  206. minFunc := func(a, b uint) uint {
  207. if a < b {
  208. return a
  209. }
  210. return b
  211. }
  212. log.Infof("KVM max cpus count: %d", kvmMaxCpus)
  213. supportedMachineType := []string{"pc", "q35", "virt"}
  214. for _, machine := range supportedMachineType {
  215. for i := 0; i < len(machineCaps); i++ {
  216. if (machineCaps[i].Alias != nil && *machineCaps[i].Alias == machine) ||
  217. machineCaps[i].Name == machine {
  218. cpuMax := uint(machineCaps[i].CPUMax)
  219. if kvmMaxCpus > 0 {
  220. cpuMax = minFunc(cpuMax, kvmMaxCpus)
  221. }
  222. if utils.IsInStringArray(machine, []string{"pc", "q35"}) {
  223. // Note: if max cpux exceed 255, machine requires Extended Interrupt Mode enabled.
  224. // You can add an IOMMU using: -device intel-iommu,intremap=on,eim=on
  225. // Set x86 machine max cpu 240 for now.
  226. m.qemuMachineCpuMax[machine] = minFunc(cpuMax, m.qemuMachineCpuMax[machine])
  227. } else {
  228. m.qemuMachineCpuMax[machine] = cpuMax
  229. }
  230. log.Infof("Machine type %s max cpus: %d", machine, m.qemuMachineCpuMax[machine])
  231. }
  232. }
  233. }
  234. }
  235. func (m *SGuestManager) InitQemuMaxMems(maxMems uint) {
  236. if m.host.IsX8664() {
  237. if options.HostOptions.GuestMaxMemSizeMb > 0 {
  238. arch.X86_MAX_MEM_MB = uint(options.HostOptions.GuestMaxMemSizeMb)
  239. } else if maxMems > arch.X86_MAX_MEM_MB {
  240. arch.X86_MAX_MEM_MB = maxMems
  241. }
  242. }
  243. if m.host.IsAarch64() {
  244. if options.HostOptions.GuestMaxMemSizeMb > 0 {
  245. arch.ARM_MAX_MEM_MB = uint(options.HostOptions.GuestMaxMemSizeMb)
  246. } else if maxMems > arch.ARM_MAX_MEM_MB {
  247. arch.ARM_MAX_MEM_MB = maxMems
  248. }
  249. }
  250. if m.host.IsRiscv64() {
  251. if options.HostOptions.GuestMaxMemSizeMb > 0 {
  252. arch.RISCV_MAX_MEM_MB = uint(options.HostOptions.GuestMaxMemSizeMb)
  253. } else if maxMems > arch.RISCV_MAX_MEM_MB {
  254. arch.RISCV_MAX_MEM_MB = maxMems
  255. }
  256. }
  257. }
  258. func (m *SGuestManager) InitPythonPath() error {
  259. defer func() {
  260. log.Infof("Python path %s", m.pythonPath)
  261. }()
  262. out, err := procutils.NewRemoteCommandAsFarAsPossible("which", "python").Output()
  263. if err == nil {
  264. m.pythonPath = string(bytes.TrimSpace(out))
  265. return nil
  266. }
  267. log.Infof("No python found %s: %s", out, err)
  268. out, err = procutils.NewRemoteCommandAsFarAsPossible("which", "python3").Output()
  269. if err == nil {
  270. m.pythonPath = string(bytes.TrimSpace(out))
  271. return nil
  272. }
  273. log.Infof("No python3 found %s: %s", out, err)
  274. out, err = procutils.NewRemoteCommandAsFarAsPossible("which", "python2").Output()
  275. if err == nil {
  276. m.pythonPath = string(bytes.TrimSpace(out))
  277. return nil
  278. }
  279. log.Infof("No python2 found %s: %s", out, err)
  280. return errors.Errorf("No python/python2/python3 found in PATH")
  281. }
  282. func (m *SGuestManager) GetCRI() pod.CRI {
  283. return m.host.GetCRI()
  284. }
  285. func (m *SGuestManager) GetContainerCPUMap() *pod.HostContainerCPUMap {
  286. return m.host.GetContainerCPUMap()
  287. }
  288. func (m *SGuestManager) getPythonPath() string {
  289. return m.pythonPath
  290. }
  291. func (m *SGuestManager) QemuLogDir() string {
  292. return path.Join(m.ServersPath, "logs")
  293. }
  294. func (m *SGuestManager) GetServer(sid string) (GuestRuntimeInstance, bool) {
  295. s, ok := m.Servers.Load(sid)
  296. if ok {
  297. return s.(GuestRuntimeInstance), ok
  298. } else {
  299. return nil, ok
  300. }
  301. }
  302. // 临时解决方案,后面应该统一 SKVMInstance 和 SPodInstance 使用 GuestRuntimeInstance 接口
  303. func (m *SGuestManager) GetKVMServer(sid string) (*SKVMGuestInstance, bool) {
  304. s, ok := m.GetServer(sid)
  305. if !ok {
  306. return nil, false
  307. }
  308. return s.(*SKVMGuestInstance), true
  309. }
  310. func (m *SGuestManager) GetUnknownServer(sid string) (GuestRuntimeInstance, bool) {
  311. s, ok := m.UnknownServers.Load(sid)
  312. if ok {
  313. return s.(GuestRuntimeInstance), ok
  314. } else {
  315. return nil, ok
  316. }
  317. }
  318. func (m *SGuestManager) SaveServer(sid string, s GuestRuntimeInstance) {
  319. m.Servers.Store(sid, s)
  320. }
  321. func (m *SGuestManager) CleanServer(sid string) {
  322. m.Servers.Delete(sid)
  323. }
  324. func (m *SGuestManager) Bootstrap() (chan struct{}, error) {
  325. hostTypo := m.host.GetHostTopology()
  326. if options.HostOptions.EnableHostAgentNumaAllocate {
  327. enableMemAlloc := m.host.IsContainerHost() || m.host.IsHugepagesEnabled()
  328. m.hostagentNumaAllocate = !m.host.IsSchedulerNumaAllocateEnabled() && enableMemAlloc && (len(hostTypo.Nodes) > 1)
  329. }
  330. var reserveCpus = cpuset.NewCPUSet()
  331. hostReserveCpus, guestPinnedCpus := m.host.GetReservedCpusInfo()
  332. if hostReserveCpus != nil {
  333. reserveCpus = reserveCpus.Union(*hostReserveCpus)
  334. }
  335. if guestPinnedCpus != nil {
  336. reserveCpus = reserveCpus.Union(*guestPinnedCpus)
  337. }
  338. cpuSet, err := NewGuestCpuSetCounter(
  339. hostTypo, reserveCpus, m.hostagentNumaAllocate, m.host.IsContainerHost(),
  340. m.host.HugepageSizeKb(), m.host.CpuCmtBound(), m.host.MemCmtBound(), m.host.GetReservedMemMb(),
  341. )
  342. if err != nil {
  343. return nil, err
  344. }
  345. m.cpuSet = cpuSet
  346. m.LoadExistingGuests()
  347. m.host.StartDHCPServer()
  348. if m.isLoaded || len(m.ServersPath) == 0 {
  349. log.Errorln("Guestman bootstrap has been called!!!!!")
  350. } else {
  351. m.isLoaded = true
  352. log.Infof("Loading existing guests ...")
  353. if m.needDirtyRecovery() {
  354. if err := m.createDisableDirtyRecoveryFile(); err != nil {
  355. log.Errorf("create disable dirty recovery file: %s", err)
  356. } else {
  357. log.Infof("[%s created] enable dirty recovery feature", m.disableDirtyRecoveryFilePath())
  358. m.enableDirtyRecoveryFeature = true
  359. }
  360. } else {
  361. log.Infof("[%s existed] disable dirty recovery feature", m.disableDirtyRecoveryFilePath())
  362. m.enableDirtyRecoveryFeature = false
  363. }
  364. if len(m.CandidateServers) > 0 {
  365. m.VerifyExistingGuests(false)
  366. } else {
  367. m.OnLoadExistingGuestsComplete()
  368. }
  369. }
  370. timeutils2.AddTimeout(time.Second*time.Duration(options.HostOptions.EnableDirtyRecoverySeconds), func() {
  371. if err := m.removeDisableDirtyRecoveryFile(); err != nil {
  372. log.Errorf("remove disable dirty recovery file %s: %s", m.disableDirtyRecoveryFilePath(), err)
  373. } else {
  374. log.Infof("[%s removed] enable dirty recovery feature at next bootstrap", m.disableDirtyRecoveryFilePath())
  375. }
  376. })
  377. if m.cpufreqSimulateManager != nil {
  378. go m.cpufreqSimulateManager.StartSetCpuFreqSimulate()
  379. }
  380. m.host.OnGuestLoadingComplete()
  381. return m.dirtyServersChan, nil
  382. }
  383. func (m *SGuestManager) VerifyExistingGuests(pendingDelete bool) {
  384. params := jsonutils.NewDict()
  385. params.Set("limit", jsonutils.NewInt(0))
  386. params.Set("scope", jsonutils.NewString("system"))
  387. params.Set("system", jsonutils.JSONTrue)
  388. params.Set("pending_delete", jsonutils.NewBool(pendingDelete))
  389. params.Set("get_all_guests_on_host", jsonutils.NewString(m.host.GetHostId()))
  390. if len(m.CandidateServers) > 0 {
  391. keys := make([]string, len(m.CandidateServers))
  392. var index = 0
  393. for k := range m.CandidateServers {
  394. keys[index] = k
  395. index++
  396. }
  397. params.Set("filter.0", jsonutils.NewString(fmt.Sprintf("id.in(%s)", strings.Join(keys, ","))))
  398. }
  399. res, err := modules.Servers.List(hostutils.GetComputeSession(context.Background()), params)
  400. if err != nil {
  401. m.OnVerifyExistingGuestsFail(err, pendingDelete)
  402. } else {
  403. m.OnVerifyExistingGuestsSucc(res.Data, pendingDelete)
  404. }
  405. }
  406. func (m *SGuestManager) OnVerifyExistingGuestsFail(err error, pendingDelete bool) {
  407. log.Errorf("OnVerifyExistingGuestFail: %s, try again 30 seconds later", err.Error())
  408. timeutils2.AddTimeout(30*time.Second, func() { m.VerifyExistingGuests(false) })
  409. }
  410. func (m *SGuestManager) disableDirtyRecoveryFilePath() string {
  411. return path.Join(options.HostOptions.ServersPath, "disable-guests-dirty-recovery")
  412. }
  413. func (m *SGuestManager) removeDisableDirtyRecoveryFile() error {
  414. if !fileutils2.Exists(m.disableDirtyRecoveryFilePath()) {
  415. return nil
  416. }
  417. return os.RemoveAll(m.disableDirtyRecoveryFilePath())
  418. }
  419. func (m *SGuestManager) createDisableDirtyRecoveryFile() error {
  420. if fileutils2.Exists(m.disableDirtyRecoveryFilePath()) {
  421. return nil
  422. }
  423. return fileutils2.FilePutContents(m.disableDirtyRecoveryFilePath(), "", false)
  424. }
  425. func (m *SGuestManager) needDirtyRecovery() bool {
  426. if fileutils2.Exists(m.disableDirtyRecoveryFilePath()) {
  427. return false
  428. }
  429. return true
  430. }
  431. func (m *SGuestManager) EnableDirtyRecoveryFeature() bool {
  432. return m.enableDirtyRecoveryFeature
  433. }
  434. func (m *SGuestManager) OnVerifyExistingGuestsSucc(servers []jsonutils.JSONObject, pendingDelete bool) {
  435. for _, v := range servers {
  436. id, _ := v.GetString("id")
  437. server, ok := m.CandidateServers[id]
  438. if !ok {
  439. log.Errorf("verify_existing_guests return unknown server %s ???????", id)
  440. } else {
  441. server.ImportServer(pendingDelete)
  442. }
  443. }
  444. if !pendingDelete {
  445. m.VerifyExistingGuests(true)
  446. } else {
  447. for id, server := range m.CandidateServers {
  448. m.UnknownServers.Store(id, server)
  449. m.dirtyServers = append(m.dirtyServers, server)
  450. log.Errorf("Server %s not found on this host", server.GetName())
  451. m.RemoveCandidateServer(server)
  452. }
  453. }
  454. }
  455. func (m *SGuestManager) RemoveCandidateServer(server GuestRuntimeInstance) {
  456. if _, ok := m.CandidateServers[server.GetInitialId()]; ok {
  457. delete(m.CandidateServers, server.GetInitialId())
  458. if len(m.CandidateServers) == 0 {
  459. m.OnLoadExistingGuestsComplete()
  460. }
  461. }
  462. }
  463. func (m *SGuestManager) OnLoadExistingGuestsComplete() {
  464. log.Infof("Load existing guests complete...")
  465. err := m.host.PutHostOnline()
  466. if err != nil {
  467. log.Fatalf("put host online failed %s", err)
  468. }
  469. go m.verifyDirtyServers()
  470. if !options.HostOptions.EnableCpuBinding {
  471. m.ClenaupCpuset()
  472. }
  473. m.startContainerSyncLoop()
  474. }
  475. func (m *SGuestManager) verifyDirtyServers() {
  476. select {
  477. case <-m.dirtyServersChan:
  478. }
  479. for i := 0; i < len(m.dirtyServers); i++ {
  480. go m.RequestVerifyDirtyServer(m.dirtyServers[i])
  481. }
  482. m.dirtyServers = nil
  483. }
  484. func (m *SGuestManager) ClenaupCpuset() {
  485. m.Servers.Range(func(k, v interface{}) bool {
  486. inst := v.(GuestRuntimeInstance)
  487. guest, ok := inst.(*SKVMGuestInstance)
  488. if !ok {
  489. return true
  490. }
  491. guest.CleanupCpuset()
  492. return true
  493. })
  494. }
  495. func (m *SGuestManager) StartCpusetBalancer() {
  496. if !options.HostOptions.EnableCpuBinding {
  497. return
  498. }
  499. go func() {
  500. defer func() {
  501. if r := recover(); r != nil {
  502. debug.PrintStack()
  503. log.Errorf("Cpuset balancer failed %s", r)
  504. }
  505. }()
  506. for {
  507. time.Sleep(time.Second * 120)
  508. if options.HostOptions.EnableCpuBinding {
  509. m.cpusetBalance()
  510. }
  511. }
  512. }()
  513. }
  514. func (m *SGuestManager) cpusetBalance() {
  515. if !options.HostOptions.DisableSetCgroup {
  516. cgrouputils.RebalanceProcesses(nil)
  517. }
  518. }
  519. func (m *SGuestManager) CPUSet(ctx context.Context, sid string, req *compute.ServerCPUSetInput) (*compute.ServerCPUSetResp, error) {
  520. guest, ok := m.GetKVMServer(sid)
  521. if !ok {
  522. return nil, httperrors.NewNotFoundError("Not found")
  523. }
  524. return guest.CPUSet(ctx, req.CPUS)
  525. }
  526. func (m *SGuestManager) CPUSetRemove(ctx context.Context, sid string) error {
  527. guest, ok := m.GetKVMServer(sid)
  528. if !ok {
  529. return httperrors.NewNotFoundError("Not found")
  530. }
  531. return guest.CPUSetRemove(ctx)
  532. }
  533. func (m *SGuestManager) IsGuestDir(f os.DirEntry) bool {
  534. fi, err := f.Info()
  535. if err != nil {
  536. return false
  537. }
  538. return hostutils.IsGuestDir(fi, m.ServersPath)
  539. }
  540. func (m *SGuestManager) IsGuestExist(sid string) bool {
  541. if _, ok := m.GetServer(sid); !ok {
  542. return false
  543. } else {
  544. return true
  545. }
  546. }
  547. func (m *SGuestManager) LoadExistingGuests() {
  548. files, err := os.ReadDir(m.ServersPath)
  549. if err != nil {
  550. log.Errorf("List servers path %s error %s", m.ServersPath, err)
  551. }
  552. for _, f := range files {
  553. if _, ok := m.GetServer(f.Name()); !ok && m.IsGuestDir(f) {
  554. log.Infof("Find existing guest %s", f.Name())
  555. m.LoadServer(f.Name())
  556. }
  557. }
  558. }
  559. func (m *SGuestManager) GetServerDescFilePath(sid string) string {
  560. return path.Join(m.ServersPath, sid, "desc")
  561. }
  562. func (m *SGuestManager) GetServerDesc(sid string) (*desc.SGuestDesc, error) {
  563. descPath := m.GetServerDescFilePath(sid)
  564. descStr, err := os.ReadFile(descPath)
  565. if err != nil {
  566. return nil, errors.Wrapf(err, "read file %s", descPath)
  567. }
  568. desc := new(desc.SGuestDesc)
  569. jsonSrcDesc, err := jsonutils.Parse(descStr)
  570. if err != nil {
  571. return nil, errors.Wrapf(err, "json parse: %s", descStr)
  572. }
  573. if err := jsonSrcDesc.Unmarshal(desc); err != nil {
  574. return nil, errors.Wrap(err, "unmarshal desc")
  575. }
  576. return desc, nil
  577. }
  578. func (m *SGuestManager) LoadServer(sid string) {
  579. desc, err := m.GetServerDesc(sid)
  580. if err != nil {
  581. log.Errorf("Get server %s desc: %v", sid, err)
  582. return
  583. }
  584. guest := NewGuestRuntimeManager().NewRuntimeInstance(sid, m, desc.Hypervisor)
  585. if err := guest.LoadDesc(); err != nil {
  586. log.Errorf("On load server error: %s", err)
  587. return
  588. }
  589. m.CandidateServers[sid] = guest
  590. if err := guest.PostLoad(m); err != nil {
  591. log.Errorf("Post load server %s: %v", sid, err)
  592. return
  593. }
  594. }
  595. func (m *SGuestManager) ShutdownServers() {
  596. m.Servers.Range(func(k, v interface{}) bool {
  597. inst := v.(GuestRuntimeInstance)
  598. guest, ok := inst.(*SKVMGuestInstance)
  599. if !ok {
  600. return true
  601. }
  602. log.Infof("Start shutdown server %s", guest.GetName())
  603. // scriptStop maybe stuck on guest storage offline
  604. if !guest.forceScriptStop() {
  605. log.Errorf("shutdown server %s failed", guest.GetName())
  606. }
  607. return true
  608. })
  609. }
  610. func (m *SGuestManager) GetQgaRunningGuests() []string {
  611. qgaRunningGuestIds := []string{}
  612. m.Servers.Range(func(k, v interface{}) bool {
  613. guest, ok := v.(*SKVMGuestInstance)
  614. if !ok {
  615. return true
  616. }
  617. if !guest.IsRunning() {
  618. return true
  619. }
  620. if guest.guestAgent == nil {
  621. // in case guestAgent not init
  622. return true
  623. }
  624. err := guest.guestAgent.GuestPing(1)
  625. if err == nil {
  626. qgaRunningGuestIds = append(qgaRunningGuestIds, guest.Id)
  627. } else {
  628. log.Debugf("failed exec guest-ping %s", err)
  629. }
  630. return true
  631. })
  632. return qgaRunningGuestIds
  633. }
  634. func (m *SGuestManager) GetGuestNicDesc(
  635. mac, ip, port, bridge string, isCandidate bool,
  636. ) (*desc.SGuestDesc, *desc.SGuestNetwork) {
  637. if isCandidate {
  638. return m.getGuestNicDescInCandidate(mac, ip, port, bridge)
  639. }
  640. var nic *desc.SGuestNetwork
  641. var guestDesc *desc.SGuestDesc
  642. m.Servers.Range(func(k interface{}, v interface{}) bool {
  643. guest := v.(GuestRuntimeInstance)
  644. if guest.IsLoaded() {
  645. nic = guest.GetNicDescMatch(mac, ip, port, bridge)
  646. if nic != nil {
  647. guestDesc = guest.GetDesc()
  648. return false
  649. }
  650. }
  651. return true
  652. })
  653. return guestDesc, nic
  654. }
  655. func (m *SGuestManager) GetAllGuestIPv6Macs(bridge string) []string {
  656. macs := []string{}
  657. m.Servers.Range(func(k, v interface{}) bool {
  658. guest := v.(GuestRuntimeInstance)
  659. if guest.IsLoaded() {
  660. nicMacs := guest.GetIpv6NicMacs(bridge)
  661. macs = append(macs, nicMacs...)
  662. }
  663. return true
  664. })
  665. return macs
  666. }
  667. func (m *SGuestManager) getGuestNicDescInCandidate(
  668. mac, ip, port, bridge string,
  669. ) (*desc.SGuestDesc, *desc.SGuestNetwork) {
  670. for _, guest := range m.CandidateServers {
  671. if guest.IsLoaded() {
  672. nic := guest.GetNicDescMatch(mac, ip, port, bridge)
  673. if nic != nil {
  674. return guest.GetDesc(), nic
  675. }
  676. }
  677. }
  678. return nil, nil
  679. }
  680. func (m *SGuestManager) PrepareCreate(sid string) error {
  681. m.ServersLock.Lock()
  682. defer m.ServersLock.Unlock()
  683. if _, ok := m.GetServer(sid); ok {
  684. return httperrors.NewBadRequestError("Guest %s exists", sid)
  685. }
  686. guest := NewKVMGuestInstance(sid, m)
  687. m.SaveServer(sid, guest)
  688. return PrepareDir(guest)
  689. }
  690. func (m *SGuestManager) PrepareDeploy(sid string) error {
  691. if guest, ok := m.GetServer(sid); !ok {
  692. return httperrors.NewBadRequestError("Guest %s not exists", sid)
  693. } else {
  694. if guest.IsRunning() || guest.IsSuspend() {
  695. return httperrors.NewBadRequestError("Cannot deploy on running/suspend guest")
  696. }
  697. }
  698. return nil
  699. }
  700. func (m *SGuestManager) Monitor(sid, cmd string, qmp bool, callback func(string)) error {
  701. if guest, ok := m.GetKVMServer(sid); ok {
  702. if guest.IsRunning() {
  703. if guest.Monitor == nil {
  704. return httperrors.NewBadRequestError("Monitor disconnected??")
  705. }
  706. if qmp {
  707. if err := guest.Monitor.QemuMonitorCommand(cmd, callback); err != nil {
  708. return errors.Wrap(err, "qemu monitor command")
  709. }
  710. } else {
  711. guest.Monitor.HumanMonitorCommand(cmd, callback)
  712. }
  713. return nil
  714. } else {
  715. return httperrors.NewBadRequestError("Server stopped??")
  716. }
  717. } else {
  718. return httperrors.NewNotFoundError("Not found KVM server: %s", sid)
  719. }
  720. }
  721. func (m *SGuestManager) sdnClient() (fwdpb.ForwarderClient, error) {
  722. sockPath := options.HostOptions.SdnSocketPath
  723. if strings.HasPrefix(sockPath, "/") {
  724. sockPath = "unix://" + sockPath
  725. }
  726. cli, err := fwd.NewClient(sockPath)
  727. return cli, err
  728. }
  729. func (m *SGuestManager) OpenForward(ctx context.Context, sid string, req *hostapi.GuestOpenForwardRequest) (*hostapi.GuestOpenForwardResponse, error) {
  730. guest, ok := m.GetKVMServer(sid)
  731. if !ok {
  732. return nil, httperrors.NewNotFoundError("Not found")
  733. }
  734. if !guest.IsRunning() {
  735. return nil, httperrors.NewBadRequestError("Server stopped??")
  736. }
  737. nic := guest.GetVpcNIC()
  738. if nic == nil {
  739. return nil, httperrors.NewBadRequestError("no vpc nic")
  740. }
  741. netId := nic.NetId
  742. if netId == "" {
  743. return nil, httperrors.NewBadRequestError("no network id")
  744. }
  745. var ip string
  746. if req.Addr != "" {
  747. ip = req.Addr
  748. } else {
  749. ip := nic.Ip
  750. if ip == "" {
  751. return nil, httperrors.NewBadRequestError("no vpc ip")
  752. }
  753. }
  754. pbreq := &fwdpb.OpenRequest{
  755. NetId: netId,
  756. Proto: req.Proto,
  757. BindAddr: m.host.GetMasterIp(),
  758. RemoteAddr: ip,
  759. RemotePort: uint32(req.Port),
  760. }
  761. cli, err := m.sdnClient()
  762. if err != nil {
  763. log.Errorf("new sdn client error: %v", err)
  764. return nil, httperrors.NewBadGatewayError("lost sdn connection")
  765. }
  766. resp, err := cli.Open(ctx, pbreq)
  767. if err != nil {
  768. return nil, httperrors.NewGeneralError(err)
  769. }
  770. output := &hostapi.GuestOpenForwardResponse{
  771. Proto: resp.Proto,
  772. Addr: resp.RemoteAddr,
  773. Port: int(resp.RemotePort),
  774. ProxyAddr: resp.BindAddr,
  775. ProxyPort: int(resp.BindPort),
  776. }
  777. return output, nil
  778. }
  779. func (m *SGuestManager) CloseForward(ctx context.Context, sid string, req *hostapi.GuestCloseForwardRequest) (*hostapi.GuestCloseForwardResponse, error) {
  780. guest, ok := m.GetKVMServer(sid)
  781. if !ok {
  782. return nil, httperrors.NewNotFoundError("Not found")
  783. }
  784. nic := guest.GetVpcNIC()
  785. if nic == nil {
  786. return nil, httperrors.NewBadRequestError("no vpc nic")
  787. }
  788. netId := nic.NetId
  789. if netId == "" {
  790. return nil, httperrors.NewBadRequestError("no network id")
  791. }
  792. pbreq := &fwdpb.CloseRequest{
  793. NetId: netId,
  794. Proto: req.Proto,
  795. BindAddr: req.ProxyAddr,
  796. BindPort: uint32(req.ProxyPort),
  797. }
  798. cli, err := m.sdnClient()
  799. if err != nil {
  800. log.Errorf("new sdn client error: %v", err)
  801. return nil, httperrors.NewBadGatewayError("lost sdn connection")
  802. }
  803. resp, err := cli.Close(ctx, pbreq)
  804. if err != nil {
  805. return nil, httperrors.NewGeneralError(err)
  806. }
  807. output := &hostapi.GuestCloseForwardResponse{
  808. Proto: resp.Proto,
  809. ProxyAddr: resp.BindAddr,
  810. ProxyPort: int(resp.BindPort),
  811. }
  812. return output, nil
  813. }
  814. func (m *SGuestManager) ListForward(ctx context.Context, sid string, req *hostapi.GuestListForwardRequest) (*hostapi.GuestListForwardResponse, error) {
  815. guest, ok := m.GetKVMServer(sid)
  816. if !ok {
  817. return nil, httperrors.NewNotFoundError("Not found")
  818. }
  819. if !guest.IsRunning() {
  820. return nil, httperrors.NewBadRequestError("Server stopped??")
  821. }
  822. nic := guest.GetVpcNIC()
  823. if nic == nil {
  824. return nil, httperrors.NewBadRequestError("no vpc nic")
  825. }
  826. netId := nic.NetId
  827. if netId == "" {
  828. return nil, httperrors.NewBadRequestError("no network id")
  829. }
  830. pbreq := &fwdpb.ListByRemoteRequest{
  831. NetId: netId,
  832. Proto: req.Proto,
  833. RemoteAddr: req.Addr,
  834. RemotePort: uint32(req.Port),
  835. }
  836. cli, err := m.sdnClient()
  837. if err != nil {
  838. log.Errorf("new sdn client error: %v", err)
  839. return nil, httperrors.NewBadGatewayError("lost sdn connection")
  840. }
  841. resp, err := cli.ListByRemote(ctx, pbreq)
  842. if err != nil {
  843. return nil, httperrors.NewGeneralError(err)
  844. }
  845. var outputForwards []hostapi.GuestOpenForwardResponse
  846. for i := range resp.Forwards {
  847. outputForwards = append(outputForwards, hostapi.GuestOpenForwardResponse{
  848. Proto: resp.Forwards[i].Proto,
  849. Addr: resp.Forwards[i].RemoteAddr,
  850. Port: int(resp.Forwards[i].RemotePort),
  851. ProxyAddr: resp.Forwards[i].BindAddr,
  852. ProxyPort: int(resp.Forwards[i].BindPort),
  853. })
  854. }
  855. output := &hostapi.GuestListForwardResponse{
  856. Forwards: outputForwards,
  857. }
  858. return output, nil
  859. }
  860. func (m *SGuestManager) GuestCreate(ctx context.Context, params interface{}) (jsonutils.JSONObject, error) {
  861. deployParams, ok := params.(*SGuestDeploy)
  862. if !ok {
  863. return nil, hostutils.ParamsError
  864. }
  865. var guest GuestRuntimeInstance
  866. e := func() error {
  867. m.ServersLock.Lock()
  868. defer m.ServersLock.Unlock()
  869. if _, ok := m.GetServer(deployParams.Sid); ok {
  870. return httperrors.NewBadRequestError("Guest %s exists", deployParams.Sid)
  871. }
  872. var (
  873. descInfo *desc.SGuestDesc = nil
  874. hypervisor = ""
  875. )
  876. if deployParams.Body.Contains("desc") {
  877. descInfo = new(desc.SGuestDesc)
  878. err := deployParams.Body.Unmarshal(descInfo, "desc")
  879. if err != nil {
  880. return httperrors.NewBadRequestError("Guest desc unmarshal failed %s", err)
  881. }
  882. hypervisor = descInfo.Hypervisor
  883. }
  884. //guest = NewKVMGuestInstance(deployParams.Sid, m)
  885. factory := NewGuestRuntimeManager()
  886. guest = factory.NewRuntimeInstance(deployParams.Sid, m, hypervisor)
  887. if descInfo != nil {
  888. if err := factory.CreateFromDesc(guest, descInfo); err != nil {
  889. return errors.Wrap(err, "create from desc")
  890. }
  891. }
  892. m.SaveServer(deployParams.Sid, guest)
  893. return nil
  894. }()
  895. if e != nil {
  896. return nil, errors.Wrap(e, "prepare guest")
  897. }
  898. return m.startDeploy(ctx, deployParams, guest)
  899. }
  900. func (m *SGuestManager) startDeploy(
  901. ctx context.Context, deployParams *SGuestDeploy, guest GuestRuntimeInstance) (jsonutils.JSONObject, error) {
  902. publicKey := deployapi.GetKeys(deployParams.Body)
  903. deployArray := make([]*deployapi.DeployContent, 0)
  904. if deployParams.Body.Contains("deploys") {
  905. err := deployParams.Body.Unmarshal(&deployArray, "deploys")
  906. if err != nil {
  907. return nil, errors.Wrapf(err, "unmarshal to array of deployapi.DeployContent")
  908. }
  909. }
  910. isRandomPassword := false
  911. password, _ := deployParams.Body.GetString("password")
  912. resetPassword := jsonutils.QueryBoolean(deployParams.Body, "reset_password", false)
  913. if resetPassword && len(password) == 0 {
  914. password = seclib.RandomPassword2(14)
  915. isRandomPassword = true
  916. }
  917. enableCloudInit := jsonutils.QueryBoolean(deployParams.Body, "enable_cloud_init", false)
  918. loginAccount, _ := deployParams.Body.GetString("login_account")
  919. deployTelegraf := jsonutils.QueryBoolean(deployParams.Body, "deploy_telegraf", false)
  920. telegrafConfig, _ := deployParams.Body.GetString("telegraf_conf")
  921. if deployTelegraf && telegrafConfig == "" {
  922. return nil, errors.Errorf("missing telegraf_conf")
  923. }
  924. // refresh port_mappings
  925. if err := NewPortMappingManager(m).AllocateGuestPortMappings(ctx, deployParams.UserCred, guest); err != nil {
  926. return nil, errors.Wrap(err, "allocate port mappings")
  927. }
  928. guestInfo, err := guest.DeployFs(ctx, deployParams.UserCred,
  929. deployapi.NewDeployInfo(
  930. publicKey, deployArray,
  931. password, isRandomPassword, deployParams.IsInit, false,
  932. options.HostOptions.LinuxDefaultRootUser, options.HostOptions.WindowsDefaultAdminUser,
  933. enableCloudInit, loginAccount, deployTelegraf, telegrafConfig,
  934. guest.GetDesc().UserData,
  935. ),
  936. )
  937. if err != nil {
  938. return nil, errors.Wrap(err, "Deploy guest fs")
  939. } else {
  940. return guestInfo, nil
  941. }
  942. }
  943. // Delay process
  944. func (m *SGuestManager) GuestDeploy(ctx context.Context, params interface{}) (jsonutils.JSONObject, error) {
  945. deployParams, ok := params.(*SGuestDeploy)
  946. if !ok {
  947. return nil, hostutils.ParamsError
  948. }
  949. guest, ok := m.GetServer(deployParams.Sid)
  950. if ok {
  951. if deployParams.Body.Contains("desc") {
  952. var guestDesc = new(desc.SGuestDesc)
  953. err := deployParams.Body.Unmarshal(guestDesc, "desc")
  954. if err != nil {
  955. return nil, httperrors.NewBadRequestError("Failed unmarshal guest desc %s", err)
  956. }
  957. if err := SaveDesc(guest, guestDesc); err != nil {
  958. return nil, errors.Wrap(err, "failed save desc")
  959. }
  960. }
  961. return m.startDeploy(ctx, deployParams, guest)
  962. } else {
  963. return nil, fmt.Errorf("Guest %s not found", deployParams.Sid)
  964. }
  965. }
  966. // delay cpuset balance
  967. func (m *SGuestManager) CpusetBalance(ctx context.Context, params interface{}) (jsonutils.JSONObject, error) {
  968. m.cpusetBalance()
  969. return nil, nil
  970. }
  971. func (m *SGuestManager) Status(sid string) string {
  972. status := m.getStatus(sid)
  973. return status
  974. }
  975. func (m *SGuestManager) GetGuestStatus(ctx context.Context, params interface{}) (jsonutils.JSONObject, error) {
  976. sid := params.(string)
  977. guest, _ := m.GetServer(sid)
  978. resp := m.ProbeGuestInitStatus(sid)
  979. if guest != nil {
  980. // resp is nil ONLY IF the monitor not started
  981. resp = guest.HandleGuestStatus(ctx, resp, false)
  982. }
  983. if resp != nil {
  984. hostutils.TaskComplete(ctx, jsonutils.Marshal(resp))
  985. }
  986. return nil, nil
  987. }
  988. func (m *SGuestManager) UploadGuestStatus(ctx context.Context, sid string) (jsonutils.JSONObject, error) {
  989. reason := fmt.Sprintf("upload guest %s status by host", sid)
  990. guest, _ := m.GetServer(sid)
  991. if guest == nil {
  992. return nil, httperrors.NewNotFoundError("Guest %s not found", sid)
  993. }
  994. status := m.ProbeGuestInitStatus(sid)
  995. status = guest.HandleGuestStatus(ctx, status, true)
  996. ret, err := hostutils.UploadGuestStatus(ctx, sid, status)
  997. // do post action like marking container dirty after uploading guests status
  998. guest.PostUploadStatus(status, reason)
  999. log.Infof("upload guest %s to region response: %s, error: %v", sid, jsonutils.Marshal(ret), err)
  1000. return jsonutils.Marshal(ret), err
  1001. }
  1002. func (m *SGuestManager) UploadGuestsStatus(ctx context.Context, i interface{}) (jsonutils.JSONObject, error) {
  1003. input := i.(*compute.HostUploadGuestsStatusRequest)
  1004. // errs := []error{}
  1005. resp := &compute.HostUploadGuestsStatusInput{
  1006. Guests: make(map[string]*compute.HostUploadGuestStatusInput, 0),
  1007. }
  1008. reason := "upload guests status by host"
  1009. for _, sid := range input.GuestIds {
  1010. guest, _ := m.GetServer(sid)
  1011. status := m.ProbeGuestInitStatus(sid)
  1012. if guest != nil {
  1013. status = guest.HandleGuestStatus(ctx, status, true)
  1014. }
  1015. // if status, err := srv.GetUploadStatus(ctx, reason); err != nil {
  1016. // errs = append(errs, errors.Wrapf(err, "upload guest %s status", srv.GetId()))
  1017. //} else {
  1018. resp.Guests[sid] = status
  1019. //}
  1020. }
  1021. // if len(errs) > 0 {
  1022. // log.Errorf("Get upload guests status: %v", errors.NewAggregate(errs))
  1023. // }
  1024. ret, err := hostutils.UploadGuestsStatus(ctx, resp)
  1025. // do post action like marking container dirty after uploading guests status
  1026. for id, status := range resp.Guests {
  1027. srv, _ := m.GetServer(id)
  1028. if srv == nil {
  1029. continue
  1030. }
  1031. srv.PostUploadStatus(status, reason)
  1032. }
  1033. log.Infof("upload guests to region response: %s", jsonutils.Marshal(ret).String())
  1034. return ret, err
  1035. }
  1036. func (m *SGuestManager) getStatus(sid string) string {
  1037. if guest, ok := m.GetServer(sid); ok {
  1038. if guest.IsRunning() {
  1039. return GUEST_RUNNING
  1040. } else if guest.IsSuspend() {
  1041. return GUEST_SUSPEND
  1042. } else {
  1043. return GUSET_STOPPED
  1044. }
  1045. } else {
  1046. return GUEST_NOT_FOUND
  1047. }
  1048. }
  1049. func (m *SGuestManager) Delete(sid string) (GuestRuntimeInstance, error) {
  1050. if guest, ok := m.GetServer(sid); ok {
  1051. m.CleanServer(sid)
  1052. // 这里应该不需要append到deleted servers
  1053. // 据观察 deleted servers 目的是为了给ofp_delegate使用,ofp已经不用了
  1054. return guest, nil
  1055. } else if guest, ok := m.GetUnknownServer(sid); ok {
  1056. m.UnknownServers.Delete(sid)
  1057. return guest, nil
  1058. } else {
  1059. return nil, httperrors.NewNotFoundError("Not found")
  1060. }
  1061. }
  1062. func (m *SGuestManager) GuestStart(ctx context.Context, userCred mcclient.TokenCredential, sid string, body jsonutils.JSONObject) (jsonutils.JSONObject, error) {
  1063. if guest, ok := m.GetServer(sid); ok {
  1064. guestDesc := new(desc.SGuestDesc)
  1065. if err := body.Unmarshal(guestDesc, "desc"); err == nil {
  1066. if err = SaveDesc(guest, guestDesc); err != nil {
  1067. return nil, errors.Wrap(err, "save desc")
  1068. }
  1069. }
  1070. return guest.HandleGuestStart(ctx, userCred, body)
  1071. } else {
  1072. return nil, httperrors.NewNotFoundError("Not found server %s", sid)
  1073. }
  1074. }
  1075. func (m *SGuestManager) GuestStop(ctx context.Context, sid string, timeout int64) error {
  1076. if server, ok := m.GetServer(sid); ok {
  1077. if err := server.HandleStop(ctx, timeout); err != nil {
  1078. return errors.Wrap(err, "Do stop")
  1079. }
  1080. } else {
  1081. return httperrors.NewNotFoundError("Guest %s not found", sid)
  1082. }
  1083. return nil
  1084. }
  1085. func (m *SGuestManager) GuestStartRescue(ctx context.Context, userCred mcclient.TokenCredential, sid string, body jsonutils.JSONObject) (jsonutils.JSONObject, error) {
  1086. if guest, ok := m.GetKVMServer(sid); ok {
  1087. // initrd and kernel should be prepared by host-deployer
  1088. if !fileutils2.Exists(guest.getRescueInitrdPath()) {
  1089. return nil, httperrors.NewInternalServerError("guest initrd not ready")
  1090. }
  1091. if !fileutils2.Exists(guest.getRescueKernelPath()) {
  1092. return nil, httperrors.NewInternalServerError("guest kernel not ready")
  1093. }
  1094. return nil, nil
  1095. } else {
  1096. return nil, httperrors.NewNotFoundError("Guest %s not found", sid)
  1097. }
  1098. }
  1099. func (m *SGuestManager) GuestSync(ctx context.Context, params interface{}) (jsonutils.JSONObject, error) {
  1100. syncParams, ok := params.(*SBaseParams)
  1101. if !ok {
  1102. return nil, hostutils.ParamsError
  1103. }
  1104. guest, _ := m.GetServer(syncParams.Sid)
  1105. if syncParams.Body.Contains("desc") {
  1106. guestDesc := new(desc.SGuestDesc)
  1107. if err := syncParams.Body.Unmarshal(guestDesc, "desc"); err != nil {
  1108. return nil, errors.Wrap(err, "unmarshal guest desc")
  1109. }
  1110. fwOnly := jsonutils.QueryBoolean(syncParams.Body, "fw_only", false)
  1111. setUefiBootOrder := jsonutils.QueryBoolean(syncParams.Body, "set_uefi_boot_order", false)
  1112. return guest.SyncConfig(ctx, guestDesc, fwOnly, setUefiBootOrder)
  1113. }
  1114. return nil, nil
  1115. }
  1116. func (m *SGuestManager) GuestSuspend(ctx context.Context, params interface{}) (jsonutils.JSONObject, error) {
  1117. sid, ok := params.(string)
  1118. if !ok {
  1119. return nil, hostutils.ParamsError
  1120. }
  1121. guest, ok := m.GetKVMServer(sid)
  1122. if !ok {
  1123. return nil, errors.Errorf("Not found KVM server: %s", sid)
  1124. }
  1125. guest.ExecSuspendTask(ctx)
  1126. return nil, nil
  1127. }
  1128. func (m *SGuestManager) GuestIoThrottle(ctx context.Context, params interface{}) (jsonutils.JSONObject, error) {
  1129. guestIoThrottle, ok := params.(*SGuestIoThrottle)
  1130. if !ok {
  1131. return nil, hostutils.ParamsError
  1132. }
  1133. guest, _ := m.GetKVMServer(guestIoThrottle.Sid)
  1134. for i := range guest.GetDesc().Disks {
  1135. diskId := guest.GetDesc().Disks[i].DiskId
  1136. if bps, ok := guestIoThrottle.Input.Bps[diskId]; ok {
  1137. guest.GetDesc().Disks[i].Bps = bps
  1138. }
  1139. if iops, ok := guestIoThrottle.Input.IOPS[diskId]; ok {
  1140. guest.GetDesc().Disks[i].Iops = iops
  1141. }
  1142. }
  1143. if err := SaveLiveDesc(guest, guest.GetDesc()); err != nil {
  1144. return nil, errors.Wrap(err, "guest save desc")
  1145. }
  1146. if guest.IsRunning() {
  1147. guest.BlockIoThrottle(ctx)
  1148. return nil, nil
  1149. }
  1150. return nil, httperrors.NewInvalidStatusError("Guest not running")
  1151. }
  1152. func (m *SGuestManager) SrcPrepareMigrate(ctx context.Context, params interface{}) (jsonutils.JSONObject, error) {
  1153. migParams, ok := params.(*SSrcPrepareMigrate)
  1154. if !ok {
  1155. return nil, hostutils.ParamsError
  1156. }
  1157. guest, _ := m.GetKVMServer(migParams.Sid)
  1158. disksBack, diskSnapsChain, sysDiskHasTemplate, err := guest.PrepareDisksMigrate(migParams.LiveMigrate)
  1159. if err != nil {
  1160. return nil, errors.Wrap(err, "PrepareDisksMigrate")
  1161. }
  1162. ret := jsonutils.NewDict()
  1163. if disksBack.Length() > 0 {
  1164. ret.Set("disks_back", disksBack)
  1165. }
  1166. if diskSnapsChain.Length() > 0 {
  1167. ret.Set("disk_snaps_chain", diskSnapsChain)
  1168. }
  1169. if sysDiskHasTemplate {
  1170. ret.Set("sys_disk_has_template", jsonutils.JSONTrue)
  1171. }
  1172. if migParams.LiveMigrate && migParams.LiveMigrateUseTLS {
  1173. certs, err := guest.PrepareMigrateCerts()
  1174. if err != nil {
  1175. return nil, errors.Wrap(err, "PrepareMigrateCerts")
  1176. }
  1177. ret.Set("migrate_certs", jsonutils.Marshal(certs))
  1178. }
  1179. if migParams.LiveMigrate {
  1180. if guest.GetDesc().Machine == "" {
  1181. guest.GetDesc().Machine = guest.getMachine()
  1182. }
  1183. if err = guest.syncVirtioDiskNumQueues(); err != nil {
  1184. return nil, errors.Wrap(err, "syncVirtioDiskNumQueues")
  1185. }
  1186. ret.Set("src_desc", jsonutils.Marshal(guest.GetDesc()))
  1187. }
  1188. return ret, nil
  1189. }
  1190. func (m *SGuestManager) DestPrepareMigrate(ctx context.Context, params interface{}) (jsonutils.JSONObject, error) {
  1191. migParams, ok := params.(*SDestPrepareMigrate)
  1192. if !ok {
  1193. return nil, hostutils.ParamsError
  1194. }
  1195. guest, _ := m.GetKVMServer(migParams.Sid)
  1196. if err := NewGuestRuntimeManager().CreateFromDesc(guest, migParams.Desc); err != nil {
  1197. return nil, err
  1198. }
  1199. disks := migParams.Desc.Disks
  1200. if len(migParams.TargetStorageIds) > 0 {
  1201. var encInfo *apis.SEncryptInfo
  1202. if guest.isEncrypted() {
  1203. info, err := guest.getEncryptKey(ctx, migParams.UserCred)
  1204. if err != nil {
  1205. return nil, errors.Wrap(err, "getEncryptKey")
  1206. }
  1207. encInfo = &info
  1208. }
  1209. for i := 0; i < len(migParams.TargetStorageIds); i++ {
  1210. iStorage := storageman.GetManager().GetStorage(migParams.TargetStorageIds[i])
  1211. if iStorage == nil {
  1212. return nil, fmt.Errorf("Target storage %s not found", migParams.TargetStorageIds[i])
  1213. }
  1214. err := iStorage.DestinationPrepareMigrate(
  1215. ctx, migParams.LiveMigrate, migParams.DisksUri, migParams.SnapshotsUri,
  1216. migParams.DisksBackingFile, migParams.DiskSnapsChain, migParams.OutChainSnaps,
  1217. migParams.RebaseDisks, disks[i], migParams.Sid, i+1, len(disks), encInfo, migParams.SysDiskHasTemplate,
  1218. )
  1219. if err != nil {
  1220. return nil, fmt.Errorf("dest prepare migrate failed %s", err)
  1221. }
  1222. }
  1223. if err := SaveDesc(guest, migParams.Desc); err != nil {
  1224. log.Errorln(err)
  1225. return nil, err
  1226. }
  1227. }
  1228. for _, disk := range guest.Desc.Disks {
  1229. if disk.Path != "" {
  1230. d, err := storageman.GetManager().GetDiskByPath(disk.Path)
  1231. if err != nil {
  1232. return nil, errors.Wrapf(err, "GetDiskByPath(%s)", disk.Path)
  1233. }
  1234. if disk.StorageType == compute.STORAGE_SLVM {
  1235. if err := lvmutils.LVActive(disk.Path, d.GetStorage().Lvmlockd(), false); err != nil {
  1236. return nil, errors.Wrap(err, "lvm active with shared")
  1237. }
  1238. _, err := storageman.GetManager().GetDiskByPath(disk.Path)
  1239. if err != nil {
  1240. return nil, errors.Wrapf(err, "slvm GetDiskByPath(%s)", disk.Path)
  1241. }
  1242. }
  1243. }
  1244. }
  1245. body := jsonutils.NewDict()
  1246. if len(migParams.SrcMemorySnapshots) > 0 {
  1247. preparedMs, err := m.destinationPrepareMigrateMemorySnapshots(ctx, migParams.Sid, migParams.MemorySnapshotsUri, migParams.SrcMemorySnapshots)
  1248. if err != nil {
  1249. return nil, errors.Wrap(err, "destination prepare migrate memory snapshots")
  1250. }
  1251. body.Add(jsonutils.Marshal(preparedMs), "dest_prepared_memory_snapshots")
  1252. }
  1253. if migParams.LiveMigrate {
  1254. startParams := jsonutils.NewDict()
  1255. startParams.Set("qemu_version", jsonutils.NewString(migParams.QemuVersion))
  1256. startParams.Set("need_migrate", jsonutils.JSONTrue)
  1257. startParams.Set("live_migrate_use_tls", jsonutils.NewBool(migParams.EnableTLS))
  1258. startParams.Set("src_desc", jsonutils.Marshal(migParams.SrcDesc))
  1259. if len(migParams.MigrateCerts) > 0 {
  1260. if err := guest.WriteMigrateCerts(migParams.MigrateCerts); err != nil {
  1261. return nil, errors.Wrap(err, "write migrate certs")
  1262. }
  1263. }
  1264. var err error
  1265. startParams, err = guest.prepareEncryptKeyForStart(ctx, migParams.UserCred, startParams)
  1266. if err != nil {
  1267. return nil, errors.Wrap(err, "prepareEncryptKeyForStart")
  1268. }
  1269. hostutils.DelayTaskWithoutReqctx(ctx, guest.asyncScriptStart, startParams)
  1270. } else {
  1271. hostutils.UpdateServerProgress(context.Background(), migParams.Sid, 100.0, 0)
  1272. }
  1273. return body, nil
  1274. }
  1275. func (m *SGuestManager) destinationPrepareMigrateMemorySnapshots(ctx context.Context, serverId string, uri string, ids []string) (map[string]string, error) {
  1276. ret := make(map[string]string, 0)
  1277. for _, id := range ids {
  1278. url := fmt.Sprintf("%s/%s/%s", uri, serverId, id)
  1279. msPath := GetMemorySnapshotPath(serverId, id)
  1280. dir := filepath.Dir(msPath)
  1281. if err := procutils.NewRemoteCommandAsFarAsPossible("mkdir", "-p", dir).Run(); err != nil {
  1282. return nil, errors.Wrapf(err, "mkdir -p %q", dir)
  1283. }
  1284. remotefile := remotefile.NewRemoteFile(ctx, url, msPath, false, "", -1, nil, "", "")
  1285. if err := remotefile.Fetch(nil); err != nil {
  1286. return nil, errors.Wrapf(err, "fetch memory snapshot file %s", url)
  1287. } else {
  1288. ret[id] = msPath
  1289. }
  1290. }
  1291. return ret, nil
  1292. }
  1293. func (m *SGuestManager) LiveMigrate(ctx context.Context, params interface{}) (jsonutils.JSONObject, error) {
  1294. migParams, ok := params.(*SLiveMigrate)
  1295. if !ok {
  1296. return nil, hostutils.ParamsError
  1297. }
  1298. guest, _ := m.GetKVMServer(migParams.Sid)
  1299. task := NewGuestLiveMigrateTask(ctx, guest, migParams)
  1300. task.Start()
  1301. return nil, nil
  1302. }
  1303. func (m *SGuestManager) CanMigrate(sid string) bool {
  1304. m.ServersLock.Lock()
  1305. defer m.ServersLock.Unlock()
  1306. if _, ok := m.GetServer(sid); ok {
  1307. log.Infof("Guest %s exists", sid)
  1308. return false
  1309. }
  1310. guest := NewKVMGuestInstance(sid, m)
  1311. m.SaveServer(sid, guest)
  1312. return true
  1313. }
  1314. func (m *SGuestManager) checkAndSetPort(port int) bool {
  1315. _, loaded := m.portsInUse.LoadOrStore(port, struct{}{})
  1316. return !loaded
  1317. }
  1318. func (m *SGuestManager) unsetPort(port int) {
  1319. m.portsInUse.Delete(port)
  1320. }
  1321. func (m *SGuestManager) GetFreePortByBase(basePort int) int {
  1322. var port = 1
  1323. for {
  1324. if netutils2.IsTcpPortUsed("0.0.0.0", basePort+port) {
  1325. port += 1
  1326. } else {
  1327. if !m.checkAndSetPort(basePort + port) {
  1328. continue
  1329. }
  1330. break
  1331. }
  1332. }
  1333. return port + basePort
  1334. }
  1335. func (m *SGuestManager) GetLiveMigrateFreePort() int {
  1336. port := m.GetFreePortByBase(LIVE_MIGRATE_PORT_BASE + LAST_USED_MIGRATE_PORT)
  1337. LAST_USED_MIGRATE_PORT = port - LIVE_MIGRATE_PORT_BASE
  1338. if LAST_USED_MIGRATE_PORT > 5000 {
  1339. LAST_USED_MIGRATE_PORT = 0
  1340. }
  1341. return port
  1342. }
  1343. func (m *SGuestManager) GetNBDServerFreePort() int {
  1344. port := m.GetFreePortByBase(BUILT_IN_NBD_SERVER_PORT_BASE + LAST_USED_NBD_SERVER_PORT)
  1345. LAST_USED_NBD_SERVER_PORT = port - BUILT_IN_NBD_SERVER_PORT_BASE
  1346. if LAST_USED_NBD_SERVER_PORT > 5000 {
  1347. LAST_USED_NBD_SERVER_PORT = 0
  1348. }
  1349. return port
  1350. }
  1351. func (m *SGuestManager) GetFreeVncPort() int {
  1352. vncPorts := make(map[int]struct{}, 0)
  1353. m.Servers.Range(func(k, v interface{}) bool {
  1354. inst := v.(GuestRuntimeInstance)
  1355. guest, ok := inst.(*SKVMGuestInstance)
  1356. if !ok {
  1357. return true
  1358. }
  1359. inUsePort := guest.GetVncPort()
  1360. if inUsePort > 0 {
  1361. vncPorts[inUsePort] = struct{}{}
  1362. }
  1363. return true
  1364. })
  1365. var port = LAST_USED_PORT + 1
  1366. for {
  1367. if _, ok := vncPorts[port]; ok ||
  1368. netutils2.IsTcpPortUsed("0.0.0.0", VNC_PORT_BASE+port) ||
  1369. netutils2.IsTcpPortUsed("127.0.0.1", MONITOR_PORT_BASE+port) ||
  1370. netutils2.IsTcpPortUsed("127.0.0.1", QMP_MONITOR_PORT_BASE+port) {
  1371. port += 1
  1372. } else {
  1373. if !m.checkAndSetPort(port) {
  1374. continue
  1375. }
  1376. break
  1377. }
  1378. }
  1379. LAST_USED_PORT = port
  1380. if LAST_USED_PORT > 5000 {
  1381. LAST_USED_PORT = 0
  1382. }
  1383. return port
  1384. }
  1385. func (m *SGuestManager) ReloadDiskSnapshot(
  1386. ctx context.Context, params interface{},
  1387. ) (jsonutils.JSONObject, error) {
  1388. reloadParams, ok := params.(*SReloadDisk)
  1389. if !ok {
  1390. return nil, hostutils.ParamsError
  1391. }
  1392. guest, _ := m.GetKVMServer(reloadParams.Sid)
  1393. return guest.ExecReloadDiskTask(ctx, reloadParams.Disk)
  1394. }
  1395. func (m *SGuestManager) DoSnapshot(ctx context.Context, params interface{}) (jsonutils.JSONObject, error) {
  1396. snapshotParams, ok := params.(*SDiskSnapshot)
  1397. if !ok {
  1398. return nil, hostutils.ParamsError
  1399. }
  1400. guest, _ := m.GetServer(snapshotParams.Sid)
  1401. return guest.DoSnapshot(ctx, snapshotParams)
  1402. }
  1403. func (m *SGuestManager) DeleteSnapshot(ctx context.Context, params interface{}) (jsonutils.JSONObject, error) {
  1404. delParams, ok := params.(*SDeleteDiskSnapshot)
  1405. if !ok {
  1406. return nil, hostutils.ParamsError
  1407. }
  1408. guest, _ := m.GetServer(delParams.Sid)
  1409. return guest.DeleteSnapshot(ctx, delParams)
  1410. }
  1411. func (m *SGuestManager) DoMemorySnapshot(ctx context.Context, params interface{}) (jsonutils.JSONObject, error) {
  1412. input, ok := params.(*SMemorySnapshot)
  1413. if !ok {
  1414. return nil, hostutils.ParamsError
  1415. }
  1416. guest, _ := m.GetKVMServer(input.Sid)
  1417. return guest.ExecMemorySnapshotTask(ctx, input.GuestMemorySnapshotRequest)
  1418. }
  1419. func (m *SGuestManager) DoResetMemorySnapshot(ctx context.Context, params interface{}) (jsonutils.JSONObject, error) {
  1420. input, ok := params.(*SMemorySnapshotReset)
  1421. if !ok {
  1422. return nil, hostutils.ParamsError
  1423. }
  1424. guest, _ := m.GetKVMServer(input.Sid)
  1425. return guest.ExecMemorySnapshotResetTask(ctx, input.GuestMemorySnapshotResetRequest)
  1426. }
  1427. func (m *SGuestManager) DoDeleteMemorySnapshot(ctx context.Context, params interface{}) (jsonutils.JSONObject, error) {
  1428. input, ok := params.(*SMemorySnapshotDelete)
  1429. if !ok {
  1430. return nil, hostutils.ParamsError
  1431. }
  1432. if err := procutils.NewRemoteCommandAsFarAsPossible("rm", input.Path).Run(); err != nil {
  1433. if !strings.Contains(strings.ToLower(err.Error()), "No such file or directory") {
  1434. return nil, err
  1435. }
  1436. }
  1437. log.Infof("Memory snapshot file %q removed", input.Path)
  1438. return nil, nil
  1439. }
  1440. func (m *SGuestManager) Resume(ctx context.Context, sid string, isLiveMigrate bool, cleanTLS bool) (jsonutils.JSONObject, error) {
  1441. guest, _ := m.GetKVMServer(sid)
  1442. if guest.IsStopping() || guest.IsStopped() {
  1443. return nil, httperrors.NewInvalidStatusError("resume stopped server???")
  1444. }
  1445. var onLiveMigrateCleanup = func(res string) {
  1446. guest.DoResumeTask(ctx, !isLiveMigrate, cleanTLS)
  1447. }
  1448. var onMonitorConnected = func() {
  1449. if isLiveMigrate {
  1450. guest.StartPresendArp()
  1451. guest.Monitor.StopNbdServer(onLiveMigrateCleanup)
  1452. } else {
  1453. onLiveMigrateCleanup("")
  1454. }
  1455. }
  1456. if guest.Monitor == nil {
  1457. guest.StartMonitor(ctx, nil, false)
  1458. return nil, nil
  1459. } else {
  1460. onMonitorConnected()
  1461. }
  1462. return nil, nil
  1463. }
  1464. func (m *SGuestManager) OnlineResizeDisk(ctx context.Context, sid string, disk storageman.IDisk, sizeMb int64) (jsonutils.JSONObject, error) {
  1465. guest, ok := m.GetServer(sid)
  1466. if !ok {
  1467. return nil, httperrors.NewNotFoundError("guest %s not found", sid)
  1468. }
  1469. if guest.IsRunning() {
  1470. guest.OnlineResizeDisk(ctx, disk, sizeMb)
  1471. return nil, nil
  1472. } else {
  1473. return nil, httperrors.NewInvalidStatusError("guest is not runnign")
  1474. }
  1475. }
  1476. // func (m *SGuestManager) StartNbdServer(ctx context.Context, params interface{}) (jsonutils.JSONObject, error) {
  1477. // sid, ok := params.(string)
  1478. // if !ok {
  1479. // return nil, hostutils.ParamsError
  1480. // }
  1481. // guest := guestManager.Servers[sid]
  1482. // port := m.GetFreePortByBase(BUILT_IN_NBD_SERVER_PORT_BASE)
  1483. // }
  1484. func (m *SGuestManager) StartBlockReplication(ctx context.Context, params interface{}) (jsonutils.JSONObject, error) {
  1485. mirrorParams, ok := params.(*SDriverMirror)
  1486. if !ok {
  1487. return nil, hostutils.ParamsError
  1488. }
  1489. nbdOpts := strings.Split(mirrorParams.NbdServerUri, ":")
  1490. if len(nbdOpts) != 3 {
  1491. return nil, fmt.Errorf("Nbd url is not vaild %s", mirrorParams.NbdServerUri)
  1492. }
  1493. guest, _ := m.GetKVMServer(mirrorParams.Sid)
  1494. // TODO: check desc
  1495. if err := SaveDesc(guest, mirrorParams.Desc); err != nil {
  1496. return nil, err
  1497. }
  1498. onSucc := func() {
  1499. if err := guest.updateChildIndex(); err != nil {
  1500. hostutils.TaskFailed(ctx, err.Error())
  1501. return
  1502. }
  1503. hostutils.TaskComplete(ctx, nil)
  1504. }
  1505. task := NewGuestBlockReplicationTask(ctx, guest, nbdOpts[1], nbdOpts[2], "full", onSucc, nil)
  1506. task.Start()
  1507. return nil, nil
  1508. }
  1509. func (m *SGuestManager) CancelBlockJobs(ctx context.Context, params interface{}) (jsonutils.JSONObject, error) {
  1510. sid, ok := params.(string)
  1511. if !ok {
  1512. return nil, hostutils.ParamsError
  1513. }
  1514. status := m.getStatus(sid)
  1515. if status == GUSET_STOPPED {
  1516. hostutils.TaskComplete(ctx, nil)
  1517. return nil, nil
  1518. }
  1519. defer func() {
  1520. if r := recover(); r != nil {
  1521. log.Errorf("STACK: %v \n %s", r, debug.Stack())
  1522. hostutils.TaskFailed(ctx, fmt.Sprintf("recover: %v", r))
  1523. }
  1524. }()
  1525. guest, _ := m.GetKVMServer(sid)
  1526. NewCancelBlockJobsTask(ctx, guest).Start()
  1527. return nil, nil
  1528. }
  1529. func (m *SGuestManager) CancelBlockReplication(ctx context.Context, params interface{}) (jsonutils.JSONObject, error) {
  1530. sid, ok := params.(string)
  1531. if !ok {
  1532. return nil, hostutils.ParamsError
  1533. }
  1534. status := m.getStatus(sid)
  1535. if status == GUSET_STOPPED {
  1536. hostutils.TaskComplete(ctx, nil)
  1537. return nil, nil
  1538. }
  1539. defer func() {
  1540. if r := recover(); r != nil {
  1541. log.Errorf("STACK: %v \n %s", r, debug.Stack())
  1542. hostutils.TaskFailed(ctx, fmt.Sprintf("recover: %v", r))
  1543. }
  1544. }()
  1545. guest, _ := m.GetKVMServer(sid)
  1546. NewCancelBlockReplicationTask(ctx, guest).Start()
  1547. return nil, nil
  1548. }
  1549. func (m *SGuestManager) HotplugCpuMem(ctx context.Context, params interface{}) (jsonutils.JSONObject, error) {
  1550. hotplugParams, ok := params.(*SGuestHotplugCpuMem)
  1551. if !ok {
  1552. return nil, hostutils.ParamsError
  1553. }
  1554. guest, _ := m.GetKVMServer(hotplugParams.Sid)
  1555. NewGuestHotplugCpuMemTask(ctx, guest, hotplugParams).Start()
  1556. return nil, nil
  1557. }
  1558. func (m *SGuestManager) ExitGuestCleanup() {
  1559. if m.cpufreqSimulateManager != nil {
  1560. m.cpufreqSimulateManager.Stop()
  1561. }
  1562. m.Servers.Range(func(k, v interface{}) bool {
  1563. guest := v.(GuestRuntimeInstance)
  1564. guest.ExitCleanup(false)
  1565. return true
  1566. })
  1567. if !options.HostOptions.DisableSetCgroup {
  1568. cgrouputils.CgroupCleanAll(hostconsts.HOST_CGROUP)
  1569. }
  1570. }
  1571. type SStorageCloneDisk struct {
  1572. ServerId string
  1573. SourceStorage storageman.IStorage
  1574. SourceDisk storageman.IDisk
  1575. TargetStorage storageman.IStorage
  1576. TargetDiskId string
  1577. DiskFormat string
  1578. TargetDiskDesc *compute.GuestdiskJsonDesc
  1579. // clone progress
  1580. CompletedDiskCount int
  1581. CloneDiskCount int
  1582. }
  1583. func (m *SGuestManager) StorageCloneDisk(ctx context.Context, params interface{}) (jsonutils.JSONObject, error) {
  1584. input := params.(*SStorageCloneDisk)
  1585. guest, _ := m.GetKVMServer(input.ServerId)
  1586. if guest == nil {
  1587. return nil, httperrors.NewNotFoundError("Not found guest by id %s", input.ServerId)
  1588. }
  1589. guestRunning := guest.IsRunning() || guest.IsSuspend()
  1590. NewGuestStorageCloneDiskTask(ctx, guest, input).Start(guestRunning)
  1591. return nil, nil
  1592. }
  1593. func (m *SGuestManager) LiveChangeDisk(ctx context.Context, params interface{}) (jsonutils.JSONObject, error) {
  1594. input := params.(*SStorageCloneDisk)
  1595. guest, _ := m.GetKVMServer(input.ServerId)
  1596. if guest == nil {
  1597. return nil, httperrors.NewNotFoundError("Not found guest by id %s", input.ServerId)
  1598. }
  1599. if !(guest.IsRunning() || guest.IsSuspend()) {
  1600. return nil, httperrors.NewBadRequestError("Guest %s is not in state running", input.ServerId)
  1601. }
  1602. task, err := NewGuestLiveChangeDiskTask(ctx, guest, input)
  1603. if err != nil {
  1604. return nil, httperrors.NewBadRequestError("Start live change disk task failed: %s", err)
  1605. }
  1606. task.Start()
  1607. return nil, nil
  1608. }
  1609. func (m *SGuestManager) GetHost() hostutils.IHost {
  1610. return m.host
  1611. }
  1612. func (m *SGuestManager) RequestVerifyDirtyServer(s GuestRuntimeInstance) {
  1613. hostId := s.GetDesc().HostId
  1614. var body = jsonutils.NewDict()
  1615. body.Set("guest_id", jsonutils.NewString(s.GetInitialId()))
  1616. body.Set("host_id", jsonutils.NewString(hostId))
  1617. ret, err := modules.Servers.PerformClassAction(
  1618. hostutils.GetComputeSession(context.Background()), "dirty-server-verify", body)
  1619. if err != nil {
  1620. log.Errorf("Dirty server request start error: %s", err)
  1621. } else if jsonutils.QueryBoolean(ret, "guest_unknown_need_clean", false) {
  1622. m.Delete(s.GetInitialId())
  1623. if err := s.CleanDirtyGuest(context.Background()); err != nil {
  1624. log.Errorf("failed clean dirty server %s: %s", s.GetInitialId(), err)
  1625. }
  1626. }
  1627. }
  1628. func (m *SGuestManager) ResetGuestNicTrafficLimit(guestId string, input []compute.ServerNicTrafficLimit) error {
  1629. guest, ok := m.GetServer(guestId)
  1630. if !ok {
  1631. return httperrors.NewNotFoundError("guest %s not found", guestId)
  1632. }
  1633. m.TrafficLock.Lock()
  1634. defer m.TrafficLock.Unlock()
  1635. for i := range input {
  1636. if err := m.resetGuestNicTrafficLimit(guest, input[i]); err != nil {
  1637. return errors.Wrap(err, "reset guest nic traffic limit")
  1638. }
  1639. }
  1640. if err := SaveLiveDesc(guest, guest.GetDesc()); err != nil {
  1641. return errors.Wrap(err, "guest save desc")
  1642. }
  1643. return nil
  1644. }
  1645. func (m *SGuestManager) resetGuestNicTrafficLimit(guest GuestRuntimeInstance, input compute.ServerNicTrafficLimit) error {
  1646. var nic *desc.SGuestNetwork
  1647. desc := guest.GetDesc()
  1648. for i := range desc.Nics {
  1649. if desc.Nics[i].Mac == input.Mac {
  1650. nic = desc.Nics[i]
  1651. break
  1652. }
  1653. }
  1654. if nic == nil {
  1655. return httperrors.NewNotFoundError("guest nic %s not found", input.Mac)
  1656. }
  1657. recordPath := guest.NicTrafficRecordPath()
  1658. if fileutils2.Exists(recordPath) {
  1659. record, err := m.GetGuestTrafficRecord(guest.GetInitialId())
  1660. if err != nil {
  1661. return errors.Wrap(err, "failed load guest traffic record")
  1662. }
  1663. nicRecord, ok := record[nic.Mac]
  1664. if !ok {
  1665. nicRecord = record[strconv.Itoa(int(nic.Index))]
  1666. }
  1667. if nicRecord != nil {
  1668. if nicRecord.TxTraffic >= nic.TxTrafficLimit || nicRecord.RxTraffic >= nic.RxTrafficLimit {
  1669. err = guest.SetNicUp(nic)
  1670. if err != nil {
  1671. return errors.Wrap(err, "set nic up")
  1672. }
  1673. }
  1674. }
  1675. if _, ok := record[nic.Mac]; ok {
  1676. delete(record, nic.Mac)
  1677. }
  1678. if _, ok := record[strconv.Itoa(int(nic.Index))]; ok {
  1679. delete(record, strconv.Itoa(int(nic.Index)))
  1680. }
  1681. if err = m.SaveGuestTrafficRecord(guest.GetInitialId(), record); err != nil {
  1682. return errors.Wrap(err, "failed save guest traffic record")
  1683. }
  1684. }
  1685. if input.RxTrafficLimit != nil {
  1686. nic.RxTrafficLimit = *input.RxTrafficLimit
  1687. }
  1688. if input.TxTrafficLimit != nil {
  1689. nic.TxTrafficLimit = *input.TxTrafficLimit
  1690. }
  1691. if input.BillingType != "" {
  1692. nic.BillingType = input.BillingType
  1693. }
  1694. if input.ChargeType != "" {
  1695. nic.ChargeType = input.ChargeType
  1696. }
  1697. return nil
  1698. }
  1699. // set the limit of nic traffic, if the traffic is less than the limit, set the nic up
  1700. func (m *SGuestManager) setNicTrafficLimit(guest GuestRuntimeInstance, input compute.ServerNicTrafficLimit) error {
  1701. var nic *desc.SGuestNetwork
  1702. desc := guest.GetDesc()
  1703. for i := range desc.Nics {
  1704. if desc.Nics[i].Mac == input.Mac {
  1705. nic = desc.Nics[i]
  1706. break
  1707. }
  1708. }
  1709. if nic == nil {
  1710. return httperrors.NewNotFoundError("guest nic %s not found", input.Mac)
  1711. }
  1712. if input.RxTrafficLimit != nil {
  1713. nic.RxTrafficLimit = *input.RxTrafficLimit
  1714. }
  1715. if input.TxTrafficLimit != nil {
  1716. nic.TxTrafficLimit = *input.TxTrafficLimit
  1717. }
  1718. if input.BillingType != "" {
  1719. nic.BillingType = input.BillingType
  1720. }
  1721. if input.ChargeType != "" {
  1722. nic.ChargeType = input.ChargeType
  1723. }
  1724. recordPath := guest.NicTrafficRecordPath()
  1725. if fileutils2.Exists(recordPath) {
  1726. record, err := m.GetGuestTrafficRecord(guest.GetInitialId())
  1727. if err != nil {
  1728. return errors.Wrap(err, "failed load guest traffic record")
  1729. }
  1730. nicRecord, ok := record[nic.Mac]
  1731. if !ok {
  1732. nicRecord = record[strconv.Itoa(int(nic.Index))]
  1733. }
  1734. if record != nil {
  1735. if nicRecord.TxTraffic < nic.TxTrafficLimit && nicRecord.RxTraffic < nic.RxTrafficLimit {
  1736. err = guest.SetNicUp(nic)
  1737. if err != nil {
  1738. return errors.Wrap(err, "set nic up")
  1739. }
  1740. }
  1741. }
  1742. return m.SaveGuestTrafficRecord(guest.GetInitialId(), record)
  1743. }
  1744. return nil
  1745. }
  1746. func (m *SGuestManager) SetGuestNicTrafficLimit(guestId string, input []compute.ServerNicTrafficLimit) error {
  1747. guest, ok := m.GetServer(guestId)
  1748. if !ok {
  1749. return httperrors.NewNotFoundError("guest %s not found", guestId)
  1750. }
  1751. m.TrafficLock.Lock()
  1752. defer m.TrafficLock.Unlock()
  1753. for i := range input {
  1754. if err := m.setNicTrafficLimit(guest, input[i]); err != nil {
  1755. return errors.Wrap(err, "set nic traffic limit")
  1756. }
  1757. }
  1758. if err := SaveLiveDesc(guest, guest.GetDesc()); err != nil {
  1759. return errors.Wrap(err, "guest save desc")
  1760. }
  1761. return nil
  1762. }
  1763. func (m *SGuestManager) SaveGuestTrafficRecord(sid string, record map[string]*compute.SNicTrafficRecord) error {
  1764. guest, _ := m.GetServer(sid)
  1765. recordPath := guest.NicTrafficRecordPath()
  1766. v, _ := json.Marshal(record)
  1767. return fileutils2.FilePutContents(recordPath, string(v), false)
  1768. }
  1769. func (m *SGuestManager) GetGuestTrafficRecord(sid string) (map[string]*compute.SNicTrafficRecord, error) {
  1770. guest, _ := m.GetServer(sid)
  1771. recordPath := guest.NicTrafficRecordPath()
  1772. if !fileutils2.Exists(recordPath) {
  1773. return nil, nil
  1774. }
  1775. recordStr, err := os.ReadFile(recordPath)
  1776. if err != nil {
  1777. return nil, errors.Wrapf(err, "read traffic record %s", recordPath)
  1778. }
  1779. record := make(map[string]*compute.SNicTrafficRecord)
  1780. err = json.Unmarshal(recordStr, &record)
  1781. if err != nil {
  1782. return nil, errors.Wrapf(err, "failed unmarshal traffic record %s", recordPath)
  1783. }
  1784. return record, nil
  1785. }
  1786. func (m *SGuestManager) ProbeGuestInitStatus(sid string) *compute.HostUploadGuestStatusInput {
  1787. guest, _ := m.GetServer(sid)
  1788. status := m.getStatus(sid)
  1789. resp := &compute.HostUploadGuestStatusInput{
  1790. PerformStatusInput: apis.PerformStatusInput{
  1791. Status: status,
  1792. BlockJobsCount: -1,
  1793. HostId: hostinfo.Instance().HostId,
  1794. },
  1795. }
  1796. if guest == nil {
  1797. return resp
  1798. }
  1799. resp.PowerStates = GetPowerStates(guest)
  1800. return resp
  1801. }
  1802. func (m *SGuestManager) RequestGuestScreenDump(sid string) (jsonutils.JSONObject, error) {
  1803. guest, _ := m.GetServer(sid)
  1804. if guest == nil {
  1805. return nil, httperrors.NewNotFoundError("guest %s not found", sid)
  1806. }
  1807. kvmGuest, ok := guest.(*SKVMGuestInstance)
  1808. if !ok {
  1809. return nil, httperrors.NewBadRequestError("guest %s not kvm instance", sid)
  1810. }
  1811. screenDumpPath := kvmGuest.generateScreenDumpPath()
  1812. screenDumpName := filepath.Base(screenDumpPath)
  1813. c := make(chan interface{}, 0)
  1814. kvmGuest.Monitor.ScreenDump(screenDumpPath, func(res string) {
  1815. log.Infof("qmp screendump res %s", res)
  1816. if len(res) > 0 {
  1817. c <- errors.Errorf("qmp screen dump failed: %s", res)
  1818. return
  1819. }
  1820. if fileutils2.Exists(screenDumpPath) {
  1821. log.Infof("screendump success at %s", screenDumpPath)
  1822. defer os.Remove(screenDumpPath)
  1823. content, err := fileutils2.FileGetContents(screenDumpPath)
  1824. if err != nil {
  1825. log.Errorf("failed FileGetContents %s %s", screenDumpPath, err)
  1826. c <- err
  1827. return
  1828. }
  1829. ret := new(compute.GetDetailsGuestScreenDumpOutput)
  1830. contentType := http.DetectContentType([]byte(content))
  1831. base64Encoded := base64.StdEncoding.EncodeToString([]byte(content))
  1832. ret.ScreenDump = fmt.Sprintf("data:%s;base64,%s", contentType, base64Encoded)
  1833. ret.GuestId = sid
  1834. ret.Name = screenDumpName
  1835. c <- jsonutils.Marshal(ret)
  1836. }
  1837. })
  1838. ret := <-c
  1839. switch ret.(type) {
  1840. case jsonutils.JSONObject:
  1841. return ret.(jsonutils.JSONObject), nil
  1842. case error:
  1843. return nil, ret.(error)
  1844. }
  1845. return nil, errors.Errorf("unknown ret of screendump")
  1846. }
  1847. func SyncGuestNicsTraffics(guestNicsTraffics *compute.GuestNicTrafficSyncInput) {
  1848. session := hostutils.GetComputeSession(context.Background())
  1849. hostId := guestManager.host.GetHostId()
  1850. data := jsonutils.Marshal(guestNicsTraffics)
  1851. _, err := modules.Hosts.PerformAction(session, hostId, "sync-guest-nic-traffics", data)
  1852. if err != nil {
  1853. log.Errorf("failed sync-guest-nic-traffics %s", err)
  1854. }
  1855. }
  1856. var guestManager *SGuestManager
  1857. func Stop() {
  1858. guestManager.ExitGuestCleanup()
  1859. }
  1860. func Init(host hostutils.IHost, serversPath string, workerCnt int) error {
  1861. if guestManager == nil {
  1862. manager, err := NewGuestManager(host, serversPath, workerCnt)
  1863. if err != nil {
  1864. return err
  1865. }
  1866. guestManager = manager
  1867. types.HealthCheckReactor = guestManager
  1868. types.GuestDescGetter = guestManager
  1869. }
  1870. return nil
  1871. }
  1872. func GetGuestManager() *SGuestManager {
  1873. return guestManager
  1874. }