hosts.go 261 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852785378547855785678577858785978607861786278637864786578667867786878697870787178727873787478757876787778787879788078817882788378847885788678877888788978907891789278937894789578967897789878997900790179027903790479057906790779087909791079117912791379147915791679177918791979207921792279237924792579267927792879297930793179327933793479357936793779387939794079417942794379447945794679477948794979507951795279537954795579567957795879597960796179627963796479657966796779687969797079717972797379747975797679777978797979807981798279837984798579867987798879897990799179927993799479957996799779987999800080018002800380048005800680078008800980108011801280138014801580168017801880198020802180228023802480258026802780288029803080318032803380348035803680378038803980408041804280438044804580468047804880498050805180528053805480558056805780588059806080618062806380648065806680678068806980708071807280738074807580768077807880798080808180828083808480858086808780888089809080918092809380948095809680978098809981008101810281038104810581068107810881098110811181128113811481158116811781188119812081218122812381248125812681278128812981308131813281338134813581368137813881398140814181428143814481458146814781488149815081518152815381548155815681578158815981608161816281638164816581668167816881698170817181728173817481758176817781788179818081818182
  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 models
  15. import (
  16. "context"
  17. "database/sql"
  18. "fmt"
  19. "net"
  20. "net/http"
  21. "net/url"
  22. "sort"
  23. "strconv"
  24. "strings"
  25. "sync"
  26. "time"
  27. "golang.org/x/sync/errgroup"
  28. v1 "k8s.io/api/core/v1"
  29. metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
  30. "yunion.io/x/cloudmux/pkg/apis/compute"
  31. "yunion.io/x/cloudmux/pkg/cloudprovider"
  32. "yunion.io/x/jsonutils"
  33. "yunion.io/x/log"
  34. "yunion.io/x/pkg/errors"
  35. "yunion.io/x/pkg/gotypes"
  36. "yunion.io/x/pkg/tristate"
  37. "yunion.io/x/pkg/util/compare"
  38. "yunion.io/x/pkg/util/fileutils"
  39. "yunion.io/x/pkg/util/httputils"
  40. "yunion.io/x/pkg/util/netutils"
  41. "yunion.io/x/pkg/util/rbacscope"
  42. "yunion.io/x/pkg/util/regutils"
  43. "yunion.io/x/pkg/util/sets"
  44. "yunion.io/x/pkg/utils"
  45. "yunion.io/x/sqlchemy"
  46. "yunion.io/x/onecloud/pkg/apis"
  47. baremetalapi "yunion.io/x/onecloud/pkg/apis/baremetal"
  48. billing_api "yunion.io/x/onecloud/pkg/apis/billing"
  49. api "yunion.io/x/onecloud/pkg/apis/compute"
  50. computeapi "yunion.io/x/onecloud/pkg/apis/compute"
  51. hostapi "yunion.io/x/onecloud/pkg/apis/host"
  52. napi "yunion.io/x/onecloud/pkg/apis/notify"
  53. "yunion.io/x/onecloud/pkg/appsrv"
  54. "yunion.io/x/onecloud/pkg/cloudcommon/consts"
  55. "yunion.io/x/onecloud/pkg/cloudcommon/db"
  56. "yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
  57. "yunion.io/x/onecloud/pkg/cloudcommon/db/quotas"
  58. "yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
  59. "yunion.io/x/onecloud/pkg/cloudcommon/notifyclient"
  60. "yunion.io/x/onecloud/pkg/cloudcommon/types"
  61. "yunion.io/x/onecloud/pkg/compute/baremetal"
  62. "yunion.io/x/onecloud/pkg/compute/options"
  63. "yunion.io/x/onecloud/pkg/httperrors"
  64. "yunion.io/x/onecloud/pkg/mcclient"
  65. "yunion.io/x/onecloud/pkg/mcclient/auth"
  66. "yunion.io/x/onecloud/pkg/mcclient/modules/scheduler"
  67. "yunion.io/x/onecloud/pkg/util/cgrouputils/cpuset"
  68. "yunion.io/x/onecloud/pkg/util/k8s/tokens"
  69. "yunion.io/x/onecloud/pkg/util/logclient"
  70. "yunion.io/x/onecloud/pkg/util/rbacutils"
  71. "yunion.io/x/onecloud/pkg/util/stringutils2"
  72. )
  73. type SHostManager struct {
  74. db.SEnabledStatusInfrasResourceBaseManager
  75. db.SExternalizedResourceBaseManager
  76. SZoneResourceBaseManager
  77. SManagedResourceBaseManager
  78. SHostnameResourceBaseManager
  79. SBackupstorageResourceBaseManager
  80. }
  81. var HostManager *SHostManager
  82. func init() {
  83. HostManager = &SHostManager{
  84. SEnabledStatusInfrasResourceBaseManager: db.NewEnabledStatusInfrasResourceBaseManager(
  85. SHost{},
  86. "hosts_tbl",
  87. "host",
  88. "hosts",
  89. ),
  90. }
  91. HostManager.SetVirtualObject(HostManager)
  92. HostManager.SetAlias("baremetal", "baremetals")
  93. notifyclient.AddNotifyDBHookResources(HostManager.KeywordPlural(), HostManager.AliasPlural())
  94. GuestManager.NameRequireAscii = false
  95. }
  96. type SHost struct {
  97. db.SEnabledStatusInfrasResourceBase
  98. db.SExternalizedResourceBase
  99. SZoneResourceBase `update:""`
  100. SManagedResourceBase
  101. SBillingResourceBase
  102. SHostnameResourceBase
  103. // 机架
  104. Rack string `width:"16" charset:"ascii" nullable:"true" get:"domain" update:"domain" create:"domain_optional"`
  105. // 机位
  106. Slots string `width:"16" charset:"ascii" nullable:"true" get:"domain" update:"domain" create:"domain_optional"`
  107. // 管理口MAC
  108. AccessMac string `width:"32" charset:"ascii" nullable:"true" index:"true" list:"domain" update:"domain"`
  109. // 管理口Ip地址
  110. AccessIp string `width:"64" charset:"ascii" nullable:"true" list:"domain" update:"domain"`
  111. // 管理地址
  112. ManagerUri string `width:"256" charset:"ascii" nullable:"true" list:"domain" update:"domain" create:"domain_optional"`
  113. // 系统信息
  114. SysInfo jsonutils.JSONObject `length:"long" nullable:"true" search:"domain" list:"domain" update:"domain" create:"domain_optional"`
  115. // 物理机序列号信息
  116. SN string `width:"128" charset:"ascii" nullable:"true" list:"domain" update:"domain" create:"domain_optional"`
  117. // CPU核数
  118. CpuCount int `nullable:"true" list:"domain" update:"domain" create:"domain_optional"`
  119. // 物理CPU颗数
  120. NodeCount int8 `nullable:"true" list:"domain" update:"domain" create:"domain_optional"`
  121. // CPU描述信息
  122. CpuDesc string `width:"128" charset:"ascii" nullable:"true" get:"domain" update:"domain" create:"domain_optional"`
  123. // CPU频率
  124. CpuMhz int `nullable:"true" get:"domain" update:"domain" create:"domain_optional"`
  125. // CPU缓存大小,单位KB
  126. CpuCache int `nullable:"true" get:"domain" update:"domain" create:"domain_optional"`
  127. // 预留CPU大小
  128. CpuReserved int `nullable:"true" default:"0" list:"domain" update:"domain" create:"domain_optional"`
  129. // CPU超分比
  130. CpuCmtbound float32 `nullable:"true" list:"domain" create:"domain_optional"`
  131. // CPUMicrocode
  132. CpuMicrocode string `width:"64" charset:"ascii" nullable:"true" get:"domain" update:"domain" create:"domain_optional"`
  133. // CPU架构
  134. CpuArchitecture string `width:"16" charset:"ascii" nullable:"true" get:"domain" list:"domain" update:"domain" create:"domain_optional"`
  135. // KVM CAP VCPU MAX
  136. KvmCapMaxVcpu int `nullable:"true" get:"domain" list:"domain" update:"domain" create:"domain_optional"`
  137. // 内存大小,单位Mb
  138. MemSize int `nullable:"true" list:"domain" update:"domain" create:"domain_optional"`
  139. // 预留内存大小
  140. MemReserved int `nullable:"true" default:"0" list:"domain" update:"domain" create:"domain_optional"`
  141. // 内存超分比
  142. MemCmtbound float32 `nullable:"true" list:"domain" create:"domain_optional"`
  143. // 页大小
  144. PageSizeKB int `nullable:"false" default:"4" list:"domain" update:"domain" create:"domain_optional"`
  145. // scheduler cpu-node/numa allocate
  146. EnableNumaAllocate bool `nullable:"true" default:"false" list:"domain" update:"domain" create:"domain_optional"`
  147. // 存储大小,单位Mb
  148. StorageSize int64 `nullable:"true" list:"domain" update:"domain" create:"domain_optional"`
  149. // 存储类型
  150. StorageType string `width:"20" charset:"ascii" nullable:"true" list:"domain" update:"domain" create:"domain_optional"`
  151. // 存储驱动类型
  152. StorageDriver string `width:"20" charset:"ascii" nullable:"true" get:"domain" update:"domain" create:"domain_optional"`
  153. // 存储详情
  154. StorageInfo jsonutils.JSONObject `nullable:"true" get:"domain" update:"domain" create:"domain_optional"`
  155. RootPartitionUsedCapacityMb int `nullable:"true" list:"domain" update:"domain" create:"domain_optional"`
  156. MemoryUsedMb int `nullable:"true" list:"domain" update:"domain" create:"domain_optional"`
  157. CpuUsagePercent float64 `nullable:"true" list:"domain" update:"domain" create:"domain_optional"`
  158. // IPMI地址
  159. IpmiIp string `width:"16" charset:"ascii" nullable:"true" list:"domain"`
  160. // IPMI详情
  161. IpmiInfo jsonutils.JSONObject `nullable:"true" get:"domain" update:"domain" create:"domain_optional"`
  162. // 宿主机状态
  163. // example: online
  164. HostStatus string `width:"16" charset:"ascii" nullable:"false" default:"offline" list:"domain"`
  165. // 宿主机类型
  166. HostType string `width:"36" charset:"ascii" nullable:"false" list:"domain" update:"domain" create:"domain_required"`
  167. // host服务软件版本
  168. Version string `width:"128" charset:"ascii" list:"domain" update:"domain" create:"domain_optional"`
  169. // OVN软件版本
  170. OvnVersion string `width:"64" charset:"ascii" list:"domain" update:"domain" create:"domain_optional"`
  171. IsBaremetal bool `nullable:"true" default:"false" list:"domain" update:"domain" create:"domain_optional"`
  172. // 是否处于维护状态
  173. IsMaintenance bool `nullable:"true" default:"false" list:"domain"`
  174. LastPingAt time.Time ``
  175. // health check enabled by host agent online
  176. EnableHealthCheck bool `nullable:"true" default:"false"`
  177. ResourceType string `width:"36" charset:"ascii" nullable:"false" list:"domain" update:"domain" create:"domain_optional" default:"shared"`
  178. RealExternalId string `width:"256" charset:"utf8" get:"domain"`
  179. // 是否为导入的宿主机
  180. IsImport bool `nullable:"true" default:"false" list:"domain" create:"domain_optional"`
  181. // 是否允许PXE启动
  182. EnablePxeBoot tristate.TriState `default:"true" list:"domain" create:"domain_optional" update:"domain"`
  183. // 主机UUID
  184. Uuid string `width:"64" nullable:"true" list:"domain" update:"domain" create:"domain_optional"`
  185. // 主机启动模式, 可能值为PXE和ISO
  186. BootMode string `width:"8" nullable:"true" list:"domain" update:"domain" create:"domain_optional"`
  187. // IPv4地址,作为私有云vpc访问外网时的网关
  188. OvnMappedIpAddr string `width:"16" charset:"ascii" nullable:"true" list:"user"`
  189. // IPv6地址,作为私有云vpc访问外网时的网关
  190. OvnMappedIp6Addr string `width:"64" charset:"ascii" nullable:"true" list:"user"`
  191. // UEFI详情
  192. UefiInfo jsonutils.JSONObject `nullable:"true" get:"domain" update:"domain" create:"domain_optional"`
  193. // 公网Ip地址
  194. PublicIp string `width:"128" charset:"ascii" nullable:"true" list:"domain" update:"domain"`
  195. }
  196. func (manager *SHostManager) GetContextManagers() [][]db.IModelManager {
  197. return [][]db.IModelManager{
  198. {ZoneManager},
  199. }
  200. }
  201. // 宿主机/物理机列表
  202. func (manager *SHostManager) ListItemFilter(
  203. ctx context.Context,
  204. q *sqlchemy.SQuery,
  205. userCred mcclient.TokenCredential,
  206. query api.HostListInput,
  207. ) (*sqlchemy.SQuery, error) {
  208. var err error
  209. q, err = manager.SManagedResourceBaseManager.ListItemFilter(ctx, q, userCred, query.ManagedResourceListInput)
  210. if err != nil {
  211. return nil, errors.Wrap(err, "SManagedResourceBaseManager.ListItemFilter")
  212. }
  213. q, err = manager.SExternalizedResourceBaseManager.ListItemFilter(ctx, q, userCred, query.ExternalizedResourceBaseListInput)
  214. if err != nil {
  215. return nil, errors.Wrap(err, "SExternalizedResourceBaseManager.ListItemFilter")
  216. }
  217. q, err = manager.SZoneResourceBaseManager.ListItemFilter(ctx, q, userCred, query.ZonalFilterListInput)
  218. if err != nil {
  219. return nil, errors.Wrap(err, "SZoneResourceBaseManager.ListItemFilter")
  220. }
  221. resType := query.ResourceType
  222. if len(resType) > 0 {
  223. switch resType {
  224. case api.HostResourceTypeShared:
  225. q = q.Filter(
  226. sqlchemy.OR(
  227. sqlchemy.IsNullOrEmpty(q.Field("resource_type")),
  228. sqlchemy.Equals(q.Field("resource_type"), api.HostResourceTypeShared),
  229. ),
  230. )
  231. default:
  232. q = q.Equals("resource_type", resType)
  233. }
  234. }
  235. q, err = manager.SEnabledStatusInfrasResourceBaseManager.ListItemFilter(ctx, q, userCred, query.EnabledStatusInfrasResourceBaseListInput)
  236. if err != nil {
  237. return nil, errors.Wrap(err, "SEnabledStatusInfrasResourceBaseManager.ListItemFilter")
  238. }
  239. if len(query.AnyMac) > 0 {
  240. anyMac := netutils.FormatMacAddr(query.AnyMac)
  241. if len(anyMac) == 0 {
  242. return nil, errors.Wrapf(httperrors.ErrInputParameter, "invalid any_mac address %s", query.AnyMac)
  243. }
  244. netifs, _ := NetInterfaceManager.FetchByMac(anyMac)
  245. var bmIds []string
  246. for i := range netifs {
  247. if !utils.IsInArray(netifs[i].BaremetalId, bmIds) {
  248. bmIds = append(bmIds, netifs[i].BaremetalId)
  249. }
  250. }
  251. if len(bmIds) > 0 {
  252. q = q.In("id", bmIds)
  253. } else {
  254. q = q.Equals("access_mac", anyMac)
  255. }
  256. }
  257. if len(query.AnyIp) > 0 {
  258. cmpFunc := sqlchemy.Equals
  259. if len(query.AnyIp) == 1 {
  260. cmpFunc = func(f sqlchemy.IQueryField, v interface{}) sqlchemy.ICondition {
  261. return sqlchemy.Regexp(f, v.(string))
  262. }
  263. }
  264. hnQ := HostnetworkManager.Query("baremetal_id") //.Contains("ip_addr", query.AnyIp).SubQuery()
  265. conditions := []sqlchemy.ICondition{}
  266. for _, ip := range query.AnyIp {
  267. conditions = append(conditions, cmpFunc(hnQ.Field("ip_addr"), ip))
  268. }
  269. hn := hnQ.Filter(
  270. sqlchemy.OR(conditions...),
  271. )
  272. conditions = []sqlchemy.ICondition{}
  273. for _, ip := range query.AnyIp {
  274. conditions = append(conditions, cmpFunc(q.Field("access_ip"), ip))
  275. conditions = append(conditions, cmpFunc(q.Field("ipmi_ip"), ip))
  276. }
  277. conditions = append(conditions, sqlchemy.In(q.Field("id"), hn))
  278. q = q.Filter(sqlchemy.OR(
  279. conditions...,
  280. ))
  281. }
  282. schedTagStr := query.SchedtagId
  283. if len(schedTagStr) > 0 {
  284. schedTag, _ := SchedtagManager.FetchByIdOrName(ctx, nil, schedTagStr)
  285. if schedTag == nil {
  286. return nil, httperrors.NewResourceNotFoundError("Schedtag %s not found", schedTagStr)
  287. }
  288. hostschedtags := HostschedtagManager.Query().SubQuery()
  289. scopeQuery := hostschedtags.Query(hostschedtags.Field("host_id")).Equals("schedtag_id", schedTag.GetId()).SubQuery()
  290. q = q.In("id", scopeQuery)
  291. }
  292. wireStr := query.WireId
  293. if len(wireStr) > 0 {
  294. wire, _ := WireManager.FetchByIdOrName(ctx, nil, wireStr)
  295. if wire == nil {
  296. return nil, httperrors.NewResourceNotFoundError("Wire %s not found", wireStr)
  297. }
  298. hostwires := NetInterfaceManager.Query().SubQuery()
  299. scopeQuery := hostwires.Query(hostwires.Field("baremetal_id")).Equals("wire_id", wire.GetId()).SubQuery()
  300. q = q.In("id", scopeQuery)
  301. }
  302. storageStr := query.StorageId
  303. if len(storageStr) > 0 {
  304. storage, _ := StorageManager.FetchByIdOrName(ctx, nil, storageStr)
  305. if storage == nil {
  306. return nil, httperrors.NewResourceNotFoundError("Storage %s not found", storageStr)
  307. }
  308. hoststorages := HoststorageManager.Query().SubQuery()
  309. scopeQuery := hoststorages.Query(hoststorages.Field("host_id")).Equals("storage_id", storage.GetId()).SubQuery()
  310. notAttached := (query.StorageNotAttached != nil && *query.StorageNotAttached)
  311. if !notAttached {
  312. q = q.In("id", scopeQuery)
  313. } else {
  314. q = q.NotIn("id", scopeQuery)
  315. }
  316. }
  317. if len(query.BackupstorageId) > 0 {
  318. hbsQ := HostBackupstorageManager.Query("host_id", "backupstorage_id")
  319. hbsQ, err = manager.SBackupstorageResourceBaseManager.ListItemFilter(ctx, hbsQ, userCred, query.BackupstorageFilterListInput)
  320. if err != nil {
  321. return q, errors.Wrap(err, "SBackupStorageResouceBaseManager.ListItemFiled")
  322. }
  323. hbsSubQ := hbsQ.SubQuery()
  324. q = q.LeftJoin(hbsSubQ, sqlchemy.Equals(q.Field("id"), hbsSubQ.Field("host_id")))
  325. notAttached := (query.StorageNotAttached != nil && *query.StorageNotAttached)
  326. if !notAttached {
  327. q = q.Filter(sqlchemy.IsNotNull(hbsSubQ.Field("backupstorage_id")))
  328. } else {
  329. q = q.Filter(sqlchemy.IsNull(hbsSubQ.Field("backupstorage_id")))
  330. }
  331. }
  332. hostStorageType := query.HostStorageType
  333. if len(hostStorageType) > 0 {
  334. hoststorages := HoststorageManager.Query()
  335. storages := StorageManager.Query().In("storage_type", hostStorageType).SubQuery()
  336. hq := hoststorages.Join(storages, sqlchemy.Equals(hoststorages.Field("storage_id"), storages.Field("id"))).SubQuery()
  337. scopeQuery := hq.Query(hq.Field("host_id")).SubQuery()
  338. q = q.In("id", scopeQuery)
  339. }
  340. hypervisorStr := query.Hypervisor
  341. if len(hypervisorStr) > 0 {
  342. q = q.Filter(sqlchemy.In(q.Field("host_type"), Hypervisors2HostTypes([]string{query.Hypervisor})))
  343. }
  344. usable := (query.Usable != nil && *query.Usable)
  345. if usable {
  346. hosts := HostManager.Query().SubQuery()
  347. netifs := NetInterfaceManager.Query().SubQuery()
  348. networks := NetworkManager.Query().SubQuery()
  349. providers := usableCloudProviders().SubQuery()
  350. hostQ1 := hosts.Query(hosts.Field("id"))
  351. hostQ1 = hostQ1.Join(providers, sqlchemy.Equals(hosts.Field("manager_id"), providers.Field("id")))
  352. hostQ1 = hostQ1.Join(netifs, sqlchemy.Equals(hosts.Field("id"), netifs.Field("baremetal_id")))
  353. hostQ1 = hostQ1.Join(networks, sqlchemy.Equals(netifs.Field("wire_id"), networks.Field("wire_id")))
  354. hostQ1 = hostQ1.Filter(sqlchemy.Equals(networks.Field("status"), api.NETWORK_STATUS_AVAILABLE))
  355. hostQ1 = hostQ1.Filter(sqlchemy.IsTrue(hosts.Field("enabled")))
  356. hostQ2 := hosts.Query(hosts.Field("id"))
  357. hostQ2 = hostQ2.Join(netifs, sqlchemy.Equals(hosts.Field("id"), netifs.Field("baremetal_id")))
  358. hostQ2 = hostQ2.Join(networks, sqlchemy.Equals(netifs.Field("wire_id"), networks.Field("wire_id")))
  359. hostQ2 = hostQ2.Filter(sqlchemy.IsNullOrEmpty(hosts.Field("manager_id")))
  360. hostQ2 = hostQ2.Filter(sqlchemy.Equals(networks.Field("status"), api.NETWORK_STATUS_AVAILABLE))
  361. hostQ2 = hostQ2.Filter(sqlchemy.IsTrue(hosts.Field("enabled")))
  362. q = q.Filter(sqlchemy.OR(
  363. sqlchemy.In(q.Field("id"), hostQ1.SubQuery()),
  364. sqlchemy.In(q.Field("id"), hostQ2.SubQuery()),
  365. ))
  366. zones := ZoneManager.Query().SubQuery()
  367. q = q.Join(zones, sqlchemy.Equals(q.Field("zone_id"), zones.Field("id"))).
  368. Filter(sqlchemy.Equals(zones.Field("status"), api.ZONE_ENABLE))
  369. q = q.In("status", []string{api.HOST_STATUS_RUNNING, api.HOST_STATUS_READY})
  370. q = q.Filter(
  371. sqlchemy.OR(
  372. sqlchemy.AND(
  373. sqlchemy.NotEquals(q.Field("host_type"), api.HOST_TYPE_BAREMETAL),
  374. sqlchemy.Equals(q.Field("host_status"), api.HOST_ONLINE),
  375. ),
  376. sqlchemy.Equals(q.Field("host_type"), api.HOST_TYPE_BAREMETAL),
  377. ),
  378. )
  379. }
  380. if query.IsEmpty != nil {
  381. isEmpty := *query.IsEmpty
  382. sq := GuestManager.Query("host_id").IsNotEmpty("host_id").GroupBy("host_id").SubQuery()
  383. if isEmpty {
  384. q = q.NotIn("id", sq)
  385. } else {
  386. q = q.In("id", sq)
  387. }
  388. }
  389. if query.Baremetal != nil {
  390. isBaremetal := *query.Baremetal
  391. if isBaremetal {
  392. q = q.Equals("host_type", api.HOST_TYPE_BAREMETAL)
  393. } else {
  394. q = q.NotEquals("host_type", api.HOST_TYPE_BAREMETAL)
  395. }
  396. }
  397. fieldQueryMap := map[string][]string{
  398. "rack": query.Rack,
  399. "slots": query.Slots,
  400. "access_mac": query.AccessMac,
  401. "access_ip": query.AccessIp,
  402. "sn": query.SN,
  403. "storage_type": query.StorageType,
  404. "ipmi_ip": query.IpmiIp,
  405. "public_ip": query.PublicIp,
  406. "host_status": query.HostStatus,
  407. "host_type": query.HostType,
  408. "version": query.Version,
  409. "ovn_version": query.OvnVersion,
  410. "uuid": query.Uuid,
  411. "boot_mode": query.BootMode,
  412. "cpu_architecture": query.CpuArchitecture,
  413. }
  414. for f, vars := range fieldQueryMap {
  415. vars = stringutils2.FilterEmpty(vars)
  416. if len(vars) > 1 {
  417. q = q.In(f, vars)
  418. } else if len(vars) == 1 {
  419. q = q.Regexp(f, vars[0])
  420. }
  421. }
  422. if len(query.CpuCount) > 0 {
  423. q = q.In("cpu_count", query.CpuCount)
  424. }
  425. if len(query.MemSize) > 0 {
  426. q = q.In("mem_size", query.MemSize)
  427. }
  428. if query.IsMaintenance != nil {
  429. if *query.IsMaintenance {
  430. q = q.IsTrue("is_maintenance")
  431. } else {
  432. q = q.IsFalse("is_maintenance")
  433. }
  434. }
  435. if query.IsImport != nil {
  436. if *query.IsImport {
  437. q = q.IsTrue("is_import")
  438. } else {
  439. q = q.IsFalse("is_import")
  440. }
  441. }
  442. if query.EnablePxeBoot != nil {
  443. if *query.EnablePxeBoot {
  444. q = q.IsTrue("enable_pxe_boot")
  445. } else {
  446. q = q.IsFalse("enable_pxe_boot")
  447. }
  448. }
  449. if len(query.OsArch) > 0 {
  450. q = db.ListQueryByArchitecture(q, "cpu_architecture", query.OsArch)
  451. }
  452. // for provider onecloud
  453. if len(query.ServerIdForNetwork) > 0 {
  454. guest := GuestManager.FetchGuestById(query.ServerIdForNetwork)
  455. if guest != nil && guest.GetHypervisor() == api.HYPERVISOR_KVM {
  456. nets, _ := guest.GetNetworks("")
  457. if len(nets) > 0 {
  458. wires := []string{}
  459. for i := 0; i < len(nets); i++ {
  460. net, _ := nets[i].GetNetwork()
  461. if net == nil {
  462. continue
  463. }
  464. vpc, _ := net.GetVpc()
  465. if vpc.Id != api.DEFAULT_VPC_ID {
  466. q = q.IsNotEmpty("ovn_version")
  467. } else {
  468. if !utils.IsInStringArray(net.WireId, wires) {
  469. wires = append(wires, net.WireId)
  470. netifs := NetInterfaceManager.Query().SubQuery()
  471. scopeQuery := netifs.Query(netifs.Field("baremetal_id")).Equals("wire_id", net.WireId).SubQuery()
  472. q = q.In("id", scopeQuery)
  473. }
  474. }
  475. }
  476. }
  477. }
  478. }
  479. return q, nil
  480. }
  481. func (manager *SHostManager) OrderByExtraFields(
  482. ctx context.Context,
  483. q *sqlchemy.SQuery,
  484. userCred mcclient.TokenCredential,
  485. query api.HostListInput,
  486. ) (*sqlchemy.SQuery, error) {
  487. var err error
  488. q, err = manager.SEnabledStatusInfrasResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.EnabledStatusInfrasResourceBaseListInput)
  489. if err != nil {
  490. return nil, errors.Wrap(err, "SEnabledStatusInfrasResourceBaseManager.OrderByExtraFields")
  491. }
  492. q, err = manager.SManagedResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.ManagedResourceListInput)
  493. if err != nil {
  494. return nil, errors.Wrap(err, "SManagedResourceBaseManager.OrderByExtraFields")
  495. }
  496. q, err = manager.SZoneResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.ZonalFilterListInput)
  497. if err != nil {
  498. return nil, errors.Wrap(err, "SZoneResourceBaseManager.OrderByExtraFields")
  499. }
  500. if db.NeedOrderQuery([]string{query.OrderByServerCount}) {
  501. guests := GuestManager.Query().SubQuery()
  502. guestCounts := guests.Query(
  503. guests.Field("host_id"),
  504. sqlchemy.COUNT("id").Label("guest_count"),
  505. ).GroupBy("host_id").SubQuery()
  506. q = q.LeftJoin(guestCounts, sqlchemy.Equals(q.Field("id"), guestCounts.Field("host_id")))
  507. db.OrderByFields(q, []string{query.OrderByServerCount}, []sqlchemy.IQueryField{guestCounts.Field("guest_count")})
  508. }
  509. if db.NeedOrderQuery([]string{query.OrderByCpuCommitRate}) {
  510. guestsQ := GuestManager.Query()
  511. if options.Options.IgnoreNonrunningGuests {
  512. guestsQ = guestsQ.Equals("status", api.VM_RUNNING)
  513. }
  514. guests := guestsQ.SubQuery()
  515. hosts := HostManager.Query().SubQuery()
  516. hostQ := hosts.Query(
  517. hosts.Field("id"),
  518. hosts.Field("cpu_count"),
  519. hosts.Field("cpu_reserved"),
  520. sqlchemy.SUM("guest_vcpu_count", guests.Field("vcpu_count")),
  521. ).LeftJoin(guests, sqlchemy.Equals(hosts.Field("id"), guests.Field("host_id")))
  522. hostSQ := hostQ.GroupBy(hostQ.Field("host_id")).SubQuery()
  523. divSQ := hostSQ.Query(
  524. hostSQ.Field("id"),
  525. sqlchemy.SUB("vcpu_count", hostSQ.Field("cpu_count"), hostSQ.Field("cpu_reserved")),
  526. hostSQ.Field("guest_vcpu_count"),
  527. ).SubQuery()
  528. sq := divSQ.Query(
  529. divSQ.Field("id").Label("host_id"),
  530. sqlchemy.DIV("cpu_commit_rate", divSQ.Field("guest_vcpu_count"), divSQ.Field("vcpu_count")),
  531. ).SubQuery()
  532. q = q.LeftJoin(sq, sqlchemy.Equals(q.Field("id"), sq.Field("host_id")))
  533. db.OrderByFields(q, []string{query.OrderByCpuCommitRate}, []sqlchemy.IQueryField{sq.Field("cpu_commit_rate")})
  534. }
  535. if db.NeedOrderQuery([]string{query.OrderByCpuCommit}) {
  536. guestsQ := GuestManager.Query()
  537. if options.Options.IgnoreNonrunningGuests {
  538. guestsQ = guestsQ.Equals("status", api.VM_RUNNING)
  539. }
  540. guests := guestsQ.SubQuery()
  541. guestQ := guests.Query(
  542. guests.Field("host_id"),
  543. sqlchemy.SUM("guest_vcpu_count", guests.Field("vcpu_count")),
  544. )
  545. guestSQ := guestQ.GroupBy(guestQ.Field("host_id")).SubQuery()
  546. q = q.LeftJoin(guestSQ, sqlchemy.Equals(q.Field("id"), guestSQ.Field("host_id")))
  547. db.OrderByFields(q, []string{query.OrderByCpuCommit}, []sqlchemy.IQueryField{q.Field("guest_vcpu_count")})
  548. }
  549. if db.NeedOrderQuery([]string{query.OrderByStorage}) {
  550. hoststorages := HoststorageManager.Query().SubQuery()
  551. storages := StorageManager.Query().IsTrue("enabled").In("storage_type", api.HOST_STORAGE_LOCAL_TYPES).SubQuery()
  552. hoststoragesQ := hoststorages.Query(
  553. hoststorages.Field("host_id"),
  554. sqlchemy.SUM("storage_capacity", storages.Field("capacity")),
  555. )
  556. hoststoragesQ = hoststoragesQ.LeftJoin(storages, sqlchemy.Equals(hoststoragesQ.Field("storage_id"), storages.Field("id")))
  557. hoststoragesSQ := hoststoragesQ.GroupBy(hoststoragesQ.Field("host_id")).SubQuery()
  558. q = q.LeftJoin(hoststoragesSQ, sqlchemy.Equals(q.Field("id"), hoststoragesSQ.Field("host_id")))
  559. db.OrderByFields(q, []string{query.OrderByStorage}, []sqlchemy.IQueryField{hoststoragesSQ.Field("storage_capacity")})
  560. }
  561. if db.NeedOrderQuery([]string{query.OrderByStorageCommitRate}) {
  562. hoststorages := HoststorageManager.Query().SubQuery()
  563. disks := DiskManager.Query().Equals("status", api.DISK_READY).SubQuery()
  564. storages := StorageManager.Query().IsTrue("enabled").In("storage_type", api.HOST_STORAGE_LOCAL_TYPES).SubQuery()
  565. disksQ := disks.Query(
  566. disks.Field("storage_id"),
  567. sqlchemy.SUM("disk_size", disks.Field("disk_size")),
  568. storages.Field("capacity"),
  569. storages.Field("reserved"),
  570. ).LeftJoin(storages, sqlchemy.Equals(disks.Field("storage_id"), storages.Field("id")))
  571. disksSQ := disksQ.GroupBy(disksQ.Field("storage_id")).SubQuery()
  572. divSQ := disksSQ.Query(
  573. disksSQ.Field("storage_id"),
  574. disksSQ.Field("disk_size"),
  575. sqlchemy.SUB("storage_capacity", disksSQ.Field("capacity"), disksSQ.Field("reserved")),
  576. ).SubQuery()
  577. hoststoragesQ := hoststorages.Query(
  578. hoststorages.Field("host_id"),
  579. sqlchemy.SUM("storage_used", divSQ.Field("disk_size")),
  580. sqlchemy.SUM("storage_capacity", divSQ.Field("storage_capacity")),
  581. )
  582. hoststoragesQ = hoststoragesQ.LeftJoin(divSQ, sqlchemy.Equals(hoststoragesQ.Field("storage_id"), divSQ.Field("storage_id")))
  583. hoststoragesSQ1 := hoststoragesQ.GroupBy(hoststoragesQ.Field("host_id")).SubQuery()
  584. hoststoragesSQ := hoststoragesSQ1.Query(
  585. hoststoragesSQ1.Field("host_id"),
  586. sqlchemy.DIV("storage_commit_rate",
  587. hoststoragesSQ1.Field("storage_used"),
  588. hoststoragesSQ1.Field("storage_capacity"),
  589. ),
  590. ).SubQuery()
  591. q = q.LeftJoin(hoststoragesSQ, sqlchemy.Equals(q.Field("id"), hoststoragesSQ.Field("host_id")))
  592. db.OrderByFields(q, []string{query.OrderByStorageCommitRate}, []sqlchemy.IQueryField{hoststoragesSQ.Field("storage_commit_rate")})
  593. }
  594. if db.NeedOrderQuery([]string{query.OrderByMemCommitRate}) {
  595. guestsQ := GuestManager.Query()
  596. if options.Options.IgnoreNonrunningGuests {
  597. guestsQ = guestsQ.Equals("status", api.VM_RUNNING)
  598. }
  599. guests := guestsQ.SubQuery()
  600. hosts := HostManager.Query().SubQuery()
  601. hostQ := hosts.Query(
  602. hosts.Field("id"),
  603. hosts.Field("mem_size"),
  604. hosts.Field("mem_reserved"),
  605. sqlchemy.SUM("guest_vmem_size", guests.Field("vmem_size")),
  606. ).LeftJoin(guests, sqlchemy.Equals(hosts.Field("id"), guests.Field("host_id")))
  607. hostSQ := hostQ.GroupBy(hostQ.Field("host_id")).SubQuery()
  608. divSQ := hostSQ.Query(
  609. hostSQ.Field("id"),
  610. sqlchemy.SUB("vmem_size", hostSQ.Field("mem_size"), hostSQ.Field("mem_reserved")),
  611. hostSQ.Field("guest_vmem_size"),
  612. ).SubQuery()
  613. sq := divSQ.Query(
  614. divSQ.Field("id").Label("host_id"),
  615. sqlchemy.DIV("mem_commit_rate", divSQ.Field("guest_vmem_size"), divSQ.Field("vmem_size")),
  616. ).SubQuery()
  617. q = q.LeftJoin(sq, sqlchemy.Equals(q.Field("id"), sq.Field("host_id")))
  618. db.OrderByFields(q, []string{query.OrderByMemCommitRate}, []sqlchemy.IQueryField{sq.Field("mem_commit_rate")})
  619. }
  620. if db.NeedOrderQuery([]string{query.OrderByMemCommit}) {
  621. guestsQ := GuestManager.Query()
  622. if options.Options.IgnoreNonrunningGuests {
  623. guestsQ = guestsQ.Equals("status", api.VM_RUNNING)
  624. }
  625. guests := guestsQ.SubQuery()
  626. guestQ := guests.Query(
  627. guests.Field("host_id"),
  628. sqlchemy.SUM("guest_vmem_size", guests.Field("vmem_size")),
  629. )
  630. guestSQ := guestQ.GroupBy(guestQ.Field("host_id")).SubQuery()
  631. q = q.LeftJoin(guestSQ, sqlchemy.Equals(q.Field("id"), guestSQ.Field("host_id")))
  632. db.OrderByFields(q, []string{query.OrderByMemCommit}, []sqlchemy.IQueryField{q.Field("guest_vmem_size")})
  633. }
  634. if db.NeedOrderQuery([]string{query.OrderByStorageUsed}) {
  635. disks := DiskManager.Query().Equals("status", api.DISK_READY).SubQuery()
  636. storages := StorageManager.Query().IsTrue("enabled").In("storage_type", api.HOST_STORAGE_LOCAL_TYPES).SubQuery()
  637. hs := HoststorageManager.Query()
  638. hoststorages := hs.Join(storages, sqlchemy.Equals(storages.Field("id"), hs.Field("storage_id"))).SubQuery()
  639. disksQ := disks.Query(
  640. disks.Field("storage_id"),
  641. sqlchemy.SUM("total_disk_size", disks.Field("disk_size")),
  642. )
  643. disksQ = disksQ.LeftJoin(storages, sqlchemy.Equals(disksQ.Field("storage_id"), storages.Field("id")))
  644. disksSQ := disksQ.GroupBy(disksQ.Field("storage_id")).SubQuery()
  645. hoststoragesQ := hoststorages.Query(
  646. hoststorages.Field("host_id"),
  647. sqlchemy.SUM("storage_used", disksSQ.Field("total_disk_size")),
  648. )
  649. hoststoragesQ = hoststoragesQ.Join(disksSQ, sqlchemy.Equals(hoststoragesQ.Field("storage_id"), disksSQ.Field("storage_id")))
  650. storageSQ := hoststoragesQ.GroupBy(hoststoragesQ.Field("host_id")).SubQuery()
  651. q = q.LeftJoin(storageSQ, sqlchemy.Equals(q.Field("id"), storageSQ.Field("host_id")))
  652. db.OrderByFields(q, []string{query.OrderByStorageUsed}, []sqlchemy.IQueryField{q.Field("storage_used")})
  653. }
  654. if db.NeedOrderQuery([]string{query.OrderByCpuUsage}) {
  655. db.OrderByFields(q, []string{query.OrderByCpuUsage}, []sqlchemy.IQueryField{q.Field("cpu_usage_percent")})
  656. }
  657. if db.NeedOrderQuery([]string{query.OrderByMemUsage}) {
  658. hosts := HostManager.Query().SubQuery()
  659. sq := hosts.Query(
  660. hosts.Field("id").Label("host_id"),
  661. sqlchemy.DIV("mem_usage", hosts.Field("memory_used_mb"), hosts.Field("mem_size")),
  662. ).SubQuery()
  663. q = q.LeftJoin(sq, sqlchemy.Equals(q.Field("id"), sq.Field("host_id")))
  664. db.OrderByFields(q, []string{query.OrderByMemUsage}, []sqlchemy.IQueryField{sq.Field("mem_usage")})
  665. }
  666. if db.NeedOrderQuery([]string{query.OrderByStorageUsage}) {
  667. hs := HoststorageManager.Query().SubQuery()
  668. storages := StorageManager.Query().IsTrue("enabled").NotEquals("storage_type", api.STORAGE_BAREMETAL).In("storage_type", api.HOST_STORAGE_LOCAL_TYPES).SubQuery()
  669. host := HostManager.Query().SubQuery()
  670. hsSQ := hs.Query(
  671. hs.Field("host_id"),
  672. sqlchemy.SUM("actual_storage_used", storages.Field("actual_capacity_used")),
  673. ).LeftJoin(storages, sqlchemy.Equals(hs.Field("storage_id"), storages.Field("id"))).GroupBy(hs.Field("host_id")).SubQuery()
  674. hsQ := hsSQ.Query(
  675. hsSQ.Field("host_id"),
  676. sqlchemy.DIV("storage_usage", hsSQ.Field("actual_storage_used"), host.Field("storage_size")),
  677. ).LeftJoin(host, sqlchemy.Equals(hsSQ.Field("host_id"), host.Field("id")))
  678. hsSSQ := hsQ.GroupBy(hsQ.Field("host_id")).SubQuery()
  679. q = q.LeftJoin(hsSSQ, sqlchemy.Equals(q.Field("id"), hsSSQ.Field("host_id")))
  680. db.OrderByFields(q, []string{query.OrderByStorageUsage}, []sqlchemy.IQueryField{hsSSQ.Field("storage_usage")})
  681. }
  682. if db.NeedOrderQuery([]string{query.OrderByVirtualMemUsage}) {
  683. guests := GuestManager.Query()
  684. if options.Options.IgnoreNonrunningGuests {
  685. guests = guests.Equals("status", api.VM_RUNNING)
  686. }
  687. sq := guests.SubQuery()
  688. guestSQ := sq.Query(
  689. sq.Field("host_id"),
  690. sqlchemy.SUM("mem_commit", sq.Field("vmem_size")),
  691. ).GroupBy(sq.Field("host_id")).SubQuery()
  692. host := HostManager.Query().SubQuery()
  693. vq := guestSQ.Query(
  694. guestSQ.Field("host_id"),
  695. guestSQ.Field("mem_commit"),
  696. sqlchemy.NewFunction(
  697. sqlchemy.NewCase().When(
  698. sqlchemy.GT(host.Field("mem_cmtbound"), 0),
  699. host.Field("mem_cmtbound"),
  700. ).Else(sqlchemy.NewConstField(options.Options.DefaultMemoryOvercommitBound)),
  701. "mem_cmtbound",
  702. true,
  703. ),
  704. sqlchemy.SUB("host_mem_size", host.Field("mem_size"), host.Field("mem_reserved")),
  705. ).LeftJoin(host, sqlchemy.Equals(guestSQ.Field("host_id"), host.Field("id"))).GroupBy(guestSQ.Field("host_id")).SubQuery()
  706. vsq := vq.Query(
  707. vq.Field("host_id"),
  708. sqlchemy.DIV("virtual_mem_usage", vq.Field("mem_commit"), sqlchemy.DIV("cmt_mem_size", vq.Field("mem_cmtbound"), vq.Field("host_mem_size"))),
  709. )
  710. vqq := vsq.GroupBy(vsq.Field("host_id")).SubQuery()
  711. q = q.LeftJoin(vqq, sqlchemy.Equals(q.Field("id"), vqq.Field("host_id")))
  712. db.OrderByFields(q, []string{query.OrderByVirtualMemUsage}, []sqlchemy.IQueryField{vqq.Field("virtual_mem_usage")})
  713. }
  714. if db.NeedOrderQuery([]string{query.OrderByVirtualCpuUsage}) {
  715. guests := GuestManager.Query()
  716. if options.Options.IgnoreNonrunningGuests {
  717. guests = guests.Equals("status", api.VM_RUNNING)
  718. }
  719. sq := guests.SubQuery()
  720. guestSQ := sq.Query(
  721. sq.Field("host_id"),
  722. sqlchemy.SUM("cpu_commit", sq.Field("vcpu_count")),
  723. ).GroupBy(sq.Field("host_id")).SubQuery()
  724. host := HostManager.Query().SubQuery()
  725. vq := guestSQ.Query(
  726. guestSQ.Field("host_id"),
  727. guestSQ.Field("cpu_commit"),
  728. sqlchemy.NewFunction(
  729. sqlchemy.NewCase().When(
  730. sqlchemy.GT(host.Field("cpu_cmtbound"), 0),
  731. host.Field("cpu_cmtbound"),
  732. ).Else(sqlchemy.NewConstField(options.Options.DefaultCPUOvercommitBound)),
  733. "cpu_cmtbound",
  734. true,
  735. ),
  736. sqlchemy.SUB("host_cpu_size", host.Field("cpu_count"), host.Field("cpu_reserved")),
  737. ).LeftJoin(host, sqlchemy.Equals(guestSQ.Field("host_id"), host.Field("id"))).GroupBy(guestSQ.Field("host_id")).SubQuery()
  738. vsq := vq.Query(
  739. vq.Field("host_id"),
  740. sqlchemy.DIV("virtual_cpu_usage", vq.Field("cpu_commit"), sqlchemy.DIV("cmt_cpu_size", vq.Field("cpu_cmtbound"), vq.Field("host_cpu_size"))),
  741. )
  742. vqq := vsq.GroupBy(vsq.Field("host_id")).SubQuery()
  743. q = q.LeftJoin(vqq, sqlchemy.Equals(q.Field("id"), vqq.Field("host_id")))
  744. db.OrderByFields(q, []string{query.OrderByVirtualCpuUsage}, []sqlchemy.IQueryField{vqq.Field("virtual_cpu_usage")})
  745. }
  746. if db.NeedOrderQuery([]string{query.OrderByVirtualStorageUsage}) {
  747. hoststorages := HoststorageManager.Query().SubQuery()
  748. storageQ := StorageManager.Query().IsTrue("enabled").NotEquals("storage_type", api.STORAGE_BAREMETAL).In("storage_type", api.HOST_STORAGE_LOCAL_TYPES).SubQuery()
  749. diskReadySQ := DiskManager.Query().Equals("status", api.DISK_READY).SubQuery()
  750. diskReadyQ := diskReadySQ.Query(sqlchemy.SUM("sum", diskReadySQ.Field("disk_size")).Label("used")).GroupBy(diskReadySQ.Field("storage_id"))
  751. readySQ := diskReadyQ.SubQuery()
  752. storageSQ := storageQ.Query(
  753. storageQ.Field("id"),
  754. sqlchemy.SUB("storage_capacity", storageQ.Field("capacity"), storageQ.Field("reserved")),
  755. hoststorages.Field("host_id"),
  756. sqlchemy.NewFunction(
  757. sqlchemy.NewCase().When(
  758. sqlchemy.GT(storageQ.Field("cmtbound"), 0),
  759. storageQ.Field("cmtbound"),
  760. ).Else(sqlchemy.NewConstField(1)),
  761. "cmtbound",
  762. true,
  763. ),
  764. readySQ.Field("used"),
  765. )
  766. storageSQ = storageSQ.Join(hoststorages, sqlchemy.Equals(storageSQ.Field("id"), hoststorages.Field("storage_id")))
  767. storageSQ = storageSQ.LeftJoin(readySQ, sqlchemy.Equals(readySQ.Field("storage_id"), storageSQ.Field("id")))
  768. sq := storageSQ.SubQuery()
  769. sqMul := sq.Query(
  770. sq.Field("host_id"),
  771. sq.Field("id"),
  772. sq.Field("used"),
  773. sqlchemy.MUL("virtual_storage_size", sq.Field("storage_capacity"), sq.Field("cmtbound")),
  774. ).SubQuery()
  775. sqSum := sqMul.Query(
  776. sqMul.Field("host_id"),
  777. sqMul.Field("id"),
  778. sqlchemy.SUM("total_used", sqMul.Field("used")),
  779. sqlchemy.SUM("total_virtual_storage_szie", sqMul.Field("virtual_storage_size")),
  780. ).GroupBy(sqMul.Field("host_id")).SubQuery()
  781. sqDiv := sqSum.Query(
  782. sqSum.Field("host_id"),
  783. sqlchemy.DIV("virtual_storage_usage", sqSum.Field("total_used"), sqSum.Field("total_virtual_storage_szie")),
  784. )
  785. usageSQ := sqDiv.GroupBy(sqDiv.Field("host_id")).SubQuery()
  786. q = q.LeftJoin(usageSQ, sqlchemy.Equals(q.Field("id"), usageSQ.Field("host_id")))
  787. db.OrderByFields(q, []string{query.OrderByVirtualStorageUsage}, []sqlchemy.IQueryField{usageSQ.Field("virtual_storage_usage")})
  788. }
  789. return q, nil
  790. }
  791. func (manager *SHostManager) QueryDistinctExtraField(q *sqlchemy.SQuery, field string) (*sqlchemy.SQuery, error) {
  792. var err error
  793. q, err = manager.SEnabledStatusInfrasResourceBaseManager.QueryDistinctExtraField(q, field)
  794. if err == nil {
  795. return q, nil
  796. }
  797. q, err = manager.SManagedResourceBaseManager.QueryDistinctExtraField(q, field)
  798. if err == nil {
  799. return q, nil
  800. }
  801. q, err = manager.SZoneResourceBaseManager.QueryDistinctExtraField(q, field)
  802. if err == nil {
  803. return q, nil
  804. }
  805. return q, httperrors.ErrNotFound
  806. }
  807. func (manager *SHostManager) QueryDistinctExtraFields(q *sqlchemy.SQuery, resource string, fields []string) (*sqlchemy.SQuery, error) {
  808. var err error
  809. q, err = manager.SManagedResourceBaseManager.QueryDistinctExtraFields(q, resource, fields)
  810. if err == nil {
  811. return q, nil
  812. }
  813. return q, httperrors.ErrNotFound
  814. }
  815. func (manager *SHostManager) CustomizeFilterList(ctx context.Context, q *sqlchemy.SQuery, userCred mcclient.TokenCredential, query jsonutils.JSONObject) (*db.CustomizeListFilters, error) {
  816. filters := db.NewCustomizeListFilters()
  817. if query.Contains("cdrom_boot") {
  818. cdromBoot := jsonutils.QueryBoolean(query, "cdrom_boot", false)
  819. cdromBootF := func(obj jsonutils.JSONObject) (bool, error) {
  820. id, err := obj.GetString("id")
  821. if err != nil {
  822. return false, err
  823. }
  824. host := manager.FetchHostById(id)
  825. ipmiInfo, err := host.GetIpmiInfo()
  826. if err != nil {
  827. return false, err
  828. }
  829. if cdromBoot && ipmiInfo.CdromBoot {
  830. return true, nil
  831. }
  832. if !cdromBoot && !ipmiInfo.CdromBoot {
  833. return true, nil
  834. }
  835. return false, nil
  836. }
  837. filters.Append(cdromBootF)
  838. }
  839. return filters, nil
  840. }
  841. func (hh *SHost) IsArmHost() bool {
  842. return hh.CpuArchitecture == apis.OS_ARCH_AARCH64
  843. }
  844. func (hh *SHost) IsRISCVHost() bool {
  845. return hh.CpuArchitecture == apis.OS_ARCH_RISCV64
  846. }
  847. func (hh *SHost) GetZone() (*SZone, error) {
  848. zone, err := ZoneManager.FetchById(hh.ZoneId)
  849. if err != nil {
  850. return nil, err
  851. }
  852. return zone.(*SZone), nil
  853. }
  854. func (hh *SHost) GetRegion() (*SCloudregion, error) {
  855. zones := ZoneManager.Query("cloudregion_id").Equals("id", hh.ZoneId).SubQuery()
  856. q := CloudregionManager.Query().In("id", zones)
  857. ret := &SCloudregion{}
  858. ret.SetModelManager(CloudregionManager, ret)
  859. err := q.First(ret)
  860. if err != nil {
  861. return nil, err
  862. }
  863. return ret, nil
  864. }
  865. func (hh *SHost) GetCpuCount() int {
  866. if hh.CpuReserved > 0 && hh.CpuReserved < hh.CpuCount {
  867. return int(hh.CpuCount - hh.CpuReserved)
  868. } else {
  869. return int(hh.CpuCount)
  870. }
  871. }
  872. func (hh *SHost) GetMemSize() int {
  873. if hh.MemReserved > 0 && hh.MemReserved < hh.MemSize {
  874. return hh.MemSize - hh.MemReserved
  875. } else {
  876. return hh.MemSize
  877. }
  878. }
  879. func (hh *SHost) IsHugePage() bool {
  880. return isHugePage(hh.PageSizeKB)
  881. }
  882. func isHugePage(pageSizeKb int) bool {
  883. return pageSizeKb > 4
  884. }
  885. func (hh *SHost) GetMemoryOvercommitBound() float32 {
  886. if hh.IsHugePage() {
  887. return 1.0
  888. }
  889. if hh.MemCmtbound > 0 {
  890. return hh.MemCmtbound
  891. }
  892. return options.Options.DefaultMemoryOvercommitBound
  893. }
  894. func (hh *SHost) GetVirtualMemorySize() float32 {
  895. return float32(hh.GetMemSize()) * hh.GetMemoryOvercommitBound()
  896. }
  897. func (hh *SHost) GetCPUOvercommitBound() float32 {
  898. if hh.CpuCmtbound > 0 {
  899. return hh.CpuCmtbound
  900. }
  901. return options.Options.DefaultCPUOvercommitBound
  902. }
  903. func (hh *SHost) GetVirtualCPUCount() float32 {
  904. return float32(hh.GetCpuCount()) * hh.GetCPUOvercommitBound()
  905. }
  906. func (hh *SHost) ValidateDeleteCondition(ctx context.Context, info api.HostDetails) error {
  907. if hh.IsBaremetal && hh.HostType != api.HOST_TYPE_BAREMETAL {
  908. return httperrors.NewInvalidStatusError("Host is a converted baremetal, should be unconverted before delete")
  909. }
  910. if hh.GetEnabled() {
  911. return httperrors.NewInvalidStatusError("Host is not disabled")
  912. }
  913. if info.Guests > 0 || info.BackupGuests > 0 {
  914. return httperrors.NewNotEmptyError("Not an empty host")
  915. }
  916. return hh.SEnabledStatusInfrasResourceBase.ValidateDeleteCondition(ctx, nil)
  917. }
  918. func (hh *SHost) validateDeleteCondition(ctx context.Context, purge bool) error {
  919. if !purge && hh.IsBaremetal && hh.HostType != api.HOST_TYPE_BAREMETAL {
  920. return httperrors.NewInvalidStatusError("Host is a converted baremetal, should be unconverted before delete")
  921. }
  922. if hh.GetEnabled() {
  923. return httperrors.NewInvalidStatusError("Host is not disabled")
  924. }
  925. cnt, err := hh.GetGuestCount()
  926. if err != nil {
  927. return httperrors.NewInternalServerError("getGuestCount fail %s", err)
  928. }
  929. if cnt > 0 {
  930. return httperrors.NewNotEmptyError("Not an empty host")
  931. }
  932. cnt, err = hh.GetBackupGuestCount()
  933. if err != nil {
  934. return httperrors.NewInternalServerError("GetBackupGuestCount fail %s", err)
  935. }
  936. if cnt > 0 {
  937. return httperrors.NewNotEmptyError("Not an empty host")
  938. }
  939. for _, hoststorage := range hh.GetHoststorages() {
  940. storage := hoststorage.GetStorage()
  941. if storage != nil && storage.IsLocal() {
  942. cnt, err := storage.GetDiskCount()
  943. if err != nil {
  944. return httperrors.NewInternalServerError("GetDiskCount fail %s", err)
  945. }
  946. if cnt > 0 {
  947. return httperrors.NewNotEmptyError("Local host storage is not empty???")
  948. }
  949. }
  950. }
  951. return hh.SEnabledStatusInfrasResourceBase.ValidateDeleteCondition(ctx, nil)
  952. }
  953. func (hh *SHost) Delete(ctx context.Context, userCred mcclient.TokenCredential) error {
  954. log.Infof("Host delete do nothing")
  955. return nil
  956. }
  957. func (hh *SHost) CustomizeDelete(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) error {
  958. if hh.IsBaremetal {
  959. return hh.StartDeleteBaremetalTask(ctx, userCred, "")
  960. }
  961. return hh.RealDelete(ctx, userCred)
  962. }
  963. func (hh *SHost) StartDeleteBaremetalTask(ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string) error {
  964. task, err := taskman.TaskManager.NewTask(ctx, "BaremetalDeleteTask", hh, userCred, nil, parentTaskId, "", nil)
  965. if err != nil {
  966. return err
  967. }
  968. return task.ScheduleRun(nil)
  969. }
  970. func (hh *SHost) RealDelete(ctx context.Context, userCred mcclient.TokenCredential) error {
  971. return hh.purge(ctx, userCred)
  972. }
  973. func (hh *SHost) GetLoadbalancerBackends() ([]SLoadbalancerBackend, error) {
  974. q := LoadbalancerBackendManager.Query().Equals("backend_id", hh.Id)
  975. ret := []SLoadbalancerBackend{}
  976. return ret, db.FetchModelObjects(LoadbalancerBackendManager, q, &ret)
  977. }
  978. func (hh *SHost) GetHoststoragesQuery() *sqlchemy.SQuery {
  979. return HoststorageManager.Query().Equals("host_id", hh.Id)
  980. }
  981. func (hh *SHost) GetStorageCount() (int, error) {
  982. return hh.GetHoststoragesQuery().CountWithError()
  983. }
  984. func (hh *SHost) GetHoststorages() []SHoststorage {
  985. hoststorages := make([]SHoststorage, 0)
  986. q := hh.GetHoststoragesQuery()
  987. err := db.FetchModelObjects(HoststorageManager, q, &hoststorages)
  988. if err != nil && errors.Cause(err) != sql.ErrNoRows {
  989. log.Errorf("GetHoststorages error %s", err)
  990. return nil
  991. }
  992. return hoststorages
  993. }
  994. func (hh *SHost) GetStorages() ([]SStorage, error) {
  995. sq := HoststorageManager.Query("storage_id").Equals("host_id", hh.Id).SubQuery()
  996. q := StorageManager.Query().In("id", sq)
  997. storages := []SStorage{}
  998. if err := db.FetchModelObjects(StorageManager, q, &storages); err != nil {
  999. return nil, err
  1000. }
  1001. return storages, nil
  1002. }
  1003. func (hh *SHost) GetHoststorageOfId(storageId string) *SHoststorage {
  1004. hoststorage := SHoststorage{}
  1005. hoststorage.SetModelManager(HoststorageManager, &hoststorage)
  1006. err := hh.GetHoststoragesQuery().Equals("storage_id", storageId).First(&hoststorage)
  1007. if err != nil {
  1008. if errors.Cause(err) != sql.ErrNoRows {
  1009. log.Errorf("GetHoststorageOfId fail %s", err)
  1010. }
  1011. return nil
  1012. }
  1013. return &hoststorage
  1014. }
  1015. func (hh *SHost) GetHoststorageByExternalId(extId string) *SHoststorage {
  1016. hoststorage := SHoststorage{}
  1017. hoststorage.SetModelManager(HoststorageManager, &hoststorage)
  1018. hoststorages := HoststorageManager.Query().SubQuery()
  1019. storages := StorageManager.Query().SubQuery()
  1020. q := hoststorages.Query()
  1021. q = q.Join(storages, sqlchemy.Equals(hoststorages.Field("storage_id"), storages.Field("id")))
  1022. q = q.Filter(sqlchemy.Equals(hoststorages.Field("host_id"), hh.Id))
  1023. q = q.Filter(sqlchemy.Equals(storages.Field("external_id"), extId))
  1024. err := q.First(&hoststorage)
  1025. if err != nil {
  1026. if errors.Cause(err) != sql.ErrNoRows {
  1027. log.Errorf("GetHoststorageByExternalId fail %s", err)
  1028. }
  1029. return nil
  1030. }
  1031. return &hoststorage
  1032. }
  1033. func (hh *SHost) GetStorageByFilePath(path string) *SStorage {
  1034. hoststorages := hh.GetHoststorages()
  1035. if hoststorages == nil {
  1036. return nil
  1037. }
  1038. for i := 0; i < len(hoststorages); i += 1 {
  1039. if len(hoststorages[i].MountPoint) > 0 && strings.HasPrefix(path, hoststorages[i].MountPoint) {
  1040. return hoststorages[i].GetStorage()
  1041. }
  1042. }
  1043. return nil
  1044. }
  1045. func (hh *SHost) GetBaremetalstorage() *SHoststorage {
  1046. if !hh.IsBaremetal {
  1047. return nil
  1048. }
  1049. hoststorages := HoststorageManager.Query().SubQuery()
  1050. storages := StorageManager.Query().SubQuery()
  1051. q := hoststorages.Query()
  1052. q = q.Join(storages, sqlchemy.AND(sqlchemy.Equals(storages.Field("id"), hoststorages.Field("storage_id")),
  1053. sqlchemy.IsFalse(storages.Field("deleted"))))
  1054. q = q.Filter(sqlchemy.Equals(storages.Field("storage_type"), api.STORAGE_BAREMETAL))
  1055. q = q.Filter(sqlchemy.Equals(hoststorages.Field("host_id"), hh.Id))
  1056. cnt, err := q.CountWithError()
  1057. if err != nil {
  1058. return nil
  1059. }
  1060. if cnt == 1 {
  1061. hs := SHoststorage{}
  1062. hs.SetModelManager(HoststorageManager, &hs)
  1063. err := q.First(&hs)
  1064. if err != nil {
  1065. log.Errorf("error %s", err)
  1066. return nil
  1067. }
  1068. return &hs
  1069. }
  1070. // log.Errorf("Cannot find baremetalstorage??")
  1071. return nil
  1072. }
  1073. func (hh *SHost) SaveCleanUpdates(doUpdate func() error) (map[string]sqlchemy.SUpdateDiff, error) {
  1074. return hh.saveUpdates(doUpdate, true)
  1075. }
  1076. func (hh *SHost) SaveUpdates(doUpdate func() error) (map[string]sqlchemy.SUpdateDiff, error) {
  1077. return hh.saveUpdates(doUpdate, false)
  1078. }
  1079. func (hh *SHost) saveUpdates(doUpdate func() error, doSchedClean bool) (map[string]sqlchemy.SUpdateDiff, error) {
  1080. diff, err := db.Update(hh, doUpdate)
  1081. if err != nil {
  1082. return nil, err
  1083. }
  1084. if doSchedClean {
  1085. hh.ClearSchedDescCache()
  1086. }
  1087. return diff, nil
  1088. }
  1089. func (hh *SHost) PerformSetCommitBound(
  1090. ctx context.Context,
  1091. userCred mcclient.TokenCredential,
  1092. query jsonutils.JSONObject,
  1093. input api.HostSetCommitBoundInput,
  1094. ) (jsonutils.JSONObject, error) {
  1095. _, err := db.Update(hh, func() error {
  1096. if input.CpuCmtbound != nil {
  1097. hh.CpuCmtbound = *input.CpuCmtbound
  1098. }
  1099. if input.MemCmtbound != nil {
  1100. hh.MemCmtbound = *input.MemCmtbound
  1101. }
  1102. return nil
  1103. })
  1104. if err != nil {
  1105. return nil, err
  1106. }
  1107. db.OpsLog.LogEvent(hh, db.ACT_SET_COMMIT_BOUND, input, userCred)
  1108. logclient.AddActionLogWithContext(ctx, hh, logclient.ACT_SET_COMMIT_BOUND, input, userCred, true)
  1109. return nil, nil
  1110. }
  1111. func (hh *SHost) PerformUpdateStorage(
  1112. ctx context.Context,
  1113. userCred mcclient.TokenCredential,
  1114. query jsonutils.JSONObject,
  1115. data jsonutils.JSONObject,
  1116. ) (jsonutils.JSONObject, error) {
  1117. bs := hh.GetBaremetalstorage()
  1118. capacity, _ := data.Int("capacity")
  1119. zoneId, _ := data.GetString("zone_id")
  1120. storageCacheId, _ := data.GetString("storagecache_id")
  1121. if bs == nil {
  1122. // 1. create storage
  1123. storage := SStorage{}
  1124. storage.Name = fmt.Sprintf("storage%s", hh.GetName())
  1125. storage.Capacity = capacity
  1126. storage.StorageType = api.STORAGE_BAREMETAL
  1127. storage.MediumType = hh.StorageType
  1128. storage.Cmtbound = 1.0
  1129. storage.Status = api.STORAGE_ONLINE
  1130. storage.Enabled = tristate.True
  1131. storage.ZoneId = zoneId
  1132. storage.StoragecacheId = storageCacheId
  1133. storage.DomainId = hh.DomainId
  1134. storage.DomainSrc = string(apis.OWNER_SOURCE_LOCAL)
  1135. err := StorageManager.TableSpec().Insert(ctx, &storage)
  1136. if err != nil {
  1137. return nil, fmt.Errorf("Create baremetal storage error: %v", err)
  1138. }
  1139. storage.SetModelManager(StorageManager, &storage)
  1140. db.OpsLog.LogEvent(&storage, db.ACT_CREATE, storage.GetShortDesc(ctx), userCred)
  1141. // 2. create host storage
  1142. bmStorage := SHoststorage{}
  1143. bmStorage.HostId = hh.Id
  1144. bmStorage.StorageId = storage.Id
  1145. bmStorage.RealCapacity = capacity
  1146. bmStorage.MountPoint = ""
  1147. err = HoststorageManager.TableSpec().Insert(ctx, &bmStorage)
  1148. if err != nil {
  1149. return nil, fmt.Errorf("Create baremetal hostStorage error: %v", err)
  1150. }
  1151. bmStorage.SetModelManager(HoststorageManager, &bmStorage)
  1152. db.OpsLog.LogAttachEvent(ctx, hh, &storage, userCred, bmStorage.GetShortDesc(ctx))
  1153. bmStorage.syncLocalStorageShare(ctx, userCred)
  1154. return nil, nil
  1155. }
  1156. storage := bs.GetStorage()
  1157. //if capacity != int64(storage.Capacity) {
  1158. diff, err := db.Update(storage, func() error {
  1159. storage.Capacity = capacity
  1160. storage.StoragecacheId = storageCacheId
  1161. storage.Enabled = tristate.True
  1162. storage.DomainId = hh.DomainId
  1163. storage.DomainSrc = string(apis.OWNER_SOURCE_LOCAL)
  1164. return nil
  1165. })
  1166. if err != nil {
  1167. return nil, fmt.Errorf("Update baremetal storage error: %v", err)
  1168. }
  1169. db.OpsLog.LogEvent(storage, db.ACT_UPDATE, diff, userCred)
  1170. bs.syncLocalStorageShare(ctx, userCred)
  1171. //}
  1172. return nil, nil
  1173. }
  1174. func (hh *SHost) GetFetchUrl(disableHttps bool) string {
  1175. managerUrl, err := url.Parse(hh.ManagerUri)
  1176. if err != nil {
  1177. log.Errorf("GetFetchUrl fail to parse url: %s", err)
  1178. }
  1179. if disableHttps {
  1180. managerUrl.Scheme = "http"
  1181. }
  1182. portStr := managerUrl.Port()
  1183. var port int
  1184. if len(portStr) > 0 {
  1185. port, _ = strconv.Atoi(portStr)
  1186. } else {
  1187. if managerUrl.Scheme == "https" {
  1188. port = 443
  1189. } else if managerUrl.Scheme == "http" {
  1190. port = 80
  1191. }
  1192. }
  1193. return fmt.Sprintf("%s://%s", managerUrl.Scheme, net.JoinHostPort(managerUrl.Hostname(), strconv.Itoa(port+40000)))
  1194. }
  1195. func (hh *SHost) GetAttachedEnabledHostStorages(storageType []string) []SStorage {
  1196. return hh._getAttachedStorages(tristate.False, tristate.True, storageType)
  1197. }
  1198. func (hh *SHost) _getAttachedStorages(isBaremetal tristate.TriState, enabled tristate.TriState, storageType []string) []SStorage {
  1199. storages := StorageManager.Query().SubQuery()
  1200. hoststorages := HoststorageManager.Query().SubQuery()
  1201. q := storages.Query()
  1202. q = q.Join(hoststorages, sqlchemy.Equals(storages.Field("id"), hoststorages.Field("storage_id")))
  1203. if enabled.IsTrue() {
  1204. q = q.IsTrue("enabled")
  1205. } else if enabled.IsFalse() {
  1206. q = q.IsFalse("enabled")
  1207. }
  1208. if isBaremetal.IsTrue() {
  1209. q = q.Equals("storage_type", api.STORAGE_BAREMETAL)
  1210. } else if isBaremetal.IsFalse() {
  1211. q = q.NotEquals("storage_type", api.STORAGE_BAREMETAL)
  1212. }
  1213. if len(storageType) > 0 {
  1214. q = q.In("storage_type", storageType)
  1215. }
  1216. q = q.Filter(sqlchemy.Equals(hoststorages.Field("host_id"), hh.Id))
  1217. ret := make([]SStorage, 0)
  1218. err := db.FetchModelObjects(StorageManager, q, &ret)
  1219. if err != nil {
  1220. log.Errorf("GetAttachedStorages fail %s", err)
  1221. return nil
  1222. }
  1223. return ret
  1224. }
  1225. func (hh *SHost) SyncAttachedStorageStatus(ctx context.Context) {
  1226. storages := hh.GetAttachedEnabledHostStorages(nil)
  1227. if storages != nil {
  1228. for _, storage := range storages {
  1229. storage.SyncStatusWithHosts(ctx)
  1230. }
  1231. hh.ClearSchedDescCache()
  1232. }
  1233. }
  1234. func (hh *SHostManager) IsNewNameUnique(name string, userCred mcclient.TokenCredential, kwargs *jsonutils.JSONDict) (bool, error) {
  1235. q := hh.Query().Equals("name", name)
  1236. if kwargs != nil && kwargs.Contains("zone_id") {
  1237. zoneId, _ := kwargs.GetString("zone_id")
  1238. q.Equals("zone_id", zoneId)
  1239. }
  1240. cnt, err := q.CountWithError()
  1241. if err != nil {
  1242. return false, err
  1243. }
  1244. return cnt == 0, nil
  1245. }
  1246. func (hh *SHostManager) GetPropertyK8sMasterNodeIps(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) (jsonutils.JSONObject, error) {
  1247. cli, err := tokens.GetCoreClient()
  1248. if err != nil {
  1249. return nil, errors.Wrap(err, "get k8s client")
  1250. }
  1251. nodes, err := cli.Nodes().List(context.Background(), metav1.ListOptions{
  1252. LabelSelector: "node-role.kubernetes.io/master",
  1253. })
  1254. if err != nil {
  1255. return nil, errors.Wrap(err, "list master nodes")
  1256. }
  1257. ips := make([]string, 0)
  1258. for i := range nodes.Items {
  1259. for j := range nodes.Items[i].Status.Addresses {
  1260. if nodes.Items[i].Status.Addresses[j].Type == v1.NodeInternalIP {
  1261. ips = append(ips, nodes.Items[i].Status.Addresses[j].Address)
  1262. }
  1263. }
  1264. }
  1265. log.Infof("k8s master nodes ips %v", ips)
  1266. res := jsonutils.NewDict()
  1267. res.Set("ips", jsonutils.Marshal(ips))
  1268. return res, nil
  1269. }
  1270. func (hh *SHostManager) GetPropertyBmStartRegisterScript(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) (jsonutils.JSONObject, error) {
  1271. regionUri, err := auth.GetPublicServiceURL(consts.GetServiceType(), options.Options.Region, "", httputils.POST)
  1272. if err != nil {
  1273. return nil, err
  1274. }
  1275. var script string
  1276. script += fmt.Sprintf("curl -k -fsSL -H 'X-Auth-Token: %s' %s/misc/bm-prepare-script", userCred.GetTokenString(), regionUri)
  1277. res := jsonutils.NewDict()
  1278. res.Add(jsonutils.NewString(script), "script")
  1279. return res, nil
  1280. }
  1281. func (hh *SHostManager) GetPropertyNodeCount(ctx context.Context, userCred mcclient.TokenCredential, query api.HostListInput) (jsonutils.JSONObject, error) {
  1282. hosts := hh.Query().SubQuery()
  1283. q := hosts.Query(hosts.Field("host_type"), sqlchemy.SUM("node_count_total", hosts.Field("node_count")))
  1284. return hh.getCount(ctx, userCred, q, query)
  1285. }
  1286. func (hh *SHostManager) getCount(ctx context.Context, userCred mcclient.TokenCredential, q *sqlchemy.SQuery, query api.HostListInput) (jsonutils.JSONObject, error) {
  1287. filterAny := false
  1288. if query.FilterAny != nil {
  1289. filterAny = *query.FilterAny
  1290. }
  1291. q, err := db.ApplyListItemsGeneralFilters(hh, q, userCred, query.Filter, filterAny)
  1292. if err != nil {
  1293. return nil, err
  1294. }
  1295. q, err = hh.ListItemFilter(ctx, q, userCred, query)
  1296. if err != nil {
  1297. return nil, err
  1298. }
  1299. rows, err := q.GroupBy("host_type").Rows()
  1300. if err != nil {
  1301. return nil, err
  1302. }
  1303. ret := jsonutils.NewDict()
  1304. defer rows.Close()
  1305. for rows.Next() {
  1306. var hostType string
  1307. var count int64
  1308. err = rows.Scan(&hostType, &count)
  1309. if err != nil {
  1310. log.Errorf("getCount scan err: %v", err)
  1311. return ret, nil
  1312. }
  1313. ret.Add(jsonutils.NewInt(count), hostType)
  1314. }
  1315. return ret, nil
  1316. }
  1317. func (hh *SHostManager) GetPropertyHostTypeCount(ctx context.Context, userCred mcclient.TokenCredential, query api.HostListInput) (jsonutils.JSONObject, error) {
  1318. hosts := hh.Query().SubQuery()
  1319. // select host_type, (case host_type when 'huaweicloudstack' then count(DISTINCT external_id) else count(id) end) as count from hosts_tbl group by host_type;
  1320. cs := sqlchemy.NewCase()
  1321. hcso := sqlchemy.Equals(hosts.Field("host_type"), api.HOST_TYPE_HCSO)
  1322. cs.When(hcso, sqlchemy.COUNT("", sqlchemy.DISTINCT("", hosts.Field("external_id"))))
  1323. cs.Else(sqlchemy.COUNT("", hosts.Field("id")))
  1324. q := hosts.Query(hosts.Field("host_type"), sqlchemy.NewFunction(cs, "count", true))
  1325. return hh.getCount(ctx, userCred, q, query)
  1326. }
  1327. func (hh *SHostManager) ClearAllSchedDescCache() error {
  1328. return hh.ClearSchedDescSessionCache("", "")
  1329. }
  1330. func (hh *SHostManager) ClearSchedDescCache(hostId string) error {
  1331. return hh.ClearSchedDescSessionCache(hostId, "")
  1332. }
  1333. func (hh *SHostManager) ClearSchedDescSessionCache(hostId, sessionId string) error {
  1334. s := auth.GetAdminSession(context.Background(), options.Options.Region)
  1335. return scheduler.SchedManager.CleanCache(s, hostId, sessionId, false)
  1336. }
  1337. func (hh *SHost) ClearSchedDescCache() error {
  1338. return hh.ClearSchedDescSessionCache("")
  1339. }
  1340. func (hh *SHost) ClearSchedDescSessionCache(sessionId string) error {
  1341. return HostManager.ClearSchedDescSessionCache(hh.Id, sessionId)
  1342. }
  1343. // sync clear sched desc on scheduler side
  1344. func (hh *SHostManager) SyncClearSchedDescSessionCache(hostId, sessionId string) error {
  1345. s := auth.GetAdminSession(context.Background(), options.Options.Region)
  1346. return scheduler.SchedManager.CleanCache(s, hostId, sessionId, true)
  1347. }
  1348. func (hh *SHost) SyncCleanSchedDescCache() error {
  1349. return hh.SyncClearSchedDescSessionCache("")
  1350. }
  1351. func (hh *SHost) SyncClearSchedDescSessionCache(sessionId string) error {
  1352. return HostManager.SyncClearSchedDescSessionCache(hh.Id, sessionId)
  1353. }
  1354. func (hh *SHost) GetDetailsSpec(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) (jsonutils.JSONObject, error) {
  1355. return GetModelSpec(HostManager, hh)
  1356. }
  1357. func (man *SHostManager) GetSpecShouldCheckStatus(query *jsonutils.JSONDict) (bool, error) {
  1358. statusCheck := true
  1359. if query.Contains("is_empty") {
  1360. isEmpty, err := query.Bool("is_empty")
  1361. if err != nil {
  1362. return statusCheck, err
  1363. }
  1364. if !isEmpty {
  1365. statusCheck = false
  1366. }
  1367. }
  1368. return statusCheck, nil
  1369. }
  1370. func (hh *SHost) GetSpec(statusCheck bool) *jsonutils.JSONDict {
  1371. if statusCheck {
  1372. if !hh.GetEnabled() {
  1373. return nil
  1374. }
  1375. if !utils.IsInStringArray(hh.Status, []string{api.BAREMETAL_RUNNING, api.BAREMETAL_READY}) || hh.GetBaremetalServer() != nil || hh.IsMaintenance {
  1376. return nil
  1377. }
  1378. if hh.MemSize == 0 || hh.CpuCount == 0 {
  1379. return nil
  1380. }
  1381. if hh.ResourceType == api.HostResourceTypePrepaidRecycle {
  1382. cnt, err := hh.GetGuestCount()
  1383. if err != nil {
  1384. return nil
  1385. }
  1386. if cnt > 0 {
  1387. // occupied
  1388. return nil
  1389. }
  1390. }
  1391. if len(hh.ManagerId) > 0 {
  1392. providerObj, _ := CloudproviderManager.FetchById(hh.ManagerId)
  1393. if providerObj == nil {
  1394. return nil
  1395. }
  1396. provider := providerObj.(*SCloudprovider)
  1397. if !provider.IsAvailable() {
  1398. return nil
  1399. }
  1400. }
  1401. }
  1402. spec := hh.GetHardwareSpecification()
  1403. specInfo := new(api.HostSpec)
  1404. if err := spec.Unmarshal(specInfo); err != nil {
  1405. return spec
  1406. }
  1407. nifs := hh.GetAllNetInterfaces()
  1408. var nicCount int
  1409. for _, nif := range nifs {
  1410. if nif.NicType != api.NIC_TYPE_IPMI {
  1411. nicCount++
  1412. }
  1413. }
  1414. specInfo.NicCount = nicCount
  1415. var manufacture string
  1416. var model string
  1417. if hh.SysInfo != nil {
  1418. manufacture, _ = hh.SysInfo.GetString("manufacture")
  1419. model, _ = hh.SysInfo.GetString("model")
  1420. }
  1421. if manufacture == "" {
  1422. manufacture = "Unknown"
  1423. }
  1424. if model == "" {
  1425. model = "Unknown"
  1426. }
  1427. specInfo.Manufacture = strings.ReplaceAll(manufacture, " ", "_")
  1428. specInfo.Model = strings.ReplaceAll(model, " ", "_")
  1429. devices := IsolatedDeviceManager.FindByHost(hh.Id)
  1430. if len(devices) > 0 {
  1431. specInfo.IsolatedDevices = make([]api.IsolatedDeviceSpec, len(devices))
  1432. for i := 0; i < len(devices); i++ {
  1433. specInfo.IsolatedDevices[i].DevType = devices[i].DevType
  1434. specInfo.IsolatedDevices[i].Model = devices[i].Model
  1435. specInfo.IsolatedDevices[i].PciId = devices[i].VendorDeviceId
  1436. specInfo.IsolatedDevices[i].Vendor = devices[i].getVendor()
  1437. }
  1438. }
  1439. return specInfo.JSON(specInfo)
  1440. }
  1441. func (manager *SHostManager) GetSpecIdent(input *jsonutils.JSONDict) []string {
  1442. spec := new(api.HostSpec)
  1443. input.Unmarshal(spec)
  1444. specKeys := []string{
  1445. fmt.Sprintf("cpu:%d", spec.Cpu),
  1446. fmt.Sprintf("mem:%dM", spec.Mem),
  1447. fmt.Sprintf("nic:%d", spec.NicCount),
  1448. fmt.Sprintf("manufacture:%s", spec.Manufacture),
  1449. fmt.Sprintf("model:%s", spec.Model),
  1450. }
  1451. diskDriverSpec := spec.Disk
  1452. if diskDriverSpec != nil {
  1453. for driver, driverSpec := range diskDriverSpec {
  1454. specKeys = append(specKeys, parseDiskDriverSpec(driver, driverSpec)...)
  1455. }
  1456. }
  1457. sort.Strings(specKeys)
  1458. return specKeys
  1459. }
  1460. func parseDiskDriverSpec(driver string, adapterSpecs api.DiskAdapterSpec) []string {
  1461. ret := make([]string, 0)
  1462. for adapterKey, adapterSpec := range adapterSpecs {
  1463. for _, diskSpec := range adapterSpec {
  1464. sizeGB, _ := utils.GetSizeGB(fmt.Sprintf("%d", diskSpec.Size), "M")
  1465. diskKey := fmt.Sprintf("disk:%s_%s_%s_%dGx%d", driver, adapterKey, diskSpec.Type, sizeGB, diskSpec.Count)
  1466. ret = append(ret, diskKey)
  1467. }
  1468. }
  1469. return ret
  1470. }
  1471. func ConvertStorageInfo2BaremetalStorages(storageInfo jsonutils.JSONObject) []*baremetal.BaremetalStorage {
  1472. if storageInfo == nil {
  1473. return nil
  1474. }
  1475. storages := []baremetal.BaremetalStorage{}
  1476. err := storageInfo.Unmarshal(&storages)
  1477. if err != nil {
  1478. log.Errorf("Unmarshal to baremetal storage error: %v", err)
  1479. return nil
  1480. }
  1481. ret := make([]*baremetal.BaremetalStorage, len(storages))
  1482. for i := range storages {
  1483. ret[i] = &storages[i]
  1484. }
  1485. return ret
  1486. }
  1487. func GetDiskSpecV2(storageInfo jsonutils.JSONObject) api.DiskDriverSpec {
  1488. refStorages := ConvertStorageInfo2BaremetalStorages(storageInfo)
  1489. if refStorages == nil {
  1490. return nil
  1491. }
  1492. return baremetal.GetDiskSpecV2(refStorages)
  1493. }
  1494. func (hh *SHost) GetHardwareSpecification() *jsonutils.JSONDict {
  1495. spec := &api.HostSpec{
  1496. Cpu: int(hh.CpuCount),
  1497. Mem: hh.MemSize,
  1498. }
  1499. if hh.StorageInfo != nil {
  1500. spec.Disk = GetDiskSpecV2(hh.StorageInfo)
  1501. spec.Driver = hh.StorageDriver
  1502. }
  1503. ret := spec.JSON(spec)
  1504. if hh.StorageInfo != nil {
  1505. ret.Set("storage_info", hh.StorageInfo)
  1506. }
  1507. return ret
  1508. }
  1509. type SStorageCapacity struct {
  1510. Capacity int64 `json:"capacity,omitzero"`
  1511. Used int64 `json:"used_capacity,omitzero"`
  1512. ActualUsed int64 `json:"real_time_used_capacity,omitzero"`
  1513. Wasted int64 `json:"waste_capacity,omitzero"`
  1514. VCapacity int64 `json:"virtual_capacity,omitzero"`
  1515. }
  1516. func (cap *SStorageCapacity) GetFree() int64 {
  1517. return cap.VCapacity - cap.Used - cap.Wasted
  1518. }
  1519. func (cap *SStorageCapacity) GetCommitRate() float64 {
  1520. if cap.Capacity > 0 {
  1521. return float64(int(float64(cap.Used)*100.0/float64(cap.Capacity)+0.5)) / 100.0
  1522. } else {
  1523. return 0.0
  1524. }
  1525. }
  1526. func (cap *SStorageCapacity) Add(cap2 SStorageCapacity) {
  1527. cap.Capacity += cap2.Capacity
  1528. cap.Used += cap2.Used
  1529. cap.Wasted += cap2.Wasted
  1530. cap.VCapacity += cap2.VCapacity
  1531. cap.ActualUsed += cap2.ActualUsed
  1532. }
  1533. func (cap *SStorageCapacity) toCapacityInfo() api.SStorageCapacityInfo {
  1534. info := api.SStorageCapacityInfo{}
  1535. info.UsedCapacity = cap.Used
  1536. info.WasteCapacity = cap.Wasted
  1537. info.VirtualCapacity = cap.VCapacity
  1538. info.CommitRate = cap.GetCommitRate()
  1539. info.FreeCapacity = cap.GetFree()
  1540. return info
  1541. }
  1542. func (hh *SHost) GetAttachedLocalStorageCapacity() SStorageCapacity {
  1543. ret := SStorageCapacity{}
  1544. storages := hh.GetAttachedEnabledHostStorages(api.HOST_STORAGE_LOCAL_TYPES)
  1545. for _, s := range storages {
  1546. ret.Add(s.getStorageCapacity())
  1547. }
  1548. return ret
  1549. }
  1550. func (hh *SHost) GetAttachedLocalStorages() []SStorage {
  1551. return hh.GetAttachedEnabledHostStorages(api.HOST_STORAGE_LOCAL_TYPES)
  1552. }
  1553. func _getLeastUsedStorage(storages []SStorage, backends []string) *SStorage {
  1554. var best *SStorage
  1555. var bestCap int64
  1556. for i := 0; i < len(storages); i++ {
  1557. s := storages[i]
  1558. if len(backends) > 0 {
  1559. in, _ := utils.InStringArray(s.StorageType, backends)
  1560. if !in {
  1561. continue
  1562. }
  1563. }
  1564. capa := s.GetFreeCapacity()
  1565. if best == nil || bestCap < capa {
  1566. bestCap = capa
  1567. best = &s
  1568. }
  1569. }
  1570. return best
  1571. }
  1572. func ChooseLeastUsedStorage(storages []SStorage, backend string) *SStorage {
  1573. var backends []string
  1574. if backend == api.STORAGE_LOCAL {
  1575. backends = []string{api.STORAGE_NAS, api.STORAGE_LOCAL}
  1576. } else if len(backend) > 0 {
  1577. backends = []string{backend}
  1578. } else {
  1579. backends = []string{}
  1580. }
  1581. return _getLeastUsedStorage(storages, backends)
  1582. }
  1583. func (hh *SHost) GetLeastUsedStorage(backend string) *SStorage {
  1584. storages := hh.GetAttachedEnabledHostStorages(nil)
  1585. if storages != nil {
  1586. return ChooseLeastUsedStorage(storages, backend)
  1587. }
  1588. return nil
  1589. }
  1590. /*func (hh *SHost) GetWiresQuery() *sqlchemy.SQuery {
  1591. return Manager.Query().Equals("host_id", hh.Id)
  1592. }
  1593. func (hh *SHost) GetWireCount() (int, error) {
  1594. return hh.GetWiresQuery().CountWithError()
  1595. }
  1596. func (hh *SHost) GetHostwires() []SHostwire {
  1597. hw := make([]SHostwire, 0)
  1598. q := hh.GetWiresQuery()
  1599. err := db.FetchModelObjects(HostwireManager, q, &hw)
  1600. if err != nil {
  1601. log.Errorf("GetWires error %s", err)
  1602. return nil
  1603. }
  1604. return hw
  1605. }*/
  1606. func (hh *SHost) getAttachedWires() []SWire {
  1607. wires := WireManager.Query().SubQuery()
  1608. netifs := NetInterfaceManager.Query().SubQuery()
  1609. q := wires.Query()
  1610. q = q.Join(netifs, sqlchemy.Equals(netifs.Field("wire_id"), wires.Field("id")))
  1611. q = q.Filter(sqlchemy.Equals(netifs.Field("baremetal_id"), hh.Id))
  1612. q = q.Distinct()
  1613. ret := make([]SWire, 0)
  1614. err := db.FetchModelObjects(WireManager, q, &ret)
  1615. if err != nil {
  1616. log.Errorf("%s", err)
  1617. return nil
  1618. }
  1619. return ret
  1620. }
  1621. func (hh *SHostManager) GetEnabledKvmHostForBackupStorage(bs *SBackupStorage) (*SHost, error) {
  1622. hbs, err := HostBackupstorageManager.GetBackupStoragesByBackup(bs.Id)
  1623. if err != nil {
  1624. return nil, errors.Wrap(err, "GetBackupStoragesByBackup")
  1625. }
  1626. candidates := make([]string, 0)
  1627. for i := range hbs {
  1628. candidates = append(candidates, hbs[i].HostId)
  1629. }
  1630. host, err := HostManager.GetEnabledKvmHost(candidates)
  1631. if err != nil {
  1632. return nil, errors.Wrap(err, "GetEnabledKvmHost")
  1633. }
  1634. return host, nil
  1635. }
  1636. func (hh *SHostManager) GetEnabledKvmHostForDiskBackup(backup *SDiskBackup) (*SHost, error) {
  1637. hbsCandidates := stringutils2.NewSortedStrings(nil)
  1638. hssCandidates := stringutils2.NewSortedStrings(nil)
  1639. var candidates []string
  1640. {
  1641. bs, err := backup.GetBackupStorage()
  1642. if err != nil {
  1643. return nil, errors.Wrap(err, "unable to get backupStorage")
  1644. }
  1645. hbs, err := HostBackupstorageManager.GetBackupStoragesByBackup(bs.Id)
  1646. if err != nil {
  1647. return nil, errors.Wrap(err, "HostBackupstorageManager.GetBackupStoragesByBackup")
  1648. }
  1649. for i := range hbs {
  1650. hbsCandidates = hbsCandidates.Append(hbs[i].HostId)
  1651. }
  1652. }
  1653. if len(backup.StorageId) > 0 {
  1654. storage, err := backup.GetStorage()
  1655. if err != nil {
  1656. return nil, errors.Wrap(err, "unable to get storage of diskbackup")
  1657. }
  1658. hss, err := HoststorageManager.GetHostStoragesByStorageId(storage.Id)
  1659. if err != nil {
  1660. return nil, errors.Wrap(err, "HoststorageManager.GetStorages")
  1661. }
  1662. for i := range hss {
  1663. hssCandidates = hssCandidates.Append(hss[i].HostId)
  1664. }
  1665. if len(hbsCandidates) == 0 {
  1666. candidates = []string(hssCandidates)
  1667. } else {
  1668. candidates = []string(stringutils2.Intersect(hbsCandidates, hssCandidates))
  1669. }
  1670. } else {
  1671. candidates = []string(hbsCandidates)
  1672. }
  1673. host, err := HostManager.GetEnabledKvmHost(candidates)
  1674. if err != nil {
  1675. return nil, errors.Wrap(err, "GetEnabledKvmHost")
  1676. }
  1677. return host, nil
  1678. }
  1679. func (hh *SHostManager) GetEnabledKvmHost(candidates []string) (*SHost, error) {
  1680. hostq := HostManager.Query().IsTrue("enabled")
  1681. hostq = hostq.Equals("host_status", api.HOST_ONLINE)
  1682. hostq = hostq.In("host_type", []string{api.HOST_TYPE_HYPERVISOR, api.HOST_TYPE_KVM, api.HOST_TYPE_CONTAINER})
  1683. hostq = hostq.IsNullOrEmpty("manager_id")
  1684. if len(candidates) > 0 {
  1685. hostq = hostq.In("id", candidates)
  1686. }
  1687. host := SHost{}
  1688. err := hostq.First(&host)
  1689. if err != nil {
  1690. return nil, err
  1691. }
  1692. host.SetModelManager(HostManager, &host)
  1693. return &host, nil
  1694. }
  1695. func (hh *SHost) GetMasterWire() *SWire {
  1696. wires := WireManager.Query().SubQuery()
  1697. netifs := NetInterfaceManager.Query().SubQuery()
  1698. q := wires.Query()
  1699. q = q.Join(netifs, sqlchemy.Equals(netifs.Field("wire_id"), wires.Field("id")))
  1700. q = q.Filter(sqlchemy.Equals(netifs.Field("baremetal_id"), hh.Id))
  1701. q = q.Filter(sqlchemy.Equals(netifs.Field("nic_type"), api.NIC_TYPE_ADMIN))
  1702. wire := SWire{}
  1703. wire.SetModelManager(WireManager, &wire)
  1704. err := q.First(&wire)
  1705. if err != nil {
  1706. log.Errorf("GetMasterWire fail %s", err)
  1707. return nil
  1708. }
  1709. return &wire
  1710. }
  1711. /*func (hh *SHost) getHostwires() ([]SHostwire, error) {
  1712. hostwires := make([]SHostwire, 0)
  1713. q := hh.GetWiresQuery()
  1714. err := db.FetchModelObjects(HostwireManager, q, &hostwires)
  1715. if err != nil {
  1716. return nil, err
  1717. }
  1718. return hostwires, nil
  1719. }
  1720. func (hh *SHost) getHostwiresOfId(wireId string) []SHostwire {
  1721. hostwires := make([]SHostwire, 0)
  1722. q := hh.GetWiresQuery().Equals("wire_id", wireId)
  1723. err := db.FetchModelObjects(HostwireManager, q, &hostwires)
  1724. if err != nil {
  1725. log.Errorf("getHostwiresOfId fail %s", err)
  1726. return nil
  1727. }
  1728. return hostwires
  1729. }
  1730. func (hh *SHost) getHostwireOfIdAndMac(wireId string, mac string) *SHostwire {
  1731. hostwire := SHostwire{}
  1732. hostwire.SetModelManager(HostwireManager, &hostwire)
  1733. q := hh.GetWiresQuery().Equals("wire_id", wireId)
  1734. q = q.Equals("mac_addr", mac)
  1735. err := q.First(&hostwire)
  1736. if err != nil {
  1737. log.Errorf("getHostwireOfIdAndMac fail %s", err)
  1738. return nil
  1739. }
  1740. return &hostwire
  1741. }*/
  1742. func (hh *SHost) GetGuestsQuery() *sqlchemy.SQuery {
  1743. return GuestManager.Query().Equals("host_id", hh.Id)
  1744. }
  1745. func (hh *SHost) GetGuests() ([]SGuest, error) {
  1746. q := hh.GetGuestsQuery()
  1747. guests := make([]SGuest, 0)
  1748. err := db.FetchModelObjects(GuestManager, q, &guests)
  1749. if err != nil {
  1750. return nil, errors.Wrapf(err, "db.FetchModelObjects")
  1751. }
  1752. return guests, nil
  1753. }
  1754. func (hh *SHost) GetKvmGuests() []SGuest {
  1755. q := GuestManager.Query().Equals("host_id", hh.Id).Equals("hypervisor", api.HYPERVISOR_KVM)
  1756. guests := make([]SGuest, 0)
  1757. err := db.FetchModelObjects(GuestManager, q, &guests)
  1758. if err != nil {
  1759. log.Errorf("GetGuests %s", err)
  1760. return nil
  1761. }
  1762. return guests
  1763. }
  1764. func (hh *SHost) GetGuestsMasterOnThisHost() []SGuest {
  1765. q := hh.GetGuestsQuery().IsNotEmpty("backup_host_id")
  1766. guests := make([]SGuest, 0)
  1767. err := db.FetchModelObjects(GuestManager, q, &guests)
  1768. if err != nil {
  1769. log.Errorf("GetGuests %s", err)
  1770. return nil
  1771. }
  1772. return guests
  1773. }
  1774. func (hh *SHost) GetGuestsBackupOnThisHost() []SGuest {
  1775. q := GuestManager.Query().Equals("backup_host_id", hh.Id)
  1776. guests := make([]SGuest, 0)
  1777. err := db.FetchModelObjects(GuestManager, q, &guests)
  1778. if err != nil {
  1779. log.Errorf("GetGuests %s", err)
  1780. return nil
  1781. }
  1782. return guests
  1783. }
  1784. func (hh *SHost) GetBackupGuestCount() (int, error) {
  1785. q := GuestManager.Query().Equals("backup_host_id", hh.Id)
  1786. return q.CountWithError()
  1787. }
  1788. func (hh *SHost) GetGuestCount() (int, error) {
  1789. q := hh.GetGuestsQuery()
  1790. return q.CountWithError()
  1791. }
  1792. func (hh *SHost) GetContainerCount(status []string) (int, error) {
  1793. q := hh.GetGuestsQuery()
  1794. q = q.Filter(sqlchemy.Equals(q.Field("hypervisor"), api.HYPERVISOR_POD))
  1795. if len(status) > 0 {
  1796. q = q.In("status", status)
  1797. }
  1798. return q.CountWithError()
  1799. }
  1800. func (hh *SHost) GetNonsystemGuestCount() (int, error) {
  1801. q := hh.GetGuestsQuery()
  1802. q = q.Filter(sqlchemy.OR(sqlchemy.IsNull(q.Field("is_system")), sqlchemy.IsFalse(q.Field("is_system"))))
  1803. return q.CountWithError()
  1804. }
  1805. func (hh *SHost) GetRunningGuestCount() (int, error) {
  1806. q := hh.GetGuestsQuery()
  1807. q = q.In("status", api.VM_RUNNING_STATUS)
  1808. return q.CountWithError()
  1809. }
  1810. func (host *SHost) hasUnknownGuests() bool {
  1811. q := host.GetGuestsQuery()
  1812. q = q.Equals("status", api.VM_UNKNOWN)
  1813. cnt, _ := q.CountWithError()
  1814. return cnt > 0
  1815. }
  1816. func (hh *SHost) GetNotReadyGuestsStat() (*SHostGuestResourceUsage, error) {
  1817. guests := GuestManager.Query().SubQuery()
  1818. q := guests.Query(sqlchemy.COUNT("guest_count"),
  1819. sqlchemy.SUM("guest_vcpu_count", guests.Field("vcpu_count")),
  1820. sqlchemy.SUM("guest_vmem_size", guests.Field("vmem_size")))
  1821. cond := sqlchemy.OR(sqlchemy.Equals(q.Field("host_id"), hh.Id),
  1822. sqlchemy.Equals(q.Field("backup_host_id"), hh.Id))
  1823. q = q.Filter(cond)
  1824. q = q.NotEquals("status", api.VM_READY)
  1825. stat := SHostGuestResourceUsage{}
  1826. err := q.First(&stat)
  1827. if err != nil {
  1828. return nil, err
  1829. }
  1830. return &stat, nil
  1831. }
  1832. func (hh *SHost) GetRunningGuestResourceUsage() *SHostGuestResourceUsage {
  1833. return hh.getGuestsResource(api.VM_RUNNING)
  1834. }
  1835. func (hh *SHost) GetBaremetalnetworksQuery() *sqlchemy.SQuery {
  1836. return HostnetworkManager.Query().Equals("baremetal_id", hh.Id)
  1837. }
  1838. func (hh *SHost) GetBaremetalnetworks() []SHostnetwork {
  1839. q := hh.GetBaremetalnetworksQuery()
  1840. hns := make([]SHostnetwork, 0)
  1841. err := db.FetchModelObjects(HostnetworkManager, q, &hns)
  1842. if err != nil {
  1843. log.Errorf("GetBaremetalnetworks error: %s", err)
  1844. }
  1845. return hns
  1846. }
  1847. func (hh *SHost) GetAttach2Network(netId string) *SHostnetwork {
  1848. q := hh.GetBaremetalnetworksQuery()
  1849. netifs := NetInterfaceManager.Query().Equals("baremetal_id", hh.Id)
  1850. netifs = netifs.Filter(sqlchemy.OR(
  1851. sqlchemy.IsNullOrEmpty(netifs.Field("nic_type")),
  1852. sqlchemy.NotEquals(netifs.Field("nic_type"), api.NIC_TYPE_IPMI),
  1853. ))
  1854. netifsSub := netifs.SubQuery()
  1855. q = q.Join(netifsSub, sqlchemy.AND(
  1856. sqlchemy.Equals(q.Field("mac_addr"), netifsSub.Field("mac")),
  1857. sqlchemy.Equals(q.Field("vlan_id"), netifsSub.Field("vlan_id")),
  1858. ))
  1859. q = q.Equals("network_id", netId)
  1860. hn := SHostnetwork{}
  1861. hn.SetModelManager(HostnetworkManager, &hn)
  1862. err := q.First(&hn)
  1863. if err != nil {
  1864. log.Errorf("GetAttach2Network fail %s", err)
  1865. return nil
  1866. }
  1867. return &hn
  1868. }
  1869. func (h *SHost) getNetInterfacesInternal(wireId string, nicTypes []compute.TNicType) []SNetInterface {
  1870. q := NetInterfaceManager.Query().Equals("baremetal_id", h.Id)
  1871. if len(wireId) > 0 {
  1872. q = q.Equals("wire_id", wireId)
  1873. }
  1874. if len(nicTypes) > 0 {
  1875. //q.IsNullOrEmpty()
  1876. if ok, _ := utils.InArray(compute.NIC_TYPE_NORMAL, nicTypes); ok {
  1877. q = q.Filter(sqlchemy.OR(sqlchemy.In(q.Field("nic_type"), nicTypes), sqlchemy.IsNull(q.Field("nic_type"))))
  1878. } else {
  1879. q = q.In("nic_type", nicTypes)
  1880. }
  1881. }
  1882. q = q.Asc("index")
  1883. q = q.Asc("vlan_id")
  1884. q = q.Asc("nic_type")
  1885. netifs := make([]SNetInterface, 0)
  1886. err := db.FetchModelObjects(NetInterfaceManager, q, &netifs)
  1887. if err != nil {
  1888. log.Errorf("GetNetInterfaces fail %s", err)
  1889. return nil
  1890. }
  1891. return netifs
  1892. }
  1893. func (hh *SHost) GetAllNetInterfaces() []SNetInterface {
  1894. return hh.getNetInterfacesInternal("", nil)
  1895. }
  1896. func (hh *SHost) GetHostNetInterfaces() []SNetInterface {
  1897. return hh.getNetInterfacesInternal("", api.HOST_NIC_TYPES)
  1898. }
  1899. func (hh *SHost) GetAdminNetInterfaces() []SNetInterface {
  1900. return hh.getNetInterfacesInternal("", []compute.TNicType{api.NIC_TYPE_ADMIN})
  1901. }
  1902. func (hh *SHost) GetNetInterface(mac string, vlanId int) *SNetInterface {
  1903. netif, _ := NetInterfaceManager.FetchByMacVlan(mac, vlanId)
  1904. if netif != nil && netif.BaremetalId == hh.Id {
  1905. return netif
  1906. }
  1907. return nil
  1908. }
  1909. func (hh *SHost) DeleteBaremetalnetwork(ctx context.Context, userCred mcclient.TokenCredential, bn *SHostnetwork, reserve bool) {
  1910. net := bn.GetNetwork()
  1911. bn.Delete(ctx, userCred)
  1912. db.OpsLog.LogDetachEvent(ctx, hh, net, userCred, nil)
  1913. if reserve && net != nil {
  1914. if len(bn.IpAddr) > 0 && regutils.MatchIP4Addr(bn.IpAddr) {
  1915. ReservedipManager.ReserveIP(ctx, userCred, net, bn.IpAddr, "Delete baremetalnetwork to reserve", api.AddressTypeIPv4)
  1916. }
  1917. if len(bn.Ip6Addr) > 0 && regutils.MatchIP6Addr(bn.Ip6Addr) {
  1918. ReservedipManager.ReserveIP(ctx, userCred, net, bn.Ip6Addr, "Delete baremetalnetwork to reserve", api.AddressTypeIPv6)
  1919. }
  1920. }
  1921. }
  1922. func (hh *SHost) GetHostDriver() (IHostDriver, error) {
  1923. if len(hh.HostType) == 0 {
  1924. hh.HostType = api.HOST_TYPE_DEFAULT
  1925. }
  1926. region, err := hh.GetRegion()
  1927. if err != nil {
  1928. return nil, errors.Wrapf(err, "GetRegion")
  1929. }
  1930. return GetHostDriver(hh.HostType, region.Provider)
  1931. }
  1932. func (manager *SHostManager) getHostsByZoneProvider(zone *SZone, region *SCloudregion, provider *SCloudprovider) ([]SHost, error) {
  1933. hosts := make([]SHost, 0)
  1934. q := manager.Query()
  1935. if zone != nil {
  1936. q = q.Equals("zone_id", zone.Id)
  1937. }
  1938. if region != nil {
  1939. zoneQ := ZoneManager.Query().Equals("cloudregion_id", region.Id).SubQuery()
  1940. q = q.Join(zoneQ, sqlchemy.Equals(q.Field("zone_id"), zoneQ.Field("id")))
  1941. }
  1942. if provider != nil {
  1943. q = q.Equals("manager_id", provider.Id)
  1944. }
  1945. // exclude prepaid_recycle fake hosts
  1946. q = q.NotEquals("resource_type", api.HostResourceTypePrepaidRecycle)
  1947. err := db.FetchModelObjects(manager, q, &hosts)
  1948. if err != nil {
  1949. log.Errorf("%s", err)
  1950. return nil, err
  1951. }
  1952. return hosts, nil
  1953. }
  1954. func (manager *SHostManager) SyncHosts(ctx context.Context, userCred mcclient.TokenCredential, provider *SCloudprovider, zone *SZone, region *SCloudregion, hosts []cloudprovider.ICloudHost, xor bool) ([]SHost, []cloudprovider.ICloudHost, compare.SyncResult) {
  1955. key := provider.Id
  1956. if zone != nil {
  1957. key = fmt.Sprintf("%s-%s", zone.Id, provider.Id)
  1958. }
  1959. lockman.LockRawObject(ctx, manager.Keyword(), key)
  1960. defer lockman.ReleaseRawObject(ctx, manager.Keyword(), key)
  1961. syncResult := compare.SyncResult{}
  1962. dbHosts, err := manager.getHostsByZoneProvider(zone, region, provider)
  1963. if err != nil {
  1964. syncResult.Error(err)
  1965. return nil, nil, syncResult
  1966. }
  1967. localHosts := make([]SHost, 0)
  1968. remoteHosts := make([]cloudprovider.ICloudHost, 0)
  1969. removed := make([]SHost, 0)
  1970. commondb := make([]SHost, 0)
  1971. commonext := make([]cloudprovider.ICloudHost, 0)
  1972. added := make([]cloudprovider.ICloudHost, 0)
  1973. err = compare.CompareSets(dbHosts, hosts, &removed, &commondb, &commonext, &added)
  1974. if err != nil {
  1975. syncResult.Error(err)
  1976. return nil, nil, syncResult
  1977. }
  1978. for i := 0; i < len(removed); i += 1 {
  1979. if removed[i].IsPrepaidRecycleResource() {
  1980. continue
  1981. }
  1982. err = removed[i].syncRemoveCloudHost(ctx, userCred)
  1983. if err != nil {
  1984. syncResult.DeleteError(err)
  1985. } else {
  1986. syncResult.Delete()
  1987. }
  1988. }
  1989. for i := 0; i < len(commondb); i += 1 {
  1990. if !xor {
  1991. err = commondb[i].SyncWithCloudHost(ctx, userCred, commonext[i])
  1992. if err != nil {
  1993. syncResult.UpdateError(err)
  1994. }
  1995. }
  1996. localHosts = append(localHosts, commondb[i])
  1997. remoteHosts = append(remoteHosts, commonext[i])
  1998. syncResult.Update()
  1999. }
  2000. for i := 0; i < len(added); i += 1 {
  2001. new, err := manager.NewFromCloudHost(ctx, userCred, added[i], provider, zone)
  2002. if err != nil {
  2003. syncResult.AddError(err)
  2004. } else {
  2005. localHosts = append(localHosts, *new)
  2006. remoteHosts = append(remoteHosts, added[i])
  2007. syncResult.Add()
  2008. }
  2009. }
  2010. return localHosts, remoteHosts, syncResult
  2011. }
  2012. func (hh *SHost) syncRemoveCloudHost(ctx context.Context, userCred mcclient.TokenCredential) error {
  2013. lockman.LockObject(ctx, hh)
  2014. defer lockman.ReleaseObject(ctx, hh)
  2015. err := hh.validateDeleteCondition(ctx, true)
  2016. if err != nil {
  2017. err = hh.purge(ctx, userCred)
  2018. if err != nil {
  2019. return errors.Wrap(err, "purge")
  2020. }
  2021. } else {
  2022. err = hh.RealDelete(ctx, userCred)
  2023. }
  2024. return err
  2025. }
  2026. func (hh *SHost) SyncWithCloudHost(ctx context.Context, userCred mcclient.TokenCredential, extHost cloudprovider.ICloudHost) error {
  2027. provider := hh.GetCloudprovider()
  2028. diff, err := db.UpdateWithLock(ctx, hh, func() error {
  2029. // hh.Name = extHost.GetName()
  2030. hh.Status = extHost.GetStatus()
  2031. hh.HostStatus = extHost.GetHostStatus()
  2032. hh.AccessIp = extHost.GetAccessIp()
  2033. hh.AccessMac = extHost.GetAccessMac()
  2034. hh.SN = extHost.GetSN()
  2035. hh.SysInfo = extHost.GetSysInfo()
  2036. hh.StorageType = extHost.GetStorageType()
  2037. hh.HostType = extHost.GetHostType()
  2038. if hh.HostType == api.HOST_TYPE_BAREMETAL {
  2039. hh.IsBaremetal = true
  2040. }
  2041. hh.StorageInfo = extHost.GetStorageInfo()
  2042. if storageDriver := extHost.GetStorageDriver(); len(storageDriver) > 0 {
  2043. hh.StorageDriver = storageDriver
  2044. }
  2045. hh.OvnVersion = extHost.GetOvnVersion()
  2046. if ipmiInfo := extHost.GetIpmiInfo(); !gotypes.IsNil(ipmiInfo) {
  2047. info := jsonutils.Marshal(ipmiInfo).(*jsonutils.JSONDict)
  2048. passwd, _ := info.GetString("password")
  2049. if len(passwd) > 0 {
  2050. passwd, _ = utils.EncryptAESBase64(hh.Id, passwd)
  2051. info.Set("password", jsonutils.NewString(passwd))
  2052. }
  2053. hh.IpmiInfo = info
  2054. }
  2055. if provider != nil && !utils.IsInStringArray(provider.Provider, strings.Split(options.Options.SkipSyncHostConfigInfoProviders, ",")) {
  2056. hh.CpuCount = extHost.GetCpuCount()
  2057. hh.NodeCount = extHost.GetNodeCount()
  2058. cpuDesc := extHost.GetCpuDesc()
  2059. if len(cpuDesc) > 128 {
  2060. cpuDesc = cpuDesc[:128]
  2061. }
  2062. hh.CpuDesc = cpuDesc
  2063. hh.CpuMhz = extHost.GetCpuMhz()
  2064. hh.MemSize = extHost.GetMemSizeMB()
  2065. hh.StorageSize = extHost.GetStorageSizeMB()
  2066. if cpuCmt := extHost.GetCpuCmtbound(); cpuCmt > 0 {
  2067. hh.CpuCmtbound = cpuCmt
  2068. }
  2069. if memCmt := extHost.GetMemCmtbound(); memCmt > 0 {
  2070. hh.MemCmtbound = memCmt
  2071. }
  2072. if arch := extHost.GetCpuArchitecture(); len(arch) > 0 {
  2073. hh.CpuArchitecture = arch
  2074. }
  2075. if reservedMem := extHost.GetReservedMemoryMb(); reservedMem > 0 {
  2076. hh.MemReserved = reservedMem
  2077. }
  2078. }
  2079. hh.IsEmulated = extHost.IsEmulated()
  2080. hh.SetEnabled(extHost.GetEnabled())
  2081. hh.IsMaintenance = extHost.GetIsMaintenance()
  2082. hh.Version = extHost.GetVersion()
  2083. return nil
  2084. })
  2085. if err != nil {
  2086. return errors.Wrapf(err, "syncWithCloudZone")
  2087. }
  2088. db.OpsLog.LogSyncUpdate(hh, diff, userCred)
  2089. if provider != nil {
  2090. SyncCloudDomain(userCred, hh, provider.GetOwnerId())
  2091. hh.SyncShareState(ctx, userCred, provider.getAccountShareInfo())
  2092. }
  2093. if account := hh.GetCloudaccount(); account != nil {
  2094. syncMetadata(ctx, userCred, hh, extHost, account.ReadOnly)
  2095. }
  2096. if !options.Options.DisableSyncSchedtags {
  2097. err = hh.syncSchedtags(ctx, userCred, extHost)
  2098. if err != nil && errors.Cause(err) != cloudprovider.ErrNotFound && errors.Cause(err) != errors.ErrNotImplemented {
  2099. log.Errorf("syncSchedtags for %s fail: %v", hh.Name, err)
  2100. }
  2101. }
  2102. if len(diff) > 0 {
  2103. if err := HostManager.ClearSchedDescCache(hh.Id); err != nil {
  2104. log.Errorf("ClearSchedDescCache for host %s error %v", hh.Name, err)
  2105. }
  2106. }
  2107. return nil
  2108. }
  2109. func (hh *SHost) syncWithCloudPrepaidVM(extVM cloudprovider.ICloudVM, host *SHost) error {
  2110. _, err := hh.SaveUpdates(func() error {
  2111. hh.CpuCount = extVM.GetVcpuCount()
  2112. hh.MemSize = extVM.GetVmemSizeMB()
  2113. hh.BillingType = billing_api.ParseBillingType(extVM.GetBillingType())
  2114. hh.ExpiredAt = extVM.GetExpiredAt()
  2115. hh.ExternalId = host.ExternalId
  2116. return nil
  2117. })
  2118. if err != nil {
  2119. log.Errorf("syncWithCloudZone error %s", err)
  2120. }
  2121. if err := HostManager.ClearSchedDescCache(hh.Id); err != nil {
  2122. log.Errorf("ClearSchedDescCache for host %s error %v", hh.Name, err)
  2123. }
  2124. return err
  2125. }
  2126. var (
  2127. METADATA_EXT_SCHEDTAG_KEY = "ext:schedtag"
  2128. )
  2129. func (h *SHost) getAllSchedtagsWithExtSchedtagKey() (map[string]string, error) {
  2130. sq := SchedtagManager.Query("id").SubQuery()
  2131. q := db.Metadata.Query("obj_id", "value").Equals("obj_type", SchedtagManager.Keyword()).Equals("key", METADATA_EXT_SCHEDTAG_KEY).In("obj_id", sq)
  2132. result := []struct {
  2133. ObjId string
  2134. Value string
  2135. }{}
  2136. err := q.All(&result)
  2137. if err != nil {
  2138. return nil, err
  2139. }
  2140. ret := make(map[string]string)
  2141. for i := range result {
  2142. ret[result[i].Value] = result[i].ObjId
  2143. }
  2144. return ret, nil
  2145. }
  2146. func (h *SHost) GetSchedtags() ([]SSchedtag, error) {
  2147. sq := HostschedtagManager.Query("schedtag_id").Equals("host_id", h.Id).SubQuery()
  2148. q := SchedtagManager.Query().In("id", sq)
  2149. schedtags := make([]SSchedtag, 0)
  2150. err := db.FetchModelObjects(SchedtagManager, q, &schedtags)
  2151. if err != nil {
  2152. return nil, errors.Wrap(err, "db.FetchModelObjects")
  2153. }
  2154. return schedtags, nil
  2155. }
  2156. func (h *SHost) syncSchedtags(ctx context.Context, userCred mcclient.TokenCredential, extHost cloudprovider.ICloudHost) error {
  2157. schedtags, err := h.GetSchedtags()
  2158. if err != nil {
  2159. return errors.Wrap(err, "GetSchedtags")
  2160. }
  2161. extSchedTags, err := extHost.GetSchedtags()
  2162. if err != nil {
  2163. return errors.Wrap(err, "extHost.GetSchedtags")
  2164. }
  2165. extTagMap := map[string]*cloudprovider.Schedtag{}
  2166. extTagIdSet := sets.NewString()
  2167. for i := range extSchedTags {
  2168. extSchedtag := &extSchedTags[i]
  2169. extTagIdSet.Insert(extSchedtag.Id)
  2170. extTagMap[extSchedtag.Id] = &extSchedTags[i]
  2171. }
  2172. removed := make([]*SSchedtag, 0)
  2173. removedIds := make([]string, 0)
  2174. for i := range schedtags {
  2175. stag := &schedtags[i]
  2176. extTagId := stag.GetMetadata(ctx, METADATA_EXT_SCHEDTAG_KEY, userCred)
  2177. if len(extTagId) == 0 {
  2178. continue
  2179. }
  2180. if !extTagIdSet.Has(extTagId) {
  2181. removed = append(removed, stag)
  2182. removedIds = append(removedIds, stag.GetId())
  2183. } else {
  2184. extTagIdSet.Delete(extTagId)
  2185. }
  2186. }
  2187. added := extTagIdSet.UnsortedList()
  2188. stagMap := make(map[string]string)
  2189. if len(added) > 0 {
  2190. stagMap, err = h.getAllSchedtagsWithExtSchedtagKey()
  2191. if err != nil {
  2192. return errors.Wrap(err, "getAllSchedtagsWithExtSchedtagKey")
  2193. }
  2194. }
  2195. for _, extSchedId := range added {
  2196. stagId, ok := stagMap[extSchedId]
  2197. if !ok {
  2198. st := &SSchedtag{
  2199. ResourceType: HostManager.KeywordPlural(),
  2200. }
  2201. st.DomainId = h.DomainId
  2202. st.Name = extTagMap[extSchedId].Name
  2203. st.Description = "Sync from cloud"
  2204. st.SetModelManager(SchedtagManager, st)
  2205. err := SchedtagManager.TableSpec().Insert(ctx, st)
  2206. if err != nil {
  2207. return errors.Wrapf(err, "unable to create schedtag %s", st.Name)
  2208. }
  2209. stagId = st.GetId()
  2210. meta := make(map[string]interface{})
  2211. meta[METADATA_EXT_SCHEDTAG_KEY] = extSchedId
  2212. for k, v := range extTagMap[extSchedId].Meta {
  2213. meta[k] = v
  2214. }
  2215. st.SetAllMetadata(ctx, meta, userCred)
  2216. }
  2217. // attach
  2218. hostschedtag := &SHostschedtag{
  2219. HostId: h.GetId(),
  2220. }
  2221. hostschedtag.SetModelManager(HostschedtagManager, hostschedtag)
  2222. hostschedtag.SchedtagId = stagId
  2223. err = HostschedtagManager.TableSpec().Insert(ctx, hostschedtag)
  2224. if err != nil {
  2225. return errors.Wrapf(err, "unable to create hostschedtag for tag %s host %s", stagId, h.GetId())
  2226. }
  2227. }
  2228. if len(removedIds) == 0 {
  2229. return nil
  2230. }
  2231. q := HostschedtagManager.Query().Equals("host_id", h.GetId()).In("schedtag_id", removedIds)
  2232. hostschedtags := make([]SHostschedtag, 0, len(removedIds))
  2233. err = db.FetchModelObjects(HostschedtagManager, q, &hostschedtags)
  2234. if err != nil {
  2235. return errors.Wrap(err, "db.FetchModelObject")
  2236. }
  2237. for i := range hostschedtags {
  2238. err = hostschedtags[i].Detach(ctx, userCred)
  2239. if err != nil {
  2240. return errors.Wrapf(err, "unable to detach host %q and schedtag %q", hostschedtags[i].HostId, hostschedtags[i].SchedtagId)
  2241. }
  2242. }
  2243. // try to clean
  2244. for _, tag := range removed {
  2245. cnt, err := tag.GetObjectCount()
  2246. if err != nil {
  2247. log.Errorf("unable to GetObjectCount for schedtag %q: %v", tag.GetName(), err)
  2248. continue
  2249. }
  2250. if cnt > 0 {
  2251. continue
  2252. }
  2253. err = tag.Delete(ctx, userCred)
  2254. if err != nil {
  2255. log.Errorf("unable to delete schedtag %q: %v", tag.GetName(), err)
  2256. continue
  2257. }
  2258. }
  2259. return nil
  2260. }
  2261. func (manager *SHostManager) NewFromCloudHost(ctx context.Context, userCred mcclient.TokenCredential, extHost cloudprovider.ICloudHost, provider *SCloudprovider, izone *SZone) (*SHost, error) {
  2262. host := SHost{}
  2263. host.SetModelManager(manager, &host)
  2264. if izone == nil {
  2265. // onpremise host
  2266. accessIp := extHost.GetAccessIp()
  2267. if len(accessIp) == 0 {
  2268. msg := fmt.Sprintf("fail to find wire for host %s: empty host access ip", extHost.GetName())
  2269. return nil, fmt.Errorf("%s", msg)
  2270. }
  2271. wire, err := WireManager.GetOnPremiseWireOfIp(accessIp)
  2272. if err != nil {
  2273. return nil, errors.Wrapf(err, "GetOnPremiseWireOfIp for host %s with ip %s", extHost.GetName(), accessIp)
  2274. }
  2275. izone, err = wire.GetZone()
  2276. if err != nil {
  2277. return nil, errors.Wrapf(err, "get zone for wire %s", wire.Name)
  2278. }
  2279. }
  2280. host.ExternalId = extHost.GetGlobalId()
  2281. host.ZoneId = izone.Id
  2282. host.HostType = extHost.GetHostType()
  2283. if host.HostType == api.HOST_TYPE_BAREMETAL {
  2284. host.IsBaremetal = true
  2285. }
  2286. host.StorageInfo = extHost.GetStorageInfo()
  2287. host.OvnVersion = extHost.GetOvnVersion()
  2288. if ipmiInfo := extHost.GetIpmiInfo(); !gotypes.IsNil(ipmiInfo) {
  2289. info := jsonutils.Marshal(ipmiInfo).(*jsonutils.JSONDict)
  2290. passwd, _ := info.GetString("password")
  2291. if len(passwd) > 0 {
  2292. passwd, _ = utils.EncryptAESBase64(host.Id, passwd)
  2293. info.Set("password", jsonutils.NewString(passwd))
  2294. }
  2295. host.IpmiInfo = info
  2296. }
  2297. host.Status = extHost.GetStatus()
  2298. host.HostStatus = extHost.GetHostStatus()
  2299. host.SetEnabled(extHost.GetEnabled())
  2300. host.AccessIp = extHost.GetAccessIp()
  2301. host.AccessMac = extHost.GetAccessMac()
  2302. host.SN = extHost.GetSN()
  2303. host.SysInfo = extHost.GetSysInfo()
  2304. host.CpuCount = extHost.GetCpuCount()
  2305. host.NodeCount = extHost.GetNodeCount()
  2306. cpuDesc := extHost.GetCpuDesc()
  2307. if len(cpuDesc) > 128 {
  2308. cpuDesc = cpuDesc[:128]
  2309. }
  2310. host.CpuDesc = cpuDesc
  2311. host.CpuMhz = extHost.GetCpuMhz()
  2312. host.MemSize = extHost.GetMemSizeMB()
  2313. host.StorageSize = extHost.GetStorageSizeMB()
  2314. host.StorageType = extHost.GetStorageType()
  2315. host.StorageDriver = extHost.GetStorageDriver()
  2316. host.CpuCmtbound = 8.0
  2317. if cpuCmt := extHost.GetCpuCmtbound(); cpuCmt > 0 {
  2318. host.CpuCmtbound = cpuCmt
  2319. }
  2320. host.MemCmtbound = 1.0
  2321. if memCmt := extHost.GetMemCmtbound(); memCmt > 0 {
  2322. host.MemCmtbound = memCmt
  2323. }
  2324. if arch := extHost.GetCpuArchitecture(); len(arch) > 0 {
  2325. host.CpuArchitecture = arch
  2326. }
  2327. if reservedMem := extHost.GetReservedMemoryMb(); reservedMem > 0 {
  2328. host.MemReserved = reservedMem
  2329. }
  2330. host.ManagerId = provider.Id
  2331. host.IsEmulated = extHost.IsEmulated()
  2332. host.IsMaintenance = extHost.GetIsMaintenance()
  2333. host.Version = extHost.GetVersion()
  2334. host.IsPublic = false
  2335. host.PublicScope = string(rbacscope.ScopeNone)
  2336. var err = func() error {
  2337. lockman.LockRawObject(ctx, manager.Keyword(), "name")
  2338. defer lockman.ReleaseRawObject(ctx, manager.Keyword(), "name")
  2339. //newName, err := db.GenerateName(ctx, manager, userCred, extHost.GetName())
  2340. //if err != nil {
  2341. // return errors.Wrapf(err, "db.GenerateName")
  2342. //}
  2343. host.Name = extHost.GetName()
  2344. return manager.TableSpec().Insert(ctx, &host)
  2345. }()
  2346. if err != nil {
  2347. return nil, errors.Wrapf(err, "Insert")
  2348. }
  2349. db.OpsLog.LogEvent(&host, db.ACT_CREATE, host.GetShortDesc(ctx), userCred)
  2350. SyncCloudDomain(userCred, &host, provider.GetOwnerId())
  2351. err = host.syncSchedtags(ctx, userCred, extHost)
  2352. if err != nil && errors.Cause(err) != cloudprovider.ErrNotFound && errors.Cause(err) != errors.ErrNotImplemented {
  2353. log.Errorf("syncSchedtags %s fail %v", host.Name, err)
  2354. }
  2355. if provider != nil {
  2356. host.SyncShareState(ctx, userCred, provider.getAccountShareInfo())
  2357. }
  2358. if err := manager.ClearSchedDescCache(host.Id); err != nil {
  2359. log.Errorf("ClearSchedDescCache for host %s error %v", host.Name, err)
  2360. }
  2361. return &host, nil
  2362. }
  2363. func (hh *SHost) SyncHostStorages(ctx context.Context, userCred mcclient.TokenCredential, storages []cloudprovider.ICloudStorage, provider *SCloudprovider, xor bool) ([]SStorage, []cloudprovider.ICloudStorage, compare.SyncResult) {
  2364. lockman.LockRawObject(ctx, "storages", hh.Id)
  2365. defer lockman.ReleaseRawObject(ctx, "storages", hh.Id)
  2366. localStorages := make([]SStorage, 0)
  2367. remoteStorages := make([]cloudprovider.ICloudStorage, 0)
  2368. syncResult := compare.SyncResult{}
  2369. dbStorages := make([]SStorage, 0)
  2370. hostStorages := hh.GetHoststorages()
  2371. for i := 0; i < len(hostStorages); i += 1 {
  2372. storage := hostStorages[i].GetStorage()
  2373. if storage == nil {
  2374. hostStorages[i].Delete(ctx, userCred)
  2375. } else {
  2376. dbStorages = append(dbStorages, *storage)
  2377. }
  2378. }
  2379. // dbStorages := hh._getAttachedStorages(tristate.None, tristate.None)
  2380. removed := make([]SStorage, 0)
  2381. commondb := make([]SStorage, 0)
  2382. commonext := make([]cloudprovider.ICloudStorage, 0)
  2383. added := make([]cloudprovider.ICloudStorage, 0)
  2384. err := compare.CompareSets(dbStorages, storages, &removed, &commondb, &commonext, &added)
  2385. if err != nil {
  2386. syncResult.Error(err)
  2387. return nil, nil, syncResult
  2388. }
  2389. for i := 0; i < len(removed); i += 1 {
  2390. log.Infof("host %s not connected with %s any more, to detach...", hh.Id, removed[i].Id)
  2391. err := hh.syncRemoveCloudHostStorage(ctx, userCred, &removed[i])
  2392. if errors.Cause(err) == ErrStorageInUse && removed[i].StorageType == api.STORAGE_LOCAL {
  2393. removed[i].SetStatus(ctx, userCred, api.STORAGE_OFFLINE, "the only host used this local storage has detached")
  2394. // prevent generating a delete error for syncResult
  2395. continue
  2396. }
  2397. if err != nil {
  2398. syncResult.DeleteError(err)
  2399. } else {
  2400. syncResult.Delete()
  2401. }
  2402. }
  2403. for i := 0; i < len(commondb); i += 1 {
  2404. if !xor {
  2405. log.Infof("host %s is still connected with %s, to update ...", hh.Id, commondb[i].Id)
  2406. err := hh.syncWithCloudHostStorage(ctx, userCred, &commondb[i], commonext[i], provider)
  2407. if err != nil {
  2408. syncResult.UpdateError(err)
  2409. }
  2410. }
  2411. localStorages = append(localStorages, commondb[i])
  2412. remoteStorages = append(remoteStorages, commonext[i])
  2413. syncResult.Update()
  2414. }
  2415. for i := 0; i < len(added); i += 1 {
  2416. log.Infof("host %s is found connected with %s, to add ...", hh.Id, added[i].GetId())
  2417. local, err := hh.newCloudHostStorage(ctx, userCred, added[i], provider)
  2418. if err != nil {
  2419. syncResult.AddError(err)
  2420. } else {
  2421. localStorages = append(localStorages, *local)
  2422. remoteStorages = append(remoteStorages, added[i])
  2423. syncResult.Add()
  2424. }
  2425. }
  2426. return localStorages, remoteStorages, syncResult
  2427. }
  2428. func (hh *SHost) syncRemoveCloudHostStorage(ctx context.Context, userCred mcclient.TokenCredential, localStorage *SStorage) error {
  2429. hs := hh.GetHoststorageOfId(localStorage.Id)
  2430. err := hs.ValidateDeleteCondition(ctx, nil)
  2431. if err == nil {
  2432. log.Errorf("sync remove hoststorage fail: %s", err)
  2433. err = hs.Detach(ctx, userCred)
  2434. } else {
  2435. }
  2436. return err
  2437. }
  2438. func (hh *SHost) syncWithCloudHostStorage(ctx context.Context, userCred mcclient.TokenCredential, localStorage *SStorage, extStorage cloudprovider.ICloudStorage, provider *SCloudprovider) error {
  2439. // do nothing
  2440. hs := hh.GetHoststorageOfId(localStorage.Id)
  2441. err := hs.syncWithCloudHostStorage(userCred, extStorage)
  2442. if err != nil {
  2443. return err
  2444. }
  2445. s := hs.GetStorage()
  2446. err = s.syncWithCloudStorage(ctx, userCred, extStorage, provider)
  2447. return err
  2448. }
  2449. func (hh *SHost) isAttach2Storage(storage *SStorage) bool {
  2450. hs := hh.GetHoststorageOfId(storage.Id)
  2451. return hs != nil
  2452. }
  2453. func (hh *SHost) Attach2Storage(ctx context.Context, userCred mcclient.TokenCredential, storage *SStorage, mountPoint string) error {
  2454. if hh.isAttach2Storage(storage) {
  2455. return nil
  2456. }
  2457. hs := SHoststorage{}
  2458. hs.SetModelManager(HoststorageManager, &hs)
  2459. hs.StorageId = storage.Id
  2460. hs.HostId = hh.Id
  2461. hs.MountPoint = mountPoint
  2462. err := HoststorageManager.TableSpec().Insert(ctx, &hs)
  2463. if err != nil {
  2464. return err
  2465. }
  2466. db.OpsLog.LogAttachEvent(ctx, hh, storage, userCred, nil)
  2467. return nil
  2468. }
  2469. func (hh *SHost) newCloudHostStorage(ctx context.Context, userCred mcclient.TokenCredential, extStorage cloudprovider.ICloudStorage, provider *SCloudprovider) (*SStorage, error) {
  2470. storageObj, err := db.FetchByExternalIdAndManagerId(StorageManager, extStorage.GetGlobalId(), func(q *sqlchemy.SQuery) *sqlchemy.SQuery {
  2471. return q.Equals("manager_id", provider.Id)
  2472. })
  2473. if err != nil {
  2474. if errors.Cause(err) == sql.ErrNoRows {
  2475. // no cloud storage found, this may happen for on-premise host
  2476. // create the storage right now
  2477. zone, _ := hh.GetZone()
  2478. storageObj, err = StorageManager.newFromCloudStorage(ctx, userCred, extStorage, provider, zone)
  2479. if err != nil {
  2480. return nil, errors.Wrapf(err, "StorageManager.newFromCloudStorage")
  2481. }
  2482. } else {
  2483. return nil, errors.Wrapf(err, "FetchByExternalIdAndManagerId(%s)", extStorage.GetGlobalId())
  2484. }
  2485. }
  2486. storage := storageObj.(*SStorage)
  2487. err = hh.Attach2Storage(ctx, userCred, storage, extStorage.GetMountPoint())
  2488. return storage, err
  2489. }
  2490. func (hh *SHost) SyncHostWires(ctx context.Context, userCred mcclient.TokenCredential, wires []cloudprovider.ICloudWire) compare.SyncResult {
  2491. lockman.LockRawObject(ctx, "wires", hh.Id)
  2492. defer lockman.ReleaseRawObject(ctx, "wires", hh.Id)
  2493. syncResult := compare.SyncResult{}
  2494. dbWires := make([]SWire, 0)
  2495. hostNetifs := hh.GetHostNetInterfaces()
  2496. for i := 0; i < len(hostNetifs); i += 1 {
  2497. wire := hostNetifs[i].GetWire()
  2498. if wire != nil {
  2499. // hostNetifs[i].Remove(ctx, userCred)
  2500. } else {
  2501. dbWires = append(dbWires, *wire)
  2502. }
  2503. }
  2504. // dbWires := hh.getAttachedWires()
  2505. removed := make([]SWire, 0)
  2506. commondb := make([]SWire, 0)
  2507. commonext := make([]cloudprovider.ICloudWire, 0)
  2508. added := make([]cloudprovider.ICloudWire, 0)
  2509. err := compare.CompareSets(dbWires, wires, &removed, &commondb, &commonext, &added)
  2510. if err != nil {
  2511. syncResult.Error(err)
  2512. return syncResult
  2513. }
  2514. for i := 0; i < len(removed); i += 1 {
  2515. log.Infof("host %s not connected with %s any more, to detach...", hh.Id, removed[i].Id)
  2516. err := hh.syncRemoveCloudHostWire(ctx, userCred, &removed[i])
  2517. if err != nil {
  2518. syncResult.DeleteError(err)
  2519. } else {
  2520. syncResult.Delete()
  2521. }
  2522. }
  2523. for i := 0; i < len(commondb); i += 1 {
  2524. log.Infof("host %s is still connected with %s, to update...", hh.Id, commondb[i].Id)
  2525. err := hh.syncWithCloudHostWire(commonext[i])
  2526. if err != nil {
  2527. syncResult.UpdateError(err)
  2528. } else {
  2529. syncResult.Update()
  2530. }
  2531. }
  2532. for i := 0; i < len(added); i += 1 {
  2533. log.Infof("host %s is found connected with %s, to add...", hh.Id, added[i].GetId())
  2534. err := hh.newCloudHostWire(ctx, userCred, added[i])
  2535. if err != nil {
  2536. syncResult.AddError(err)
  2537. } else {
  2538. syncResult.Add()
  2539. }
  2540. }
  2541. return syncResult
  2542. }
  2543. func (hh *SHost) syncRemoveCloudHostWire(ctx context.Context, userCred mcclient.TokenCredential, localwire *SWire) error {
  2544. netifs := hh.getNetifsOnWire(localwire.Id)
  2545. for i := range netifs {
  2546. err := netifs[i].Delete(ctx, userCred)
  2547. if err != nil {
  2548. return errors.Wrap(err, "delete")
  2549. }
  2550. }
  2551. return nil
  2552. }
  2553. func (hh *SHost) syncWithCloudHostWire(extWire cloudprovider.ICloudWire) error {
  2554. // do nothing
  2555. return nil
  2556. }
  2557. func (hh *SHost) Attach2Wire(ctx context.Context, userCred mcclient.TokenCredential, wire *SWire) error {
  2558. netif := SNetInterface{}
  2559. netif.SetModelManager(NetInterfaceManager, &netif)
  2560. netif.Mac = stringutils2.HashIdsMac(hh.Id, wire.Id)
  2561. netif.VlanId = 1
  2562. netif.WireId = wire.Id
  2563. netif.BaremetalId = hh.Id
  2564. err := NetInterfaceManager.TableSpec().InsertOrUpdate(ctx, &netif)
  2565. if err != nil {
  2566. return errors.Wrap(err, "InsertOrUpdate")
  2567. }
  2568. return nil
  2569. }
  2570. func (hh *SHost) newCloudHostWire(ctx context.Context, userCred mcclient.TokenCredential, extWire cloudprovider.ICloudWire) error {
  2571. wireObj, err := db.FetchByExternalIdAndManagerId(WireManager, extWire.GetGlobalId(), func(q *sqlchemy.SQuery) *sqlchemy.SQuery {
  2572. sq := VpcManager.Query().SubQuery()
  2573. return q.Join(sq, sqlchemy.Equals(sq.Field("id"), q.Field("vpc_id"))).Filter(sqlchemy.Equals(sq.Field("manager_id"), hh.ManagerId))
  2574. })
  2575. if err != nil {
  2576. log.Errorf("%s", err)
  2577. return nil
  2578. }
  2579. wire := wireObj.(*SWire)
  2580. err = hh.Attach2Wire(ctx, userCred, wire)
  2581. return err
  2582. }
  2583. type SGuestSyncResult struct {
  2584. Local *SGuest
  2585. Remote cloudprovider.ICloudVM
  2586. IsNew bool
  2587. }
  2588. func IsNeedSkipSync(ext cloudprovider.ICloudResource) (bool, string) {
  2589. if len(options.Options.SkipServerBySysTagKeys) == 0 &&
  2590. len(options.Options.SkipServerByUserTagKeys) == 0 &&
  2591. len(options.Options.SkipServerByUserTagValues) == 0 &&
  2592. len(options.Options.RetentionServerByUserTagKeys) == 0 &&
  2593. len(options.Options.RetentionServerByUserTagValues) == 0 &&
  2594. len(options.Options.RetentionServerByUserTags) == 0 {
  2595. return false, ""
  2596. }
  2597. tags, _ := ext.GetTags()
  2598. if keys := strings.Split(options.Options.SkipServerBySysTagKeys, ","); len(keys) > 0 {
  2599. for key := range ext.GetSysTags() {
  2600. key = strings.Trim(key, "")
  2601. if len(key) > 0 && utils.IsInStringArray(key, keys) {
  2602. return true, key
  2603. }
  2604. }
  2605. }
  2606. if userKeys := strings.Split(options.Options.SkipServerByUserTagKeys, ","); len(userKeys) > 0 {
  2607. for key := range tags {
  2608. key = strings.Trim(key, "")
  2609. if len(key) > 0 && utils.IsInStringArray(key, userKeys) {
  2610. return true, key
  2611. }
  2612. }
  2613. }
  2614. if len(options.Options.SkipServerByUserTagValues) > 0 {
  2615. for _, value := range tags {
  2616. value = strings.Trim(value, "")
  2617. if len(value) > 0 && utils.IsInStringArray(value, options.Options.SkipServerByUserTagValues) {
  2618. return true, value
  2619. }
  2620. }
  2621. }
  2622. keys, values, pairs := []string{}, []string{}, []string{}
  2623. for key, value := range tags {
  2624. key = strings.Trim(key, "")
  2625. keys = append(keys, key)
  2626. values = append(values, value)
  2627. pairs = append(pairs, fmt.Sprintf("%s:%s", key, value))
  2628. }
  2629. if len(options.Options.RetentionServerByUserTagKeys) > 0 {
  2630. skip, tagKey := true, ""
  2631. for _, key := range options.Options.RetentionServerByUserTagKeys {
  2632. key = strings.Trim(key, "")
  2633. if len(key) > 0 && utils.IsInStringArray(key, keys) {
  2634. skip, tagKey = false, key
  2635. break
  2636. }
  2637. }
  2638. return skip, tagKey
  2639. }
  2640. if len(options.Options.RetentionServerByUserTagValues) > 0 {
  2641. skip, tagValue := true, ""
  2642. for _, value := range options.Options.RetentionServerByUserTagValues {
  2643. value = strings.Trim(value, "")
  2644. if len(value) > 0 && utils.IsInStringArray(value, values) {
  2645. skip, tagValue = false, value
  2646. break
  2647. }
  2648. }
  2649. return skip, tagValue
  2650. }
  2651. if len(options.Options.RetentionServerByUserTags) > 0 {
  2652. skip, tagPair := true, ""
  2653. for _, pair := range options.Options.RetentionServerByUserTags {
  2654. pair = strings.Trim(pair, "")
  2655. if len(pair) > 0 && utils.IsInStringArray(pair, pairs) {
  2656. skip, tagPair = false, pair
  2657. break
  2658. }
  2659. }
  2660. return skip, tagPair
  2661. }
  2662. return false, ""
  2663. }
  2664. func (self *SGuest) Purge(ctx context.Context, userCred mcclient.TokenCredential) error {
  2665. return self.purge(ctx, userCred)
  2666. }
  2667. func (hh *SHost) GetIsolateDevices() ([]SIsolatedDevice, error) {
  2668. q := IsolatedDeviceManager.Query().Equals("host_id", hh.Id)
  2669. ret := []SIsolatedDevice{}
  2670. err := db.FetchModelObjects(IsolatedDeviceManager, q, &ret)
  2671. if err != nil {
  2672. return nil, err
  2673. }
  2674. return ret, nil
  2675. }
  2676. func (hh *SHost) SyncHostIsolateDevices(ctx context.Context, userCred mcclient.TokenCredential, iprovider cloudprovider.ICloudProvider, devs []cloudprovider.IsolateDevice, syncOwnerId mcclient.IIdentityProvider, xor bool) compare.SyncResult {
  2677. lockman.LockRawObject(ctx, IsolatedDeviceManager.Keyword(), hh.Id)
  2678. defer lockman.ReleaseRawObject(ctx, IsolatedDeviceManager.Keyword(), hh.Id)
  2679. result := compare.SyncResult{}
  2680. dbDevs, err := hh.GetIsolateDevices()
  2681. if err != nil {
  2682. result.Error(errors.Wrapf(err, "GetIsolateDevices"))
  2683. return result
  2684. }
  2685. removed := make([]SIsolatedDevice, 0)
  2686. commondb := make([]SIsolatedDevice, 0)
  2687. commonext := make([]cloudprovider.IsolateDevice, 0)
  2688. added := make([]cloudprovider.IsolateDevice, 0)
  2689. duplicated := make(map[string][]cloudprovider.IsolateDevice)
  2690. err = compare.CompareSets2(dbDevs, devs, &removed, &commondb, &commonext, &added, &duplicated)
  2691. if err != nil {
  2692. result.Error(err)
  2693. return result
  2694. }
  2695. for i := 0; i < len(removed); i += 1 {
  2696. err := removed[i].Delete(ctx, userCred)
  2697. if err != nil {
  2698. result.DeleteError(err)
  2699. continue
  2700. }
  2701. result.Delete()
  2702. }
  2703. if !xor {
  2704. for i := 0; i < len(commondb); i += 1 {
  2705. err := commondb[i].syncWithCloudIsolateDevice(ctx, userCred, commonext[i])
  2706. if err != nil {
  2707. result.UpdateError(err)
  2708. continue
  2709. }
  2710. result.Update()
  2711. }
  2712. }
  2713. for i := 0; i < len(added); i += 1 {
  2714. err := hh.newIsolateDevice(ctx, userCred, added[i])
  2715. if err != nil {
  2716. result.AddError(err)
  2717. continue
  2718. }
  2719. result.Add()
  2720. }
  2721. if len(duplicated) > 0 {
  2722. errs := make([]error, 0)
  2723. for k, vms := range duplicated {
  2724. errs = append(errs, errors.Wrapf(errors.ErrDuplicateId, "Duplicate Id %s (%d)", k, len(vms)))
  2725. }
  2726. result.AddError(errors.NewAggregate(errs))
  2727. }
  2728. return result
  2729. }
  2730. func (hh *SHost) newIsolateDevice(ctx context.Context, userCred mcclient.TokenCredential, dev cloudprovider.IsolateDevice) error {
  2731. ret := &SIsolatedDevice{}
  2732. ret.SetModelManager(IsolatedDeviceManager, ret)
  2733. ret.HostId = hh.Id
  2734. ret.ExternalId = dev.GetGlobalId()
  2735. ret.Name = dev.GetName()
  2736. ret.Model = dev.GetModel()
  2737. ret.Addr = dev.GetAddr()
  2738. ret.DevType = dev.GetDevType()
  2739. ret.NumaNode = dev.GetNumaNode()
  2740. ret.VendorDeviceId = dev.GetVendorDeviceId()
  2741. err := IsolatedDeviceManager.TableSpec().Insert(ctx, ret)
  2742. if err != nil {
  2743. return err
  2744. }
  2745. sharedProjectIds, err := dev.GetSharedProjectIds()
  2746. if err != nil {
  2747. if errors.Cause(err) == cloudprovider.ErrNotImplemented {
  2748. return nil
  2749. }
  2750. return err
  2751. }
  2752. if len(sharedProjectIds) == 0 {
  2753. return nil
  2754. }
  2755. if len(sharedProjectIds) > 0 {
  2756. projectIds, err := db.FetchField(ExternalProjectManager, "tenant_id", func(q *sqlchemy.SQuery) *sqlchemy.SQuery {
  2757. return q.Equals("manager_id", hh.ManagerId).In("external_id", sharedProjectIds)
  2758. })
  2759. if err != nil {
  2760. return err
  2761. }
  2762. input := apis.PerformPublicProjectInput{SharedProjectIds: projectIds}
  2763. input.Scope = "project"
  2764. db.SharablePerformPublic(ret, ctx, userCred, input)
  2765. }
  2766. return nil
  2767. }
  2768. func (hh *SHost) SyncHostVMs(ctx context.Context, userCred mcclient.TokenCredential, iprovider cloudprovider.ICloudProvider, vms []cloudprovider.ICloudVM, syncOwnerId mcclient.IIdentityProvider, xor bool) ([]SGuestSyncResult, compare.SyncResult) {
  2769. lockman.LockRawObject(ctx, GuestManager.Keyword(), hh.Id)
  2770. defer lockman.ReleaseRawObject(ctx, GuestManager.Keyword(), hh.Id)
  2771. syncVMPairs := make([]SGuestSyncResult, 0)
  2772. syncResult := compare.SyncResult{}
  2773. dbVMs, err := hh.GetGuests()
  2774. if err != nil {
  2775. syncResult.Error(errors.Wrapf(err, "GetGuests"))
  2776. return nil, syncResult
  2777. }
  2778. for i := range dbVMs {
  2779. if taskman.TaskManager.IsInTask(&dbVMs[i]) {
  2780. syncResult.Error(fmt.Errorf("server %s(%s)in task", dbVMs[i].Name, dbVMs[i].Id))
  2781. return nil, syncResult
  2782. }
  2783. }
  2784. removed := make([]SGuest, 0)
  2785. commondb := make([]SGuest, 0)
  2786. commonext := make([]cloudprovider.ICloudVM, 0)
  2787. added := make([]cloudprovider.ICloudVM, 0)
  2788. duplicated := make(map[string][]cloudprovider.ICloudVM)
  2789. err = compare.CompareSets2(dbVMs, vms, &removed, &commondb, &commonext, &added, &duplicated)
  2790. if err != nil {
  2791. syncResult.Error(err)
  2792. return nil, syncResult
  2793. }
  2794. for i := 0; i < len(removed); i += 1 {
  2795. err := removed[i].SyncRemoveCloudVM(ctx, userCred, true)
  2796. if err != nil {
  2797. syncResult.DeleteError(err)
  2798. } else {
  2799. syncResult.Delete()
  2800. }
  2801. }
  2802. if !xor {
  2803. for i := 0; i < len(commondb); i += 1 {
  2804. skip, key := IsNeedSkipSync(commonext[i])
  2805. if skip {
  2806. log.Infof("delete server %s(%s) with tag key or value: %s", commonext[i].GetName(), commonext[i].GetGlobalId(), key)
  2807. err := commondb[i].purge(ctx, userCred)
  2808. if err != nil {
  2809. syncResult.DeleteError(err)
  2810. continue
  2811. }
  2812. syncResult.Delete()
  2813. continue
  2814. }
  2815. err := commondb[i].syncWithCloudVM(ctx, userCred, iprovider, hh, commonext[i], syncOwnerId, true)
  2816. if err != nil {
  2817. syncResult.UpdateError(err)
  2818. continue
  2819. }
  2820. syncVMPair := SGuestSyncResult{
  2821. Local: &commondb[i],
  2822. Remote: commonext[i],
  2823. IsNew: false,
  2824. }
  2825. syncVMPairs = append(syncVMPairs, syncVMPair)
  2826. syncResult.Update()
  2827. }
  2828. }
  2829. for i := 0; i < len(added); i += 1 {
  2830. skip, key := IsNeedSkipSync(added[i])
  2831. if skip {
  2832. log.Infof("skip server %s(%s) sync with tag key or value: %s", added[i].GetName(), added[i].GetGlobalId(), key)
  2833. continue
  2834. }
  2835. vm, err := db.FetchByExternalIdAndManagerId(GuestManager, added[i].GetGlobalId(), func(q *sqlchemy.SQuery) *sqlchemy.SQuery {
  2836. sq := HostManager.Query().SubQuery()
  2837. return q.Join(sq, sqlchemy.Equals(sq.Field("id"), q.Field("host_id"))).Filter(sqlchemy.Equals(sq.Field("manager_id"), hh.ManagerId))
  2838. })
  2839. if err != nil && errors.Cause(err) != sql.ErrNoRows {
  2840. log.Errorf("failed to found guest by externalId %s error: %v", added[i].GetGlobalId(), err)
  2841. continue
  2842. }
  2843. if vm != nil {
  2844. guest := vm.(*SGuest)
  2845. ihost := added[i].GetIHost()
  2846. if ihost == nil {
  2847. log.Errorf("failed to found ihost from vm %s", added[i].GetGlobalId())
  2848. continue
  2849. }
  2850. _host, err := db.FetchByExternalIdAndManagerId(HostManager, ihost.GetGlobalId(), func(q *sqlchemy.SQuery) *sqlchemy.SQuery {
  2851. return q.Equals("manager_id", hh.ManagerId)
  2852. })
  2853. if err != nil {
  2854. log.Errorf("failed to found host by externalId %s", ihost.GetGlobalId())
  2855. continue
  2856. }
  2857. host := _host.(*SHost)
  2858. err = guest.syncWithCloudVM(ctx, userCred, iprovider, host, added[i], syncOwnerId, true)
  2859. if err != nil {
  2860. syncResult.UpdateError(err)
  2861. } else {
  2862. syncResult.Update()
  2863. }
  2864. continue
  2865. }
  2866. if added[i].GetBillingType() == string(billing_api.BILLING_TYPE_PREPAID) {
  2867. vhost := HostManager.GetHostByRealExternalId(added[i].GetGlobalId())
  2868. if vhost != nil {
  2869. // this recycle vm is not build yet, skip synchronize
  2870. err = vhost.SyncWithRealPrepaidVM(ctx, userCred, added[i])
  2871. if err != nil {
  2872. syncResult.AddError(err)
  2873. }
  2874. continue
  2875. }
  2876. }
  2877. new, err := GuestManager.newCloudVM(ctx, userCred, iprovider, hh, added[i], syncOwnerId)
  2878. if err != nil {
  2879. syncResult.AddError(err)
  2880. } else {
  2881. syncVMPair := SGuestSyncResult{
  2882. Local: new,
  2883. Remote: added[i],
  2884. IsNew: true,
  2885. }
  2886. syncVMPairs = append(syncVMPairs, syncVMPair)
  2887. syncResult.Add()
  2888. }
  2889. }
  2890. if len(duplicated) > 0 {
  2891. errs := make([]error, 0)
  2892. for k, vms := range duplicated {
  2893. errs = append(errs, errors.Wrapf(errors.ErrDuplicateId, "Duplicate Id %s (%d)", k, len(vms)))
  2894. }
  2895. syncResult.AddError(errors.NewAggregate(errs))
  2896. }
  2897. return syncVMPairs, syncResult
  2898. }
  2899. func (hh *SHost) getNetworkOfIPOnHost(ctx context.Context, ipAddr string) (*SNetwork, error) {
  2900. netInterfaces := hh.GetHostNetInterfaces()
  2901. for _, netInterface := range netInterfaces {
  2902. network, err := netInterface.GetCandidateNetworkForIp(ctx, nil, nil, rbacscope.ScopeNone, ipAddr)
  2903. if err == nil && network != nil {
  2904. return network, nil
  2905. }
  2906. }
  2907. return nil, fmt.Errorf("IP %s not reachable on this host", ipAddr)
  2908. }
  2909. func (hh *SHost) GetNetinterfacesWithIdAndCredential(netId string, userCred mcclient.TokenCredential, reserved bool) ([]SNetInterface, *SNetwork, error) {
  2910. netObj, err := NetworkManager.FetchById(netId)
  2911. if err != nil {
  2912. return nil, nil, errors.Wrapf(err, "fetch by id %q", netId)
  2913. }
  2914. net := netObj.(*SNetwork)
  2915. used, err := net.getFreeAddressCount()
  2916. if err != nil {
  2917. return nil, nil, errors.Wrapf(err, "get network %q free address count", net.GetName())
  2918. }
  2919. if used == 0 && !reserved && !options.Options.BaremetalServerReuseHostIp {
  2920. return nil, nil, errors.Errorf("network %q out of usage", net.GetName())
  2921. }
  2922. matchNetIfs := make([]SNetInterface, 0)
  2923. netifs := hh.GetHostNetInterfaces()
  2924. for i := 0; i < len(netifs); i++ {
  2925. if !netifs[i].IsUsableServernic() {
  2926. continue
  2927. }
  2928. if netifs[i].WireId == net.WireId {
  2929. matchNetIfs = append(matchNetIfs, netifs[i])
  2930. // return &netifs[i], net
  2931. }
  2932. }
  2933. if len(matchNetIfs) > 0 {
  2934. return matchNetIfs, net, nil
  2935. }
  2936. return nil, nil, errors.Errorf("not found matched netinterface by net %q wire %q", net.GetName(), net.WireId)
  2937. }
  2938. func (hh *SHost) GetNetworkWithId(netId string, reserved bool) (*SNetwork, error) {
  2939. var q1, q2, q3, q4 *sqlchemy.SQuery
  2940. {
  2941. // classic network
  2942. networks := NetworkManager.Query()
  2943. netifs := NetInterfaceManager.Query().SubQuery()
  2944. hosts := HostManager.Query().SubQuery()
  2945. q1 = networks
  2946. q1 = q1.Join(netifs, sqlchemy.Equals(netifs.Field("wire_id"), networks.Field("wire_id")))
  2947. q1 = q1.Join(hosts, sqlchemy.Equals(hosts.Field("id"), netifs.Field("baremetal_id")))
  2948. q1 = q1.Filter(sqlchemy.Equals(networks.Field("id"), netId))
  2949. q1 = q1.Filter(sqlchemy.Equals(hosts.Field("id"), hh.Id))
  2950. }
  2951. {
  2952. // vpc network
  2953. networks := NetworkManager.Query()
  2954. wires := WireManager.Query().SubQuery()
  2955. vpcs := VpcManager.Query().SubQuery()
  2956. regions := CloudregionManager.Query().SubQuery()
  2957. q2 = networks
  2958. q2 = q2.Join(wires, sqlchemy.Equals(wires.Field("id"), networks.Field("wire_id")))
  2959. q2 = q2.Join(vpcs, sqlchemy.Equals(vpcs.Field("id"), wires.Field("vpc_id")))
  2960. q2 = q2.Join(regions, sqlchemy.Equals(regions.Field("id"), vpcs.Field("cloudregion_id")))
  2961. q2 = q2.Filter(sqlchemy.Equals(networks.Field("id"), netId))
  2962. q2 = q2.Filter(
  2963. sqlchemy.OR(
  2964. sqlchemy.AND(
  2965. sqlchemy.Equals(regions.Field("provider"), api.CLOUD_PROVIDER_ONECLOUD),
  2966. sqlchemy.NOT(sqlchemy.Equals(vpcs.Field("id"), api.DEFAULT_VPC_ID)),
  2967. ),
  2968. sqlchemy.AND(
  2969. sqlchemy.Equals(regions.Field("provider"), api.CLOUD_PROVIDER_CLOUDPODS),
  2970. sqlchemy.NOT(sqlchemy.Equals(vpcs.Field("external_id"), api.DEFAULT_VPC_ID)),
  2971. ),
  2972. ),
  2973. )
  2974. }
  2975. {
  2976. // network additional wires
  2977. networks := NetworkManager.Query()
  2978. networkAdditionalWires := NetworkAdditionalWireManager.Query().SubQuery()
  2979. netifs := NetInterfaceManager.Query().SubQuery()
  2980. hosts := HostManager.Query().SubQuery()
  2981. q3 = networks
  2982. q3 = q3.Join(networkAdditionalWires, sqlchemy.Equals(networks.Field("id"), networkAdditionalWires.Field("network_id")))
  2983. q3 = q3.Join(netifs, sqlchemy.Equals(netifs.Field("wire_id"), networkAdditionalWires.Field("wire_id")))
  2984. q3 = q3.Join(hosts, sqlchemy.Equals(hosts.Field("id"), netifs.Field("baremetal_id")))
  2985. q3 = q3.Filter(sqlchemy.Equals(networks.Field("id"), netId))
  2986. q3 = q3.Filter(sqlchemy.Equals(hosts.Field("id"), hh.Id))
  2987. }
  2988. {
  2989. // host local network
  2990. networks := NetworkManager.Query()
  2991. wires := WireManager.Query().SubQuery()
  2992. vpcs := VpcManager.Query().SubQuery()
  2993. regions := CloudregionManager.Query().SubQuery()
  2994. q4 = networks
  2995. q4 = q4.Join(wires, sqlchemy.Equals(wires.Field("id"), networks.Field("wire_id")))
  2996. q4 = q4.Join(vpcs, sqlchemy.Equals(vpcs.Field("id"), wires.Field("vpc_id")))
  2997. q4 = q4.Join(regions, sqlchemy.Equals(regions.Field("id"), vpcs.Field("cloudregion_id")))
  2998. q4 = q4.Filter(sqlchemy.Equals(networks.Field("id"), netId))
  2999. q4 = q4.Filter(
  3000. sqlchemy.OR(
  3001. sqlchemy.AND(
  3002. sqlchemy.Equals(regions.Field("provider"), api.CLOUD_PROVIDER_ONECLOUD),
  3003. sqlchemy.Equals(vpcs.Field("id"), api.DEFAULT_VPC_ID),
  3004. sqlchemy.Equals(wires.Field("id"), computeapi.DEFAULT_HOST_LOCAL_WIRE_ID),
  3005. ),
  3006. sqlchemy.AND(
  3007. sqlchemy.Equals(regions.Field("provider"), api.CLOUD_PROVIDER_CLOUDPODS),
  3008. sqlchemy.Equals(vpcs.Field("external_id"), api.DEFAULT_VPC_ID),
  3009. sqlchemy.Equals(wires.Field("external_id"), computeapi.DEFAULT_HOST_LOCAL_WIRE_ID),
  3010. ),
  3011. ),
  3012. )
  3013. }
  3014. q := sqlchemy.Union(q1, q2, q3, q4).Query().Distinct()
  3015. net := SNetwork{}
  3016. net.SetModelManager(NetworkManager, &net)
  3017. err := q.First(&net)
  3018. if err != nil {
  3019. return nil, err
  3020. }
  3021. if reserved {
  3022. return &net, nil
  3023. }
  3024. freeCnt, err := net.getFreeAddressCount()
  3025. if err != nil {
  3026. return nil, err
  3027. }
  3028. if freeCnt > 0 {
  3029. return &net, nil
  3030. }
  3031. return nil, fmt.Errorf("No IP address")
  3032. }
  3033. func (manager *SHostManager) FetchHostById(hostId string) *SHost {
  3034. host := SHost{}
  3035. host.SetModelManager(manager, &host)
  3036. err := manager.Query().Equals("id", hostId).First(&host)
  3037. if err != nil {
  3038. log.Errorf("fetchHostById fail %s", err)
  3039. return nil
  3040. } else {
  3041. return &host
  3042. }
  3043. }
  3044. func (manager *SHostManager) FetchHostByHostname(hostname string) *SHost {
  3045. host := SHost{}
  3046. host.SetModelManager(manager, &host)
  3047. err := manager.Query().Startswith("name", hostname).First(&host)
  3048. if err != nil {
  3049. log.Errorf("fetch host by hostname %s failed %s", hostname, err)
  3050. return nil
  3051. } else {
  3052. return &host
  3053. }
  3054. }
  3055. func (manager *SHostManager) totalCountQ(
  3056. ctx context.Context,
  3057. userCred mcclient.IIdentityProvider,
  3058. scope rbacscope.TRbacScope,
  3059. rangeObjs []db.IStandaloneModel,
  3060. hostStatus, status string,
  3061. hostTypes []string,
  3062. resourceTypes []string,
  3063. providers []string, brands []string, cloudEnv string,
  3064. enabled, isBaremetal tristate.TriState,
  3065. policyResult rbacutils.SPolicyResult,
  3066. ) *sqlchemy.SQuery {
  3067. hosts := manager.Query().SubQuery()
  3068. q := hosts.Query(
  3069. hosts.Field("mem_size"),
  3070. hosts.Field("memory_used_mb"),
  3071. hosts.Field("page_size_kb"),
  3072. hosts.Field("mem_reserved"),
  3073. hosts.Field("mem_cmtbound"),
  3074. hosts.Field("cpu_count"),
  3075. hosts.Field("cpu_usage_percent"),
  3076. hosts.Field("cpu_reserved"),
  3077. hosts.Field("cpu_cmtbound"),
  3078. hosts.Field("storage_size"),
  3079. )
  3080. if scope != rbacscope.ScopeSystem && userCred != nil {
  3081. q = q.Filter(sqlchemy.Equals(hosts.Field("domain_id"), userCred.GetProjectDomainId()))
  3082. }
  3083. if len(status) > 0 {
  3084. q = q.Filter(sqlchemy.Equals(hosts.Field("status"), status))
  3085. }
  3086. if len(hostStatus) > 0 {
  3087. q = q.Filter(sqlchemy.Equals(hosts.Field("host_status"), hostStatus))
  3088. }
  3089. if !enabled.IsNone() {
  3090. cond := sqlchemy.IsFalse
  3091. if enabled.Bool() {
  3092. cond = sqlchemy.IsTrue
  3093. }
  3094. q = q.Filter(cond(hosts.Field("enabled")))
  3095. }
  3096. if !isBaremetal.IsNone() {
  3097. if isBaremetal.Bool() {
  3098. q = q.Filter(sqlchemy.AND(
  3099. sqlchemy.IsTrue(hosts.Field("is_baremetal")),
  3100. sqlchemy.Equals(hosts.Field("host_type"), api.HOST_TYPE_BAREMETAL),
  3101. ))
  3102. } else {
  3103. q = q.Filter(sqlchemy.OR(
  3104. sqlchemy.IsFalse(hosts.Field("is_baremetal")),
  3105. sqlchemy.NotEquals(hosts.Field("host_type"), api.HOST_TYPE_BAREMETAL),
  3106. ))
  3107. }
  3108. }
  3109. q = db.ObjectIdQueryWithPolicyResult(ctx, q, HostManager, policyResult)
  3110. isolatedDevices := IsolatedDeviceManager.Query().SubQuery()
  3111. iq := isolatedDevices.Query(
  3112. isolatedDevices.Field("host_id"),
  3113. sqlchemy.SUM("isolated_reserved_memory", isolatedDevices.Field("reserved_memory")),
  3114. sqlchemy.SUM("isolated_reserved_cpu", isolatedDevices.Field("reserved_cpu")),
  3115. sqlchemy.SUM("isolated_reserved_storage", isolatedDevices.Field("reserved_storage")),
  3116. ).IsNullOrEmpty("guest_id").GroupBy(isolatedDevices.Field("host_id")).SubQuery()
  3117. q = q.LeftJoin(iq, sqlchemy.Equals(q.Field("id"), iq.Field("host_id")))
  3118. q.AppendField(
  3119. iq.Field("isolated_reserved_memory"),
  3120. iq.Field("isolated_reserved_cpu"),
  3121. iq.Field("isolated_reserved_storage"),
  3122. )
  3123. q = AttachUsageQuery(q, hosts, hostTypes, resourceTypes, providers, brands, cloudEnv, rangeObjs)
  3124. // log.Debugf("hostCount: %s", q.String())
  3125. return q
  3126. }
  3127. type HostStat struct {
  3128. MemSize int
  3129. MemoryUsedMb int64
  3130. PageSizeKB int
  3131. MemReserved int
  3132. MemCmtbound float32
  3133. CpuCount int
  3134. CpuUsagePercent float64
  3135. CpuReserved int
  3136. CpuCmtbound float32
  3137. StorageSize int
  3138. IsolatedReservedMemory int64
  3139. IsolatedReservedCpu int64
  3140. IsolatedReservedStorage int64
  3141. }
  3142. type HostsCountStat struct {
  3143. StorageSize int64
  3144. Count int64
  3145. Memory int64
  3146. MemoryUsed int64
  3147. MemoryTotal int64
  3148. MemoryVirtual float64
  3149. MemoryReserved int64
  3150. CPU int64
  3151. CPUTotal int64
  3152. CPUUsed int64
  3153. CPUVirtual float64
  3154. IsolatedReservedMemory int64
  3155. IsolatedReservedCpu int64
  3156. IsolatedReservedStorage int64
  3157. }
  3158. func (manager *SHostManager) calculateCount(q *sqlchemy.SQuery) HostsCountStat {
  3159. usableSize := func(act, reserved int) int {
  3160. aSize := 0
  3161. if reserved > 0 && reserved < act {
  3162. aSize = act - reserved
  3163. } else {
  3164. aSize = act
  3165. }
  3166. return aSize
  3167. }
  3168. var (
  3169. tStore int64 = 0
  3170. tCnt int64 = 0
  3171. tMem int64 = 0
  3172. tVmem float64 = 0.0
  3173. rMem int64 = 0
  3174. tCPU int64 = 0
  3175. tVCPU float64 = 0.0
  3176. irMem int64 = 0
  3177. irCpu int64 = 0
  3178. irStore int64 = 0
  3179. totalMem int64 = 0
  3180. totalMemUsed int64 = 0
  3181. totalCPU int64 = 0
  3182. totalCPUUsed float64 = 0.0
  3183. )
  3184. stats := make([]HostStat, 0)
  3185. err := q.All(&stats)
  3186. if err != nil {
  3187. log.Errorf("%v", err)
  3188. }
  3189. for _, stat := range stats {
  3190. if stat.MemSize == 0 {
  3191. continue
  3192. }
  3193. tCnt += 1
  3194. if stat.StorageSize > 0 {
  3195. tStore += int64(stat.StorageSize)
  3196. }
  3197. aMem := usableSize(stat.MemSize, stat.MemReserved)
  3198. aCpu := usableSize(int(stat.CpuCount), int(stat.CpuReserved))
  3199. tMem += int64(aMem)
  3200. totalMem += int64(stat.MemSize)
  3201. totalMemUsed += int64(stat.MemoryUsedMb)
  3202. tCPU += int64(aCpu)
  3203. totalCPU += int64(stat.CpuCount)
  3204. totalCPUUsed += stat.CpuUsagePercent * float64(stat.CpuCount) / 100
  3205. if isHugePage(stat.PageSizeKB) {
  3206. stat.MemCmtbound = 1.0
  3207. } else if stat.MemCmtbound <= 0.0 {
  3208. stat.MemCmtbound = options.Options.DefaultMemoryOvercommitBound
  3209. }
  3210. if stat.CpuCmtbound <= 0.0 {
  3211. stat.CpuCmtbound = options.Options.DefaultCPUOvercommitBound
  3212. }
  3213. rMem += int64(stat.MemReserved)
  3214. tVmem += float64(float32(aMem) * stat.MemCmtbound)
  3215. tVCPU += float64(float32(aCpu) * stat.CpuCmtbound)
  3216. irMem += stat.IsolatedReservedMemory
  3217. irCpu += stat.IsolatedReservedCpu
  3218. irStore += stat.IsolatedReservedStorage
  3219. }
  3220. return HostsCountStat{
  3221. StorageSize: tStore,
  3222. Count: tCnt,
  3223. Memory: tMem,
  3224. MemoryUsed: totalMemUsed,
  3225. MemoryTotal: totalMem,
  3226. MemoryVirtual: tVmem,
  3227. MemoryReserved: rMem,
  3228. CPU: tCPU,
  3229. CPUUsed: int64(totalCPUUsed),
  3230. CPUTotal: totalCPU,
  3231. CPUVirtual: tVCPU,
  3232. IsolatedReservedCpu: irCpu,
  3233. IsolatedReservedMemory: irMem,
  3234. IsolatedReservedStorage: irStore,
  3235. }
  3236. }
  3237. func (manager *SHostManager) TotalCount(
  3238. ctx context.Context,
  3239. userCred mcclient.IIdentityProvider,
  3240. scope rbacscope.TRbacScope,
  3241. rangeObjs []db.IStandaloneModel,
  3242. hostStatus, status string,
  3243. hostTypes []string,
  3244. resourceTypes []string,
  3245. providers []string, brands []string, cloudEnv string,
  3246. enabled, isBaremetal tristate.TriState,
  3247. policyResult rbacutils.SPolicyResult,
  3248. ) HostsCountStat {
  3249. return manager.calculateCount(
  3250. manager.totalCountQ(
  3251. ctx,
  3252. userCred,
  3253. scope,
  3254. rangeObjs,
  3255. hostStatus,
  3256. status,
  3257. hostTypes,
  3258. resourceTypes,
  3259. providers,
  3260. brands,
  3261. cloudEnv,
  3262. enabled,
  3263. isBaremetal,
  3264. policyResult,
  3265. ),
  3266. )
  3267. }
  3268. func (hh *SHost) GetIHost(ctx context.Context) (cloudprovider.ICloudHost, error) {
  3269. host, _, err := hh.GetIHostAndProvider(ctx)
  3270. return host, err
  3271. }
  3272. func (hh *SHost) GetIHostAndProvider(ctx context.Context) (cloudprovider.ICloudHost, cloudprovider.ICloudProvider, error) {
  3273. iregion, provider, err := hh.GetIRegionAndProvider(ctx)
  3274. if err != nil {
  3275. return nil, nil, errors.Wrapf(err, "GetIRegionAndProvider")
  3276. }
  3277. ihost, err := iregion.GetIHostById(hh.ExternalId)
  3278. if err != nil {
  3279. return nil, nil, errors.Wrapf(err, "iregion.GetIHostById(%s)", hh.ExternalId)
  3280. }
  3281. return ihost, provider, nil
  3282. }
  3283. func (hh *SHost) GetIRegionAndProvider(ctx context.Context) (cloudprovider.ICloudRegion, cloudprovider.ICloudProvider, error) {
  3284. provider, err := hh.GetDriver(ctx)
  3285. if err != nil {
  3286. return nil, nil, errors.Wrapf(err, "GetDriver")
  3287. }
  3288. var iregion cloudprovider.ICloudRegion
  3289. if provider.GetFactory().IsOnPremise() {
  3290. iregion, err = provider.GetOnPremiseIRegion()
  3291. if err != nil {
  3292. return nil, nil, errors.Wrapf(err, "provider.GetOnPremiseIRegio")
  3293. }
  3294. } else {
  3295. region, err := hh.GetRegion()
  3296. if err != nil {
  3297. return nil, nil, errors.Wrapf(err, "GetRegion")
  3298. }
  3299. iregion, err = provider.GetIRegionById(region.ExternalId)
  3300. if err != nil {
  3301. return nil, nil, errors.Wrapf(err, "provider.GetIRegionById(%s)", region.ExternalId)
  3302. }
  3303. }
  3304. return iregion, provider, nil
  3305. }
  3306. func (hh *SHost) GetIRegion(ctx context.Context) (cloudprovider.ICloudRegion, error) {
  3307. region, _, err := hh.GetIRegionAndProvider(ctx)
  3308. return region, err
  3309. }
  3310. func (hh *SHost) getDiskConfig() jsonutils.JSONObject {
  3311. bs := hh.GetBaremetalstorage()
  3312. if bs != nil {
  3313. return bs.Config
  3314. }
  3315. return nil
  3316. }
  3317. func (hh *SHost) GetBaremetalServer() *SGuest {
  3318. if !hh.IsBaremetal {
  3319. return nil
  3320. }
  3321. guest := SGuest{}
  3322. guest.SetModelManager(GuestManager, &guest)
  3323. q := GuestManager.Query().Equals("host_id", hh.Id).Equals("hypervisor", api.HOST_TYPE_BAREMETAL)
  3324. err := q.First(&guest)
  3325. if err != nil {
  3326. if err != sql.ErrNoRows {
  3327. log.Errorf("query fail %s", err)
  3328. }
  3329. return nil
  3330. }
  3331. return &guest
  3332. }
  3333. type SHostGuestResourceUsage struct {
  3334. GuestCount int
  3335. GuestVcpuCount int
  3336. GuestVmemSize int
  3337. }
  3338. func (hh *SHost) getGuestsResource(status string) *SHostGuestResourceUsage {
  3339. guests := GuestManager.Query().SubQuery()
  3340. q := guests.Query(sqlchemy.COUNT("guest_count"),
  3341. sqlchemy.SUM("guest_vcpu_count", guests.Field("vcpu_count")),
  3342. sqlchemy.SUM("guest_vmem_size", guests.Field("vmem_size")))
  3343. cond := sqlchemy.OR(sqlchemy.Equals(q.Field("host_id"), hh.Id),
  3344. sqlchemy.Equals(q.Field("backup_host_id"), hh.Id))
  3345. q = q.Filter(cond)
  3346. if len(status) > 0 {
  3347. q = q.Equals("status", status)
  3348. }
  3349. stat := SHostGuestResourceUsage{}
  3350. err := q.First(&stat)
  3351. if err != nil {
  3352. log.Errorf("%s", err)
  3353. return nil
  3354. }
  3355. return &stat
  3356. }
  3357. func fetchHostGuestResource(hostIds []string, status string) (map[string]SHostGuestResourceUsage, error) {
  3358. ret := map[string]SHostGuestResourceUsage{}
  3359. // Query by host_id
  3360. {
  3361. guests := GuestManager.Query().In("host_id", hostIds)
  3362. if len(status) > 0 {
  3363. guests = guests.Equals("status", status)
  3364. }
  3365. sq := guests.SubQuery()
  3366. q := sq.Query(
  3367. sqlchemy.COUNT("id").Label("guest_count"),
  3368. sq.Field("host_id"),
  3369. sqlchemy.SUM("guest_vcpu_count", sq.Field("vcpu_count")),
  3370. sqlchemy.SUM("guest_vmem_size", sq.Field("vmem_size")),
  3371. ).GroupBy(sq.Field("host_id"))
  3372. stat := []struct {
  3373. HostId string
  3374. SHostGuestResourceUsage
  3375. }{}
  3376. if err := q.All(&stat); err != nil {
  3377. return nil, err
  3378. }
  3379. for i := range stat {
  3380. ret[stat[i].HostId] = stat[i].SHostGuestResourceUsage
  3381. }
  3382. }
  3383. // Query by backup_host_id, and attribute usage to backup host
  3384. {
  3385. guests := GuestManager.Query().In("backup_host_id", hostIds)
  3386. if len(status) > 0 {
  3387. guests = guests.Equals("status", status)
  3388. }
  3389. sq := guests.SubQuery()
  3390. backupHostId := sq.Field("backup_host_id").Label("host_id")
  3391. q := sq.Query(
  3392. sqlchemy.COUNT("id").Label("guest_count"),
  3393. backupHostId,
  3394. sqlchemy.SUM("guest_vcpu_count", sq.Field("vcpu_count")),
  3395. sqlchemy.SUM("guest_vmem_size", sq.Field("vmem_size")),
  3396. ).GroupBy(sq.Field("backup_host_id"))
  3397. stat := []struct {
  3398. HostId string
  3399. SHostGuestResourceUsage
  3400. }{}
  3401. if err := q.All(&stat); err != nil {
  3402. return nil, err
  3403. }
  3404. for i := range stat {
  3405. v := ret[stat[i].HostId]
  3406. v.GuestCount += stat[i].GuestCount
  3407. v.GuestVcpuCount += stat[i].GuestVcpuCount
  3408. v.GuestVmemSize += stat[i].GuestVmemSize
  3409. ret[stat[i].HostId] = v
  3410. }
  3411. }
  3412. return ret, nil
  3413. }
  3414. func fetchHostNics(hostIds []string) (map[string][]*types.SNic, error) {
  3415. nicQ := NetInterfaceManager.Query().In("baremetal_id", hostIds).SubQuery()
  3416. wires := WireManager.Query().SubQuery()
  3417. zones := ZoneManager.Query().SubQuery()
  3418. hn := HostnetworkManager.Query().SubQuery()
  3419. networks := NetworkManager.Query().SubQuery()
  3420. q := nicQ.Query(
  3421. nicQ.Field("mac"),
  3422. nicQ.Field("vlan_id"),
  3423. nicQ.Field("baremetal_id"),
  3424. nicQ.Field("wire_id"),
  3425. nicQ.Field("rate"),
  3426. nicQ.Field("nic_type"),
  3427. nicQ.Field("index"),
  3428. nicQ.Field("link_up"),
  3429. nicQ.Field("bridge"),
  3430. nicQ.Field("mtu"),
  3431. wires.Field("name").Label("wire"),
  3432. wires.Field("bandwidth"),
  3433. hn.Field("ip_addr"),
  3434. hn.Field("ip6_addr"),
  3435. networks.Field("guest_gateway").Label("gateway"),
  3436. networks.Field("guest_gateway6").Label("gateway6"),
  3437. networks.Field("guest_dns").Label("dns"),
  3438. networks.Field("guest_domain").Label("domain"),
  3439. networks.Field("guest_ntp").Label("ntp"),
  3440. networks.Field("guest_ip_mask").Label("masklen"),
  3441. networks.Field("guest_ip6_mask").Label("masklen6"),
  3442. networks.Field("name").Label("net"),
  3443. networks.Field("id").Label("net_id"),
  3444. zones.Field("name").Label("zone"),
  3445. )
  3446. q = q.LeftJoin(wires, sqlchemy.Equals(wires.Field("id"), nicQ.Field("wire_id")))
  3447. q = q.LeftJoin(hn, sqlchemy.AND(
  3448. sqlchemy.Equals(nicQ.Field("baremetal_id"), hn.Field("baremetal_id")),
  3449. sqlchemy.Equals(nicQ.Field("mac"), hn.Field("mac_addr")),
  3450. sqlchemy.Equals(nicQ.Field("vlan_id"), hn.Field("vlan_id")),
  3451. ))
  3452. q = q.LeftJoin(networks, sqlchemy.Equals(hn.Field("network_id"), networks.Field("id")))
  3453. q = q.LeftJoin(zones, sqlchemy.Equals(wires.Field("zone_id"), zones.Field("id")))
  3454. nics := []struct {
  3455. types.SNic
  3456. BaremetalId string
  3457. Zone string
  3458. }{}
  3459. err := q.All(&nics)
  3460. if err != nil {
  3461. return nil, err
  3462. }
  3463. ret := map[string][]*types.SNic{}
  3464. for i := range nics {
  3465. nic := nics[i]
  3466. _, ok := ret[nic.BaremetalId]
  3467. if !ok {
  3468. ret[nic.BaremetalId] = []*types.SNic{}
  3469. }
  3470. if len(nic.Gateway) > 0 && !regutils.MatchIP4Addr(nic.Gateway) {
  3471. nic.Gateway = ""
  3472. }
  3473. if len(nic.Dns) == 0 && len(nic.Zone) > 0 {
  3474. srvs, _ := auth.GetDNSServers(options.Options.Region, nic.Zone)
  3475. if len(srvs) > 0 {
  3476. nic.Dns = strings.Join(srvs, ",")
  3477. } else {
  3478. nic.Dns = options.Options.DNSServer
  3479. }
  3480. }
  3481. if len(nic.Domain) == 0 {
  3482. nic.Domain = options.Options.DNSDomain
  3483. }
  3484. if len(nic.Ntp) == 0 && len(nic.Zone) > 0 {
  3485. srvs, _ := auth.GetNTPServers(options.Options.Region, nic.Zone)
  3486. if len(srvs) > 0 {
  3487. nic.Ntp = strings.Join(srvs, ",")
  3488. }
  3489. }
  3490. ret[nic.BaremetalId] = append(ret[nic.BaremetalId], &nic.SNic)
  3491. }
  3492. return ret, nil
  3493. }
  3494. func fetchHostStorages(hostIds []string) (map[string]*SStorageCapacity, error) {
  3495. hoststorages := HoststorageManager.Query().In("host_id", hostIds).SubQuery()
  3496. storageQ := StorageManager.Query().IsTrue("enabled").NotEquals("storage_type", api.STORAGE_BAREMETAL).In("storage_type", api.HOST_STORAGE_LOCAL_TYPES).SubQuery()
  3497. diskReadySQ := DiskManager.Query().Equals("status", api.DISK_READY).SubQuery()
  3498. diskReadyQ := diskReadySQ.Query(sqlchemy.SUM("sum", diskReadySQ.Field("disk_size")).Label("used")).GroupBy(diskReadySQ.Field("storage_id"))
  3499. readySQ := diskReadyQ.SubQuery()
  3500. diskWasteSQ := DiskManager.Query().NotEquals("status", api.DISK_READY).SubQuery()
  3501. diskWasteQ := diskWasteSQ.Query(sqlchemy.SUM("sum", diskWasteSQ.Field("disk_size")).Label("wasted")).GroupBy(diskWasteSQ.Field("storage_id"))
  3502. wasteSQ := diskWasteQ.SubQuery()
  3503. q := storageQ.Query(
  3504. storageQ.Field("id"),
  3505. storageQ.Field("capacity"),
  3506. storageQ.Field("reserved"),
  3507. hoststorages.Field("host_id"),
  3508. storageQ.Field("cmtbound"),
  3509. storageQ.Field("actual_capacity_used"),
  3510. readySQ.Field("used"),
  3511. wasteSQ.Field("wasted"),
  3512. )
  3513. q = q.Join(hoststorages, sqlchemy.Equals(q.Field("id"), hoststorages.Field("storage_id")))
  3514. q = q.LeftJoin(readySQ, sqlchemy.Equals(readySQ.Field("storage_id"), storageQ.Field("id")))
  3515. q = q.LeftJoin(wasteSQ, sqlchemy.Equals(wasteSQ.Field("storage_id"), storageQ.Field("id")))
  3516. values := []struct {
  3517. HostId string
  3518. Capacity int64
  3519. Reserved int64
  3520. Cmtbound float32
  3521. ActualCapacityUsed int64
  3522. Used int64
  3523. Wasted int64
  3524. }{}
  3525. err := q.All(&values)
  3526. if err != nil {
  3527. return nil, err
  3528. }
  3529. ret := map[string]*SStorageCapacity{}
  3530. for i := range values {
  3531. v := values[i]
  3532. _, ok := ret[v.HostId]
  3533. if !ok {
  3534. ret[v.HostId] = &SStorageCapacity{}
  3535. }
  3536. capa := SStorageCapacity{}
  3537. capa.Capacity = v.Capacity - v.Reserved
  3538. capa.Used = v.Used
  3539. capa.Wasted = v.Wasted
  3540. cmtbound := options.Options.DefaultStorageOvercommitBound
  3541. if v.Cmtbound > 0 {
  3542. cmtbound = v.Cmtbound
  3543. }
  3544. capa.VCapacity = int64(float32(capa.Capacity) * cmtbound)
  3545. capa.ActualUsed = v.ActualCapacityUsed
  3546. ret[v.HostId].Add(capa)
  3547. }
  3548. return ret, nil
  3549. }
  3550. func fetchHostSchedtags(hostIds []string) (map[string][]api.SchedtagShortDescDetails, error) {
  3551. schedtags := SchedtagManager.Query().SubQuery()
  3552. objschedtags := HostschedtagManager.Query().SubQuery()
  3553. q := schedtags.Query(
  3554. objschedtags.Field("host_id"),
  3555. schedtags.Field("id"),
  3556. schedtags.Field("name"),
  3557. schedtags.Field("default_strategy").Label("default"),
  3558. sqlchemy.NewStringField("schedtag").Label("res_name"),
  3559. )
  3560. q = q.Join(objschedtags, sqlchemy.AND(sqlchemy.Equals(objschedtags.Field("schedtag_id"), schedtags.Field("id")),
  3561. sqlchemy.IsFalse(objschedtags.Field("deleted"))))
  3562. q = q.Filter(sqlchemy.In(objschedtags.Field("host_id"), hostIds))
  3563. tags := []struct {
  3564. Id string
  3565. HostId string
  3566. Name string
  3567. ResName string
  3568. Default string
  3569. }{}
  3570. err := q.All(&tags)
  3571. if err != nil {
  3572. return nil, err
  3573. }
  3574. ret := map[string][]api.SchedtagShortDescDetails{}
  3575. for i := range tags {
  3576. _, ok := ret[tags[i].HostId]
  3577. if !ok {
  3578. ret[tags[i].HostId] = []api.SchedtagShortDescDetails{}
  3579. }
  3580. tag := api.SchedtagShortDescDetails{}
  3581. jsonutils.Update(&tag, tags[i])
  3582. ret[tags[i].HostId] = append(ret[tags[i].HostId], tag)
  3583. }
  3584. return ret, nil
  3585. }
  3586. type sGuestCnt struct {
  3587. GuestCnt int
  3588. BackupGuestCnt int
  3589. RunningGuestCnt int
  3590. ReadyGuestCnt int
  3591. OtherGuestCnt int
  3592. PendingDeletedGuestCnt int
  3593. NonsystemGuestCnt int
  3594. }
  3595. func (manager *SHostManager) FetchGuestCnt(hostIds []string) map[string]*sGuestCnt {
  3596. ret := map[string]*sGuestCnt{}
  3597. if len(hostIds) == 0 {
  3598. return ret
  3599. }
  3600. guests := []SGuest{}
  3601. err := GuestManager.RawQuery().IsFalse("deleted").In("host_id", hostIds).NotEquals("hypervisor", api.HYPERVISOR_POD).All(&guests)
  3602. if err != nil {
  3603. log.Errorf("query host %s guests error: %v", hostIds, err)
  3604. }
  3605. for _, guest := range guests {
  3606. _, ok := ret[guest.HostId]
  3607. if !ok {
  3608. ret[guest.HostId] = &sGuestCnt{}
  3609. }
  3610. if guest.PendingDeleted {
  3611. ret[guest.HostId].PendingDeletedGuestCnt += 1
  3612. continue
  3613. }
  3614. ret[guest.HostId].GuestCnt += 1
  3615. switch guest.Status {
  3616. case api.VM_RUNNING:
  3617. ret[guest.HostId].RunningGuestCnt += 1
  3618. case api.VM_READY:
  3619. ret[guest.HostId].ReadyGuestCnt += 1
  3620. default:
  3621. ret[guest.HostId].OtherGuestCnt += 1
  3622. }
  3623. if !guest.IsSystem {
  3624. ret[guest.HostId].NonsystemGuestCnt += 1
  3625. }
  3626. }
  3627. GuestManager.RawQuery().IsFalse("deleted").In("backup_host_id", hostIds).NotEquals("hypervisor", api.HYPERVISOR_POD).All(&guests)
  3628. for _, guest := range guests {
  3629. _, ok := ret[guest.BackupHostId]
  3630. if !ok {
  3631. ret[guest.BackupHostId] = &sGuestCnt{}
  3632. }
  3633. ret[guest.BackupHostId].BackupGuestCnt += 1
  3634. }
  3635. return ret
  3636. }
  3637. func (hh *SHost) GetReservedResourceForIsolatedDevice() (int, *api.IsolatedDeviceReservedResourceInput) {
  3638. if devs := IsolatedDeviceManager.FindByHost(hh.Id); len(devs) == 0 {
  3639. return -1, nil
  3640. } else {
  3641. return len(devs), hh.GetDevsReservedResource(devs)
  3642. }
  3643. }
  3644. func (hh *SHost) GetDevsReservedResource(devs []SIsolatedDevice) *api.IsolatedDeviceReservedResourceInput {
  3645. reservedCpu, reservedMem, reservedStorage := 0, 0, 0
  3646. reservedResourceForGpu := api.IsolatedDeviceReservedResourceInput{
  3647. ReservedStorage: &reservedStorage,
  3648. ReservedMemory: &reservedMem,
  3649. ReservedCpu: &reservedCpu,
  3650. }
  3651. for _, dev := range devs {
  3652. if !utils.IsInStringArray(dev.DevType, api.VALID_GPU_TYPES) {
  3653. continue
  3654. }
  3655. reservedCpu += dev.ReservedCpu
  3656. reservedMem += dev.ReservedMemory
  3657. reservedStorage += dev.ReservedStorage
  3658. }
  3659. return &reservedResourceForGpu
  3660. }
  3661. func (hh *SHost) GetMetadataHiddenKeys() []string {
  3662. return []string{}
  3663. }
  3664. func (manager *SHostManager) FetchCustomizeColumns(
  3665. ctx context.Context,
  3666. userCred mcclient.TokenCredential,
  3667. query jsonutils.JSONObject,
  3668. objs []interface{},
  3669. fields stringutils2.SSortedStrings,
  3670. isList bool,
  3671. ) []api.HostDetails {
  3672. rows := make([]api.HostDetails, len(objs))
  3673. stdRows := manager.SEnabledStatusInfrasResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
  3674. managerRows := manager.SManagedResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
  3675. zoneRows := manager.SZoneResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
  3676. showReason := false
  3677. if query.Contains("show_fail_reason") {
  3678. showReason = true
  3679. }
  3680. var hideCpuTypoInfo = jsonutils.QueryBoolean(query, "hide_cpu_topo_info", false)
  3681. hostIds := make([]string, len(objs))
  3682. hosts := make([]*SHost, len(objs))
  3683. for i := range rows {
  3684. rows[i] = api.HostDetails{
  3685. EnabledStatusInfrasResourceBaseDetails: stdRows[i],
  3686. ManagedResourceInfo: managerRows[i],
  3687. ZoneResourceInfo: zoneRows[i],
  3688. }
  3689. host := objs[i].(*SHost)
  3690. hostIds[i] = host.Id
  3691. hosts[i] = host
  3692. }
  3693. baremetalServers, err := fetchBaremetalServer(hostIds)
  3694. if err != nil {
  3695. log.Errorf("fetchBaremetalServer error: %v", err)
  3696. return rows
  3697. }
  3698. serverIds := []string{}
  3699. for _, server := range baremetalServers {
  3700. serverIds = append(serverIds, server.Id)
  3701. }
  3702. serverIps := fetchGuestIPs(serverIds, tristate.False)
  3703. status := ""
  3704. if options.Options.IgnoreNonrunningGuests {
  3705. status = api.VM_RUNNING
  3706. }
  3707. guestResources, err := fetchHostGuestResource(hostIds, status)
  3708. if err != nil {
  3709. log.Errorf("fetchHostGuestResource error: %v", err)
  3710. return rows
  3711. }
  3712. metas := []db.SMetadata{}
  3713. err = db.Metadata.Query().In("obj_id", hostIds).In("key", []string{api.HOSTMETA_AUTO_MIGRATE_ON_HOST_DOWN, api.HOSTMETA_AUTO_MIGRATE_ON_HOST_SHUTDOWN}).All(&metas)
  3714. if err != nil {
  3715. log.Errorf("query meta error: %v", err)
  3716. return rows
  3717. }
  3718. downMap, shutdownMap := map[string]bool{}, map[string]bool{}
  3719. for _, meta := range metas {
  3720. switch meta.Key {
  3721. case api.HOSTMETA_AUTO_MIGRATE_ON_HOST_DOWN:
  3722. downMap[meta.ObjId] = (meta.Value == "enable")
  3723. case api.HOSTMETA_AUTO_MIGRATE_ON_HOST_SHUTDOWN:
  3724. shutdownMap[meta.ObjId] = (meta.Value == "enable")
  3725. }
  3726. }
  3727. isolatedDevices := IsolatedDeviceManager.FindByHosts(hostIds)
  3728. isolatedDeviceMap := map[string][]SIsolatedDevice{}
  3729. for i := range isolatedDevices {
  3730. _, ok := isolatedDeviceMap[isolatedDevices[i].HostId]
  3731. if !ok {
  3732. isolatedDeviceMap[isolatedDevices[i].HostId] = []SIsolatedDevice{}
  3733. }
  3734. isolatedDeviceMap[isolatedDevices[i].HostId] = append(isolatedDeviceMap[isolatedDevices[i].HostId], isolatedDevices[i])
  3735. }
  3736. schedtags, err := fetchHostSchedtags(hostIds)
  3737. if err != nil {
  3738. log.Errorf("fetchHostSchedtags error: %v", err)
  3739. // return rows
  3740. }
  3741. storages, err := fetchHostStorages(hostIds)
  3742. if err != nil {
  3743. log.Errorf("host storages error: %v", err)
  3744. // return rows
  3745. }
  3746. nics, err := fetchHostNics(hostIds)
  3747. if err != nil {
  3748. log.Errorf("fetchHostNics error: %v", err)
  3749. // return rows
  3750. }
  3751. guestCnts := manager.FetchGuestCnt(hostIds)
  3752. hostFiles, err := fetchHostHostFiles(hostIds)
  3753. if err != nil {
  3754. log.Errorf("fetchHostHostFiles error: %v", err)
  3755. }
  3756. for i := range rows {
  3757. cnt, ok := guestCnts[hostIds[i]]
  3758. if ok {
  3759. rows[i].Guests = cnt.GuestCnt
  3760. rows[i].RunningGuests = cnt.RunningGuestCnt
  3761. rows[i].ReadyGuests = cnt.ReadyGuestCnt
  3762. rows[i].OtherGuests = cnt.OtherGuestCnt
  3763. rows[i].NonsystemGuests = cnt.NonsystemGuestCnt
  3764. rows[i].PendingDeletedGuests = cnt.PendingDeletedGuestCnt
  3765. }
  3766. if server, ok := baremetalServers[hostIds[i]]; ok {
  3767. rows[i].ServerId = server.Id
  3768. rows[i].Server = server.Name
  3769. rows[i].ServerPendingDeleted = server.PendingDeleted
  3770. if hosts[i].HostType == api.HOST_TYPE_BAREMETAL && len(serverIps) > 0 {
  3771. if ips, _ := serverIps[server.Id]; len(ips) > 0 {
  3772. rows[i].ServerIps = strings.Join(ips, ",")
  3773. }
  3774. }
  3775. }
  3776. if hosts[i].EnableHealthCheck && hostHealthChecker != nil {
  3777. rows[i].AllowHealthCheck = true
  3778. }
  3779. rows[i].AutoMigrateOnHostDown = downMap[hostIds[i]]
  3780. rows[i].AutoMigrateOnHostShutdown = shutdownMap[hostIds[i]]
  3781. if hosts[i].IsBaremetal {
  3782. rows[i].CanPrepare = true
  3783. if server := baremetalServers[hostIds[i]]; server != nil && server.Status != api.VM_ADMIN {
  3784. rows[i].CanPrepare = false
  3785. if showReason {
  3786. rows[i].PrepareFailReason = fmt.Sprintf("Cannot prepare baremetal in server status %s", server.Status)
  3787. }
  3788. }
  3789. err := hosts[i].canPrepare()
  3790. if err != nil && rows[i].CanPrepare {
  3791. rows[i].CanPrepare = false
  3792. if showReason {
  3793. rows[i].PrepareFailReason = err.Error()
  3794. }
  3795. }
  3796. }
  3797. if !isList {
  3798. pinnedCpus, _ := hosts[i].GetPinnedCpusetCores(ctx, userCred, nil)
  3799. if pinnedCpus != nil {
  3800. rows[i].GuestPinnedCpus = pinnedCpus.ToSlice()
  3801. }
  3802. }
  3803. if usage, ok := guestResources[hostIds[i]]; ok {
  3804. rows[i].CpuCommit = usage.GuestVcpuCount
  3805. rows[i].MemCommit = usage.GuestVmemSize
  3806. totalCpu := hosts[i].GetCpuCount()
  3807. cpuCommitRate := 0.0
  3808. if totalCpu > 0 && usage.GuestVcpuCount > 0 {
  3809. cpuCommitRate = float64(usage.GuestVcpuCount) * 1.0 / float64(totalCpu)
  3810. }
  3811. rows[i].CpuCommitRate = cpuCommitRate
  3812. totalMem := hosts[i].GetMemSize()
  3813. memCommitRate := 0.0
  3814. if totalMem > 0 && usage.GuestVmemSize > 0 {
  3815. memCommitRate = float64(usage.GuestVmemSize) * 1.0 / float64(totalMem)
  3816. }
  3817. rows[i].MemCommitRate = memCommitRate
  3818. }
  3819. if devs, ok := isolatedDeviceMap[hostIds[i]]; ok {
  3820. rows[i].IsolatedDeviceCount = len(devs)
  3821. for j := range devs {
  3822. dev := devs[j]
  3823. if rows[i].IsolatedDeviceTypeCount == nil {
  3824. rows[i].IsolatedDeviceTypeCount = make(map[string]int, 0)
  3825. }
  3826. if cnt, ok := rows[i].IsolatedDeviceTypeCount[dev.DevType]; ok {
  3827. rows[i].IsolatedDeviceTypeCount[dev.DevType] = cnt + 1
  3828. } else {
  3829. rows[i].IsolatedDeviceTypeCount[dev.DevType] = 1
  3830. }
  3831. }
  3832. rows[i].ReservedResourceForGpu = hosts[i].GetDevsReservedResource(devs)
  3833. }
  3834. if capa, ok := storages[hostIds[i]]; ok {
  3835. rows[i].Storage = capa.Capacity
  3836. rows[i].StorageUsed = capa.Used
  3837. rows[i].ActualStorageUsed = capa.ActualUsed
  3838. rows[i].StorageWaste = capa.Wasted
  3839. rows[i].StorageVirtual = capa.VCapacity
  3840. rows[i].StorageFree = capa.GetFree()
  3841. rows[i].StorageCommitRate = capa.GetCommitRate()
  3842. }
  3843. rows[i].IsPrepaidRecycle = hosts[i].IsPrepaidRecycle()
  3844. rows[i].CpuCommitBound = hosts[i].GetCPUOvercommitBound()
  3845. rows[i].MemCommitBound = hosts[i].GetMemoryOvercommitBound()
  3846. rows[i].Spec = hosts[i].GetHardwareSpecification()
  3847. rows[i].Schedtags, _ = schedtags[hostIds[i]]
  3848. rows[i].NicInfo, _ = nics[hostIds[i]]
  3849. rows[i].NicCount = len(rows[i].NicInfo)
  3850. rows[i].HostFiles = hostFiles[hostIds[i]]
  3851. if hideCpuTypoInfo {
  3852. sysInfo, ok := hosts[i].SysInfo.(*jsonutils.JSONDict)
  3853. if ok {
  3854. sysInfo.Remove("cpu_info")
  3855. sysInfo.Remove("topology")
  3856. }
  3857. delete(rows[i].Metadata, "cpu_info")
  3858. delete(rows[i].Metadata, "topology")
  3859. }
  3860. }
  3861. return rows
  3862. }
  3863. type SInfrasStatusInfo struct {
  3864. apis.TotalCountBase
  3865. StatusInfo []apis.StatusStatisticStatusInfo
  3866. }
  3867. type SHostTotalCount struct {
  3868. SInfrasStatusInfo
  3869. MemoryUsed int64
  3870. MemoryTotal int64
  3871. CPUUsed int64
  3872. CPUTotal int64
  3873. }
  3874. func (manager *SHostManager) CustomizedTotalCount(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, totalQ *sqlchemy.SQuery) (int, jsonutils.JSONObject, error) {
  3875. results := SHostTotalCount{}
  3876. totalQ = totalQ.AppendField(sqlchemy.SUM("cpu_total", totalQ.Field("cpu_count")))
  3877. totalQ = totalQ.AppendField(sqlchemy.SUM("memory_total", totalQ.Field("mem_size")))
  3878. totalQ = totalQ.AppendField(sqlchemy.SUM("memory_used", totalQ.Field("memory_used_mb")))
  3879. totalQ = totalQ.AppendField(sqlchemy.CASTInt(sqlchemy.SUM("cpu_used", sqlchemy.MUL("use_cpu", totalQ.Field("cpu_usage_percent"), totalQ.Field("cpu_count"), sqlchemy.NewConstField(0.01))), "cpu_used"))
  3880. err := totalQ.First(&results)
  3881. if err != nil && errors.Cause(err) != sql.ErrNoRows {
  3882. return -1, nil, errors.Wrapf(err, "First")
  3883. }
  3884. _, statusInfo, err := manager.SEnabledStatusInfrasResourceBaseManager.CustomizedTotalCount(ctx, userCred, query, totalQ)
  3885. if err != nil {
  3886. return -1, nil, errors.Wrapf(err, "virt.CustomizedTotalCount")
  3887. }
  3888. statusInfo.Unmarshal(&results.SInfrasStatusInfo)
  3889. log.Debugf("CustomizedTotalCount %s", jsonutils.Marshal(results))
  3890. return results.Count, jsonutils.Marshal(results), nil
  3891. }
  3892. func fetchBaremetalServer(hostIds []string) (map[string]*SGuest, error) {
  3893. guests := []SGuest{}
  3894. err := GuestManager.Query().In("host_id", hostIds).Equals("hypervisor", api.HOST_TYPE_BAREMETAL).All(&guests)
  3895. if err != nil {
  3896. return nil, err
  3897. }
  3898. ret := map[string]*SGuest{}
  3899. for i := range guests {
  3900. ret[guests[i].HostId] = &guests[i]
  3901. }
  3902. return ret, nil
  3903. }
  3904. func (hh *SHost) GetDetailsVnc(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) (jsonutils.JSONObject, error) {
  3905. if utils.IsInStringArray(hh.Status, []string{api.BAREMETAL_READY, api.BAREMETAL_RUNNING}) {
  3906. retval := jsonutils.NewDict()
  3907. retval.Set("host_id", jsonutils.NewString(hh.Id))
  3908. zone, _ := hh.GetZone()
  3909. retval.Set("zone", jsonutils.NewString(zone.GetName()))
  3910. return retval, nil
  3911. }
  3912. return jsonutils.NewDict(), nil
  3913. }
  3914. func (hh *SHost) GetDetailsIpmi(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) (jsonutils.JSONObject, error) {
  3915. ret, ok := hh.IpmiInfo.(*jsonutils.JSONDict)
  3916. if !ok {
  3917. return nil, httperrors.NewNotFoundError("No ipmi information was found for host %s", hh.Name)
  3918. }
  3919. password, err := ret.GetString("password")
  3920. if err != nil {
  3921. return nil, httperrors.NewNotFoundError("IPMI has no password information")
  3922. }
  3923. descryptedPassword, err := utils.DescryptAESBase64(hh.Id, password)
  3924. if err != nil {
  3925. return nil, err
  3926. }
  3927. ret.Set("password", jsonutils.NewString(descryptedPassword))
  3928. return ret, nil
  3929. }
  3930. func (manager *SHostManager) GetHostsByManagerAndRegion(managerId string, regionId string) []SHost {
  3931. zones := ZoneManager.Query().Equals("cloudregion_id", regionId).SubQuery()
  3932. hosts := HostManager.Query()
  3933. q := hosts.Equals("manager_id", managerId)
  3934. q = q.Join(zones, sqlchemy.Equals(zones.Field("id"), hosts.Field("zone_id")))
  3935. ret := make([]SHost, 0)
  3936. err := db.FetchModelObjects(HostManager, q, &ret)
  3937. if err != nil {
  3938. log.Errorf("GetHostsByManagerAndRegion fail %s", err)
  3939. return nil
  3940. }
  3941. return ret
  3942. }
  3943. func (hh *SHost) RequestScanIsolatedDevices(ctx context.Context, userCred mcclient.TokenCredential) error {
  3944. _, err := hh.Request(ctx, userCred, "POST", fmt.Sprintf("/hosts/%s/probe-isolated-devices", hh.Id), mcclient.GetTokenHeaders(userCred), nil)
  3945. if err != nil {
  3946. return errors.Wrapf(err, "request host %s probe isolaed devices", hh.Id)
  3947. }
  3948. return nil
  3949. }
  3950. func (hh *SHost) Request(ctx context.Context, userCred mcclient.TokenCredential, method httputils.THttpMethod, url string, headers http.Header, body jsonutils.JSONObject) (jsonutils.JSONObject, error) {
  3951. s := auth.GetSession(ctx, userCred, "")
  3952. _, ret, err := s.JSONRequest(hh.ManagerUri, "", method, url, headers, body)
  3953. return ret, err
  3954. }
  3955. func (hh *SHost) GetLocalStoragecache() *SStoragecache {
  3956. localStorages := hh.GetAttachedLocalStorages()
  3957. for i := 0; i < len(localStorages); i += 1 {
  3958. sc := localStorages[i].GetStoragecache()
  3959. if sc != nil {
  3960. return sc
  3961. }
  3962. }
  3963. return nil
  3964. }
  3965. func (hh *SHost) GetStoragecache() *SStoragecache {
  3966. localStorages := hh.GetAttachedEnabledHostStorages(nil)
  3967. for i := 0; i < len(localStorages); i += 1 {
  3968. sc := localStorages[i].GetStoragecache()
  3969. if sc != nil {
  3970. return sc
  3971. }
  3972. }
  3973. return nil
  3974. }
  3975. func (hh *SHost) PostCreate(
  3976. ctx context.Context,
  3977. userCred mcclient.TokenCredential,
  3978. ownerId mcclient.IIdentityProvider,
  3979. query jsonutils.JSONObject,
  3980. data jsonutils.JSONObject,
  3981. ) {
  3982. hh.SEnabledStatusInfrasResourceBase.PostCreate(ctx, userCred, ownerId, query, data)
  3983. input := api.HostCreateInput{}
  3984. err := data.Unmarshal(&input)
  3985. if err != nil {
  3986. log.Errorf("data.Unmarshal fail %s", err)
  3987. return
  3988. }
  3989. kwargs := data.(*jsonutils.JSONDict)
  3990. ipmiInfo, err := fetchIpmiInfo(input.HostIpmiAttributes, hh.Id)
  3991. if err != nil {
  3992. log.Errorf("fetchIpmiInfo fail %s", err)
  3993. return
  3994. }
  3995. ipmiInfoJson := jsonutils.Marshal(ipmiInfo).(*jsonutils.JSONDict)
  3996. if ipmiInfoJson.Length() > 0 {
  3997. _, err := hh.SaveUpdates(func() error {
  3998. hh.IpmiInfo = ipmiInfoJson
  3999. return nil
  4000. })
  4001. if err != nil {
  4002. log.Errorf("save updates: %v", err)
  4003. } else if len(ipmiInfo.IpAddr) > 0 {
  4004. hh.setIpmiIp(userCred, ipmiInfo.IpAddr)
  4005. }
  4006. }
  4007. if len(input.AccessIp) > 0 {
  4008. hh.setAccessIp(userCred, input.AccessIp)
  4009. }
  4010. if len(input.AccessMac) > 0 {
  4011. hh.setAccessMac(userCred, input.AccessMac)
  4012. }
  4013. noProbe := false
  4014. if input.NoProbe != nil {
  4015. noProbe = *input.NoProbe
  4016. }
  4017. if len(hh.ZoneId) > 0 && hh.HostType == api.HOST_TYPE_BAREMETAL && !noProbe {
  4018. // ipmiInfo, _ := hh.GetIpmiInfo()
  4019. if len(ipmiInfo.IpAddr) > 0 {
  4020. hh.StartBaremetalCreateTask(ctx, userCred, kwargs, "")
  4021. }
  4022. }
  4023. if hh.OvnVersion != "" && hh.OvnMappedIpAddr == "" {
  4024. HostManager.lockAllocOvnMappedIpAddr(ctx)
  4025. defer HostManager.unlockAllocOvnMappedIpAddr(ctx)
  4026. addr, err := HostManager.allocOvnMappedIpAddr(ctx)
  4027. if err != nil {
  4028. log.Errorf("host %s(%s): alloc vpc mapped addr: %v",
  4029. hh.Name, hh.Id, err)
  4030. }
  4031. if _, err := db.Update(hh, func() error {
  4032. hh.OvnMappedIpAddr = addr
  4033. hh.OvnMappedIp6Addr = api.GenVpcMappedIP6(addr)
  4034. return nil
  4035. }); err != nil {
  4036. log.Errorf("host %s(%s): db update vpc mapped addr: %v",
  4037. hh.Name, hh.Id, err)
  4038. }
  4039. }
  4040. keys := GetHostQuotaKeysFromCreateInput(ownerId, input)
  4041. quota := SInfrasQuota{Host: 1}
  4042. quota.SetKeys(keys)
  4043. err = quotas.CancelPendingUsage(ctx, userCred, &quota, &quota, true)
  4044. if err != nil {
  4045. log.Errorf("CancelPendingUsage fail %s", err)
  4046. }
  4047. hh.SEnabledStatusInfrasResourceBase.PostCreate(ctx, userCred, ownerId, query, data)
  4048. notifyclient.EventNotify(ctx, userCred, notifyclient.SEventNotifyParam{
  4049. Obj: hh,
  4050. Action: notifyclient.ActionCreate,
  4051. })
  4052. }
  4053. func (hh *SHost) StartBaremetalCreateTask(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict, parentTaskId string) error {
  4054. if task, err := taskman.TaskManager.NewTask(ctx, "BaremetalCreateTask", hh, userCred, data, parentTaskId, "", nil); err != nil {
  4055. log.Errorln(err)
  4056. return err
  4057. } else {
  4058. task.ScheduleRun(nil)
  4059. return nil
  4060. }
  4061. }
  4062. func (manager *SHostManager) ValidateSizeParams(input api.HostSizeAttributes) (api.HostSizeAttributes, error) {
  4063. memStr := input.MemSize
  4064. if len(memStr) > 0 {
  4065. if !regutils.MatchSize(memStr) {
  4066. return input, errors.Wrap(httperrors.ErrInputParameter, "Memory size must be number[+unit], like 256M, 1G or 256")
  4067. }
  4068. memSize, err := fileutils.GetSizeMb(memStr, 'M', 1024)
  4069. if err != nil {
  4070. return input, errors.Wrap(err, "fileutils.GetSizeMb")
  4071. }
  4072. input.MemSize = strconv.FormatInt(int64(memSize), 10)
  4073. // data.Set("mem_size", jsonutils.NewInt(int64(memSize)))
  4074. }
  4075. memReservedStr := input.MemReserved
  4076. if len(memReservedStr) > 0 {
  4077. if !regutils.MatchSize(memReservedStr) {
  4078. return input, errors.Wrap(httperrors.ErrInputParameter, "Memory size must be number[+unit], like 256M, 1G or 256")
  4079. }
  4080. memSize, err := fileutils.GetSizeMb(memReservedStr, 'M', 1024)
  4081. if err != nil {
  4082. return input, errors.Wrap(err, "fileutils.GetSizeMb")
  4083. }
  4084. input.MemReserved = strconv.FormatInt(int64(memSize), 10)
  4085. // data.Set("mem_reserved", jsonutils.NewInt(int64(memSize)))
  4086. }
  4087. cpuCacheStr := input.CpuCache
  4088. if len(cpuCacheStr) > 0 {
  4089. if !regutils.MatchSize(cpuCacheStr) {
  4090. return input, errors.Wrapf(httperrors.ErrInputParameter, "Illegal cpu cache size %s", cpuCacheStr)
  4091. }
  4092. cpuCache, err := fileutils.GetSizeKb(cpuCacheStr, 'K', 1024)
  4093. if err != nil {
  4094. return input, errors.Wrap(err, "fileutils.GetSizeKb")
  4095. }
  4096. input.CpuCache = strconv.FormatInt(int64(cpuCache), 10)
  4097. // data.Set("cpu_cache", jsonutils.NewInt(int64(cpuCache)))
  4098. }
  4099. return input, nil
  4100. }
  4101. func (manager *SHostManager) inputUniquenessCheck(input api.HostAccessAttributes, zoneId string, hostId string) (api.HostAccessAttributes, error) {
  4102. for key, val := range map[string]string{
  4103. "manager_uri": input.ManagerUri,
  4104. "access_ip": input.AccessIp,
  4105. } {
  4106. if len(val) > 0 {
  4107. q := manager.Query().Equals(key, val)
  4108. if len(zoneId) > 0 {
  4109. q = q.Equals("zone_id", zoneId)
  4110. } else {
  4111. q = q.IsNullOrEmpty("zone_id")
  4112. }
  4113. if len(hostId) > 0 {
  4114. q = q.NotEquals("id", hostId)
  4115. }
  4116. cnt, err := q.CountWithError()
  4117. if err != nil {
  4118. return input, httperrors.NewInternalServerError("check %s duplication fail %s", key, err)
  4119. }
  4120. if cnt > 0 {
  4121. return input, httperrors.NewConflictError("duplicate %s %s", key, val)
  4122. }
  4123. }
  4124. }
  4125. accessMac := input.AccessMac
  4126. if len(accessMac) > 0 {
  4127. accessMac2 := netutils.FormatMacAddr(accessMac)
  4128. if len(accessMac2) == 0 {
  4129. return input, httperrors.NewInputParameterError("invalid macAddr %s", accessMac)
  4130. }
  4131. if accessMac2 != api.ACCESS_MAC_ANY {
  4132. q := manager.Query().Equals("access_mac", accessMac2)
  4133. if len(hostId) > 0 {
  4134. q = q.NotEquals("id", hostId)
  4135. }
  4136. cnt, err := q.CountWithError()
  4137. if err != nil {
  4138. return input, httperrors.NewInternalServerError("check access_mac duplication fail %s", err)
  4139. }
  4140. if cnt > 0 {
  4141. return input, httperrors.NewConflictError("duplicate access_mac %s", accessMac)
  4142. }
  4143. input.AccessMac = accessMac2
  4144. }
  4145. }
  4146. return input, nil
  4147. }
  4148. func (manager *SHostManager) ValidateCreateData(
  4149. ctx context.Context,
  4150. userCred mcclient.TokenCredential,
  4151. ownerId mcclient.IIdentityProvider,
  4152. query jsonutils.JSONObject,
  4153. input api.HostCreateInput,
  4154. ) (api.HostCreateInput, error) {
  4155. var err error
  4156. if len(input.ZoneId) > 0 {
  4157. _, input.ZoneResourceInput, err = ValidateZoneResourceInput(ctx, userCred, input.ZoneResourceInput)
  4158. if err != nil {
  4159. return input, errors.Wrap(err, "ValidateZoneResourceInput")
  4160. }
  4161. }
  4162. noProbe := false
  4163. if input.NoProbe != nil {
  4164. noProbe = *input.NoProbe
  4165. }
  4166. input.HostAccessAttributes, err = manager.inputUniquenessCheck(input.HostAccessAttributes, input.ZoneId, "")
  4167. if err != nil {
  4168. return input, errors.Wrap(err, "manager.inputUniquenessCheck")
  4169. }
  4170. input.HostSizeAttributes, err = manager.ValidateSizeParams(input.HostSizeAttributes)
  4171. if err != nil {
  4172. return input, errors.Wrap(err, "manager.ValidateSizeParams")
  4173. }
  4174. if len(input.MemReserved) == 0 {
  4175. if input.HostType != api.HOST_TYPE_BAREMETAL {
  4176. memSize, _ := strconv.ParseInt(input.MemSize, 10, 64)
  4177. memReserved := memSize / 8
  4178. if memReserved > 4096 {
  4179. memReserved = 4096
  4180. }
  4181. input.MemReserved = strconv.FormatInt(memReserved, 10)
  4182. // data.Set("mem_reserved", jsonutils.NewInt(memReserved))
  4183. } else {
  4184. input.MemReserved = "0"
  4185. // data.Set("mem_reserved", jsonutils.NewInt(0))
  4186. }
  4187. }
  4188. ipmiInfo, err := fetchIpmiInfo(input.HostIpmiAttributes, "")
  4189. if err != nil {
  4190. return input, errors.Wrap(err, "fetchIpmiInfo")
  4191. }
  4192. ipmiIpAddr := ipmiInfo.IpAddr
  4193. if len(ipmiIpAddr) == 0 {
  4194. noProbe = true
  4195. }
  4196. if len(ipmiIpAddr) > 0 && !noProbe {
  4197. net, _ := NetworkManager.GetOnPremiseNetworkOfIP(ipmiIpAddr, "", tristate.None)
  4198. if net == nil {
  4199. return input, httperrors.NewInputParameterError("%s is out of network IP ranges", ipmiIpAddr)
  4200. }
  4201. // check ip has been reserved
  4202. rip := ReservedipManager.GetReservedIP(net, ipmiIpAddr, api.AddressTypeIPv4)
  4203. if rip == nil {
  4204. // if not, reserve this IP temporarily
  4205. err := net.reserveIpWithDuration(ctx, userCred, ipmiIpAddr, "reserve for baremetal ipmi IP", 30*time.Minute)
  4206. if err != nil {
  4207. return input, errors.Wrap(err, "net.reserveIpWithDuration")
  4208. }
  4209. }
  4210. zoneObj, _ := net.GetZone()
  4211. if zoneObj == nil {
  4212. return input, httperrors.NewInputParameterError("IPMI network has no zone???")
  4213. }
  4214. originZoneId := input.ZoneId
  4215. if len(originZoneId) > 0 && originZoneId != zoneObj.GetId() {
  4216. return input, httperrors.NewInputParameterError("IPMI address located in different zone than specified")
  4217. }
  4218. input.ZoneId = zoneObj.GetId()
  4219. // data.Set("zone_id", jsonutils.NewString(zoneObj.GetId()))
  4220. }
  4221. if !noProbe || input.NoBMC {
  4222. var accessNet *SNetwork
  4223. accessIpAddr := input.AccessIp // tString("access_ip")
  4224. if len(accessIpAddr) > 0 {
  4225. net, _ := NetworkManager.GetOnPremiseNetworkOfIP(accessIpAddr, "", tristate.None)
  4226. if net == nil {
  4227. return input, httperrors.NewInputParameterError("%s is out of network IP ranges", accessIpAddr)
  4228. }
  4229. accessNet = net
  4230. } else {
  4231. accessNetStr := input.AccessNet // data.GetString("access_net")
  4232. if len(accessNetStr) > 0 {
  4233. netObj, err := NetworkManager.FetchByIdOrName(ctx, userCred, accessNetStr)
  4234. if err != nil {
  4235. if errors.Cause(err) == sql.ErrNoRows {
  4236. return input, httperrors.NewResourceNotFoundError2("network", accessNetStr)
  4237. } else {
  4238. return input, httperrors.NewGeneralError(err)
  4239. }
  4240. }
  4241. accessNet = netObj.(*SNetwork)
  4242. } else {
  4243. accessWireStr := input.AccessWire // data.GetString("access_wire")
  4244. if len(accessWireStr) > 0 {
  4245. wireObj, err := WireManager.FetchByIdOrName(ctx, userCred, accessWireStr)
  4246. if err != nil {
  4247. if errors.Cause(err) == sql.ErrNoRows {
  4248. return input, httperrors.NewResourceNotFoundError2("wire", accessWireStr)
  4249. } else {
  4250. return input, httperrors.NewGeneralError(err)
  4251. }
  4252. }
  4253. wire := wireObj.(*SWire)
  4254. lockman.LockObject(ctx, wire)
  4255. defer lockman.ReleaseObject(ctx, wire)
  4256. net, err := wire.GetCandidatePrivateNetwork(ctx, userCred, userCred, NetworkManager.AllowScope(userCred), false, []api.TNetworkType{api.NETWORK_TYPE_PXE, api.NETWORK_TYPE_BAREMETAL, api.NETWORK_TYPE_GUEST})
  4257. if err != nil {
  4258. return input, httperrors.NewGeneralError(err)
  4259. }
  4260. accessNet = net
  4261. }
  4262. }
  4263. }
  4264. if accessNet != nil {
  4265. lockman.LockObject(ctx, accessNet)
  4266. defer lockman.ReleaseObject(ctx, accessNet)
  4267. accessIp, err := accessNet.GetFreeIP(ctx, userCred, nil, nil, accessIpAddr, api.IPAllocationNone, true, api.AddressTypeIPv4)
  4268. if err != nil {
  4269. return input, httperrors.NewGeneralError(err)
  4270. }
  4271. if len(accessIpAddr) > 0 && accessIpAddr != accessIp {
  4272. return input, httperrors.NewConflictError("Access ip %s has been used", accessIpAddr)
  4273. }
  4274. zoneObj, _ := accessNet.GetZone()
  4275. if zoneObj == nil {
  4276. return input, httperrors.NewInputParameterError("Access network has no zone???")
  4277. }
  4278. originZoneId := input.ZoneId // data.GetString("zone_id")
  4279. if len(originZoneId) > 0 && originZoneId != zoneObj.GetId() {
  4280. return input, httperrors.NewInputParameterError("Access address located in different zone than specified")
  4281. }
  4282. // check ip has been reserved
  4283. rip := ReservedipManager.GetReservedIP(accessNet, accessIp, api.AddressTypeIPv4)
  4284. if rip == nil {
  4285. // if not reserved, reserve this IP temporarily
  4286. err = accessNet.reserveIpWithDuration(ctx, userCred, accessIp, "reserve for baremetal access IP", 30*time.Minute)
  4287. if err != nil {
  4288. return input, err
  4289. }
  4290. }
  4291. input.AccessIp = accessIp
  4292. input.ZoneId = zoneObj.GetId()
  4293. // data.Set("access_ip", jsonutils.NewString(accessIp))
  4294. // data.Set("zone_id", jsonutils.NewString(zoneObj.GetId()))
  4295. }
  4296. }
  4297. // only baremetal can be created
  4298. hostType := input.HostType // .GetString("host_type")
  4299. if len(hostType) == 0 {
  4300. hostType = api.HOST_TYPE_BAREMETAL
  4301. input.HostType = hostType
  4302. // data.Set("host_type", jsonutils.NewString(hostType))
  4303. }
  4304. if hostType == api.HOST_TYPE_BAREMETAL {
  4305. isBaremetal := true
  4306. input.IsBaremetal = &isBaremetal
  4307. // data.Set("is_baremetal", jsonutils.JSONTrue)
  4308. }
  4309. if noProbe {
  4310. // accessMac := input.AccessMac // data.GetString("access_mac")
  4311. // uuid := input.Uuid // data.GetString("uuid")
  4312. if len(input.AccessMac) == 0 && len(input.Uuid) == 0 {
  4313. return input, httperrors.NewInputParameterError("missing access_mac and uuid in no_probe mode")
  4314. }
  4315. }
  4316. input.EnabledStatusInfrasResourceBaseCreateInput, err = manager.SEnabledStatusInfrasResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.EnabledStatusInfrasResourceBaseCreateInput)
  4317. if err != nil {
  4318. return input, errors.Wrap(err, "SEnabledStatusInfrasResourceBaseManager.ValidateCreateData")
  4319. }
  4320. name := input.Name
  4321. if len(name) == 0 {
  4322. name = input.GenerateName
  4323. }
  4324. input.HostnameInput, err = manager.SHostnameResourceBaseManager.ValidateHostname(name, "", input.HostnameInput)
  4325. if err != nil {
  4326. return input, err
  4327. }
  4328. keys := GetHostQuotaKeysFromCreateInput(ownerId, input)
  4329. quota := SInfrasQuota{Host: 1}
  4330. quota.SetKeys(keys)
  4331. err = quotas.CheckSetPendingQuota(ctx, userCred, &quota)
  4332. if err != nil {
  4333. return input, errors.Wrapf(err, "CheckSetPendingQuota")
  4334. }
  4335. return input, nil
  4336. }
  4337. func (hh *SHost) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.HostUpdateInput) (api.HostUpdateInput, error) {
  4338. // validate Hostname
  4339. if len(input.Hostname) > 0 {
  4340. if !regutils.MatchDomainName(input.Hostname) {
  4341. return input, httperrors.NewInputParameterError("hostname should be a legal domain name")
  4342. }
  4343. }
  4344. var err error
  4345. input.HostAccessAttributes, err = HostManager.inputUniquenessCheck(input.HostAccessAttributes, hh.ZoneId, hh.Id)
  4346. if err != nil {
  4347. return input, errors.Wrap(err, "inputUniquenessCheck")
  4348. }
  4349. if hh.IsHugePage() && input.MemCmtbound != nil && *input.MemCmtbound != hh.MemCmtbound {
  4350. return input, errors.Errorf("host mem is hugepage, cannot update mem_cmtbound")
  4351. }
  4352. if input.CpuReserved != nil {
  4353. info := hh.GetMetadata(ctx, api.HOSTMETA_RESERVED_CPUS_INFO, nil)
  4354. if len(info) > 0 {
  4355. return input, errors.Wrap(httperrors.ErrInputParameter, "host cpu has been reserved, cannot update cpu_reserved")
  4356. }
  4357. }
  4358. input.HostSizeAttributes, err = HostManager.ValidateSizeParams(input.HostSizeAttributes)
  4359. if err != nil {
  4360. return input, errors.Wrap(err, "ValidateSizeParams")
  4361. }
  4362. ipmiInfo, err := fetchIpmiInfo(input.HostIpmiAttributes, hh.Id)
  4363. if err != nil {
  4364. return input, errors.Wrap(err, "fetchIpmiInfo")
  4365. }
  4366. ipmiInfoJson := jsonutils.Marshal(ipmiInfo).(*jsonutils.JSONDict)
  4367. if ipmiInfoJson.Length() > 0 {
  4368. ipmiIpAddr := ipmiInfo.IpAddr
  4369. if len(ipmiIpAddr) > 0 {
  4370. net, _ := NetworkManager.GetOnPremiseNetworkOfIP(ipmiIpAddr, "", tristate.None)
  4371. if net == nil {
  4372. return input, httperrors.NewInputParameterError("%s is out of network IP ranges", ipmiIpAddr)
  4373. }
  4374. zoneObj, _ := net.GetZone()
  4375. if zoneObj == nil {
  4376. return input, httperrors.NewInputParameterError("IPMI network has not zone???")
  4377. }
  4378. if zoneObj.GetId() != hh.ZoneId {
  4379. return input, httperrors.NewInputParameterError("New IPMI address located in another zone!")
  4380. }
  4381. }
  4382. val := jsonutils.NewDict()
  4383. val.Update(hh.IpmiInfo)
  4384. val.Update(ipmiInfoJson)
  4385. input.IpmiInfo = val
  4386. }
  4387. input.EnabledStatusInfrasResourceBaseUpdateInput, err = hh.SEnabledStatusInfrasResourceBase.ValidateUpdateData(ctx, userCred, query, input.EnabledStatusInfrasResourceBaseUpdateInput)
  4388. if err != nil {
  4389. return input, errors.Wrap(err, "SEnabledStatusInfrasResourceBase.ValidateUpdateData")
  4390. }
  4391. if len(input.Name) > 0 {
  4392. hh.UpdateDnsRecords(false)
  4393. }
  4394. if input.EnableNumaAllocate != nil {
  4395. if hh.HostType != api.HOST_TYPE_CONTAINER {
  4396. if cnt, err := hh.GetRunningGuestCount(); err != nil {
  4397. return input, errors.Wrap(err, "GetRunningGuestCount")
  4398. } else if cnt > 0 {
  4399. return input, errors.Errorf("Host has running guest, can't enable/disable numa allocate")
  4400. }
  4401. }
  4402. }
  4403. return input, nil
  4404. }
  4405. func (hh *SHost) PostUpdate(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) {
  4406. hh.SEnabledStatusInfrasResourceBase.PostUpdate(ctx, userCred, query, data)
  4407. if data.Contains("cpu_cmtbound") || data.Contains("mem_cmtbound") || data.Contains("enable_numa_allocate") {
  4408. hh.ClearSchedDescCache()
  4409. }
  4410. if hh.OvnVersion != "" && hh.OvnMappedIpAddr == "" {
  4411. HostManager.lockAllocOvnMappedIpAddr(ctx)
  4412. defer HostManager.unlockAllocOvnMappedIpAddr(ctx)
  4413. addr, err := HostManager.allocOvnMappedIpAddr(ctx)
  4414. if err != nil {
  4415. log.Errorf("host %s(%s): alloc vpc mapped addr: %v",
  4416. hh.Name, hh.Id, err)
  4417. return
  4418. }
  4419. if _, err := db.Update(hh, func() error {
  4420. hh.OvnMappedIpAddr = addr
  4421. hh.OvnMappedIp6Addr = api.GenVpcMappedIP6(addr)
  4422. return nil
  4423. }); err != nil {
  4424. log.Errorf("host %s(%s): db update vpc mapped addr: %v",
  4425. hh.Name, hh.Id, err)
  4426. return
  4427. }
  4428. }
  4429. // update baremetal host related server
  4430. if guest := hh.GetBaremetalServer(); guest != nil && hh.HostType == api.HOST_TYPE_BAREMETAL {
  4431. if _, err := db.Update(guest, func() error {
  4432. guest.VmemSize = hh.MemSize
  4433. guest.VcpuCount = hh.CpuCount
  4434. return nil
  4435. }); err != nil {
  4436. log.Errorf("baremetal host %s update related server %s spec error: %v", hh.GetName(), guest.GetName(), err)
  4437. }
  4438. }
  4439. notSyncConf, _ := data.Bool("not_sync_config")
  4440. if !notSyncConf {
  4441. if err := hh.startSyncConfig(ctx, userCred, "", true); err != nil {
  4442. log.Errorf("start sync host %q config after updated", hh.GetName())
  4443. }
  4444. }
  4445. }
  4446. func (hh *SHost) PostDelete(ctx context.Context, userCred mcclient.TokenCredential) {
  4447. hh.SEnabledStatusInfrasResourceBase.PostDelete(ctx, userCred)
  4448. notifyclient.EventNotify(ctx, userCred, notifyclient.SEventNotifyParam{
  4449. Obj: hh,
  4450. Action: notifyclient.ActionDelete,
  4451. })
  4452. }
  4453. func (hh *SHost) UpdateDnsRecords(isAdd bool) {
  4454. for _, netif := range hh.GetHostNetInterfaces() {
  4455. hh.UpdateDnsRecord(&netif, isAdd)
  4456. }
  4457. }
  4458. func (hh *SHost) UpdateDnsRecord(netif *SNetInterface, isAdd bool) {
  4459. name := hh.GetNetifName(netif)
  4460. if len(name) == 0 {
  4461. return
  4462. }
  4463. bn := netif.GetHostNetwork()
  4464. if bn == nil {
  4465. log.Errorf("Interface %s not enable", netif.GetId())
  4466. return
  4467. }
  4468. net := bn.GetNetwork()
  4469. if net == nil {
  4470. log.Errorf("BaremetalNetwoke %s not found network", bn.GetId())
  4471. }
  4472. net._updateDnsRecord(name, bn.IpAddr, isAdd)
  4473. }
  4474. func (hh *SHost) GetNetifName(netif *SNetInterface) string {
  4475. if netif.NicType == api.NIC_TYPE_IPMI {
  4476. return hh.GetName()
  4477. } else if netif.NicType == api.NIC_TYPE_ADMIN {
  4478. return hh.GetName() + "-admin"
  4479. }
  4480. return ""
  4481. }
  4482. func fetchIpmiInfo(data api.HostIpmiAttributes, hostId string) (types.SIPMIInfo, error) {
  4483. info := types.SIPMIInfo{}
  4484. info.Username = data.IpmiUsername
  4485. if len(data.IpmiPassword) > 0 {
  4486. if len(hostId) > 0 {
  4487. value, err := utils.EncryptAESBase64(hostId, data.IpmiPassword)
  4488. if err != nil {
  4489. log.Errorf("encrypt password failed %s", err)
  4490. return info, errors.Wrap(err, "utils.EncryptAESBase64")
  4491. }
  4492. info.Password = value
  4493. } else {
  4494. info.Password = data.IpmiPassword
  4495. }
  4496. }
  4497. if len(data.IpmiIpAddr) > 0 && !regutils.MatchIP4Addr(data.IpmiIpAddr) && !regutils.MatchIP6Addr(data.IpmiIpAddr) {
  4498. msg := fmt.Sprintf("ipmi_ip_addr: %v not valid address", data.IpmiIpAddr)
  4499. log.Errorf("%s", msg)
  4500. return info, errors.Wrap(httperrors.ErrInvalidFormat, msg)
  4501. }
  4502. info.IpAddr = data.IpmiIpAddr
  4503. if data.IpmiPresent != nil {
  4504. info.Present = *data.IpmiPresent
  4505. }
  4506. if data.IpmiLanChannel != nil {
  4507. info.LanChannel = *data.IpmiLanChannel
  4508. }
  4509. if data.IpmiVerified != nil {
  4510. info.Verified = *data.IpmiVerified
  4511. }
  4512. if data.IpmiRedfishApi != nil {
  4513. info.RedfishApi = *data.IpmiRedfishApi
  4514. }
  4515. if data.IpmiCdromBoot != nil {
  4516. info.CdromBoot = *data.IpmiCdromBoot
  4517. }
  4518. if data.IpmiPxeBoot != nil {
  4519. info.PxeBoot = *data.IpmiPxeBoot
  4520. }
  4521. return info, nil
  4522. }
  4523. func (hh *SHost) PerformStart(
  4524. ctx context.Context,
  4525. userCred mcclient.TokenCredential,
  4526. query jsonutils.JSONObject,
  4527. input api.HostPerformStartInput,
  4528. ) (jsonutils.JSONObject, error) {
  4529. if !hh.IsBaremetal {
  4530. return nil, httperrors.NewBadRequestError("Cannot start a non-baremetal host")
  4531. }
  4532. if !utils.IsInStringArray(hh.Status, []string{api.BAREMETAL_READY}) {
  4533. return nil, httperrors.NewInvalidStatusError("Cannot start baremetal with active guest")
  4534. }
  4535. guest := hh.GetBaremetalServer()
  4536. if guest != nil {
  4537. if hh.HostType == api.HOST_TYPE_BAREMETAL && utils.ToBool(guest.GetMetadata(ctx, "is_fake_baremetal_server", userCred)) {
  4538. return nil, hh.InitializedGuestStart(ctx, userCred, guest)
  4539. }
  4540. // if !utils.IsInStringArray(guest.Status, []string{VM_ADMIN}) {
  4541. // return nil, httperrors.NewBadRequestError("Cannot start baremetal with active guest")
  4542. // }
  4543. hh.SetStatus(ctx, userCred, api.BAREMETAL_START_MAINTAIN, "")
  4544. return guest.PerformStart(ctx, userCred, query, api.GuestPerformStartInput{})
  4545. }
  4546. params := jsonutils.NewDict()
  4547. params.Set("force_reboot", jsonutils.NewBool(false))
  4548. params.Set("action", jsonutils.NewString("start"))
  4549. return hh.PerformMaintenance(ctx, userCred, nil, params)
  4550. }
  4551. func (hh *SHost) PerformPurge(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject,
  4552. data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
  4553. if hh.GetEnabled() {
  4554. return nil, httperrors.NewInvalidStatusError("Host is not disabled")
  4555. }
  4556. return nil, hh.purge(ctx, userCred)
  4557. }
  4558. func (hh *SHost) PerformStop(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject,
  4559. data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
  4560. if !hh.IsBaremetal {
  4561. return nil, httperrors.NewBadRequestError("Cannot stop a non-baremetal host")
  4562. }
  4563. if !utils.IsInStringArray(hh.Status, []string{api.BAREMETAL_RUNNING}) {
  4564. return nil, httperrors.NewInvalidStatusError("Cannot stop baremetal with non-active guest")
  4565. }
  4566. guest := hh.GetBaremetalServer()
  4567. if guest != nil {
  4568. if hh.HostType != api.HOST_TYPE_BAREMETAL {
  4569. if !utils.IsInStringArray(guest.Status, []string{api.VM_ADMIN}) {
  4570. return nil, httperrors.NewBadRequestError("Cannot stop baremetal with active guest")
  4571. }
  4572. } else {
  4573. if utils.ToBool(guest.GetMetadata(ctx, "is_fake_baremetal_server", userCred)) {
  4574. return nil, hh.InitializedGuestStop(ctx, userCred, guest)
  4575. }
  4576. hh.SetStatus(ctx, userCred, api.BAREMETAL_START_MAINTAIN, "")
  4577. input := api.ServerStopInput{}
  4578. data.Unmarshal(&input)
  4579. return guest.PerformStop(ctx, userCred, query, input)
  4580. }
  4581. }
  4582. return nil, hh.StartBaremetalUnmaintenanceTask(ctx, userCred, false, "stop")
  4583. }
  4584. func (hh *SHost) InitializedGuestStart(ctx context.Context, userCred mcclient.TokenCredential, guest *SGuest) error {
  4585. task, err := taskman.TaskManager.NewTask(ctx, "BaremetalServerStartTask", guest, userCred, nil, "", "", nil)
  4586. if err != nil {
  4587. return err
  4588. }
  4589. return task.ScheduleRun(nil)
  4590. }
  4591. func (hh *SHost) InitializedGuestStop(ctx context.Context, userCred mcclient.TokenCredential, guest *SGuest) error {
  4592. task, err := taskman.TaskManager.NewTask(ctx, "BaremetalServerStopTask", guest, userCred, nil, "", "", nil)
  4593. if err != nil {
  4594. return err
  4595. }
  4596. task.ScheduleRun(nil)
  4597. return nil
  4598. }
  4599. func (hh *SHost) PerformMaintenance(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
  4600. if !utils.IsInStringArray(hh.Status, []string{api.BAREMETAL_READY, api.BAREMETAL_RUNNING}) {
  4601. return nil, httperrors.NewInvalidStatusError("Cannot do maintenance in status %s", hh.Status)
  4602. }
  4603. guest := hh.GetBaremetalServer()
  4604. if guest != nil && !utils.IsInStringArray(guest.Status, []string{api.VM_READY, api.VM_RUNNING, api.VM_ADMIN}) {
  4605. return nil, httperrors.NewInvalidStatusError("Cannot do maintenance while guest status %s", guest.Status)
  4606. }
  4607. params := jsonutils.NewDict()
  4608. if guest != nil {
  4609. if guest.Status == api.VM_RUNNING {
  4610. params.Set("guest_running", jsonutils.NewBool(true))
  4611. }
  4612. guest.SetStatus(ctx, userCred, api.VM_ADMIN, "")
  4613. }
  4614. if hh.Status == api.BAREMETAL_RUNNING && jsonutils.QueryBoolean(data, "force_reboot", false) {
  4615. params.Set("force_reboot", jsonutils.NewBool(true))
  4616. }
  4617. action := "maintenance"
  4618. if data.Contains("action") {
  4619. action, _ = data.GetString("action")
  4620. }
  4621. params.Set("action", jsonutils.NewString(action))
  4622. hh.SetStatus(ctx, userCred, api.BAREMETAL_START_MAINTAIN, "")
  4623. task, err := taskman.TaskManager.NewTask(ctx, "BaremetalMaintenanceTask", hh, userCred, params, "", "", nil)
  4624. if err != nil {
  4625. return nil, err
  4626. }
  4627. return nil, task.ScheduleRun(nil)
  4628. }
  4629. func (hh *SHost) PerformUnmaintenance(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
  4630. if !utils.IsInStringArray(hh.Status, []string{api.BAREMETAL_RUNNING, api.BAREMETAL_READY}) {
  4631. return nil, httperrors.NewInvalidStatusError("Cannot do unmaintenance in status %s", hh.Status)
  4632. }
  4633. guest := hh.GetBaremetalServer()
  4634. if guest != nil && guest.Status != api.VM_ADMIN {
  4635. return nil, httperrors.NewInvalidStatusError("Wrong guest status %s", guest.Status)
  4636. }
  4637. action, _ := data.GetString("action")
  4638. if len(action) == 0 {
  4639. action = "unmaintenance"
  4640. }
  4641. guestRunning := hh.GetMetadata(ctx, "__maint_guest_running", userCred)
  4642. var startGuest = false
  4643. if utils.ToBool(guestRunning) {
  4644. startGuest = true
  4645. }
  4646. return nil, hh.StartBaremetalUnmaintenanceTask(ctx, userCred, startGuest, action)
  4647. }
  4648. func (hh *SHost) StartBaremetalUnmaintenanceTask(ctx context.Context, userCred mcclient.TokenCredential, startGuest bool, action string) error {
  4649. hh.SetStatus(ctx, userCred, api.BAREMETAL_START_MAINTAIN, "")
  4650. params := jsonutils.NewDict()
  4651. params.Set("guest_running", jsonutils.NewBool(startGuest))
  4652. if len(action) == 0 {
  4653. action = "unmaintenance"
  4654. }
  4655. params.Set("action", jsonutils.NewString(action))
  4656. task, err := taskman.TaskManager.NewTask(ctx, "BaremetalUnmaintenanceTask", hh, userCred, params, "", "", nil)
  4657. if err != nil {
  4658. return err
  4659. }
  4660. task.ScheduleRun(nil)
  4661. return nil
  4662. }
  4663. func (hh *SHost) StartSyncstatus(ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string) error {
  4664. guest := hh.GetBaremetalServer()
  4665. if guest != nil {
  4666. return guest.StartSyncstatus(ctx, userCred, parentTaskId)
  4667. }
  4668. task, err := taskman.TaskManager.NewTask(ctx, "BaremetalSyncStatusTask", hh, userCred, nil, parentTaskId, "", nil)
  4669. if err != nil {
  4670. return errors.Wrapf(err, "NewTask")
  4671. }
  4672. return task.ScheduleRun(nil)
  4673. }
  4674. func (hh *SHost) PerformOffline(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input *api.HostOfflineInput) (jsonutils.JSONObject, error) {
  4675. if hh.HostStatus != api.HOST_OFFLINE {
  4676. _, err := hh.SaveUpdates(func() error {
  4677. hh.HostStatus = api.HOST_OFFLINE
  4678. if input.UpdateHealthStatus != nil && *input.UpdateHealthStatus {
  4679. hh.EnableHealthCheck = false
  4680. }
  4681. // Note: update host status to unknown on host offline
  4682. // we did not have host status after host offline
  4683. hh.Status = api.BAREMETAL_UNKNOWN
  4684. return nil
  4685. })
  4686. if err != nil {
  4687. return nil, err
  4688. }
  4689. db.OpsLog.LogEvent(hh, db.ACT_OFFLINE, input.Reason, userCred)
  4690. logclient.AddActionLogWithContext(ctx, hh, logclient.ACT_OFFLINE, input, userCred, true)
  4691. ndata := jsonutils.Marshal(hh).(*jsonutils.JSONDict)
  4692. if len(input.Reason) > 0 {
  4693. ndata.Add(jsonutils.NewString(input.Reason), "reason")
  4694. }
  4695. notifyclient.SystemExceptionNotify(ctx, napi.ActionOffline, HostManager.Keyword(), ndata)
  4696. hh.SyncAttachedStorageStatus(ctx)
  4697. }
  4698. return nil, nil
  4699. }
  4700. func (hh *SHost) PerformOnline(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
  4701. if hh.HostStatus != api.HOST_ONLINE {
  4702. _, err := hh.SaveUpdates(func() error {
  4703. hh.LastPingAt = time.Now()
  4704. hh.HostStatus = api.HOST_ONLINE
  4705. hh.EnableHealthCheck = true
  4706. if !hh.IsMaintaining() {
  4707. hh.Status = api.BAREMETAL_RUNNING
  4708. }
  4709. return nil
  4710. })
  4711. if err != nil {
  4712. return nil, err
  4713. }
  4714. if hostHealthChecker != nil {
  4715. hostHealthChecker.WatchHost(context.Background(), hh.GetHostnameByName())
  4716. }
  4717. db.OpsLog.LogEvent(hh, db.ACT_ONLINE, "", userCred)
  4718. logclient.AddActionLogWithContext(ctx, hh, logclient.ACT_ONLINE, data, userCred, true)
  4719. hh.SyncAttachedStorageStatus(ctx)
  4720. hh.StartUploadAllGuestsStatusTask(ctx, userCred)
  4721. }
  4722. return nil, nil
  4723. }
  4724. func (hh *SHost) PerformRestartHostAgent(
  4725. ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject,
  4726. ) (jsonutils.JSONObject, error) {
  4727. _, err := hh.Request(ctx, userCred, "POST", fmt.Sprintf("/hosts/%s/restart-host-agent", hh.Id),
  4728. mcclient.GetTokenHeaders(userCred), data)
  4729. if err != nil {
  4730. return nil, err
  4731. }
  4732. return nil, nil
  4733. }
  4734. func (hh *SHost) PerformAutoMigrateOnHostDown(
  4735. ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.HostAutoMigrateInput,
  4736. ) (jsonutils.JSONObject, error) {
  4737. if input.AutoMigrateOnHostShutdown == "enable" &&
  4738. input.AutoMigrateOnHostDown != "enable" {
  4739. return nil, httperrors.NewBadRequestError("must enable auto_migrate_on_host_down at same time")
  4740. }
  4741. var meta = make(map[string]interface{})
  4742. if input.AutoMigrateOnHostShutdown == "enable" {
  4743. meta[api.HOSTMETA_AUTO_MIGRATE_ON_HOST_SHUTDOWN] = "enable"
  4744. } else if input.AutoMigrateOnHostShutdown == "disable" {
  4745. meta[api.HOSTMETA_AUTO_MIGRATE_ON_HOST_SHUTDOWN] = "disable"
  4746. }
  4747. data := jsonutils.NewDict()
  4748. if input.AutoMigrateOnHostDown == "enable" {
  4749. data.Set("shutdown_servers", jsonutils.JSONTrue)
  4750. meta[api.HOSTMETA_AUTO_MIGRATE_ON_HOST_DOWN] = "enable"
  4751. } else if input.AutoMigrateOnHostDown == "disable" {
  4752. meta[api.HOSTMETA_AUTO_MIGRATE_ON_HOST_DOWN] = "disable"
  4753. data.Set("shutdown_servers", jsonutils.JSONFalse)
  4754. }
  4755. _, err := hh.Request(ctx, userCred, "POST", fmt.Sprintf("/hosts/%s/shutdown-servers-on-host-down", hh.Id),
  4756. mcclient.GetTokenHeaders(userCred), data)
  4757. if err != nil {
  4758. return nil, err
  4759. }
  4760. logclient.AddActionLogWithContext(ctx, hh, logclient.ACT_AUTO_MIGRATE_ON_HOST_DOWN, nil, userCred, true)
  4761. return nil, hh.SetAllMetadata(ctx, meta, userCred)
  4762. }
  4763. func (hh *SHost) StartUploadAllGuestsStatusTask(ctx context.Context, userCred mcclient.TokenCredential) error {
  4764. if task, err := taskman.TaskManager.NewTask(ctx, "BaremetalUploadAllGuestsStatusTask", hh, userCred, nil, "", "", nil); err != nil {
  4765. log.Errorln(err)
  4766. return err
  4767. } else {
  4768. task.ScheduleRun(nil)
  4769. return nil
  4770. }
  4771. }
  4772. func (hh *SHost) GetStoragesByMasterHost() ([]string, error) {
  4773. sq := StorageManager.Query()
  4774. sq = sq.In("storage_type", api.SHARED_STORAGE)
  4775. sq = sq.Filter(sqlchemy.OR(sqlchemy.Equals(sq.Field("master_host"), hh.Id), sqlchemy.IsNullOrEmpty(sq.Field("master_host"))))
  4776. subq := sq.SubQuery()
  4777. hsq := HoststorageManager.Query().Equals("host_id", hh.Id)
  4778. hsq = hsq.Join(subq, sqlchemy.Equals(subq.Field("id"), hsq.Field("storage_id")))
  4779. hostStorages := make([]SHoststorage, 0)
  4780. if err := hsq.All(&hostStorages); err != nil && err != sql.ErrNoRows {
  4781. return nil, errors.Wrap(err, "get hostStorages")
  4782. } else if err == sql.ErrNoRows {
  4783. return nil, nil
  4784. }
  4785. storages := make([]string, len(hostStorages))
  4786. for i := range storages {
  4787. storages[i] = hostStorages[i].StorageId
  4788. }
  4789. return storages, nil
  4790. }
  4791. func (hh *SHost) PerformReportDmesg(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.SHostReportDmesgInput) (jsonutils.JSONObject, error) {
  4792. for i := range input.Entries {
  4793. logLevel := db.LogLevelToString(input.Entries[i].Level)
  4794. HostDmesgLogManager.LogDmesg(ctx, hh, logLevel, input.Entries[i].Time, input.Entries[i].Message, userCred)
  4795. }
  4796. return nil, nil
  4797. }
  4798. func (hh *SHost) PerformPing(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.SHostPingInput) (jsonutils.JSONObject, error) {
  4799. if hh.HostType == api.HOST_TYPE_BAREMETAL {
  4800. return nil, httperrors.NewNotSupportedError("ping host type %s not support", hh.HostType)
  4801. }
  4802. if input.WithData {
  4803. // piggyback storage stats info
  4804. log.Debugf("host ping %#v", input)
  4805. for _, si := range input.StorageStats {
  4806. storageObj, err := StorageManager.FetchById(si.StorageId)
  4807. if err != nil {
  4808. log.Errorf("fetch storage %s error %s", si.StorageId, err)
  4809. } else {
  4810. storage := storageObj.(*SStorage)
  4811. _, err := db.Update(storage, func() error {
  4812. storage.Capacity = si.CapacityMb
  4813. storage.ActualCapacityUsed = si.ActualCapacityUsedMb
  4814. return nil
  4815. })
  4816. if err != nil {
  4817. log.Errorf("update storage info error %s", err)
  4818. }
  4819. }
  4820. }
  4821. if len(hh.ManagerId) == 0 {
  4822. guests, _ := hh.GetGuests()
  4823. for _, guest := range guests {
  4824. if utils.IsInStringArray(guest.Id, input.QgaRunningGuestIds) {
  4825. if guest.QgaStatus != api.QGA_STATUS_AVAILABLE {
  4826. guest.UpdateQgaStatus(api.QGA_STATUS_AVAILABLE)
  4827. }
  4828. } else {
  4829. if guest.QgaStatus != api.QGA_STATUS_UNKNOWN {
  4830. guest.UpdateQgaStatus(api.QGA_STATUS_UNKNOWN)
  4831. }
  4832. }
  4833. }
  4834. }
  4835. }
  4836. hh.SaveUpdates(func() error {
  4837. if hh.HostStatus == api.HOST_ONLINE {
  4838. hh.LastPingAt = time.Now()
  4839. }
  4840. if input.WithData {
  4841. if input.RootPartitionUsedCapacityMb > 0 {
  4842. hh.RootPartitionUsedCapacityMb = input.RootPartitionUsedCapacityMb
  4843. }
  4844. if input.MemoryUsedMb > 0 {
  4845. hh.MemoryUsedMb = input.MemoryUsedMb
  4846. }
  4847. if input.CpuUsagePercent > 0 {
  4848. hh.CpuUsagePercent = input.CpuUsagePercent
  4849. }
  4850. }
  4851. return nil
  4852. })
  4853. if hh.HostStatus != api.HOST_ONLINE {
  4854. hh.PerformOnline(ctx, userCred, query, nil)
  4855. } else {
  4856. if hh.hasUnknownGuests() && len(hh.ManagerId) == 0 {
  4857. hh.StartUploadAllGuestsStatusTask(ctx, userCred)
  4858. }
  4859. }
  4860. if len(hh.ManagerId) > 0 {
  4861. return nil, nil
  4862. }
  4863. result := jsonutils.NewDict()
  4864. result.Set("name", jsonutils.NewString(hh.GetName()))
  4865. dependSvcs := []string{"ntpd", "kafka", apis.SERVICE_TYPE_INFLUXDB, apis.SERVICE_TYPE_VICTORIA_METRICS, "elasticsearch", "opentsdb"}
  4866. catalog := auth.GetCatalogData(dependSvcs, options.Options.Region)
  4867. if catalog == nil {
  4868. return nil, errors.Wrap(errors.ErrServer, "Get catalog error")
  4869. }
  4870. result.Set("catalog", catalog)
  4871. if storages, err := hh.GetStoragesByMasterHost(); err != nil {
  4872. return nil, errors.Wrap(err, "get storages by master host")
  4873. } else {
  4874. result.Set("master_host_storages", jsonutils.NewStringArray(storages))
  4875. }
  4876. hostFiles, err := hh.getHostFiles()
  4877. if err != nil {
  4878. return nil, errors.Wrap(err, "get host files")
  4879. }
  4880. result.Set("host_files", jsonutils.Marshal(hostFiles))
  4881. appParams := appsrv.AppContextGetParams(ctx)
  4882. if appParams != nil {
  4883. // skip log&trace, when everything is normal
  4884. appParams.SkipTrace = true
  4885. appParams.SkipLog = true
  4886. }
  4887. return result, nil
  4888. }
  4889. func (host *SHost) getHostNodeReservePercent(reservedCpusStr string) (map[string]float32, error) {
  4890. reservedCpuset, err := cpuset.Parse(reservedCpusStr)
  4891. if err != nil {
  4892. return nil, errors.Wrap(err, "cpuset parse reserved cpus")
  4893. }
  4894. topoObj, err := host.SysInfo.Get("topology")
  4895. if err != nil {
  4896. return nil, errors.Wrap(err, "get topology from host sys_info")
  4897. }
  4898. info := new(hostapi.HostTopology)
  4899. if err := topoObj.Unmarshal(info); err != nil {
  4900. return nil, errors.Wrap(err, "Unmarshal host topology struct")
  4901. }
  4902. nodecpus := map[int]int{}
  4903. nodeReservedCpus := map[int]int{}
  4904. for i := range info.Nodes {
  4905. cSet := cpuset.NewBuilder()
  4906. for j := 0; j < len(info.Nodes[i].Cores); j++ {
  4907. for k := 0; k < len(info.Nodes[i].Cores[j].LogicalProcessors); k++ {
  4908. if reservedCpuset.Contains(info.Nodes[i].Cores[j].LogicalProcessors[k]) {
  4909. if cnt, ok := nodeReservedCpus[info.Nodes[i].ID]; !ok {
  4910. nodeReservedCpus[info.Nodes[i].ID] = 1
  4911. } else {
  4912. nodeReservedCpus[info.Nodes[i].ID] = 1 + cnt
  4913. }
  4914. }
  4915. cSet.Add(info.Nodes[i].Cores[j].LogicalProcessors[k])
  4916. }
  4917. }
  4918. nodecpus[info.Nodes[i].ID] = cSet.Result().Size()
  4919. }
  4920. reserveRate := map[string]float32{}
  4921. for nodeId, cnt := range nodecpus {
  4922. reserveCnt, ok := nodeReservedCpus[nodeId]
  4923. if !ok {
  4924. reserveCnt = 0
  4925. }
  4926. reserveRate[strconv.Itoa(nodeId)] = float32(reserveCnt) / float32(cnt)
  4927. }
  4928. return reserveRate, nil
  4929. }
  4930. func (host *SHost) getHostLogicalCores() ([]int, error) {
  4931. cpuObj, err := host.SysInfo.Get("cpu_info")
  4932. if err != nil {
  4933. return nil, errors.Wrap(err, "get cpu info from host sys_info")
  4934. }
  4935. cpuInfo := new(hostapi.HostCPUInfo)
  4936. if err := cpuObj.Unmarshal(cpuInfo); err != nil {
  4937. return nil, errors.Wrap(err, "Unmarshal host cpu info struct")
  4938. }
  4939. // get host logical cores
  4940. allCores := []int{}
  4941. if len(cpuInfo.Processors) != 0 {
  4942. for _, p := range cpuInfo.Processors {
  4943. for _, core := range p.Cores {
  4944. allCores = append(allCores, core.LogicalProcessors...)
  4945. }
  4946. }
  4947. sort.Ints(allCores)
  4948. } else {
  4949. topoObj, err := host.SysInfo.Get("topology")
  4950. if err != nil {
  4951. return nil, errors.Wrap(err, "get topology from host sys_info")
  4952. }
  4953. hostTopo := new(hostapi.HostTopology)
  4954. if err := topoObj.Unmarshal(hostTopo); err != nil {
  4955. return nil, errors.Wrap(err, "Unmarshal host topology struct")
  4956. }
  4957. for _, node := range hostTopo.Nodes {
  4958. for _, cores := range node.Cores {
  4959. allCores = append(allCores, cores.LogicalProcessors...)
  4960. }
  4961. }
  4962. }
  4963. return allCores, nil
  4964. }
  4965. func (hh *SHost) PerformUnreserveCpus(
  4966. ctx context.Context, userCred mcclient.TokenCredential,
  4967. query jsonutils.JSONObject, data jsonutils.JSONObject,
  4968. ) (jsonutils.JSONObject, error) {
  4969. return nil, hh.RemoveMetadata(ctx, api.HOSTMETA_RESERVED_CPUS_INFO, userCred)
  4970. }
  4971. func (hh *SHost) PerformReserveCpus(
  4972. ctx context.Context, userCred mcclient.TokenCredential,
  4973. query jsonutils.JSONObject, input api.HostReserveCpusInput,
  4974. ) (jsonutils.JSONObject, error) {
  4975. if !utils.IsInStringArray(hh.HostType, []string{api.HOST_TYPE_HYPERVISOR, api.HOST_TYPE_CONTAINER}) {
  4976. return nil, httperrors.NewNotSupportedError("host type %s not support reserve cpus", hh.HostType)
  4977. }
  4978. if input.Cpus == "" {
  4979. return nil, httperrors.NewInputParameterError("missing cpus")
  4980. }
  4981. cs, err := cpuset.Parse(input.Cpus)
  4982. if err != nil {
  4983. return nil, httperrors.NewInputParameterError("cpus %s not valid", input.Cpus)
  4984. }
  4985. allCores, err := hh.getHostLogicalCores()
  4986. if err != nil {
  4987. return nil, err
  4988. }
  4989. hSets := sets.NewInt(allCores...)
  4990. cSlice := cs.ToSlice()
  4991. if !hSets.HasAll(cSlice...) {
  4992. return nil, httperrors.NewInputParameterError("Host cores not contains input %v", input.Cpus)
  4993. }
  4994. if hSets.Len() == len(cSlice) {
  4995. return nil, httperrors.NewInputParameterError("Can't reserve host all cpus")
  4996. }
  4997. pinnedCores, err := hh.GetPinnedCpusetCores(ctx, userCred, nil)
  4998. if err != nil {
  4999. return nil, err
  5000. }
  5001. if pinnedCores != nil {
  5002. if cs.Union(*pinnedCores).Size() != (cs.Size() + pinnedCores.Size()) {
  5003. return nil, httperrors.NewBadRequestError("request cpus confilct with guest pinned cpus")
  5004. }
  5005. }
  5006. if input.Mems != "" {
  5007. mems, err := cpuset.Parse(input.Mems)
  5008. if err != nil {
  5009. return nil, httperrors.NewInputParameterError("mems %s not valid", input.Mems)
  5010. }
  5011. // to slice will sort slice default
  5012. memSlice := mems.ToSlice()
  5013. if 0 > memSlice[len(memSlice)-1] || memSlice[len(memSlice)-1] >= int(hh.NodeCount) {
  5014. return nil, httperrors.NewInputParameterError("mems %s out of range", input.Mems)
  5015. }
  5016. }
  5017. if len(input.Cpus) > 0 {
  5018. reservePercent, err := hh.getHostNodeReservePercent(input.Cpus)
  5019. if err != nil {
  5020. return nil, errors.Errorf("failed getHostNodeReservePercent: %s", err)
  5021. }
  5022. err = hh.SetMetadata(ctx, api.HOSTMETA_RESERVED_CPUS_RATE, reservePercent, userCred)
  5023. if err != nil {
  5024. return nil, err
  5025. }
  5026. } else {
  5027. err = hh.RemoveMetadata(ctx, api.HOSTMETA_RESERVED_CPUS_RATE, userCred)
  5028. if err != nil {
  5029. return nil, err
  5030. }
  5031. }
  5032. err = hh.SetMetadata(ctx, api.HOSTMETA_RESERVED_CPUS_INFO, input, userCred)
  5033. if err != nil {
  5034. return nil, err
  5035. }
  5036. if err = hh.updateHostReservedCpus(ctx, userCred); err != nil {
  5037. return nil, errors.Wrap(err, "update host reserved cpus")
  5038. }
  5039. return nil, err
  5040. }
  5041. func (hh *SHost) HasBMC() bool {
  5042. ipmiInfo, _ := hh.GetIpmiInfo()
  5043. if ipmiInfo.Username != "" && ipmiInfo.Password != "" {
  5044. return true
  5045. }
  5046. return false
  5047. }
  5048. func (hh *SHost) IsUEFIBoot() bool {
  5049. info, _ := hh.GetUEFIInfo()
  5050. if info == nil {
  5051. return false
  5052. }
  5053. if len(info.PxeBootNum) == 0 {
  5054. return false
  5055. }
  5056. return true
  5057. }
  5058. func (hh *SHost) isRedfishCapable() bool {
  5059. ipmiInfo, _ := hh.GetIpmiInfo()
  5060. if ipmiInfo.Verified && ipmiInfo.RedfishApi {
  5061. return true
  5062. }
  5063. return false
  5064. }
  5065. func (hh *SHost) canPrepare() error {
  5066. if !hh.isRedfishCapable() && len(hh.AccessMac) == 0 && len(hh.Uuid) == 0 {
  5067. return httperrors.NewInvalidStatusError("need valid access_mac and uuid to do prepare")
  5068. }
  5069. if !utils.IsInStringArray(hh.Status, []string{api.BAREMETAL_READY, api.BAREMETAL_RUNNING, api.BAREMETAL_PREPARE_FAIL}) {
  5070. return httperrors.NewInvalidStatusError("Cannot prepare baremetal in status %s", hh.Status)
  5071. }
  5072. return nil
  5073. }
  5074. func (hh *SHost) PerformPrepare(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
  5075. if !hh.IsBaremetal {
  5076. return nil, httperrors.NewInvalidStatusError("not a baremetal")
  5077. }
  5078. server := hh.GetBaremetalServer()
  5079. if server != nil && server.Status != api.VM_ADMIN {
  5080. return nil, httperrors.NewInvalidStatusError("Cannot prepare baremetal in server status %s", server.Status)
  5081. }
  5082. err := hh.canPrepare()
  5083. if err != nil {
  5084. return nil, err
  5085. }
  5086. var onfinish string
  5087. if server != nil && hh.Status == api.BAREMETAL_READY {
  5088. onfinish = "shutdown"
  5089. }
  5090. return nil, hh.StartPrepareTask(ctx, userCred, onfinish, "")
  5091. }
  5092. func (hh *SHost) StartPrepareTask(ctx context.Context, userCred mcclient.TokenCredential, onfinish, parentTaskId string) error {
  5093. data := jsonutils.NewDict()
  5094. if len(onfinish) > 0 {
  5095. data.Set("on_finish", jsonutils.NewString(onfinish))
  5096. }
  5097. hh.SetStatus(ctx, userCred, api.BAREMETAL_PREPARE, "start prepare task")
  5098. if task, err := taskman.TaskManager.NewTask(ctx, "BaremetalPrepareTask", hh, userCred, data, parentTaskId, "", nil); err != nil {
  5099. log.Errorln(err)
  5100. return err
  5101. } else {
  5102. task.ScheduleRun(nil)
  5103. return nil
  5104. }
  5105. }
  5106. func (hh *SHost) PerformIpmiProbe(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
  5107. if utils.IsInStringArray(hh.Status, []string{api.BAREMETAL_INIT, api.BAREMETAL_READY, api.BAREMETAL_RUNNING, api.BAREMETAL_PROBE_FAIL, api.BAREMETAL_UNKNOWN}) {
  5108. return nil, hh.StartIpmiProbeTask(ctx, userCred, "")
  5109. }
  5110. return nil, httperrors.NewInvalidStatusError("Cannot do Ipmi-probe in status %s", hh.Status)
  5111. }
  5112. func (hh *SHost) StartIpmiProbeTask(ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string) error {
  5113. data := jsonutils.NewDict()
  5114. hh.SetStatus(ctx, userCred, api.BAREMETAL_START_PROBE, "start ipmi-probe task")
  5115. if task, err := taskman.TaskManager.NewTask(ctx, "BaremetalIpmiProbeTask", hh, userCred, data, parentTaskId, "", nil); err != nil {
  5116. log.Errorln(err)
  5117. return err
  5118. } else {
  5119. task.ScheduleRun(nil)
  5120. return nil
  5121. }
  5122. }
  5123. func (hm *SHostManager) PerformValidateIpmi(ctx context.Context, userCred mcclient.TokenCredential, _ jsonutils.JSONObject, input *baremetalapi.ValidateIPMIRequest) (*baremetalapi.ValidateIPMIResponse, error) {
  5124. resp, err := hm.BaremetalSyncRequest(ctx, "POST", "/baremetals/validate-ipmi", mcclient.GetTokenHeaders(userCred), jsonutils.Marshal(input).(*jsonutils.JSONDict), "")
  5125. if err != nil {
  5126. return nil, err
  5127. }
  5128. out := new(baremetalapi.ValidateIPMIResponse)
  5129. resp.Unmarshal(out)
  5130. return out, nil
  5131. }
  5132. func (hh *SHost) PerformInitialize(
  5133. ctx context.Context, userCred mcclient.TokenCredential,
  5134. query jsonutils.JSONObject, data jsonutils.JSONObject,
  5135. ) (jsonutils.JSONObject, error) {
  5136. if !utils.IsInStringArray(
  5137. hh.Status, []string{api.BAREMETAL_INIT, api.BAREMETAL_PREPARE_FAIL}) {
  5138. return nil, httperrors.NewBadRequestError(
  5139. "Cannot do initialization in status %s", hh.Status)
  5140. }
  5141. name, err := data.GetString("name")
  5142. if err != nil || hh.GetBaremetalServer() != nil {
  5143. return nil, nil
  5144. }
  5145. err = db.NewNameValidator(ctx, GuestManager, userCred, name, nil)
  5146. if err != nil {
  5147. return nil, err
  5148. }
  5149. if hh.IpmiInfo == nil || !hh.IpmiInfo.Contains("ip_addr") ||
  5150. !hh.IpmiInfo.Contains("password") {
  5151. return nil, httperrors.NewBadRequestError("IPMI infomation not configured")
  5152. }
  5153. guest := &SGuest{}
  5154. guest.Name = name
  5155. guest.VmemSize = hh.MemSize
  5156. guest.VcpuCount = hh.CpuCount
  5157. guest.DisableDelete = tristate.True
  5158. guest.Hypervisor = api.HYPERVISOR_BAREMETAL
  5159. guest.HostId = hh.Id
  5160. guest.ProjectId = userCred.GetProjectId()
  5161. guest.DomainId = userCred.GetProjectDomainId()
  5162. guest.Status = api.VM_RUNNING
  5163. guest.PowerStates = api.VM_POWER_STATES_ON
  5164. guest.OsType = "Linux"
  5165. guest.SetModelManager(GuestManager, guest)
  5166. err = GuestManager.TableSpec().Insert(ctx, guest)
  5167. if err != nil {
  5168. return nil, httperrors.NewInternalServerError("Guest Insert error: %s", err)
  5169. }
  5170. guest.SetAllMetadata(ctx, map[string]interface{}{
  5171. "is_fake_baremetal_server": true, "host_ip": hh.AccessIp}, userCred)
  5172. caps := hh.GetAttachedLocalStorageCapacity()
  5173. diskConfig := &api.DiskConfig{SizeMb: int(caps.GetFree())}
  5174. err = guest.CreateDisksOnHost(ctx, userCred, hh, []*api.DiskConfig{diskConfig}, nil, true, true, nil, nil, true)
  5175. if err != nil {
  5176. log.Errorf("Host perform initialize failed on create disk %s", err)
  5177. }
  5178. net, err := hh.getNetworkOfIPOnHost(ctx, hh.AccessIp)
  5179. if err != nil {
  5180. log.Errorf("host perfrom initialize failed fetch net of access ip %s", err)
  5181. } else {
  5182. if options.Options.BaremetalServerReuseHostIp {
  5183. _, err = guest.attach2NetworkDesc(ctx, userCred, hh, &api.NetworkConfig{Network: net.Id}, nil, nil)
  5184. if err != nil {
  5185. log.Errorf("host perform initialize failed on attach network %s", err)
  5186. }
  5187. }
  5188. }
  5189. return nil, nil
  5190. }
  5191. func validateHostNetif(input api.HostNetifInput) (api.HostNetifInput, error) {
  5192. mac := input.Mac
  5193. if len(input.Mac) > 0 {
  5194. mac = netutils.FormatMacAddr(input.Mac)
  5195. }
  5196. if len(mac) == 0 {
  5197. return input, errors.Wrapf(httperrors.ErrInputParameter, "Invaild mac address %s", input.Mac)
  5198. }
  5199. input.Mac = mac
  5200. vlan := input.VlanId
  5201. if vlan == 0 {
  5202. vlan = 1
  5203. }
  5204. if vlan < 0 || vlan > 4095 {
  5205. return input, errors.Wrapf(httperrors.ErrInputParameter, "Invalid vlan_id %d", input.VlanId)
  5206. }
  5207. input.VlanId = vlan
  5208. return input, nil
  5209. }
  5210. func (h *SHost) PerformAddNetif(
  5211. ctx context.Context,
  5212. userCred mcclient.TokenCredential,
  5213. query jsonutils.JSONObject,
  5214. input api.HostAddNetifInput,
  5215. ) (jsonutils.JSONObject, error) {
  5216. log.Debugf("add_netif %s", jsonutils.Marshal(input))
  5217. var err error
  5218. input.HostNetifInput, err = validateHostNetif(input.HostNetifInput)
  5219. if err != nil {
  5220. return nil, errors.Wrap(err, "validateHostNetif")
  5221. }
  5222. mac := input.Mac
  5223. vlan := input.VlanId
  5224. wireId := input.WireId
  5225. if len(input.WireId) > 0 {
  5226. wireObj, err := WireManager.FetchByIdOrName(ctx, userCred, input.WireId)
  5227. if err != nil {
  5228. if errors.Cause(err) == sql.ErrNoRows {
  5229. return nil, httperrors.NewResourceNotFoundError2(WireManager.Keyword(), input.WireId)
  5230. } else {
  5231. return nil, errors.Wrap(err, "FetchByIdOrName")
  5232. }
  5233. }
  5234. wireId = wireObj.GetId()
  5235. }
  5236. ipAddr := input.IpAddr
  5237. if len(ipAddr) > 0 && !regutils.MatchIP4Addr(ipAddr) {
  5238. return nil, errors.Wrapf(httperrors.ErrInputParameter, "invalid ip_addr %s", ipAddr)
  5239. }
  5240. ip6Addr := input.Ip6Addr
  5241. if len(ip6Addr) > 0 && !regutils.MatchIP6Addr(ip6Addr) {
  5242. return nil, errors.Wrapf(httperrors.ErrInputParameter, "invalid ip6_addr %s", ip6Addr)
  5243. }
  5244. rate := input.Rate
  5245. nicType := input.NicType
  5246. index := input.Index
  5247. linkUp := input.LinkUp
  5248. mtu := input.Mtu
  5249. reset := (input.Reset != nil && *input.Reset)
  5250. netIf := input.Interface
  5251. bridge := input.Bridge
  5252. reserve := (input.Reserve != nil && *input.Reserve)
  5253. requireDesignatedIp := (input.RequireDesignatedIp != nil && *input.RequireDesignatedIp)
  5254. requireIpv6 := (input.RequireIpv6 != nil && *input.RequireIpv6)
  5255. strictIpv6 := (input.StrictIpv6 != nil && *input.StrictIpv6)
  5256. isLinkUp := tristate.None
  5257. if linkUp != "" {
  5258. if utils.ToBool(linkUp) {
  5259. isLinkUp = tristate.True
  5260. } else {
  5261. isLinkUp = tristate.False
  5262. }
  5263. }
  5264. err = h.addNetif(ctx, userCred, mac, vlan, wireId, ipAddr, ip6Addr, int(rate), nicType, index, isLinkUp,
  5265. int16(mtu), reset, netIf, bridge, reserve, requireDesignatedIp, requireIpv6, strictIpv6)
  5266. return nil, errors.Wrap(err, "addNetif")
  5267. }
  5268. func (h *SHost) addNetif(ctx context.Context, userCred mcclient.TokenCredential,
  5269. mac string, vlanId int, wireId string, ipAddr string, ip6Addr string,
  5270. rate int, nicType compute.TNicType, index int, linkUp tristate.TriState, mtu int16,
  5271. reset bool, strInterface *string, strBridge *string,
  5272. reserve bool, requireDesignatedIp bool, requireIpv6 bool, strictIpv6 bool,
  5273. ) error {
  5274. var sw *SWire
  5275. if len(wireId) > 0 {
  5276. iWire, err := WireManager.FetchById(wireId)
  5277. if err != nil {
  5278. if err == sql.ErrNoRows {
  5279. return httperrors.NewResourceNotFoundError2(WireManager.Keyword(), wireId)
  5280. } else {
  5281. return httperrors.NewInternalServerError("find Wire %s error: %s", wireId, err)
  5282. }
  5283. }
  5284. sw = iWire.(*SWire)
  5285. if len(ipAddr) > 0 || len(ip6Addr) > 0 {
  5286. var v4addr *netutils.IPV4Addr
  5287. var v6addr *netutils.IPV6Addr
  5288. if len(ipAddr) > 0 {
  5289. iIpAddr, err := netutils.NewIPV4Addr(ipAddr)
  5290. if err != nil {
  5291. return httperrors.NewInputParameterError("invalid ipaddr %s", ipAddr)
  5292. }
  5293. v4addr = &iIpAddr
  5294. }
  5295. if len(ip6Addr) > 0 {
  5296. iIp6Addr, err := netutils.NewIPV6Addr(ip6Addr)
  5297. if err != nil {
  5298. return httperrors.NewInputParameterError("invalid ip6addr %s", ip6Addr)
  5299. }
  5300. v6addr = &iIp6Addr
  5301. }
  5302. var v4net, v6net *SNetwork
  5303. swNets, err := sw.getNetworks(ctx, userCred, userCred, NetworkManager.AllowScope(userCred))
  5304. if err != nil {
  5305. return httperrors.NewInputParameterError("no networks on wire %s", wireId)
  5306. }
  5307. for i := range swNets {
  5308. if v4net == nil && v4addr != nil && swNets[i].IsAddressInRange(*v4addr) {
  5309. v4net = &swNets[i]
  5310. }
  5311. if v6net == nil && v6addr != nil && swNets[i].IsAddress6InRange(*v6addr) {
  5312. v6net = &swNets[i]
  5313. }
  5314. if v4net != nil && v6net != nil {
  5315. break
  5316. }
  5317. }
  5318. if v4net == nil && v6net == nil {
  5319. var addrs []string
  5320. if len(ipAddr) > 0 {
  5321. addrs = append(addrs, ipAddr)
  5322. }
  5323. if len(ip6Addr) > 0 {
  5324. addrs = append(addrs, ip6Addr)
  5325. }
  5326. return httperrors.NewBadRequestError("IP %s not attach to wire %s", strings.Join(addrs, ","), wireId)
  5327. }
  5328. if v4net != nil && v6net != nil && v4net.Id != v6net.Id {
  5329. return httperrors.NewConflictError("IPv4 %s and IPv6 %s must be on the same network", ipAddr, ip6Addr)
  5330. }
  5331. }
  5332. } else {
  5333. var v4wire, v6wire *SWire
  5334. if len(ipAddr) > 0 {
  5335. ipWire, err := WireManager.GetOnPremiseWireOfIp(ipAddr)
  5336. if err != nil {
  5337. return httperrors.NewBadRequestError("IP %s not attach to any wire", ipAddr)
  5338. }
  5339. v4wire = ipWire
  5340. }
  5341. if len(ip6Addr) > 0 {
  5342. ipWire, err := WireManager.GetOnPremiseWireOfIp6(ip6Addr)
  5343. if err != nil {
  5344. return httperrors.NewBadRequestError("IPv6 %s not attach to any wire", ip6Addr)
  5345. }
  5346. v6wire = ipWire
  5347. }
  5348. if v4wire != nil && v6wire != nil && v4wire.Id != v6wire.Id {
  5349. return httperrors.NewConflictError("IPv4 %s and IPv6 %s must be on the same wire", ipAddr, ip6Addr)
  5350. }
  5351. if v4wire != nil {
  5352. sw = v4wire
  5353. } else if v6wire != nil {
  5354. sw = v6wire
  5355. }
  5356. }
  5357. netif, err := NetInterfaceManager.FetchByMacVlan(mac, vlanId)
  5358. if err != nil {
  5359. if errors.Cause(err) != sql.ErrNoRows {
  5360. return httperrors.NewInternalServerError("fail to fetch netif by mac %s: %s", mac, err)
  5361. }
  5362. // else not found
  5363. netif = &SNetInterface{}
  5364. netif.SetModelManager(NetInterfaceManager, netif)
  5365. netif.Mac = mac
  5366. netif.VlanId = vlanId
  5367. }
  5368. var changed bool
  5369. if netif.BaremetalId != h.Id {
  5370. if len(netif.BaremetalId) > 0 {
  5371. changed = true
  5372. // previously conencted to another host
  5373. }
  5374. netif.BaremetalId = h.Id
  5375. }
  5376. if sw != nil && netif.WireId != sw.Id {
  5377. if len(netif.WireId) > 0 {
  5378. changed = true
  5379. }
  5380. netif.WireId = sw.Id
  5381. } else if netif.WireId != "" && sw == nil {
  5382. changed = true
  5383. netif.WireId = ""
  5384. }
  5385. if rate > 0 && rate != netif.Rate {
  5386. netif.Rate = rate
  5387. }
  5388. if nicType != "" && nicType != netif.NicType {
  5389. netif.NicType = nicType
  5390. }
  5391. if index >= 0 {
  5392. netif.Index = index
  5393. }
  5394. if !linkUp.IsNone() && linkUp.Bool() != netif.LinkUp {
  5395. netif.LinkUp = linkUp.Bool()
  5396. }
  5397. if mtu > 0 && mtu != netif.Mtu {
  5398. netif.Mtu = mtu
  5399. }
  5400. if strInterface != nil {
  5401. netif.Interface = *strInterface
  5402. }
  5403. if strBridge != nil {
  5404. netif.Bridge = *strBridge
  5405. }
  5406. // ensure index is unique on host
  5407. {
  5408. ifs := h.GetHostNetInterfaces()
  5409. dupIdx := false
  5410. var maxIdx int
  5411. for i := range ifs {
  5412. if ifs[i].Mac == netif.Mac && ifs[i].VlanId == netif.VlanId {
  5413. // find self, skip
  5414. continue
  5415. }
  5416. if netif.Index == ifs[i].Index {
  5417. // duplicate nic index
  5418. dupIdx = true
  5419. }
  5420. if maxIdx < ifs[i].Index {
  5421. maxIdx = ifs[i].Index
  5422. }
  5423. }
  5424. if dupIdx {
  5425. netif.Index = maxIdx + 1
  5426. }
  5427. }
  5428. err = NetInterfaceManager.TableSpec().InsertOrUpdate(ctx, netif)
  5429. if err != nil {
  5430. return errors.Wrap(err, "InsertOrUpdate")
  5431. }
  5432. if changed || reset {
  5433. h.DisableNetif(ctx, userCred, netif, false)
  5434. }
  5435. if netif.NicType == api.NIC_TYPE_ADMIN {
  5436. oldadmins := h.GetAdminNetInterfaces()
  5437. for i := range oldadmins {
  5438. oldNetif := oldadmins[i]
  5439. if oldNetif.Mac != netif.Mac || oldNetif.VlanId != netif.VlanId {
  5440. // make normal netif
  5441. err := oldNetif.setNicType(api.NIC_TYPE_NORMAL)
  5442. if err != nil {
  5443. return errors.Wrapf(err, "setNicType %s", oldNetif.String())
  5444. }
  5445. }
  5446. }
  5447. err := h.setAccessMac(userCred, netif.Mac)
  5448. if err != nil {
  5449. return errors.Wrap(err, "setAccessMac")
  5450. }
  5451. // inherit wire's class metadata
  5452. sw = netif.GetWire()
  5453. if sw != nil {
  5454. err := db.InheritFromTo(ctx, userCred, sw, h)
  5455. if err != nil {
  5456. return errors.Wrapf(err, "unable to inherit class metadata from sw %s", sw.GetName())
  5457. }
  5458. }
  5459. }
  5460. if len(ipAddr) > 0 || len(ip6Addr) > 0 {
  5461. err = h.EnableNetif(ctx, userCred, netif, "", ipAddr, ip6Addr, "", "", reserve, requireDesignatedIp, requireIpv6, strictIpv6)
  5462. if err != nil {
  5463. return httperrors.NewBadRequestError("%v", err)
  5464. }
  5465. }
  5466. h.ClearSchedDescCache()
  5467. return nil
  5468. }
  5469. func (h *SHost) PerformEnableNetif(
  5470. ctx context.Context,
  5471. userCred mcclient.TokenCredential,
  5472. query jsonutils.JSONObject,
  5473. input api.HostEnableNetifInput,
  5474. ) (jsonutils.JSONObject, error) {
  5475. log.Debugf("enable_netif %s", jsonutils.Marshal(input))
  5476. var err error
  5477. input.HostNetifInput, err = validateHostNetif(input.HostNetifInput)
  5478. if err != nil {
  5479. return nil, errors.Wrap(err, "validateHostNetif")
  5480. }
  5481. netif := h.GetNetInterface(input.Mac, input.VlanId)
  5482. if netif == nil {
  5483. return nil, httperrors.NewBadRequestError("Interface %s(vlan:%d) not exist", input.Mac, input.VlanId)
  5484. }
  5485. // if netif.NicType ! !utils.IsInArray(netif.NicType, api.NIC_TYPES) {
  5486. // return nil, httperrors.NewBadRequestError("Only ADMIN and IPMI nic can be enable")
  5487. // }
  5488. reserve := (input.Reserve != nil && *input.Reserve)
  5489. requireDesignatedIp := (input.RequireDesignatedIp != nil && *input.RequireDesignatedIp)
  5490. requireIpv6 := (input.RequireIpv6 != nil && *input.RequireIpv6)
  5491. strictIpv6 := (input.StrictIpv6 != nil && *input.StrictIpv6)
  5492. err = h.EnableNetif(ctx, userCred, netif, input.NetworkId, input.IpAddr, input.Ip6Addr, input.AllocDir, input.NetType, reserve, requireDesignatedIp, requireIpv6, strictIpv6)
  5493. if err != nil {
  5494. return nil, httperrors.NewBadRequestError("%v", err)
  5495. }
  5496. return nil, nil
  5497. }
  5498. func (h *SHost) EnableNetif(ctx context.Context, userCred mcclient.TokenCredential, netif *SNetInterface,
  5499. network, ipAddr, ip6Addr, allocDir string, netType api.TNetworkType, reserve, requireDesignatedIp bool,
  5500. requireIpv6 bool, strictIpv6 bool) error {
  5501. // bn := netif.GetHostNetwork()
  5502. // if bn != nil {
  5503. // log.Debugf("Netif has been attach2network? %s", jsonutils.Marshal(bn))
  5504. // return nil
  5505. // }
  5506. var v4net, v6net *SNetwork
  5507. var err error
  5508. if len(ipAddr) > 0 && !strictIpv6 {
  5509. net, err := netif.GetCandidateNetworkForIp(ctx, userCred, userCred, NetworkManager.AllowScope(userCred), ipAddr)
  5510. if net != nil {
  5511. log.Infof("find network %s for ip4 %s", net.GetName(), ipAddr)
  5512. v4net = net
  5513. } else if requireDesignatedIp {
  5514. log.Errorf("Cannot allocate IP %s, not reachable: %s", ipAddr, err)
  5515. return fmt.Errorf("Cannot allocate IP %s, not reachable: %s", ipAddr, err)
  5516. } else {
  5517. log.Infof("not found network with scope: %s, ip_addr: %s, err: %s", NetworkManager.AllowScope(userCred), ipAddr, err)
  5518. // the ipaddr is not usable, should be reset to empty
  5519. ipAddr = ""
  5520. }
  5521. }
  5522. if len(ip6Addr) > 0 {
  5523. if v4net != nil {
  5524. ip6, err := netutils.NewIPV6Addr(ip6Addr)
  5525. if err != nil {
  5526. return errors.Wrapf(err, "netutils.NewIPV6Addr: %s", ip6Addr)
  5527. }
  5528. if v4net.IsAddress6InRange(ip6) {
  5529. v6net = v4net
  5530. }
  5531. } else {
  5532. net, err := netif.GetCandidateNetworkForIp6(ctx, userCred, userCred, NetworkManager.AllowScope(userCred), ip6Addr)
  5533. if net != nil {
  5534. log.Infof("find network %s for ip %s", net.GetName(), ip6Addr)
  5535. v6net = net
  5536. } else if requireIpv6 {
  5537. log.Errorf("Cannot allocate IPv6 %s, not reachable: %s", ip6Addr, err)
  5538. return fmt.Errorf("Cannot allocate IPv6 %s, not reachable: %s", ip6Addr, err)
  5539. } else {
  5540. log.Infof("not found network with scope: %s, ip6_addr: %s, err: %s", NetworkManager.AllowScope(userCred), ip6Addr, err)
  5541. // the ipaddr is not usable, should be reset to empty
  5542. ip6Addr = ""
  5543. }
  5544. }
  5545. }
  5546. var net *SNetwork
  5547. if v4net != nil && v6net != nil {
  5548. if v4net.Id != v6net.Id {
  5549. return errors.Wrap(httperrors.ErrConflict, "v4net and v6net must be on the same network")
  5550. }
  5551. net = v4net
  5552. } else if v6net != nil {
  5553. net = v6net
  5554. } else if v4net != nil {
  5555. net = v4net
  5556. }
  5557. wire := netif.GetWire()
  5558. if wire == nil {
  5559. return fmt.Errorf("No wire attached")
  5560. }
  5561. if h.ZoneId == "" {
  5562. if _, err := h.SaveUpdates(func() error {
  5563. h.ZoneId = wire.ZoneId
  5564. return nil
  5565. }); err != nil {
  5566. return errors.Wrapf(err, "set host zone_id %s by wire", wire.ZoneId)
  5567. }
  5568. }
  5569. if net == nil {
  5570. if len(network) > 0 {
  5571. iNet, err := NetworkManager.FetchByIdOrName(ctx, userCred, network)
  5572. if err != nil {
  5573. return fmt.Errorf("Network %s not found: %s", network, err)
  5574. }
  5575. net = iNet.(*SNetwork)
  5576. if len(net.WireId) == 0 || net.WireId != wire.Id {
  5577. return fmt.Errorf("Network %s not reacheable on mac %s", network, netif.Mac)
  5578. }
  5579. } else {
  5580. var netTypes []api.TNetworkType
  5581. if len(netType) > 0 && netType != api.NETWORK_TYPE_BAREMETAL {
  5582. netTypes = []api.TNetworkType{netType, api.NETWORK_TYPE_BAREMETAL}
  5583. } else {
  5584. netTypes = []api.TNetworkType{api.NETWORK_TYPE_BAREMETAL}
  5585. }
  5586. net, err = wire.GetCandidatePrivateNetwork(ctx, userCred, userCred, NetworkManager.AllowScope(userCred), false, netTypes)
  5587. if err != nil {
  5588. return fmt.Errorf("fail to find private network %s", err)
  5589. }
  5590. if net == nil {
  5591. net, err = wire.GetCandidateAutoAllocNetwork(ctx, userCred, userCred, NetworkManager.AllowScope(userCred), false, netTypes)
  5592. if err != nil {
  5593. return fmt.Errorf("fail to find public network %s", err)
  5594. }
  5595. if net == nil {
  5596. return fmt.Errorf("No auto_alloc network found of wire: %s(%s), netTypes: %v", wire.GetName(), wire.GetId(), netTypes)
  5597. }
  5598. }
  5599. }
  5600. } else if net.WireId != wire.Id {
  5601. return fmt.Errorf("conflict??? candiate net is not on wire")
  5602. }
  5603. attachOpt := &hostAttachNetworkOption{
  5604. netif: netif,
  5605. net: net,
  5606. ipAddr: ipAddr,
  5607. allocDir: allocDir,
  5608. reserved: reserve,
  5609. requireDesignatedIp: requireDesignatedIp,
  5610. ip6Addr: ip6Addr,
  5611. requireIpv6: requireIpv6,
  5612. strictIpv6: strictIpv6,
  5613. }
  5614. bn, err := h.attach2Network(ctx, userCred, attachOpt)
  5615. if err != nil {
  5616. return errors.Wrap(err, "hh.Attach2Network")
  5617. }
  5618. bnIP := bn.IpAddr
  5619. if len(bnIP) == 0 {
  5620. bnIP = bn.Ip6Addr
  5621. }
  5622. switch netif.NicType {
  5623. case api.NIC_TYPE_IPMI:
  5624. err = h.setIpmiIp(userCred, bnIP)
  5625. if err != nil {
  5626. return errors.Wrap(err, "setIpmiIp")
  5627. }
  5628. case api.NIC_TYPE_ADMIN:
  5629. err = h.setAccessIp(userCred, bnIP)
  5630. if err != nil {
  5631. return errors.Wrap(err, "setAccessIp")
  5632. }
  5633. }
  5634. return nil
  5635. }
  5636. func (hh *SHost) PerformDisableNetif(
  5637. ctx context.Context,
  5638. userCred mcclient.TokenCredential,
  5639. query jsonutils.JSONObject,
  5640. input api.HostDisableNetifInput,
  5641. ) (jsonutils.JSONObject, error) {
  5642. var err error
  5643. input.HostNetifInput, err = validateHostNetif(input.HostNetifInput)
  5644. if err != nil {
  5645. return nil, errors.Wrap(err, "validateHostNetif")
  5646. }
  5647. netif := hh.GetNetInterface(input.Mac, input.VlanId)
  5648. if netif == nil {
  5649. return nil, httperrors.NewBadRequestError("Interface %s(vlan:%d) not exists", input.Mac, input.VlanId)
  5650. }
  5651. reserve := (input.Reserve != nil && *input.Reserve)
  5652. err = hh.DisableNetif(ctx, userCred, netif, reserve)
  5653. if err != nil {
  5654. return nil, httperrors.NewBadRequestError("%v", err)
  5655. }
  5656. return nil, nil
  5657. }
  5658. /*
  5659. * Disable a net interface, remove IP address if assigned
  5660. */
  5661. func (hh *SHost) DisableNetif(ctx context.Context, userCred mcclient.TokenCredential, netif *SNetInterface, reserve bool) error {
  5662. bn := netif.GetHostNetwork()
  5663. var ipAddr, ip6Addr string
  5664. if bn != nil {
  5665. ipAddr = bn.IpAddr
  5666. ip6Addr = bn.Ip6Addr
  5667. hh.UpdateDnsRecord(netif, false)
  5668. hh.DeleteBaremetalnetwork(ctx, userCred, bn, reserve)
  5669. }
  5670. var err error
  5671. switch netif.NicType {
  5672. case api.NIC_TYPE_IPMI:
  5673. if ipAddr == hh.IpmiIp || ip6Addr == hh.IpmiIp {
  5674. err = hh.setIpmiIp(userCred, "")
  5675. }
  5676. case api.NIC_TYPE_ADMIN:
  5677. if ipAddr == hh.AccessIp || ip6Addr == hh.AccessIp {
  5678. err = hh.setAccessIp(userCred, "")
  5679. }
  5680. }
  5681. return err
  5682. }
  5683. type hostAttachNetworkOption struct {
  5684. netif *SNetInterface
  5685. net *SNetwork
  5686. ipAddr string
  5687. allocDir string
  5688. reserved bool
  5689. requireDesignatedIp bool
  5690. ip6Addr string
  5691. requireIpv6 bool
  5692. strictIpv6 bool
  5693. }
  5694. func (hh *SHost) IsIpAddrWithinConvertedGuest(ctx context.Context, userCred mcclient.TokenCredential, ipAddr, ip6Addr string, netif *SNetInterface) error {
  5695. if !hh.IsBaremetal {
  5696. return httperrors.NewNotAcceptableError("Not a baremetal")
  5697. }
  5698. // ?
  5699. // if hh.HostType == api.HOST_TYPE_KVM {
  5700. // return httperrors.NewNotAcceptableError("Not being convert to hypervisor")
  5701. // }
  5702. bmServer := hh.GetBaremetalServer()
  5703. if bmServer == nil {
  5704. return httperrors.NewNotAcceptableError("Not found baremetal server record")
  5705. }
  5706. guestNics, err := bmServer.GetNetworks("")
  5707. if err != nil {
  5708. return errors.Wrap(err, "Get guest networks")
  5709. }
  5710. var findNic *SGuestnetwork
  5711. for idx := range guestNics {
  5712. nic := guestNics[idx]
  5713. if nic.MacAddr == netif.Mac {
  5714. findNic = &nic
  5715. break
  5716. }
  5717. }
  5718. if findNic == nil {
  5719. return httperrors.NewNotFoundError("Not found guest nic by mac %s", netif.Mac)
  5720. }
  5721. if len(ipAddr) > 0 && findNic.IpAddr != ipAddr {
  5722. return httperrors.NewNotAcceptableError("Guest nic ip addr %s not equal %s", findNic.IpAddr, ipAddr)
  5723. }
  5724. if len(ip6Addr) > 0 && findNic.Ip6Addr != ip6Addr {
  5725. return httperrors.NewNotAcceptableError("Guest nic ip addr6 %s not equal %s", findNic.Ip6Addr, ip6Addr)
  5726. }
  5727. return nil
  5728. }
  5729. func (hh *SHost) attach2Network(
  5730. ctx context.Context,
  5731. userCred mcclient.TokenCredential,
  5732. opt *hostAttachNetworkOption,
  5733. ) (*SHostnetwork, error) {
  5734. log.Infof("host attach2Network: %s", jsonutils.Marshal(opt))
  5735. netif := opt.netif
  5736. net := opt.net
  5737. ipAddr := opt.ipAddr
  5738. ip6Addr := opt.ip6Addr
  5739. allocDir := opt.allocDir
  5740. reserved := opt.reserved
  5741. requireDesignatedIp := opt.requireDesignatedIp
  5742. bn := opt.netif.GetHostNetwork()
  5743. lockman.LockObject(ctx, net)
  5744. defer lockman.ReleaseObject(ctx, net)
  5745. var freeIp4, freeIp6 string
  5746. if (!opt.strictIpv6 || len(ipAddr) > 0) && (bn == nil || bn.IpAddr != ipAddr) && net.HasIPv4Addr() {
  5747. // allocate ipv4 address
  5748. usedAddrs := net.GetUsedAddresses(ctx)
  5749. if ipAddr != "" {
  5750. // converted baremetal can resuse related guest network ip
  5751. if err := hh.IsIpAddrWithinConvertedGuest(ctx, userCred, ipAddr, "", netif); err == nil {
  5752. // force remove used server addr for reuse
  5753. delete(usedAddrs, ipAddr)
  5754. } else {
  5755. log.Warningf("check IsIpAddrWithinConvertedGuest: %v", err)
  5756. }
  5757. }
  5758. freeIp, err := net.GetFreeIP(ctx, userCred, usedAddrs, nil, ipAddr, api.IPAllocationDirection(allocDir), reserved, api.AddressTypeIPv4)
  5759. if err != nil {
  5760. return nil, errors.Wrap(err, "net.GetFreeIPv4")
  5761. }
  5762. if len(ipAddr) > 0 && ipAddr != freeIp && requireDesignatedIp {
  5763. return nil, fmt.Errorf("IPv4 address %s is occupied, get %s instead", ipAddr, freeIp)
  5764. }
  5765. freeIp4 = freeIp
  5766. }
  5767. if (opt.requireIpv6 || len(ip6Addr) > 0) && (bn == nil || bn.Ip6Addr != ip6Addr) && net.HasIPv6Addr() {
  5768. usedAddrs6 := net.GetUsedAddresses6(ctx)
  5769. if ip6Addr != "" {
  5770. // converted baremetal can resuse related guest network ip
  5771. if err := hh.IsIpAddrWithinConvertedGuest(ctx, userCred, "", ip6Addr, netif); err == nil {
  5772. // force remove used server addr for reuse
  5773. delete(usedAddrs6, ip6Addr)
  5774. } else {
  5775. log.Warningf("check IsIpAddrWithinConvertedGuest: %v", err)
  5776. }
  5777. }
  5778. freeIp, err := net.GetFreeIP(ctx, userCred, usedAddrs6, nil, ip6Addr, api.IPAllocationDirection(allocDir), reserved, api.AddressTypeIPv6)
  5779. if err != nil {
  5780. return nil, errors.Wrap(err, "net.GetFreeIPv6")
  5781. }
  5782. if len(ip6Addr) > 0 && ip6Addr != freeIp && requireDesignatedIp {
  5783. return nil, fmt.Errorf("IPv6 address %s is occupied, get %s instead", ip6Addr, freeIp)
  5784. }
  5785. freeIp6 = freeIp
  5786. }
  5787. if bn == nil {
  5788. bn = &SHostnetwork{}
  5789. bn.SetModelManager(HostnetworkManager, bn)
  5790. bn.BaremetalId = hh.Id
  5791. bn.NetworkId = net.Id
  5792. bn.MacAddr = netif.Mac
  5793. bn.VlanId = netif.VlanId
  5794. bn.IpAddr = freeIp4
  5795. bn.Ip6Addr = freeIp6
  5796. err := HostnetworkManager.TableSpec().Insert(ctx, bn)
  5797. if err != nil {
  5798. return nil, errors.Wrap(err, "HostnetworkManager.TableSpec().Insert")
  5799. }
  5800. } else if (freeIp4 != "" && freeIp4 != bn.IpAddr) || (freeIp6 != "" && freeIp6 != bn.Ip6Addr) {
  5801. _, err := db.Update(bn, func() error {
  5802. if freeIp4 != "" {
  5803. bn.IpAddr = freeIp4
  5804. }
  5805. if freeIp6 != "" {
  5806. bn.Ip6Addr = freeIp6
  5807. }
  5808. return nil
  5809. })
  5810. if err != nil {
  5811. return nil, errors.Wrap(err, "HostnetworkManager.TableSpec().Insert")
  5812. }
  5813. } else {
  5814. return bn, nil
  5815. }
  5816. var addrs []string
  5817. if len(freeIp4) > 0 {
  5818. addrs = append(addrs, freeIp4)
  5819. }
  5820. if len(freeIp6) > 0 {
  5821. addrs = append(addrs, freeIp6)
  5822. }
  5823. db.OpsLog.LogAttachEvent(ctx, hh, net, userCred, jsonutils.NewString(strings.Join(addrs, ",")))
  5824. hh.UpdateDnsRecord(netif, true)
  5825. // net.UpdateBaremetalNetmap(bn, hh.GetNetifName(netif))
  5826. return bn, nil
  5827. }
  5828. func (hh *SHost) PerformRemoveNetif(
  5829. ctx context.Context,
  5830. userCred mcclient.TokenCredential,
  5831. query jsonutils.JSONObject,
  5832. input api.HostRemoveNetifInput,
  5833. ) (jsonutils.JSONObject, error) {
  5834. var err error
  5835. input.HostNetifInput, err = validateHostNetif(input.HostNetifInput)
  5836. if err != nil {
  5837. return nil, errors.Wrap(err, "validateHostNetif")
  5838. }
  5839. netif := hh.GetNetInterface(input.Mac, input.VlanId)
  5840. if netif == nil {
  5841. return nil, httperrors.NewBadRequestError("Interface %s(vlan:%d) not exists", input.Mac, input.VlanId)
  5842. }
  5843. reserve := (input.Reserve != nil && *input.Reserve)
  5844. return nil, hh.RemoveNetif(ctx, userCred, netif, reserve)
  5845. }
  5846. func (h *SHost) RemoveNetif(ctx context.Context, userCred mcclient.TokenCredential, netif *SNetInterface, reserve bool) error {
  5847. h.DisableNetif(ctx, userCred, netif, reserve)
  5848. // is this a converted host?
  5849. if h.HostType == api.HOST_TYPE_HYPERVISOR && h.IsBaremetal {
  5850. guests, err := h.GetGuests()
  5851. if err != nil {
  5852. return errors.Wrap(err, "GetGuests")
  5853. }
  5854. for i := range guests {
  5855. guest := &guests[i]
  5856. if guest.Hypervisor == api.HYPERVISOR_BAREMETAL {
  5857. gn, err := guest.GetGuestnetworkByMac(netif.Mac)
  5858. if err != nil && errors.Cause(err) != sql.ErrNoRows {
  5859. return errors.Wrap(err, "GetGuestnetworkByMac")
  5860. } else if gn != nil {
  5861. err = gn.Detach(ctx, userCred)
  5862. if err != nil {
  5863. return errors.Wrap(err, "detach guest nic")
  5864. }
  5865. }
  5866. }
  5867. }
  5868. }
  5869. if netif.NicType == api.NIC_TYPE_ADMIN && h.AccessMac == netif.Mac {
  5870. err := h.setAccessMac(userCred, "")
  5871. if err != nil {
  5872. return errors.Wrap(err, "setAccessMac")
  5873. }
  5874. }
  5875. err := netif.Delete(ctx, userCred)
  5876. if err != nil {
  5877. return errors.Wrap(err, "netif.Remove")
  5878. }
  5879. h.ClearSchedDescCache()
  5880. return nil
  5881. }
  5882. func (hh *SHost) getNetifsOnWire(wireId string) []SNetInterface {
  5883. return hh.getNetInterfacesInternal(wireId, api.HOST_NIC_TYPES)
  5884. }
  5885. func (hh *SHost) PerformSyncstatus(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
  5886. if hh.HostType != api.HOST_TYPE_BAREMETAL {
  5887. return nil, httperrors.NewBadRequestError("Cannot sync status a non-baremetal host")
  5888. }
  5889. hh.SetStatus(ctx, userCred, api.BAREMETAL_SYNCING_STATUS, "")
  5890. return nil, hh.StartSyncstatus(ctx, userCred, "")
  5891. }
  5892. func (hh *SHost) PerformReset(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
  5893. if !hh.IsBaremetal {
  5894. return nil, httperrors.NewBadRequestError("Cannot start a non-baremetal host")
  5895. }
  5896. if hh.Status != api.BAREMETAL_RUNNING {
  5897. return nil, httperrors.NewBadRequestError("Cannot reset baremetal in status %s", hh.Status)
  5898. }
  5899. guest := hh.GetBaremetalServer()
  5900. if guest != nil {
  5901. if hh.HostType == api.HOST_TYPE_BAREMETAL {
  5902. if guest.Status != api.VM_ADMIN {
  5903. return nil, httperrors.NewBadRequestError("Cannot reset baremetal with active guest")
  5904. }
  5905. } else {
  5906. return guest.PerformReset(ctx, userCred, query, data)
  5907. }
  5908. }
  5909. kwargs := jsonutils.NewDict()
  5910. kwargs.Set("force_reboot", jsonutils.JSONTrue)
  5911. kwargs.Set("action", jsonutils.NewString("reset"))
  5912. return hh.PerformMaintenance(ctx, userCred, query, kwargs)
  5913. }
  5914. func (hh *SHost) PerformRemoveAllNetifs(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
  5915. netifs := hh.GetAllNetInterfaces()
  5916. for i := 0; i < len(netifs); i++ {
  5917. if netifs[i].NicType == api.NIC_TYPE_NORMAL {
  5918. hh.RemoveNetif(ctx, userCred, &netifs[i], false)
  5919. }
  5920. }
  5921. return nil, nil
  5922. }
  5923. func (hh *SHost) PerformEnable(
  5924. ctx context.Context,
  5925. userCred mcclient.TokenCredential,
  5926. query jsonutils.JSONObject,
  5927. input apis.PerformEnableInput,
  5928. ) (jsonutils.JSONObject, error) {
  5929. if !hh.GetEnabled() {
  5930. _, err := hh.SEnabledStatusInfrasResourceBase.PerformEnable(ctx, userCred, query, input)
  5931. if err != nil {
  5932. return nil, errors.Wrap(err, "SEnabledStatusInfrasResourceBase.PerformEnable")
  5933. }
  5934. hh.SyncAttachedStorageStatus(ctx)
  5935. hh.updateNotify(ctx, userCred)
  5936. }
  5937. return nil, nil
  5938. }
  5939. func (hh *SHost) PerformDisable(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.PerformDisableInput) (jsonutils.JSONObject, error) {
  5940. if hh.GetEnabled() {
  5941. _, err := hh.SEnabledStatusInfrasResourceBase.PerformDisable(ctx, userCred, query, input)
  5942. if err != nil {
  5943. return nil, errors.Wrap(err, "SEnabledStatusInfrasResourceBase.PerformDisable")
  5944. }
  5945. hh.SyncAttachedStorageStatus(ctx)
  5946. hh.updateNotify(ctx, userCred)
  5947. }
  5948. return nil, nil
  5949. }
  5950. func (hh *SHost) PerformCacheImage(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.CacheImageInput) (jsonutils.JSONObject, error) {
  5951. if hh.HostType == api.HOST_TYPE_BAREMETAL || hh.HostStatus != api.HOST_ONLINE {
  5952. return nil, httperrors.NewInvalidStatusError("Cannot perform cache image in status %s", hh.Status)
  5953. }
  5954. if len(input.ImageId) == 0 {
  5955. return nil, httperrors.NewMissingParameterError("image_id")
  5956. }
  5957. img, err := CachedimageManager.getImageInfo(ctx, userCred, input.ImageId, false)
  5958. if err != nil {
  5959. return nil, httperrors.NewNotFoundError("image %s not found", input.ImageId)
  5960. }
  5961. input.ImageId = img.Id
  5962. if len(img.Checksum) != 0 && regutils.MatchUUID(img.Checksum) {
  5963. return nil, httperrors.NewInvalidStatusError("Cannot cache image with no checksum")
  5964. }
  5965. return nil, hh.StartImageCacheTask(ctx, userCred, input)
  5966. }
  5967. func (hh *SHost) StartImageCacheTask(ctx context.Context, userCred mcclient.TokenCredential, input api.CacheImageInput) error {
  5968. var sc *SStoragecache
  5969. switch hh.HostType {
  5970. case api.HOST_TYPE_BAREMETAL:
  5971. case api.HOST_TYPE_HYPERVISOR, api.HOST_TYPE_ESXI:
  5972. sc = hh.GetLocalStoragecache()
  5973. default:
  5974. sc = hh.GetStoragecache()
  5975. }
  5976. if sc == nil {
  5977. return errors.Wrap(errors.ErrNotSupported, "No associate storage cache found")
  5978. }
  5979. return sc.StartImageCacheTask(ctx, userCred, input)
  5980. }
  5981. func (hh *SHost) isAlterNameUnique(name string) (bool, error) {
  5982. q := HostManager.Query().Equals("name", name).NotEquals("id", hh.Id).Equals("zone_id", hh.ZoneId)
  5983. cnt, err := q.CountWithError()
  5984. if err != nil {
  5985. return false, err
  5986. }
  5987. return cnt == 0, nil
  5988. }
  5989. func (hh *SHost) PerformConvertHypervisor(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
  5990. hostType, err := data.GetString("host_type")
  5991. if err != nil {
  5992. return nil, httperrors.NewNotAcceptableError("host_type must be specified")
  5993. }
  5994. if hh.HostType != api.HOST_TYPE_BAREMETAL {
  5995. return nil, httperrors.NewNotAcceptableError("Must be a baremetal host")
  5996. }
  5997. if hh.GetBaremetalServer() != nil {
  5998. return nil, httperrors.NewNotAcceptableError("Baremetal host is aleady occupied")
  5999. }
  6000. if !utils.IsInStringArray(hh.Status, []string{api.BAREMETAL_READY, api.BAREMETAL_RUNNING}) {
  6001. return nil, httperrors.NewNotAcceptableError("Connot convert hypervisor in status %s", hh.Status)
  6002. }
  6003. // check ownership
  6004. var ownerId mcclient.IIdentityProvider
  6005. hostOwnerId := hh.GetOwnerId()
  6006. if userCred.GetProjectDomainId() != hostOwnerId.GetProjectDomainId() {
  6007. if !db.IsAdminAllowPerform(ctx, userCred, hh, "convert-hypervisor") {
  6008. return nil, httperrors.NewNotSufficientPrivilegeError("require system previleges to convert host in other domain")
  6009. }
  6010. firstProject, err := db.TenantCacheManager.FindFirstProjectOfDomain(ctx, hostOwnerId.GetProjectDomainId())
  6011. if err != nil {
  6012. return nil, errors.Wrap(err, "FindFirstProjectOfDomain")
  6013. }
  6014. ownerId = firstProject
  6015. } else {
  6016. ownerId = userCred
  6017. }
  6018. driver, err := GetHostDriver(hostType, api.CLOUD_PROVIDER_ONECLOUD)
  6019. if err != nil {
  6020. return nil, errors.Wrapf(err, "GetHostDriver")
  6021. }
  6022. if data.Contains("name") {
  6023. name, _ := data.GetString("name")
  6024. err := hh.GetModelManager().ValidateName(name)
  6025. if err != nil {
  6026. return nil, err
  6027. }
  6028. uniq, err := hh.isAlterNameUnique(name)
  6029. if err != nil {
  6030. return nil, httperrors.NewInternalServerError("isAlterNameUnique fail %s", err)
  6031. }
  6032. if !uniq {
  6033. return nil, httperrors.NewDuplicateNameError(name, hh.Id)
  6034. }
  6035. }
  6036. image, _ := data.GetString("image")
  6037. raid, _ := data.GetString("raid")
  6038. input, err := driver.PrepareConvert(hh, image, raid, data)
  6039. if err != nil {
  6040. return nil, httperrors.NewNotAcceptableError("Convert error: %s", err.Error())
  6041. }
  6042. // admin delegate user to create system resource
  6043. input.ProjectDomainId = ownerId.GetProjectDomainId()
  6044. input.ProjectId = ownerId.GetProjectId()
  6045. params := input.JSON(input)
  6046. adminCred := auth.AdminCredential()
  6047. guest, err := db.DoCreate(GuestManager, ctx, adminCred, nil, params, ownerId)
  6048. if err != nil {
  6049. return nil, err
  6050. }
  6051. func() {
  6052. lockman.LockObject(ctx, guest)
  6053. defer lockman.ReleaseObject(ctx, guest)
  6054. guest.PostCreate(ctx, adminCred, ownerId, nil, params)
  6055. }()
  6056. log.Infof("Host convert to %s", guest.GetName())
  6057. db.OpsLog.LogEvent(hh, db.ACT_CONVERT_START, "", userCred)
  6058. db.OpsLog.LogEvent(guest, db.ACT_CREATE, "Convert hypervisor", userCred)
  6059. opts := jsonutils.NewDict()
  6060. opts.Set("server_params", params)
  6061. opts.Set("server_id", jsonutils.NewString(guest.GetId()))
  6062. opts.Set("convert_host_type", jsonutils.NewString(hostType))
  6063. task, err := taskman.TaskManager.NewTask(ctx, "BaremetalConvertHypervisorTask", hh, adminCred, opts, "", "", nil)
  6064. if err != nil {
  6065. return nil, err
  6066. }
  6067. task.ScheduleRun(nil)
  6068. hh.SetStatus(ctx, userCred, api.BAREMETAL_START_CONVERT, "")
  6069. return nil, nil
  6070. }
  6071. func (hh *SHost) PerformUndoConvert(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
  6072. if !hh.IsBaremetal {
  6073. return nil, httperrors.NewNotAcceptableError("Not a baremetal")
  6074. }
  6075. if hh.HostType == api.HOST_TYPE_BAREMETAL {
  6076. return nil, httperrors.NewNotAcceptableError("Not being convert to hypervisor")
  6077. }
  6078. if hh.GetEnabled() {
  6079. return nil, httperrors.NewNotAcceptableError("Host should be disabled")
  6080. }
  6081. if !utils.IsInStringArray(hh.Status, []string{api.BAREMETAL_READY, api.BAREMETAL_RUNNING}) {
  6082. return nil, httperrors.NewNotAcceptableError("Cannot unconvert in status %s", hh.Status)
  6083. }
  6084. driver, err := hh.GetHostDriver()
  6085. if err != nil {
  6086. return nil, errors.Wrapf(err, "GetHostDriver")
  6087. }
  6088. err = driver.PrepareUnconvert(hh)
  6089. if err != nil {
  6090. return nil, httperrors.NewNotAcceptableError("%v", err)
  6091. }
  6092. guests, err := hh.GetGuests()
  6093. if err != nil {
  6094. return nil, httperrors.NewGeneralError(errors.Wrapf(err, "GetGuests"))
  6095. }
  6096. if len(guests) > 1 {
  6097. return nil, httperrors.NewNotAcceptableError("Not an empty host")
  6098. } else if len(guests) == 1 {
  6099. guest := guests[0]
  6100. if guest.Hypervisor != api.HYPERVISOR_BAREMETAL {
  6101. return nil, httperrors.NewNotAcceptableError("Not an converted hypervisor")
  6102. }
  6103. err := guest.SetDisableDelete(userCred, false)
  6104. if err != nil {
  6105. return nil, err
  6106. }
  6107. db.OpsLog.LogEvent(&guest, db.ACT_DELETE, "Unconvert baremetal", userCred)
  6108. }
  6109. db.OpsLog.LogEvent(hh, db.ACT_UNCONVERT_START, "", userCred)
  6110. logclient.AddActionLogWithContext(ctx, hh, logclient.ACT_UNCONVERT_START, nil, userCred, true)
  6111. task, err := taskman.TaskManager.NewTask(ctx, "BaremetalUnconvertHypervisorTask", hh, userCred, nil, "", "", nil)
  6112. if err != nil {
  6113. return nil, err
  6114. }
  6115. task.ScheduleRun(nil)
  6116. return nil, nil
  6117. }
  6118. func (hh *SHost) UpdateDiskConfig(userCred mcclient.TokenCredential, layouts []baremetal.Layout) error {
  6119. bs := hh.GetBaremetalstorage()
  6120. if bs != nil {
  6121. diff, err := db.Update(bs, func() error {
  6122. if len(layouts) != 0 {
  6123. bs.Config = jsonutils.Marshal(layouts).(*jsonutils.JSONArray)
  6124. var size int64
  6125. for i := 0; i < len(layouts); i++ {
  6126. size += layouts[i].Size
  6127. }
  6128. bs.RealCapacity = size
  6129. } else {
  6130. bs.Config = jsonutils.NewArray()
  6131. bs.RealCapacity = bs.GetStorage().Capacity
  6132. }
  6133. return nil
  6134. })
  6135. if err != nil {
  6136. log.Errorln(err)
  6137. return err
  6138. }
  6139. db.OpsLog.LogEvent(bs, db.ACT_UPDATE, diff, userCred)
  6140. }
  6141. return nil
  6142. }
  6143. // TODO: support multithreaded operation
  6144. /*func (host *SHost) SyncEsxiHostWires(ctx context.Context, userCred mcclient.TokenCredential, remoteHost cloudprovider.ICloudHost) compare.SyncResult {
  6145. lockman.LockObject(ctx, host)
  6146. defer lockman.ReleaseObject(ctx, host)
  6147. result := compare.SyncResult{}
  6148. ca := host.GetCloudaccount()
  6149. host2wires, err := ca.GetHost2Wire(ctx, userCred)
  6150. if err != nil {
  6151. result.Error(errors.Wrap(err, "unable to GetHost2Wire"))
  6152. return result
  6153. }
  6154. log.Infof("host2wires: %s", jsonutils.Marshal(host2wires))
  6155. ihost := remoteHost.(*esxi.SHost)
  6156. remoteHostId := ihost.GetId()
  6157. vsWires := host2wires[remoteHostId]
  6158. log.Infof("vsWires: %s", jsonutils.Marshal(vsWires))
  6159. netIfs := host.GetHostNetInterfaces()
  6160. for i := range vsWires {
  6161. vsWire := vsWires[i]
  6162. if vsWire.SyncTimes > 0 {
  6163. continue
  6164. }
  6165. netif := host.findNetIfs(netIfs, vsWire.Mac, 1)
  6166. if netif == nil {
  6167. // do nothing
  6168. continue
  6169. }
  6170. if netif.Bridge != vsWire.VsId {
  6171. db.Update(netif, func() error {
  6172. netif.Bridge = vsWire.VsId
  6173. return nil
  6174. })
  6175. }
  6176. if len(netif.WireId) == 0 {
  6177. db.Update(netif, func() error {
  6178. netif.WireId = vsWire.WireId
  6179. return nil
  6180. })
  6181. }
  6182. vsWires[i].SyncTimes += 1
  6183. }
  6184. log.Infof("after sync: %s", jsonutils.Marshal(host2wires))
  6185. ca.SetHost2Wire(ctx, userCred, host2wires)
  6186. return result
  6187. }*/
  6188. /*func (host *SHost) findHostwire(hostwires []SHostwire, wireId string, mac string) *SHostwire {
  6189. for i := range hostwires {
  6190. if hostwires[i].WireId == wireId && hostwires[i].MacAddr == mac {
  6191. return &hostwires[i]
  6192. }
  6193. }
  6194. return nil
  6195. }*/
  6196. func (host *SHost) findNetIfs(netIfs []SNetInterface, mac string, vlanId int) *SNetInterface {
  6197. for i := range netIfs {
  6198. if netIfs[i].Mac == mac && netIfs[i].VlanId == vlanId {
  6199. return &netIfs[i]
  6200. }
  6201. }
  6202. return nil
  6203. }
  6204. func (host *SHost) SyncHostExternalNics(ctx context.Context, userCred mcclient.TokenCredential, ihost cloudprovider.ICloudHost, provider *SCloudprovider) compare.SyncResult {
  6205. result := compare.SyncResult{}
  6206. netIfs := host.GetHostNetInterfaces()
  6207. extNics, err := ihost.GetIHostNics()
  6208. if err != nil {
  6209. log.Errorf("GetIHostNics fail %s", err)
  6210. result.Error(err)
  6211. return result
  6212. }
  6213. log.Debugf("SyncHostExternalNics for host %s netIfs %d ihost %s extNics %d", host.Name, len(netIfs), ihost.GetName(), len(extNics))
  6214. disables := make([]*SNetInterface, 0)
  6215. enables := make([]cloudprovider.ICloudHostNetInterface, 0)
  6216. type sRemoveNetInterface struct {
  6217. netif *SNetInterface
  6218. reserveIp bool
  6219. }
  6220. type sAddNetInterface struct {
  6221. netif cloudprovider.ICloudHostNetInterface
  6222. reserveIp bool
  6223. }
  6224. removes := make([]sRemoveNetInterface, 0)
  6225. adds := make([]sAddNetInterface, 0)
  6226. for i := 0; i < len(netIfs); i++ {
  6227. find := false
  6228. for j := 0; j < len(extNics); j++ {
  6229. if netIfs[i].Mac == extNics[j].GetMac() && netIfs[i].VlanId == extNics[j].GetVlanId() {
  6230. // find! need to update
  6231. find = true
  6232. obn := netIfs[i].GetHostNetwork()
  6233. var oip string
  6234. if obn != nil {
  6235. oip = obn.IpAddr
  6236. }
  6237. nip := extNics[j].GetIpAddr()
  6238. if oip != nip {
  6239. if obn != nil {
  6240. disables = append(disables, &netIfs[i])
  6241. }
  6242. if len(nip) > 0 {
  6243. enables = append(enables, extNics[j])
  6244. }
  6245. } else {
  6246. wireId := ""
  6247. extWire := extNics[j].GetIWire()
  6248. if extWire != nil {
  6249. wire, err := WireManager.FetchWireByExternalId(provider.Id, extWire.GetGlobalId())
  6250. if err != nil {
  6251. result.AddError(err)
  6252. } else {
  6253. wireId = wire.Id
  6254. }
  6255. }
  6256. // in sync, sync interface and bridge
  6257. if netIfs[i].Bridge != extNics[j].GetBridge() || netIfs[i].Interface != extNics[j].GetDevice() || netIfs[i].WireId != wireId {
  6258. _, err := db.Update(&netIfs[i], func() error {
  6259. netIfs[i].Interface = extNics[j].GetDevice()
  6260. netIfs[i].Bridge = extNics[j].GetBridge()
  6261. netIfs[i].WireId = wireId
  6262. return nil
  6263. })
  6264. if err != nil {
  6265. result.Error(errors.Wrap(err, "update interface and bridge fail"))
  6266. return result
  6267. }
  6268. }
  6269. }
  6270. break
  6271. }
  6272. }
  6273. if !find {
  6274. // need to remove
  6275. removes = append(removes, sRemoveNetInterface{netif: &netIfs[i], reserveIp: false})
  6276. }
  6277. }
  6278. for j := 0; j < len(extNics); j++ {
  6279. find := false
  6280. for i := 0; i < len(netIfs); i++ {
  6281. if netIfs[i].Mac == extNics[j].GetMac() && netIfs[i].VlanId == extNics[j].GetVlanId() {
  6282. find = true
  6283. break
  6284. }
  6285. }
  6286. if !find {
  6287. // need to add
  6288. adds = append(adds, sAddNetInterface{netif: extNics[j], reserveIp: false})
  6289. }
  6290. }
  6291. // find out which ip need to be reserved
  6292. for i := 0; i < len(removes); i++ {
  6293. var oip string
  6294. obn := removes[i].netif.GetHostNetwork()
  6295. if obn != nil {
  6296. oip = obn.IpAddr
  6297. }
  6298. if len(oip) == 0 {
  6299. // skip
  6300. continue
  6301. }
  6302. for j := 0; j < len(adds); j++ {
  6303. if oip == adds[j].netif.GetIpAddr() {
  6304. // find out ! IP reserved but interface changed!
  6305. removes[i].reserveIp = true
  6306. adds[j].reserveIp = true
  6307. break
  6308. }
  6309. }
  6310. }
  6311. log.Debugf("SyncHostExternalNics %s remove %d disable %d enable %d add %d", host.Name, len(removes), len(disables), len(enables), len(adds))
  6312. for i := len(removes) - 1; i >= 0; i -= 1 {
  6313. log.Debugf("remove netif %s", removes[i].netif.Mac)
  6314. err := host.RemoveNetif(ctx, userCred, removes[i].netif, removes[i].reserveIp)
  6315. if err != nil {
  6316. result.DeleteError(err)
  6317. } else {
  6318. result.Delete()
  6319. }
  6320. }
  6321. for i := len(disables) - 1; i >= 0; i -= 1 {
  6322. log.Debugf("disable netif %s", disables[i].Mac)
  6323. err := host.DisableNetif(ctx, userCred, disables[i], false)
  6324. if err != nil {
  6325. result.DeleteError(err)
  6326. } else {
  6327. result.Delete()
  6328. }
  6329. }
  6330. for i := 0; i < len(enables); i += 1 {
  6331. netif := host.GetNetInterface(enables[i].GetMac(), enables[i].GetVlanId())
  6332. // always true reserved address pool
  6333. log.Debugf("enable netif %s", enables[i].GetMac())
  6334. err = host.EnableNetif(ctx, userCred, netif, "", enables[i].GetIpAddr(), "", "", "", true, true, false, false)
  6335. if err != nil {
  6336. result.AddError(err)
  6337. } else {
  6338. result.Add()
  6339. }
  6340. }
  6341. for i := 0; i < len(adds); i += 1 {
  6342. log.Debugf("add netif %s", adds[i].netif.GetMac())
  6343. // always try reserved pool
  6344. extNic := adds[i].netif
  6345. var strNetIf, strBridge *string
  6346. netif := extNic.GetDevice()
  6347. bridge := extNic.GetBridge()
  6348. if len(netif) > 0 {
  6349. strNetIf = &netif
  6350. }
  6351. if len(bridge) > 0 {
  6352. strBridge = &bridge
  6353. }
  6354. wireId := ""
  6355. extWire := extNic.GetIWire()
  6356. if extWire != nil {
  6357. wire, err := WireManager.FetchWireByExternalId(provider.Id, extWire.GetGlobalId())
  6358. if err != nil {
  6359. result.AddError(err)
  6360. } else {
  6361. wireId = wire.Id
  6362. }
  6363. }
  6364. err = host.addNetif(ctx, userCred, extNic.GetMac(), extNic.GetVlanId(), wireId, extNic.GetIpAddr(), "", 0,
  6365. compute.TNicType(extNic.GetNicType()), int(extNic.GetIndex()),
  6366. extNic.IsLinkUp(), int16(extNic.GetMtu()), false, strNetIf, strBridge, true, true, false, false)
  6367. if err != nil {
  6368. result.AddError(err)
  6369. } else {
  6370. result.Add()
  6371. }
  6372. }
  6373. return result
  6374. }
  6375. // func (manager *SHostManager) GetEsxiAgentHostId(key string) (string, error) {
  6376. // q := HostManager.Query("id")
  6377. // q = q.Equals("host_status", HOST_ONLINE)
  6378. // q = q.Equals("host_type", HOST_TYPE_HYPERVISOR)
  6379. // q = q.IsTrue("enabled")
  6380. //
  6381. // rows, err := q.Rows()
  6382. // if err != nil {
  6383. // return "", err
  6384. // }
  6385. // defer rows.Close()
  6386. //
  6387. // var hostId string
  6388. // hostIds := make([]string, 0)
  6389. // for rows.Next() {
  6390. // err = rows.Scan(&hostId)
  6391. // if err != nil {
  6392. // return "", err
  6393. // }
  6394. // hostIds = append(hostIds, hostId)
  6395. // }
  6396. //
  6397. // ring := hashring.New(hostIds)
  6398. // ret, _ := ring.GetNode(key)
  6399. // return ret, nil
  6400. // }
  6401. //
  6402. // func (manager *SHostManager) GetEsxiAgentHost(key string) (*SHost, error) {
  6403. // hostId, err := manager.GetEsxiAgentHostId(key)
  6404. // if err != nil {
  6405. // return nil, err
  6406. // }
  6407. // return manager.FetchHostById(hostId), nil
  6408. // }
  6409. //
  6410. // func (host *SHost) GetEsxiAgentHost() (*SHost, error) {
  6411. // return HostManager.GetEsxiAgentHost(host.Id)
  6412. // }
  6413. func (hh *SHost) IsBaremetalAgentReady() bool {
  6414. return hh.isAgentReady(api.AgentTypeBaremetal)
  6415. }
  6416. func (hh *SHost) BaremetalSyncRequest(ctx context.Context, method httputils.THttpMethod, url string, headers http.Header, body *jsonutils.JSONDict) (jsonutils.JSONObject, error) {
  6417. return HostManager.BaremetalSyncRequest(ctx, method, url, headers, body, hh.ZoneId)
  6418. }
  6419. func (hm *SHostManager) BaremetalSyncRequest(ctx context.Context, method httputils.THttpMethod, url string, headers http.Header, body *jsonutils.JSONDict, zoneId string) (jsonutils.JSONObject, error) {
  6420. return hm.doAgentRequest(api.AgentTypeBaremetal, ctx, method, url, headers, body, zoneId)
  6421. }
  6422. func (hh *SHost) IsEsxiAgentReady() bool {
  6423. return hh.isAgentReady(api.AgentTypeEsxi)
  6424. }
  6425. func (hh *SHost) EsxiRequest(ctx context.Context, method httputils.THttpMethod, url string, headers http.Header, body *jsonutils.JSONDict) (jsonutils.JSONObject, error) {
  6426. return HostManager.doAgentRequest(api.AgentTypeEsxi, ctx, method, url, headers, body, hh.ZoneId)
  6427. }
  6428. func (hh *SHost) GetAgent(at api.TAgentType) *SBaremetalagent {
  6429. return HostManager.GetAgent(at, hh.ZoneId)
  6430. }
  6431. func (hm *SHostManager) GetAgent(at api.TAgentType, zoneId string) *SBaremetalagent {
  6432. agent := BaremetalagentManager.GetAgent(at, zoneId)
  6433. if agent == nil {
  6434. agent = BaremetalagentManager.GetAgent(at, "")
  6435. }
  6436. return agent
  6437. }
  6438. func (hh *SHost) isAgentReady(agentType api.TAgentType) bool {
  6439. agent := hh.GetAgent(agentType)
  6440. if agent == nil {
  6441. log.Errorf("%s ready: false", agentType)
  6442. return false
  6443. }
  6444. return true
  6445. }
  6446. func (hm *SHostManager) doAgentRequest(agentType api.TAgentType, ctx context.Context, method httputils.THttpMethod, url string, headers http.Header, body *jsonutils.JSONDict, zoneId string) (jsonutils.JSONObject, error) {
  6447. agent := hm.GetAgent(agentType, zoneId)
  6448. if agent == nil {
  6449. return nil, fmt.Errorf("no valid %s", agentType)
  6450. }
  6451. serviceUrl := agent.ManagerUri
  6452. if url[0] != '/' && serviceUrl[len(serviceUrl)-1] != '/' {
  6453. serviceUrl += "/"
  6454. }
  6455. url = serviceUrl + url
  6456. _, data, err := httputils.JSONRequest(httputils.GetDefaultClient(), ctx, method, url, headers, body, false)
  6457. return data, err
  6458. }
  6459. func (manager *SHostManager) GetHostByIp(managerId, hostType, hostIp string) (*SHost, error) {
  6460. q := manager.Query()
  6461. q = q.Equals("access_ip", hostIp).Equals("host_type", hostType)
  6462. if len(managerId) > 0 {
  6463. q = q.Equals("manager_id", managerId)
  6464. }
  6465. ret := []SHost{}
  6466. err := db.FetchModelObjects(manager, q, &ret)
  6467. if err != nil {
  6468. return nil, err
  6469. }
  6470. if len(ret) == 0 {
  6471. return nil, errors.Wrapf(cloudprovider.ErrNotFound, "%s %s", hostType, hostIp)
  6472. }
  6473. if len(ret) > 1 {
  6474. return nil, errors.Wrapf(cloudprovider.ErrDuplicateId, "%s %s", hostType, hostIp)
  6475. }
  6476. return &ret[0], nil
  6477. }
  6478. func (hh *SHost) getCloudProviderInfo() SCloudProviderInfo {
  6479. var region *SCloudregion
  6480. zone, _ := hh.GetZone()
  6481. if zone != nil {
  6482. region, _ = zone.GetRegion()
  6483. }
  6484. provider := hh.GetCloudprovider()
  6485. return MakeCloudProviderInfo(region, zone, provider)
  6486. }
  6487. func (hh *SHost) GetShortDesc(ctx context.Context) *jsonutils.JSONDict {
  6488. desc := hh.SEnabledStatusInfrasResourceBase.GetShortDesc(ctx)
  6489. info := hh.getCloudProviderInfo()
  6490. desc.Update(jsonutils.Marshal(&info))
  6491. return desc
  6492. }
  6493. func (hh *SHost) MarkGuestUnknown(ctx context.Context, userCred mcclient.TokenCredential) {
  6494. guests, _ := hh.GetGuests()
  6495. for _, guest := range guests {
  6496. guest.SetStatus(ctx, userCred, api.VM_UNKNOWN, "host offline")
  6497. guest.UpdateQgaStatus(api.QGA_STATUS_UNKNOWN)
  6498. }
  6499. guests2 := hh.GetGuestsBackupOnThisHost()
  6500. for _, guest := range guests2 {
  6501. guest.SetBackupGuestStatus(userCred, api.VM_UNKNOWN, "host offline")
  6502. }
  6503. }
  6504. func (manager *SHostManager) PingDetectionTask(ctx context.Context, userCred mcclient.TokenCredential, isStart bool) {
  6505. deadline := time.Now().Add(-1 * time.Duration(options.Options.HostOfflineMaxSeconds) * time.Second)
  6506. q := manager.Query().Equals("host_status", api.HOST_ONLINE).
  6507. In("host_type", []string{api.HOST_TYPE_HYPERVISOR, api.HOST_TYPE_CONTAINER}).IsNullOrEmpty("manager_id")
  6508. q = q.Filter(sqlchemy.OR(sqlchemy.IsNull(q.Field("last_ping_at")),
  6509. sqlchemy.LT(q.Field("last_ping_at"), deadline)))
  6510. hosts := []SHost{}
  6511. err := db.FetchModelObjects(manager, q, &hosts)
  6512. if err != nil {
  6513. return
  6514. }
  6515. updateHealthStatus := false
  6516. for i := range hosts {
  6517. func() {
  6518. lockman.LockObject(ctx, &hosts[i])
  6519. defer lockman.ReleaseObject(ctx, &hosts[i])
  6520. hosts[i].PerformOffline(ctx, userCred, nil, &api.HostOfflineInput{UpdateHealthStatus: &updateHealthStatus, Reason: fmt.Sprintf("last ping detection at %s", deadline)})
  6521. hosts[i].MarkGuestUnknown(ctx, userCred)
  6522. }()
  6523. }
  6524. }
  6525. func (hh *SHost) IsPrepaidRecycleResource() bool {
  6526. return hh.ResourceType == api.HostResourceTypePrepaidRecycle
  6527. }
  6528. func (host *SHost) PerformSetSchedtag(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
  6529. return PerformSetResourceSchedtag(host, ctx, userCred, query, data)
  6530. }
  6531. func (host *SHost) GetDynamicConditionInput() *jsonutils.JSONDict {
  6532. return jsonutils.Marshal(host).(*jsonutils.JSONDict)
  6533. }
  6534. func (host *SHost) PerformStatus(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.PerformStatusInput) (jsonutils.JSONObject, error) {
  6535. ret, err := host.SEnabledStatusInfrasResourceBase.PerformStatus(ctx, userCred, query, input)
  6536. if err != nil {
  6537. return nil, errors.Wrap(err, "SEnabledStatusInfrasResourceBase.PerformStatus")
  6538. }
  6539. host.ClearSchedDescCache()
  6540. return ret, nil
  6541. }
  6542. func (host *SHost) GetSchedtagJointManager() ISchedtagJointManager {
  6543. return HostschedtagManager
  6544. }
  6545. func (host *SHost) PerformHostExitMaintenance(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
  6546. if !utils.IsInStringArray(host.Status, []string{api.BAREMETAL_MAINTAIN_FAIL, api.BAREMETAL_MAINTAINING}) {
  6547. return nil, httperrors.NewInvalidStatusError("host status %s can't exit maintenance", host.Status)
  6548. }
  6549. err := host.SetStatus(ctx, userCred, api.HOST_STATUS_RUNNING, "exit maintenance")
  6550. if err != nil {
  6551. return nil, err
  6552. }
  6553. logclient.AddSimpleActionLog(host, logclient.ACT_HOST_UNMAINTENANCE, "host unmaintenance", userCred, true)
  6554. return nil, nil
  6555. }
  6556. func (host *SHost) PerformHostMaintenance(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
  6557. if host.HostType != api.HOST_TYPE_HYPERVISOR {
  6558. return nil, httperrors.NewBadRequestError("host type %s can't do host maintenance", host.HostType)
  6559. }
  6560. if host.HostStatus == api.BAREMETAL_START_MAINTAIN {
  6561. return nil, httperrors.NewBadRequestError("unsupport on host status %s", host.HostStatus)
  6562. }
  6563. var preferHostId string
  6564. preferHost, _ := data.GetString("prefer_host")
  6565. if len(preferHost) > 0 {
  6566. iHost, _ := HostManager.FetchByIdOrName(ctx, userCred, preferHost)
  6567. if iHost == nil {
  6568. return nil, httperrors.NewBadRequestError("Host %s not found", preferHost)
  6569. }
  6570. host := iHost.(*SHost)
  6571. preferHostId = host.Id
  6572. err := host.IsAssignable(ctx, userCred)
  6573. if err != nil {
  6574. return nil, errors.Wrap(err, "IsAssignable")
  6575. }
  6576. }
  6577. guests := host.GetKvmGuests()
  6578. for i := 0; i < len(guests); i++ {
  6579. lockman.LockObject(ctx, &guests[i])
  6580. defer lockman.ReleaseObject(ctx, &guests[i])
  6581. guest, err := guests[i].validateForBatchMigrate(ctx, false)
  6582. if err != nil {
  6583. return nil, err
  6584. }
  6585. guests[i] = *guest
  6586. if host.HostStatus == api.HOST_OFFLINE && guests[i].Status != api.VM_UNKNOWN {
  6587. return nil, httperrors.NewBadRequestError("Host %s can't migrate guests %s in status %s",
  6588. host.HostStatus, guests[i].Name, guests[i].Status)
  6589. }
  6590. }
  6591. var hostGuests = []*api.GuestBatchMigrateParams{}
  6592. for i := 0; i < len(guests); i++ {
  6593. bmp := &api.GuestBatchMigrateParams{
  6594. Id: guests[i].Id,
  6595. LiveMigrate: guests[i].Status == api.VM_RUNNING,
  6596. RescueMode: guests[i].Status == api.VM_UNKNOWN,
  6597. OldStatus: guests[i].Status,
  6598. }
  6599. guests[i].SetStatus(ctx, userCred, api.VM_START_MIGRATE, "host maintainence")
  6600. hostGuests = append(hostGuests, bmp)
  6601. }
  6602. kwargs := jsonutils.NewDict()
  6603. kwargs.Set("guests", jsonutils.Marshal(hostGuests))
  6604. kwargs.Set("prefer_host_id", jsonutils.NewString(preferHostId))
  6605. return nil, host.StartMaintainTask(ctx, userCred, kwargs)
  6606. }
  6607. func (host *SHost) autoMigrateOnHostShutdown(ctx context.Context) bool {
  6608. return host.GetMetadata(ctx, api.HOSTMETA_AUTO_MIGRATE_ON_HOST_SHUTDOWN, nil) == "enable"
  6609. }
  6610. func (host *SHost) RemoteHealthStatus(ctx context.Context) string {
  6611. var status = api.HOST_HEALTH_STATUS_UNKNOWN
  6612. userCred := auth.AdminCredential()
  6613. res, err := host.Request(
  6614. ctx, userCred, "GET", "/hosts/health-status",
  6615. mcclient.GetTokenHeaders(userCred), nil,
  6616. )
  6617. if err != nil {
  6618. log.Errorf("failed get remote health status %s", err)
  6619. } else {
  6620. status, _ = res.GetString("status")
  6621. }
  6622. log.Infof("remote health status %s", status)
  6623. return status
  6624. }
  6625. func (host *SHost) GetHostnameByName() string {
  6626. hostname := host.Name
  6627. accessIp := strings.Replace(host.AccessIp, ".", "-", -1)
  6628. if strings.HasSuffix(host.Name, "-"+accessIp) {
  6629. hostname = hostname[0 : len(hostname)-len(accessIp)-1]
  6630. }
  6631. return hostname
  6632. }
  6633. func (host *SHost) OnHostDown(ctx context.Context, userCred mcclient.TokenCredential) {
  6634. log.Errorf("watched host down %s, status %s", host.Name, host.HostStatus)
  6635. hostHealthChecker.UnwatchHost(ctx, host.GetHostnameByName())
  6636. if host.HostStatus == api.HOST_OFFLINE && !host.EnableHealthCheck &&
  6637. !host.autoMigrateOnHostShutdown(ctx) {
  6638. // hostagent requested offline, and not enable auto migrate on host shutdown
  6639. log.Infof("host not need auto migrate on host shutdown")
  6640. return
  6641. }
  6642. hostname := host.Name
  6643. if host.HostStatus == api.HOST_OFFLINE {
  6644. // host has been marked offline, check host status in k8s
  6645. coreCli, err := tokens.GetCoreClient()
  6646. if err != nil {
  6647. log.Errorf("failed get k8s client %s", err)
  6648. return
  6649. }
  6650. hostname = host.GetHostnameByName()
  6651. node, err := coreCli.Nodes().Get(context.TODO(), hostname, metav1.GetOptions{})
  6652. if err != nil {
  6653. log.Errorf("failed get node %s info %s", hostname, err)
  6654. return
  6655. }
  6656. // check node status is ready
  6657. if length := len(node.Status.Conditions); length > 0 {
  6658. if node.Status.Conditions[length-1].Type == v1.NodeReady &&
  6659. node.Status.Conditions[length-1].Status == v1.ConditionTrue {
  6660. log.Infof("node %s status ready, no need entry rescue", hostname)
  6661. return
  6662. }
  6663. }
  6664. }
  6665. log.Errorf("host %s down, try rescue guests", hostname)
  6666. if _, err := host.SaveCleanUpdates(func() error {
  6667. host.EnableHealthCheck = false
  6668. host.HostStatus = api.HOST_OFFLINE
  6669. return nil
  6670. }); err != nil {
  6671. log.Errorf("update host %s failed %s", host.Id, err)
  6672. }
  6673. data := jsonutils.NewDict()
  6674. data.Set("reason", jsonutils.NewString("host down"))
  6675. db.OpsLog.LogEvent(host, db.ACT_HOST_DOWN, data, userCred)
  6676. logclient.AddActionLogWithContext(ctx, host, logclient.ACT_OFFLINE, data, userCred, false)
  6677. notifyclient.SystemExceptionNotify(ctx, napi.ActionHostDown, HostManager.Keyword(), data)
  6678. host.SyncCleanSchedDescCache()
  6679. host.switchWithBackup(ctx, userCred)
  6680. host.migrateOnHostDown(ctx, userCred)
  6681. }
  6682. func (host *SHost) switchWithBackup(ctx context.Context, userCred mcclient.TokenCredential) {
  6683. guests := host.GetGuestsMasterOnThisHost()
  6684. for i := 0; i < len(guests); i++ {
  6685. data := jsonutils.NewDict()
  6686. _, err := guests[i].PerformSwitchToBackup(ctx, userCred, nil, data)
  6687. if err != nil {
  6688. db.OpsLog.LogEvent(
  6689. &guests[i], db.ACT_SWITCH_FAILED, fmt.Sprintf("PerformSwitchToBackup on host down: %s", err), userCred,
  6690. )
  6691. logclient.AddSimpleActionLog(
  6692. &guests[i], logclient.ACT_SWITCH_TO_BACKUP,
  6693. fmt.Sprintf("PerformSwitchToBackup on host down: %s", err), userCred, false,
  6694. )
  6695. }
  6696. }
  6697. }
  6698. func (host *SHost) migrateOnHostDown(ctx context.Context, userCred mcclient.TokenCredential) {
  6699. if host.GetMetadata(ctx, api.HOSTMETA_AUTO_MIGRATE_ON_HOST_DOWN, nil) == "enable" {
  6700. if err := host.MigrateSharedStorageServers(ctx, userCred); err != nil {
  6701. db.OpsLog.LogEvent(host, db.ACT_HOST_DOWN, fmt.Sprintf("migrate servers failed %s", err), userCred)
  6702. }
  6703. }
  6704. }
  6705. func (host *SHost) MigrateSharedStorageServers(ctx context.Context, userCred mcclient.TokenCredential) error {
  6706. guests, err := host.GetGuests()
  6707. if err != nil {
  6708. return errors.Wrapf(err, "host %s(%s) get guests", host.Name, host.Id)
  6709. }
  6710. migGuests := []*SGuest{}
  6711. hostGuests := []*api.GuestBatchMigrateParams{}
  6712. for i := 0; i < len(guests); i++ {
  6713. if guests[i].isNotRunningStatus(guests[i].Status) {
  6714. // skip not running guests
  6715. continue
  6716. }
  6717. lockman.LockObject(ctx, &guests[i])
  6718. defer lockman.ReleaseObject(ctx, &guests[i])
  6719. _, err := guests[i].validateForBatchMigrate(ctx, true)
  6720. if err != nil {
  6721. continue
  6722. } else {
  6723. bmp := &api.GuestBatchMigrateParams{
  6724. Id: guests[i].Id,
  6725. LiveMigrate: false,
  6726. RescueMode: true,
  6727. OldStatus: guests[i].Status,
  6728. }
  6729. guests[i].SetStatus(ctx, userCred, api.VM_START_MIGRATE, "host down")
  6730. hostGuests = append(hostGuests, bmp)
  6731. migGuests = append(migGuests, &guests[i])
  6732. }
  6733. }
  6734. kwargs := jsonutils.NewDict()
  6735. kwargs.Set("guests", jsonutils.Marshal(hostGuests))
  6736. db.OpsLog.LogEvent(host, db.ACT_HOST_DOWN_AUTO_MIGRATE, kwargs, userCred)
  6737. logclient.AddActionLogWithContext(ctx, host, logclient.ACT_HOST_DOWN_AUTO_MIGRATE, kwargs, userCred, true)
  6738. notifyclient.SystemExceptionNotify(ctx, napi.ActionHostDownAutoMigrate, HostManager.Keyword(), kwargs)
  6739. return GuestManager.StartHostGuestsMigrateTask(ctx, userCred, migGuests, kwargs, "")
  6740. }
  6741. func (host *SHost) SetStatus(ctx context.Context, userCred mcclient.TokenCredential, status string, reason string) error {
  6742. err := host.SEnabledStatusInfrasResourceBase.SetStatus(ctx, userCred, status, reason)
  6743. if err != nil {
  6744. return err
  6745. }
  6746. host.ClearSchedDescCache()
  6747. return nil
  6748. }
  6749. func (host *SHost) StartMaintainTask(ctx context.Context, userCred mcclient.TokenCredential, data *jsonutils.JSONDict) error {
  6750. host.SetStatus(ctx, userCred, api.BAREMETAL_START_MAINTAIN, "start maintenance")
  6751. if task, err := taskman.TaskManager.NewTask(ctx, "HostMaintainTask", host, userCred, data, "", "", nil); err != nil {
  6752. log.Errorln(err)
  6753. return err
  6754. } else {
  6755. task.ScheduleRun(nil)
  6756. }
  6757. return nil
  6758. }
  6759. func (host *SHost) IsMaintaining() bool {
  6760. return utils.IsInStringArray(host.Status, []string{api.BAREMETAL_START_MAINTAIN, api.BAREMETAL_MAINTAINING, api.BAREMETAL_MAINTAIN_FAIL})
  6761. }
  6762. // InstanceGroups returns the enabled group of guest in host and their frequency of occurrence
  6763. func (host *SHost) InstanceGroups() ([]SGroup, map[string]int, error) {
  6764. q := GuestManager.Query("id")
  6765. guestQ := q.Filter(sqlchemy.OR(sqlchemy.Equals(q.Field("host_id"), host.Id),
  6766. sqlchemy.Equals(q.Field("backup_host_id"), host.Id))).SubQuery()
  6767. groupQ := GroupguestManager.Query().SubQuery()
  6768. q = groupQ.Query().Join(guestQ, sqlchemy.Equals(guestQ.Field("id"), groupQ.Field("guest_id")))
  6769. groupguests := make([]SGroupguest, 0, 1)
  6770. err := db.FetchModelObjects(GroupguestManager, q, &groupguests)
  6771. if err != nil {
  6772. return nil, nil, err
  6773. }
  6774. groupIds, groupSet := make([]string, 0, len(groupguests)), make(map[string]int)
  6775. for i := range groupguests {
  6776. id := groupguests[i].GroupId
  6777. if _, ok := groupSet[id]; !ok {
  6778. groupIds = append(groupIds, id)
  6779. groupSet[id] = 1
  6780. continue
  6781. }
  6782. groupSet[id] += 1
  6783. }
  6784. if len(groupIds) == 0 {
  6785. return []SGroup{}, make(map[string]int), nil
  6786. }
  6787. groups := make([]SGroup, 0, len(groupIds))
  6788. q = GroupManager.Query().In("id", groupIds).IsTrue("enabled")
  6789. err = db.FetchModelObjects(GroupManager, q, &groups)
  6790. if err != nil {
  6791. return nil, nil, err
  6792. }
  6793. retSet := make(map[string]int)
  6794. for i := range groups {
  6795. retSet[groups[i].GetId()] = groupSet[groups[i].GetId()]
  6796. }
  6797. return groups, retSet, nil
  6798. }
  6799. func (host *SHost) setIpmiIp(userCred mcclient.TokenCredential, ipAddr string) error {
  6800. if host.IpmiIp == ipAddr {
  6801. return nil
  6802. }
  6803. diff, err := db.Update(host, func() error {
  6804. host.IpmiIp = ipAddr
  6805. return nil
  6806. })
  6807. if err != nil {
  6808. return errors.Wrap(err, "db.Update")
  6809. }
  6810. db.OpsLog.LogEvent(host, db.ACT_UPDATE, diff, userCred)
  6811. return nil
  6812. }
  6813. func (host *SHost) setAccessIp(userCred mcclient.TokenCredential, ipAddr string) error {
  6814. if host.AccessIp == ipAddr {
  6815. return nil
  6816. }
  6817. diff, err := db.Update(host, func() error {
  6818. host.AccessIp = ipAddr
  6819. return nil
  6820. })
  6821. if err != nil {
  6822. return errors.Wrap(err, "db.Update")
  6823. }
  6824. db.OpsLog.LogEvent(host, db.ACT_UPDATE, diff, userCred)
  6825. return nil
  6826. }
  6827. func (host *SHost) setAccessMac(userCred mcclient.TokenCredential, mac string) error {
  6828. mac = netutils.FormatMacAddr(mac)
  6829. if host.AccessMac == mac {
  6830. return nil
  6831. }
  6832. diff, err := db.Update(host, func() error {
  6833. host.AccessMac = mac
  6834. return nil
  6835. })
  6836. if err != nil {
  6837. return errors.Wrap(err, "db.Update")
  6838. }
  6839. db.OpsLog.LogEvent(host, db.ACT_UPDATE, diff, userCred)
  6840. return nil
  6841. }
  6842. func (host *SHost) GetIpmiInfo() (types.SIPMIInfo, error) {
  6843. info := types.SIPMIInfo{}
  6844. if host.IpmiInfo != nil {
  6845. err := host.IpmiInfo.Unmarshal(&info)
  6846. if err != nil {
  6847. return info, errors.Wrap(err, "host.IpmiInfo.Unmarshal")
  6848. }
  6849. }
  6850. return info, nil
  6851. }
  6852. func (host *SHost) GetNics() []*types.SNic {
  6853. netifs := host.GetAllNetInterfaces()
  6854. nicInfos := []*types.SNic{}
  6855. if netifs != nil && len(netifs) > 0 {
  6856. for i := 0; i < len(netifs); i += 1 {
  6857. nicInfos = append(nicInfos, netifs[i].getBaremetalJsonDesc())
  6858. }
  6859. }
  6860. return nicInfos
  6861. }
  6862. func (host *SHost) GetUEFIInfo() (*types.EFIBootMgrInfo, error) {
  6863. if host.UefiInfo == nil {
  6864. return nil, nil
  6865. }
  6866. info := new(types.EFIBootMgrInfo)
  6867. if err := host.UefiInfo.Unmarshal(info); err != nil {
  6868. return nil, errors.Wrap(err, "host.UefiInfo.Unmarshal")
  6869. }
  6870. return info, nil
  6871. }
  6872. func (hh *SHost) GetDetailsJnlp(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) (jsonutils.JSONObject, error) {
  6873. url := fmt.Sprintf("/baremetals/%s/jnlp", hh.Id)
  6874. header := mcclient.GetTokenHeaders(userCred)
  6875. resp, err := hh.BaremetalSyncRequest(ctx, "POST", url, header, nil)
  6876. if err != nil {
  6877. return nil, errors.Wrap(err, "BaremetalSyncRequest")
  6878. }
  6879. return resp, nil
  6880. }
  6881. func (hh *SHost) PerformInsertIso(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
  6882. if utils.IsInStringArray(hh.Status, []string{api.BAREMETAL_READY, api.BAREMETAL_RUNNING}) {
  6883. imageStr, err := data.GetString("image")
  6884. image, err := CachedimageManager.getImageInfo(ctx, userCred, imageStr, false)
  6885. if err != nil {
  6886. if err == sql.ErrNoRows {
  6887. return nil, httperrors.NewResourceNotFoundError2("image", imageStr)
  6888. } else {
  6889. return nil, httperrors.NewGeneralError(err)
  6890. }
  6891. }
  6892. if image.Status != cloudprovider.IMAGE_STATUS_ACTIVE {
  6893. return nil, httperrors.NewInvalidStatusError("Image status is not active")
  6894. }
  6895. boot := jsonutils.QueryBoolean(data, "boot", false)
  6896. return nil, hh.StartInsertIsoTask(ctx, userCred, image.Id, boot, "")
  6897. }
  6898. return nil, httperrors.NewInvalidStatusError("Cannot do insert-iso in status %s", hh.Status)
  6899. }
  6900. func (hh *SHost) StartInsertIsoTask(ctx context.Context, userCred mcclient.TokenCredential, imageId string, boot bool, parentTaskId string) error {
  6901. data := jsonutils.NewDict()
  6902. data.Add(jsonutils.NewString(imageId), "image_id")
  6903. if boot {
  6904. data.Add(jsonutils.JSONTrue, "boot")
  6905. }
  6906. data.Add(jsonutils.NewString(api.BAREMETAL_CDROM_ACTION_INSERT), "action")
  6907. hh.SetStatus(ctx, userCred, api.BAREMETAL_START_INSERT_ISO, "start insert iso task")
  6908. if task, err := taskman.TaskManager.NewTask(ctx, "BaremetalCdromTask", hh, userCred, data, parentTaskId, "", nil); err != nil {
  6909. log.Errorln(err)
  6910. return err
  6911. } else {
  6912. task.ScheduleRun(nil)
  6913. return nil
  6914. }
  6915. }
  6916. func (hh *SHost) PerformEjectIso(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
  6917. if utils.IsInStringArray(hh.Status, []string{api.BAREMETAL_READY, api.BAREMETAL_RUNNING}) {
  6918. return nil, hh.StartEjectIsoTask(ctx, userCred, "")
  6919. }
  6920. return nil, httperrors.NewInvalidStatusError("Cannot do eject-iso in status %s", hh.Status)
  6921. }
  6922. func (hh *SHost) StartEjectIsoTask(ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string) error {
  6923. data := jsonutils.NewDict()
  6924. data.Add(jsonutils.NewString(api.BAREMETAL_CDROM_ACTION_EJECT), "action")
  6925. hh.SetStatus(ctx, userCred, api.BAREMETAL_START_EJECT_ISO, "start eject iso task")
  6926. if task, err := taskman.TaskManager.NewTask(ctx, "BaremetalCdromTask", hh, userCred, data, parentTaskId, "", nil); err != nil {
  6927. log.Errorln(err)
  6928. return err
  6929. } else {
  6930. task.ScheduleRun(nil)
  6931. return nil
  6932. }
  6933. }
  6934. func (hh *SHost) PerformSyncConfig(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
  6935. if hh.HostType != api.HOST_TYPE_BAREMETAL {
  6936. return nil, httperrors.NewBadRequestError("Cannot sync config a non-baremetal host")
  6937. }
  6938. hh.SetStatus(ctx, userCred, api.BAREMETAL_SYNCING_STATUS, "")
  6939. return nil, hh.StartSyncConfig(ctx, userCred, "")
  6940. }
  6941. func (hh *SHost) StartSyncConfig(ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string) error {
  6942. return hh.startSyncConfig(ctx, userCred, parentTaskId, false)
  6943. }
  6944. func (hh *SHost) startSyncConfig(ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string, noStatus bool) error {
  6945. data := jsonutils.NewDict()
  6946. data.Add(jsonutils.NewBool(noStatus), "not_sync_status")
  6947. task, err := taskman.TaskManager.NewTask(ctx, "BaremetalSyncConfigTask", hh, userCred, data, parentTaskId, "", nil)
  6948. if err != nil {
  6949. return err
  6950. }
  6951. return task.ScheduleRun(nil)
  6952. }
  6953. func (model *SHost) CustomizeCreate(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data jsonutils.JSONObject) error {
  6954. // make host default public
  6955. return model.SEnabledStatusInfrasResourceBase.CustomizeCreate(ctx, userCred, ownerId, query, data)
  6956. }
  6957. func (host *SHost) PerformChangeOwner(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.PerformChangeDomainOwnerInput) (jsonutils.JSONObject, error) {
  6958. ret, err := host.SEnabledStatusInfrasResourceBase.PerformChangeOwner(ctx, userCred, query, input)
  6959. if err != nil {
  6960. return nil, errors.Wrap(err, "SEnabledStatusInfrasResourceBase.PerformChangeOwner")
  6961. }
  6962. localStorages := host._getAttachedStorages(tristate.None, tristate.None, api.HOST_STORAGE_LOCAL_TYPES)
  6963. for i := range localStorages {
  6964. _, err := localStorages[i].performChangeOwnerInternal(ctx, userCred, query, input)
  6965. if err != nil {
  6966. return nil, errors.Wrap(err, "local storage change owner")
  6967. }
  6968. }
  6969. err = host.StartSyncTask(ctx, userCred, "")
  6970. if err != nil {
  6971. return nil, errors.Wrap(err, "PerformChangeOwner StartSyncTask err")
  6972. }
  6973. return ret, nil
  6974. }
  6975. func (hh *SHost) StartSyncTask(ctx context.Context, userCred mcclient.TokenCredential, parentTaskId string) error {
  6976. if task, err := taskman.TaskManager.NewTask(ctx, "HostSyncTask", hh, userCred, jsonutils.NewDict(), parentTaskId, "",
  6977. nil); err != nil {
  6978. log.Errorln(err)
  6979. return err
  6980. } else {
  6981. task.ScheduleRun(nil)
  6982. }
  6983. return nil
  6984. }
  6985. func (host *SHost) GetChangeOwnerRequiredDomainIds() []string {
  6986. requires := stringutils2.SSortedStrings{}
  6987. guests, _ := host.GetGuests()
  6988. for i := range guests {
  6989. requires = stringutils2.Append(requires, guests[i].DomainId)
  6990. }
  6991. return requires
  6992. }
  6993. func GetHostQuotaKeysFromCreateInput(owner mcclient.IIdentityProvider, input api.HostCreateInput) quotas.SDomainRegionalCloudResourceKeys {
  6994. ownerId := &db.SOwnerId{DomainId: owner.GetProjectDomainId()}
  6995. var zone *SZone
  6996. if len(input.ZoneId) > 0 {
  6997. zone = ZoneManager.FetchZoneById(input.ZoneId)
  6998. }
  6999. zoneKeys := fetchZonalQuotaKeys(rbacscope.ScopeDomain, ownerId, zone, nil)
  7000. keys := quotas.SDomainRegionalCloudResourceKeys{}
  7001. keys.SBaseDomainQuotaKeys = zoneKeys.SBaseDomainQuotaKeys
  7002. keys.SRegionalBaseKeys = zoneKeys.SRegionalBaseKeys
  7003. return keys
  7004. }
  7005. func (model *SHost) GetQuotaKeys() quotas.SDomainRegionalCloudResourceKeys {
  7006. zone, _ := model.GetZone()
  7007. manager := model.GetCloudprovider()
  7008. ownerId := model.GetOwnerId()
  7009. zoneKeys := fetchZonalQuotaKeys(rbacscope.ScopeDomain, ownerId, zone, manager)
  7010. keys := quotas.SDomainRegionalCloudResourceKeys{}
  7011. keys.SBaseDomainQuotaKeys = zoneKeys.SBaseDomainQuotaKeys
  7012. keys.SRegionalBaseKeys = zoneKeys.SRegionalBaseKeys
  7013. keys.SCloudResourceBaseKeys = zoneKeys.SCloudResourceBaseKeys
  7014. return keys
  7015. }
  7016. func (host *SHost) GetUsages() []db.IUsage {
  7017. if host.Deleted {
  7018. return nil
  7019. }
  7020. usage := SInfrasQuota{Host: 1}
  7021. keys := host.GetQuotaKeys()
  7022. usage.SetKeys(keys)
  7023. return []db.IUsage{
  7024. &usage,
  7025. }
  7026. }
  7027. func (host *SHost) PerformPublic(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.PerformPublicDomainInput) (jsonutils.JSONObject, error) {
  7028. // perform public for all connected local storage
  7029. storages := host._getAttachedStorages(tristate.None, tristate.None, api.HOST_STORAGE_LOCAL_TYPES)
  7030. for i := range storages {
  7031. _, err := storages[i].performPublicInternal(ctx, userCred, query, input)
  7032. if err != nil {
  7033. return nil, errors.Wrap(err, "storage.PerformPublic")
  7034. }
  7035. }
  7036. return host.SEnabledStatusInfrasResourceBase.PerformPublic(ctx, userCred, query, input)
  7037. }
  7038. func (host *SHost) PerformPrivate(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input apis.PerformPrivateInput) (jsonutils.JSONObject, error) {
  7039. // perform private for all connected local storage
  7040. storages := host._getAttachedStorages(tristate.None, tristate.None, api.HOST_STORAGE_LOCAL_TYPES)
  7041. for i := range storages {
  7042. _, err := storages[i].performPrivateInternal(ctx, userCred, query, input)
  7043. if err != nil {
  7044. return nil, errors.Wrap(err, "storage.PerformPrivate")
  7045. }
  7046. }
  7047. return host.SEnabledStatusInfrasResourceBase.PerformPrivate(ctx, userCred, query, input)
  7048. }
  7049. func (host *SHost) PerformSetReservedResourceForIsolatedDevice(
  7050. ctx context.Context, userCred mcclient.TokenCredential,
  7051. query jsonutils.JSONObject, input api.IsolatedDeviceReservedResourceInput,
  7052. ) (jsonutils.JSONObject, error) {
  7053. if input.ReservedCpu != nil && *input.ReservedCpu < 0 {
  7054. return nil, httperrors.NewInputParameterError("reserved cpu must >= 0")
  7055. }
  7056. if input.ReservedMemory != nil && *input.ReservedMemory < 0 {
  7057. return nil, httperrors.NewInputParameterError("reserved memory must >= 0")
  7058. }
  7059. if input.ReservedStorage != nil && *input.ReservedStorage < 0 {
  7060. return nil, httperrors.NewInputParameterError("reserved storage must >= 0")
  7061. }
  7062. devs := IsolatedDeviceManager.FindByHost(host.Id)
  7063. if len(devs) == 0 {
  7064. return nil, nil
  7065. }
  7066. if input.ReservedCpu != nil && host.GetCpuCount() < *input.ReservedCpu*len(devs) {
  7067. return nil, httperrors.NewBadRequestError(
  7068. "host %s can't reserve %d cpu for each isolated device, not enough", host.Name, *input.ReservedCpu)
  7069. }
  7070. if input.ReservedMemory != nil && host.GetMemSize() < *input.ReservedMemory*len(devs) {
  7071. return nil, httperrors.NewBadRequestError(
  7072. "host %s can't reserve %dM memory for each isolated device, not enough", host.Name, *input.ReservedMemory)
  7073. }
  7074. caps := host.GetAttachedLocalStorageCapacity()
  7075. if input.ReservedStorage != nil && caps.Capacity < int64(*input.ReservedStorage*len(devs)) {
  7076. return nil, httperrors.NewBadRequestError(
  7077. "host %s can't reserve %dM storage for each isolated device, not enough", host.Name, input.ReservedStorage)
  7078. }
  7079. defer func() {
  7080. go host.ClearSchedDescCache()
  7081. }()
  7082. for i := 0; i < len(devs); i++ {
  7083. _, err := db.Update(&devs[i], func() error {
  7084. if input.ReservedCpu != nil {
  7085. devs[i].ReservedCpu = *input.ReservedCpu
  7086. }
  7087. if input.ReservedMemory != nil {
  7088. devs[i].ReservedMemory = *input.ReservedMemory
  7089. }
  7090. if input.ReservedStorage != nil {
  7091. devs[i].ReservedStorage = *input.ReservedStorage
  7092. }
  7093. return nil
  7094. })
  7095. if err != nil {
  7096. return nil, errors.Wrap(err, "update isolated device")
  7097. }
  7098. }
  7099. logclient.AddSimpleActionLog(host, logclient.ACT_SET_RESERVE_RESOURCE_FOR_ISOLATED_DEVICES, nil, userCred, true)
  7100. return nil, nil
  7101. }
  7102. func (manager *SHostManager) ListItemExportKeys(ctx context.Context,
  7103. q *sqlchemy.SQuery,
  7104. userCred mcclient.TokenCredential,
  7105. keys stringutils2.SSortedStrings,
  7106. ) (*sqlchemy.SQuery, error) {
  7107. q, err := manager.SEnabledStatusInfrasResourceBaseManager.ListItemExportKeys(ctx, q, userCred, keys)
  7108. if err != nil {
  7109. return nil, errors.Wrap(err, "SEnabledStatusInfrasResourceBaseManager.ListItemExportKeys")
  7110. }
  7111. if keys.ContainsAny(manager.SManagedResourceBaseManager.GetExportKeys()...) {
  7112. q, err = manager.SManagedResourceBaseManager.ListItemExportKeys(ctx, q, userCred, keys)
  7113. if err != nil {
  7114. return nil, errors.Wrap(err, "SManagedResourceBaseManager.ListItemExportKeys")
  7115. }
  7116. }
  7117. if keys.ContainsAny(manager.SZoneResourceBaseManager.GetExportKeys()...) {
  7118. q, err = manager.SZoneResourceBaseManager.ListItemExportKeys(ctx, q, userCred, keys)
  7119. if err != nil {
  7120. return nil, errors.Wrap(err, "SZoneResourceBaseManager.ListItemExportKeys")
  7121. }
  7122. }
  7123. return q, nil
  7124. }
  7125. func (manager *SHostManager) FetchHostByExtId(extid string) *SHost {
  7126. host := SHost{}
  7127. host.SetModelManager(manager, &host)
  7128. err := manager.Query().Equals("external_id", extid).First(&host)
  7129. if err != nil {
  7130. log.Errorf("fetchHostByExtId fail %s", err)
  7131. return nil
  7132. } else {
  7133. return &host
  7134. }
  7135. }
  7136. func (host *SHost) IsAssignable(ctx context.Context, userCred mcclient.TokenCredential) error {
  7137. if db.IsAdminAllowPerform(ctx, userCred, host, "assign-host") {
  7138. return nil
  7139. } else if db.IsDomainAllowPerform(ctx, userCred, host, "assign-host") &&
  7140. (userCred.GetProjectDomainId() == host.DomainId ||
  7141. host.PublicScope == string(rbacscope.ScopeSystem) ||
  7142. (host.PublicScope == string(rbacscope.ScopeDomain) && utils.IsInStringArray(userCred.GetProjectDomainId(), host.GetSharedDomains()))) {
  7143. return nil
  7144. } else {
  7145. return httperrors.NewNotSufficientPrivilegeError("Only system admin can assign host")
  7146. }
  7147. }
  7148. func (manager *SHostManager) initHostname() error {
  7149. hosts := []SHost{}
  7150. q := manager.Query().IsNullOrEmpty("hostname")
  7151. err := db.FetchModelObjects(manager, q, &hosts)
  7152. if err != nil {
  7153. return errors.Wrapf(err, "db.FetchModelObjects")
  7154. }
  7155. for i := range hosts {
  7156. db.Update(&hosts[i], func() error {
  7157. hostname, _ := manager.SHostnameResourceBaseManager.ValidateHostname(
  7158. hosts[i].Hostname,
  7159. "",
  7160. api.HostnameInput{
  7161. Hostname: hosts[i].Name,
  7162. },
  7163. )
  7164. hosts[i].Hostname = hostname.Hostname
  7165. return nil
  7166. })
  7167. }
  7168. return nil
  7169. }
  7170. func (manager *SHostManager) initOvnMappedIp6Addr() error {
  7171. hosts := []SHost{}
  7172. q := manager.Query().IsNotEmpty("ovn_version")
  7173. q = q.Filter(
  7174. sqlchemy.OR(
  7175. sqlchemy.IsNullOrEmpty(q.Field("ovn_mapped_ip6_addr")),
  7176. sqlchemy.IsNullOrEmpty(q.Field("ovn_mapped_ip_addr")),
  7177. ),
  7178. )
  7179. err := db.FetchModelObjects(manager, q, &hosts)
  7180. if err != nil {
  7181. return errors.Wrapf(err, "db.FetchModelObjects")
  7182. }
  7183. for i := range hosts {
  7184. hh := &hosts[i]
  7185. var v4addr string
  7186. if hh.OvnMappedIp6Addr == "" {
  7187. addr, err := HostManager.allocOvnMappedIpAddr(context.Background())
  7188. if err != nil {
  7189. return errors.Wrapf(err, "host %s(%s): alloc vpc mapped addr", hh.Name, hh.Id)
  7190. }
  7191. v4addr = addr
  7192. } else {
  7193. v4addr = hh.OvnMappedIpAddr
  7194. }
  7195. if _, err := db.Update(hh, func() error {
  7196. hh.OvnMappedIpAddr = v4addr
  7197. hh.OvnMappedIp6Addr = api.GenVpcMappedIP6(v4addr)
  7198. return nil
  7199. }); err != nil {
  7200. return errors.Wrapf(err, "host %s(%s): db update vpc mapped addr", hh.Name, hh.Id)
  7201. }
  7202. }
  7203. return nil
  7204. }
  7205. func (manager *SHostManager) InitializeData() error {
  7206. var err error
  7207. err = manager.initHostname()
  7208. if err != nil {
  7209. return errors.Wrapf(err, "initHostname")
  7210. }
  7211. err = manager.initOvnMappedIp6Addr()
  7212. if err != nil {
  7213. return errors.Wrapf(err, "initOvnMappedIp6Addr")
  7214. }
  7215. return nil
  7216. }
  7217. func (hh *SHost) PerformProbeIsolatedDevices(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
  7218. driver, err := hh.GetHostDriver()
  7219. if err != nil {
  7220. return nil, errors.Wrapf(err, "GetHostDriver")
  7221. }
  7222. return driver.RequestProbeIsolatedDevices(ctx, userCred, hh, data)
  7223. }
  7224. func (hh *SHost) PerformSyncIsolatedDevices(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
  7225. devs, err := IsolatedDeviceManager.GetAllDevsOnHost(hh.Id)
  7226. if err != nil {
  7227. return nil, err
  7228. }
  7229. reqDevs, err := data.GetArray("isolated_devices")
  7230. if err != nil {
  7231. return nil, httperrors.NewMissingParameterError("isolated_devices")
  7232. }
  7233. retDevs := jsonutils.NewArray()
  7234. foundDevIndex := map[int]struct{}{}
  7235. eg := errgroup.Group{}
  7236. wg := sync.Mutex{}
  7237. for i := range devs {
  7238. foundDev := false
  7239. dev := &devs[i]
  7240. for j := range reqDevs {
  7241. venderDeviceId, _ := reqDevs[j].GetString("vendor_device_id")
  7242. devAddr, _ := reqDevs[j].GetString("addr")
  7243. mdevId, _ := reqDevs[j].GetString("mdev_id")
  7244. if dev.VendorDeviceId == venderDeviceId && dev.Addr == devAddr && dev.MdevId == mdevId {
  7245. eg.Go(func() error {
  7246. // update isolated device
  7247. log.Infof("dev %s %s do update", dev.DevType, dev.Addr)
  7248. devRet, err := db.DoUpdate(IsolatedDeviceManager, dev, ctx, userCred, jsonutils.NewDict(), reqDevs[j])
  7249. if err != nil {
  7250. return err
  7251. }
  7252. wg.Lock()
  7253. retDevs.Add(devRet)
  7254. wg.Unlock()
  7255. return nil
  7256. })
  7257. foundDevIndex[j] = struct{}{}
  7258. foundDev = true
  7259. break
  7260. }
  7261. }
  7262. if !foundDev {
  7263. eg.Go(func() error {
  7264. // detach isolated device
  7265. params := jsonutils.NewDict()
  7266. params.Set("purge", jsonutils.JSONTrue)
  7267. _, err := dev.PerformPurge(ctx, userCred, nil, params)
  7268. if err != nil {
  7269. return err
  7270. }
  7271. return err
  7272. })
  7273. }
  7274. }
  7275. if err = eg.Wait(); err != nil {
  7276. return nil, err
  7277. }
  7278. for i := range reqDevs {
  7279. if _, ok := foundDevIndex[i]; ok {
  7280. continue
  7281. }
  7282. // create isolated device
  7283. dev, err := db.DoCreate(IsolatedDeviceManager, ctx, userCred, nil, reqDevs[i], userCred)
  7284. if err != nil {
  7285. return nil, err
  7286. }
  7287. devRet, err := db.GetItemDetails(IsolatedDeviceManager, dev, ctx, userCred)
  7288. if err != nil {
  7289. return nil, err
  7290. }
  7291. retDevs.Add(devRet)
  7292. }
  7293. res := jsonutils.NewDict()
  7294. res.Set("isolated_devices", retDevs)
  7295. return res, nil
  7296. }
  7297. func (hh *SHost) GetPinnedCpusetCores(ctx context.Context, userCred mcclient.TokenCredential, excludeGuestIds []string) (*cpuset.CPUSet, error) {
  7298. gsts, err := hh.GetGuests()
  7299. if err != nil {
  7300. return nil, errors.Wrap(err, "Get all guests")
  7301. }
  7302. ret := cpuset.NewBuilder()
  7303. for _, gst := range gsts {
  7304. if utils.IsInStringArray(gst.Id, excludeGuestIds) {
  7305. continue
  7306. }
  7307. pinned, err := gst.getPinnedCpusetCores(ctx, userCred)
  7308. if err != nil {
  7309. return nil, errors.Wrapf(err, "get guest %s pinned cpuset cores", gst.GetName())
  7310. }
  7311. ret.Add(pinned...)
  7312. }
  7313. resCpuset := ret.Result()
  7314. if resCpuset.Size() == 0 {
  7315. return nil, nil
  7316. }
  7317. return &resCpuset, nil
  7318. }
  7319. func (hh *SHost) GetReservedCpus() (*cpuset.CPUSet, error) {
  7320. reservedCpusStr := hh.GetMetadata(context.Background(), api.HOSTMETA_RESERVED_CPUS_INFO, nil)
  7321. if reservedCpusStr != "" {
  7322. reservedCpusJson, err := jsonutils.ParseString(reservedCpusStr)
  7323. if err != nil {
  7324. return nil, errors.Wrap(err, "parse reserved cpus info failed")
  7325. }
  7326. reservedCpusInfo := api.HostReserveCpusInput{}
  7327. err = reservedCpusJson.Unmarshal(&reservedCpusInfo)
  7328. if err != nil {
  7329. return nil, errors.Wrap(err, "unmarshal host reserved cpus info failed")
  7330. }
  7331. if reservedCpusInfo.Cpus == "" {
  7332. return nil, nil
  7333. }
  7334. cs, err := cpuset.Parse(reservedCpusInfo.Cpus)
  7335. if err != nil {
  7336. return nil, errors.Wrap(err, "parse reserved cpuset")
  7337. }
  7338. return &cs, nil
  7339. }
  7340. return nil, nil
  7341. }
  7342. func (hh *SHost) updateHostReservedCpus(ctx context.Context, userCred mcclient.TokenCredential) error {
  7343. reservedCpus, err := hh.GetReservedCpus()
  7344. if err != nil {
  7345. return err
  7346. }
  7347. pinnedCpus, err := hh.GetPinnedCpusetCores(ctx, userCred, nil)
  7348. if err != nil {
  7349. return err
  7350. }
  7351. var reservedCpuCnt = 0
  7352. if reservedCpus != nil {
  7353. reservedCpuCnt += reservedCpus.Size()
  7354. }
  7355. if pinnedCpus != nil {
  7356. reservedCpuCnt += pinnedCpus.Size()
  7357. }
  7358. if hh.CpuReserved != reservedCpuCnt {
  7359. _, err = db.Update(hh, func() error {
  7360. hh.CpuReserved = reservedCpuCnt
  7361. return nil
  7362. })
  7363. if err != nil {
  7364. return err
  7365. }
  7366. }
  7367. hh.ClearSchedDescCache()
  7368. return nil
  7369. }
  7370. func (h *SHost) PerformSyncGuestNicTraffics(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.GuestNicTrafficSyncInput) (jsonutils.JSONObject, error) {
  7371. for guestId := range input.Traffic {
  7372. nicTrafficMap := input.Traffic[guestId]
  7373. guest := GuestManager.FetchGuestById(guestId)
  7374. gns, err := guest.GetNetworks("")
  7375. if err != nil {
  7376. log.Errorf("failed fetch guest %s networks %s", guestId, err)
  7377. continue
  7378. }
  7379. for i := range gns {
  7380. nicTraffic, ok := nicTrafficMap[gns[i].MacAddr]
  7381. if !ok {
  7382. continue
  7383. }
  7384. if err := gns[i].UpdateNicTrafficUsed(ctx, guest, nicTraffic, input.SyncAt, input.IsReset); err != nil {
  7385. log.Errorf("failed update guestnetwork %d traffic used %s", gns[i].RowId, err)
  7386. continue
  7387. }
  7388. }
  7389. }
  7390. return nil, nil
  7391. }
  7392. func (h *SHost) GetDetailsAppOptions(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) (jsonutils.JSONObject, error) {
  7393. return h.Request(ctx, userCred, httputils.GET, "/app-options", nil, nil)
  7394. }
  7395. func (h *SHost) GetDetailsWorkerStats(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) (jsonutils.JSONObject, error) {
  7396. return h.Request(ctx, userCred, httputils.GET, "/worker_stats", nil, nil)
  7397. }
  7398. func (hh *SHost) GetDetailsIsolatedDeviceNumaStats(ctx context.Context, userCred mcclient.TokenCredential, input *api.HostIsolatedDeviceNumaStatsInput) (jsonutils.JSONObject, error) {
  7399. if !utils.IsInStringArray(input.DevType, api.VALID_PASSTHROUGH_TYPES) {
  7400. return nil, httperrors.NewInputParameterError("dev_type %s is invalid", input.DevType)
  7401. }
  7402. stats, err := IsolatedDeviceManager.GetHostAllocatedIsolatedDeviceNumaStats(input.DevType, hh.Id)
  7403. if err != nil {
  7404. return nil, err
  7405. }
  7406. return jsonutils.Marshal(stats), nil
  7407. }
  7408. func (hh *SHost) IsAttach2Wire(wireId string) bool {
  7409. netifs := hh.getNetifsOnWire(wireId)
  7410. return len(netifs) > 0
  7411. }
  7412. func (h *SHost) updateNotify(ctx context.Context, userCred mcclient.TokenCredential) {
  7413. notifyclient.EventNotify(ctx, userCred, notifyclient.SEventNotifyParam{
  7414. Action: notifyclient.ActionUpdate,
  7415. Obj: h,
  7416. })
  7417. }