guests.go 230 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631
  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. "bytes"
  17. "context"
  18. "database/sql"
  19. "fmt"
  20. "net/http"
  21. "net/url"
  22. "regexp"
  23. "strconv"
  24. "strings"
  25. "time"
  26. "yunion.io/x/cloudmux/pkg/cloudprovider"
  27. "yunion.io/x/jsonutils"
  28. "yunion.io/x/log"
  29. "yunion.io/x/pkg/errors"
  30. "yunion.io/x/pkg/gotypes"
  31. "yunion.io/x/pkg/tristate"
  32. "yunion.io/x/pkg/util/billing"
  33. "yunion.io/x/pkg/util/compare"
  34. "yunion.io/x/pkg/util/netutils"
  35. "yunion.io/x/pkg/util/osprofile"
  36. "yunion.io/x/pkg/util/pinyinutils"
  37. "yunion.io/x/pkg/util/rbacscope"
  38. "yunion.io/x/pkg/util/regutils"
  39. "yunion.io/x/pkg/util/timeutils"
  40. "yunion.io/x/pkg/utils"
  41. "yunion.io/x/sqlchemy"
  42. "yunion.io/x/onecloud/pkg/apis"
  43. billing_api "yunion.io/x/onecloud/pkg/apis/billing"
  44. api "yunion.io/x/onecloud/pkg/apis/compute"
  45. imageapi "yunion.io/x/onecloud/pkg/apis/image"
  46. schedapi "yunion.io/x/onecloud/pkg/apis/scheduler"
  47. "yunion.io/x/onecloud/pkg/cloudcommon/cmdline"
  48. "yunion.io/x/onecloud/pkg/cloudcommon/consts"
  49. "yunion.io/x/onecloud/pkg/cloudcommon/db"
  50. "yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
  51. "yunion.io/x/onecloud/pkg/cloudcommon/db/quotas"
  52. "yunion.io/x/onecloud/pkg/cloudcommon/db/taskman"
  53. "yunion.io/x/onecloud/pkg/cloudcommon/notifyclient"
  54. "yunion.io/x/onecloud/pkg/cloudcommon/policy"
  55. "yunion.io/x/onecloud/pkg/cloudcommon/userdata"
  56. "yunion.io/x/onecloud/pkg/compute/options"
  57. "yunion.io/x/onecloud/pkg/compute/sshkeys"
  58. devtool_utils "yunion.io/x/onecloud/pkg/devtool/utils"
  59. "yunion.io/x/onecloud/pkg/httperrors"
  60. "yunion.io/x/onecloud/pkg/mcclient"
  61. "yunion.io/x/onecloud/pkg/mcclient/auth"
  62. "yunion.io/x/onecloud/pkg/mcclient/modules/image"
  63. "yunion.io/x/onecloud/pkg/util/bitmap"
  64. "yunion.io/x/onecloud/pkg/util/logclient"
  65. "yunion.io/x/onecloud/pkg/util/netutils2"
  66. "yunion.io/x/onecloud/pkg/util/rbacutils"
  67. "yunion.io/x/onecloud/pkg/util/seclib2"
  68. "yunion.io/x/onecloud/pkg/util/stringutils2"
  69. )
  70. // +onecloud:swagger-gen-model-singular=server
  71. // +onecloud:swagger-gen-model-plural=servers
  72. type SGuestManager struct {
  73. db.SVirtualResourceBaseManager
  74. db.SExternalizedResourceBaseManager
  75. SDeletePreventableResourceBaseManager
  76. SHostResourceBaseManager
  77. SBillingResourceBaseManager
  78. SNetworkResourceBaseManager
  79. SDiskResourceBaseManager
  80. SScalingGroupResourceBaseManager
  81. db.SMultiArchResourceBaseManager
  82. db.SRecordChecksumResourceBaseManager
  83. SHostnameResourceBaseManager
  84. db.SEncryptedResourceManager
  85. }
  86. var GuestManager *SGuestManager
  87. func init() {
  88. GuestManager = &SGuestManager{
  89. SVirtualResourceBaseManager: db.NewVirtualResourceBaseManager(
  90. SGuest{},
  91. "guests_tbl",
  92. "server",
  93. "servers",
  94. ),
  95. SRecordChecksumResourceBaseManager: *db.NewRecordChecksumResourceBaseManager(),
  96. }
  97. GuestManager.SetVirtualObject(GuestManager)
  98. GuestManager.SetAlias("guest", "guests")
  99. GuestManager.NameRequireAscii = false
  100. notifyclient.AddNotifyDBHookResources(GuestManager.KeywordPlural(), GuestManager.AliasPlural())
  101. }
  102. type SGuest struct {
  103. db.SVirtualResourceBase
  104. db.SExternalizedResourceBase
  105. SBillingResourceBase
  106. SDeletePreventableResourceBase
  107. db.SMultiArchResourceBase
  108. db.SRecordChecksumResourceBase
  109. SHostnameResourceBase
  110. SHostResourceBase `width:"36" charset:"ascii" nullable:"true" list:"user" get:"user" index:"true"`
  111. db.SEncryptedResource
  112. // CPU插槽(socket)的数量
  113. CpuSockets int `nullable:"false" default:"1" list:"user" create:"optional"`
  114. // CPU核(core)的数量, VcpuCount = CpuSockets * (cores per socket),例如 2颗CPU,每颗CPU8核,则 VcpuCount=2*8=16
  115. VcpuCount int `nullable:"false" default:"1" list:"user" create:"optional"`
  116. // 内存大小, 单位MB
  117. VmemSize int `nullable:"false" list:"user" create:"required"`
  118. // CPU 内存绑定信息
  119. CpuNumaPin jsonutils.JSONObject `nullable:"true" get:"user" update:"user" create:"optional"`
  120. // 额外分配的 CPU 数量
  121. ExtraCpuCount int `nullable:"false" default:"0" list:"user" create:"optional"`
  122. // 启动顺序
  123. BootOrder string `width:"8" charset:"ascii" nullable:"true" default:"cdn" list:"user" update:"user" create:"optional"`
  124. // 关机操作类型
  125. // example: stop
  126. ShutdownBehavior string `width:"16" charset:"ascii" default:"stop" list:"user" update:"user" create:"optional"`
  127. // 关机收费模式
  128. // example: keep_charging, stop_charging
  129. ShutdownMode string `width:"16" charset:"ascii" default:"keep_charging" list:"user"`
  130. // 秘钥对Id
  131. KeypairId string `width:"36" charset:"ascii" nullable:"true" list:"user" create:"optional"`
  132. // 备份机所在宿主机Id
  133. BackupHostId string `width:"36" charset:"ascii" nullable:"true" list:"user" get:"user"`
  134. BackupGuestStatus string `width:"36" charset:"ascii" nullable:"false" default:"init" list:"user" create:"optional" json:"backup_guest_status"`
  135. // 迁移或克隆的速度
  136. ProgressMbps float64 `nullable:"false" default:"0" list:"user" create:"optional" update:"user" log:"skip"`
  137. Vga string `width:"36" charset:"ascii" nullable:"true" list:"user" update:"user" create:"optional"`
  138. Vdi string `width:"36" charset:"ascii" nullable:"true" list:"user" update:"user" create:"optional"`
  139. Machine string `width:"36" charset:"ascii" nullable:"true" list:"user" update:"user" create:"optional"`
  140. Bios string `width:"36" charset:"ascii" nullable:"true" list:"user" update:"user" create:"optional"`
  141. // 操作系统类型
  142. OsType string `width:"36" charset:"ascii" nullable:"true" list:"user" create:"optional"`
  143. FlavorId string `width:"36" charset:"ascii" nullable:"true" list:"user" create:"optional"`
  144. // 安全组Id
  145. // example: default
  146. SecgrpId string `width:"36" charset:"ascii" nullable:"true" list:"user" get:"user" create:"optional"`
  147. // 管理员可见安全组Id
  148. AdminSecgrpId string `width:"36" charset:"ascii" nullable:"true" list:"domain" get:"domain"`
  149. SrcIpCheck tristate.TriState `default:"true" create:"optional" list:"user" update:"user"`
  150. SrcMacCheck tristate.TriState `default:"true" create:"optional" list:"user" update:"user"`
  151. // 虚拟化技术
  152. // example: kvm
  153. Hypervisor string `width:"16" charset:"ascii" nullable:"false" default:"kvm" list:"user" create:"required"`
  154. // 套餐名称
  155. InstanceType string `width:"64" charset:"utf8" nullable:"true" list:"user" create:"optional"`
  156. SshableLastState tristate.TriState `default:"false" list:"user"`
  157. IsDaemon tristate.TriState `default:"false" list:"admin" create:"admin_optional" update:"admin"`
  158. // 最大内网带宽
  159. InternetMaxBandwidthOut int `nullable:"true" list:"user" create:"optional"`
  160. // 磁盘吞吐量
  161. Throughput int `nullable:"true" list:"user" create:"optional"`
  162. QgaStatus string `width:"36" charset:"ascii" nullable:"false" default:"unknown" list:"user" create:"optional"`
  163. // power_states limit in [on, off, unknown]
  164. PowerStates string `width:"36" charset:"ascii" nullable:"false" default:"unknown" list:"user" create:"optional"`
  165. // 健康状态, 仅开机中火运行中有效, 目前只支持阿里云
  166. HealthStatus string `width:"36" charset:"ascii" nullable:"true" default:"ok" list:"user"`
  167. // Used for guest rescue
  168. RescueMode bool `nullable:"false" default:"false" list:"user" create:"optional"`
  169. // 上次开机时间
  170. LastStartAt time.Time `json:"last_start_at" list:"user"`
  171. // 资源池,仅vmware指定调度标签时内部使用
  172. ResourcePool string `width:"64" charset:"utf8" nullable:"true" create:"optional"`
  173. }
  174. func (manager *SGuestManager) GetPropertyStatistics(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) (*apis.StatusStatistic, error) {
  175. ret, err := manager.SVirtualResourceBaseManager.GetPropertyStatistics(ctx, userCred, query)
  176. if err != nil {
  177. return nil, err
  178. }
  179. q := manager.Query()
  180. q, err = db.ListItemQueryFilters(manager, ctx, q, userCred, query, policy.PolicyActionList)
  181. if err != nil {
  182. return nil, err
  183. }
  184. sq := q.SubQuery()
  185. statQ := sq.Query(sqlchemy.SUM("total_cpu_count", sq.Field("vcpu_count")), sqlchemy.SUM("total_mem_size_mb", sq.Field("vmem_size")))
  186. err = statQ.First(ret)
  187. if err != nil {
  188. return ret, err
  189. }
  190. diskQ := DiskManager.Query()
  191. gdsSQ := GuestdiskManager.Query().SubQuery()
  192. diskQ = diskQ.Join(gdsSQ, sqlchemy.Equals(diskQ.Field("id"), gdsSQ.Field("disk_id"))).
  193. Join(sq, sqlchemy.Equals(gdsSQ.Field("guest_id"), sq.Field("id")))
  194. diskSQ := diskQ.SubQuery()
  195. return ret, diskSQ.Query(sqlchemy.SUM("total_disk_size_mb", diskSQ.Field("disk_size"))).First(ret)
  196. }
  197. // 云主机实例列表
  198. func (manager *SGuestManager) ListItemFilter(
  199. ctx context.Context,
  200. q *sqlchemy.SQuery,
  201. userCred mcclient.TokenCredential,
  202. query api.ServerListInput,
  203. ) (*sqlchemy.SQuery, error) {
  204. var err error
  205. q, err = manager.SHostResourceBaseManager.ListItemFilter(ctx, q, userCred, query.HostFilterListInput)
  206. if err != nil {
  207. return nil, errors.Wrap(err, "SHostResourceBaseManager.ListItemFilter")
  208. }
  209. q, err = manager.SExternalizedResourceBaseManager.ListItemFilter(ctx, q, userCred, query.ExternalizedResourceBaseListInput)
  210. if err != nil {
  211. return nil, errors.Wrap(err, "SExternalizedResourceBaseManager.ListItemFilter")
  212. }
  213. q, err = manager.SDeletePreventableResourceBaseManager.ListItemFilter(ctx, q, userCred, query.DeletePreventableResourceBaseListInput)
  214. if err != nil {
  215. return nil, errors.Wrap(err, "SDeletePreventableResourceBaseManager.ListItemFilter")
  216. }
  217. q, err = manager.SBillingResourceBaseManager.ListItemFilter(ctx, q, userCred, query.BillingResourceListInput)
  218. if err != nil {
  219. return nil, errors.Wrap(err, "SBillingResourceBaseManager.ListItemFilter")
  220. }
  221. q, err = manager.SVirtualResourceBaseManager.ListItemFilter(ctx, q, userCred, query.VirtualResourceListInput)
  222. if err != nil {
  223. return nil, errors.Wrap(err, "SVirtualResourceBaseManager.ListItemFilter")
  224. }
  225. q, err = manager.SMultiArchResourceBaseManager.ListItemFilter(ctx, q, userCred, query.MultiArchResourceBaseListInput)
  226. if err != nil {
  227. return nil, errors.Wrap(err, "MultiArchResourceBaseListInput.ListItemFilter")
  228. }
  229. netQ := GuestnetworkManager.Query("guest_id").Snapshot()
  230. netQ, err = manager.SNetworkResourceBaseManager.ListItemFilter(ctx, netQ, userCred, query.NetworkFilterListInput)
  231. if err != nil {
  232. return nil, errors.Wrap(err, "SNetworkResourceBaseManager.ListItemFilter")
  233. }
  234. if netQ.IsAltered() {
  235. q = q.In("id", netQ.SubQuery())
  236. }
  237. //diskQ := GuestdiskManager.Query("guest_id").Snapshot()
  238. //diskQ, err = manager.SDiskResourceBaseManager.ListItemFilter(ctx, diskQ, userCred, query.DiskFilterListInput)
  239. //if err != nil {
  240. // return nil, errors.Wrap(err, "SDiskResourceBaseManager.ListItemFilter")
  241. //}
  242. //if diskQ.IsAltered() {
  243. // q = q.In("id", diskQ.SubQuery())
  244. //}
  245. scalingGroupQ := ScalingGroupGuestManager.Query("guest_id").Snapshot()
  246. scalingGroupQ, err = manager.SScalingGroupResourceBaseManager.ListItemFilter(ctx, scalingGroupQ, userCred, query.ScalingGroupFilterListInput)
  247. if err != nil {
  248. return nil, errors.Wrap(err, "SScaligGroupResourceBaseManager.ListItemFilter")
  249. }
  250. if scalingGroupQ.IsAltered() {
  251. q = q.In("id", scalingGroupQ.SubQuery())
  252. }
  253. hypervisorList := query.Hypervisor
  254. if len(hypervisorList) > 0 {
  255. q = q.In("hypervisor", hypervisorList)
  256. }
  257. resourceTypeStr := query.ResourceType
  258. if len(resourceTypeStr) > 0 {
  259. hosts := HostManager.Query().SubQuery()
  260. subq := hosts.Query(hosts.Field("id"))
  261. switch resourceTypeStr {
  262. case api.HostResourceTypeShared:
  263. subq = subq.Filter(
  264. sqlchemy.OR(
  265. sqlchemy.IsNullOrEmpty(hosts.Field("resource_type")),
  266. sqlchemy.Equals(hosts.Field("resource_type"), resourceTypeStr),
  267. ),
  268. )
  269. default:
  270. subq = subq.Equals("resource_type", resourceTypeStr)
  271. }
  272. q = q.In("host_id", subq.SubQuery())
  273. }
  274. hostFilter := query.GetAllGuestsOnHost
  275. if len(hostFilter) > 0 {
  276. host, _ := HostManager.FetchByIdOrName(ctx, nil, hostFilter)
  277. if host == nil {
  278. return nil, httperrors.NewResourceNotFoundError("host %s not found", hostFilter)
  279. }
  280. q.Filter(sqlchemy.OR(sqlchemy.Equals(q.Field("host_id"), host.GetId()),
  281. sqlchemy.Equals(q.Field("backup_host_id"), host.GetId())))
  282. }
  283. secgrpFilter := query.SecgroupId
  284. if len(secgrpFilter) > 0 {
  285. var notIn = false
  286. // HACK FOR NOT IN SECGROUP
  287. if strings.HasPrefix(secgrpFilter, "!") {
  288. secgrpFilter = secgrpFilter[1:]
  289. notIn = true
  290. }
  291. secgrpIds := []string{}
  292. secgrps := []SSecurityGroup{}
  293. sgq := SecurityGroupManager.Query()
  294. sgq = sgq.Filter(sqlchemy.OR(sqlchemy.Equals(sgq.Field("id"), secgrpFilter), sqlchemy.Equals(sgq.Field("name"), secgrpFilter)))
  295. if err := db.FetchModelObjects(SecurityGroupManager, sgq, &secgrps); err != nil {
  296. return nil, err
  297. }
  298. if len(secgrps) == 0 {
  299. return nil, httperrors.NewResourceNotFoundError("secgroup %s not found", secgrpFilter)
  300. }
  301. for _, secgrp := range secgrps {
  302. secgrpIds = append(secgrpIds, secgrp.Id)
  303. }
  304. isAdmin := false
  305. // admin := (query.VirtualResourceListInput.Admin != nil && *query.VirtualResourceListInput.Admin)
  306. allowScope, _ := policy.PolicyManager.AllowScope(userCred, consts.GetServiceType(), manager.KeywordPlural(), policy.PolicyActionList)
  307. if allowScope == rbacscope.ScopeSystem || allowScope == rbacscope.ScopeDomain {
  308. isAdmin = true
  309. }
  310. filters := []sqlchemy.ICondition{}
  311. if notIn {
  312. filters = append(filters, sqlchemy.NotIn(q.Field("id"),
  313. GuestsecgroupManager.Query("guest_id").In("secgroup_id", secgrpIds).SubQuery()))
  314. filters = append(filters, sqlchemy.NotIn(q.Field("secgrp_id"), secgrpIds))
  315. if isAdmin {
  316. filters = append(filters, sqlchemy.NotIn(q.Field("admin_secgrp_id"), secgrpIds))
  317. }
  318. q = q.Filter(sqlchemy.AND(filters...))
  319. } else {
  320. filters = append(filters, sqlchemy.In(q.Field("id"),
  321. GuestsecgroupManager.Query("guest_id").In("secgroup_id", secgrpIds).SubQuery()))
  322. filters = append(filters, sqlchemy.In(q.Field("secgrp_id"), secgrpIds))
  323. if isAdmin {
  324. filters = append(filters, sqlchemy.In(q.Field("admin_secgrp_id"), secgrpIds))
  325. }
  326. q = q.Filter(sqlchemy.OR(filters...))
  327. }
  328. }
  329. var eipMode string
  330. usableServerForEipFilter := query.UsableServerForEip
  331. if len(usableServerForEipFilter) > 0 {
  332. eipObj, err := ElasticipManager.FetchByIdOrName(ctx, userCred, usableServerForEipFilter)
  333. if err != nil {
  334. if err == sql.ErrNoRows {
  335. return nil, httperrors.NewResourceNotFoundError("eip %s not found", usableServerForEipFilter)
  336. }
  337. return nil, httperrors.NewGeneralError(err)
  338. }
  339. eip := eipObj.(*SElasticip)
  340. if eip.GetProviderName() == api.CLOUD_PROVIDER_AWS {
  341. eipMode = api.EIP_MODE_STANDALONE_EIP
  342. }
  343. if len(eip.NetworkId) > 0 {
  344. sq := GuestnetworkManager.Query("guest_id").Equals("network_id", eip.NetworkId).SubQuery()
  345. q = q.NotIn("id", sq)
  346. if cp := eip.GetCloudprovider(); cp == nil || cp.Provider == api.CLOUD_PROVIDER_ONECLOUD {
  347. gnq := GuestnetworkManager.Query().SubQuery()
  348. nq := NetworkManager.Query().SubQuery()
  349. wq := WireManager.Query().SubQuery()
  350. vq := VpcManager.Query().SubQuery()
  351. q.Join(gnq, sqlchemy.Equals(gnq.Field("guest_id"), q.Field("id")))
  352. q.Join(nq, sqlchemy.Equals(nq.Field("id"), gnq.Field("network_id")))
  353. q.Join(wq, sqlchemy.Equals(wq.Field("id"), nq.Field("wire_id")))
  354. q.Join(vq, sqlchemy.Equals(vq.Field("id"), wq.Field("vpc_id")))
  355. q.Filter(sqlchemy.IsNullOrEmpty(gnq.Field("eip_id")))
  356. q.Filter(sqlchemy.NotEquals(vq.Field("id"), api.DEFAULT_VPC_ID))
  357. // vpc provider thing will be handled ok below
  358. }
  359. }
  360. hostTable := HostManager.Query().SubQuery()
  361. zoneTable := ZoneManager.Query().SubQuery()
  362. hostQ := hostTable.Query(hostTable.Field("id"))
  363. hostQ = hostQ.Join(zoneTable,
  364. sqlchemy.Equals(zoneTable.Field("id"), hostTable.Field("zone_id")))
  365. if eip.ManagerId != "" {
  366. hostQ = hostQ.Equals("manager_id", eip.ManagerId)
  367. } else {
  368. hostQ = hostQ.IsNullOrEmpty("manager_id")
  369. }
  370. region, err := eip.GetRegion()
  371. if err != nil {
  372. return nil, httperrors.NewGeneralError(errors.Wrapf(err, "eip.GetRegion"))
  373. }
  374. regionTable := CloudregionManager.Query().SubQuery()
  375. sq := hostQ.Join(regionTable, sqlchemy.Equals(zoneTable.Field("cloudregion_id"), regionTable.Field("id"))).
  376. Filter(sqlchemy.Equals(regionTable.Field("id"), region.GetId())).SubQuery()
  377. q = q.In("host_id", sq)
  378. }
  379. if len(query.IpAddrs) > 0 {
  380. // 如果只有一个ip地址,则使用正则匹配,否则使用等于匹配
  381. cmpFunc := sqlchemy.Equals
  382. if len(query.IpAddrs) == 1 {
  383. cmpFunc = func(f sqlchemy.IQueryField, v interface{}) sqlchemy.ICondition {
  384. return sqlchemy.Regexp(f, v.(string))
  385. }
  386. }
  387. grpnets := GroupnetworkManager.Query().SubQuery()
  388. vipq := GroupguestManager.Query("guest_id")
  389. conditions := []sqlchemy.ICondition{}
  390. for _, ipAddr := range query.IpAddrs {
  391. conditions = append(conditions, cmpFunc(grpnets.Field("ip_addr"), ipAddr))
  392. conditions = append(conditions, cmpFunc(grpnets.Field("ip6_addr"), ipAddr))
  393. }
  394. vipq = vipq.Join(grpnets, sqlchemy.Equals(grpnets.Field("group_id"), vipq.Field("group_id"))).Filter(
  395. sqlchemy.OR(conditions...),
  396. )
  397. grpeips := ElasticipManager.Query().Equals("associate_type", api.EIP_ASSOCIATE_TYPE_INSTANCE_GROUP).SubQuery()
  398. conditions = []sqlchemy.ICondition{}
  399. for _, ipAddr := range query.IpAddrs {
  400. conditions = append(conditions, cmpFunc(grpeips.Field("ip_addr"), ipAddr))
  401. }
  402. vipeipq := GroupguestManager.Query("guest_id")
  403. vipeipq = vipeipq.Join(grpeips, sqlchemy.Equals(grpeips.Field("associate_id"), vipeipq.Field("group_id"))).Filter(
  404. sqlchemy.OR(conditions...),
  405. )
  406. gnQ := GuestnetworkManager.Query("guest_id")
  407. conditions = []sqlchemy.ICondition{}
  408. for _, ipAddr := range query.IpAddrs {
  409. conditions = append(conditions, cmpFunc(gnQ.Field("ip_addr"), ipAddr))
  410. conditions = append(conditions, cmpFunc(gnQ.Field("ip6_addr"), ipAddr))
  411. }
  412. gn := gnQ.Filter(sqlchemy.OR(conditions...))
  413. guestEipQ := ElasticipManager.Query("associate_id").Equals("associate_type", api.EIP_ASSOCIATE_TYPE_SERVER)
  414. conditions = []sqlchemy.ICondition{}
  415. for _, ipAddr := range query.IpAddrs {
  416. conditions = append(conditions, cmpFunc(guestEipQ.Field("ip_addr"), ipAddr))
  417. }
  418. guestEip := guestEipQ.Filter(sqlchemy.OR(conditions...))
  419. metadataQ := db.Metadata.Query("obj_id")
  420. conditions = []sqlchemy.ICondition{}
  421. for _, ipAddr := range query.IpAddrs {
  422. conditions = append(conditions, sqlchemy.AND(
  423. cmpFunc(metadataQ.Field("value"), ipAddr),
  424. sqlchemy.Equals(metadataQ.Field("key"), "sync_ips"),
  425. sqlchemy.Equals(metadataQ.Field("obj_type"), "server"),
  426. ))
  427. }
  428. metadataQ = metadataQ.Filter(sqlchemy.OR(conditions...))
  429. q = q.Filter(sqlchemy.OR(
  430. sqlchemy.In(q.Field("id"), gn.SubQuery()),
  431. sqlchemy.In(q.Field("id"), guestEip.SubQuery()),
  432. sqlchemy.In(q.Field("id"), vipq.SubQuery()),
  433. sqlchemy.In(q.Field("id"), vipeipq.SubQuery()),
  434. sqlchemy.In(q.Field("id"), metadataQ.SubQuery()),
  435. ))
  436. }
  437. diskFilter := query.AttachableServersForDisk
  438. if len(diskFilter) > 0 {
  439. diskI, _ := DiskManager.FetchByIdOrName(ctx, userCred, diskFilter)
  440. if diskI == nil {
  441. return nil, httperrors.NewResourceNotFoundError("disk %s not found", diskFilter)
  442. }
  443. disk := diskI.(*SDisk)
  444. guestdisks := GuestdiskManager.Query().SubQuery()
  445. count, err := guestdisks.Query().Equals("disk_id", disk.Id).CountWithError()
  446. if err != nil {
  447. return nil, httperrors.NewInternalServerError("checkout guestdisk count fail %s", err)
  448. }
  449. if count > 0 {
  450. sgq := guestdisks.Query(guestdisks.Field("guest_id")).Equals("disk_id", disk.Id).SubQuery()
  451. q = q.Filter(sqlchemy.In(q.Field("id"), sgq))
  452. } else {
  453. hosts := HostManager.Query().SubQuery()
  454. hoststorages := HoststorageManager.Query().SubQuery()
  455. storages := StorageManager.Query().SubQuery()
  456. sq := hosts.Query(hosts.Field("id")).
  457. Join(hoststorages, sqlchemy.Equals(hoststorages.Field("host_id"), hosts.Field("id"))).
  458. Join(storages, sqlchemy.Equals(storages.Field("id"), hoststorages.Field("storage_id"))).
  459. Filter(sqlchemy.Equals(storages.Field("id"), disk.StorageId)).SubQuery()
  460. q = q.In("host_id", sq)
  461. }
  462. }
  463. withEip := (query.WithEip != nil && *query.WithEip)
  464. withoutEip := (query.WithoutEip != nil && *query.WithoutEip) || (query.EipAssociable != nil && *query.EipAssociable)
  465. if withEip || withoutEip {
  466. eips := ElasticipManager.Query().SubQuery()
  467. sq := eips.Query(eips.Field("associate_id")).Equals("associate_type", api.EIP_ASSOCIATE_TYPE_SERVER)
  468. sq = sq.IsNotNull("associate_id").IsNotEmpty("associate_id")
  469. if len(eipMode) > 0 {
  470. sq = sq.Equals("mode", eipMode)
  471. }
  472. if withEip {
  473. q = q.In("id", sq)
  474. } else if withoutEip {
  475. q = q.NotIn("id", sq)
  476. }
  477. }
  478. if query.EipAssociable != nil {
  479. sq1 := NetworkManager.Query("id")
  480. sq2 := WireManager.Query().SubQuery()
  481. sq3 := VpcManager.Query().SubQuery()
  482. sq1 = sq1.Join(sq2, sqlchemy.Equals(sq1.Field("wire_id"), sq2.Field("id")))
  483. sq1 = sq1.Join(sq3, sqlchemy.Equals(sq2.Field("vpc_id"), sq3.Field("id")))
  484. cond1 := []string{api.VPC_EXTERNAL_ACCESS_MODE_EIP, api.VPC_EXTERNAL_ACCESS_MODE_EIP_DISTGW}
  485. if *query.EipAssociable {
  486. sq1 = sq1.Filter(sqlchemy.In(sq3.Field("external_access_mode"), cond1))
  487. } else {
  488. sq1 = sq1.Filter(sqlchemy.NotIn(sq3.Field("external_access_mode"), cond1))
  489. }
  490. sq := GuestnetworkManager.Query("guest_id").In("network_id", sq1)
  491. q = q.In("id", sq)
  492. }
  493. devTypeQ := func(q *sqlchemy.SQuery, checkType, backup *bool, dType string, conditions []sqlchemy.ICondition) []sqlchemy.ICondition {
  494. if checkType != nil {
  495. isodev := IsolatedDeviceManager.Query().SubQuery()
  496. isodevCons := []sqlchemy.ICondition{sqlchemy.IsNotNull(isodev.Field("guest_id"))}
  497. if len(dType) > 0 {
  498. isodevCons = append(isodevCons, sqlchemy.Startswith(isodev.Field("dev_type"), dType))
  499. }
  500. sgq := isodev.Query(isodev.Field("guest_id")).Filter(sqlchemy.AND(isodevCons...))
  501. cond := sqlchemy.NotIn
  502. if *checkType {
  503. cond = sqlchemy.In
  504. }
  505. if dType == "GPU" {
  506. sq := ServerSkuManager.Query("name").GT("gpu_count", 0).Distinct().SubQuery()
  507. if backup != nil {
  508. afterAnd := sqlchemy.AND
  509. if *backup {
  510. backupCond := sqlchemy.IsNotEmpty(q.Field("backup_host_id"))
  511. conditions = append(conditions, afterAnd(cond(q.Field("instance_type"), sq), backupCond))
  512. } else {
  513. backupCond := sqlchemy.IsEmpty(q.Field("backup_host_id"))
  514. conditions = append(conditions, afterAnd(cond(q.Field("instance_type"), sq), backupCond))
  515. }
  516. } else {
  517. conditions = append(conditions, cond(q.Field("instance_type"), sq))
  518. }
  519. } else {
  520. if backup != nil {
  521. afterAnd := sqlchemy.AND
  522. if *backup {
  523. backupCond := sqlchemy.IsNotEmpty(q.Field("backup_host_id"))
  524. conditions = append(conditions, afterAnd(cond(q.Field("id"), sgq), backupCond))
  525. } else {
  526. backupCond := sqlchemy.IsEmpty(q.Field("backup_host_id"))
  527. conditions = append(conditions, afterAnd(cond(q.Field("id"), sgq), backupCond))
  528. }
  529. } else {
  530. conditions = append(conditions, cond(q.Field("id"), sgq))
  531. }
  532. }
  533. return conditions
  534. }
  535. return conditions
  536. }
  537. conditions := []sqlchemy.ICondition{}
  538. if len(query.ServerType) > 0 {
  539. var trueVal, falseVal = true, false
  540. for _, serverType := range query.ServerType {
  541. switch serverType {
  542. case "normal":
  543. query.Normal = &falseVal
  544. query.Backup = &falseVal
  545. case "gpu":
  546. query.Gpu = &trueVal
  547. query.Backup = &falseVal
  548. sq := ServerSkuManager.Query("name").IsNotEmpty("gpu_spec").Distinct()
  549. conditions = append(conditions, sqlchemy.In(q.Field("instance_type"), sq.SubQuery()))
  550. case "backup":
  551. query.Gpu = &falseVal
  552. query.Backup = &trueVal
  553. case "usb":
  554. query.Usb = &trueVal
  555. query.Backup = &falseVal
  556. default:
  557. query.CustomDevType = serverType
  558. query.Backup = &falseVal
  559. }
  560. conditions = devTypeQ(q, query.Normal, query.Backup, "", conditions)
  561. conditions = devTypeQ(q, query.Gpu, query.Backup, "GPU", conditions)
  562. conditions = devTypeQ(q, query.Usb, query.Backup, api.USB_TYPE, conditions)
  563. if len(query.CustomDevType) > 0 {
  564. ct := true
  565. conditions = devTypeQ(q, &ct, query.Backup, query.CustomDevType, conditions)
  566. }
  567. query.Normal = nil
  568. query.Gpu = nil
  569. query.Backup = nil
  570. }
  571. }
  572. if len(conditions) > 0 {
  573. q = q.Filter(sqlchemy.OR(conditions...))
  574. }
  575. groupFilter := query.GroupId
  576. if len(groupFilter) != 0 {
  577. groupObj, err := GroupManager.FetchByIdOrName(ctx, userCred, groupFilter)
  578. if err != nil {
  579. return nil, httperrors.NewNotFoundError("group %s not found", groupFilter)
  580. }
  581. // queryDict.Add(jsonutils.NewString(groupObj.GetId()), "group")
  582. ggSub := GroupguestManager.Query("guest_id").Equals("group_id", groupObj.GetId()).SubQuery()
  583. q = q.Join(ggSub, sqlchemy.Equals(ggSub.Field("guest_id"), q.Field("id")))
  584. }
  585. /*orderByDisk := query.OrderByDisk
  586. if orderByDisk == "asc" || orderByDisk == "desc" {
  587. guestdisks := GuestdiskManager.Query().SubQuery()
  588. disks := DiskManager.Query().SubQuery()
  589. guestdiskQ := guestdisks.Query(
  590. guestdisks.Field("guest_id"),
  591. sqlchemy.SUM("disks_size", disks.Field("disk_size")),
  592. )
  593. guestdiskQ = guestdiskQ.LeftJoin(disks, sqlchemy.Equals(guestdiskQ.Field("disk_id"), disks.Field("id")))
  594. guestdiskSQ := guestdiskQ.GroupBy(guestdiskQ.Field("guest_id")).SubQuery()
  595. q = q.LeftJoin(guestdiskSQ, sqlchemy.Equals(q.Field("id"), guestdiskSQ.Field("guest_id")))
  596. switch orderByDisk {
  597. case "asc":
  598. q = q.Asc(guestdiskSQ.Field("disks_size"))
  599. case "desc":
  600. q = q.Desc(guestdiskSQ.Field("disks_size"))
  601. }
  602. }*/
  603. if len(query.OsType) > 0 {
  604. q = q.In("os_type", query.OsType)
  605. }
  606. if len(query.OsDist) > 0 {
  607. metaSQ := db.Metadata.Query().Equals("key", "os_distribution").In("value", query.OsDist).SubQuery()
  608. q = q.Join(metaSQ, sqlchemy.Equals(q.Field("id"), metaSQ.Field("obj_id")))
  609. }
  610. if len(query.VcpuCount) > 0 {
  611. q = q.In("vcpu_count", query.VcpuCount)
  612. }
  613. if len(query.VmemSize) > 0 {
  614. q = q.In("vmem_size", query.VmemSize)
  615. }
  616. if len(query.BootOrder) > 0 {
  617. q = q.In("boot_order", query.BootOrder)
  618. }
  619. if len(query.Vga) > 0 {
  620. q = q.In("vga", query.Vga)
  621. }
  622. if len(query.Vdi) > 0 {
  623. q = q.In("vdi", query.Vdi)
  624. }
  625. if len(query.Machine) > 0 {
  626. q = q.In("machine", query.Machine)
  627. }
  628. if len(query.Bios) > 0 {
  629. q = q.In("bios", query.Bios)
  630. }
  631. if query.SrcIpCheck != nil {
  632. if *query.SrcIpCheck {
  633. q = q.IsTrue("src_ip_check")
  634. } else {
  635. q = q.IsFalse("src_ip_check")
  636. }
  637. }
  638. if query.SrcMacCheck != nil {
  639. if *query.SrcMacCheck {
  640. q = q.IsTrue("src_mac_check")
  641. } else {
  642. q = q.IsFalse("src_mac_check")
  643. }
  644. }
  645. if len(query.InstanceType) > 0 {
  646. q = q.In("instance_type", query.InstanceType)
  647. }
  648. if query.WithHost != nil {
  649. if *query.WithHost {
  650. q = q.IsNotEmpty("host_id")
  651. } else {
  652. q = q.IsNullOrEmpty("host_id")
  653. }
  654. }
  655. if len(query.SnapshotpolicyId) > 0 {
  656. sp := SnapshotPolicyResourceManager.Query("resource_id").
  657. Equals("resource_type", api.SNAPSHOT_POLICY_TYPE_SERVER).
  658. Equals("snapshotpolicy_id", query.SnapshotpolicyId).SubQuery()
  659. q = q.In("id", sp)
  660. }
  661. if query.BindingSnapshotpolicy != nil {
  662. spjsq := SnapshotPolicyResourceManager.Query("resource_id").
  663. Equals("resource_type", api.SNAPSHOT_POLICY_TYPE_SERVER).
  664. SubQuery()
  665. if *query.BindingSnapshotpolicy {
  666. q = q.In("id", spjsq)
  667. } else {
  668. q = q.NotIn("id", spjsq)
  669. }
  670. }
  671. if query.BindingDisksSnapshotpolicy != nil {
  672. guestDisks := GuestdiskManager.Query("guest_id")
  673. sq := SnapshotPolicyResourceManager.Query("resource_id").Equals("resource_type", api.SNAPSHOT_POLICY_TYPE_DISK).SubQuery()
  674. gdsq := guestDisks.Join(sq, sqlchemy.Equals(guestDisks.Field("disk_id"), sq.Field("resource_id"))).SubQuery()
  675. if *query.BindingDisksSnapshotpolicy {
  676. q = q.In("id", gdsq)
  677. } else {
  678. q = q.NotIn("id", gdsq)
  679. }
  680. }
  681. return q, nil
  682. }
  683. func (manager *SGuestManager) ExtraSearchConditions(ctx context.Context, q *sqlchemy.SQuery, like string) []sqlchemy.ICondition {
  684. var sq *sqlchemy.SSubQuery
  685. if len(like) > 1 {
  686. switch {
  687. case strings.Contains(like, "."):
  688. sq = GuestnetworkManager.Query("guest_id").Contains("ip_addr", like).SubQuery()
  689. case strings.Contains(like, ":"):
  690. sq = GuestnetworkManager.Query("guest_id").Contains("mac_addr", like).SubQuery()
  691. }
  692. }
  693. if sq != nil {
  694. return []sqlchemy.ICondition{sqlchemy.In(q.Field("id"), sq)}
  695. }
  696. return nil
  697. }
  698. func (manager *SGuestManager) OrderByExtraFields(ctx context.Context, q *sqlchemy.SQuery, userCred mcclient.TokenCredential, query api.ServerListInput) (*sqlchemy.SQuery, error) {
  699. var err error
  700. q, err = manager.SVirtualResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.VirtualResourceListInput)
  701. if err != nil {
  702. return nil, errors.Wrap(err, "SVirtualResourceBaseManager.OrderByExtraFields")
  703. }
  704. q, err = manager.SHostResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.HostFilterListInput)
  705. if err != nil {
  706. return nil, errors.Wrap(err, "SHostResourceBaseManager.OrderByExtraFields")
  707. }
  708. fields := manager.SNetworkResourceBaseManager.GetOrderByFields(query.NetworkFilterListInput)
  709. if db.NeedOrderQuery(fields) {
  710. netQ := GuestnetworkManager.Query("guest_id", "network_id").SubQuery()
  711. q = q.LeftJoin(netQ, sqlchemy.Equals(q.Field("id"), netQ.Field("guest_id"))).Distinct()
  712. q, err = manager.SNetworkResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query.NetworkFilterListInput)
  713. if err != nil {
  714. return nil, errors.Wrap(err, "SNetworkResourceBaseManager.OrderByExtraFields")
  715. }
  716. }
  717. if db.NeedOrderQuery([]string{query.OrderByOsDist}) {
  718. meta := db.Metadata.Query().Equals("key", "os_distribution").SubQuery()
  719. q = q.LeftJoin(meta, sqlchemy.Equals(q.Field("id"), meta.Field("obj_id")))
  720. db.OrderByFields(q, []string{query.OrderByOsDist}, []sqlchemy.IQueryField{meta.Field("value")})
  721. }
  722. if db.NeedOrderQuery([]string{query.OrderByDisk}) {
  723. guestdisks := GuestdiskManager.Query().SubQuery()
  724. disks := DiskManager.Query().SubQuery()
  725. guestdiskQ := guestdisks.Query(
  726. guestdisks.Field("guest_id"),
  727. sqlchemy.SUM("disks_size", disks.Field("disk_size")),
  728. )
  729. guestdiskQ = guestdiskQ.LeftJoin(disks, sqlchemy.Equals(guestdiskQ.Field("disk_id"), disks.Field("id")))
  730. guestdiskSQ := guestdiskQ.GroupBy(guestdiskQ.Field("guest_id")).SubQuery()
  731. q = q.LeftJoin(guestdiskSQ, sqlchemy.Equals(q.Field("id"), guestdiskSQ.Field("guest_id")))
  732. db.OrderByFields(q, []string{query.OrderByDisk}, []sqlchemy.IQueryField{guestdiskSQ.Field("disks_size")})
  733. }
  734. if db.NeedOrderQuery([]string{query.OrderByIp}) {
  735. guestnet := GuestnetworkManager.Query("guest_id", "ip_addr").SubQuery()
  736. q.AppendField(q.QueryFields()...)
  737. q.AppendField(guestnet.Field("ip_addr"))
  738. q = q.LeftJoin(guestnet, sqlchemy.Equals(q.Field("id"), guestnet.Field("guest_id")))
  739. db.OrderByFields(q, []string{query.OrderByIp}, []sqlchemy.IQueryField{sqlchemy.INET_ATON(q.Field("ip_addr"))})
  740. }
  741. return q, nil
  742. }
  743. func (manager *SGuestManager) QueryDistinctExtraField(q *sqlchemy.SQuery, field string) (*sqlchemy.SQuery, error) {
  744. var err error
  745. q, err = manager.SVirtualResourceBaseManager.QueryDistinctExtraField(q, field)
  746. if err == nil {
  747. return q, nil
  748. }
  749. q, err = manager.SHostResourceBaseManager.QueryDistinctExtraField(q, field)
  750. if err == nil {
  751. return q, nil
  752. }
  753. if field == "os_dist" {
  754. metaQuery := db.Metadata.Query("obj_id", "value").Equals("key", "os_distribution").SubQuery()
  755. q = q.AppendField(metaQuery.Field("value", field)).Distinct()
  756. q = q.Join(metaQuery, sqlchemy.Equals(q.Field("id"), metaQuery.Field("obj_id")))
  757. q.GroupBy(metaQuery.Field("value"))
  758. return q, nil
  759. }
  760. guestnets := GuestnetworkManager.Query("guest_id", "network_id").SubQuery()
  761. q = q.LeftJoin(guestnets, sqlchemy.Equals(q.Field("id"), guestnets.Field("guest_id")))
  762. q, err = manager.SNetworkResourceBaseManager.QueryDistinctExtraField(q, field)
  763. if err == nil {
  764. return q, nil
  765. }
  766. guestdisks := GuestdiskManager.Query("guest_id", "disk_id").SubQuery()
  767. q = q.LeftJoin(guestdisks, sqlchemy.Equals(q.Field("id"), guestdisks.Field("guest_id")))
  768. q, err = manager.SDiskResourceBaseManager.QueryDistinctExtraField(q, field)
  769. if err == nil {
  770. return q, nil
  771. }
  772. return q, httperrors.ErrNotFound
  773. }
  774. func (manager *SGuestManager) QueryDistinctExtraFields(q *sqlchemy.SQuery, resource string, fields []string) (*sqlchemy.SQuery, error) {
  775. switch resource {
  776. case NetworkManager.Keyword():
  777. guestnets := GuestnetworkManager.Query("guest_id", "network_id").SubQuery()
  778. q = q.LeftJoin(guestnets, sqlchemy.Equals(q.Field("id"), guestnets.Field("guest_id")))
  779. return manager.SNetworkResourceBaseManager.QueryDistinctExtraFields(q, resource, fields)
  780. }
  781. return q, httperrors.ErrNotFound
  782. }
  783. func (manager *SGuestManager) initHostname() error {
  784. guests := []SGuest{}
  785. q := manager.Query().IsNullOrEmpty("hostname")
  786. err := db.FetchModelObjects(manager, q, &guests)
  787. if err != nil {
  788. return errors.Wrapf(err, "db.FetchModelObjects")
  789. }
  790. for i := range guests {
  791. db.Update(&guests[i], func() error {
  792. hostname, _ := manager.SHostnameResourceBaseManager.ValidateHostname(
  793. guests[i].Hostname,
  794. guests[i].OsType,
  795. api.HostnameInput{
  796. Hostname: guests[i].Name,
  797. },
  798. )
  799. guests[i].Hostname = hostname.Hostname
  800. return nil
  801. })
  802. }
  803. return nil
  804. }
  805. func (manager *SGuestManager) clearSecgroups() error {
  806. guests := make([]SGuest, 0, 10)
  807. q := manager.Query()
  808. q = q.In("hypervisor", []string{api.HYPERVISOR_ESXI, api.HYPERVISOR_NUTANIX}).Filter(
  809. sqlchemy.OR(
  810. sqlchemy.IsNotEmpty(q.Field("secgrp_id")),
  811. sqlchemy.IsNotEmpty(q.Field("admin_secgrp_id")),
  812. ),
  813. )
  814. err := db.FetchModelObjects(manager, q, &guests)
  815. if err != nil {
  816. return errors.Wrap(err, "db.FetchModelObjects")
  817. }
  818. // remove secgroup for esxi nutanix guest
  819. for i := range guests {
  820. db.Update(&guests[i], func() error {
  821. guests[i].SecgrpId = ""
  822. guests[i].AdminSecgrpId = ""
  823. return nil
  824. })
  825. }
  826. return nil
  827. }
  828. func (manager *SGuestManager) initAdminSecgroupId() error {
  829. {
  830. err := manager.initAdminSecgroupIdForHypervisor(api.HYPERVISOR_KVM)
  831. if err != nil {
  832. return errors.Wrap(err, "initAdminSecgroupIdForKvm")
  833. }
  834. }
  835. {
  836. err := manager.initAdminSecgroupIdForHypervisor(api.HYPERVISOR_POD)
  837. if err != nil {
  838. return errors.Wrap(err, "initAdminSecgroupIdForContainer")
  839. }
  840. }
  841. return nil
  842. }
  843. func (manager *SGuestManager) initAdminSecgroupIdForHypervisor(hypervisor string) error {
  844. secGrpId := options.Options.GetDefaultAdminSecurityGroupId(hypervisor)
  845. if len(secGrpId) == 0 {
  846. return nil
  847. }
  848. adminSec, _ := SecurityGroupManager.FetchSecgroupById(secGrpId)
  849. if adminSec == nil {
  850. return nil
  851. }
  852. adminSecId := adminSec.Id
  853. guests := make([]SGuest, 0, 10)
  854. q := manager.Query()
  855. q = q.Equals("hypervisor", hypervisor).IsNullOrEmpty("admin_secgrp_id")
  856. err := db.FetchModelObjects(manager, q, &guests)
  857. if err != nil {
  858. return errors.Wrap(err, "db.FetchModelObjects")
  859. }
  860. // remove secgroup for esxi nutanix guest
  861. for i := range guests {
  862. db.Update(&guests[i], func() error {
  863. guests[i].AdminSecgrpId = adminSecId
  864. return nil
  865. })
  866. }
  867. return nil
  868. }
  869. func (manager *SGuestManager) InitializeData() error {
  870. if err := manager.initHostname(); err != nil {
  871. return errors.Wrap(err, "initHostname")
  872. }
  873. if err := manager.clearSecgroups(); err != nil {
  874. return errors.Wrap(err, "cleanSecgroups")
  875. }
  876. if err := manager.initAdminSecgroupId(); err != nil {
  877. return errors.Wrap(err, "initAdminSecgroupId")
  878. }
  879. return nil
  880. }
  881. func (guest *SGuest) GetHypervisor() string {
  882. if len(guest.Hypervisor) == 0 {
  883. return api.HYPERVISOR_DEFAULT
  884. }
  885. return guest.Hypervisor
  886. }
  887. func (guest *SGuest) GetHostType() string {
  888. host, err := guest.GetHost()
  889. if err != nil {
  890. return ""
  891. }
  892. return host.HostType
  893. }
  894. func (guest *SGuest) GetRegion() (*SCloudregion, error) {
  895. hosts := HostManager.Query("zone_id").Equals("id", guest.HostId).SubQuery()
  896. zones := ZoneManager.Query("cloudregion_id").In("id", hosts).SubQuery()
  897. q := CloudregionManager.Query().In("id", zones)
  898. ret := &SCloudregion{}
  899. ret.SetModelManager(CloudregionManager, ret)
  900. err := q.First(ret)
  901. if err != nil {
  902. return nil, errors.Wrapf(err, "q.First")
  903. }
  904. return ret, nil
  905. }
  906. func (guest *SGuest) GetZone() (*SZone, error) {
  907. hosts := HostManager.Query("zone_id").Equals("id", guest.HostId).SubQuery()
  908. q := ZoneManager.Query().In("id", hosts)
  909. ret := &SZone{}
  910. ret.SetModelManager(ZoneManager, ret)
  911. err := q.First(ret)
  912. if err != nil {
  913. return nil, errors.Wrapf(err, "q.First")
  914. }
  915. return ret, nil
  916. }
  917. func (guest *SGuest) GetDriver() (IGuestDriver, error) {
  918. hypervisor := guest.GetHypervisor()
  919. region, err := guest.GetRegion()
  920. if err != nil {
  921. return nil, errors.Wrapf(err, "GetRegion")
  922. }
  923. return GetDriver(hypervisor, region.Provider)
  924. }
  925. func (guest *SGuest) validateDeleteCondition(ctx context.Context, isPurge bool) error {
  926. if guest.DisableDelete.IsTrue() {
  927. return httperrors.NewInvalidStatusError("Virtual server is locked, cannot delete")
  928. }
  929. if !isPurge && guest.IsNotDeletablePrePaid() {
  930. return httperrors.NewForbiddenError("not allow to delete prepaid server in valid status")
  931. }
  932. return guest.SVirtualResourceBase.ValidateDeleteCondition(ctx, nil)
  933. }
  934. func (guest *SGuest) ValidateDeleteCondition(ctx context.Context, info *api.ServerDetails) error {
  935. if gotypes.IsNil(info) {
  936. info = &api.ServerDetails{}
  937. host, err := guest.GetHost()
  938. if err != nil {
  939. return err
  940. }
  941. info.HostType = host.HostType
  942. info.HostEnabled = host.Enabled.Bool()
  943. info.HostStatus = host.Status
  944. info.HostServiceStatus = host.HostStatus
  945. }
  946. if len(info.HostType) > 0 && guest.GetHypervisor() != api.HYPERVISOR_BAREMETAL {
  947. if !info.HostEnabled {
  948. return httperrors.NewInputParameterError("Cannot delete server on disabled host")
  949. }
  950. if info.HostServiceStatus != api.HOST_ONLINE {
  951. return httperrors.NewInputParameterError("Cannot delete server on offline host")
  952. }
  953. }
  954. return guest.validateDeleteCondition(ctx, false)
  955. }
  956. func (guest *SGuest) GetDisksQuery() *sqlchemy.SQuery {
  957. return GuestdiskManager.Query().Equals("guest_id", guest.Id)
  958. }
  959. func (guest *SGuest) DiskCount() (int, error) {
  960. return guest.GetDisksQuery().CountWithError()
  961. }
  962. func (guest *SGuest) GetSystemDisk() (*SDisk, error) {
  963. q := DiskManager.Query().Equals("disk_type", api.DISK_TYPE_SYS)
  964. gs := GuestdiskManager.Query().SubQuery()
  965. q = q.Join(gs, sqlchemy.Equals(gs.Field("disk_id"), q.Field("id"))).
  966. Filter(sqlchemy.Equals(gs.Field("guest_id"), guest.Id))
  967. count, err := q.CountWithError()
  968. if err != nil {
  969. return nil, err
  970. }
  971. if count > 1 {
  972. return nil, sqlchemy.ErrDuplicateEntry
  973. }
  974. if count == 0 {
  975. return nil, sql.ErrNoRows
  976. }
  977. disk := &SDisk{}
  978. err = q.First(disk)
  979. if err != nil {
  980. return nil, errors.Wrap(err, "q.First(disk)")
  981. }
  982. disk.SetModelManager(DiskManager, disk)
  983. return disk, nil
  984. }
  985. func (self *SGuest) GetDisks() ([]SDisk, error) {
  986. gds := GuestdiskManager.Query().SubQuery()
  987. sq := DiskManager.Query()
  988. q := sq.Join(gds, sqlchemy.Equals(gds.Field("disk_id"), sq.Field("id"))).Filter(
  989. sqlchemy.Equals(gds.Field("guest_id"), self.Id),
  990. ).Asc(gds.Field("index"))
  991. disks := []SDisk{}
  992. err := db.FetchModelObjects(DiskManager, q, &disks)
  993. if err != nil {
  994. return nil, errors.Wrapf(err, "db.FetchModelObjects")
  995. }
  996. return disks, nil
  997. }
  998. func (guest *SGuest) GetGuestDisks() ([]SGuestdisk, error) {
  999. disks := make([]SGuestdisk, 0)
  1000. q := guest.GetDisksQuery().Asc("index")
  1001. err := db.FetchModelObjects(GuestdiskManager, q, &disks)
  1002. if err != nil {
  1003. return nil, errors.Wrapf(err, "db.FetchModelObjects")
  1004. }
  1005. return disks, nil
  1006. }
  1007. func (guest *SGuest) GetGuestDisk(diskId string) *SGuestdisk {
  1008. guestdisk, err := db.NewModelObject(GuestdiskManager)
  1009. if err != nil {
  1010. log.Errorf("new guestdisk model failed: %s", err)
  1011. return nil
  1012. }
  1013. q := guest.GetDisksQuery()
  1014. err = q.Equals("disk_id", diskId).First(guestdisk)
  1015. if err != nil {
  1016. log.Errorf("GetGuestDisk error: %s", err)
  1017. return nil
  1018. }
  1019. return guestdisk.(*SGuestdisk)
  1020. }
  1021. func (guest *SGuest) GetNetworksQuery(netId string) *sqlchemy.SQuery {
  1022. q := GuestnetworkManager.Query().Equals("guest_id", guest.Id)
  1023. if len(netId) > 0 {
  1024. q = q.Equals("network_id", netId)
  1025. }
  1026. return q
  1027. }
  1028. func (guest *SGuest) NetworkCount() (int, error) {
  1029. return guest.GetNetworksQuery("").CountWithError()
  1030. }
  1031. func (guest *SGuest) GetVpc() (*SVpc, error) {
  1032. q := guest.GetNetworksQuery("")
  1033. guestnic := &SGuestnetwork{}
  1034. err := q.First(guestnic)
  1035. if err != nil {
  1036. return nil, errors.Wrapf(err, "failed getting guest network of %s(%s)", guest.Name, guest.Id)
  1037. }
  1038. guestnic.SetModelManager(GuestnetworkManager, guestnic)
  1039. network, err := guestnic.GetNetwork()
  1040. if err != nil {
  1041. return nil, errors.Wrapf(err, "GetVpc")
  1042. }
  1043. vpc, err := network.GetVpc()
  1044. if err != nil {
  1045. return nil, errors.Wrapf(err, "GetVpc")
  1046. }
  1047. return vpc, nil
  1048. }
  1049. func (guest *SGuest) IsOneCloudVpcNetwork() (bool, error) {
  1050. gns, err := guest.GetNetworks("")
  1051. if err != nil {
  1052. return false, errors.Wrap(err, "GetNetworks")
  1053. }
  1054. for _, gn := range gns {
  1055. n, _ := gn.GetNetwork()
  1056. if n != nil && n.isOneCloudVpcNetwork() {
  1057. return true, nil
  1058. }
  1059. }
  1060. return false, nil
  1061. }
  1062. func (guest *SGuest) GetNetworks(netId string) ([]SGuestnetwork, error) {
  1063. guestnics := make([]SGuestnetwork, 0)
  1064. q := guest.GetNetworksQuery(netId).Asc("index")
  1065. err := db.FetchModelObjects(GuestnetworkManager, q, &guestnics)
  1066. if err != nil {
  1067. return nil, errors.Wrapf(err, "db.FetchModelObjects")
  1068. }
  1069. return guestnics, nil
  1070. }
  1071. func (guest *SGuest) GetSlaveNetworks() ([]SGuestnetwork, error) {
  1072. guestnics := make([]SGuestnetwork, 0)
  1073. q := guest.GetNetworksQuery("").IsNotEmpty("team_with")
  1074. err := db.FetchModelObjects(GuestnetworkManager, q, &guestnics)
  1075. if err != nil {
  1076. return nil, errors.Wrapf(err, "db.FetchModelObjects")
  1077. }
  1078. return guestnics, nil
  1079. }
  1080. func (guest *SGuest) ConvertEsxiNetworks(targetGuest *SGuest) error {
  1081. gns, err := guest.GetNetworks("")
  1082. if err != nil {
  1083. return err
  1084. }
  1085. var i int
  1086. for ; i < len(gns); i++ {
  1087. _, err = db.Update(&gns[i], func() error {
  1088. gns[i].GuestId = targetGuest.Id
  1089. if gns[i].Driver != "e1000" && gns[i].Driver != "vmxnet3" {
  1090. gns[i].Driver = "e1000"
  1091. }
  1092. return nil
  1093. })
  1094. if err != nil {
  1095. log.Errorf("update guestnetworks failed %s", err)
  1096. break
  1097. }
  1098. }
  1099. if err != nil {
  1100. for j := 0; j < i; j++ {
  1101. _, err = db.Update(&gns[j], func() error {
  1102. gns[j].GuestId = guest.Id
  1103. return nil
  1104. })
  1105. if err != nil {
  1106. log.Errorf("update guestnetworks failed %s", err)
  1107. break
  1108. }
  1109. }
  1110. }
  1111. return err
  1112. }
  1113. func (guest *SGuest) getGuestnetworkByIndex(networkIndex int) (*SGuestnetwork, error) {
  1114. q := guest.GetNetworksQuery("").Equals("index", networkIndex)
  1115. guestnic := SGuestnetwork{}
  1116. err := q.First(&guestnic)
  1117. if err != nil {
  1118. return nil, err
  1119. }
  1120. guestnic.SetModelManager(GuestnetworkManager, &guestnic)
  1121. return &guestnic, nil
  1122. }
  1123. func (guest *SGuest) getGuestnetworkByIpOrMac(ipAddr string, ip6Addr string, macAddr string) (*SGuestnetwork, error) {
  1124. q := guest.GetNetworksQuery("")
  1125. if len(ipAddr) > 0 {
  1126. q = q.Equals("ip_addr", ipAddr)
  1127. }
  1128. if len(ip6Addr) > 0 {
  1129. addr, err := netutils.NewIPV6Addr(ip6Addr)
  1130. if err == nil {
  1131. q = q.Equals("ip6_addr", addr.String())
  1132. }
  1133. }
  1134. if len(macAddr) > 0 {
  1135. macAddr = netutils2.FormatMac(macAddr)
  1136. q = q.Equals("mac_addr", macAddr)
  1137. }
  1138. guestnic := SGuestnetwork{}
  1139. err := q.First(&guestnic)
  1140. if err != nil {
  1141. return nil, err
  1142. }
  1143. guestnic.SetModelManager(GuestnetworkManager, &guestnic)
  1144. return &guestnic, nil
  1145. }
  1146. func (guest *SGuest) GetGuestnetworkByIp(ipAddr string) (*SGuestnetwork, error) {
  1147. return guest.getGuestnetworkByIpOrMac(ipAddr, "", "")
  1148. }
  1149. func (guest *SGuest) GetGuestnetworkByIp6(ip6Addr string) (*SGuestnetwork, error) {
  1150. return guest.getGuestnetworkByIpOrMac("", ip6Addr, "")
  1151. }
  1152. func (guest *SGuest) GetGuestnetworkByMac(macAddr string) (*SGuestnetwork, error) {
  1153. return guest.getGuestnetworkByIpOrMac("", "", macAddr)
  1154. }
  1155. func (guest *SGuest) IsNetworkAllocated() bool {
  1156. guestnics, err := guest.GetNetworks("")
  1157. if err != nil {
  1158. return false
  1159. }
  1160. for _, gn := range guestnics {
  1161. if !gn.IsAllocated() {
  1162. return false
  1163. }
  1164. }
  1165. return true
  1166. }
  1167. func (guest *SGuest) CustomizeCreate(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data jsonutils.JSONObject) error {
  1168. optAdminSecGrpId := options.Options.GetDefaultAdminSecurityGroupId(guest.Hypervisor)
  1169. if len(guest.SecgrpId) > 0 && len(optAdminSecGrpId) > 0 {
  1170. adminSec, _ := SecurityGroupManager.FetchSecgroupById(optAdminSecGrpId)
  1171. if adminSec != nil {
  1172. guest.AdminSecgrpId = adminSec.Id
  1173. }
  1174. }
  1175. guest.HostId = ""
  1176. err := guest.SEncryptedResource.CustomizeCreate(ctx, userCred, ownerId, data, "server-"+pinyinutils.Text2Pinyin(guest.Name))
  1177. if err != nil {
  1178. return errors.Wrap(err, "EncryptResourceBase.CustomizeCreate")
  1179. }
  1180. return guest.SVirtualResourceBase.CustomizeCreate(ctx, userCred, ownerId, query, data)
  1181. }
  1182. func (guest *SGuest) GetCloudproviderId() string {
  1183. host, _ := guest.GetHost()
  1184. if host != nil {
  1185. return host.GetCloudproviderId()
  1186. }
  1187. return ""
  1188. }
  1189. func (guest *SGuest) GetHost() (*SHost, error) {
  1190. if len(guest.HostId) > 0 && regutils.MatchUUID(guest.HostId) {
  1191. host, err := HostManager.FetchById(guest.HostId)
  1192. if err != nil {
  1193. return nil, err
  1194. }
  1195. return host.(*SHost), nil
  1196. }
  1197. return nil, fmt.Errorf("empty host id")
  1198. }
  1199. func (guest *SGuest) SetHostId(userCred mcclient.TokenCredential, hostId string) error {
  1200. if guest.HostId != hostId {
  1201. diff, err := db.Update(guest, func() error {
  1202. guest.HostId = hostId
  1203. return nil
  1204. })
  1205. if err != nil {
  1206. return err
  1207. }
  1208. db.OpsLog.LogEvent(guest, db.ACT_UPDATE, diff, userCred)
  1209. }
  1210. return nil
  1211. }
  1212. func (guest *SGuest) SetHostIdWithBackup(userCred mcclient.TokenCredential, master, slave string) error {
  1213. diff, err := db.Update(guest, func() error {
  1214. guest.HostId = master
  1215. guest.BackupHostId = slave
  1216. return nil
  1217. })
  1218. if err != nil {
  1219. return err
  1220. }
  1221. db.OpsLog.LogEvent(guest, db.ACT_UPDATE, diff, userCred)
  1222. return err
  1223. }
  1224. func (guest *SGuest) UpdateCpuNumaPin(
  1225. ctx context.Context, userCred mcclient.TokenCredential,
  1226. schedCpuNumaPin []schedapi.SCpuNumaPin, cpuNumaPinTarget []api.SCpuNumaPin,
  1227. ) error {
  1228. srcSchedCpuNumaPin := make([]schedapi.SCpuNumaPin, 0)
  1229. err := guest.CpuNumaPin.Unmarshal(&srcSchedCpuNumaPin)
  1230. if err != nil {
  1231. return err
  1232. }
  1233. srcSchedCpuNumaPin = append(srcSchedCpuNumaPin, schedCpuNumaPin...)
  1234. srcCpuNumaPin := make([]api.SCpuNumaPin, 0)
  1235. cpuNumaPinStr := guest.GetMetadata(ctx, api.VM_METADATA_CPU_NUMA_PIN, nil)
  1236. cpuNumaPinJson, err := jsonutils.ParseString(cpuNumaPinStr)
  1237. if err != nil {
  1238. return err
  1239. }
  1240. err = cpuNumaPinJson.Unmarshal(&srcCpuNumaPin)
  1241. if err != nil {
  1242. return err
  1243. }
  1244. srcCpuNumaPin = append(srcCpuNumaPin, cpuNumaPinTarget...)
  1245. diff, err := db.Update(guest, func() error {
  1246. guest.CpuNumaPin = jsonutils.Marshal(srcSchedCpuNumaPin)
  1247. return nil
  1248. })
  1249. if err != nil {
  1250. return err
  1251. }
  1252. var jcpuNumaPin = jsonutils.Marshal(srcCpuNumaPin)
  1253. err = guest.SetMetadata(ctx, api.VM_METADATA_CPU_NUMA_PIN, jcpuNumaPin, userCred)
  1254. if err != nil {
  1255. return err
  1256. }
  1257. db.OpsLog.LogEvent(guest, db.ACT_UPDATE, diff, userCred)
  1258. return nil
  1259. }
  1260. func (guest *SGuest) SetCpuNumaPin(
  1261. ctx context.Context, userCred mcclient.TokenCredential,
  1262. schedCpuNumaPin []schedapi.SCpuNumaPin, cpuNumaPin []api.SCpuNumaPin,
  1263. ) error {
  1264. if cpuNumaPin == nil && schedCpuNumaPin != nil {
  1265. cpuNumaPin = make([]api.SCpuNumaPin, len(schedCpuNumaPin))
  1266. vcpuId := 0
  1267. for i := range schedCpuNumaPin {
  1268. cpuNumaPin[i] = api.SCpuNumaPin{
  1269. SizeMB: schedCpuNumaPin[i].MemSizeMB,
  1270. NodeId: schedCpuNumaPin[i].NodeId,
  1271. ExtraCpuCount: schedCpuNumaPin[i].ExtraCpuCount,
  1272. }
  1273. if len(schedCpuNumaPin[i].CpuPin) > 0 {
  1274. cpuNumaPin[i].VcpuPin = make([]api.SVCpuPin, len(schedCpuNumaPin[i].CpuPin))
  1275. for j := range schedCpuNumaPin[i].CpuPin {
  1276. cpuNumaPin[i].VcpuPin[j].Pcpu = schedCpuNumaPin[i].CpuPin[j]
  1277. cpuNumaPin[i].VcpuPin[j].Vcpu = vcpuId
  1278. vcpuId += 1
  1279. }
  1280. }
  1281. }
  1282. }
  1283. var cpuNumaPinType string
  1284. var schedCpuNumaPinJ jsonutils.JSONObject
  1285. if schedCpuNumaPin != nil {
  1286. schedCpuNumaPinJ = jsonutils.Marshal(schedCpuNumaPin)
  1287. cpuNumaPinType = api.VM_CPU_NUMA_PIN_SCHEDULER
  1288. } else if cpuNumaPin != nil {
  1289. schedCpuNumaPinJ = jsonutils.Marshal(cpuNumaPin)
  1290. }
  1291. diff, err := db.Update(guest, func() error {
  1292. guest.CpuNumaPin = schedCpuNumaPinJ
  1293. return nil
  1294. })
  1295. if err != nil {
  1296. return err
  1297. }
  1298. var jcpuNumaPin interface{} = ""
  1299. if cpuNumaPin != nil {
  1300. jcpuNumaPin = jsonutils.Marshal(cpuNumaPin)
  1301. }
  1302. metadataMap := map[string]interface{}{
  1303. api.VM_METADATA_CPU_NUMA_PIN: jcpuNumaPin,
  1304. api.VM_METADATA_CPU_NUMA_PIN_TYPE: cpuNumaPinType,
  1305. }
  1306. err = guest.SetAllMetadata(ctx, metadataMap, userCred)
  1307. if err != nil {
  1308. return err
  1309. }
  1310. db.OpsLog.LogEvent(guest, db.ACT_UPDATE, diff, userCred)
  1311. return err
  1312. }
  1313. func (guest *SGuest) ValidateResizeDisk(disk *SDisk, storage *SStorage) error {
  1314. drv, err := guest.GetDriver()
  1315. if err != nil {
  1316. return err
  1317. }
  1318. return drv.ValidateResizeDisk(guest, disk, storage)
  1319. }
  1320. func ValidateMemData(vmemSize int, driver IGuestDriver) (int, error) {
  1321. if vmemSize > 0 {
  1322. maxVmemGb := driver.GetMaxVMemSizeGB()
  1323. if vmemSize < 8 || vmemSize > maxVmemGb*1024 {
  1324. return 0, httperrors.NewInputParameterError("Memory size must be 8MB ~ %d GB", maxVmemGb)
  1325. }
  1326. }
  1327. return vmemSize, nil
  1328. }
  1329. func ValidateCpuData(vcpuCount int, driver IGuestDriver) (int, error) {
  1330. maxVcpuCount := driver.GetMaxVCpuCount()
  1331. if vcpuCount < 1 || vcpuCount > maxVcpuCount {
  1332. return 0, httperrors.NewInputParameterError("CPU core count must be 1 ~ %d", maxVcpuCount)
  1333. }
  1334. return vcpuCount, nil
  1335. }
  1336. func ValidateMemCpuData(vmemSize, vcpuCount int, hypervisor, provider string) (int, int, error) {
  1337. if len(hypervisor) == 0 {
  1338. hypervisor = api.HYPERVISOR_DEFAULT
  1339. }
  1340. driver, err := GetDriver(hypervisor, provider)
  1341. if err != nil {
  1342. return 0, 0, err
  1343. }
  1344. vmemSize, err = ValidateMemData(vmemSize, driver)
  1345. if err != nil {
  1346. return 0, 0, err
  1347. }
  1348. vcpuCount, err = ValidateCpuData(vcpuCount, driver)
  1349. if err != nil {
  1350. return 0, 0, err
  1351. }
  1352. return vmemSize, vcpuCount, nil
  1353. }
  1354. func (self *SGuest) ValidateUpdateData(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input api.ServerUpdateInput) (api.ServerUpdateInput, error) {
  1355. if len(input.Name) > 0 && len(input.Name) < 2 {
  1356. return input, httperrors.NewInputParameterError("name is too short")
  1357. }
  1358. // validate Hostname
  1359. if len(input.Hostname) > 0 {
  1360. if !regutils.MatchDomainName(input.Hostname) {
  1361. return input, httperrors.NewInputParameterError("hostname should be a legal domain name")
  1362. }
  1363. }
  1364. // 避免调度失败的机器修改删除保护时报no rows in result set 错误,导致前端删不掉机器
  1365. if len(self.HostId) > 0 {
  1366. drv, err := self.GetDriver()
  1367. if err != nil {
  1368. return input, err
  1369. }
  1370. input, err = drv.ValidateUpdateData(ctx, self, userCred, input)
  1371. if err != nil {
  1372. return input, errors.Wrap(err, "GetDriver().ValidateUpdateData")
  1373. }
  1374. }
  1375. var err error
  1376. input.VirtualResourceBaseUpdateInput, err = self.SVirtualResourceBase.ValidateUpdateData(ctx, userCred, query, input.VirtualResourceBaseUpdateInput)
  1377. if err != nil {
  1378. return input, errors.Wrap(err, "SVirtualResourceBase.ValidateUpdateData")
  1379. }
  1380. return input, nil
  1381. }
  1382. func serverCreateInput2ComputeQuotaKeys(input api.ServerCreateInput, ownerId mcclient.IIdentityProvider) (SComputeResourceKeys, error) {
  1383. var keys SComputeResourceKeys
  1384. if len(input.PreferHost) > 0 {
  1385. hostObj, err := HostManager.FetchById(input.PreferHost)
  1386. if err != nil {
  1387. return keys, err
  1388. }
  1389. host := hostObj.(*SHost)
  1390. input.PreferZone = host.ZoneId
  1391. keys.ZoneId = host.ZoneId
  1392. }
  1393. if len(input.PreferWire) > 0 {
  1394. wireObj, err := WireManager.FetchById(input.PreferWire)
  1395. if err != nil {
  1396. return keys, err
  1397. }
  1398. wire := wireObj.(*SWire)
  1399. if len(wire.ZoneId) > 0 {
  1400. input.PreferZone = wire.ZoneId
  1401. keys.ZoneId = wire.ZoneId
  1402. }
  1403. }
  1404. if len(input.PreferZone) > 0 {
  1405. zoneObj, err := ZoneManager.FetchById(input.PreferZone)
  1406. if err != nil {
  1407. return keys, err
  1408. }
  1409. zone := zoneObj.(*SZone)
  1410. input.PreferRegion = zone.CloudregionId
  1411. keys.ZoneId = zone.Id
  1412. keys.RegionId = zone.CloudregionId
  1413. }
  1414. if len(input.PreferRegion) > 0 {
  1415. regionObj, err := CloudregionManager.FetchById(input.PreferRegion)
  1416. if err != nil {
  1417. return keys, err
  1418. }
  1419. region := regionObj.(*SCloudregion)
  1420. keys.RegionId = region.GetId()
  1421. keys.Brand = region.Provider
  1422. }
  1423. return keys, nil
  1424. }
  1425. func (manager *SGuestManager) BatchPreValidate(
  1426. ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider,
  1427. query jsonutils.JSONObject, data *jsonutils.JSONDict, count int,
  1428. ) error {
  1429. input, err := manager.validateCreateData(ctx, userCred, ownerId, query, data)
  1430. if err != nil {
  1431. return errors.Wrap(err, "manager.validateCreateData")
  1432. }
  1433. if input.IsSystem == nil || !(*input.IsSystem) {
  1434. err := manager.checkCreateQuota(ctx, userCred, ownerId, *input, input.Backup, count)
  1435. if err != nil {
  1436. return errors.Wrap(err, "manager.checkCreateQuota")
  1437. }
  1438. }
  1439. return nil
  1440. }
  1441. func parseInstanceSnapshot(ctx context.Context, input *api.ServerCreateInput) (*api.ServerCreateInput, error) {
  1442. ispi, err := InstanceSnapshotManager.FetchByIdOrName(ctx, nil, input.InstanceSnapshotId)
  1443. if err == sql.ErrNoRows {
  1444. return nil, httperrors.NewBadRequestError("can't find instance snapshot %s", input.InstanceSnapshotId)
  1445. }
  1446. if err != nil {
  1447. return nil, httperrors.NewInternalServerError("fetch instance snapshot error %s", err)
  1448. }
  1449. isp := ispi.(*SInstanceSnapshot)
  1450. if isp.Status != api.INSTANCE_SNAPSHOT_READY {
  1451. return nil, httperrors.NewBadRequestError("Instance snapshot not ready")
  1452. }
  1453. input, err = isp.ToInstanceCreateInput(input)
  1454. if len(input.Disks) == 0 {
  1455. return nil, httperrors.NewInputParameterError("there are no disks in this instance snapshot, try another one")
  1456. }
  1457. return input, nil
  1458. }
  1459. func parseInstanceBackup(ctx context.Context, input *api.ServerCreateInput) (*api.ServerCreateInput, error) {
  1460. ispi, err := InstanceBackupManager.FetchByIdOrName(ctx, nil, input.InstanceBackupId)
  1461. if err == sql.ErrNoRows {
  1462. return nil, httperrors.NewBadRequestError("can't find instance backup %s", input.InstanceBackupId)
  1463. }
  1464. if err != nil {
  1465. return nil, httperrors.NewInternalServerError("fetch instance backup error %s", err)
  1466. }
  1467. isp := ispi.(*SInstanceBackup)
  1468. if isp.Status != api.INSTANCE_BACKUP_STATUS_READY && isp.Status != api.INSTANCE_BACKUP_STATUS_RECOVERY {
  1469. return nil, httperrors.NewBadRequestError("Instance backup not ready")
  1470. }
  1471. input, err = isp.ToInstanceCreateInput(input)
  1472. if len(input.Disks) == 0 {
  1473. return nil, httperrors.NewInputParameterError("there are no disks in this instance backup, try another one")
  1474. }
  1475. return input, nil
  1476. }
  1477. func (manager *SGuestManager) ExpandBatchCreateData(
  1478. ctx context.Context,
  1479. userCred mcclient.TokenCredential,
  1480. ownerId mcclient.IIdentityProvider,
  1481. query jsonutils.JSONObject,
  1482. data *jsonutils.JSONDict,
  1483. index int,
  1484. ) (*api.ServerCreateInput, error) {
  1485. input, err := cmdline.FetchServerCreateInputByJSON(data)
  1486. if err != nil {
  1487. return nil, err
  1488. }
  1489. for i := range input.Networks {
  1490. if index < len(input.Networks[i].Macs) {
  1491. input.Networks[i].Mac = input.Networks[i].Macs[index]
  1492. }
  1493. if index < len(input.Networks[i].Addresses) {
  1494. input.Networks[i].Address = input.Networks[i].Addresses[index]
  1495. }
  1496. if index < len(input.Networks[i].Addresses6) {
  1497. input.Networks[i].Address6 = input.Networks[i].Addresses6[index]
  1498. }
  1499. }
  1500. log.Debugf("ExpandBatchCreateData %s", jsonutils.Marshal(input))
  1501. return input, nil
  1502. }
  1503. func (manager *SGuestManager) validateCreateData(
  1504. ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider,
  1505. query jsonutils.JSONObject, data *jsonutils.JSONDict) (*api.ServerCreateInput, error) {
  1506. // TODO: 定义 api.ServerCreateInput 的 Unmarshal 函数,直接通过 data.Unmarshal(input) 解析参数
  1507. input, err := cmdline.FetchServerCreateInputByJSON(data)
  1508. if err != nil {
  1509. return nil, err
  1510. }
  1511. if len(input.Metadata) > 20 {
  1512. return nil, httperrors.NewInputParameterError("metdata must less then 20")
  1513. }
  1514. if len(input.InstanceSnapshotId) > 0 {
  1515. inputMem := input.VmemSize
  1516. inputCpu := input.VcpuCount
  1517. inputInstaceType := input.InstanceType
  1518. input, err = parseInstanceSnapshot(ctx, input)
  1519. if err != nil {
  1520. return nil, err
  1521. }
  1522. // keep input cpu mem flavor
  1523. if inputMem > 0 {
  1524. input.VmemSize = inputMem
  1525. }
  1526. if inputMem > 0 {
  1527. input.VcpuCount = inputCpu
  1528. }
  1529. if len(inputInstaceType) > 0 {
  1530. input.InstanceType = inputInstaceType
  1531. }
  1532. } else if len(input.InstanceBackupId) > 0 {
  1533. inputMem := input.VmemSize
  1534. inputCpu := input.VcpuCount
  1535. inputInstaceType := input.InstanceType
  1536. input, err = parseInstanceBackup(ctx, input)
  1537. if err != nil {
  1538. return nil, err
  1539. }
  1540. // keep input cpu mem flavor
  1541. if inputMem > 0 {
  1542. input.VmemSize = inputMem
  1543. }
  1544. if inputMem > 0 {
  1545. input.VcpuCount = inputCpu
  1546. }
  1547. if len(inputInstaceType) > 0 {
  1548. input.InstanceType = inputInstaceType
  1549. }
  1550. }
  1551. resetPassword := true
  1552. if input.ResetPassword != nil {
  1553. resetPassword = *input.ResetPassword
  1554. }
  1555. passwd := input.Password
  1556. if len(passwd) > 0 {
  1557. err = seclib2.ValidatePassword(passwd)
  1558. if err != nil {
  1559. return nil, err
  1560. }
  1561. resetPassword = true
  1562. input.ResetPassword = &resetPassword
  1563. }
  1564. if resetPassword && len(input.LoginAccount) > 0 {
  1565. if len(input.LoginAccount) > 32 {
  1566. return nil, httperrors.NewInputParameterError("login_account is longer than 32 chars")
  1567. }
  1568. if err := manager.ValidateNameLoginAccount(input.LoginAccount); err != nil {
  1569. return nil, err
  1570. }
  1571. }
  1572. // check group
  1573. if len(input.InstanceGroupIds) > 0 {
  1574. newGroupIds := make([]string, len(input.InstanceGroupIds))
  1575. for index, id := range input.InstanceGroupIds {
  1576. model, err := GroupManager.FetchByIdOrName(ctx, userCred, id)
  1577. if err != nil {
  1578. return nil, httperrors.NewResourceNotFoundError("no such group %s", id)
  1579. }
  1580. newGroupIds[index] = model.GetId()
  1581. }
  1582. // list of id or name ==> ids
  1583. input.InstanceGroupIds = newGroupIds
  1584. }
  1585. // check that all image of disk is the part of guest imgae, if use guest image to create guest
  1586. err = manager.checkGuestImage(ctx, input)
  1587. if err != nil {
  1588. return nil, errors.Wrap(err, "checkGuestImage")
  1589. }
  1590. if len(input.PreferManager) > 0 && len(input.Provider) == 0 {
  1591. providerObj, err := CloudproviderManager.FetchById(input.PreferManager)
  1592. if err != nil {
  1593. return nil, errors.Wrapf(err, "zone fetch by id %s", input.PreferZone)
  1594. }
  1595. provider := providerObj.(*SCloudprovider)
  1596. input.Provider = provider.Provider
  1597. }
  1598. if len(input.PreferZone) > 0 && len(input.Provider) == 0 {
  1599. zoneObj, err := ZoneManager.FetchById(input.PreferZone)
  1600. if err != nil {
  1601. return nil, errors.Wrapf(err, "zone fetch by id %s", input.PreferZone)
  1602. }
  1603. zone := zoneObj.(*SZone)
  1604. input.PreferRegion = zone.CloudregionId
  1605. }
  1606. if len(input.PreferRegion) > 0 && len(input.Provider) == 0 {
  1607. regionObj, err := CloudregionManager.FetchById(input.PreferRegion)
  1608. if err != nil {
  1609. return nil, errors.Wrapf(err, "region fetch by id %s", input.PreferRegion)
  1610. }
  1611. region := regionObj.(*SCloudregion)
  1612. input.Provider = region.Provider
  1613. }
  1614. if len(input.Provider) == 0 {
  1615. input.Provider = api.CLOUD_PROVIDER_ONECLOUD
  1616. }
  1617. var hypervisor string
  1618. // var rootStorageType string
  1619. var osProf osprofile.SOSProfile
  1620. hypervisor = input.Hypervisor
  1621. if hypervisor != api.HYPERVISOR_POD {
  1622. if len(input.Disks) == 0 && input.Cdrom == "" {
  1623. return nil, httperrors.NewInputParameterError("No bootable disk information provided")
  1624. }
  1625. var imgProperties map[string]string
  1626. var imgEncryptKeyId string
  1627. var imageDiskFormat string
  1628. if len(input.Disks) > 0 {
  1629. diskConfig := input.Disks[0]
  1630. diskConfig, err = parseDiskInfo(ctx, userCred, diskConfig)
  1631. if err != nil {
  1632. return nil, httperrors.NewInputParameterError("Invalid root image: %s", err)
  1633. }
  1634. input.Disks[0] = diskConfig
  1635. imgEncryptKeyId = diskConfig.ImageEncryptKeyId
  1636. imgProperties = diskConfig.ImageProperties
  1637. imageDiskFormat = imgProperties[imageapi.IMAGE_DISK_FORMAT]
  1638. if imgProperties[imageapi.IMAGE_DISK_FORMAT] == "iso" {
  1639. return nil, httperrors.NewInputParameterError("System disk does not support iso image, please consider using cdrom parameter")
  1640. }
  1641. }
  1642. if input.Cdrom != "" {
  1643. cdromStr := input.Cdrom
  1644. image, err := parseIsoInfo(ctx, userCred, cdromStr)
  1645. if err != nil {
  1646. return nil, httperrors.NewInputParameterError("parse cdrom device info error %s", err)
  1647. }
  1648. input.Cdrom = image.Id
  1649. imageDiskFormat = image.DiskFormat
  1650. if len(imgProperties) == 0 {
  1651. imgProperties = image.Properties
  1652. }
  1653. }
  1654. // check boot indexes
  1655. bm := bitmap.NewBitMap(128)
  1656. if input.CdromBootIndex != nil && *input.CdromBootIndex >= 0 {
  1657. bm.Set(int64(*input.CdromBootIndex))
  1658. }
  1659. for i := 0; i < len(input.Disks); i++ {
  1660. if input.Disks[i].BootIndex != nil && *input.Disks[i].BootIndex >= 0 {
  1661. if bm.Has(int64(*input.Disks[i].BootIndex)) {
  1662. return nil, httperrors.NewInputParameterError("duplicate boot index %d", *input.Disks[i].BootIndex)
  1663. }
  1664. bm.Set(int64(*input.Disks[i].BootIndex))
  1665. }
  1666. }
  1667. arch := imgProperties["os_arch"]
  1668. if strings.Contains(arch, "aarch") || strings.Contains(arch, "arm") {
  1669. input.OsArch = apis.OS_ARCH_AARCH64
  1670. } else if strings.Contains(arch, "riscv") {
  1671. input.OsArch = apis.OS_ARCH_RISCV64
  1672. }
  1673. // enable tpm on windows 11 image
  1674. osDist := imgProperties["os_distribution"]
  1675. osVer := imgProperties["os_version"]
  1676. if strings.Contains(osDist, "Windows 11") || strings.Contains(osVer, "Windows 11") {
  1677. input.EnableTpm = true
  1678. }
  1679. // use uefi boot and q35 machine type on enable tpm
  1680. if input.EnableTpm {
  1681. input.Bios = "UEFI"
  1682. input.Machine = api.VM_MACHINE_TYPE_Q35
  1683. }
  1684. if imageDiskFormat != imageapi.IMAGE_DISK_FORMAT_ISO {
  1685. var imgSupportUEFI *bool
  1686. var imgSupportBIOS *bool
  1687. if desc, ok := imgProperties[imageapi.IMAGE_UEFI_SUPPORT]; ok {
  1688. support := desc == "true"
  1689. imgSupportUEFI = &support
  1690. }
  1691. if biosDesc, ok := imgProperties[imageapi.IMAGE_BIOS_SUPPORT]; ok {
  1692. supportBIOS := biosDesc == "true"
  1693. imgSupportBIOS = &supportBIOS
  1694. }
  1695. // uefi is not support set default support bios
  1696. if imgSupportUEFI == nil || !*imgSupportUEFI {
  1697. supportBIOS := true
  1698. imgSupportBIOS = &supportBIOS
  1699. }
  1700. if apis.IsARM(input.OsArch) || apis.IsRISCV(input.OsArch) {
  1701. // arm image supports UEFI by default
  1702. support := true
  1703. imgSupportUEFI = &support
  1704. }
  1705. switch input.Bios {
  1706. case "UEFI":
  1707. if imgSupportUEFI == nil || !*imgSupportUEFI {
  1708. return nil, httperrors.NewInputParameterError("UEFI boot mode requires UEFI image")
  1709. }
  1710. case "BIOS":
  1711. if imgSupportBIOS == nil || !*imgSupportBIOS {
  1712. return nil, httperrors.NewInputParameterError("BIOS boot mode requires BIOS image")
  1713. }
  1714. default:
  1715. if imgSupportUEFI != nil && *imgSupportUEFI {
  1716. input.Bios = "UEFI"
  1717. } else {
  1718. input.Bios = "BIOS"
  1719. }
  1720. }
  1721. } else {
  1722. if input.Bios == "" {
  1723. // if ISO support uefi and not specified boot mode
  1724. // set default boot mode uefi
  1725. if desc, ok := imgProperties[imageapi.IMAGE_UEFI_SUPPORT]; ok && desc == "true" {
  1726. input.Bios = "UEFI"
  1727. }
  1728. }
  1729. }
  1730. if len(imgProperties) == 0 {
  1731. imgProperties = map[string]string{"os_type": "Linux"}
  1732. }
  1733. input.DisableUsbKbd = imgProperties[imageapi.IMAGE_DISABLE_USB_KBD] == "true"
  1734. imgIsWindows := imgProperties[imageapi.IMAGE_OS_TYPE] == "Windows"
  1735. hasGpuVga := func() bool {
  1736. for i := 0; i < len(input.IsolatedDevices); i++ {
  1737. if input.IsolatedDevices[i].DevType == api.GPU_VGA_TYPE {
  1738. return true
  1739. }
  1740. }
  1741. return false
  1742. }()
  1743. if imgIsWindows && hasGpuVga && input.Bios != "UEFI" {
  1744. return nil, httperrors.NewInputParameterError("Windows use gpu vga requires UEFI image")
  1745. }
  1746. if vdi, ok := imgProperties[imageapi.IMAGE_VDI_PROTOCOL]; ok && len(vdi) > 0 && len(input.Vdi) == 0 {
  1747. input.Vdi = vdi
  1748. }
  1749. if input.EncryptKeyId == nil && len(imgEncryptKeyId) > 0 {
  1750. input.EncryptKeyId = &imgEncryptKeyId
  1751. }
  1752. if input.EncryptKeyId != nil || input.EncryptKeyNew != nil {
  1753. input.EncryptedResourceCreateInput, err = manager.SEncryptedResourceManager.ValidateCreateData(ctx, userCred, ownerId, query, input.EncryptedResourceCreateInput)
  1754. if err != nil {
  1755. return nil, errors.Wrap(err, "SEncryptedResourceManager.ValidateCreateData")
  1756. }
  1757. if len(imgEncryptKeyId) > 0 {
  1758. if imgEncryptKeyId != *input.EncryptKeyId {
  1759. return nil, errors.Wrap(httperrors.ErrConflict, "encryption key inconsist with image")
  1760. }
  1761. }
  1762. }
  1763. osType := input.OsType
  1764. osProf, err = osprofile.GetOSProfileFromImageProperties(imgProperties, hypervisor)
  1765. if err != nil {
  1766. return nil, httperrors.NewInputParameterError("Invalid root image: %s", err)
  1767. }
  1768. if len(osProf.Hypervisor) > 0 && len(hypervisor) == 0 {
  1769. hypervisor = osProf.Hypervisor
  1770. input.Hypervisor = hypervisor
  1771. }
  1772. if len(osProf.OSType) > 0 && len(osType) == 0 {
  1773. osType = osProf.OSType
  1774. input.OsType = osType
  1775. }
  1776. input.OsProfile = jsonutils.Marshal(osProf)
  1777. }
  1778. input, err = ValidateScheduleCreateData(ctx, userCred, input, hypervisor)
  1779. if err != nil {
  1780. return nil, err
  1781. }
  1782. optionSystemHypervisor := []string{api.HYPERVISOR_KVM, api.HYPERVISOR_ESXI, api.HYPERVISOR_POD}
  1783. if !utils.IsInStringArray(input.Hypervisor, optionSystemHypervisor) && len(input.Disks[0].ImageId) == 0 && len(input.Disks[0].SnapshotId) == 0 && input.Cdrom == "" {
  1784. return nil, httperrors.NewBadRequestError("Miss operating system???")
  1785. }
  1786. if input.Hypervisor == api.HYPERVISOR_KVM {
  1787. if input.IsDaemon == nil && options.Options.SetKVMServerAsDaemonOnCreate {
  1788. setDaemon := true
  1789. input.IsDaemon = &setDaemon
  1790. }
  1791. }
  1792. hypervisor = input.Hypervisor
  1793. driver, err := GetDriver(hypervisor, input.Provider)
  1794. if err != nil {
  1795. return nil, err
  1796. }
  1797. if hypervisor != api.HYPERVISOR_POD {
  1798. // support sku here
  1799. var sku *SServerSku
  1800. skuName := input.InstanceType
  1801. if len(skuName) > 0 {
  1802. sku, err = ServerSkuManager.FetchSkuByNameAndProvider(skuName, input.Provider, true)
  1803. if err != nil {
  1804. return nil, err
  1805. }
  1806. input.InstanceType = sku.Name
  1807. input.VmemSize = sku.MemorySizeMB
  1808. input.VcpuCount = sku.CpuCoreCount
  1809. } else {
  1810. vmemSize, vcpuCount, err := ValidateMemCpuData(input.VmemSize, input.VcpuCount, input.Hypervisor, input.Provider)
  1811. if err != nil {
  1812. return nil, err
  1813. }
  1814. if vmemSize == 0 {
  1815. return nil, httperrors.NewMissingParameterError("vmem_size")
  1816. }
  1817. if vcpuCount == 0 {
  1818. vcpuCount = 1
  1819. }
  1820. input.VmemSize = vmemSize
  1821. input.VcpuCount = vcpuCount
  1822. }
  1823. dataDiskDefs := []*api.DiskConfig{}
  1824. if sku != nil && sku.AttachedDiskCount > 0 {
  1825. if sku.AttachedDiskSizeGB == 0 {
  1826. return nil, httperrors.NewInputParameterError("sku %s not indicate attached disk size", sku.Name)
  1827. }
  1828. if len(sku.AttachedDiskType) == 0 {
  1829. return nil, httperrors.NewInputParameterError("sku %s not indicate attached disk backend", sku.Name)
  1830. }
  1831. for i := 0; i < sku.AttachedDiskCount; i += 1 {
  1832. dataDisk := &api.DiskConfig{
  1833. SizeMb: sku.AttachedDiskSizeGB * 1024,
  1834. Backend: strings.ToLower(sku.AttachedDiskType),
  1835. }
  1836. dataDiskDefs = append(dataDiskDefs, dataDisk)
  1837. }
  1838. }
  1839. // start from data disk
  1840. disks := input.Disks
  1841. for idx := 1; idx < len(disks); idx += 1 {
  1842. dataDiskDefs = append(dataDiskDefs, disks[idx])
  1843. }
  1844. rootDiskConfig, err := parseDiskInfo(ctx, userCred, disks[0])
  1845. if err != nil {
  1846. return nil, httperrors.NewGeneralError(err) // should no error
  1847. }
  1848. // validate root disk config
  1849. {
  1850. if rootDiskConfig.NVMEDevice != nil {
  1851. return nil, httperrors.NewBadRequestError("NVMe device can't assign as root disk")
  1852. }
  1853. if input.ResourceType != api.HostResourceTypePrepaidRecycle {
  1854. if len(rootDiskConfig.Backend) == 0 {
  1855. defaultStorageType, _ := data.GetString("default_storage_type")
  1856. if len(defaultStorageType) > 0 {
  1857. rootDiskConfig.Backend = defaultStorageType
  1858. } else {
  1859. rootDiskConfig.Backend = driver.GetDefaultSysDiskBackend()
  1860. }
  1861. }
  1862. sysMinDiskMB := driver.GetMinimalSysDiskSizeGb() * 1024
  1863. if rootDiskConfig.SizeMb != api.DISK_SIZE_AUTOEXTEND && rootDiskConfig.SizeMb < sysMinDiskMB {
  1864. rootDiskConfig.SizeMb = sysMinDiskMB
  1865. }
  1866. }
  1867. if len(rootDiskConfig.Driver) == 0 {
  1868. rootDiskConfig.Driver = osProf.DiskDriver
  1869. }
  1870. log.Debugf("ROOT DISK: %#v", rootDiskConfig)
  1871. input.Disks[0] = rootDiskConfig
  1872. if sku != nil {
  1873. if len(rootDiskConfig.OsArch) > 0 && len(sku.CpuArch) > 0 {
  1874. if !strings.Contains(rootDiskConfig.OsArch, sku.CpuArch) {
  1875. return nil, httperrors.NewConflictError("root disk image(%s) and sku(%s) architecture mismatch", rootDiskConfig.OsArch, sku.CpuArch)
  1876. }
  1877. }
  1878. }
  1879. }
  1880. for i := 0; i < len(dataDiskDefs); i += 1 {
  1881. diskConfig, err := parseDiskInfo(ctx, userCred, dataDiskDefs[i])
  1882. if err != nil {
  1883. return nil, httperrors.NewInputParameterError("parse disk description error %s", err)
  1884. }
  1885. if diskConfig.DiskType == api.DISK_TYPE_SYS {
  1886. log.Warningf("Snapshot error: disk index %d > 0 but disk type is %s", i+1, api.DISK_TYPE_SYS)
  1887. diskConfig.DiskType = api.DISK_TYPE_DATA
  1888. }
  1889. if len(diskConfig.Backend) == 0 {
  1890. diskConfig.Backend = rootDiskConfig.Backend
  1891. }
  1892. if len(diskConfig.Driver) == 0 {
  1893. diskConfig.Driver = osProf.DiskDriver
  1894. }
  1895. if diskConfig.NVMEDevice != nil {
  1896. if input.Backup {
  1897. return nil, httperrors.NewBadRequestError("Cannot create backup with isolated device")
  1898. }
  1899. devConfig, err := IsolatedDeviceManager.parseDeviceInfo(userCred, diskConfig.NVMEDevice)
  1900. if err != nil {
  1901. return nil, httperrors.NewInputParameterError("parse isolated device description error %s", err)
  1902. }
  1903. err = IsolatedDeviceManager.isValidNVMEDeviceInfo(devConfig)
  1904. if err != nil {
  1905. return nil, err
  1906. }
  1907. diskConfig.NVMEDevice = devConfig
  1908. diskConfig.Driver = api.DISK_DRIVER_VFIO
  1909. diskConfig.Backend = api.STORAGE_NVME_PT
  1910. }
  1911. input.Disks[i+1] = diskConfig
  1912. }
  1913. if len(input.Duration) > 0 {
  1914. if input.ResourceType == api.HostResourceTypePrepaidRecycle {
  1915. return nil, httperrors.NewConflictError("cannot create prepaid server on prepaid resource type")
  1916. }
  1917. billingCycle, err := billing.ParseBillingCycle(input.Duration)
  1918. if err != nil {
  1919. return nil, httperrors.NewInputParameterError("invalid duration %s", input.Duration)
  1920. }
  1921. if input.BillingType == billing_api.BILLING_TYPE_POSTPAID {
  1922. if !driver.IsSupportPostpaidExpire() {
  1923. return nil, httperrors.NewBadRequestError("guest %s unsupport postpaid expire", hypervisor)
  1924. }
  1925. } else {
  1926. if !driver.IsSupportedBillingCycle(billingCycle) {
  1927. return nil, httperrors.NewInputParameterError("unsupported duration %s", input.Duration)
  1928. }
  1929. }
  1930. if len(input.BillingType) == 0 {
  1931. input.BillingType = billing_api.BILLING_TYPE_PREPAID
  1932. }
  1933. input.BillingCycle = billingCycle.String()
  1934. input.Duration = billingCycle.String()
  1935. if input.BillingType == billing_api.BILLING_TYPE_POSTPAID {
  1936. input.ReleaseAt = billingCycle.EndAt(time.Now())
  1937. }
  1938. }
  1939. }
  1940. // HACK: if input networks is empty, add one random network config
  1941. if len(input.Networks) == 0 {
  1942. input.Networks = append(input.Networks, &api.NetworkConfig{Exit: false})
  1943. }
  1944. netArray := input.Networks
  1945. defaultGwCnt := 0
  1946. firstExit := -1
  1947. for idx := 0; idx < len(netArray); idx += 1 {
  1948. netConfig, err := parseNetworkInfo(ctx, userCred, netArray[idx])
  1949. if err != nil {
  1950. return nil, httperrors.NewInputParameterError("parse network description error %s", err)
  1951. }
  1952. err = isValidNetworkInfo(ctx, userCred, netConfig, "", "")
  1953. if err != nil {
  1954. return nil, err
  1955. }
  1956. if len(netConfig.Driver) == 0 {
  1957. netConfig.Driver = osProf.NetDriver
  1958. }
  1959. if netConfig.SriovDevice != nil {
  1960. if input.Backup {
  1961. return nil, httperrors.NewBadRequestError("Cannot create backup with isolated device")
  1962. }
  1963. devConfig, err := IsolatedDeviceManager.parseDeviceInfo(userCred, netConfig.SriovDevice)
  1964. if err != nil {
  1965. return nil, httperrors.NewInputParameterError("parse isolated device description error %s", err)
  1966. }
  1967. err = IsolatedDeviceManager.isValidNicDeviceInfo(devConfig)
  1968. if err != nil {
  1969. return nil, err
  1970. }
  1971. netConfig.SriovDevice = devConfig
  1972. netConfig.Driver = api.NETWORK_DRIVER_VFIO
  1973. }
  1974. secgroupIds, err := isValidSecgroups(ctx, userCred, netConfig.Secgroups)
  1975. if err != nil {
  1976. return nil, err
  1977. }
  1978. netConfig.Secgroups = secgroupIds
  1979. netConfig.Project = ownerId.GetProjectId()
  1980. netConfig.Domain = ownerId.GetProjectDomainId()
  1981. if netConfig.IsDefault {
  1982. defaultGwCnt++
  1983. }
  1984. if firstExit < 0 && netConfig.Exit {
  1985. firstExit = idx
  1986. }
  1987. input.Networks[idx] = netConfig
  1988. }
  1989. // check default gateway
  1990. if defaultGwCnt == 0 {
  1991. defIdx := 0
  1992. if firstExit >= 0 {
  1993. // there is a exit network, make it the default
  1994. defIdx = firstExit
  1995. }
  1996. // make the first nic as default
  1997. input.Networks[defIdx].IsDefault = true
  1998. } else if defaultGwCnt > 1 {
  1999. return nil, errors.Wrapf(httperrors.ErrInputParameter, "more than 1 nic(%d) assigned as default gateway", defaultGwCnt)
  2000. }
  2001. isoDevArray := input.IsolatedDevices
  2002. for idx := 0; idx < len(isoDevArray); idx += 1 { // .Contains(fmt.Sprintf("isolated_device.%d", idx)); idx += 1 {
  2003. if input.Backup {
  2004. return nil, httperrors.NewBadRequestError("Cannot create backup with isolated device")
  2005. }
  2006. devConfig, err := IsolatedDeviceManager.parseDeviceInfo(userCred, isoDevArray[idx])
  2007. if err != nil {
  2008. return nil, httperrors.NewInputParameterError("parse isolated device description error %s", err)
  2009. }
  2010. err = IsolatedDeviceManager.isValidDeviceInfo(devConfig)
  2011. if err != nil {
  2012. return nil, err
  2013. }
  2014. input.IsolatedDevices[idx] = devConfig
  2015. }
  2016. nvidiaVgpuCnt := 0
  2017. gpuCnt := 0
  2018. for i := 0; i < len(input.IsolatedDevices); i++ {
  2019. if input.IsolatedDevices[i].DevType == api.LEGACY_VGPU_TYPE {
  2020. nvidiaVgpuCnt += 1
  2021. } else if utils.IsInStringArray(input.IsolatedDevices[i].DevType, api.VALID_GPU_TYPES) {
  2022. gpuCnt += 1
  2023. }
  2024. }
  2025. if nvidiaVgpuCnt > 1 {
  2026. return nil, httperrors.NewBadRequestError("Nvidia vgpu count exceed > 1")
  2027. }
  2028. if nvidiaVgpuCnt > 0 && gpuCnt > 0 {
  2029. return nil, httperrors.NewBadRequestError("Nvidia vgpu can't passthrough with other gpus")
  2030. }
  2031. keypairId := input.KeypairId
  2032. if len(keypairId) > 0 {
  2033. keypairObj, err := KeypairManager.FetchByIdOrName(ctx, userCred, keypairId)
  2034. if err != nil {
  2035. return nil, httperrors.NewResourceNotFoundError("Keypair %s not found", keypairId)
  2036. }
  2037. input.KeypairId = keypairObj.GetId()
  2038. }
  2039. secGrpIds, err := isValidSecgroups(ctx, userCred, input.Secgroups)
  2040. if err != nil {
  2041. return nil, err
  2042. }
  2043. if len(secGrpIds) > 0 {
  2044. input.SecgroupId = secGrpIds[0]
  2045. input.Secgroups = secGrpIds[1:]
  2046. } else if input.SecgroupId != "" {
  2047. secGrpId := input.SecgroupId
  2048. secGrpObj, err := SecurityGroupManager.FetchByIdOrName(ctx, userCred, secGrpId)
  2049. if err != nil {
  2050. return nil, httperrors.NewResourceNotFoundError("Secgroup %s not found", secGrpId)
  2051. }
  2052. input.SecgroupId = secGrpObj.GetId()
  2053. } else {
  2054. input.SecgroupId = options.Options.GetDefaultSecurityGroupId(hypervisor)
  2055. }
  2056. maxSecgrpCount := driver.GetMaxSecurityGroupCount()
  2057. if maxSecgrpCount == 0 { //esxi 不支持安全组
  2058. input.SecgroupId = ""
  2059. input.Secgroups = []string{}
  2060. } else if len(input.Secgroups)+1 > maxSecgrpCount {
  2061. return nil, httperrors.NewInputParameterError("%s shall bind up to %d security groups", hypervisor, maxSecgrpCount)
  2062. }
  2063. preferRegionId, _ := data.GetString("prefer_region_id")
  2064. if err := manager.validateEip(ctx, userCred, input, preferRegionId, input.PreferManager); err != nil {
  2065. return nil, err
  2066. }
  2067. /*
  2068. TODO
  2069. group
  2070. for idx := 0; data.Contains(fmt.Sprintf("srvtag.%d", idx)); idx += 1 {
  2071. }*/
  2072. if input.ResourceType != api.HostResourceTypePrepaidRecycle {
  2073. input, err = driver.ValidateCreateData(ctx, userCred, input)
  2074. if err != nil {
  2075. return nil, err
  2076. }
  2077. }
  2078. input.VirtualResourceCreateInput, err = manager.SVirtualResourceBaseManager.ValidateCreateData(ctx, userCred, ownerId, query, input.VirtualResourceCreateInput)
  2079. if err != nil {
  2080. return nil, err
  2081. }
  2082. name := input.Name
  2083. if len(name) == 0 {
  2084. name = input.GenerateName
  2085. }
  2086. input.HostnameInput, err = manager.SHostnameResourceBaseManager.ValidateHostname(name, input.OsType, input.HostnameInput)
  2087. if err != nil {
  2088. return nil, err
  2089. }
  2090. // validate UserData
  2091. if err := userdata.ValidateUserdata(input.UserData, input.OsType); err != nil {
  2092. return nil, httperrors.NewInputParameterError("Invalid userdata: %v", err)
  2093. }
  2094. // validate KickstartConfig
  2095. if input.KickstartConfig != nil && input.KickstartConfig.IsEnabled() {
  2096. if err := validateKickstartConfig(input.KickstartConfig); err != nil {
  2097. return nil, httperrors.NewInputParameterError("Invalid kickstart config: %v", err)
  2098. }
  2099. }
  2100. err = manager.ValidatePolicyDefinitions(ctx, userCred, ownerId, query, input)
  2101. if err != nil {
  2102. return nil, err
  2103. }
  2104. input.ProjectId = ownerId.GetProjectId()
  2105. input.ProjectDomainId = ownerId.GetProjectDomainId()
  2106. return input, nil
  2107. }
  2108. func (manager *SGuestManager) ValidatePolicyDefinitions(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, input *api.ServerCreateInput) error {
  2109. definitions, err := PolicyDefinitionManager.GetAvailablePolicyDefinitions(ctx, userCred)
  2110. if err != nil {
  2111. return httperrors.NewGeneralError(err)
  2112. }
  2113. for i := range definitions {
  2114. switch definitions[i].Category {
  2115. case api.POLICY_DEFINITION_CATEGORY_CLOUDREGION:
  2116. if len(input.PreferRegion) == 0 {
  2117. return httperrors.NewMissingParameterError(fmt.Sprintf("policy definition %s require prefer_region_id parameter", definitions[i].Name))
  2118. }
  2119. if definitions[i].Parameters == nil {
  2120. return httperrors.NewPolicyDefinitionError("invalid parameters for policy definition %s", definitions[i].Name)
  2121. }
  2122. regionDefinitions := api.SCloudregionPolicyDefinitions{}
  2123. definitions[i].Parameters.Unmarshal(&regionDefinitions)
  2124. regions := []string{}
  2125. for _, region := range regionDefinitions.Cloudregions {
  2126. regions = append(regions, region.Id)
  2127. regions = append(regions, region.Name)
  2128. }
  2129. isIn := utils.IsInStringArray(input.PreferRegion, regions)
  2130. switch definitions[i].Condition {
  2131. case api.POLICY_DEFINITION_CONDITION_IN:
  2132. if !isIn {
  2133. return httperrors.NewPolicyDefinitionError("policy definition %s require cloudregion in %s", definitions[i].Name, definitions[i].Parameters)
  2134. }
  2135. case api.POLICY_DEFINITION_CONDITION_NOT_IN:
  2136. if isIn {
  2137. return httperrors.NewPolicyDefinitionError("policy definition %s require cloudregion not in %s", definitions[i].Name, definitions[i].Parameters)
  2138. }
  2139. default:
  2140. return httperrors.NewPolicyDefinitionError("invalid policy definition %s(%s) condition %s", definitions[i].Name, definitions[i].Id, definitions[i].Condition)
  2141. }
  2142. case api.POLICY_DEFINITION_CATEGORY_TAG:
  2143. tags := []string{}
  2144. if definitions[i].Parameters == nil {
  2145. return httperrors.NewPolicyDefinitionError("invalid parameters for policy definition %s", definitions[i].Name)
  2146. }
  2147. definitions[i].Parameters.Unmarshal(&tags, "tags")
  2148. metadataKeys := []string{}
  2149. for k, _ := range input.Metadata {
  2150. metadataKeys = append(metadataKeys, strings.TrimPrefix(k, db.USER_TAG_PREFIX))
  2151. }
  2152. for _, tag := range tags {
  2153. isIn := utils.IsInStringArray(tag, metadataKeys)
  2154. switch definitions[i].Condition {
  2155. case api.POLICY_DEFINITION_CONDITION_CONTAINS:
  2156. if !isIn {
  2157. return httperrors.NewPolicyDefinitionError("policy definition %s require must contains tag %s", definitions[i].Name, tag)
  2158. }
  2159. case api.POLICY_DEFINITION_CONDITION_EXCEPT:
  2160. if isIn {
  2161. return httperrors.NewPolicyDefinitionError("policy definition %s require except tag %s", definitions[i].Name, tag)
  2162. }
  2163. default:
  2164. return httperrors.NewPolicyDefinitionError("invalid policy definition %s(%s) condition %s", definitions[i].Name, definitions[i].Id, definitions[i].Condition)
  2165. }
  2166. }
  2167. default:
  2168. return httperrors.NewPolicyDefinitionError("invalid category %s for policy definition %s(%s)", definitions[i].Category, definitions[i].Name, definitions[i].Id)
  2169. }
  2170. }
  2171. return nil
  2172. }
  2173. func (manager *SGuestManager) BatchCreateValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
  2174. input, err := manager.validateCreateData(ctx, userCred, ownerId, query, data)
  2175. if err != nil {
  2176. return nil, err
  2177. }
  2178. return input.JSON(input), nil
  2179. }
  2180. // 创建虚拟机实例
  2181. func (manager *SGuestManager) ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, oinput api.ServerCreateInput) (*jsonutils.JSONDict, error) {
  2182. input, err := manager.validateCreateData(ctx, userCred, ownerId, query, oinput.JSON(oinput))
  2183. if err != nil {
  2184. return nil, err
  2185. }
  2186. if input.IsSystem == nil || !(*input.IsSystem) {
  2187. err = manager.checkCreateQuota(ctx, userCred, ownerId, *input, input.Backup, 1)
  2188. if err != nil {
  2189. return nil, err
  2190. }
  2191. }
  2192. return input.JSON(input), nil
  2193. }
  2194. func validateKickstartConfig(config *api.KickstartConfig) error {
  2195. if config.OSType == "" {
  2196. return httperrors.NewMissingParameterError("os_type")
  2197. }
  2198. if !utils.IsInStringArray(config.OSType, api.KICKSTART_VALID_OS_TYPES) {
  2199. return httperrors.NewInputParameterError("unsupported os_type: %s, supported types: %v", config.OSType, api.KICKSTART_VALID_OS_TYPES)
  2200. }
  2201. // 验证配置内容和URL二选一
  2202. if config.Config == "" && config.ConfigURL == "" {
  2203. return httperrors.NewInputParameterError("either config or config_url must be provided")
  2204. }
  2205. if config.Config != "" && config.ConfigURL != "" {
  2206. return httperrors.NewInputParameterError("config and config_url cannot be both provided, choose one")
  2207. }
  2208. if config.Config != "" {
  2209. const maxConfigSize = 64 * 1024
  2210. if len(config.Config) > maxConfigSize {
  2211. return httperrors.NewInputParameterError("config content too large: %d bytes, maximum allowed: %d bytes", len(config.Config), maxConfigSize)
  2212. }
  2213. if len(strings.TrimSpace(config.Config)) == 0 {
  2214. return httperrors.NewInputParameterError("config content cannot be empty")
  2215. }
  2216. }
  2217. if config.ConfigURL != "" {
  2218. if len(config.ConfigURL) > 2048 {
  2219. return httperrors.NewInputParameterError("config URL too long: %d characters, maximum allowed: 2048", len(config.ConfigURL))
  2220. }
  2221. if strings.TrimSpace(config.ConfigURL) == "" {
  2222. return httperrors.NewInputParameterError("config URL cannot be empty")
  2223. }
  2224. parsedURL, err := url.Parse(config.ConfigURL)
  2225. if err != nil {
  2226. return httperrors.NewInputParameterError("invalid URL format: %v", err)
  2227. }
  2228. if parsedURL.Scheme != "http" && parsedURL.Scheme != "https" {
  2229. return httperrors.NewInputParameterError("invalid URL scheme: %s, only http and https are allowed", parsedURL.Scheme)
  2230. }
  2231. if parsedURL.Host == "" {
  2232. return httperrors.NewInputParameterError("URL must specify a host")
  2233. }
  2234. if err := checkKickstartURLContentSize(config.ConfigURL); err != nil {
  2235. return httperrors.NewInputParameterError("URL content validation failed: %v", err)
  2236. }
  2237. }
  2238. // 设置默认值
  2239. if config.Enabled == nil {
  2240. enabled := true
  2241. config.Enabled = &enabled
  2242. }
  2243. if config.MaxRetries <= 0 {
  2244. config.MaxRetries = 3
  2245. }
  2246. if config.TimeoutMinutes <= 0 {
  2247. config.TimeoutMinutes = 60
  2248. }
  2249. return nil
  2250. }
  2251. // determineKickstartType determines kickstart type based on config content
  2252. func determineKickstartType(config *api.KickstartConfig) string {
  2253. if config.Config != "" {
  2254. return api.KICKSTART_TYPE_CONTENT
  2255. }
  2256. return api.KICKSTART_TYPE_URL
  2257. }
  2258. func checkKickstartURLContentSize(configURL string) error {
  2259. const maxURLContentSize = 64 * 1024
  2260. const requestTimeout = 10 * time.Second
  2261. client := &http.Client{Timeout: requestTimeout}
  2262. req, err := http.NewRequest("HEAD", configURL, nil)
  2263. if err != nil {
  2264. return fmt.Errorf("failed to create request: %v", err)
  2265. }
  2266. resp, err := client.Do(req)
  2267. if err != nil {
  2268. log.Warningf("Failed to check URL content size for %s: %v", configURL, err)
  2269. return nil
  2270. }
  2271. defer resp.Body.Close()
  2272. if resp.StatusCode != http.StatusOK {
  2273. return fmt.Errorf("URL returned status code: %d", resp.StatusCode)
  2274. }
  2275. contentLengthStr := resp.Header.Get("Content-Length")
  2276. if contentLengthStr != "" {
  2277. contentLength, err := strconv.ParseInt(contentLengthStr, 10, 64)
  2278. if err != nil {
  2279. log.Warningf("Failed to parse Content-Length header: %v", err)
  2280. return nil
  2281. }
  2282. if contentLength > maxURLContentSize {
  2283. return fmt.Errorf("URL content too large: %d bytes, maximum allowed: %d bytes", contentLength, maxURLContentSize)
  2284. }
  2285. log.Infof("URL content size validated: %d bytes", contentLength)
  2286. } else {
  2287. log.Warningf("URL %s does not provide Content-Length header, size validation skipped", configURL)
  2288. }
  2289. return nil
  2290. }
  2291. func (manager *SGuestManager) validateEip(ctx context.Context, userCred mcclient.TokenCredential, input *api.ServerCreateInput,
  2292. preferRegionId string, preferManagerId string) error {
  2293. driver, err := GetDriver(input.Hypervisor, input.Provider)
  2294. if err != nil {
  2295. return err
  2296. }
  2297. if input.PublicIpBw > 0 {
  2298. if !driver.IsSupportPublicIp() {
  2299. return httperrors.NewNotImplementedError("public ip not supported for %s", input.Hypervisor)
  2300. }
  2301. if len(input.PublicIpChargeType) == 0 {
  2302. input.PublicIpChargeType = billing_api.TNetChargeType(cloudprovider.ElasticipChargeTypeByTraffic)
  2303. }
  2304. if !utils.IsInStringArray(string(input.PublicIpChargeType), []string{
  2305. string(cloudprovider.ElasticipChargeTypeByTraffic),
  2306. string(cloudprovider.ElasticipChargeTypeByBandwidth),
  2307. }) {
  2308. return httperrors.NewInputParameterError("invalid public_ip_charge_type %s", input.PublicIpChargeType)
  2309. }
  2310. return nil
  2311. }
  2312. eipStr := input.Eip
  2313. eipBw := input.EipBw
  2314. if len(eipStr) > 0 || eipBw > 0 {
  2315. if !driver.IsSupportEip() {
  2316. return httperrors.NewNotImplementedError("eip not supported for %s", input.Hypervisor)
  2317. }
  2318. if len(eipStr) > 0 {
  2319. eipObj, err := ElasticipManager.FetchByIdOrName(ctx, userCred, eipStr)
  2320. if err != nil {
  2321. if err == sql.ErrNoRows {
  2322. return httperrors.NewResourceNotFoundError2(ElasticipManager.Keyword(), eipStr)
  2323. } else {
  2324. return httperrors.NewGeneralError(err)
  2325. }
  2326. }
  2327. eip := eipObj.(*SElasticip)
  2328. if eip.Status != api.EIP_STATUS_READY {
  2329. return httperrors.NewInvalidStatusError("eip %s status invalid %s", eipStr, eip.Status)
  2330. }
  2331. if eip.IsAssociated() {
  2332. return httperrors.NewResourceBusyError("eip %s has been associated", eipStr)
  2333. }
  2334. input.Eip = eipObj.GetId()
  2335. eipCloudprovider := eip.GetCloudprovider()
  2336. if eipCloudprovider != nil {
  2337. if len(preferManagerId) > 0 && preferManagerId != eipCloudprovider.Id {
  2338. return httperrors.NewConflictError("cannot assoicate with eip %s: different cloudprovider", eipStr)
  2339. }
  2340. input.PreferManager = eipCloudprovider.Id
  2341. }
  2342. eipRegion, err := eip.GetRegion()
  2343. if err != nil {
  2344. return httperrors.NewGeneralError(errors.Wrapf(err, "eip.GetRegion"))
  2345. }
  2346. // preferRegionId, _ := data.GetString("prefer_region_id")
  2347. if len(preferRegionId) > 0 && preferRegionId != eipRegion.Id {
  2348. return httperrors.NewConflictError("cannot assoicate with eip %s: different region", eipStr)
  2349. }
  2350. input.PreferRegion = eipRegion.Id
  2351. } else {
  2352. // create new eip
  2353. }
  2354. }
  2355. return nil
  2356. }
  2357. func (self *SGuest) PostUpdate(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) {
  2358. self.SVirtualResourceBase.PostUpdate(ctx, userCred, query, data)
  2359. if len(self.ExternalId) > 0 && (data.Contains("name") || data.Contains("__meta__") || data.Contains("description")) || data.Contains("hostname") {
  2360. err := self.StartRemoteUpdateTask(ctx, userCred, false, "")
  2361. if err != nil {
  2362. log.Errorf("StartRemoteUpdateTask fail: %s", err)
  2363. }
  2364. }
  2365. if port, err := data.Int("ssh_port"); err != nil {
  2366. err := self.SetSshPort(ctx, userCred, int(port))
  2367. if err != nil {
  2368. log.Errorf("unable to set sshport for guest %s", self.GetId())
  2369. }
  2370. }
  2371. }
  2372. func (manager *SGuestManager) checkCreateQuota(
  2373. ctx context.Context,
  2374. userCred mcclient.TokenCredential,
  2375. ownerId mcclient.IIdentityProvider,
  2376. input api.ServerCreateInput,
  2377. hasBackup bool,
  2378. count int,
  2379. ) error {
  2380. req, regionReq := getGuestResourceRequirements(ctx, userCred, input, ownerId, count, hasBackup)
  2381. log.Debugf("computeQuota: %s", jsonutils.Marshal(req))
  2382. log.Debugf("regionQuota: %s", jsonutils.Marshal(regionReq))
  2383. err := quotas.CheckSetPendingQuota(ctx, userCred, &req)
  2384. if err != nil {
  2385. return errors.Wrap(err, "quotas.CheckSetPendingQuota")
  2386. }
  2387. err = quotas.CheckSetPendingQuota(ctx, userCred, &regionReq)
  2388. if err != nil {
  2389. return errors.Wrap(err, "quotas.CheckSetPendingQuota")
  2390. }
  2391. return nil
  2392. }
  2393. func (self *SGuest) checkUpdateQuota(ctx context.Context, userCred mcclient.TokenCredential, vcpuCount int, vmemSize int) (quotas.IQuota, error) {
  2394. req := SQuota{}
  2395. if vcpuCount > 0 && vcpuCount > int(self.VcpuCount) {
  2396. req.Cpu = vcpuCount - int(self.VcpuCount)
  2397. }
  2398. if vmemSize > 0 && vmemSize > self.VmemSize {
  2399. req.Memory = vmemSize - self.VmemSize
  2400. }
  2401. keys, err := self.GetQuotaKeys()
  2402. if err != nil {
  2403. return nil, errors.Wrap(err, "self.GetQuotaKeys")
  2404. }
  2405. req.SetKeys(keys)
  2406. err = quotas.CheckSetPendingQuota(ctx, userCred, &req)
  2407. if err != nil {
  2408. return nil, errors.Wrap(err, "quotas.CheckSetPendingQuota")
  2409. }
  2410. return &req, nil
  2411. }
  2412. func getGuestResourceRequirements(
  2413. ctx context.Context,
  2414. userCred mcclient.TokenCredential,
  2415. input api.ServerCreateInput,
  2416. ownerId mcclient.IIdentityProvider,
  2417. count int,
  2418. hasBackup bool,
  2419. ) (SQuota, SRegionQuota) {
  2420. vcpuCount := input.VcpuCount
  2421. if vcpuCount == 0 {
  2422. vcpuCount = 1
  2423. }
  2424. vmemSize := input.VmemSize
  2425. diskSize := 0
  2426. for _, diskConfig := range input.Disks {
  2427. if diskConfig.DiskId != "" {
  2428. // disk has been created, ignore resource requirement
  2429. continue
  2430. }
  2431. diskSize += diskConfig.SizeMb
  2432. }
  2433. devCount := len(input.IsolatedDevices)
  2434. eNicCnt := 0
  2435. iNicCnt := 0
  2436. eBw := 0
  2437. iBw := 0
  2438. for _, netConfig := range input.Networks {
  2439. if IsExitNetworkInfo(ctx, userCred, netConfig) {
  2440. eNicCnt += 1
  2441. eBw += netConfig.BwLimit
  2442. } else {
  2443. iNicCnt += 1
  2444. iBw += netConfig.BwLimit
  2445. }
  2446. if netConfig.SriovDevice != nil {
  2447. devCount += 1
  2448. }
  2449. }
  2450. if hasBackup {
  2451. vcpuCount = vcpuCount * 2
  2452. vmemSize = vmemSize * 2
  2453. diskSize = diskSize * 2
  2454. }
  2455. eipCnt := 0
  2456. eipBw := input.EipBw
  2457. if eipBw > 0 {
  2458. eipCnt = 1
  2459. }
  2460. req := SQuota{
  2461. Count: count,
  2462. Cpu: int(vcpuCount) * count,
  2463. Memory: int(vmemSize) * count,
  2464. Storage: diskSize * count,
  2465. IsolatedDevice: devCount * count,
  2466. }
  2467. regionReq := SRegionQuota{
  2468. Port: iNicCnt * count,
  2469. Eport: eNicCnt * count,
  2470. //Bw: iBw * count,
  2471. //Ebw: eBw * count,
  2472. Eip: eipCnt * count,
  2473. }
  2474. keys, _ := serverCreateInput2ComputeQuotaKeys(input, ownerId)
  2475. req.SetKeys(keys)
  2476. regionReq.SetKeys(keys.SRegionalCloudResourceKeys)
  2477. return req, regionReq
  2478. }
  2479. func (guest *SGuest) getGuestBackupResourceRequirements(ctx context.Context, userCred mcclient.TokenCredential) SQuota {
  2480. guestDisksSize := guest.getDiskSize()
  2481. return SQuota{
  2482. Count: 1,
  2483. Cpu: int(guest.VcpuCount),
  2484. Memory: guest.VmemSize,
  2485. Storage: guestDisksSize,
  2486. }
  2487. }
  2488. func (guest *SGuest) PostCreate(ctx context.Context, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data jsonutils.JSONObject) {
  2489. guest.SVirtualResourceBase.PostCreate(ctx, userCred, ownerId, query, data)
  2490. tags := []string{"cpu_bound", "io_bound", "io_hardlimit"}
  2491. appTags := make([]string, 0)
  2492. for _, tag := range tags {
  2493. if data.Contains(tag) {
  2494. appTags = append(appTags, tag)
  2495. }
  2496. }
  2497. guest.setApptags(ctx, appTags, userCred)
  2498. guest.SetCreateParams(ctx, userCred, data)
  2499. osProfileJson, _ := data.Get("__os_profile__")
  2500. if osProfileJson != nil {
  2501. guest.setOSProfile(ctx, userCred, osProfileJson)
  2502. }
  2503. if jsonutils.QueryBoolean(data, api.VM_METADATA_ENABLE_MEMCLEAN, false) {
  2504. guest.SetMetadata(ctx, api.VM_METADATA_ENABLE_MEMCLEAN, "true", userCred)
  2505. }
  2506. if jsonutils.QueryBoolean(data, api.VM_METADATA_ENABLE_TPM, false) {
  2507. guest.SetMetadata(ctx, api.VM_METADATA_ENABLE_TPM, "true", userCred)
  2508. }
  2509. if jsonutils.QueryBoolean(data, imageapi.IMAGE_DISABLE_USB_KBD, false) {
  2510. guest.SetMetadata(ctx, imageapi.IMAGE_DISABLE_USB_KBD, "true", userCred)
  2511. }
  2512. matcherJson, _ := data.Get(api.BAREMETAL_SERVER_METATA_ROOT_DISK_MATCHER)
  2513. if matcherJson != nil {
  2514. guest.SetMetadata(ctx, api.BAREMETAL_SERVER_METATA_ROOT_DISK_MATCHER, matcherJson, userCred)
  2515. }
  2516. userData, _ := data.GetString("user_data")
  2517. if len(userData) > 0 {
  2518. guest.setUserData(ctx, userCred, userData)
  2519. }
  2520. if guest.Hypervisor == api.HYPERVISOR_ESXI {
  2521. schedtags := []api.SchedtagConfig{}
  2522. data.Unmarshal(&schedtags, "schedtags")
  2523. for _, tag := range schedtags {
  2524. if tag.ResourceType != HostManager.KeywordPlural() {
  2525. continue
  2526. }
  2527. meta := db.SMetadata{}
  2528. db.Metadata.Query().
  2529. Equals("obj_type", SchedtagManager.Keyword()).
  2530. Equals("obj_id", tag.Id).
  2531. Equals("key", cloudprovider.METADATA_POOL_ID).First(&meta)
  2532. if len(meta.Value) > 0 {
  2533. db.Update(guest, func() error {
  2534. guest.ResourcePool = meta.Value
  2535. return nil
  2536. })
  2537. }
  2538. }
  2539. }
  2540. // set kickstart metadata
  2541. kickstartConfigJson, _ := data.Get("kickstart_config")
  2542. if kickstartConfigJson != nil {
  2543. kickstartConfig := &api.KickstartConfig{}
  2544. if err := kickstartConfigJson.Unmarshal(kickstartConfig); err != nil {
  2545. log.Errorf("unmarshal kickstart config fail: %s", err)
  2546. } else if kickstartConfig.IsEnabled() {
  2547. if err := guest.SetKickstartConfig(ctx, kickstartConfig, userCred); err != nil {
  2548. log.Errorf("Failed to set kickstart config for guest %s: %v", guest.Name, err)
  2549. } else {
  2550. //if err := guest.SetKickstartStatus(ctx, api.VM_KICKSTART_PENDING, userCred); err != nil {
  2551. // log.Errorf("Failed to set kickstart status for guest %s: %v", guest.Name, err)
  2552. //}
  2553. if err := guest.SetMetadata(ctx, api.VM_METADATA_KICKSTART_COMPLETED_FLAG, "false", userCred); err != nil {
  2554. log.Errorf("Failed to set kickstart completed flag for guest %s: %v", guest.Name, err)
  2555. }
  2556. // Determine and set kickstart type based on config
  2557. kickstartType := determineKickstartType(kickstartConfig)
  2558. if err := guest.SetKickstartType(ctx, kickstartType, userCred); err != nil {
  2559. log.Errorf("Failed to set kickstart type for guest %s: %v", guest.Name, err)
  2560. }
  2561. log.Debugf("Successfully set kickstart config for guest %s with OS type %s", guest.Name, kickstartConfig.OSType)
  2562. }
  2563. }
  2564. }
  2565. input := struct {
  2566. PreferZone string
  2567. PreferRegion string
  2568. PreferManagerId string
  2569. Provider string
  2570. }{}
  2571. data.Unmarshal(&input)
  2572. if len(input.PreferManagerId) > 0 && len(input.Provider) == 0 {
  2573. manObj, err := CloudproviderManager.FetchById(input.PreferManagerId)
  2574. if err == nil {
  2575. man := manObj.(*SCloudprovider)
  2576. input.Provider = man.Provider
  2577. }
  2578. }
  2579. if len(input.PreferZone) > 0 && len(input.Provider) == 0 {
  2580. zoneObj, err := ZoneManager.FetchById(input.PreferZone)
  2581. if err == nil {
  2582. zone := zoneObj.(*SZone)
  2583. input.PreferRegion = zone.CloudregionId
  2584. }
  2585. }
  2586. if len(input.PreferRegion) > 0 && len(input.Provider) == 0 {
  2587. regionObj, err := CloudregionManager.FetchById(input.PreferRegion)
  2588. if err == nil {
  2589. region := regionObj.(*SCloudregion)
  2590. input.Provider = region.Provider
  2591. }
  2592. }
  2593. if len(input.Provider) == 0 {
  2594. input.Provider = api.CLOUD_PROVIDER_ONECLOUD
  2595. }
  2596. drv, _ := GetDriver(guest.Hypervisor, input.Provider)
  2597. if drv != nil && drv.GetMaxSecurityGroupCount() > 0 {
  2598. secgroups, _ := jsonutils.GetStringArray(data, "secgroups")
  2599. for _, secgroupId := range secgroups {
  2600. if secgroupId != guest.SecgrpId {
  2601. gs := SGuestsecgroup{}
  2602. gs.SecgroupId = secgroupId
  2603. gs.GuestId = guest.Id
  2604. GuestsecgroupManager.TableSpec().Insert(ctx, &gs)
  2605. }
  2606. }
  2607. } else {
  2608. db.Update(guest, func() error {
  2609. guest.SecgrpId = ""
  2610. return nil
  2611. })
  2612. }
  2613. }
  2614. func (guest *SGuest) setApptags(ctx context.Context, appTags []string, userCred mcclient.TokenCredential) {
  2615. err := guest.SetMetadata(ctx, api.VM_METADATA_APP_TAGS, strings.Join(appTags, ","), userCred)
  2616. if err != nil {
  2617. log.Errorln(err)
  2618. }
  2619. }
  2620. func (guest *SGuest) SetCreateParams(ctx context.Context, userCred mcclient.TokenCredential, data jsonutils.JSONObject) {
  2621. // delete deploy files info
  2622. createParams := data.(*jsonutils.JSONDict).CopyExcludes("deploy_configs")
  2623. err := guest.SetMetadata(ctx, api.VM_METADATA_CREATE_PARAMS, createParams.String(), userCred)
  2624. if err != nil {
  2625. log.Errorf("Server %s SetCreateParams: %v", guest.Name, err)
  2626. }
  2627. }
  2628. func (guest *SGuest) GetCreateParams(ctx context.Context, userCred mcclient.TokenCredential) (*api.ServerCreateInput, error) {
  2629. input := new(api.ServerCreateInput)
  2630. data := guest.GetMetadataJson(ctx, api.VM_METADATA_CREATE_PARAMS, userCred)
  2631. if data == nil {
  2632. return nil, fmt.Errorf("Not found %s %s in metadata", guest.Name, api.VM_METADATA_CREATE_PARAMS)
  2633. }
  2634. err := data.Unmarshal(input)
  2635. return input, err
  2636. }
  2637. func (manager *SGuestManager) SetPropertiesWithInstanceSnapshot(
  2638. ctx context.Context, userCred mcclient.TokenCredential, ispId string, items []db.IModel,
  2639. ) {
  2640. misp, err := InstanceSnapshotManager.FetchById(ispId)
  2641. if err == nil {
  2642. isp := misp.(*SInstanceSnapshot)
  2643. for i := 0; i < len(items); i++ {
  2644. guest := items[i].(*SGuest)
  2645. if isp.ServerMetadata != nil {
  2646. metadata := make(map[string]interface{}, 0)
  2647. isp.ServerMetadata.Unmarshal(metadata)
  2648. if passwd, ok := metadata["passwd"]; ok {
  2649. delete(metadata, "passwd")
  2650. metadata["login_key"], _ = utils.EncryptAESBase64(guest.Id, passwd.(string))
  2651. }
  2652. metadata[api.BASE_INSTANCE_SNAPSHOT_ID] = isp.Id
  2653. guest.SetAllMetadata(ctx, metadata, userCred)
  2654. }
  2655. }
  2656. }
  2657. }
  2658. func (manager *SGuestManager) OnCreateComplete(ctx context.Context, items []db.IModel, userCred mcclient.TokenCredential, ownerId mcclient.IIdentityProvider, query jsonutils.JSONObject, data []jsonutils.JSONObject) {
  2659. input := api.ServerCreateInput{}
  2660. data[0].Unmarshal(&input)
  2661. if len(input.InstanceSnapshotId) > 0 {
  2662. manager.SetPropertiesWithInstanceSnapshot(ctx, userCred, input.InstanceSnapshotId, items)
  2663. }
  2664. pendingUsage, pendingRegionUsage := getGuestResourceRequirements(ctx, userCred, input, ownerId, len(items), input.Backup)
  2665. err := RunBatchCreateTask(ctx, items, userCred, data, pendingUsage, pendingRegionUsage, "GuestBatchCreateTask", input.ParentTaskId)
  2666. if err != nil {
  2667. for i := range items {
  2668. guest := items[i].(*SGuest)
  2669. guest.SetStatus(ctx, userCred, api.VM_CREATE_FAILED, err.Error())
  2670. }
  2671. }
  2672. }
  2673. func (guest *SGuest) GetGroups() []SGroupguest {
  2674. guestgroups := make([]SGroupguest, 0)
  2675. q := GroupguestManager.Query().Equals("guest_id", guest.Id)
  2676. err := db.FetchModelObjects(GroupguestManager, q, &guestgroups)
  2677. if err != nil {
  2678. log.Errorf("GetGroups fail %s", err)
  2679. return nil
  2680. }
  2681. return guestgroups
  2682. }
  2683. func (self *SGuest) getBandwidth(isExit bool) int {
  2684. bw := 0
  2685. networks, err := self.GetNetworks("")
  2686. if err != nil {
  2687. return bw
  2688. }
  2689. if networks != nil && len(networks) > 0 {
  2690. for i := 0; i < len(networks); i += 1 {
  2691. net, _ := networks[i].GetNetwork()
  2692. if networks[i].IsExit(net) == isExit {
  2693. bw += networks[i].getBandwidth(net, nil)
  2694. }
  2695. }
  2696. }
  2697. return bw
  2698. }
  2699. func (self *SGuest) getExtBandwidth() int {
  2700. return self.getBandwidth(true)
  2701. }
  2702. func (self *SGuestManager) GetMetadataHiddenKeys() []string {
  2703. return []string{
  2704. api.VM_METADATA_CREATE_PARAMS,
  2705. }
  2706. }
  2707. func (manager *SGuestManager) ListItemExportKeys(ctx context.Context, q *sqlchemy.SQuery, userCred mcclient.TokenCredential, keys stringutils2.SSortedStrings) (*sqlchemy.SQuery, error) {
  2708. var err error
  2709. q, err = manager.SVirtualResourceBaseManager.ListItemExportKeys(ctx, q, userCred, keys)
  2710. if err != nil {
  2711. return nil, err
  2712. }
  2713. // exportKeys, _ := query.GetString("export_keys")
  2714. // keys := strings.Split(exportKeys, ",")
  2715. // guest_id as filter key
  2716. if keys.Contains("ips") {
  2717. guestIpsQuery := GuestnetworkManager.Query("guest_id").GroupBy("guest_id")
  2718. guestIpsQuery.AppendField(sqlchemy.GROUP_CONCAT("concat_ip_addr", guestIpsQuery.Field("ip_addr")))
  2719. ipsSubQuery := guestIpsQuery.SubQuery()
  2720. q.LeftJoin(ipsSubQuery, sqlchemy.Equals(q.Field("id"), ipsSubQuery.Field("guest_id")))
  2721. q.AppendField(ipsSubQuery.Field("concat_ip_addr"))
  2722. }
  2723. if keys.Contains("disk") {
  2724. guestDisksQuery := GuestdiskManager.Query("guest_id", "disk_id").GroupBy("guest_id")
  2725. diskQuery := DiskManager.Query("id", "disk_size").SubQuery()
  2726. guestDisksQuery.Join(diskQuery, sqlchemy.Equals(diskQuery.Field("id"), guestDisksQuery.Field("disk_id")))
  2727. guestDisksQuery.AppendField(sqlchemy.SUM("disk_size", diskQuery.Field("disk_size")))
  2728. guestDisksSubQuery := guestDisksQuery.SubQuery()
  2729. q.LeftJoin(guestDisksSubQuery, sqlchemy.Equals(q.Field("id"), guestDisksSubQuery.Field("guest_id")))
  2730. q.AppendField(guestDisksSubQuery.Field("disk_size"))
  2731. }
  2732. if keys.Contains("eip") {
  2733. eipsQuery := ElasticipManager.Query("associate_id", "ip_addr").Equals("associate_type", "server").GroupBy("associate_id")
  2734. eipsSubQuery := eipsQuery.SubQuery()
  2735. q.LeftJoin(eipsSubQuery, sqlchemy.Equals(q.Field("id"), eipsSubQuery.Field("associate_id")))
  2736. q.AppendField(eipsSubQuery.Field("ip_addr", "eip"))
  2737. }
  2738. if keys.ContainsAny(manager.SHostResourceBaseManager.GetExportKeys()...) {
  2739. q, err = manager.SHostResourceBaseManager.ListItemExportKeys(ctx, q, userCred, keys)
  2740. if err != nil {
  2741. return nil, errors.Wrap(err, "SHostResourceBaseManager.ListItemExportKeys")
  2742. }
  2743. }
  2744. return q, nil
  2745. }
  2746. func (manager *SGuestManager) GetExportExtraKeys(ctx context.Context, keys stringutils2.SSortedStrings, rowMap map[string]string) *jsonutils.JSONDict {
  2747. res := manager.SVirtualResourceBaseManager.GetExportExtraKeys(ctx, keys, rowMap)
  2748. // exportKeys, _ := query.GetString("export_keys")
  2749. // keys := strings.Split(exportKeys, ",")
  2750. if ips, ok := rowMap["concat_ip_addr"]; ok && len(ips) > 0 {
  2751. res.Set("ips", jsonutils.NewString(ips))
  2752. }
  2753. if eip, ok := rowMap["eip"]; ok && len(eip) > 0 {
  2754. res.Set("eip", jsonutils.NewString(eip))
  2755. }
  2756. if disk, ok := rowMap["disk_size"]; ok {
  2757. res.Set("disk", jsonutils.NewString(disk))
  2758. }
  2759. if host, ok := rowMap["host"]; ok && len(host) > 0 {
  2760. res.Set("host", jsonutils.NewString(host))
  2761. }
  2762. if zone, ok := rowMap["zone"]; ok && len(zone) > 0 {
  2763. res.Set("zone", jsonutils.NewString(zone))
  2764. }
  2765. if region, ok := rowMap["region"]; ok && len(region) > 0 {
  2766. res.Set("region", jsonutils.NewString(region))
  2767. }
  2768. if manager, ok := rowMap["manager"]; ok && len(manager) > 0 {
  2769. res.Set("manager", jsonutils.NewString(manager))
  2770. }
  2771. if keys.Contains("tenant") {
  2772. if projectId, ok := rowMap["tenant_id"]; ok {
  2773. tenant, err := db.TenantCacheManager.FetchTenantById(ctx, projectId)
  2774. if err == nil {
  2775. res.Set("tenant", jsonutils.NewString(tenant.GetName()))
  2776. }
  2777. }
  2778. }
  2779. if keys.Contains("os_distribution") {
  2780. if osType, ok := rowMap["os_type"]; ok {
  2781. res.Set("os_distribution", jsonutils.NewString(osType))
  2782. }
  2783. }
  2784. return res
  2785. }
  2786. func (self *SGuest) getNetworksDetails() string {
  2787. guestnets, err := self.GetNetworks("")
  2788. if err != nil {
  2789. return ""
  2790. }
  2791. var buf bytes.Buffer
  2792. for _, nic := range guestnets {
  2793. buf.WriteString(nic.GetDetailedString())
  2794. buf.WriteString("\n")
  2795. }
  2796. return buf.String()
  2797. }
  2798. func (self *SGuest) GetCdrom() *SGuestcdrom {
  2799. return self.getCdrom(false, 0)
  2800. }
  2801. func (self *SGuest) GetCdromByOrdinal(ordinal int64) *SGuestcdrom {
  2802. return self.getCdrom(false, ordinal)
  2803. }
  2804. func (self *SGuest) getCdrom(create bool, ordinal int64) *SGuestcdrom {
  2805. cdrom := SGuestcdrom{}
  2806. cdrom.SetModelManager(GuestcdromManager, &cdrom)
  2807. err := GuestcdromManager.Query().Equals("id", self.Id).Equals("ordinal", ordinal).First(&cdrom)
  2808. if err != nil {
  2809. if err == sql.ErrNoRows {
  2810. if create {
  2811. cdrom.Id = self.Id
  2812. cdrom.Ordinal = int(ordinal)
  2813. err = GuestcdromManager.TableSpec().Insert(context.TODO(), &cdrom)
  2814. if err != nil {
  2815. log.Errorf("insert cdrom fail %s", err)
  2816. return nil
  2817. }
  2818. return &cdrom
  2819. } else {
  2820. return nil
  2821. }
  2822. } else {
  2823. log.Errorf("getCdrom query fail %s", err)
  2824. return nil
  2825. }
  2826. } else {
  2827. return &cdrom
  2828. }
  2829. }
  2830. func (self *SGuest) getCdroms() ([]SGuestcdrom, error) {
  2831. cdroms := make([]SGuestcdrom, 0)
  2832. q := GuestcdromManager.Query().Equals("id", self.Id)
  2833. err := db.FetchModelObjects(GuestcdromManager, q, &cdroms)
  2834. if err != nil {
  2835. return nil, errors.Wrapf(err, "db.FetchModelObjects")
  2836. }
  2837. return cdroms, nil
  2838. }
  2839. func (self *SGuest) getFloppys() ([]SGuestfloppy, error) {
  2840. floppys := make([]SGuestfloppy, 0)
  2841. q := GuestFloppyManager.Query().Equals("id", self.Id)
  2842. err := db.FetchModelObjects(GuestFloppyManager, q, &floppys)
  2843. if err != nil {
  2844. return nil, errors.Wrapf(err, "db.FetchModelObjects")
  2845. }
  2846. return floppys, nil
  2847. }
  2848. func (self *SGuest) getFloppy(create bool, ordinal int64) *SGuestfloppy {
  2849. floppy := SGuestfloppy{}
  2850. floppy.SetModelManager(GuestFloppyManager, &floppy)
  2851. err := GuestFloppyManager.Query().Equals("id", self.Id).Equals("ordinal", ordinal).First(&floppy)
  2852. if err != nil {
  2853. if err == sql.ErrNoRows {
  2854. if create {
  2855. floppy.Id = self.Id
  2856. floppy.Ordinal = int(ordinal)
  2857. err = GuestFloppyManager.TableSpec().Insert(context.TODO(), &floppy)
  2858. if err != nil {
  2859. log.Errorf("insert cdrom fail %s", err)
  2860. return nil
  2861. }
  2862. return &floppy
  2863. } else {
  2864. return nil
  2865. }
  2866. } else {
  2867. log.Errorf("getFloppy query fail %s", err)
  2868. return nil
  2869. }
  2870. } else {
  2871. return &floppy
  2872. }
  2873. }
  2874. func (self *SGuest) getKeypair() *SKeypair {
  2875. if len(self.KeypairId) > 0 {
  2876. keypair, _ := KeypairManager.FetchById(self.KeypairId)
  2877. if keypair != nil {
  2878. return keypair.(*SKeypair)
  2879. }
  2880. }
  2881. return nil
  2882. }
  2883. func (self *SGuest) getKeypairName() string {
  2884. keypair := self.getKeypair()
  2885. if keypair != nil {
  2886. return keypair.Name
  2887. }
  2888. return ""
  2889. }
  2890. func (self *SGuest) getNotifyIps() string {
  2891. ips := self.GetRealIPs()
  2892. vips := self.getVirtualIPs()
  2893. if vips != nil {
  2894. ips = append(ips, vips...)
  2895. }
  2896. return strings.Join(ips, ",")
  2897. }
  2898. /*
  2899. func (self *SGuest) GetRealIPs() []string {
  2900. guestnets, err := self.GetNetworks("")
  2901. if err != nil {
  2902. return nil
  2903. }
  2904. ips := make([]string, 0)
  2905. for _, nic := range guestnets {
  2906. if !nic.Virtual {
  2907. ips = append(ips, nic.IpAddr)
  2908. }
  2909. }
  2910. return ips
  2911. }
  2912. */
  2913. func (self *SGuest) IsExitOnly() bool {
  2914. for _, ip := range self.GetRealIPs() {
  2915. if regutils.MatchIP4Addr(ip) {
  2916. addr, _ := netutils.NewIPV4Addr(ip)
  2917. if !netutils.IsExitAddress(addr) {
  2918. return false
  2919. }
  2920. }
  2921. }
  2922. return true
  2923. }
  2924. func (self *SGuest) getVirtualIPs() []string {
  2925. ips := make([]string, 0)
  2926. for _, guestgroup := range self.GetGroups() {
  2927. group := guestgroup.GetGroup()
  2928. groupnets, err := group.GetNetworks()
  2929. if err != nil {
  2930. continue
  2931. }
  2932. for _, groupnetwork := range groupnets {
  2933. if len(groupnetwork.IpAddr) > 0 {
  2934. ips = append(ips, groupnetwork.IpAddr)
  2935. }
  2936. if len(groupnetwork.Ip6Addr) > 0 {
  2937. ips = append(ips, groupnetwork.Ip6Addr)
  2938. }
  2939. }
  2940. }
  2941. return ips
  2942. }
  2943. func (self *SGuest) GetPrivateIPs() []string {
  2944. ips := self.GetRealIPs()
  2945. for i := len(ips) - 1; i >= 0; i-- {
  2946. if regutils.MatchIP4Addr(ips[i]) {
  2947. ipAddr, err := netutils.NewIPV4Addr(ips[i])
  2948. if err != nil {
  2949. log.Errorf("guest %s(%s) has bad ipv4 address (%s): %v", self.Name, self.Id, ips[i], err)
  2950. continue
  2951. }
  2952. if !netutils.IsPrivate(ipAddr) {
  2953. ips = append(ips[:i], ips[i+1:]...)
  2954. }
  2955. }
  2956. }
  2957. return ips
  2958. }
  2959. func (self *SGuest) getIPs() []string {
  2960. ips := self.GetRealIPs()
  2961. vips := self.getVirtualIPs()
  2962. ips = append(ips, vips...)
  2963. /*eip, _ := self.GetEip()
  2964. if eip != nil {
  2965. ips = append(ips, eip.IpAddr)
  2966. }*/
  2967. return ips
  2968. }
  2969. func (self *SGuest) getZone() (*SZone, error) {
  2970. host, err := self.GetHost()
  2971. if err != nil {
  2972. return nil, err
  2973. }
  2974. return host.GetZone()
  2975. }
  2976. func (self *SGuest) getRegion() (*SCloudregion, error) {
  2977. zone, err := self.getZone()
  2978. if err != nil {
  2979. return nil, err
  2980. }
  2981. return zone.GetRegion()
  2982. }
  2983. func (self *SGuest) GetOS() string {
  2984. if len(self.OsType) > 0 {
  2985. return self.OsType
  2986. }
  2987. return self.GetMetadata(context.Background(), "os_name", nil)
  2988. }
  2989. func (self *SGuest) IsLinux() bool {
  2990. os := self.GetOS()
  2991. if strings.HasPrefix(strings.ToLower(os), "lin") {
  2992. return true
  2993. } else {
  2994. return false
  2995. }
  2996. }
  2997. func (self *SGuest) IsWindows() bool {
  2998. os := self.GetOS()
  2999. if strings.HasPrefix(strings.ToLower(os), "win") {
  3000. return true
  3001. } else {
  3002. return false
  3003. }
  3004. }
  3005. func (self *SGuest) getSecgroupJson() ([]*api.SecgroupJsonDesc, error) {
  3006. ret := []*api.SecgroupJsonDesc{}
  3007. secgroups, err := self.GetSecgroups()
  3008. if err != nil {
  3009. return nil, errors.Wrap(err, "GetSecgroups")
  3010. }
  3011. for _, secGrp := range secgroups {
  3012. ret = append(ret, secGrp.getDesc())
  3013. }
  3014. return ret, nil
  3015. }
  3016. func (self *SGuest) GetSecgroups() ([]SSecurityGroup, error) {
  3017. secgrpQuery := SecurityGroupManager.Query()
  3018. secgrpQuery.Filter(
  3019. sqlchemy.OR(
  3020. sqlchemy.Equals(secgrpQuery.Field("id"), self.SecgrpId),
  3021. sqlchemy.In(secgrpQuery.Field("id"), GuestsecgroupManager.Query("secgroup_id").Equals("guest_id", self.Id).SubQuery()),
  3022. ),
  3023. )
  3024. secgroups := []SSecurityGroup{}
  3025. err := db.FetchModelObjects(SecurityGroupManager, secgrpQuery, &secgroups)
  3026. if err != nil {
  3027. return nil, errors.Wrapf(err, "db.FetchModelObjects")
  3028. }
  3029. return secgroups, nil
  3030. }
  3031. func (self *SGuest) getAdminSecgroup() *SSecurityGroup {
  3032. secGrp, _ := SecurityGroupManager.FetchSecgroupById(self.AdminSecgrpId)
  3033. return secGrp
  3034. }
  3035. func (self *SGuest) getAdminSecgroupName() string {
  3036. secgrp := self.getAdminSecgroup()
  3037. if secgrp != nil {
  3038. return secgrp.GetName()
  3039. }
  3040. return ""
  3041. }
  3042. // 获取多个安全组规则,优先级降序排序
  3043. func (self *SGuest) getSecurityGroupsRules() string {
  3044. secgroups, _ := self.GetSecgroups()
  3045. secgroupids := []string{}
  3046. for _, secgroup := range secgroups {
  3047. secgroupids = append(secgroupids, secgroup.Id)
  3048. }
  3049. q := SecurityGroupRuleManager.Query()
  3050. q.Filter(sqlchemy.In(q.Field("secgroup_id"), secgroupids)).Desc(q.Field("priority"), q.Field("action"))
  3051. secrules := []SSecurityGroupRule{}
  3052. if err := db.FetchModelObjects(SecurityGroupRuleManager, q, &secrules); err != nil {
  3053. log.Errorf("Get security group rules error: %v", err)
  3054. return ""
  3055. }
  3056. rules := []string{}
  3057. for _, rule := range secrules {
  3058. rules = append(rules, rule.String())
  3059. }
  3060. return strings.Join(rules, SECURITY_GROUP_SEPARATOR)
  3061. }
  3062. func (self *SGuest) getNetworkSecurityGroupsRules(networkIndex int) string {
  3063. gnss, _ := self.GetGuestNetworkSecgroups(networkIndex)
  3064. secgroupids := []string{}
  3065. for _, gns := range gnss {
  3066. secgroupids = append(secgroupids, gns.SecgroupId)
  3067. }
  3068. q := SecurityGroupRuleManager.Query()
  3069. q.Filter(sqlchemy.In(q.Field("secgroup_id"), secgroupids)).Desc(q.Field("priority"), q.Field("action"))
  3070. secrules := []SSecurityGroupRule{}
  3071. if err := db.FetchModelObjects(SecurityGroupRuleManager, q, &secrules); err != nil {
  3072. log.Errorf("Get security group rules error: %v", err)
  3073. return ""
  3074. }
  3075. rules := []string{}
  3076. for _, rule := range secrules {
  3077. rules = append(rules, rule.String())
  3078. }
  3079. return strings.Join(rules, SECURITY_GROUP_SEPARATOR)
  3080. }
  3081. func (self *SGuest) getAdminSecurityRules() string {
  3082. secgrp := self.getAdminSecgroup()
  3083. if secgrp != nil {
  3084. ret, _ := secgrp.getSecurityRuleString()
  3085. return ret
  3086. }
  3087. return ""
  3088. }
  3089. func (self *SGuest) IsFailureStatus() bool {
  3090. return strings.Index(self.Status, "fail") >= 0
  3091. }
  3092. var (
  3093. lostNamePattern = regexp.MustCompile(`-lost@\d{8}$`)
  3094. )
  3095. func (self *SGuest) GetIRegion(ctx context.Context) (cloudprovider.ICloudRegion, error) {
  3096. host, err := self.GetHost()
  3097. if err != nil {
  3098. return nil, errors.Wrapf(err, "GetHost")
  3099. }
  3100. provider, err := host.GetDriver(ctx)
  3101. if err != nil {
  3102. return nil, errors.Wrapf(err, "host.GetDriver")
  3103. }
  3104. if provider.GetFactory().IsOnPremise() {
  3105. return provider.GetOnPremiseIRegion()
  3106. }
  3107. return host.GetIRegion(ctx)
  3108. }
  3109. func (self *SGuest) SyncRemoveCloudVM(ctx context.Context, userCred mcclient.TokenCredential, check bool) error {
  3110. lockman.LockObject(ctx, self)
  3111. defer lockman.ReleaseObject(ctx, self)
  3112. if self.BillingType == billing_api.BILLING_TYPE_PREPAID {
  3113. diff, err := db.Update(self, func() error {
  3114. self.BillingType = billing_api.BILLING_TYPE_POSTPAID
  3115. self.ExpiredAt = time.Time{}
  3116. return nil
  3117. })
  3118. if err != nil {
  3119. return err
  3120. }
  3121. db.OpsLog.LogSyncUpdate(self, diff, userCred)
  3122. }
  3123. if self.IsFailureStatus() {
  3124. return nil
  3125. }
  3126. iregion, err := self.GetIRegion(ctx)
  3127. if err != nil {
  3128. return err
  3129. }
  3130. if check {
  3131. iVM, err := iregion.GetIVMById(self.ExternalId)
  3132. if err == nil { //漂移归位
  3133. if hostId := iVM.GetIHostId(); len(hostId) > 0 {
  3134. host, err := db.FetchByExternalIdAndManagerId(HostManager, hostId, func(q *sqlchemy.SQuery) *sqlchemy.SQuery {
  3135. host, _ := self.GetHost()
  3136. if host != nil {
  3137. return q.Equals("manager_id", host.ManagerId)
  3138. }
  3139. return q
  3140. })
  3141. if err != nil {
  3142. log.Errorf("fetch vm %s(%s) host by id %s error: %v", self.Name, self.ExternalId, hostId, err)
  3143. return nil
  3144. }
  3145. _, err = db.Update(self, func() error {
  3146. self.HostId = host.GetId()
  3147. self.Status = iVM.GetStatus()
  3148. self.PowerStates = iVM.GetPowerStates()
  3149. self.InferPowerStates()
  3150. return nil
  3151. })
  3152. return err
  3153. }
  3154. // 公有云实例, 因为翻页查询导致实例返回结果漏查,且GetIHostId一般返回为空
  3155. return nil
  3156. } else if errors.Cause(err) != cloudprovider.ErrNotFound {
  3157. return errors.Wrap(err, "GetIVMById")
  3158. }
  3159. }
  3160. if self.Status != api.VM_UNKNOWN {
  3161. self.SetStatus(ctx, userCred, api.VM_UNKNOWN, "Sync lost")
  3162. }
  3163. if options.Options.EnableSyncPurge {
  3164. log.Debugf("purge removed resource %s", self.Name)
  3165. err := self.purge(ctx, userCred)
  3166. if err != nil {
  3167. return err
  3168. }
  3169. notifyclient.EventNotify(ctx, userCred, notifyclient.SEventNotifyParam{
  3170. Obj: self,
  3171. Action: notifyclient.ActionSyncDelete,
  3172. })
  3173. return nil
  3174. }
  3175. if !lostNamePattern.MatchString(self.Name) {
  3176. db.Update(self, func() error {
  3177. self.Name = fmt.Sprintf("%s-lost@%s", self.Name, timeutils.ShortDate(time.Now()))
  3178. return nil
  3179. })
  3180. }
  3181. return nil
  3182. }
  3183. func (guest *SGuest) SyncAllWithCloudVM(ctx context.Context, userCred mcclient.TokenCredential, host *SHost, extVM cloudprovider.ICloudVM, syncStatus bool) error {
  3184. if host == nil {
  3185. return errors.Error("guest has no host")
  3186. }
  3187. provider := host.GetCloudprovider()
  3188. if provider == nil {
  3189. return errors.Error("host has no provider")
  3190. }
  3191. driver, err := provider.GetProvider(ctx)
  3192. if err != nil {
  3193. return errors.Wrap(err, "provider.GetProvider")
  3194. }
  3195. err = guest.syncWithCloudVM(ctx, userCred, driver, host, extVM, provider.GetOwnerId(), syncStatus)
  3196. if err != nil {
  3197. return errors.Wrap(err, "guest.syncWithCloudVM")
  3198. }
  3199. SyncVMPeripherals(ctx, userCred, guest, extVM, host, provider, driver)
  3200. return nil
  3201. }
  3202. func (g *SGuest) SyncOsInfo(ctx context.Context, userCred mcclient.TokenCredential, extVM cloudprovider.IOSInfo) error {
  3203. drv, err := g.GetDriver()
  3204. if err != nil {
  3205. return err
  3206. }
  3207. return drv.SyncOsInfo(ctx, userCred, g, extVM)
  3208. }
  3209. func (g *SGuest) SyncHostname(ext cloudprovider.ICloudVM) {
  3210. hostname := pinyinutils.Text2Pinyin(ext.GetHostname())
  3211. if len(hostname) > 128 {
  3212. hostname = hostname[:128]
  3213. }
  3214. if len(hostname) > 0 {
  3215. g.Hostname = hostname
  3216. }
  3217. }
  3218. func (g *SGuest) syncWithCloudVM(ctx context.Context, userCred mcclient.TokenCredential, provider cloudprovider.ICloudProvider, host *SHost, extVM cloudprovider.ICloudVM, syncOwnerId mcclient.IIdentityProvider, syncStatus bool) error {
  3219. recycle := false
  3220. if provider.GetFactory().IsSupportPrepaidResources() && g.IsPrepaidRecycle() {
  3221. recycle = true
  3222. }
  3223. diff, err := db.UpdateWithLock(ctx, g, func() error {
  3224. if options.Options.EnableSyncName && !recycle {
  3225. newName, _ := db.GenerateAlterName(g, extVM.GetName())
  3226. if len(newName) > 0 && newName != g.Name {
  3227. g.Name = newName
  3228. }
  3229. }
  3230. g.SyncHostname(extVM)
  3231. if !g.IsFailureStatus() && syncStatus {
  3232. g.Status = extVM.GetStatus()
  3233. if g.Status == api.VM_RUNNING || g.Status == api.VM_STARTING {
  3234. g.HealthStatus = extVM.GetHealthStatus()
  3235. }
  3236. g.PowerStates = extVM.GetPowerStates()
  3237. g.InferPowerStates()
  3238. }
  3239. g.VcpuCount = extVM.GetVcpuCount()
  3240. g.CpuSockets = extVM.GetCpuSockets()
  3241. g.BootOrder = extVM.GetBootOrder()
  3242. g.Vga = extVM.GetVga()
  3243. g.Vdi = extVM.GetVdi()
  3244. if len(extVM.GetOsArch()) > 0 {
  3245. g.OsArch = extVM.GetOsArch()
  3246. }
  3247. if len(g.OsType) == 0 {
  3248. g.OsType = string(extVM.GetOsType())
  3249. }
  3250. if len(g.Bios) == 0 {
  3251. g.Bios = string(extVM.GetBios())
  3252. }
  3253. g.Machine = extVM.GetMachine()
  3254. if !recycle {
  3255. g.HostId = host.Id
  3256. }
  3257. g.InternetMaxBandwidthOut = extVM.GetInternetMaxBandwidthOut()
  3258. g.Throughput = extVM.GetThroughput()
  3259. instanceType := extVM.GetInstanceType()
  3260. if len(instanceType) > 0 {
  3261. g.InstanceType = instanceType
  3262. }
  3263. memSizeMb := extVM.GetVmemSizeMB()
  3264. if g.VmemSize == 0 || g.VmemSize != memSizeMb {
  3265. if memSizeMb > 0 {
  3266. g.VmemSize = memSizeMb
  3267. } else {
  3268. sku, _ := ServerSkuManager.FetchSkuByNameAndProvider(instanceType, provider.GetFactory().GetName(), false)
  3269. if sku != nil && sku.MemorySizeMB > 0 {
  3270. g.VmemSize = sku.MemorySizeMB
  3271. }
  3272. }
  3273. }
  3274. g.Hypervisor = extVM.GetHypervisor()
  3275. if len(extVM.GetDescription()) > 0 {
  3276. g.Description = extVM.GetDescription()
  3277. }
  3278. g.BillingType = billing_api.TBillingType(extVM.GetBillingType())
  3279. g.ExpiredAt = time.Time{}
  3280. g.AutoRenew = false
  3281. if g.BillingType == billing_api.BILLING_TYPE_PREPAID {
  3282. g.ExpiredAt = extVM.GetExpiredAt()
  3283. g.AutoRenew = extVM.IsAutoRenew()
  3284. }
  3285. return nil
  3286. })
  3287. if err != nil {
  3288. log.Errorf("%s", err)
  3289. return err
  3290. }
  3291. db.OpsLog.LogSyncUpdate(g, diff, userCred)
  3292. if len(diff) > 0 {
  3293. notifyclient.EventNotify(ctx, userCred, notifyclient.SEventNotifyParam{
  3294. Obj: g,
  3295. Action: notifyclient.ActionSyncUpdate,
  3296. })
  3297. }
  3298. g.SyncOsInfo(ctx, userCred, extVM)
  3299. if account := host.GetCloudaccount(); account != nil {
  3300. syncVirtualResourceMetadata(ctx, userCred, g, extVM, account.ReadOnly)
  3301. }
  3302. if cloudprovider := host.GetCloudprovider(); cloudprovider != nil {
  3303. SyncCloudProject(ctx, userCred, g, syncOwnerId, extVM, cloudprovider)
  3304. }
  3305. if provider.GetFactory().IsSupportPrepaidResources() && recycle {
  3306. vhost, _ := g.GetHost()
  3307. err = vhost.syncWithCloudPrepaidVM(extVM, host)
  3308. if err != nil {
  3309. return err
  3310. }
  3311. }
  3312. return nil
  3313. }
  3314. func (manager *SGuestManager) newCloudVM(ctx context.Context, userCred mcclient.TokenCredential, provider cloudprovider.ICloudProvider, host *SHost, extVM cloudprovider.ICloudVM, syncOwnerId mcclient.IIdentityProvider) (*SGuest, error) {
  3315. guest := SGuest{}
  3316. guest.SetModelManager(manager, &guest)
  3317. guest.Status = extVM.GetStatus()
  3318. guest.PowerStates = extVM.GetPowerStates()
  3319. guest.InferPowerStates()
  3320. guest.ExternalId = extVM.GetGlobalId()
  3321. guest.VcpuCount = extVM.GetVcpuCount()
  3322. guest.CpuSockets = extVM.GetCpuSockets()
  3323. guest.BootOrder = extVM.GetBootOrder()
  3324. guest.Vga = extVM.GetVga()
  3325. guest.Vdi = extVM.GetVdi()
  3326. guest.OsArch = extVM.GetOsArch()
  3327. guest.OsType = string(extVM.GetOsType())
  3328. guest.Bios = string(extVM.GetBios())
  3329. guest.Machine = extVM.GetMachine()
  3330. guest.Hypervisor = extVM.GetHypervisor()
  3331. hostname := extVM.GetHostname()
  3332. if len(hostname) == 0 {
  3333. hostname = extVM.GetName()
  3334. }
  3335. guest.Hostname = pinyinutils.Text2Pinyin(hostname)
  3336. guest.InternetMaxBandwidthOut = extVM.GetInternetMaxBandwidthOut()
  3337. guest.Throughput = extVM.GetThroughput()
  3338. guest.Description = extVM.GetDescription()
  3339. guest.IsEmulated = extVM.IsEmulated()
  3340. guest.BillingType = billing_api.TBillingType(extVM.GetBillingType())
  3341. guest.ExpiredAt = time.Time{}
  3342. guest.AutoRenew = false
  3343. if guest.BillingType == billing_api.BILLING_TYPE_PREPAID {
  3344. guest.ExpiredAt = extVM.GetExpiredAt()
  3345. guest.AutoRenew = extVM.IsAutoRenew()
  3346. }
  3347. if createdAt := extVM.GetCreatedAt(); !createdAt.IsZero() {
  3348. guest.CreatedAt = createdAt
  3349. }
  3350. guest.HostId = host.Id
  3351. instanceType := extVM.GetInstanceType()
  3352. if len(instanceType) > 0 {
  3353. guest.InstanceType = instanceType
  3354. }
  3355. if extVM.GetHypervisor() == api.HYPERVISOR_AWS {
  3356. sku, err := ServerSkuManager.FetchSkuByNameAndProvider(instanceType, api.CLOUD_PROVIDER_AWS, false)
  3357. if err == nil {
  3358. guest.VmemSize = sku.MemorySizeMB
  3359. } else {
  3360. guest.VmemSize = extVM.GetVmemSizeMB()
  3361. }
  3362. } else {
  3363. guest.VmemSize = extVM.GetVmemSizeMB()
  3364. }
  3365. var err = func() error {
  3366. lockman.LockRawObject(ctx, manager.Keyword(), "name")
  3367. defer lockman.ReleaseRawObject(ctx, manager.Keyword(), "name")
  3368. newName, err := db.GenerateName(ctx, manager, syncOwnerId, extVM.GetName())
  3369. if err != nil {
  3370. return errors.Wrapf(err, "db.GenerateName")
  3371. }
  3372. guest.Name = newName
  3373. return manager.TableSpec().Insert(ctx, &guest)
  3374. }()
  3375. if err != nil {
  3376. return nil, errors.Wrapf(err, "Insert")
  3377. }
  3378. guest.SyncOsInfo(ctx, userCred, extVM)
  3379. syncVirtualResourceMetadata(ctx, userCred, &guest, extVM, false)
  3380. if cloudprovider := host.GetCloudprovider(); cloudprovider != nil {
  3381. SyncCloudProject(ctx, userCred, &guest, syncOwnerId, extVM, cloudprovider)
  3382. }
  3383. db.OpsLog.LogEvent(&guest, db.ACT_CREATE, guest.GetShortDesc(ctx), userCred)
  3384. if guest.Status == api.VM_RUNNING {
  3385. db.OpsLog.LogEvent(&guest, db.ACT_START, guest.GetShortDesc(ctx), userCred)
  3386. }
  3387. notifyclient.EventNotify(ctx, userCred, notifyclient.SEventNotifyParam{
  3388. Obj: &guest,
  3389. Action: notifyclient.ActionSyncCreate,
  3390. })
  3391. drv, _ := guest.GetDriver()
  3392. if drv != nil && drv.GetMaxSecurityGroupCount() == 0 {
  3393. db.Update(&guest, func() error {
  3394. guest.SecgrpId = ""
  3395. return nil
  3396. })
  3397. }
  3398. if guest.Status == api.VM_RUNNING {
  3399. db.OpsLog.LogEvent(&guest, db.ACT_START, guest.GetShortDesc(ctx), userCred)
  3400. }
  3401. return &guest, nil
  3402. }
  3403. func (manager *SGuestManager) TotalCount(
  3404. ctx context.Context,
  3405. scope rbacscope.TRbacScope,
  3406. ownerId mcclient.IIdentityProvider,
  3407. rangeObjs []db.IStandaloneModel,
  3408. status []string, hypervisors []string,
  3409. includeSystem bool, pendingDelete bool,
  3410. hostTypes []string, resourceTypes []string, providers []string, brands []string, cloudEnv string,
  3411. since *time.Time,
  3412. policyResult rbacutils.SPolicyResult,
  3413. ) map[string]SGuestCountStat {
  3414. return usageTotalGuestResourceCount(ctx, scope, ownerId, rangeObjs, status, hypervisors, includeSystem, pendingDelete, hostTypes, resourceTypes, providers, brands, cloudEnv, since, policyResult)
  3415. }
  3416. func (self *SGuest) detachNetworks(ctx context.Context, userCred mcclient.TokenCredential, gns []SGuestnetwork, reserve bool) error {
  3417. err := GuestnetworkManager.DeleteGuestNics(ctx, userCred, gns, reserve)
  3418. if err != nil {
  3419. return err
  3420. }
  3421. host, _ := self.GetHost()
  3422. if host != nil {
  3423. host.ClearSchedDescCache() // ignore error
  3424. }
  3425. return nil
  3426. }
  3427. func (self *SGuest) getAttach2NetworkCount(net *SNetwork) (int, error) {
  3428. q := GuestnetworkManager.Query()
  3429. q = q.Equals("guest_id", self.Id).Equals("network_id", net.Id)
  3430. return q.CountWithError()
  3431. }
  3432. func (self *SGuest) getUsableNicIndex() int {
  3433. nics, err := self.GetNetworks("")
  3434. if err != nil {
  3435. return -1
  3436. }
  3437. maxIndex := len(nics)
  3438. for i := 0; i <= maxIndex; i++ {
  3439. found := true
  3440. for j := range nics {
  3441. if nics[j].Index == i {
  3442. found = false
  3443. break
  3444. }
  3445. }
  3446. if found {
  3447. return i
  3448. }
  3449. }
  3450. panic(fmt.Sprintf("cannot find usable nic index for guest %s(%s)",
  3451. self.Name, self.Id))
  3452. }
  3453. func (self *SGuest) setOSProfile(ctx context.Context, userCred mcclient.TokenCredential, profile jsonutils.JSONObject) error {
  3454. return self.SetMetadata(ctx, "__os_profile__", profile, userCred)
  3455. }
  3456. func (self *SGuest) GetOSProfile() osprofile.SOSProfile {
  3457. osName := self.GetOS()
  3458. osProf := osprofile.GetOSProfile(osName, self.Hypervisor)
  3459. val := self.GetMetadata(context.Background(), "__os_profile__", nil)
  3460. if len(val) > 0 {
  3461. jsonVal, _ := jsonutils.ParseString(val)
  3462. if jsonVal != nil {
  3463. jsonVal.Unmarshal(&osProf)
  3464. }
  3465. }
  3466. return osProf
  3467. }
  3468. // Summary of network address allocation strategy
  3469. //
  3470. // # IpAddr when specified must be part of the network
  3471. //
  3472. // Use IpAddr without checking if it's already allocated when UseDesignatedIP
  3473. // is true. See b31bc7fa ("feature: 1. baremetal server reuse host ip...")
  3474. //
  3475. // Try IpAddr from reserved pool when allowed by TryReserved. Otherwise
  3476. // fallback to usual allocation method (AllocDir). Error when
  3477. // RequireDesignatedIP is true and the allocated address does not match IpAddr
  3478. type Attach2NetworkArgs struct {
  3479. Network *SNetwork
  3480. IpAddr string
  3481. Ip6Addr string
  3482. AllocDir api.IPAllocationDirection
  3483. TryReserved bool
  3484. RequireDesignatedIP bool
  3485. UseDesignatedIP bool
  3486. RequireIPv6 bool
  3487. StrictIPv6 bool
  3488. BwLimit int
  3489. NicDriver string
  3490. NumQueues int
  3491. RxTrafficLimit int64
  3492. TxTrafficLimit int64
  3493. NicConfs []SNicConfig
  3494. Virtual bool
  3495. IsDefault bool
  3496. PortMappings api.GuestPortMappings
  3497. BillingType billing_api.TBillingType
  3498. ChargeType billing_api.TNetChargeType
  3499. PendingUsage quotas.IQuota
  3500. }
  3501. func (args *Attach2NetworkArgs) onceArgs(i int) attach2NetworkOnceArgs {
  3502. if i < 0 || i > len(args.NicConfs)-1 {
  3503. return attach2NetworkOnceArgs{}
  3504. }
  3505. r := attach2NetworkOnceArgs{
  3506. network: args.Network,
  3507. ipAddr: args.IpAddr,
  3508. ip6Addr: args.Ip6Addr,
  3509. allocDir: args.AllocDir,
  3510. tryReserved: args.TryReserved,
  3511. requireDesignatedIP: args.RequireDesignatedIP,
  3512. useDesignatedIP: args.UseDesignatedIP,
  3513. requireIPv6: args.RequireIPv6,
  3514. strictIPv6: args.StrictIPv6,
  3515. bwLimit: args.BwLimit,
  3516. nicDriver: args.NicDriver,
  3517. numQueues: args.NumQueues,
  3518. txTrafficLimit: args.TxTrafficLimit,
  3519. rxTrafficLimit: args.RxTrafficLimit,
  3520. nicConf: args.NicConfs[i],
  3521. virtual: args.Virtual,
  3522. isDefault: args.IsDefault,
  3523. pendingUsage: args.PendingUsage,
  3524. portMappings: args.PortMappings,
  3525. billingType: args.BillingType,
  3526. chargeType: args.ChargeType,
  3527. }
  3528. if i > 0 {
  3529. r.ipAddr = ""
  3530. r.ip6Addr = ""
  3531. r.bwLimit = 0
  3532. r.virtual = true
  3533. r.tryReserved = false
  3534. r.requireDesignatedIP = false
  3535. r.useDesignatedIP = false
  3536. r.nicConf = args.NicConfs[i]
  3537. r.nicDriver = ""
  3538. r.numQueues = 1
  3539. r.isDefault = false
  3540. r.requireIPv6 = false
  3541. }
  3542. return r
  3543. }
  3544. type attach2NetworkOnceArgs struct {
  3545. network *SNetwork
  3546. ipAddr string
  3547. ip6Addr string
  3548. allocDir api.IPAllocationDirection
  3549. tryReserved bool
  3550. requireDesignatedIP bool
  3551. useDesignatedIP bool
  3552. requireIPv6 bool
  3553. strictIPv6 bool
  3554. bwLimit int
  3555. nicDriver string
  3556. numQueues int
  3557. nicConf SNicConfig
  3558. teamWithMac string
  3559. rxTrafficLimit int64
  3560. txTrafficLimit int64
  3561. virtual bool
  3562. isDefault bool
  3563. pendingUsage quotas.IQuota
  3564. portMappings api.GuestPortMappings
  3565. billingType billing_api.TBillingType
  3566. chargeType billing_api.TNetChargeType
  3567. }
  3568. func (self *SGuest) Attach2Network(
  3569. ctx context.Context,
  3570. userCred mcclient.TokenCredential,
  3571. args Attach2NetworkArgs,
  3572. ) ([]SGuestnetwork, error) {
  3573. log.Debugf("Attach2Network %s", jsonutils.Marshal(args))
  3574. onceArgs := args.onceArgs(0)
  3575. firstNic, err := self.attach2NetworkOnce(ctx, userCred, onceArgs)
  3576. if err != nil {
  3577. return nil, errors.Wrap(err, "self.attach2NetworkOnce")
  3578. }
  3579. retNics := []SGuestnetwork{*firstNic}
  3580. if len(args.NicConfs) > 1 {
  3581. firstMac, _ := netutils.ParseMac(firstNic.MacAddr)
  3582. for i := 1; i < len(args.NicConfs); i += 1 {
  3583. onceArgs := args.onceArgs(i)
  3584. onceArgs.nicDriver = firstNic.Driver
  3585. onceArgs.teamWithMac = firstNic.MacAddr
  3586. if onceArgs.nicConf.Mac == "" {
  3587. onceArgs.nicConf.Mac = firstMac.Add(i).String()
  3588. }
  3589. gn, err := self.attach2NetworkOnce(ctx, userCred, onceArgs)
  3590. if err != nil {
  3591. return retNics, errors.Wrap(err, "self.attach2NetworkOnce")
  3592. }
  3593. retNics = append(retNics, *gn)
  3594. }
  3595. }
  3596. return retNics, nil
  3597. }
  3598. func (self *SGuest) attach2NetworkOnce(
  3599. ctx context.Context,
  3600. userCred mcclient.TokenCredential,
  3601. args attach2NetworkOnceArgs,
  3602. ) (*SGuestnetwork, error) {
  3603. var (
  3604. index = args.nicConf.Index
  3605. nicDriver = args.nicDriver
  3606. )
  3607. if index < 0 {
  3608. index = self.getUsableNicIndex()
  3609. }
  3610. if nicDriver == "" {
  3611. osProf := self.GetOSProfile()
  3612. nicDriver = osProf.NetDriver
  3613. }
  3614. newArgs := newGuestNetworkArgs{
  3615. guest: self,
  3616. network: args.network,
  3617. index: index,
  3618. ipAddr: args.ipAddr,
  3619. ip6Addr: args.ip6Addr,
  3620. allocDir: args.allocDir,
  3621. tryReserved: args.tryReserved,
  3622. requireDesignatedIP: args.requireDesignatedIP,
  3623. useDesignatedIP: args.useDesignatedIP,
  3624. requireIPv6: args.requireIPv6,
  3625. strictIPv6: args.strictIPv6,
  3626. ifname: args.nicConf.Ifname,
  3627. macAddr: args.nicConf.Mac,
  3628. bwLimit: args.bwLimit,
  3629. nicDriver: nicDriver,
  3630. numQueues: args.numQueues,
  3631. teamWithMac: args.teamWithMac,
  3632. rxTrafficLimit: args.rxTrafficLimit,
  3633. txTrafficLimit: args.txTrafficLimit,
  3634. virtual: args.virtual,
  3635. isDefault: args.isDefault,
  3636. portMappings: args.portMappings,
  3637. billingType: args.billingType,
  3638. chargeType: args.chargeType,
  3639. }
  3640. lockman.LockClass(ctx, QuotaManager, self.ProjectId)
  3641. defer lockman.ReleaseClass(ctx, QuotaManager, self.ProjectId)
  3642. guestnic, err := GuestnetworkManager.newGuestNetwork(ctx, userCred, newArgs)
  3643. if err != nil {
  3644. return nil, errors.Wrap(err, "GuestnetworkManager.newGuestNetwork")
  3645. }
  3646. var (
  3647. network = args.network
  3648. pendingUsage = args.pendingUsage
  3649. teamWithMac = args.teamWithMac
  3650. )
  3651. network.updateDnsRecord(guestnic, true)
  3652. if pendingUsage != nil && len(teamWithMac) == 0 {
  3653. cancelUsage := SRegionQuota{}
  3654. if network.IsExitNetwork() {
  3655. cancelUsage.Eport = 1
  3656. } else {
  3657. cancelUsage.Port = 1
  3658. }
  3659. keys, err := self.GetRegionalQuotaKeys()
  3660. if err != nil {
  3661. log.Warningf("self.GetRegionalQuotaKeys fail %s", err)
  3662. }
  3663. cancelUsage.SetKeys(keys)
  3664. err = quotas.CancelPendingUsage(ctx, userCred, pendingUsage, &cancelUsage, true)
  3665. if err != nil {
  3666. log.Warningf("QuotaManager.CancelPendingUsage fail %s", err)
  3667. }
  3668. }
  3669. db.OpsLog.LogAttachEvent(ctx, self, network, userCred, guestnic.GetShortDesc(ctx))
  3670. return guestnic, nil
  3671. }
  3672. func getCloudNicNetwork(ctx context.Context, vnic cloudprovider.ICloudNic, host *SHost, ipList []string, index int) (*SNetwork, error) {
  3673. vnetId := vnic.GetINetworkId()
  3674. if len(vnetId) == 0 {
  3675. if vnic.InClassicNetwork() {
  3676. region, _ := host.GetRegion()
  3677. cloudprovider := host.GetCloudprovider()
  3678. vpc, err := VpcManager.GetOrCreateVpcForClassicNetwork(ctx, cloudprovider, region)
  3679. if err != nil {
  3680. return nil, errors.Wrap(err, "NewVpcForClassicNetwork")
  3681. }
  3682. zone, _ := host.GetZone()
  3683. wire, err := WireManager.GetOrCreateWireForClassicNetwork(ctx, vpc, zone)
  3684. if err != nil {
  3685. return nil, errors.Wrap(err, "NewWireForClassicNetwork")
  3686. }
  3687. return NetworkManager.GetOrCreateClassicNetwork(ctx, wire)
  3688. }
  3689. ip := vnic.GetIP()
  3690. if len(ip) == 0 {
  3691. if index < len(ipList) {
  3692. ip = ipList[index]
  3693. }
  3694. if len(ip) == 0 {
  3695. return nil, fmt.Errorf("Cannot find inetwork for vnics %s: no ip", vnic.GetMAC())
  3696. }
  3697. }
  3698. // find network by IP
  3699. return host.getNetworkOfIPOnHost(ctx, ip)
  3700. }
  3701. localNetObj, err := db.FetchByExternalIdAndManagerId(NetworkManager, vnetId, func(q *sqlchemy.SQuery) *sqlchemy.SQuery {
  3702. // vpc := VpcManager.Query().SubQuery()
  3703. wire := WireManager.Query().SubQuery()
  3704. return q.Join(wire, sqlchemy.Equals(q.Field("wire_id"), wire.Field("id"))).
  3705. Filter(sqlchemy.Equals(wire.Field("manager_id"), host.ManagerId))
  3706. })
  3707. if err != nil {
  3708. return nil, errors.Wrapf(err, "Cannot find network of external_id %s", vnetId)
  3709. }
  3710. localNet := localNetObj.(*SNetwork)
  3711. return localNet, nil
  3712. }
  3713. func (self *SGuest) SyncVMNics(
  3714. ctx context.Context,
  3715. userCred mcclient.TokenCredential,
  3716. host *SHost,
  3717. vnics []cloudprovider.ICloudNic,
  3718. ipList []string,
  3719. ) compare.SyncResult {
  3720. result := compare.SyncResult{}
  3721. nics, err := self.GetNetworks("")
  3722. if err != nil {
  3723. result.Error(err)
  3724. return result
  3725. }
  3726. removed := make([]SGuestnetwork, 0)
  3727. commondb := make([]SGuestnetwork, 0)
  3728. commonext := make([]cloudprovider.ICloudNic, 0)
  3729. added := make([]cloudprovider.ICloudNic, 0)
  3730. set := compare.SCompareSet{
  3731. DBFunc: "GetMAC",
  3732. DBSet: nics,
  3733. ExtFunc: "GetMAC",
  3734. ExtSet: vnics,
  3735. }
  3736. err = compare.CompareSetsFunc(set, &removed, &commondb, &commonext, &added, nil)
  3737. if err != nil {
  3738. result.Error(errors.Wrapf(err, "compare.CompareSets"))
  3739. return result
  3740. }
  3741. log.Debugf("SyncVMNics: removed: %d common: %d add: %d", len(removed), len(commondb), len(added))
  3742. for i := 0; i < len(removed); i += 1 {
  3743. err = self.detachNetworks(ctx, userCred, []SGuestnetwork{removed[i]}, false)
  3744. if err != nil {
  3745. result.DeleteError(err)
  3746. continue
  3747. }
  3748. result.Delete()
  3749. }
  3750. for i := 0; i < len(commondb); i += 1 {
  3751. err := NetworkAddressManager.syncGuestnetworkICloudNic(ctx, userCred, &commondb[i], commonext[i])
  3752. if err != nil {
  3753. result.UpdateError(err)
  3754. continue
  3755. }
  3756. _, err = db.Update(&commondb[i], func() error {
  3757. network, _ := commondb[i].GetNetwork()
  3758. ip := commonext[i].GetIP()
  3759. ip6 := commonext[i].GetIP6()
  3760. if len(ip) > 0 {
  3761. if !network.Contains(ip) {
  3762. localNet, err := getCloudNicNetwork(ctx, commonext[i], host, ipList, i)
  3763. if err != nil {
  3764. return errors.Wrapf(err, "getCloudNicNetwork")
  3765. }
  3766. commondb[i].NetworkId = localNet.Id
  3767. commondb[i].IpAddr = ip
  3768. } else {
  3769. commondb[i].IpAddr = ip
  3770. commondb[i].Ip6Addr = ip6
  3771. }
  3772. }
  3773. commondb[i].Driver = commonext[i].GetDriver()
  3774. return nil
  3775. })
  3776. if err != nil {
  3777. result.UpdateError(errors.Wrapf(err, "db.Update"))
  3778. continue
  3779. }
  3780. result.Update()
  3781. }
  3782. syncIps := make([]string, 0)
  3783. for i := 0; i < len(added); i += 1 {
  3784. localNet, err := getCloudNicNetwork(ctx, added[i], host, ipList, i)
  3785. if err != nil {
  3786. log.Errorf("SyncVMNics getCloudNicNetwork add fail: %s", err)
  3787. if ip := added[i].GetIP(); len(ip) > 0 {
  3788. syncIps = append(syncIps, ip)
  3789. }
  3790. result.AddError(err)
  3791. continue
  3792. }
  3793. nicConf := SNicConfig{
  3794. Mac: added[i].GetMAC(),
  3795. Index: -1,
  3796. Ifname: "",
  3797. }
  3798. ip := added[i].GetIP()
  3799. // vmware, may be sync fix ip
  3800. if len(ip) == 0 && len(ipList) > 0 {
  3801. ip = ipList[0]
  3802. }
  3803. // always try allocate from reserved pool
  3804. guestnetworks, err := self.Attach2Network(ctx, userCred, Attach2NetworkArgs{
  3805. Network: localNet,
  3806. IpAddr: ip,
  3807. Ip6Addr: added[i].GetIP6(),
  3808. NicDriver: added[i].GetDriver(),
  3809. TryReserved: true,
  3810. AllocDir: api.IPAllocationDefault,
  3811. RequireDesignatedIP: true,
  3812. // UseDesignatedIP: true,
  3813. NicConfs: []SNicConfig{nicConf},
  3814. })
  3815. if err != nil {
  3816. result.AddError(err)
  3817. continue
  3818. }
  3819. if len(ipList) > 0 {
  3820. // shift
  3821. ipList = ipList[1:]
  3822. }
  3823. result.Add()
  3824. for i := range guestnetworks {
  3825. guestnetwork := &guestnetworks[i]
  3826. if NetworkAddressManager.syncGuestnetworkICloudNic(
  3827. ctx, userCred, guestnetwork, added[i]); err != nil {
  3828. result.AddError(err)
  3829. }
  3830. }
  3831. }
  3832. if len(syncIps) > 0 {
  3833. self.SetMetadata(ctx, "sync_ips", strings.Join(syncIps, ","), userCred)
  3834. } else {
  3835. self.SetMetadata(ctx, "sync_ips", "None", userCred)
  3836. }
  3837. return result
  3838. }
  3839. func (self *SGuest) IsAttach2Disk(disk *SDisk) (bool, error) {
  3840. return self.isAttach2Disk(disk)
  3841. }
  3842. func (self *SGuest) isAttach2Disk(disk *SDisk) (bool, error) {
  3843. q := GuestdiskManager.Query().Equals("disk_id", disk.Id).Equals("guest_id", self.Id)
  3844. cnt, err := q.CountWithError()
  3845. if err != nil {
  3846. return false, err
  3847. }
  3848. return cnt > 0, nil
  3849. }
  3850. func (self *SGuest) getDiskIndex() int8 {
  3851. guestdisks, _ := self.GetGuestDisks()
  3852. var max uint
  3853. for i := 0; i < len(guestdisks); i++ {
  3854. if uint(guestdisks[i].Index) > max {
  3855. max = uint(guestdisks[i].Index)
  3856. }
  3857. }
  3858. idxs := make([]int, max+1)
  3859. for i := 0; i < len(guestdisks); i++ {
  3860. idxs[guestdisks[i].Index] = 1
  3861. }
  3862. // find first idx not set
  3863. for i := 0; i < len(idxs); i++ {
  3864. if idxs[i] != 1 {
  3865. return int8(i)
  3866. }
  3867. }
  3868. return int8(max + 1)
  3869. }
  3870. func (self *SGuest) AttachDisk(ctx context.Context, disk *SDisk, userCred mcclient.TokenCredential, driver string, cache string, mountpoint string, bootIndex *int8) error {
  3871. return self.attach2Disk(ctx, disk, userCred, driver, cache, mountpoint, bootIndex)
  3872. }
  3873. func (self *SGuest) attach2Disk(ctx context.Context, disk *SDisk, userCred mcclient.TokenCredential, driver string, cache string, mountpoint string, bootIndex *int8) error {
  3874. attached, err := self.isAttach2Disk(disk)
  3875. if err != nil {
  3876. return errors.Wrap(err, "isAttach2Disk")
  3877. }
  3878. if attached {
  3879. return fmt.Errorf("Guest has been attached to disk")
  3880. }
  3881. if len(driver) == 0 {
  3882. // depends the last disk of this guest
  3883. existingDisks, _ := self.GetGuestDisks()
  3884. if len(existingDisks) > 0 {
  3885. prevDisk := existingDisks[len(existingDisks)-1]
  3886. if prevDisk.Driver == api.DISK_DRIVER_IDE {
  3887. driver = api.DISK_DRIVER_VIRTIO
  3888. } else {
  3889. driver = prevDisk.Driver
  3890. }
  3891. } else {
  3892. osProf := self.GetOSProfile()
  3893. driver = osProf.DiskDriver
  3894. }
  3895. }
  3896. guestdisk := SGuestdisk{}
  3897. guestdisk.SetModelManager(GuestdiskManager, &guestdisk)
  3898. guestdisk.DiskId = disk.Id
  3899. guestdisk.GuestId = self.Id
  3900. lockman.LockObject(ctx, self)
  3901. defer lockman.ReleaseObject(ctx, self)
  3902. guestdisk.Index = self.getDiskIndex()
  3903. if bootIndex != nil {
  3904. guestdisk.BootIndex = *bootIndex
  3905. } else {
  3906. guestdisk.BootIndex = -1
  3907. }
  3908. err = guestdisk.DoSave(ctx, driver, cache, mountpoint)
  3909. if err == nil {
  3910. db.OpsLog.LogAttachEvent(ctx, self, disk, userCred, nil)
  3911. }
  3912. return err
  3913. }
  3914. func (self *SGuest) SyncVMDisks(
  3915. ctx context.Context,
  3916. userCred mcclient.TokenCredential,
  3917. provider cloudprovider.ICloudProvider,
  3918. host *SHost,
  3919. vdisks []cloudprovider.ICloudDisk,
  3920. syncOwnerId mcclient.IIdentityProvider,
  3921. ) compare.SyncResult {
  3922. lockman.LockRawObject(ctx, self.Id, DiskManager.Keyword())
  3923. defer lockman.ReleaseRawObject(ctx, self.Id, DiskManager.Keyword())
  3924. result := compare.SyncResult{}
  3925. dbDisks, err := self.GetDisks()
  3926. if err != nil {
  3927. result.Error(errors.Wrapf(err, "GetDisks"))
  3928. return result
  3929. }
  3930. removed := make([]SDisk, 0)
  3931. commondb := make([]SDisk, 0)
  3932. commonext := make([]cloudprovider.ICloudDisk, 0)
  3933. added := make([]cloudprovider.ICloudDisk, 0)
  3934. err = compare.CompareSets(dbDisks, vdisks, &removed, &commondb, &commonext, &added)
  3935. if err != nil {
  3936. result.Error(errors.Wrapf(err, "compare.CompareSets"))
  3937. return result
  3938. }
  3939. for i := 0; i < len(removed); i += 1 {
  3940. self.DetachDisk(ctx, &removed[i], userCred)
  3941. result.Delete()
  3942. }
  3943. for i := 0; i < len(commondb); i += 1 {
  3944. if commondb[i].PendingDeleted != self.PendingDeleted { //避免主机正常,磁盘在回收站的情况
  3945. db.Update(&commondb[i], func() error {
  3946. commondb[i].PendingDeleted = self.PendingDeleted
  3947. return nil
  3948. })
  3949. }
  3950. commondb[i].SyncCloudProjectId(userCred, self.GetOwnerId())
  3951. result.Update()
  3952. }
  3953. for i := 0; i < len(added); i += 1 {
  3954. disk, err := DiskManager.findOrCreateDisk(ctx, userCred, provider, added[i], -1, self.GetOwnerId(), host.ManagerId)
  3955. if err != nil {
  3956. result.AddError(errors.Wrapf(err, "findOrCreateDisk(%s)", added[i].GetGlobalId()))
  3957. continue
  3958. }
  3959. disk.SyncCloudProjectId(userCred, self.GetOwnerId())
  3960. err = self.attach2Disk(ctx, disk, userCred, added[i].GetDriver(), added[i].GetCacheMode(), added[i].GetMountpoint(), nil)
  3961. if err != nil {
  3962. result.AddError(err)
  3963. continue
  3964. }
  3965. result.Add()
  3966. }
  3967. err = self.fixSysDiskIndex()
  3968. if err != nil {
  3969. result.Error(errors.Wrapf(err, "fixSysDiskIndex"))
  3970. }
  3971. return result
  3972. }
  3973. func (self *SGuest) setSystemDisk() error {
  3974. sq := GuestdiskManager.Query("disk_id").Equals("guest_id", self.Id).Equals("index", 0).SubQuery()
  3975. disks := DiskManager.Query().In("id", sq)
  3976. disk := &SDisk{}
  3977. disk.SetModelManager(DiskManager, disk)
  3978. err := disks.First(disk)
  3979. if err != nil {
  3980. return err
  3981. }
  3982. _, err = db.Update(disk, func() error {
  3983. disk.DiskType = api.DISK_TYPE_SYS
  3984. return nil
  3985. })
  3986. return err
  3987. }
  3988. func (self *SGuest) fixSysDiskIndex() error {
  3989. disks := DiskManager.Query().SubQuery()
  3990. sysQ := GuestdiskManager.Query().Equals("guest_id", self.Id)
  3991. sysQ = sysQ.Join(disks, sqlchemy.Equals(disks.Field("id"), sysQ.Field("disk_id"))).Filter(sqlchemy.Equals(disks.Field("disk_type"), api.DISK_TYPE_SYS))
  3992. sysDisk := &SGuestdisk{}
  3993. sysDisk.SetModelManager(GuestdiskManager, sysDisk)
  3994. err := sysQ.First(sysDisk)
  3995. if err != nil {
  3996. if errors.Cause(err) == sql.ErrNoRows {
  3997. return self.setSystemDisk()
  3998. }
  3999. return err
  4000. }
  4001. if sysDisk.Index == 0 {
  4002. return nil
  4003. }
  4004. q := GuestdiskManager.Query().Equals("guest_id", self.Id).Equals("index", 0)
  4005. firstDisk := &SGuestdisk{}
  4006. firstDisk.SetModelManager(GuestdiskManager, firstDisk)
  4007. err = q.First(firstDisk)
  4008. if err != nil {
  4009. return err
  4010. }
  4011. _, err = db.Update(firstDisk, func() error {
  4012. firstDisk.Index = sysDisk.Index
  4013. return nil
  4014. })
  4015. if err != nil {
  4016. return err
  4017. }
  4018. _, err = db.Update(sysDisk, func() error {
  4019. sysDisk.Index = 0
  4020. return nil
  4021. })
  4022. return err
  4023. }
  4024. func filterGuestByRange(q *sqlchemy.SQuery, rangeObjs []db.IStandaloneModel, hostTypes []string, resourceTypes []string, providers []string, brands []string, cloudEnv string) *sqlchemy.SQuery {
  4025. hosts := HostManager.Query().SubQuery()
  4026. subq := hosts.Query(hosts.Field("id"))
  4027. subq = AttachUsageQuery(subq, hosts, hostTypes, resourceTypes, providers, brands, cloudEnv, rangeObjs)
  4028. q = q.In("host_id", subq.SubQuery())
  4029. return q
  4030. }
  4031. type SGuestCountStat struct {
  4032. TotalGuestCount int
  4033. TotalCpuCount int
  4034. TotalMemSize int
  4035. TotalDiskSize int
  4036. TotalIsolatedCount int
  4037. TotalBackupGuestCount int
  4038. TotalBackupCpuCount int
  4039. TotalBackupMemSize int
  4040. TotalBackupDiskSize int
  4041. }
  4042. func usageTotalGuestResourceCount(
  4043. ctx context.Context,
  4044. scope rbacscope.TRbacScope,
  4045. ownerId mcclient.IIdentityProvider,
  4046. rangeObjs []db.IStandaloneModel,
  4047. status []string,
  4048. hypervisors []string,
  4049. includeSystem bool,
  4050. pendingDelete bool,
  4051. hostTypes []string,
  4052. resourceTypes []string,
  4053. providers []string, brands []string, cloudEnv string,
  4054. since *time.Time,
  4055. policyResult rbacutils.SPolicyResult,
  4056. ) map[string]SGuestCountStat {
  4057. countStat := make(map[string]SGuestCountStat)
  4058. for _, arch := range []string{apis.OS_ARCH_ALL, apis.OS_ARCH_X86_64, apis.OS_ARCH_AARCH64} {
  4059. allStat := usageTotalGuestResourceCountByArch(
  4060. ctx, scope, ownerId, rangeObjs, status,
  4061. hypervisors, includeSystem, pendingDelete,
  4062. hostTypes, resourceTypes, providers, brands,
  4063. cloudEnv, since, policyResult, arch,
  4064. )
  4065. countStat[arch] = allStat
  4066. }
  4067. return countStat
  4068. }
  4069. func usageTotalGuestResourceCountByArch(
  4070. ctx context.Context,
  4071. scope rbacscope.TRbacScope,
  4072. ownerId mcclient.IIdentityProvider,
  4073. rangeObjs []db.IStandaloneModel,
  4074. status []string,
  4075. hypervisors []string,
  4076. includeSystem bool,
  4077. pendingDelete bool,
  4078. hostTypes []string,
  4079. resourceTypes []string,
  4080. providers []string, brands []string, cloudEnv string,
  4081. since *time.Time,
  4082. policyResult rbacutils.SPolicyResult,
  4083. osArch string,
  4084. ) SGuestCountStat {
  4085. q, guests := _guestResourceCountQuery(
  4086. ctx,
  4087. scope, ownerId, rangeObjs, status, hypervisors,
  4088. pendingDelete, hostTypes, resourceTypes, providers, brands, cloudEnv, since,
  4089. policyResult, osArch,
  4090. )
  4091. if !includeSystem {
  4092. q = q.Filter(sqlchemy.OR(
  4093. sqlchemy.IsNull(guests.Field("is_system")), sqlchemy.IsFalse(guests.Field("is_system"))))
  4094. }
  4095. stat := SGuestCountStat{}
  4096. row := q.Row()
  4097. err := q.Row2Struct(row, &stat)
  4098. if err != nil {
  4099. log.Errorf("%s", err)
  4100. }
  4101. stat.TotalCpuCount += stat.TotalBackupCpuCount
  4102. stat.TotalMemSize += stat.TotalBackupMemSize
  4103. stat.TotalDiskSize += stat.TotalBackupDiskSize
  4104. return stat
  4105. }
  4106. func _guestResourceCountQuery(
  4107. ctx context.Context,
  4108. scope rbacscope.TRbacScope,
  4109. ownerId mcclient.IIdentityProvider,
  4110. rangeObjs []db.IStandaloneModel,
  4111. status []string,
  4112. hypervisors []string,
  4113. pendingDelete bool,
  4114. hostTypes []string,
  4115. resourceTypes []string,
  4116. providers []string, brands []string, cloudEnv string,
  4117. since *time.Time,
  4118. policyResult rbacutils.SPolicyResult,
  4119. osArch string,
  4120. ) (*sqlchemy.SQuery, *sqlchemy.SSubQuery) {
  4121. guestdisks := GuestdiskManager.Query().SubQuery()
  4122. disks := DiskManager.Query().SubQuery()
  4123. diskQuery := guestdisks.Query(guestdisks.Field("guest_id"), sqlchemy.SUM("guest_disk_size", disks.Field("disk_size")))
  4124. diskQuery = diskQuery.Join(disks, sqlchemy.Equals(guestdisks.Field("disk_id"), disks.Field("id")))
  4125. diskQuery = diskQuery.GroupBy(guestdisks.Field("guest_id"))
  4126. diskSubQuery := diskQuery.SubQuery()
  4127. backupDiskQuery := guestdisks.Query(guestdisks.Field("guest_id"), sqlchemy.SUM("guest_disk_size", disks.Field("disk_size")))
  4128. backupDiskQuery = backupDiskQuery.LeftJoin(disks, sqlchemy.Equals(guestdisks.Field("disk_id"), disks.Field("id")))
  4129. backupDiskQuery = backupDiskQuery.Filter(sqlchemy.IsNotEmpty(disks.Field("backup_storage_id")))
  4130. backupDiskQuery = backupDiskQuery.GroupBy(guestdisks.Field("guest_id"))
  4131. diskBackupSubQuery := backupDiskQuery.SubQuery()
  4132. // diskBackupSubQuery := diskQuery.IsNotEmpty("backup_storage_id").SubQuery()
  4133. isolated := IsolatedDeviceManager.Query().SubQuery()
  4134. isoDevQuery := isolated.Query(isolated.Field("guest_id"), sqlchemy.COUNT("device_sum"))
  4135. isoDevQuery = isoDevQuery.Filter(sqlchemy.IsNotNull(isolated.Field("guest_id")))
  4136. isoDevQuery = isoDevQuery.GroupBy(isolated.Field("guest_id"))
  4137. isoDevSubQuery := isoDevQuery.SubQuery()
  4138. var gq *sqlchemy.SQuery
  4139. if since != nil && !since.IsZero() {
  4140. gq = GuestManager.RawQuery()
  4141. } else {
  4142. gq = GuestManager.Query()
  4143. }
  4144. if osArch != "" && osArch != apis.OS_ARCH_ALL {
  4145. gq = gq.Equals("os_arch", osArch)
  4146. }
  4147. if len(rangeObjs) > 0 || len(hostTypes) > 0 || len(resourceTypes) > 0 || len(providers) > 0 || len(brands) > 0 || len(cloudEnv) > 0 {
  4148. gq = filterGuestByRange(gq, rangeObjs, hostTypes, resourceTypes, providers, brands, cloudEnv)
  4149. }
  4150. switch scope {
  4151. case rbacscope.ScopeSystem:
  4152. case rbacscope.ScopeDomain:
  4153. gq = gq.Filter(sqlchemy.Equals(gq.Field("domain_id"), ownerId.GetProjectDomainId()))
  4154. case rbacscope.ScopeProject:
  4155. gq = gq.Filter(sqlchemy.Equals(gq.Field("tenant_id"), ownerId.GetProjectId()))
  4156. }
  4157. if len(status) > 0 {
  4158. gq = gq.Filter(sqlchemy.In(gq.Field("status"), status))
  4159. }
  4160. if len(hypervisors) > 0 {
  4161. gq = gq.Filter(sqlchemy.In(gq.Field("hypervisor"), hypervisors))
  4162. }
  4163. if pendingDelete {
  4164. gq = gq.Filter(sqlchemy.IsTrue(gq.Field("pending_deleted")))
  4165. } else {
  4166. gq = gq.Filter(sqlchemy.OR(sqlchemy.IsNull(gq.Field("pending_deleted")), sqlchemy.IsFalse(gq.Field("pending_deleted"))))
  4167. }
  4168. if since != nil && !since.IsZero() {
  4169. gq = gq.Filter(sqlchemy.GT(gq.Field("created_at"), *since))
  4170. }
  4171. gq = db.ObjectIdQueryWithPolicyResult(ctx, gq, GuestManager, policyResult)
  4172. guests := gq.SubQuery()
  4173. guestBackupSubQuery := GuestManager.Query(
  4174. "id",
  4175. "vcpu_count",
  4176. "vmem_size",
  4177. ).IsNotEmpty("backup_host_id").SubQuery()
  4178. q := guests.Query(sqlchemy.COUNT("total_guest_count"),
  4179. sqlchemy.SUM("total_cpu_count", guests.Field("vcpu_count")),
  4180. sqlchemy.SUM("total_mem_size", guests.Field("vmem_size")),
  4181. sqlchemy.SUM("total_disk_size", diskSubQuery.Field("guest_disk_size")),
  4182. sqlchemy.SUM("total_isolated_count", isoDevSubQuery.Field("device_sum")),
  4183. sqlchemy.SUM("total_backup_disk_size", diskBackupSubQuery.Field("guest_disk_size")),
  4184. sqlchemy.SUM("total_backup_cpu_count", guestBackupSubQuery.Field("vcpu_count")),
  4185. sqlchemy.SUM("total_backup_mem_size", guestBackupSubQuery.Field("vmem_size")),
  4186. sqlchemy.COUNT("total_backup_guest_count", guestBackupSubQuery.Field("id")),
  4187. )
  4188. q = q.LeftJoin(guestBackupSubQuery, sqlchemy.Equals(guestBackupSubQuery.Field("id"), guests.Field("id")))
  4189. q = q.LeftJoin(diskSubQuery, sqlchemy.Equals(diskSubQuery.Field("guest_id"), guests.Field("id")))
  4190. q = q.LeftJoin(diskBackupSubQuery, sqlchemy.Equals(diskBackupSubQuery.Field("guest_id"), guests.Field("id")))
  4191. q = q.LeftJoin(isoDevSubQuery, sqlchemy.Equals(isoDevSubQuery.Field("guest_id"), guests.Field("id")))
  4192. return q, guests
  4193. }
  4194. func (self *SGuest) getDefaultNetworkConfig() *api.NetworkConfig {
  4195. netConf := api.NetworkConfig{}
  4196. netConf.BwLimit = options.Options.DefaultBandwidth
  4197. osProf := self.GetOSProfile()
  4198. netConf.Driver = osProf.NetDriver
  4199. return &netConf
  4200. }
  4201. func (self *SGuest) CreateNetworksOnHost(
  4202. ctx context.Context,
  4203. userCred mcclient.TokenCredential,
  4204. host *SHost,
  4205. netArray []*api.NetworkConfig,
  4206. pendingUsage, pendingUsageZone quotas.IQuota,
  4207. candidateNets []*schedapi.CandidateNet,
  4208. ) error {
  4209. if len(netArray) == 0 {
  4210. netConfig := self.getDefaultNetworkConfig()
  4211. _, err := self.attach2RandomNetwork(ctx, userCred, host, netConfig, pendingUsage)
  4212. return errors.Wrap(err, "self.attach2RandomNetwork")
  4213. }
  4214. for idx := range netArray {
  4215. netConfig, err := parseNetworkInfo(ctx, userCred, netArray[idx])
  4216. if err != nil {
  4217. return errors.Wrapf(err, "parseNetworkInfo at %d", idx)
  4218. }
  4219. var candidateNet *schedapi.CandidateNet
  4220. if len(candidateNets) > idx {
  4221. candidateNet = candidateNets[idx]
  4222. }
  4223. networkIds := []string{}
  4224. if candidateNet != nil {
  4225. networkIds = candidateNet.NetworkIds
  4226. }
  4227. if idx == 0 && netConfig.NumQueues == 0 {
  4228. numQueues := self.VcpuCount / 2
  4229. if numQueues > 16 {
  4230. numQueues = 16
  4231. }
  4232. netConfig.NumQueues = numQueues
  4233. }
  4234. gns, err := self.attach2NetworkDesc(ctx, userCred, host, netConfig, pendingUsage, networkIds)
  4235. if err != nil {
  4236. return errors.Wrap(err, "self.attach2NetworkDesc")
  4237. }
  4238. if netConfig.SriovDevice != nil {
  4239. err = self.allocSriovNicDevice(ctx, userCred, host, &gns[0], netConfig, pendingUsageZone)
  4240. if err != nil {
  4241. return errors.Wrap(err, "self.allocSriovNicDevice")
  4242. }
  4243. }
  4244. if len(netConfig.Secgroups) > 0 {
  4245. err = self.SaveNetworkSecgroups(ctx, userCred, netConfig.Secgroups, gns[0].Index)
  4246. if err != nil {
  4247. return errors.Wrap(err, "SaveNetworkSecgroups")
  4248. }
  4249. }
  4250. }
  4251. return nil
  4252. }
  4253. func (self *SGuest) allocSriovNicDevice(
  4254. ctx context.Context,
  4255. userCred mcclient.TokenCredential,
  4256. host *SHost,
  4257. gn *SGuestnetwork, netConfig *api.NetworkConfig,
  4258. pendingUsageZone quotas.IQuota,
  4259. ) error {
  4260. net, err := gn.GetNetwork()
  4261. if err != nil {
  4262. return errors.Wrapf(err, "GetNetwork")
  4263. }
  4264. netConfig.SriovDevice.NetworkIndex = &gn.Index
  4265. netConfig.SriovDevice.WireId = net.WireId
  4266. err = self.createIsolatedDeviceOnHost(ctx, userCred, host, netConfig.SriovDevice, pendingUsageZone, nil, nil)
  4267. if err != nil {
  4268. return errors.Wrap(err, "self.createIsolatedDeviceOnHost")
  4269. }
  4270. dev, err := self.GetIsolatedDeviceByNetworkIndex(gn.Index)
  4271. if err != nil {
  4272. return errors.Wrap(err, "self.GetIsolatedDeviceByNetworkIndex")
  4273. }
  4274. if dev.OvsOffloadInterface != "" {
  4275. _, err = db.Update(gn, func() error {
  4276. gn.Ifname = dev.OvsOffloadInterface
  4277. return nil
  4278. })
  4279. if err != nil {
  4280. return errors.Wrap(err, "update sriov network ifname")
  4281. }
  4282. }
  4283. return nil
  4284. }
  4285. func (self *SGuest) attach2NetworkDesc(
  4286. ctx context.Context,
  4287. userCred mcclient.TokenCredential,
  4288. host *SHost,
  4289. netConfig *api.NetworkConfig,
  4290. pendingUsage quotas.IQuota,
  4291. candiateNetIds []string,
  4292. ) ([]SGuestnetwork, error) {
  4293. var gns []SGuestnetwork
  4294. var errs []error
  4295. tryNetworkIds := []string{}
  4296. if len(netConfig.Network) > 0 {
  4297. tryNetworkIds = append(tryNetworkIds, netConfig.Network)
  4298. }
  4299. if len(candiateNetIds) > 0 {
  4300. // suggestion by scheduler
  4301. tryNetworkIds = append(tryNetworkIds, candiateNetIds...)
  4302. }
  4303. if len(tryNetworkIds) > 0 {
  4304. for _, tryNetwork := range tryNetworkIds {
  4305. var err error
  4306. netConfig.Network = tryNetwork
  4307. gns, err = self.attach2NamedNetworkDesc(ctx, userCred, host, netConfig, pendingUsage)
  4308. if err == nil {
  4309. return gns, nil
  4310. }
  4311. errs = append(errs, err)
  4312. }
  4313. return nil, errors.NewAggregate(errs)
  4314. } else {
  4315. netConfig.Network = ""
  4316. return self.attach2RandomNetwork(ctx, userCred, host, netConfig, pendingUsage)
  4317. }
  4318. }
  4319. func (self *SGuest) attach2NamedNetworkDesc(ctx context.Context, userCred mcclient.TokenCredential, host *SHost, netConfig *api.NetworkConfig, pendingUsage quotas.IQuota) ([]SGuestnetwork, error) {
  4320. driver, err := self.GetDriver()
  4321. if err != nil {
  4322. return nil, errors.Wrapf(err, "GetDriver")
  4323. }
  4324. net, nicConfs, allocDir, reuseAddr, err := driver.GetNamedNetworkConfiguration(self, ctx, userCred, host, netConfig)
  4325. if err != nil {
  4326. if errors.Cause(err) == sql.ErrNoRows {
  4327. return nil, errors.Wrapf(httperrors.ErrResourceNotReady, "Network not avaiable on host %q", host.GetName())
  4328. } else {
  4329. return nil, errors.Wrapf(err, "GetNamedNetworkConfiguration on host %q", host.GetName())
  4330. }
  4331. }
  4332. if net != nil {
  4333. if len(nicConfs) == 0 {
  4334. return nil, fmt.Errorf("no available network interface?")
  4335. }
  4336. var sriovWires []string
  4337. if netConfig.SriovDevice != nil {
  4338. if netConfig.SriovDevice.Id != "" {
  4339. idev, err := IsolatedDeviceManager.FetchById(netConfig.SriovDevice.Id)
  4340. if err != nil {
  4341. return nil, errors.Wrap(err, "fetch isolated device")
  4342. }
  4343. dev, _ := idev.(*SIsolatedDevice)
  4344. sriovWires = []string{dev.WireId}
  4345. } else {
  4346. wires, err := IsolatedDeviceManager.FindUnusedNicWiresByModel(netConfig.SriovDevice.Model)
  4347. if err != nil {
  4348. return nil, errors.Wrap(err, "FindUnusedNicWiresByModel")
  4349. }
  4350. sriovWires = wires
  4351. }
  4352. vpc, err := net.GetVpc()
  4353. if err != nil {
  4354. return nil, errors.Wrap(err, "attach2NamedNetworkDesc get vpc by network")
  4355. }
  4356. if vpc.Id == api.DEFAULT_VPC_ID && !utils.IsInStringArray(net.WireId, sriovWires) {
  4357. return nil, fmt.Errorf("no available sriov nic for wire %s", net.WireId)
  4358. }
  4359. }
  4360. gn, err := self.Attach2Network(ctx, userCred, Attach2NetworkArgs{
  4361. Network: net,
  4362. PendingUsage: pendingUsage,
  4363. IpAddr: netConfig.Address,
  4364. Ip6Addr: netConfig.Address6,
  4365. RequireIPv6: netConfig.RequireIPv6,
  4366. StrictIPv6: netConfig.StrictIPv6,
  4367. NicDriver: netConfig.Driver,
  4368. NumQueues: netConfig.NumQueues,
  4369. BwLimit: netConfig.BwLimit,
  4370. RxTrafficLimit: netConfig.RxTrafficLimit,
  4371. TxTrafficLimit: netConfig.TxTrafficLimit,
  4372. Virtual: netConfig.Vip,
  4373. TryReserved: netConfig.Reserved,
  4374. AllocDir: allocDir,
  4375. RequireDesignatedIP: netConfig.RequireDesignatedIP,
  4376. UseDesignatedIP: reuseAddr,
  4377. NicConfs: nicConfs,
  4378. IsDefault: netConfig.IsDefault,
  4379. PortMappings: netConfig.PortMappings,
  4380. BillingType: netConfig.BillingType,
  4381. ChargeType: netConfig.ChargeType,
  4382. })
  4383. if err != nil {
  4384. return nil, errors.Wrap(err, "Attach2Network fail")
  4385. } else {
  4386. return gn, nil
  4387. }
  4388. } else {
  4389. return nil, fmt.Errorf("Network %s not available", netConfig.Network)
  4390. }
  4391. }
  4392. func (self *SGuest) attach2RandomNetwork(ctx context.Context, userCred mcclient.TokenCredential, host *SHost, netConfig *api.NetworkConfig, pendingUsage quotas.IQuota) ([]SGuestnetwork, error) {
  4393. driver, err := self.GetDriver()
  4394. if err != nil {
  4395. return nil, err
  4396. }
  4397. return driver.Attach2RandomNetwork(self, ctx, userCred, host, netConfig, pendingUsage)
  4398. }
  4399. func (self *SGuest) CreateDisksOnHost(
  4400. ctx context.Context,
  4401. userCred mcclient.TokenCredential,
  4402. host *SHost,
  4403. disks []*api.DiskConfig,
  4404. pendingUsage quotas.IQuota,
  4405. inheritBilling bool,
  4406. isWithServerCreate bool,
  4407. candidateDisks []*schedapi.CandidateDisk,
  4408. backupCandidateDisks []*schedapi.CandidateDisk,
  4409. autoAttach bool,
  4410. ) error {
  4411. for idx := 0; idx < len(disks); idx += 1 {
  4412. if len(disks[idx].DiskId) > 0 && len(disks[idx].Storage) > 0 {
  4413. continue
  4414. }
  4415. diskConfig, err := parseDiskInfo(ctx, userCred, disks[idx])
  4416. if err != nil {
  4417. return errors.Wrap(err, "parseDiskInfo")
  4418. }
  4419. var candidateDisk *schedapi.CandidateDisk
  4420. var backupCandidateDisk *schedapi.CandidateDisk
  4421. if len(candidateDisks) > idx {
  4422. candidateDisk = candidateDisks[idx]
  4423. }
  4424. if len(backupCandidateDisks) != 0 && len(backupCandidateDisks) > idx {
  4425. backupCandidateDisk = backupCandidateDisks[idx]
  4426. }
  4427. disk, err := self.createDiskOnHost(ctx, userCred, host, diskConfig, pendingUsage, inheritBilling, isWithServerCreate, candidateDisk, backupCandidateDisk, autoAttach)
  4428. if err != nil {
  4429. return err
  4430. }
  4431. diskConfig.DiskId = disk.Id
  4432. disks[idx] = diskConfig
  4433. if diskConfig.NVMEDevice != nil {
  4434. err = self.attachNVMEDevice(ctx, userCred, host, pendingUsage, disk, diskConfig)
  4435. if err != nil {
  4436. return err
  4437. }
  4438. }
  4439. }
  4440. return nil
  4441. }
  4442. func (self *SGuest) attachNVMEDevice(
  4443. ctx context.Context, userCred mcclient.TokenCredential,
  4444. host *SHost, pendingUsage quotas.IQuota,
  4445. disk *SDisk, diskConfig *api.DiskConfig,
  4446. ) error {
  4447. gd := self.GetGuestDisk(disk.Id)
  4448. diskConfig.NVMEDevice.DiskIndex = &gd.Index
  4449. err := self.createIsolatedDeviceOnHost(ctx, userCred, host, diskConfig.NVMEDevice, pendingUsage, nil, nil)
  4450. if err != nil {
  4451. return errors.Wrap(err, "self.createIsolatedDeviceOnHost")
  4452. }
  4453. dev, err := self.GetIsolatedDeviceByDiskIndex(gd.Index)
  4454. if err != nil {
  4455. return errors.Wrap(err, "self.GetIsolatedDeviceByDiskIndex")
  4456. }
  4457. diskConfig.SizeMb = dev.NvmeSizeMB
  4458. _, err = db.Update(disk, func() error {
  4459. disk.DiskSize = dev.NvmeSizeMB
  4460. return nil
  4461. })
  4462. if err != nil {
  4463. return errors.Wrap(err, "update nvme disk size")
  4464. }
  4465. return nil
  4466. }
  4467. func (self *SGuest) CreateDiskOnStorage(ctx context.Context, userCred mcclient.TokenCredential, storage *SStorage,
  4468. diskConfig *api.DiskConfig, pendingUsage quotas.IQuota, inheritBilling bool, isWithServerCreate bool) (*SDisk, error) {
  4469. lockman.LockObject(ctx, storage)
  4470. defer lockman.ReleaseObject(ctx, storage)
  4471. lockman.LockClass(ctx, QuotaManager, self.ProjectId)
  4472. defer lockman.ReleaseClass(ctx, QuotaManager, self.ProjectId)
  4473. diskName := fmt.Sprintf("vdisk-%s-%d", pinyinutils.Text2Pinyin(self.Name), time.Now().UnixNano())
  4474. billingType := billing_api.BILLING_TYPE_POSTPAID
  4475. billingCycle := ""
  4476. if inheritBilling {
  4477. billingType = self.BillingType
  4478. billingCycle = self.BillingCycle
  4479. }
  4480. autoDelete := false
  4481. if storage.IsLocal() || billingType == billing_api.BILLING_TYPE_PREPAID || isWithServerCreate {
  4482. autoDelete = true
  4483. }
  4484. if diskConfig.AutoDelete != nil {
  4485. autoDelete = *diskConfig.AutoDelete
  4486. }
  4487. disk, err := storage.createDisk(ctx, diskName, diskConfig, userCred, self.GetOwnerId(), autoDelete, self.IsSystem,
  4488. billingType, billingCycle, self.EncryptKeyId)
  4489. if err != nil {
  4490. return nil, err
  4491. }
  4492. if isWithServerCreate {
  4493. meta, _ := self.GetAllUserMetadata()
  4494. if len(meta) > 0 {
  4495. disk.SetUserMetadataAll(ctx, meta, userCred)
  4496. }
  4497. }
  4498. if pendingUsage != nil {
  4499. cancelUsage := SQuota{}
  4500. cancelUsage.Storage = disk.DiskSize
  4501. keys, err := self.GetQuotaKeys()
  4502. if err != nil {
  4503. return nil, err
  4504. }
  4505. cancelUsage.SetKeys(keys)
  4506. err = quotas.CancelPendingUsage(ctx, userCred, pendingUsage, &cancelUsage, true)
  4507. if err != nil {
  4508. return nil, err
  4509. }
  4510. }
  4511. return disk, nil
  4512. }
  4513. func (self *SGuest) ChooseHostStorage(host *SHost, diskConfig *api.DiskConfig, candidate *schedapi.CandidateDisk) (*SStorage, error) {
  4514. drv, err := self.GetDriver()
  4515. if err != nil {
  4516. return nil, err
  4517. }
  4518. if candidate == nil || len(candidate.StorageIds) == 0 {
  4519. return drv.ChooseHostStorage(host, self, diskConfig, nil)
  4520. }
  4521. return drv.ChooseHostStorage(host, self, diskConfig, candidate.StorageIds)
  4522. }
  4523. func (self *SGuest) createDiskOnHost(
  4524. ctx context.Context,
  4525. userCred mcclient.TokenCredential,
  4526. host *SHost,
  4527. diskConfig *api.DiskConfig,
  4528. pendingUsage quotas.IQuota,
  4529. inheritBilling bool,
  4530. isWithServerCreate bool,
  4531. candidate *schedapi.CandidateDisk,
  4532. backupCandidate *schedapi.CandidateDisk,
  4533. autoAttach bool,
  4534. ) (*SDisk, error) {
  4535. var (
  4536. storage *SStorage
  4537. err error
  4538. )
  4539. if len(diskConfig.Storage) > 0 {
  4540. _storage, err := StorageManager.FetchByIdOrName(ctx, userCred, diskConfig.Storage)
  4541. if err != nil {
  4542. if err == sql.ErrNoRows {
  4543. return nil, httperrors.NewResourceNotFoundError2("storage", diskConfig.Storage)
  4544. }
  4545. return nil, fmt.Errorf("get storage(%s) error: %v", diskConfig.Storage, err)
  4546. }
  4547. storage = _storage.(*SStorage)
  4548. } else {
  4549. storage, err = self.ChooseHostStorage(host, diskConfig, candidate)
  4550. if err != nil {
  4551. return nil, errors.Wrap(err, "ChooseHostStorage")
  4552. }
  4553. }
  4554. if storage == nil {
  4555. return nil, fmt.Errorf("No storage on %s to create disk for %s", host.GetName(), diskConfig.Backend)
  4556. }
  4557. log.Debugf("Choose storage %s:%s for disk %#v", storage.Name, storage.Id, diskConfig)
  4558. disk, err := self.CreateDiskOnStorage(ctx, userCred, storage, diskConfig, pendingUsage, inheritBilling, isWithServerCreate)
  4559. if err != nil {
  4560. return nil, err
  4561. }
  4562. if diskConfig.ExistingPath != "" {
  4563. disk.SetMetadata(ctx, api.DISK_META_EXISTING_PATH, diskConfig.ExistingPath, userCred)
  4564. }
  4565. if len(self.BackupHostId) > 0 {
  4566. backupHost := HostManager.FetchHostById(self.BackupHostId)
  4567. backupStorage, err := self.ChooseHostStorage(backupHost, diskConfig, backupCandidate)
  4568. if err != nil {
  4569. return nil, errors.Wrap(err, "ChooseHostStorage")
  4570. }
  4571. diff, err := db.Update(disk, func() error {
  4572. disk.BackupStorageId = backupStorage.Id
  4573. return nil
  4574. })
  4575. if err != nil {
  4576. log.Errorf("Disk save backup storage error")
  4577. return disk, err
  4578. }
  4579. db.OpsLog.LogEvent(disk, db.ACT_UPDATE, diff, userCred)
  4580. }
  4581. if autoAttach {
  4582. err = self.attach2Disk(ctx, disk, userCred, diskConfig.Driver, diskConfig.Cache, diskConfig.Mountpoint, diskConfig.BootIndex)
  4583. }
  4584. err = self.InheritTo(ctx, userCred, disk)
  4585. if err != nil {
  4586. return nil, errors.Wrapf(err, "unable to inherit from guest %s to disk %s", self.GetId(), disk.GetId())
  4587. }
  4588. return disk, err
  4589. }
  4590. func (self *SGuest) CreateIsolatedDeviceOnHost(ctx context.Context, userCred mcclient.TokenCredential, host *SHost, devs []*api.IsolatedDeviceConfig, pendingUsage quotas.IQuota) error {
  4591. var numaNodes []int
  4592. if self.IsSchedulerNumaAllocate() {
  4593. numaNodes = make([]int, 0)
  4594. cpuNumaPin := make([]schedapi.SCpuNumaPin, 0)
  4595. self.CpuNumaPin.Unmarshal(&cpuNumaPin)
  4596. for i := range cpuNumaPin {
  4597. numaNodes = append(numaNodes, cpuNumaPin[i].NodeId)
  4598. }
  4599. }
  4600. lockman.LockObject(ctx, host)
  4601. defer lockman.ReleaseObject(ctx, host)
  4602. usedDeviceMap := map[string]*SIsolatedDevice{}
  4603. for _, devConfig := range devs {
  4604. if devConfig.DevType == api.NIC_TYPE || devConfig.DevType == api.NVME_PT_TYPE {
  4605. continue
  4606. }
  4607. err := self.createIsolatedDeviceOnHost(ctx, userCred, host, devConfig, pendingUsage, usedDeviceMap, numaNodes)
  4608. if err != nil {
  4609. return err
  4610. }
  4611. }
  4612. return nil
  4613. }
  4614. func (self *SGuest) createIsolatedDeviceOnHost(ctx context.Context, userCred mcclient.TokenCredential, host *SHost, devConfig *api.IsolatedDeviceConfig, pendingUsage quotas.IQuota, usedDevMap map[string]*SIsolatedDevice, preferNumaNodes []int) error {
  4615. lockman.LockClass(ctx, QuotaManager, self.ProjectId)
  4616. defer lockman.ReleaseClass(ctx, QuotaManager, self.ProjectId)
  4617. err := IsolatedDeviceManager.attachHostDeviceToGuestByDesc(ctx, self, host, devConfig, userCred, usedDevMap, preferNumaNodes)
  4618. if err != nil {
  4619. return err
  4620. }
  4621. cancelUsage := SQuota{IsolatedDevice: 1}
  4622. keys, err := self.GetQuotaKeys()
  4623. if err != nil {
  4624. return err
  4625. }
  4626. cancelUsage.SetKeys(keys)
  4627. err = quotas.CancelPendingUsage(ctx, userCred, pendingUsage, &cancelUsage, true) // success
  4628. return err
  4629. }
  4630. func (self *SGuest) JoinGroups(ctx context.Context, userCred mcclient.TokenCredential, groupIds []string) error {
  4631. for _, id := range groupIds {
  4632. _, err := GroupguestManager.Attach(ctx, id, self.Id)
  4633. if err != nil {
  4634. return err
  4635. }
  4636. }
  4637. return nil
  4638. }
  4639. type SGuestDiskCategory struct {
  4640. Root *SDisk
  4641. Swap []*SDisk
  4642. Data []*SDisk
  4643. }
  4644. func (self *SGuest) CategorizeDisks() SGuestDiskCategory {
  4645. diskCat := SGuestDiskCategory{}
  4646. guestdisks, err := self.GetGuestDisks()
  4647. if err != nil {
  4648. log.Errorf("no disk for this server!!!")
  4649. return diskCat
  4650. }
  4651. for _, gd := range guestdisks {
  4652. if diskCat.Root == nil {
  4653. diskCat.Root = gd.GetDisk()
  4654. } else {
  4655. disk := gd.GetDisk()
  4656. if disk.FsFormat == "swap" {
  4657. diskCat.Swap = append(diskCat.Swap, disk)
  4658. } else {
  4659. diskCat.Data = append(diskCat.Data, disk)
  4660. }
  4661. }
  4662. }
  4663. return diskCat
  4664. }
  4665. type SGuestNicCategory struct {
  4666. InternalNics []SGuestnetwork
  4667. ExternalNics []SGuestnetwork
  4668. }
  4669. func (self *SGuest) CategorizeNics() SGuestNicCategory {
  4670. netCat := SGuestNicCategory{}
  4671. guestnics, err := self.GetNetworks("")
  4672. if err != nil {
  4673. log.Errorf("no nics for this server!!! %s", err)
  4674. return netCat
  4675. }
  4676. for _, gn := range guestnics {
  4677. if gn.IsExit(nil) {
  4678. netCat.ExternalNics = append(netCat.ExternalNics, gn)
  4679. } else {
  4680. netCat.InternalNics = append(netCat.InternalNics, gn)
  4681. }
  4682. }
  4683. return netCat
  4684. }
  4685. func (self *SGuest) LeaveAllGroups(ctx context.Context, userCred mcclient.TokenCredential) {
  4686. groupGuests := make([]SGroupguest, 0)
  4687. q := GroupguestManager.Query()
  4688. err := q.Filter(sqlchemy.Equals(q.Field("guest_id"), self.Id)).All(&groupGuests)
  4689. if err != nil {
  4690. log.Errorf("query by guest_id %s: %v", self.Id, err)
  4691. return
  4692. }
  4693. for _, gg := range groupGuests {
  4694. gg.SetModelManager(GroupguestManager, &gg)
  4695. gg.Delete(context.Background(), userCred)
  4696. var group SGroup
  4697. gq := GroupManager.Query()
  4698. err := gq.Filter(sqlchemy.Equals(gq.Field("id"), gg.GroupId)).First(&group)
  4699. if err != nil {
  4700. log.Errorf("get by group id %s: %v", gg.GroupId, err)
  4701. return
  4702. }
  4703. group.SetModelManager(GroupManager, &group)
  4704. db.OpsLog.LogDetachEvent(ctx, self, &group, userCred, nil)
  4705. }
  4706. }
  4707. func (self *SGuest) DetachAllNetworks(ctx context.Context, userCred mcclient.TokenCredential) error {
  4708. // from clouds.models.portmaps import Portmaps
  4709. // Portmaps.delete_guest_network_portmaps(self, user_cred)
  4710. gns, err := self.GetNetworks("")
  4711. if err != nil {
  4712. return err
  4713. }
  4714. return GuestnetworkManager.DeleteGuestNics(ctx, userCred, gns, false)
  4715. }
  4716. func (self *SGuest) EjectIso(cdromOrdinal int64, userCred mcclient.TokenCredential) bool {
  4717. cdrom := self.getCdrom(false, cdromOrdinal)
  4718. if cdrom != nil && len(cdrom.ImageId) > 0 {
  4719. imageId := cdrom.ImageId
  4720. if cdrom.ejectIso() {
  4721. db.OpsLog.LogEvent(self, db.ACT_ISO_DETACH, imageId, userCred)
  4722. return true
  4723. }
  4724. }
  4725. return false
  4726. }
  4727. func (self *SGuest) EjectAllIso(userCred mcclient.TokenCredential) bool {
  4728. cdroms, _ := self.getCdroms()
  4729. for _, cdrom := range cdroms {
  4730. if len(cdrom.ImageId) > 0 {
  4731. imageId := cdrom.ImageId
  4732. if cdrom.ejectIso() {
  4733. db.OpsLog.LogEvent(self, db.ACT_ISO_DETACH, imageId, userCred)
  4734. } else {
  4735. return false
  4736. }
  4737. }
  4738. }
  4739. return true
  4740. }
  4741. func (self *SGuest) EjectVfd(floppyOrdinal int64, userCred mcclient.TokenCredential) bool {
  4742. floppy := self.getFloppy(false, floppyOrdinal)
  4743. if floppy != nil && len(floppy.ImageId) > 0 {
  4744. imageId := floppy.ImageId
  4745. if floppy.ejectVfd() {
  4746. db.OpsLog.LogEvent(self, db.ACT_VFD_DETACH, imageId, userCred)
  4747. return true
  4748. }
  4749. }
  4750. return false
  4751. }
  4752. func (self *SGuest) EjectAllVfd(userCred mcclient.TokenCredential) bool {
  4753. floppys, _ := self.getFloppys()
  4754. for _, floppy := range floppys {
  4755. if len(floppy.ImageId) > 0 {
  4756. imageId := floppy.ImageId
  4757. if floppy.ejectVfd() {
  4758. db.OpsLog.LogEvent(self, db.ACT_ISO_DETACH, imageId, userCred)
  4759. } else {
  4760. return false
  4761. }
  4762. }
  4763. }
  4764. return true
  4765. }
  4766. func (self *SGuest) Delete(ctx context.Context, userCred mcclient.TokenCredential) error {
  4767. // self.SVirtualResourceBase.Delete(ctx, userCred)
  4768. // override
  4769. log.Infof("guest delete do nothing")
  4770. return nil
  4771. }
  4772. func (self *SGuest) CleanTapRecords(ctx context.Context, userCred mcclient.TokenCredential) error {
  4773. // delete tap devices
  4774. if err := NetTapServiceManager.removeTapServicesByGuestId(ctx, userCred, self.Id); err != nil {
  4775. return errors.Wrap(err, "NetTapServiceManager.getTapServicesByGuestId")
  4776. }
  4777. if err := NetTapFlowManager.removeTapFlowsByGuestId(ctx, userCred, self.Id); err != nil {
  4778. return errors.Wrap(err, "NetTapFlowManager.getTapServicesByGuestId")
  4779. }
  4780. return nil
  4781. }
  4782. func (self *SGuest) GetLoadbalancerBackends() ([]SLoadbalancerBackend, error) {
  4783. q := LoadbalancerBackendManager.Query().Equals("backend_id", self.Id)
  4784. ret := []SLoadbalancerBackend{}
  4785. return ret, db.FetchModelObjects(LoadbalancerBackendManager, q, &ret)
  4786. }
  4787. func (self *SGuest) RealDelete(ctx context.Context, userCred mcclient.TokenCredential) error {
  4788. SnapshotPolicyResourceManager.RemoveByResource(self.Id, api.SNAPSHOT_POLICY_TYPE_SERVER)
  4789. return self.purge(ctx, userCred)
  4790. }
  4791. func (self *SGuest) AllowDeleteItem(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) bool {
  4792. overridePendingDelete := false
  4793. purge := false
  4794. if query != nil {
  4795. overridePendingDelete = jsonutils.QueryBoolean(query, "override_pending_delete", false)
  4796. purge = jsonutils.QueryBoolean(query, "purge", false)
  4797. }
  4798. if (overridePendingDelete || purge) && !db.IsAdminAllowDelete(ctx, userCred, self) {
  4799. return false
  4800. }
  4801. return self.IsOwner(userCred) || db.IsAdminAllowDelete(ctx, userCred, self)
  4802. }
  4803. // 删除虚拟机
  4804. func (self *SGuest) CustomizeDelete(ctx context.Context, userCred mcclient.TokenCredential, query api.ServerDeleteInput, data jsonutils.JSONObject) error {
  4805. return self.StartDeleteGuestTask(ctx, userCred, "", query)
  4806. }
  4807. func (self *SGuest) DeleteAllDisksInDB(ctx context.Context, userCred mcclient.TokenCredential) error {
  4808. guestDisks, err := self.GetGuestDisks()
  4809. if err != nil {
  4810. return errors.Wrapf(err, "GetGuestDisks")
  4811. }
  4812. for _, guestdisk := range guestDisks {
  4813. disk := guestdisk.GetDisk()
  4814. err := guestdisk.Detach(ctx, userCred)
  4815. if err != nil {
  4816. return errors.Wrapf(err, "guestdisk.Detach guest_id: %s disk_id: %s", guestdisk.GuestId, guestdisk.DiskId)
  4817. }
  4818. if disk != nil {
  4819. cnt, err := disk.GetGuestDiskCount()
  4820. if err != nil {
  4821. return errors.Wrap(err, "disk.GetGuestDiskCount")
  4822. }
  4823. if cnt == 0 {
  4824. db.OpsLog.LogEvent(disk, db.ACT_DELETE, nil, userCred)
  4825. db.OpsLog.LogEvent(disk, db.ACT_DELOCATE, nil, userCred)
  4826. err = disk.RealDelete(ctx, userCred)
  4827. if err != nil {
  4828. return errors.Wrap(err, "disk.RealDelete")
  4829. }
  4830. }
  4831. }
  4832. }
  4833. return nil
  4834. }
  4835. func (self *SGuest) DeleteAllInstanceSnapshotInDB(ctx context.Context, userCred mcclient.TokenCredential) error {
  4836. isps, err := self.GetInstanceSnapshots()
  4837. if err != nil {
  4838. return errors.Wrap(err, "unable to GetInstanceSnapshots")
  4839. }
  4840. for i := range isps {
  4841. err = isps[i].RealDelete(ctx, userCred)
  4842. return errors.Wrapf(err, "unable to real delete instance snapshot %q for guest %q", isps[i].GetName(), self.GetId())
  4843. }
  4844. return nil
  4845. }
  4846. func (self *SGuest) isNeedDoResetPasswd() bool {
  4847. guestdisks, _ := self.GetGuestDisks()
  4848. if len(guestdisks) > 0 {
  4849. disk := guestdisks[0].GetDisk()
  4850. if len(disk.SnapshotId) > 0 {
  4851. return false
  4852. }
  4853. }
  4854. return true
  4855. }
  4856. func (self *SGuest) IsSchedulerNumaAllocate() bool {
  4857. cpuNumaPinType := self.GetMetadata(context.Background(), api.VM_METADATA_CPU_NUMA_PIN_TYPE, nil)
  4858. return cpuNumaPinType == api.VM_CPU_NUMA_PIN_SCHEDULER && self.CpuNumaPin != nil
  4859. }
  4860. func (self *SGuest) GetDeployConfigOnHost(ctx context.Context, userCred mcclient.TokenCredential, host *SHost, params *jsonutils.JSONDict) (*jsonutils.JSONDict, error) {
  4861. config := jsonutils.NewDict()
  4862. drv, err := self.GetDriver()
  4863. if err != nil {
  4864. return nil, err
  4865. }
  4866. desc, err := drv.GetJsonDescAtHost(ctx, userCred, self, host, params)
  4867. if err != nil {
  4868. return nil, errors.Wrapf(err, "GetJsonDescAtHost")
  4869. }
  4870. config.Add(desc, "desc")
  4871. deploys, err := cmdline.FetchDeployConfigsByJSON(params)
  4872. if err != nil {
  4873. return nil, err
  4874. }
  4875. if len(deploys) > 0 {
  4876. config.Add(jsonutils.Marshal(deploys), "deploys")
  4877. }
  4878. deployAction, _ := params.GetString("deploy_action")
  4879. if len(deployAction) == 0 {
  4880. deployAction = "deploy"
  4881. }
  4882. config.Add(jsonutils.NewBool(jsonutils.QueryBoolean(params, "enable_cloud_init", false)), "enable_cloud_init")
  4883. if account, _ := params.GetString("login_account"); len(account) > 0 {
  4884. config.Set("login_account", jsonutils.NewString(account))
  4885. }
  4886. resetPasswd := jsonutils.QueryBoolean(params, "reset_password", true)
  4887. if deployAction == "create" && resetPasswd {
  4888. resetPasswd = self.isNeedDoResetPasswd()
  4889. }
  4890. if resetPasswd {
  4891. config.Add(jsonutils.JSONTrue, "reset_password")
  4892. passwd, _ := params.GetString("password")
  4893. if len(passwd) > 0 {
  4894. config.Add(jsonutils.NewString(passwd), "password")
  4895. }
  4896. keypair := self.getKeypair()
  4897. if keypair != nil {
  4898. config.Add(jsonutils.NewString(keypair.PublicKey), "public_key")
  4899. config.Add(jsonutils.NewString(keypair.Name), "keypair_name")
  4900. }
  4901. deletePubKey, _ := params.GetString("delete_public_key")
  4902. if len(deletePubKey) > 0 {
  4903. config.Add(jsonutils.NewString(deletePubKey), "delete_public_key")
  4904. }
  4905. } else {
  4906. config.Add(jsonutils.JSONFalse, "reset_password")
  4907. }
  4908. // add default public keys
  4909. _, adminPubKey, err := sshkeys.GetSshAdminKeypair(ctx)
  4910. if err != nil {
  4911. log.Errorf("fail to get ssh admin public key %s", err)
  4912. }
  4913. _, projPubKey, err := sshkeys.GetSshProjectKeypair(ctx, self.ProjectId)
  4914. if err != nil {
  4915. log.Errorf("fail to get ssh project public key %s", err)
  4916. }
  4917. config.Add(jsonutils.NewString(adminPubKey), "admin_public_key")
  4918. config.Add(jsonutils.NewString(projPubKey), "project_public_key")
  4919. config.Add(jsonutils.NewString(deployAction), "action")
  4920. onFinish := "shutdown"
  4921. if jsonutils.QueryBoolean(params, "auto_start", false) || jsonutils.QueryBoolean(params, "restart", false) {
  4922. onFinish = "none"
  4923. } else if utils.IsInStringArray(self.Status, []string{api.VM_ADMIN}) {
  4924. onFinish = "none"
  4925. }
  4926. config.Add(jsonutils.NewString(onFinish), "on_finish")
  4927. if jsonutils.QueryBoolean(params, "deploy_telegraf", false) {
  4928. influxdbUrl := drv.FetchMonitorUrl(ctx, self)
  4929. config.Add(jsonutils.JSONTrue, "deploy_telegraf")
  4930. serverDetails, err := self.getDetails(ctx, userCred)
  4931. if err != nil {
  4932. return nil, errors.Wrap(err, "get details")
  4933. }
  4934. telegrafConf, err := devtool_utils.GenerateTelegrafConf(
  4935. serverDetails, influxdbUrl, self.OsType, self.Hypervisor)
  4936. if err != nil {
  4937. return nil, errors.Wrap(err, "get telegraf conf")
  4938. }
  4939. config.Add(jsonutils.NewString(telegrafConf), "telegraf_conf")
  4940. }
  4941. return config, nil
  4942. }
  4943. func (self *SGuest) getDetails(ctx context.Context, userCred mcclient.TokenCredential) (*api.ServerDetails, error) {
  4944. res := GuestManager.FetchCustomizeColumns(ctx, userCred, jsonutils.NewDict(), []interface{}{self}, nil, false)
  4945. jsonDict := jsonutils.Marshal(res[0]).(*jsonutils.JSONDict)
  4946. jsonDict.Update(jsonutils.Marshal(self).(*jsonutils.JSONDict))
  4947. serverDetails := new(api.ServerDetails)
  4948. err := jsonDict.Unmarshal(serverDetails)
  4949. if err != nil {
  4950. return nil, err
  4951. }
  4952. return serverDetails, nil
  4953. }
  4954. func (self *SGuest) isBootIndexDuplicated(bootIndex int8) (bool, error) {
  4955. if bootIndex < 0 {
  4956. return false, nil
  4957. }
  4958. cdroms, err := self.getCdroms()
  4959. if err != nil {
  4960. return true, err
  4961. }
  4962. for i := 0; i < len(cdroms); i++ {
  4963. if cdroms[i].BootIndex == bootIndex {
  4964. return true, nil
  4965. }
  4966. }
  4967. gd, err := self.GetGuestDisks()
  4968. if err != nil {
  4969. return true, err
  4970. }
  4971. for i := 0; i < len(gd); i++ {
  4972. if gd[i].BootIndex == bootIndex {
  4973. return true, nil
  4974. }
  4975. }
  4976. return false, nil
  4977. }
  4978. func (self *SGuest) getVga() string {
  4979. if utils.IsInStringArray(self.Vga, []string{"cirrus", "vmware", "qxl", "virtio", "std"}) {
  4980. return self.Vga
  4981. }
  4982. return "std"
  4983. }
  4984. func (self *SGuest) GetVdi() string {
  4985. if utils.IsInStringArray(self.Vdi, []string{"vnc", "spice"}) {
  4986. return self.Vdi
  4987. }
  4988. return "vnc"
  4989. }
  4990. func (self *SGuest) getMachine() string {
  4991. if utils.IsInStringArray(self.Machine, []string{"pc", "q35"}) {
  4992. return self.Machine
  4993. }
  4994. return "pc"
  4995. }
  4996. func (self *SGuest) getBios() string {
  4997. if utils.IsInStringArray(self.Bios, []string{"BIOS", "UEFI"}) {
  4998. return self.Bios
  4999. }
  5000. return "BIOS"
  5001. }
  5002. func (self *SGuest) getKvmOptions() string {
  5003. return self.GetMetadata(context.Background(), "kvm", nil)
  5004. }
  5005. func (self *SGuest) getExtraOptions(ctx context.Context) jsonutils.JSONObject {
  5006. return self.GetMetadataJson(ctx, "extra_options", nil)
  5007. }
  5008. func (self *SGuest) GetIsolatedDevices() ([]SIsolatedDevice, error) {
  5009. q := IsolatedDeviceManager.Query().Equals("guest_id", self.Id)
  5010. devs := []SIsolatedDevice{}
  5011. err := db.FetchModelObjects(IsolatedDeviceManager, q, &devs)
  5012. if err != nil {
  5013. return nil, errors.Wrapf(err, "db.FetchModelObjects")
  5014. }
  5015. return devs, nil
  5016. }
  5017. func (self *SGuest) GetIsolatedDeviceByNetworkIndex(index int) (*SIsolatedDevice, error) {
  5018. dev := SIsolatedDevice{}
  5019. q := IsolatedDeviceManager.Query().Equals("guest_id", self.Id).Equals("network_index", index)
  5020. if cnt, err := q.CountWithError(); err != nil {
  5021. return nil, err
  5022. } else if cnt == 0 {
  5023. return nil, nil
  5024. }
  5025. err := q.First(&dev)
  5026. if err != nil {
  5027. return nil, err
  5028. }
  5029. dev.SetModelManager(IsolatedDeviceManager, &dev)
  5030. return &dev, nil
  5031. }
  5032. func (self *SGuest) GetIsolatedDeviceByDiskIndex(index int8) (*SIsolatedDevice, error) {
  5033. dev := SIsolatedDevice{}
  5034. q := IsolatedDeviceManager.Query().Equals("guest_id", self.Id).Equals("disk_index", index)
  5035. if cnt, err := q.CountWithError(); err != nil {
  5036. return nil, err
  5037. } else if cnt == 0 {
  5038. return nil, nil
  5039. }
  5040. err := q.First(&dev)
  5041. if err != nil {
  5042. return nil, err
  5043. }
  5044. dev.SetModelManager(IsolatedDeviceManager, &dev)
  5045. return &dev, nil
  5046. }
  5047. func (self *SGuest) GetJsonDescAtHypervisor(ctx context.Context, host *SHost) *api.GuestJsonDesc {
  5048. desc := &api.GuestJsonDesc{
  5049. Name: self.Name,
  5050. Hostname: self.Hostname,
  5051. Description: self.Description,
  5052. UUID: self.Id,
  5053. Mem: self.VmemSize,
  5054. Cpu: self.VcpuCount,
  5055. CpuSockets: self.CpuSockets,
  5056. Vga: self.getVga(),
  5057. Vdi: self.GetVdi(),
  5058. Machine: self.getMachine(),
  5059. Bios: self.getBios(),
  5060. BootOrder: self.BootOrder,
  5061. SrcIpCheck: self.SrcIpCheck.Bool(),
  5062. SrcMacCheck: self.SrcMacCheck.Bool(),
  5063. HostId: host.Id,
  5064. HostAccessIp: host.AccessIp,
  5065. HostEIP: host.PublicIp,
  5066. EncryptKeyId: self.EncryptKeyId,
  5067. IsDaemon: self.IsDaemon.Bool(),
  5068. LightMode: self.RescueMode,
  5069. Hypervisor: self.GetHypervisor(),
  5070. EnableEsxiSwap: options.Options.EnableEsxiSwap,
  5071. }
  5072. if len(self.BackupHostId) > 0 {
  5073. if self.HostId == host.Id {
  5074. isMaster := true
  5075. desc.IsMaster = &isMaster
  5076. } else if self.BackupHostId == host.Id {
  5077. isSlave := true
  5078. desc.IsSlave = &isSlave
  5079. }
  5080. }
  5081. if self.HostId != host.Id {
  5082. desc.IsVolatileHost = true
  5083. }
  5084. // isolated devices
  5085. isolatedDevs, _ := self.GetIsolatedDevices()
  5086. for _, dev := range isolatedDevs {
  5087. desc.IsolatedDevices = append(desc.IsolatedDevices, dev.getDesc())
  5088. }
  5089. if self.IsSchedulerNumaAllocate() {
  5090. cpuNumaPin := make([]api.SCpuNumaPin, 0)
  5091. cpuNumaPinStr := self.GetMetadata(ctx, api.VM_METADATA_CPU_NUMA_PIN, nil)
  5092. cpuNumaPinJson, err := jsonutils.ParseString(cpuNumaPinStr)
  5093. if err != nil {
  5094. log.Errorf("failed parse cpu numa pin %s: %s", cpuNumaPinStr, err)
  5095. } else {
  5096. cpuNumaPinJson.Unmarshal(&cpuNumaPin)
  5097. desc.CpuNumaPin = cpuNumaPin
  5098. }
  5099. }
  5100. // nics, domain
  5101. desc.Domain = options.Options.DNSDomain
  5102. nics, _ := self.GetNetworks("")
  5103. changed, _ := self.fixDefaultGatewayByNics(ctx, auth.AdminCredential(), nics)
  5104. if changed {
  5105. nics, _ = self.GetNetworks("")
  5106. }
  5107. for _, nic := range nics {
  5108. nicDesc := nic.getJsonDescAtHost(ctx, host)
  5109. desc.Nics = append(desc.Nics, nicDesc)
  5110. if len(nicDesc.Domain) > 0 {
  5111. desc.Domain = nicDesc.Domain
  5112. }
  5113. secgroupDesc := nic.getSecgroupDesc()
  5114. if secgroupDesc != nil {
  5115. if desc.NicSecgroups == nil {
  5116. desc.NicSecgroups = make([]*api.GuestnetworkSecgroupDesc, 0)
  5117. }
  5118. desc.NicSecgroups = append(desc.NicSecgroups, secgroupDesc)
  5119. }
  5120. }
  5121. {
  5122. var prevNicDesc *api.GuestnetworkJsonDesc
  5123. if len(desc.Nics) > 0 {
  5124. prevNicDesc = desc.Nics[len(desc.Nics)-1]
  5125. }
  5126. // append tap nic
  5127. tapNicDesc := self.getTapNicJsonDesc(ctx, prevNicDesc)
  5128. if tapNicDesc != nil {
  5129. desc.Nics = append(desc.Nics, tapNicDesc)
  5130. }
  5131. }
  5132. // disks
  5133. disks, _ := self.GetGuestDisks()
  5134. for _, disk := range disks {
  5135. diskDesc := disk.GetJsonDescAtHost(ctx, host)
  5136. desc.Disks = append(desc.Disks, diskDesc)
  5137. }
  5138. cdroms, _ := self.getCdroms()
  5139. for _, cdrom := range cdroms {
  5140. cdromDesc := cdrom.getJsonDesc()
  5141. desc.Cdroms = append(desc.Cdroms, cdromDesc)
  5142. }
  5143. if len(desc.Cdroms) > 0 {
  5144. desc.Cdrom = desc.Cdroms[0]
  5145. }
  5146. //floppy
  5147. floppys, _ := self.getFloppys()
  5148. for _, floppy := range floppys {
  5149. floppyDesc := floppy.getJsonDesc()
  5150. desc.Floppys = append(desc.Floppys, floppyDesc)
  5151. }
  5152. // tenant
  5153. tc, _ := self.GetTenantCache(ctx)
  5154. if tc != nil {
  5155. desc.Tenant = tc.GetName()
  5156. desc.DomainId = tc.DomainId
  5157. desc.ProjectDomain = tc.Domain
  5158. }
  5159. desc.TenantId = self.ProjectId
  5160. keypair := self.getKeypair()
  5161. if keypair != nil {
  5162. desc.Keypair = keypair.Name
  5163. desc.Pubkey = keypair.PublicKey
  5164. }
  5165. desc.NetworkRoles = self.getNetworkRoles()
  5166. desc.Secgroups, _ = self.getSecgroupJson()
  5167. desc.SecurityRules = self.getSecurityGroupsRules()
  5168. desc.AdminSecurityRules = self.getAdminSecurityRules()
  5169. desc.ExtraOptions = self.getExtraOptions(ctx)
  5170. desc.Kvm = self.getKvmOptions()
  5171. zone, _ := self.getZone()
  5172. if zone != nil {
  5173. desc.ZoneId = zone.Id
  5174. desc.Zone = zone.Name
  5175. }
  5176. desc.OsName = self.GetOS()
  5177. desc.Metadata, _ = self.GetAllMetadata(ctx, nil)
  5178. userData, _ := desc.Metadata["user_data"]
  5179. if len(userData) > 0 {
  5180. decodeData, _ := userdata.Decode(userData)
  5181. if len(decodeData) > 0 {
  5182. userData = decodeData
  5183. }
  5184. desc.UserData = userData
  5185. }
  5186. desc.PendingDeleted = self.PendingDeleted
  5187. // add scaling group
  5188. sggs, err := ScalingGroupGuestManager.Fetch("", self.Id)
  5189. if err == nil && len(sggs) > 0 {
  5190. desc.ScalingGroupId = sggs[0].ScalingGroupId
  5191. }
  5192. return desc
  5193. }
  5194. func (self *SGuest) GetJsonDescAtBaremetal(ctx context.Context, host *SHost) *api.GuestJsonDesc {
  5195. desc := &api.GuestJsonDesc{
  5196. Name: self.Name,
  5197. Description: self.Description,
  5198. UUID: self.Id,
  5199. Mem: self.VmemSize,
  5200. Cpu: self.VcpuCount,
  5201. }
  5202. desc.DiskConfig = host.getDiskConfig()
  5203. self.fixDefaultGateway(ctx, auth.AdminCredential())
  5204. netifs := host.GetAllNetInterfaces()
  5205. desc.Domain = options.Options.DNSDomain
  5206. for _, nic := range netifs {
  5207. nicDesc := nic.getServerJsonDesc()
  5208. if len(nicDesc.Ip) > 0 {
  5209. desc.Nics = append(desc.Nics, nicDesc)
  5210. if len(nicDesc.Domain) > 0 {
  5211. desc.Domain = nicDesc.Domain
  5212. }
  5213. } else {
  5214. desc.NicsStandby = append(desc.NicsStandby, nicDesc)
  5215. }
  5216. }
  5217. disks, _ := self.GetGuestDisks()
  5218. for _, disk := range disks {
  5219. diskDesc := disk.GetJsonDescAtHost(ctx, host)
  5220. desc.Disks = append(desc.Disks, diskDesc)
  5221. }
  5222. tc, _ := self.GetTenantCache(ctx)
  5223. if tc != nil {
  5224. desc.Tenant = tc.GetName()
  5225. desc.DomainId = tc.DomainId
  5226. desc.ProjectDomain = tc.Domain
  5227. }
  5228. desc.TenantId = self.ProjectId
  5229. keypair := self.getKeypair()
  5230. if keypair != nil {
  5231. desc.Keypair = keypair.Name
  5232. desc.Pubkey = keypair.PublicKey
  5233. }
  5234. desc.NetworkRoles = self.getNetworkRoles()
  5235. desc.SecurityRules = self.getSecurityGroupsRules()
  5236. desc.AdminSecurityRules = self.getAdminSecurityRules()
  5237. zone, _ := self.getZone()
  5238. if zone != nil {
  5239. desc.ZoneId = zone.Id
  5240. desc.Zone = zone.Name
  5241. }
  5242. desc.OsName = self.GetOS()
  5243. desc.Metadata, _ = self.GetAllMetadata(ctx, nil)
  5244. desc.UserData, _ = desc.Metadata["user_data"]
  5245. desc.PendingDeleted = self.PendingDeleted
  5246. return desc
  5247. }
  5248. func (self *SGuest) getNetworkRoles() []string {
  5249. key := db.Metadata.GetSysadminKey("network_role")
  5250. roleStr := self.GetMetadata(context.Background(), key, auth.AdminCredential())
  5251. if len(roleStr) > 0 {
  5252. return strings.Split(roleStr, ",")
  5253. }
  5254. return nil
  5255. }
  5256. func (manager *SGuestManager) FetchGuestById(guestId string) *SGuest {
  5257. guest, err := manager.FetchById(guestId)
  5258. if err != nil {
  5259. log.Errorf("FetchById fail %s", err)
  5260. return nil
  5261. }
  5262. return guest.(*SGuest)
  5263. }
  5264. func (manager *SGuestManager) GetSpecShouldCheckStatus(query *jsonutils.JSONDict) (bool, error) {
  5265. return true, nil
  5266. }
  5267. func (self *SGuest) GetSpec(checkStatus bool) *jsonutils.JSONDict {
  5268. if checkStatus {
  5269. if utils.IsInStringArray(self.Status, []string{api.VM_SCHEDULE_FAILED}) {
  5270. return nil
  5271. }
  5272. }
  5273. spec := jsonutils.NewDict()
  5274. spec.Set("cpu", jsonutils.NewInt(int64(self.VcpuCount)))
  5275. spec.Set("mem", jsonutils.NewInt(int64(self.VmemSize)))
  5276. // get disk spec
  5277. guestdisks, _ := self.GetGuestDisks()
  5278. diskSpecs := jsonutils.NewArray()
  5279. for _, guestdisk := range guestdisks {
  5280. info := guestdisk.ToDiskInfo()
  5281. diskSpec := jsonutils.NewDict()
  5282. diskSpec.Set("size", jsonutils.NewInt(info.Size))
  5283. diskSpec.Set("backend", jsonutils.NewString(info.Backend))
  5284. diskSpec.Set("medium_type", jsonutils.NewString(info.MediumType))
  5285. diskSpec.Set("disk_type", jsonutils.NewString(info.DiskType))
  5286. diskSpecs.Add(diskSpec)
  5287. }
  5288. spec.Set("disk", diskSpecs)
  5289. // get nic spec
  5290. guestnics, _ := self.GetNetworks("")
  5291. nicSpecs := jsonutils.NewArray()
  5292. for _, guestnic := range guestnics {
  5293. nicSpec := jsonutils.NewDict()
  5294. net, _ := guestnic.GetNetwork()
  5295. nicSpec.Set("bandwidth", jsonutils.NewInt(int64(guestnic.getBandwidth(net, nil))))
  5296. t := "int"
  5297. if guestnic.IsExit(net) {
  5298. t = "ext"
  5299. }
  5300. nicSpec.Set("type", jsonutils.NewString(t))
  5301. nicSpecs.Add(nicSpec)
  5302. }
  5303. spec.Set("nic", nicSpecs)
  5304. // get isolate device spec
  5305. guestgpus, _ := self.GetIsolatedDevices()
  5306. gpuSpecs := []GpuSpec{}
  5307. for _, guestgpu := range guestgpus {
  5308. if strings.HasPrefix(guestgpu.DevType, "GPU") {
  5309. gs := guestgpu.GetGpuSpec()
  5310. gpuSpecs = append(gpuSpecs, *gs)
  5311. }
  5312. }
  5313. spec.Set("gpu", jsonutils.Marshal(gpuSpecs))
  5314. return spec
  5315. }
  5316. func (manager *SGuestManager) GetSpecIdent(spec *jsonutils.JSONDict) []string {
  5317. cpuCount, _ := spec.Int("cpu")
  5318. memSize, _ := spec.Int("mem")
  5319. memSizeMB, _ := utils.GetSizeMB(fmt.Sprintf("%d", memSize), "M")
  5320. specKeys := []string{
  5321. fmt.Sprintf("cpu:%d", cpuCount),
  5322. fmt.Sprintf("mem:%dM", memSizeMB),
  5323. }
  5324. countKey := func(kf func(*jsonutils.JSONDict) string, dataArray jsonutils.JSONObject) map[string]int64 {
  5325. countMap := make(map[string]int64)
  5326. datas, _ := dataArray.GetArray()
  5327. for _, data := range datas {
  5328. key := kf(data.(*jsonutils.JSONDict))
  5329. if count, ok := countMap[key]; !ok {
  5330. countMap[key] = 1
  5331. } else {
  5332. count++
  5333. countMap[key] = count
  5334. }
  5335. }
  5336. return countMap
  5337. }
  5338. kfuncs := map[string]func(*jsonutils.JSONDict) string{
  5339. "disk": func(data *jsonutils.JSONDict) string {
  5340. backend, _ := data.GetString("backend")
  5341. mediumType, _ := data.GetString("medium_type")
  5342. size, _ := data.Int("size")
  5343. sizeGB, _ := utils.GetSizeGB(fmt.Sprintf("%d", size), "M")
  5344. return fmt.Sprintf("disk:%s_%s_%dG", backend, mediumType, sizeGB)
  5345. },
  5346. "nic": func(data *jsonutils.JSONDict) string {
  5347. typ, _ := data.GetString("type")
  5348. bw, _ := data.Int("bandwidth")
  5349. return fmt.Sprintf("nic:%s_%dM", typ, bw)
  5350. },
  5351. "gpu": func(data *jsonutils.JSONDict) string {
  5352. vendor, _ := data.GetString("vendor")
  5353. model, _ := data.GetString("model")
  5354. return fmt.Sprintf("gpu:%s_%s", vendor, model)
  5355. },
  5356. }
  5357. for sKey, kf := range kfuncs {
  5358. sArrary, err := spec.Get(sKey)
  5359. if err != nil {
  5360. log.Errorf("Get key %s array error: %v", sKey, err)
  5361. continue
  5362. }
  5363. for key, count := range countKey(kf, sArrary) {
  5364. specKeys = append(specKeys, fmt.Sprintf("%sx%d", key, count))
  5365. }
  5366. }
  5367. return specKeys
  5368. }
  5369. func (self *SGuest) GetGpuSpec() *GpuSpec {
  5370. if len(self.InstanceType) == 0 {
  5371. return nil
  5372. }
  5373. host, err := self.GetHost()
  5374. if err != nil {
  5375. return nil
  5376. }
  5377. zone, err := host.GetZone()
  5378. if err != nil {
  5379. return nil
  5380. }
  5381. q := ServerSkuManager.Query().Equals("name", self.InstanceType).Equals("cloudregion_id", zone.CloudregionId).IsNotEmpty("gpu_spec")
  5382. sku := &SServerSku{}
  5383. err = q.First(sku)
  5384. if err != nil {
  5385. return nil
  5386. }
  5387. return &GpuSpec{
  5388. Model: sku.GpuSpec,
  5389. Amount: sku.GpuCount,
  5390. }
  5391. }
  5392. func (self *SGuest) GetShortDesc(ctx context.Context) *jsonutils.JSONDict {
  5393. desc := self.SVirtualResourceBase.GetShortDesc(ctx)
  5394. desc.Set("mem", jsonutils.NewInt(int64(self.VmemSize)))
  5395. desc.Set("cpu", jsonutils.NewInt(int64(self.VcpuCount)))
  5396. desc.Set("status", jsonutils.NewString(self.Status))
  5397. desc.Set("shutdown_mode", jsonutils.NewString(self.ShutdownMode))
  5398. if len(self.InstanceType) > 0 {
  5399. desc.Set("instance_type", jsonutils.NewString(self.InstanceType))
  5400. }
  5401. if gp := self.GetGpuSpec(); gp != nil {
  5402. desc.Set("gpu_model", jsonutils.NewString(gp.Model))
  5403. desc.Set("gpu_count", jsonutils.NewString(gp.Amount))
  5404. }
  5405. address := jsonutils.NewString(strings.Join(self.GetRealIPs(), ","))
  5406. desc.Set("ip_addr", address)
  5407. if len(self.OsType) > 0 {
  5408. desc.Add(jsonutils.NewString(self.OsType), "os_type")
  5409. }
  5410. if osDist := self.GetMetadata(ctx, "os_distribution", nil); len(osDist) > 0 {
  5411. desc.Add(jsonutils.NewString(osDist), "os_distribution")
  5412. }
  5413. if osVer := self.GetMetadata(ctx, "os_version", nil); len(osVer) > 0 {
  5414. desc.Add(jsonutils.NewString(osVer), "os_version")
  5415. }
  5416. templateId := self.GetTemplateId()
  5417. if len(templateId) > 0 {
  5418. desc.Set("template_id", jsonutils.NewString(templateId))
  5419. }
  5420. extBw := self.getBandwidth(true)
  5421. intBw := self.getBandwidth(false)
  5422. if extBw > 0 {
  5423. desc.Set("ext_bandwidth", jsonutils.NewInt(int64(extBw)))
  5424. }
  5425. if intBw > 0 {
  5426. desc.Set("int_bandwidth", jsonutils.NewInt(int64(intBw)))
  5427. }
  5428. if len(self.OsType) > 0 {
  5429. desc.Add(jsonutils.NewString(self.OsType), "os_type")
  5430. }
  5431. if len(self.ExternalId) > 0 {
  5432. desc.Add(jsonutils.NewString(self.ExternalId), "externalId")
  5433. }
  5434. desc.Set("hypervisor", jsonutils.NewString(self.GetHypervisor()))
  5435. host, _ := self.GetHost()
  5436. spec := self.GetSpec(false)
  5437. if self.GetHypervisor() == api.HYPERVISOR_BAREMETAL {
  5438. if host != nil {
  5439. hostSpec := host.GetSpec(false)
  5440. hostSpecIdent := HostManager.GetSpecIdent(hostSpec)
  5441. spec.Set("host_spec", jsonutils.NewString(strings.Join(hostSpecIdent, "/")))
  5442. }
  5443. }
  5444. if spec != nil {
  5445. desc.Update(spec)
  5446. }
  5447. var billingInfo SCloudBillingInfo
  5448. if host != nil {
  5449. desc.Set("host", jsonutils.NewString(host.Name))
  5450. desc.Set("host_id", jsonutils.NewString(host.Id))
  5451. billingInfo.SCloudProviderInfo = host.getCloudProviderInfo()
  5452. }
  5453. if len(self.BackupHostId) > 0 {
  5454. backupHost := HostManager.FetchHostById(self.BackupHostId)
  5455. if backupHost != nil {
  5456. desc.Set("backup_host", jsonutils.NewString(backupHost.Name))
  5457. desc.Set("backup_host_id", jsonutils.NewString(backupHost.Id))
  5458. }
  5459. }
  5460. if priceKey := self.GetMetadata(ctx, "ext:price_key", nil); len(priceKey) > 0 {
  5461. billingInfo.PriceKey = priceKey
  5462. }
  5463. billingInfo.SBillingBaseInfo = self.getBillingBaseInfo()
  5464. desc.Update(jsonutils.Marshal(billingInfo))
  5465. return desc
  5466. }
  5467. func (self *SGuest) saveOsType(userCred mcclient.TokenCredential, osType string) error {
  5468. diff, err := db.Update(self, func() error {
  5469. self.OsType = osType
  5470. return nil
  5471. })
  5472. if err != nil {
  5473. return err
  5474. }
  5475. db.OpsLog.LogEvent(self, db.ACT_UPDATE, diff, userCred)
  5476. return err
  5477. }
  5478. type sDeployInfo struct {
  5479. Os string
  5480. Account string
  5481. Key string
  5482. Distro string
  5483. Version string
  5484. Arch string
  5485. Language string
  5486. TelegrafDeployed bool
  5487. CurrentVersion string
  5488. }
  5489. func (self *SGuest) SaveDeployInfo(ctx context.Context, userCred mcclient.TokenCredential, data jsonutils.JSONObject) {
  5490. deployInfo := sDeployInfo{}
  5491. data.Unmarshal(&deployInfo)
  5492. info := make(map[string]interface{})
  5493. if len(deployInfo.Os) > 0 {
  5494. self.saveOsType(userCred, deployInfo.Os)
  5495. info["os_name"] = deployInfo.Os
  5496. }
  5497. driver, _ := self.GetDriver()
  5498. if len(deployInfo.Account) > 0 {
  5499. info["login_account"] = deployInfo.Account
  5500. if len(deployInfo.Key) > 0 {
  5501. info["login_key"] = deployInfo.Key
  5502. if len(self.KeypairId) > 0 && (driver != nil && !driver.IsSupportdDcryptPasswordFromSecretKey()) { // Tencent Cloud does not support simultaneous setting of secret keys and passwords
  5503. info["login_key"], _ = seclib2.EncryptBase64(self.GetKeypairPublicKey(), "")
  5504. }
  5505. info["login_key_timestamp"] = timeutils.UtcNow()
  5506. } else {
  5507. info["login_key"] = "none"
  5508. info["login_key_timestamp"] = "none"
  5509. }
  5510. }
  5511. if len(deployInfo.Distro) > 0 {
  5512. info["os_distribution"] = deployInfo.Distro
  5513. }
  5514. if len(deployInfo.Version) > 0 {
  5515. info["os_version"] = deployInfo.Version
  5516. }
  5517. if len(deployInfo.Arch) > 0 {
  5518. info["os_arch"] = deployInfo.Arch
  5519. }
  5520. if len(deployInfo.Language) > 0 {
  5521. info["os_language"] = deployInfo.Language
  5522. }
  5523. if deployInfo.TelegrafDeployed {
  5524. info["telegraf_deployed"] = true
  5525. }
  5526. if len(deployInfo.CurrentVersion) > 0 {
  5527. info["current_version"] = deployInfo.CurrentVersion
  5528. }
  5529. self.SetAllMetadata(ctx, info, userCred)
  5530. self.saveOldPassword(ctx, userCred)
  5531. }
  5532. func (self *SGuest) isAllDisksReady() bool {
  5533. ready := true
  5534. disks, _ := self.GetGuestDisks()
  5535. if disks == nil || len(disks) == 0 {
  5536. return true
  5537. }
  5538. for i := 0; i < len(disks); i += 1 {
  5539. disk := disks[i].GetDisk()
  5540. if !(disk.isReady() || disk.Status == api.DISK_START_MIGRATE) {
  5541. ready = false
  5542. break
  5543. }
  5544. }
  5545. return ready
  5546. }
  5547. func (self *SGuest) GetKeypairPublicKey() string {
  5548. keypair := self.getKeypair()
  5549. if keypair != nil {
  5550. return keypair.PublicKey
  5551. }
  5552. return ""
  5553. }
  5554. func (self *SGuest) GetKeypair() *SKeypair {
  5555. return self.getKeypair()
  5556. }
  5557. func (manager *SGuestManager) GetIpsInProjectWithName(projectId, name string, isExitOnly bool, addrType api.TAddressType) []string {
  5558. name = strings.TrimSuffix(name, ".")
  5559. ipField := "ip_addr"
  5560. gwField := "guest_gateway"
  5561. if addrType == api.AddressTypeIPv6 {
  5562. ipField = "ip6_addr"
  5563. gwField = "guest_gateway6"
  5564. }
  5565. guestnics := GuestnetworkManager.Query().IsNotEmpty(ipField).SubQuery()
  5566. guestsQ := manager.Query().IsFalse("pending_deleted").Equals("hostname", name)
  5567. if len(projectId) > 0 {
  5568. guestsQ = guestsQ.Equals("tenant_id", projectId)
  5569. }
  5570. guests := guestsQ.SubQuery()
  5571. networks := NetworkManager.Query().IsNotNull(gwField).SubQuery()
  5572. q := guestnics.Query(guestnics.Field(ipField))
  5573. q = q.Join(guests, sqlchemy.Equals(guests.Field("id"), guestnics.Field("guest_id")))
  5574. q = q.Join(networks, sqlchemy.Equals(networks.Field("id"), guestnics.Field("network_id")))
  5575. ips := make([]string, 0)
  5576. rows, err := q.Rows()
  5577. if err != nil {
  5578. log.Errorf("Get guest ip with name query err: %v", err)
  5579. return ips
  5580. }
  5581. defer rows.Close()
  5582. for rows.Next() {
  5583. var ip string
  5584. err = rows.Scan(&ip)
  5585. if err != nil {
  5586. log.Errorf("Get guest ip with name scan err: %v", err)
  5587. return ips
  5588. }
  5589. ips = append(ips, ip)
  5590. }
  5591. if addrType == api.AddressTypeIPv6 {
  5592. return ips
  5593. }
  5594. return manager.getIpsByExit(ips, isExitOnly)
  5595. }
  5596. func (manager *SGuestManager) getIpsByExit(ips []string, isExitOnly bool) []string {
  5597. intRet := make([]string, 0)
  5598. extRet := make([]string, 0)
  5599. for _, ip := range ips {
  5600. addr, _ := netutils.NewIPV4Addr(ip)
  5601. if netutils.IsExitAddress(addr) {
  5602. extRet = append(extRet, ip)
  5603. continue
  5604. }
  5605. intRet = append(intRet, ip)
  5606. }
  5607. if isExitOnly {
  5608. return extRet
  5609. } else if len(intRet) > 0 {
  5610. return intRet
  5611. }
  5612. return extRet
  5613. }
  5614. func (manager *SGuestManager) getExpiredPendingDeleteGuests() []SGuest {
  5615. deadline := time.Now().Add(time.Duration(options.Options.PendingDeleteExpireSeconds*-1) * time.Second)
  5616. q := manager.Query()
  5617. q = q.IsTrue("pending_deleted").LT("pending_deleted_at", deadline).Limit(options.Options.PendingDeleteMaxCleanBatchSize)
  5618. guests := make([]SGuest, 0)
  5619. err := db.FetchModelObjects(GuestManager, q, &guests)
  5620. if err != nil {
  5621. log.Errorf("fetch guests error %s", err)
  5622. return nil
  5623. }
  5624. return guests
  5625. }
  5626. func (manager *SGuestManager) CleanPendingDeleteServers(ctx context.Context, userCred mcclient.TokenCredential, isStart bool) {
  5627. guests := manager.getExpiredPendingDeleteGuests()
  5628. if guests == nil {
  5629. return
  5630. }
  5631. for i := 0; i < len(guests); i += 1 {
  5632. opts := api.ServerDeleteInput{
  5633. OverridePendingDelete: true,
  5634. DeleteSnapshots: options.Options.DeleteSnapshotExpiredRelease,
  5635. DeleteEip: options.Options.DeleteEipExpiredRelease,
  5636. DeleteDisks: options.Options.DeleteDisksExpiredRelease,
  5637. }
  5638. // 跳过单独在云上开机过的虚拟机,避免误清理
  5639. if len(guests[i].GetExternalId()) > 0 {
  5640. iVm, err := guests[i].GetIVM(ctx)
  5641. if err == nil && iVm.GetStatus() == api.VM_RUNNING {
  5642. if guests[i].Status != api.VM_DELETE_FAIL {
  5643. guests[i].SetStatus(ctx, userCred, api.VM_DELETE_FAIL, "vm status is running")
  5644. }
  5645. continue
  5646. }
  5647. }
  5648. guests[i].StartDeleteGuestTask(ctx, userCred, "", opts)
  5649. }
  5650. }
  5651. func (manager *SGuestManager) getExpiredPrepaidGuests() []SGuest {
  5652. deadline := time.Now().Add(time.Duration(options.Options.PrepaidExpireCheckSeconds*-1) * time.Second)
  5653. q := manager.Query()
  5654. q = q.Equals("billing_type", billing_api.BILLING_TYPE_PREPAID).LT("expired_at", deadline).
  5655. IsFalse("pending_deleted").Limit(options.Options.ExpiredPrepaidMaxCleanBatchSize)
  5656. guests := make([]SGuest, 0)
  5657. err := db.FetchModelObjects(GuestManager, q, &guests)
  5658. if err != nil {
  5659. log.Errorf("fetch guests error %s", err)
  5660. return nil
  5661. }
  5662. return guests
  5663. }
  5664. func (manager *SGuestManager) getNeedRenewPrepaidGuests() ([]SGuest, error) {
  5665. deadline := time.Now().Add(time.Duration(options.Options.PrepaidAutoRenewHours)*time.Hour + 20*time.Minute)
  5666. q := manager.Query()
  5667. q = q.Equals("billing_type", billing_api.BILLING_TYPE_PREPAID).LT("expired_at", deadline).
  5668. IsFalse("pending_deleted").In("hypervisor", GetNotSupportAutoRenewHypervisors()).IsTrue("auto_renew")
  5669. guests := make([]SGuest, 0)
  5670. err := db.FetchModelObjects(GuestManager, q, &guests)
  5671. if err != nil {
  5672. return nil, errors.Wrap(err, "db.FetchModelObjects")
  5673. }
  5674. return guests, nil
  5675. }
  5676. func (manager *SGuestManager) getExpiredPostpaidGuests() []SGuest {
  5677. q := ListExpiredPostpaidResources(manager.Query(), options.Options.ExpiredPrepaidMaxCleanBatchSize)
  5678. q = q.IsFalse("pending_deleted")
  5679. guests := make([]SGuest, 0)
  5680. err := db.FetchModelObjects(GuestManager, q, &guests)
  5681. if err != nil {
  5682. log.Errorf("fetch guests error %s", err)
  5683. return nil
  5684. }
  5685. return guests
  5686. }
  5687. func (self *SGuest) doExternalSync(ctx context.Context, userCred mcclient.TokenCredential) error {
  5688. host, _ := self.GetHost()
  5689. if host == nil {
  5690. return fmt.Errorf("no host???")
  5691. }
  5692. ihost, iprovider, err := host.GetIHostAndProvider(ctx)
  5693. if err != nil {
  5694. return err
  5695. }
  5696. iVM, err := ihost.GetIVMById(self.ExternalId)
  5697. if err != nil {
  5698. return err
  5699. }
  5700. return self.syncWithCloudVM(ctx, userCred, iprovider, host, iVM, nil, true)
  5701. }
  5702. func (manager *SGuestManager) DeleteExpiredPrepaidServers(ctx context.Context, userCred mcclient.TokenCredential, isStart bool) {
  5703. guests := manager.getExpiredPrepaidGuests()
  5704. if guests == nil {
  5705. return
  5706. }
  5707. for i := 0; i < len(guests); i += 1 {
  5708. // fake delete expired prepaid servers
  5709. if len(guests[i].ExternalId) > 0 {
  5710. err := guests[i].doExternalSync(ctx, userCred)
  5711. if err == nil && guests[i].IsValidPrePaid() {
  5712. continue
  5713. }
  5714. }
  5715. guests[i].SetDisableDelete(userCred, false)
  5716. opts := api.ServerDeleteInput{
  5717. DeleteSnapshots: options.Options.DeleteSnapshotExpiredRelease,
  5718. DeleteEip: options.Options.DeleteEipExpiredRelease,
  5719. DeleteDisks: options.Options.DeleteDisksExpiredRelease,
  5720. }
  5721. guests[i].StartDeleteGuestTask(ctx, userCred, "", opts)
  5722. }
  5723. }
  5724. func (manager *SGuestManager) AutoRenewPrepaidServer(ctx context.Context, userCred mcclient.TokenCredential, isStart bool) {
  5725. guests, err := manager.getNeedRenewPrepaidGuests()
  5726. if err != nil {
  5727. log.Errorf("failed to get need renew prepaid guests error: %v", err)
  5728. return
  5729. }
  5730. for i := 0; i < len(guests); i += 1 {
  5731. drv, err := guests[i].GetDriver()
  5732. if err != nil {
  5733. continue
  5734. }
  5735. if len(guests[i].ExternalId) > 0 && !drv.IsSupportSetAutoRenew() {
  5736. err := guests[i].doExternalSync(ctx, userCred)
  5737. if err == nil && guests[i].IsValidPrePaid() {
  5738. continue
  5739. }
  5740. }
  5741. guests[i].startGuestRenewTask(ctx, userCred, guests[i].BillingCycle, "")
  5742. }
  5743. }
  5744. func (manager *SGuestManager) DeleteExpiredPostpaidServers(ctx context.Context, userCred mcclient.TokenCredential, isStart bool) {
  5745. guests := manager.getExpiredPostpaidGuests()
  5746. if len(guests) == 0 {
  5747. log.Infof("No expired postpaid guest")
  5748. return
  5749. }
  5750. for i := 0; i < len(guests); i++ {
  5751. if len(guests[i].ExternalId) > 0 {
  5752. err := guests[i].doExternalSync(ctx, userCred)
  5753. if err == nil && guests[i].IsValidPostPaid() {
  5754. continue
  5755. }
  5756. }
  5757. guests[i].SetDisableDelete(userCred, false)
  5758. opts := api.ServerDeleteInput{
  5759. DeleteSnapshots: options.Options.DeleteSnapshotExpiredRelease,
  5760. DeleteEip: options.Options.DeleteEipExpiredRelease,
  5761. DeleteDisks: options.Options.DeleteDisksExpiredRelease,
  5762. }
  5763. guests[i].StartDeleteGuestTask(ctx, userCred, "", opts)
  5764. }
  5765. }
  5766. func (self *SGuest) IsEipAssociable() error {
  5767. if !utils.IsInStringArray(self.Status, []string{api.VM_READY, api.VM_RUNNING}) {
  5768. return errors.Wrapf(httperrors.ErrInvalidStatus, "cannot associate eip in status %s", self.Status)
  5769. }
  5770. err := ValidateAssociateEip(self)
  5771. if err != nil {
  5772. return errors.Wrap(err, "ValidateAssociateEip")
  5773. }
  5774. var eip *SElasticip
  5775. switch self.Hypervisor {
  5776. case api.HYPERVISOR_AWS:
  5777. eip, err = self.GetElasticIp()
  5778. default:
  5779. eip, err = self.GetEipOrPublicIp()
  5780. }
  5781. if err != nil {
  5782. log.Errorf("Fail to get Eip %s", err)
  5783. return errors.Wrap(err, "IsEipAssociable")
  5784. }
  5785. if eip != nil {
  5786. return httperrors.NewInvalidStatusError("already associate with eip")
  5787. }
  5788. return nil
  5789. }
  5790. func (self *SGuest) GetEipOrPublicIp() (*SElasticip, error) {
  5791. return ElasticipManager.getEip(api.EIP_ASSOCIATE_TYPE_SERVER, self.Id, "")
  5792. }
  5793. func (self *SGuest) GetElasticIp() (*SElasticip, error) {
  5794. return ElasticipManager.getEip(api.EIP_ASSOCIATE_TYPE_SERVER, self.Id, api.EIP_MODE_STANDALONE_EIP)
  5795. }
  5796. func (self *SGuest) GetPublicIp() (*SElasticip, error) {
  5797. return ElasticipManager.getEip(api.EIP_ASSOCIATE_TYPE_SERVER, self.Id, api.EIP_MODE_INSTANCE_PUBLICIP)
  5798. }
  5799. func (self *SGuest) SyncVMEip(ctx context.Context, userCred mcclient.TokenCredential, provider *SCloudprovider, extEip cloudprovider.ICloudEIP, syncOwnerId mcclient.IIdentityProvider) compare.SyncResult {
  5800. result := compare.SyncResult{}
  5801. eip, err := self.GetEipOrPublicIp()
  5802. if err != nil {
  5803. result.Error(fmt.Errorf("GetEipOrPublicIp error %s", err))
  5804. return result
  5805. }
  5806. region, err := self.getRegion()
  5807. if err != nil {
  5808. result.Error(fmt.Errorf("getRegion error %s", err))
  5809. return result
  5810. }
  5811. if eip == nil && extEip == nil {
  5812. // do nothing
  5813. return result
  5814. }
  5815. if eip == nil && extEip != nil {
  5816. // add
  5817. neip, err := ElasticipManager.getEipByExtEip(ctx, userCred, extEip, provider, region, syncOwnerId)
  5818. if err != nil {
  5819. result.AddError(errors.Wrapf(err, "getEipByExtEip"))
  5820. return result
  5821. }
  5822. err = neip.AssociateInstance(ctx, userCred, api.EIP_ASSOCIATE_TYPE_SERVER, self)
  5823. if err != nil {
  5824. result.AddError(errors.Wrapf(err, "neip.AssociateInstance"))
  5825. return result
  5826. }
  5827. result.Add()
  5828. return result
  5829. }
  5830. if eip != nil && extEip == nil {
  5831. // remove
  5832. err = eip.Dissociate(ctx, userCred)
  5833. if err != nil {
  5834. result.DeleteError(err)
  5835. return result
  5836. }
  5837. result.Delete()
  5838. return result
  5839. }
  5840. // sync
  5841. if eip.IpAddr != extEip.GetIpAddr() {
  5842. // remove then add
  5843. err = eip.Dissociate(ctx, userCred)
  5844. if err != nil {
  5845. // fail to remove
  5846. result.DeleteError(err)
  5847. return result
  5848. }
  5849. result.Delete()
  5850. neip, err := ElasticipManager.getEipByExtEip(ctx, userCred, extEip, provider, region, syncOwnerId)
  5851. if err != nil {
  5852. result.AddError(err)
  5853. return result
  5854. }
  5855. err = neip.AssociateInstance(ctx, userCred, api.EIP_ASSOCIATE_TYPE_SERVER, self)
  5856. if err != nil {
  5857. result.AddError(err)
  5858. } else {
  5859. result.Add()
  5860. }
  5861. return result
  5862. }
  5863. // do nothing
  5864. err = eip.SyncWithCloudEip(ctx, userCred, provider, extEip, syncOwnerId)
  5865. if err != nil {
  5866. result.UpdateError(err)
  5867. } else {
  5868. result.Update()
  5869. }
  5870. return result
  5871. }
  5872. func (self *SGuest) getSecgroupsBySecgroupExternalIds(externalIds []string) ([]SSecurityGroup, error) {
  5873. vpc, err := self.GetVpc()
  5874. if err != nil {
  5875. return nil, errors.Wrapf(err, "GetVpc")
  5876. }
  5877. region, err := vpc.GetRegion()
  5878. if err != nil {
  5879. return nil, errors.Wrapf(err, "GetRegion")
  5880. }
  5881. filter, err := region.GetDriver().GetSecurityGroupFilter(vpc)
  5882. if err != nil {
  5883. return nil, errors.Wrapf(err, "GetSecurityGroupFilter")
  5884. }
  5885. q := SecurityGroupManager.Query().In("external_id", externalIds)
  5886. q = filter(q)
  5887. secgroups := []SSecurityGroup{}
  5888. err = db.FetchModelObjects(SecurityGroupManager, q, &secgroups)
  5889. if err != nil {
  5890. return nil, errors.Wrapf(err, "db.FetchModelObjects")
  5891. }
  5892. return secgroups, nil
  5893. }
  5894. func (self *SGuest) SyncVMSecgroups(ctx context.Context, userCred mcclient.TokenCredential, externalIds []string) error {
  5895. // clear secgroup if vm not support security group
  5896. drv, err := self.GetDriver()
  5897. if err != nil {
  5898. return err
  5899. }
  5900. if drv.GetMaxSecurityGroupCount() == 0 || len(externalIds) == 0 {
  5901. _, err := db.Update(self, func() error {
  5902. self.SecgrpId = ""
  5903. self.AdminSecgrpId = ""
  5904. return nil
  5905. })
  5906. return err
  5907. }
  5908. secgroups, err := self.getSecgroupsBySecgroupExternalIds(externalIds)
  5909. if err != nil {
  5910. return errors.Wrap(err, "getSecgroupsBySecgroupExternalIds")
  5911. }
  5912. secgroupIds := []string{}
  5913. for _, secgroup := range secgroups {
  5914. secgroupIds = append(secgroupIds, secgroup.Id)
  5915. }
  5916. return self.SaveSecgroups(ctx, userCred, secgroupIds)
  5917. }
  5918. func (self *SGuest) GetIVM(ctx context.Context) (cloudprovider.ICloudVM, error) {
  5919. if len(self.ExternalId) == 0 {
  5920. return nil, errors.Wrapf(cloudprovider.ErrNotFound, "empty externalId")
  5921. }
  5922. host, err := self.GetHost()
  5923. if err != nil {
  5924. return nil, errors.Wrapf(err, "GetHost")
  5925. }
  5926. iregion, err := host.GetIRegion(ctx)
  5927. if err != nil {
  5928. return nil, errors.Wrapf(err, "GetIRegion")
  5929. }
  5930. ihost, err := iregion.GetIHostById(host.ExternalId)
  5931. if err != nil {
  5932. return nil, errors.Wrapf(err, "GetIHost")
  5933. }
  5934. ivm, err := ihost.GetIVMById(self.ExternalId)
  5935. if err != nil {
  5936. if errors.Cause(err) != cloudprovider.ErrNotFound {
  5937. return nil, errors.Wrapf(err, "GetIVMById(%s)", self.ExternalId)
  5938. }
  5939. return iregion.GetIVMById(self.ExternalId)
  5940. }
  5941. return ivm, nil
  5942. }
  5943. func (self *SGuest) PendingDetachScalingGroup() error {
  5944. sggs, err := ScalingGroupGuestManager.Fetch("", self.GetId())
  5945. if err != nil {
  5946. return err
  5947. }
  5948. for i := range sggs {
  5949. sggs[i].SetGuestStatus(api.SG_GUEST_STATUS_PENDING_REMOVE)
  5950. }
  5951. return nil
  5952. }
  5953. func (self *SGuest) DeleteEip(ctx context.Context, userCred mcclient.TokenCredential) error {
  5954. eip, err := self.GetEipOrPublicIp()
  5955. if err != nil {
  5956. log.Errorf("Delete eip fail for get Eip %s", err)
  5957. return err
  5958. }
  5959. if eip == nil {
  5960. return nil
  5961. }
  5962. if eip.Mode == api.EIP_MODE_INSTANCE_PUBLICIP {
  5963. err = eip.RealDelete(ctx, userCred)
  5964. if err != nil {
  5965. log.Errorf("Delete eip on delete server fail %s", err)
  5966. return err
  5967. }
  5968. } else {
  5969. err = eip.Dissociate(ctx, userCred)
  5970. if err != nil {
  5971. log.Errorf("Dissociate eip on delete server fail %s", err)
  5972. return err
  5973. }
  5974. }
  5975. return nil
  5976. }
  5977. func (self *SGuest) SetDisableDelete(userCred mcclient.TokenCredential, val bool) error {
  5978. diff, err := db.Update(self, func() error {
  5979. if val {
  5980. self.DisableDelete = tristate.True
  5981. } else {
  5982. self.DisableDelete = tristate.False
  5983. }
  5984. return nil
  5985. })
  5986. if err != nil {
  5987. return err
  5988. }
  5989. db.OpsLog.LogEvent(self, db.ACT_UPDATE, diff, userCred)
  5990. logclient.AddSimpleActionLog(self, logclient.ACT_UPDATE, diff, userCred, true)
  5991. return err
  5992. }
  5993. func (self *SGuest) getDefaultStorageType() string {
  5994. diskCat := self.CategorizeDisks()
  5995. if diskCat.Root != nil {
  5996. rootStorage, _ := diskCat.Root.GetStorage()
  5997. if rootStorage != nil {
  5998. return rootStorage.StorageType
  5999. }
  6000. }
  6001. return api.STORAGE_LOCAL
  6002. }
  6003. func (self *SGuest) GetApptags() []string {
  6004. tagsStr := self.GetMetadata(context.Background(), api.VM_METADATA_APP_TAGS, nil)
  6005. if len(tagsStr) > 0 {
  6006. return strings.Split(tagsStr, ",")
  6007. }
  6008. return nil
  6009. }
  6010. func (self *SGuest) ToSchedDesc() *schedapi.ScheduleInput {
  6011. desc := new(schedapi.ScheduleInput)
  6012. config := &schedapi.ServerConfig{
  6013. Name: self.Name,
  6014. Memory: self.VmemSize,
  6015. Ncpu: int(self.VcpuCount),
  6016. ServerConfigs: new(api.ServerConfigs),
  6017. }
  6018. desc.Id = self.Id
  6019. self.FillGroupSchedDesc(config.ServerConfigs)
  6020. self.FillDiskSchedDesc(config.ServerConfigs)
  6021. self.FillNetSchedDesc(config.ServerConfigs)
  6022. if len(self.HostId) > 0 && regutils.MatchUUID(self.HostId) {
  6023. desc.HostId = self.HostId
  6024. }
  6025. config.Project = self.ProjectId
  6026. config.Domain = self.DomainId
  6027. /*tags := self.GetApptags()
  6028. for i := 0; i < len(tags); i++ {
  6029. desc.Set(tags[i], jsonutils.JSONTrue)
  6030. }*/
  6031. config.Hypervisor = self.GetHypervisor()
  6032. desc.ServerConfig = *config
  6033. desc.OsArch = self.OsArch
  6034. desc.ExtraCpuCount = self.ExtraCpuCount
  6035. return desc
  6036. }
  6037. func (self *SGuest) FillGroupSchedDesc(desc *api.ServerConfigs) {
  6038. groups := make([]SGroupguest, 0)
  6039. err := GroupguestManager.Query().Equals("guest_id", self.Id).All(&groups)
  6040. if err != nil {
  6041. log.Errorln(err)
  6042. return
  6043. }
  6044. groupids := make([]string, len(groups))
  6045. for i := range groups {
  6046. groupids[i] = groups[i].GroupId
  6047. }
  6048. desc.InstanceGroupIds = groupids
  6049. }
  6050. func (self *SGuest) FillDiskSchedDesc(desc *api.ServerConfigs) {
  6051. guestDisks := make([]SGuestdisk, 0)
  6052. err := GuestdiskManager.Query().Equals("guest_id", self.Id).All(&guestDisks)
  6053. if err != nil {
  6054. log.Errorf("FillDiskSchedDesc: %v", err)
  6055. return
  6056. }
  6057. for i := 0; i < len(guestDisks); i++ {
  6058. diskConf := guestDisks[i].ToDiskConfig()
  6059. // HACK: storage used by self, so earse it
  6060. if !utils.IsInStringArray(diskConf.Backend, api.SHARED_STORAGE) {
  6061. diskConf.Storage = ""
  6062. }
  6063. desc.Disks = append(desc.Disks, diskConf)
  6064. }
  6065. }
  6066. func (self *SGuest) FillNetSchedDesc(desc *api.ServerConfigs) {
  6067. guestNetworks := make([]SGuestnetwork, 0)
  6068. err := GuestnetworkManager.Query().Equals("guest_id", self.Id).All(&guestNetworks)
  6069. if err != nil {
  6070. log.Errorf("FillNetSchedDesc: %v", err)
  6071. return
  6072. }
  6073. if desc.Networks == nil {
  6074. desc.Networks = make([]*api.NetworkConfig, 0)
  6075. }
  6076. for i := 0; i < len(guestNetworks); i++ {
  6077. desc.Networks = append(desc.Networks, guestNetworks[i].ToNetworkConfig())
  6078. }
  6079. }
  6080. func (self *SGuest) GuestDisksHasSnapshot() (bool, error) {
  6081. guestDisks, err := self.GetGuestDisks()
  6082. if err != nil {
  6083. return false, errors.Wrapf(err, "GetGuestDisks")
  6084. }
  6085. for i := 0; i < len(guestDisks); i++ {
  6086. cnt, err := SnapshotManager.GetDiskSnapshotCount(guestDisks[i].DiskId)
  6087. if err != nil {
  6088. return false, err
  6089. }
  6090. if cnt > 0 {
  6091. return true, nil
  6092. }
  6093. }
  6094. return false, nil
  6095. }
  6096. func (self *SGuest) OnScheduleToHost(ctx context.Context, userCred mcclient.TokenCredential, hostId string) error {
  6097. err := self.SetHostId(userCred, hostId)
  6098. if err != nil {
  6099. return err
  6100. }
  6101. notes := jsonutils.NewDict()
  6102. notes.Add(jsonutils.NewString(hostId), "host_id")
  6103. db.OpsLog.LogEvent(self, db.ACT_SCHEDULE, notes, userCred)
  6104. host, _ := self.GetHost()
  6105. return host.ClearSchedDescCache()
  6106. }
  6107. func (guest *SGuest) GetDetailsTasks(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) (jsonutils.JSONObject, error) {
  6108. since := time.Time{}
  6109. if query.Contains("since") {
  6110. since, _ = query.GetTime("since")
  6111. }
  6112. var isOpen *bool = nil
  6113. if query.Contains("is_open") {
  6114. isOpenVal, _ := query.Bool("is_open")
  6115. isOpen = &isOpenVal
  6116. }
  6117. q := taskman.TaskManager.QueryTasksOfObject(guest, since, isOpen)
  6118. objs, err := db.Query2List(taskman.TaskManager, ctx, userCred, q, query, false)
  6119. if err != nil {
  6120. return nil, err
  6121. }
  6122. ret := jsonutils.NewDict()
  6123. ret.Add(jsonutils.NewArray(objs...), "tasks")
  6124. return ret, nil
  6125. }
  6126. func (guest *SGuest) GetDynamicConditionInput() *jsonutils.JSONDict {
  6127. return guest.ToSchedDesc().ToConditionInput()
  6128. }
  6129. func (self *SGuest) ToCreateInput(ctx context.Context, userCred mcclient.TokenCredential) *api.ServerCreateInput {
  6130. genInput := self.toCreateInput()
  6131. userInput, err := self.GetCreateParams(ctx, userCred)
  6132. if err != nil {
  6133. return genInput
  6134. }
  6135. if self.GetHypervisor() != api.HYPERVISOR_BAREMETAL {
  6136. // fill missing create params like schedtags
  6137. disks := []*api.DiskConfig{}
  6138. for idx, disk := range genInput.Disks {
  6139. tmpD := disk
  6140. if idx < len(userInput.Disks) {
  6141. inputDisk := userInput.Disks[idx]
  6142. tmpD.Schedtags = inputDisk.Schedtags
  6143. tmpD.Storage = inputDisk.Storage
  6144. }
  6145. disks = append(disks, tmpD)
  6146. }
  6147. userInput.Disks = disks
  6148. }
  6149. nets := []*api.NetworkConfig{}
  6150. for idx, net := range genInput.Networks {
  6151. tmpN := net
  6152. if idx < len(userInput.Networks) {
  6153. inputNet := userInput.Networks[idx]
  6154. tmpN.Schedtags = inputNet.Schedtags
  6155. tmpN.Network = inputNet.Network
  6156. }
  6157. nets = append(nets, tmpN)
  6158. }
  6159. userInput.Networks = nets
  6160. userInput.IsolatedDevices = genInput.IsolatedDevices
  6161. userInput.Count = 1
  6162. // override some old userInput properties via genInput because of change config behavior
  6163. userInput.VmemSize = genInput.VmemSize
  6164. userInput.VcpuCount = genInput.VcpuCount
  6165. userInput.Vga = genInput.Vga
  6166. userInput.Vdi = genInput.Vdi
  6167. userInput.Bios = genInput.Bios
  6168. userInput.Cdrom = genInput.Cdrom
  6169. userInput.Description = genInput.Description
  6170. userInput.BootOrder = genInput.BootOrder
  6171. userInput.DisableDelete = genInput.DisableDelete
  6172. userInput.ShutdownBehavior = genInput.ShutdownBehavior
  6173. userInput.IsSystem = genInput.IsSystem
  6174. userInput.SecgroupId = genInput.SecgroupId
  6175. userInput.KeypairId = genInput.KeypairId
  6176. userInput.EipBw = genInput.EipBw
  6177. userInput.EipChargeType = genInput.EipChargeType
  6178. drv, _ := self.GetDriver()
  6179. if drv != nil && drv.IsSupportPublicIp() {
  6180. userInput.PublicIpBw = genInput.PublicIpBw
  6181. userInput.PublicIpChargeType = genInput.PublicIpChargeType
  6182. }
  6183. userInput.AutoRenew = genInput.AutoRenew
  6184. // cloned server should belongs to the project creating it
  6185. userInput.ProjectId = userCred.GetProjectId()
  6186. userInput.ProjectDomainId = userCred.GetProjectDomainId()
  6187. userInput.Secgroups = []string{}
  6188. secgroups, _ := self.GetSecgroups()
  6189. for _, secgroup := range secgroups {
  6190. userInput.Secgroups = append(userInput.Secgroups, secgroup.Id)
  6191. }
  6192. if genInput.ResourceType != "" {
  6193. userInput.ResourceType = genInput.ResourceType
  6194. }
  6195. if genInput.InstanceType != "" {
  6196. userInput.InstanceType = genInput.InstanceType
  6197. }
  6198. if genInput.PreferRegion != "" {
  6199. userInput.PreferRegion = genInput.PreferRegion
  6200. }
  6201. if genInput.PreferZone != "" {
  6202. userInput.PreferZone = genInput.PreferZone
  6203. }
  6204. // clean some of user input
  6205. userInput.GenerateName = ""
  6206. userInput.Description = ""
  6207. userInput.Hostname = ""
  6208. return userInput
  6209. }
  6210. func (self *SGuest) toCreateInput() *api.ServerCreateInput {
  6211. r := new(api.ServerCreateInput)
  6212. r.VmemSize = self.VmemSize
  6213. r.VcpuCount = int(self.VcpuCount)
  6214. if guestCdrom := self.getCdrom(false, 0); guestCdrom != nil {
  6215. r.Cdrom = guestCdrom.ImageId
  6216. }
  6217. r.Vga = self.Vga
  6218. r.Vdi = self.Vdi
  6219. r.Bios = self.Bios
  6220. r.Description = self.Description
  6221. r.BootOrder = self.BootOrder
  6222. r.DisableDelete = new(bool)
  6223. *r.DisableDelete = self.DisableDelete.Bool()
  6224. r.ShutdownBehavior = self.ShutdownBehavior
  6225. // ignore r.DeployConfigs
  6226. r.IsSystem = &self.IsSystem
  6227. r.SecgroupId = self.SecgrpId
  6228. r.ServerConfigs = new(api.ServerConfigs)
  6229. r.Hypervisor = self.Hypervisor
  6230. r.InstanceType = self.InstanceType
  6231. r.ProjectId = self.ProjectId
  6232. r.ProjectDomainId = self.DomainId
  6233. r.Count = 1
  6234. r.Disks = self.ToDisksConfig()
  6235. r.Networks = self.ToNetworksConfig()
  6236. r.IsolatedDevices = self.ToIsolatedDevicesConfig()
  6237. r.AutoRenew = self.AutoRenew
  6238. if keypair := self.getKeypair(); keypair != nil {
  6239. r.KeypairId = keypair.Id
  6240. }
  6241. if host, _ := self.GetHost(); host != nil {
  6242. r.ResourceType = host.ResourceType
  6243. }
  6244. if eip, _ := self.GetEipOrPublicIp(); eip != nil {
  6245. switch eip.Mode {
  6246. case api.EIP_MODE_STANDALONE_EIP:
  6247. r.EipBw = eip.Bandwidth
  6248. r.EipChargeType = eip.ChargeType
  6249. case api.EIP_MODE_INSTANCE_PUBLICIP:
  6250. drv, _ := self.GetDriver()
  6251. if drv != nil && drv.IsSupportPublicIp() {
  6252. r.PublicIpBw = eip.Bandwidth
  6253. r.PublicIpChargeType = eip.ChargeType
  6254. }
  6255. }
  6256. }
  6257. if zone, _ := self.getZone(); zone != nil {
  6258. region, _ := zone.GetRegion()
  6259. r.PreferRegion = region.GetId()
  6260. r.PreferZone = zone.GetId()
  6261. }
  6262. return r
  6263. }
  6264. func (self *SGuest) ToDisksConfig() []*api.DiskConfig {
  6265. guestDisks, err := self.GetGuestDisks()
  6266. if err != nil {
  6267. return nil
  6268. }
  6269. ret := make([]*api.DiskConfig, len(guestDisks))
  6270. for idx, guestDisk := range guestDisks {
  6271. diskConf := new(api.DiskConfig)
  6272. disk := guestDisk.GetDisk()
  6273. diskConf.Index = int(guestDisk.Index)
  6274. diskConf.ImageId = disk.GetTemplateId()
  6275. diskConf.SnapshotId = disk.SnapshotId
  6276. diskConf.DiskType = disk.DiskType
  6277. diskConf.SizeMb = disk.DiskSize
  6278. diskConf.Fs = disk.FsFormat
  6279. diskConf.Format = disk.DiskFormat
  6280. diskConf.Driver = guestDisk.Driver
  6281. diskConf.Cache = guestDisk.CacheMode
  6282. diskConf.Mountpoint = guestDisk.Mountpoint
  6283. storage, _ := disk.GetStorage()
  6284. diskConf.Backend = storage.StorageType
  6285. diskConf.Medium = storage.MediumType
  6286. ret[idx] = diskConf
  6287. }
  6288. return ret
  6289. }
  6290. func (self *SGuest) ToNetworksConfig() []*api.NetworkConfig {
  6291. guestNetworks, _ := self.GetNetworks("")
  6292. if len(guestNetworks) == 0 {
  6293. return nil
  6294. }
  6295. ret := make([]*api.NetworkConfig, 0)
  6296. teamMacs := []string{}
  6297. for _, gn := range guestNetworks {
  6298. if tg, _ := gn.GetTeamGuestnetwork(); tg != nil {
  6299. teamMacs = append(teamMacs, gn.TeamWith)
  6300. }
  6301. }
  6302. for _, guestNetwork := range guestNetworks {
  6303. netConf := new(api.NetworkConfig)
  6304. network, err := guestNetwork.GetNetwork()
  6305. if err != nil {
  6306. continue
  6307. }
  6308. requireTeaming := false
  6309. if tg, _ := guestNetwork.GetTeamGuestnetwork(); tg != nil {
  6310. requireTeaming = true
  6311. }
  6312. if utils.IsInStringArray(guestNetwork.MacAddr, teamMacs) {
  6313. continue
  6314. }
  6315. // XXX: same wire
  6316. netConf.Wire = network.WireId
  6317. netConf.Network = network.Id
  6318. netConf.Exit = guestNetwork.IsExit(nil)
  6319. if len(guestNetwork.Ip6Addr) > 0 {
  6320. netConf.RequireIPv6 = true
  6321. if len(guestNetwork.IpAddr) == 0 {
  6322. netConf.StrictIPv6 = true
  6323. }
  6324. }
  6325. // netConf.Private
  6326. // netConf.Reserved
  6327. netConf.Driver = guestNetwork.Driver
  6328. netConf.BwLimit = guestNetwork.BwLimit
  6329. netConf.RequireTeaming = requireTeaming
  6330. // netConf.NetType
  6331. ret = append(ret, netConf)
  6332. }
  6333. return ret
  6334. }
  6335. func (self *SGuest) ToIsolatedDevicesConfig() []*api.IsolatedDeviceConfig {
  6336. guestIsolatedDevices, _ := self.GetIsolatedDevices()
  6337. if len(guestIsolatedDevices) == 0 {
  6338. return nil
  6339. }
  6340. ret := make([]*api.IsolatedDeviceConfig, len(guestIsolatedDevices))
  6341. for idx, guestIsolatedDevice := range guestIsolatedDevices {
  6342. devConf := new(api.IsolatedDeviceConfig)
  6343. devConf.Model = guestIsolatedDevice.Model
  6344. devConf.Vendor = guestIsolatedDevice.getVendor()
  6345. devConf.DevType = guestIsolatedDevice.DevType
  6346. ret[idx] = devConf
  6347. }
  6348. return ret
  6349. }
  6350. func (self *SGuest) IsImport(ctx context.Context, userCred mcclient.TokenCredential) bool {
  6351. return self.GetMetadata(ctx, "__is_import", userCred) == "true"
  6352. }
  6353. func (guest *SGuest) GetDetailsRemoteNics(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) (jsonutils.JSONObject, error) {
  6354. iVM, err := guest.GetIVM(ctx)
  6355. if err != nil {
  6356. return nil, httperrors.NewGeneralError(err)
  6357. }
  6358. iNics, err := iVM.GetINics()
  6359. if err != nil {
  6360. return nil, httperrors.NewGeneralError(err)
  6361. }
  6362. type SVNic struct {
  6363. Index int
  6364. Ip string
  6365. Mac string
  6366. Driver string
  6367. }
  6368. nics := make([]SVNic, len(iNics))
  6369. for i := range iNics {
  6370. nics[i] = SVNic{
  6371. Index: i,
  6372. Ip: iNics[i].GetIP(),
  6373. Mac: iNics[i].GetMAC(),
  6374. Driver: iNics[i].GetDriver(),
  6375. }
  6376. }
  6377. // ret := jsonutils.NewDict()
  6378. // ret.Set("vnics", jsonutils.Marshal(nics))
  6379. return jsonutils.Marshal(nics), nil
  6380. }
  6381. func (self *SGuest) GetInstanceSnapshots() ([]SInstanceSnapshot, error) {
  6382. instanceSnapshots := make([]SInstanceSnapshot, 0)
  6383. q := InstanceSnapshotManager.Query().Equals("guest_id", self.Id)
  6384. err := db.FetchModelObjects(InstanceSnapshotManager, q, &instanceSnapshots)
  6385. if err != nil {
  6386. return nil, err
  6387. }
  6388. return instanceSnapshots, nil
  6389. }
  6390. func (self *SGuest) GetInstanceSnapshotCount() (int, error) {
  6391. q := InstanceSnapshotManager.Query().Equals("guest_id", self.Id)
  6392. return q.CountWithError()
  6393. }
  6394. func (self *SGuest) GetDiskSnapshotsNotInInstanceSnapshots() ([]SSnapshot, error) {
  6395. guestDisks, err := self.GetGuestDisks()
  6396. if err != nil {
  6397. return nil, errors.Wrapf(err, "GetGuestDisks")
  6398. }
  6399. diskIds := make([]string, len(guestDisks))
  6400. for i := 0; i < len(guestDisks); i++ {
  6401. diskIds[i] = guestDisks[i].DiskId
  6402. }
  6403. snapshots := make([]SSnapshot, 0)
  6404. q := SnapshotManager.Query().IsFalse("fake_deleted").In("disk_id", diskIds)
  6405. sq := InstanceSnapshotJointManager.Query("snapshot_id").SubQuery()
  6406. q = q.LeftJoin(sq, sqlchemy.Equals(q.Field("id"), sq.Field("snapshot_id"))).
  6407. Filter(sqlchemy.IsNull(sq.Field("snapshot_id")))
  6408. err = db.FetchModelObjects(SnapshotManager, q, &snapshots)
  6409. if err != nil {
  6410. return nil, errors.Wrapf(err, "db.FetchModelObjects")
  6411. }
  6412. return snapshots, nil
  6413. }
  6414. func (self *SGuest) getGuestUsage(guestCount int) (SQuota, SRegionQuota, error) {
  6415. usage := SQuota{}
  6416. regionUsage := SRegionQuota{}
  6417. usage.Count = guestCount
  6418. usage.Cpu = int(self.VcpuCount) * guestCount
  6419. usage.Memory = int(self.VmemSize * guestCount)
  6420. diskSize := self.getDiskSize()
  6421. if diskSize < 0 {
  6422. return usage, regionUsage, httperrors.NewInternalServerError("fetch disk size failed")
  6423. }
  6424. usage.Storage = self.getDiskSize() * guestCount
  6425. netCount, err := self.NetworkCount()
  6426. if err != nil && errors.Cause(err) != sql.ErrNoRows {
  6427. return usage, regionUsage, err
  6428. }
  6429. regionUsage.Port = netCount
  6430. // regionUsage.Bw = self.getBandwidth(false)
  6431. eip, err := self.GetEipOrPublicIp()
  6432. if err != nil && errors.Cause(err) != sql.ErrNoRows {
  6433. return usage, regionUsage, err
  6434. }
  6435. if eip != nil {
  6436. regionUsage.Eip = 1
  6437. }
  6438. return usage, regionUsage, nil
  6439. }
  6440. func (self *SGuestManager) checkGuestImage(ctx context.Context, input *api.ServerCreateInput) error {
  6441. if len(input.GuestImageID) == 0 {
  6442. return nil
  6443. }
  6444. guestImageId := input.GuestImageID
  6445. params := jsonutils.NewDict()
  6446. params.Add(jsonutils.JSONTrue, "details")
  6447. s := auth.GetAdminSession(ctx, options.Options.Region)
  6448. ret, err := image.GuestImages.Get(s, guestImageId, params)
  6449. if err != nil {
  6450. return errors.Wrap(err, "get guest image from glance error")
  6451. }
  6452. images := &api.SImagesInGuest{}
  6453. err = ret.Unmarshal(images)
  6454. if err != nil {
  6455. return errors.Wrap(err, "unmarshal guest image")
  6456. }
  6457. input.GuestImageID = images.Id
  6458. log.Infof("usage guest image %s(%s)", images.Name, images.Id)
  6459. if len(input.Disks) > 0 {
  6460. input.Disks[0].ImageId = images.RootImage.Id
  6461. } else {
  6462. input.Disks = append(input.Disks,
  6463. &api.DiskConfig{
  6464. ImageId: images.RootImage.Id,
  6465. },
  6466. )
  6467. }
  6468. for i := range images.DataImages {
  6469. if len(input.Disks) > i+1 {
  6470. input.Disks[i+1].ImageId = images.DataImages[i].Id
  6471. } else {
  6472. input.Disks = append(input.Disks,
  6473. &api.DiskConfig{
  6474. ImageId: images.DataImages[i].Id,
  6475. },
  6476. )
  6477. }
  6478. }
  6479. return nil
  6480. }
  6481. func (self *SGuest) GetDiskIndex(diskId string) int8 {
  6482. guestDisks, _ := self.GetGuestDisks()
  6483. for _, gd := range guestDisks {
  6484. if gd.DiskId == diskId {
  6485. return gd.Index
  6486. }
  6487. }
  6488. return -1
  6489. }
  6490. func (guest *SGuest) GetRegionalQuotaKeys() (quotas.IQuotaKeys, error) {
  6491. host, _ := guest.GetHost()
  6492. if host == nil {
  6493. return nil, errors.Wrap(httperrors.ErrInvalidStatus, "no valid host")
  6494. }
  6495. provider := host.GetCloudprovider()
  6496. if provider == nil && len(host.ManagerId) > 0 {
  6497. return nil, errors.Wrap(httperrors.ErrInvalidStatus, "no valid manager")
  6498. }
  6499. region, _ := host.GetRegion()
  6500. if region == nil {
  6501. return nil, errors.Wrap(httperrors.ErrInvalidStatus, "no valid region")
  6502. }
  6503. return fetchRegionalQuotaKeys(rbacscope.ScopeProject, guest.GetOwnerId(), region, provider), nil
  6504. }
  6505. func (guest *SGuest) GetCloudprovider() (*SCloudprovider, error) {
  6506. hosts := HostManager.Query("manager_id").Equals("id", guest.HostId).SubQuery()
  6507. q := CloudproviderManager.Query().In("id", hosts)
  6508. ret := &SCloudprovider{}
  6509. ret.SetModelManager(CloudproviderManager, ret)
  6510. err := q.First(ret)
  6511. if err != nil {
  6512. return nil, errors.Wrapf(err, "q.First")
  6513. }
  6514. return ret, nil
  6515. }
  6516. func (guest *SGuest) GetQuotaKeys() (quotas.IQuotaKeys, error) {
  6517. provider, _ := guest.GetCloudprovider()
  6518. zone, _ := guest.GetZone()
  6519. hypervisor := guest.Hypervisor
  6520. return fetchComputeQuotaKeys(
  6521. rbacscope.ScopeProject,
  6522. guest.GetOwnerId(),
  6523. zone,
  6524. provider,
  6525. hypervisor,
  6526. ), nil
  6527. }
  6528. func (guest *SGuest) GetUsages() []db.IUsage {
  6529. if guest.PendingDeleted || guest.Deleted {
  6530. return nil
  6531. }
  6532. usage, regionUsage, err := guest.getGuestUsage(1)
  6533. if err != nil {
  6534. log.Errorf("guest.getGuestUsage fail %s", err)
  6535. return nil
  6536. }
  6537. keys, err := guest.GetQuotaKeys()
  6538. if err != nil {
  6539. log.Errorf("guest.GetQuotaKeys fail %s", err)
  6540. return nil
  6541. }
  6542. usage.SetKeys(keys)
  6543. regionUsage.SetKeys(keys.(SComputeResourceKeys).SRegionalCloudResourceKeys)
  6544. return []db.IUsage{
  6545. &usage,
  6546. &regionUsage,
  6547. }
  6548. }
  6549. var (
  6550. // `^[a-zA-Z][a-zA-Z0-9._@-]*$`)
  6551. serverNameREG = regexp.MustCompile(`^[a-zA-Z$][a-zA-Z0-9-${}.]*$`)
  6552. hostnameREG = regexp.MustCompile(`^[a-z$][a-z0-9-${}.]*$`)
  6553. )
  6554. func (manager *SGuestManager) ValidateNameLoginAccount(name string) error {
  6555. if serverNameREG.MatchString(name) {
  6556. return nil
  6557. }
  6558. return httperrors.NewInputParameterError("name starts with letter, and contains letter, number and - only")
  6559. }
  6560. func (guest *SGuest) StartRemoteUpdateTask(ctx context.Context, userCred mcclient.TokenCredential, replaceTags bool, parentTaskId string) error {
  6561. data := jsonutils.NewDict()
  6562. if replaceTags {
  6563. data.Add(jsonutils.JSONTrue, "replace_tags")
  6564. }
  6565. if task, err := taskman.TaskManager.NewTask(ctx, "GuestRemoteUpdateTask", guest, userCred, data, parentTaskId, "", nil); err != nil {
  6566. log.Errorln(err)
  6567. return errors.Wrap(err, "Start GuestRemoteUpdateTask")
  6568. } else {
  6569. guest.SetStatus(ctx, userCred, api.VM_UPDATE_TAGS, "StartRemoteUpdateTask")
  6570. task.ScheduleRun(nil)
  6571. }
  6572. return nil
  6573. }
  6574. func (guest *SGuest) OnMetadataUpdated(ctx context.Context, userCred mcclient.TokenCredential) {
  6575. if len(guest.ExternalId) == 0 || options.Options.KeepTagLocalization {
  6576. return
  6577. }
  6578. host, err := guest.GetHost()
  6579. if err != nil {
  6580. return
  6581. }
  6582. if account := host.GetCloudaccount(); account != nil && account.ReadOnly {
  6583. return
  6584. }
  6585. err = guest.StartRemoteUpdateTask(ctx, userCred, true, "")
  6586. if err != nil {
  6587. log.Errorf("StartRemoteUpdateTask fail: %s", err)
  6588. }
  6589. }
  6590. func (self *SGuest) GetAddress() (string, error) {
  6591. gns, err := self.GetNetworks("")
  6592. if err != nil {
  6593. return "", errors.Wrapf(err, "GetNetworks")
  6594. }
  6595. for _, gn := range gns {
  6596. if !gn.IsExit(nil) {
  6597. return gn.IpAddr, nil
  6598. }
  6599. }
  6600. return "", errors.Wrapf(cloudprovider.ErrNotFound, "guest %s address", self.Name)
  6601. }
  6602. func (guest *SGuest) InferPowerStates() {
  6603. if len(guest.PowerStates) == 0 {
  6604. switch guest.Status {
  6605. case api.VM_READY:
  6606. guest.PowerStates = api.VM_POWER_STATES_OFF
  6607. case api.VM_UNKNOWN:
  6608. guest.PowerStates = api.VM_POWER_STATES_UNKNOWN
  6609. case api.VM_INIT:
  6610. guest.PowerStates = api.VM_POWER_STATES_ON
  6611. case api.VM_SCHEDULE:
  6612. guest.PowerStates = api.VM_POWER_STATES_ON
  6613. case api.VM_SCHEDULE_FAILED:
  6614. guest.PowerStates = api.VM_POWER_STATES_ON
  6615. case api.VM_CREATE_NETWORK:
  6616. guest.PowerStates = api.VM_POWER_STATES_ON
  6617. case api.VM_NETWORK_FAILED:
  6618. guest.PowerStates = api.VM_POWER_STATES_ON
  6619. case api.VM_DEVICE_FAILED:
  6620. guest.PowerStates = api.VM_POWER_STATES_UNKNOWN
  6621. case api.VM_CREATE_FAILED:
  6622. guest.PowerStates = api.VM_POWER_STATES_OFF
  6623. case api.VM_CREATE_DISK:
  6624. guest.PowerStates = api.VM_POWER_STATES_OFF
  6625. case api.VM_DISK_FAILED:
  6626. guest.PowerStates = api.VM_POWER_STATES_OFF
  6627. case api.VM_IMAGE_CACHING:
  6628. guest.PowerStates = api.VM_POWER_STATES_ON
  6629. case api.VM_START_DEPLOY:
  6630. guest.PowerStates = api.VM_POWER_STATES_ON
  6631. case api.VM_DEPLOYING:
  6632. guest.PowerStates = api.VM_POWER_STATES_OFF
  6633. case api.VM_START_START:
  6634. guest.PowerStates = api.VM_POWER_STATES_ON
  6635. case api.VM_STARTING:
  6636. guest.PowerStates = api.VM_POWER_STATES_ON
  6637. case api.VM_START_FAILED:
  6638. guest.PowerStates = api.VM_POWER_STATES_OFF
  6639. case api.VM_RUNNING:
  6640. guest.PowerStates = api.VM_POWER_STATES_ON
  6641. case api.VM_START_STOP:
  6642. guest.PowerStates = api.VM_POWER_STATES_ON
  6643. case api.VM_STOPPING:
  6644. guest.PowerStates = api.VM_POWER_STATES_ON
  6645. case api.VM_STOP_FAILED:
  6646. guest.PowerStates = api.VM_POWER_STATES_ON
  6647. case api.VM_RENEWING:
  6648. guest.PowerStates = api.VM_POWER_STATES_ON
  6649. case api.VM_RENEW_FAILED:
  6650. guest.PowerStates = api.VM_POWER_STATES_ON
  6651. case api.VM_ATTACH_DISK:
  6652. guest.PowerStates = api.VM_POWER_STATES_UNKNOWN
  6653. case api.VM_DETACH_DISK:
  6654. guest.PowerStates = api.VM_POWER_STATES_UNKNOWN
  6655. default:
  6656. guest.PowerStates = api.VM_POWER_STATES_UNKNOWN
  6657. }
  6658. }
  6659. }
  6660. func (guest *SGuest) HasBackupGuest() bool {
  6661. return guest.BackupHostId != ""
  6662. }
  6663. func (guest *SGuest) SetGuestBackupMirrorJobInProgress(ctx context.Context, userCred mcclient.TokenCredential) error {
  6664. return guest.SetMetadata(ctx, api.MIRROR_JOB, api.MIRROR_JOB_INPROGRESS, userCred)
  6665. }
  6666. func (guest *SGuest) SetKickstartConfig(ctx context.Context, config *api.KickstartConfig, userCred mcclient.TokenCredential) error {
  6667. if config == nil {
  6668. return guest.RemoveMetadata(ctx, api.VM_METADATA_KICKSTART_CONFIG, userCred)
  6669. }
  6670. if err := validateKickstartConfig(config); err != nil {
  6671. return errors.Wrap(err, "validate kickstart config")
  6672. }
  6673. configJson := jsonutils.Marshal(config)
  6674. return guest.SetMetadata(ctx, api.VM_METADATA_KICKSTART_CONFIG, configJson, userCred)
  6675. }
  6676. func (guest *SGuest) GetKickstartConfig(ctx context.Context, userCred mcclient.TokenCredential) (*api.KickstartConfig, error) {
  6677. configJson := guest.GetMetadataJson(ctx, api.VM_METADATA_KICKSTART_CONFIG, userCred)
  6678. if configJson == nil {
  6679. return nil, nil
  6680. }
  6681. config := &api.KickstartConfig{}
  6682. if err := configJson.Unmarshal(config); err != nil {
  6683. return nil, errors.Wrap(err, "unmarshal kickstart config")
  6684. }
  6685. return config, nil
  6686. }
  6687. func (guest *SGuest) SetKickstartStatus(ctx context.Context, status string, userCred mcclient.TokenCredential) error {
  6688. if !utils.IsInStringArray(status, api.VM_KICKSTART_STATUS) {
  6689. return errors.Errorf("invalid kickstart status: %s", status)
  6690. }
  6691. return guest.SetStatus(ctx, userCred, status, "")
  6692. }
  6693. func (guest *SGuest) GetKickstartStatus(ctx context.Context, userCred mcclient.TokenCredential) string {
  6694. if utils.IsInStringArray(guest.Status, api.VM_KICKSTART_STATUS) {
  6695. return guest.Status
  6696. }
  6697. return ""
  6698. }
  6699. func (guest *SGuest) IsInKickstartStatus() bool {
  6700. return utils.IsInStringArray(guest.Status, api.VM_KICKSTART_STATUS)
  6701. }
  6702. func (guest *SGuest) SetKickstartType(ctx context.Context, kickstartType string, userCred mcclient.TokenCredential) error {
  6703. if !utils.IsInStringArray(kickstartType, api.KICKSTART_VALID_TYPES) {
  6704. return errors.Errorf("invalid kickstart type: %s", kickstartType)
  6705. }
  6706. return guest.SetMetadata(ctx, api.VM_METADATA_KICKSTART_TYPE, kickstartType, userCred)
  6707. }
  6708. func (guest *SGuest) GetKickstartType(ctx context.Context, userCred mcclient.TokenCredential) string {
  6709. kickstartType := guest.GetMetadata(ctx, api.VM_METADATA_KICKSTART_TYPE, userCred)
  6710. if kickstartType == "" {
  6711. return api.KICKSTART_TYPE_URL
  6712. }
  6713. return kickstartType
  6714. }
  6715. func (guest *SGuest) IsKickstartEnabled(ctx context.Context, userCred mcclient.TokenCredential) bool {
  6716. config, err := guest.GetKickstartConfig(ctx, userCred)
  6717. if err != nil || config == nil {
  6718. return false
  6719. }
  6720. if config.Enabled == nil {
  6721. return true
  6722. }
  6723. return *config.Enabled
  6724. }
  6725. func (guest *SGuest) SetGuestBackupMirrorJobNotReady(ctx context.Context, userCred mcclient.TokenCredential) error {
  6726. return guest.SetMetadata(ctx, api.MIRROR_JOB, "", userCred)
  6727. }
  6728. func (guest *SGuest) TrySetGuestBackupMirrorJobReady(ctx context.Context, userCred mcclient.TokenCredential) error {
  6729. if guest.IsGuestBackupMirrorJobFailed(ctx, userCred) {
  6730. // can't update guest backup mirror job status from failed to ready
  6731. return nil
  6732. }
  6733. return guest.SetMetadata(ctx, api.MIRROR_JOB, api.MIRROR_JOB_READY, userCred)
  6734. }
  6735. func (guest *SGuest) SetGuestBackupMirrorJobFailed(ctx context.Context, userCred mcclient.TokenCredential) error {
  6736. return guest.SetMetadata(ctx, api.MIRROR_JOB, api.MIRROR_JOB_FAILED, userCred)
  6737. }
  6738. func (guest *SGuest) IsGuestBackupMirrorJobFailed(ctx context.Context, userCred mcclient.TokenCredential) bool {
  6739. return guest.GetMetadata(ctx, api.MIRROR_JOB, userCred) == api.MIRROR_JOB_FAILED
  6740. }
  6741. func (guest *SGuest) IsGuestBackupMirrorJobReady(ctx context.Context, userCred mcclient.TokenCredential) bool {
  6742. return guest.GetMetadata(ctx, api.MIRROR_JOB, userCred) == api.MIRROR_JOB_READY
  6743. }
  6744. func (guest *SGuest) GetGuestBackupMirrorJobStatus(ctx context.Context, userCred mcclient.TokenCredential) string {
  6745. return guest.GetMetadata(ctx, api.MIRROR_JOB, userCred)
  6746. }
  6747. func (guest *SGuest) ResetGuestQuorumChildIndex(ctx context.Context, userCred mcclient.TokenCredential) error {
  6748. return guest.SetMetadata(ctx, api.QUORUM_CHILD_INDEX, "", userCred)
  6749. }
  6750. type SGuestTotalCount struct {
  6751. apis.TotalCountBase
  6752. CpuCount int
  6753. MemMb int
  6754. DiskMb int64
  6755. DiskCount int
  6756. }
  6757. func (manager *SGuestManager) CustomizedTotalCount(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, totalQ *sqlchemy.SQuery) (int, jsonutils.JSONObject, error) {
  6758. results := SGuestTotalCount{}
  6759. totalQ = totalQ.AppendField(sqlchemy.SUM("cpu_count", totalQ.Field("vcpu_count")))
  6760. totalQ = totalQ.AppendField(sqlchemy.SUM("mem_mb", totalQ.Field("vmem_size")))
  6761. err := totalQ.First(&results)
  6762. if err != nil {
  6763. return -1, nil, errors.Wrap(err, "SGuestManager query total")
  6764. }
  6765. log.Debugf("CustomizedTotalCount %s", jsonutils.Marshal(results))
  6766. diskQ := DiskManager.Query()
  6767. diskGuestQ := GuestdiskManager.Query().SubQuery()
  6768. diskQ = diskQ.Join(diskGuestQ, sqlchemy.Equals(diskQ.Field("id"), diskGuestQ.Field("disk_id")))
  6769. totalSQ := totalQ.ResetFields().SubQuery()
  6770. diskQ = diskQ.Join(totalSQ, sqlchemy.Equals(diskGuestQ.Field("guest_id"), totalSQ.Field("id")))
  6771. diskQ = diskQ.AppendField(sqlchemy.COUNT("disk_count"))
  6772. diskQ = diskQ.AppendField(sqlchemy.SUM("disk_mb", diskQ.Field("disk_size")))
  6773. err = diskQ.First(&results)
  6774. if err != nil {
  6775. return -1, nil, errors.Wrap(err, "SGuestManager query total_disk")
  6776. }
  6777. _, statusInfo, err := manager.SVirtualResourceBaseManager.CustomizedTotalCount(ctx, userCred, query, totalQ)
  6778. if err != nil {
  6779. return -1, nil, errors.Wrapf(err, "virt.CustomizedTotalCount")
  6780. }
  6781. ret := jsonutils.Marshal(results).(*jsonutils.JSONDict)
  6782. ret.Update(statusInfo)
  6783. return results.Count, ret, nil
  6784. }
  6785. func (guest *SGuest) IsSriov() bool {
  6786. nics, err := guest.GetNetworks("")
  6787. if err != nil {
  6788. log.Errorf("guest.GetNetworks fail %s", err)
  6789. return false
  6790. }
  6791. for i := range nics {
  6792. if nics[i].Driver == api.NETWORK_DRIVER_VFIO {
  6793. return true
  6794. }
  6795. }
  6796. return false
  6797. }
  6798. func (guest *SGuest) getDisksCandidateHostIds() ([]string, error) {
  6799. disks, err := guest.GetDisks()
  6800. if err != nil {
  6801. return nil, errors.Wrap(err, "guest.GetDisks")
  6802. }
  6803. ret := stringutils2.NewSortedStrings(nil)
  6804. for i := range disks {
  6805. candidates, err := disks[i].getCandidateHostIds()
  6806. if err != nil {
  6807. return nil, errors.Wrap(err, "getCandidateHostIds")
  6808. }
  6809. sorted := stringutils2.NewSortedStrings(candidates)
  6810. if i > 0 {
  6811. ret = stringutils2.Intersect(ret, sorted)
  6812. } else {
  6813. ret = sorted
  6814. }
  6815. }
  6816. return ret, nil
  6817. }
  6818. func (guest *SGuest) SaveLastStartAt() error {
  6819. _, err := db.Update(guest, func() error {
  6820. guest.LastStartAt = time.Now().UTC()
  6821. return nil
  6822. })
  6823. return errors.Wrap(err, "SaveLastStartAt")
  6824. }
  6825. func (guest *SGuest) finalizeFakeDeleteTask(ctx context.Context, userCred mcclient.TokenCredential, task taskman.ITask) {
  6826. db.OpsLog.LogEvent(guest, db.ACT_PENDING_DELETE, guest.GetShortDesc(ctx), userCred)
  6827. logclient.AddActionLogWithStartable(task, guest, logclient.ACT_PENDING_DELETE, guest.GetShortDesc(ctx), userCred, true)
  6828. if !guest.IsSystem {
  6829. guest.EventNotify(ctx, userCred, notifyclient.ActionPendingDelete)
  6830. }
  6831. }
  6832. func (guest *SGuest) finalizeRealDeleteTask(ctx context.Context, userCred mcclient.TokenCredential, task taskman.ITask) {
  6833. guest.RealDelete(ctx, userCred)
  6834. guest.RemoveAllMetadata(ctx, userCred)
  6835. db.OpsLog.LogEvent(guest, db.ACT_DELOCATE, guest.GetShortDesc(ctx), userCred)
  6836. logclient.AddActionLogWithStartable(task, guest, logclient.ACT_DELOCATE, nil, userCred, true)
  6837. if !guest.IsSystem {
  6838. guest.EventNotify(ctx, userCred, notifyclient.ActionDelete)
  6839. }
  6840. HostManager.ClearSchedDescCache(guest.HostId)
  6841. }
  6842. func (guest *SGuest) FinalizeDeleteTask(ctx context.Context, userCred mcclient.TokenCredential, task taskman.ITask, data jsonutils.JSONObject) {
  6843. if jsonutils.QueryBoolean(data, "real_delete", false) {
  6844. guest.finalizeRealDeleteTask(ctx, userCred, task)
  6845. } else {
  6846. guest.finalizeFakeDeleteTask(ctx, userCred, task)
  6847. }
  6848. }
  6849. func (guest *SGuest) StartBaseDeleteTask(ctx context.Context, t taskman.ITask) error {
  6850. task, err := taskman.TaskManager.NewTask(ctx, "BaseGuestDeleteTask", guest, t.GetUserCred(), t.GetParams(), t.GetTaskId(), "", nil)
  6851. if err != nil {
  6852. return errors.Wrap(err, "StartBaseDeleteTask")
  6853. }
  6854. err = task.ScheduleRun(nil)
  6855. if err != nil {
  6856. return errors.Wrap(err, "ScheduleRun")
  6857. }
  6858. return nil
  6859. }