3lddlZddlZddlZddlmZmZddlZddlmZmZmZm Z m Z m Z ddl m Z mZddlmZddlmZddlmZmZddlmZdd lmZdd lmZdd lmZmZdd lm Z m!Z!dd l"m#Z#dZ$gdZ%gdZ&eZ'Gdde'Z(Gdde'Z)Gdde*Z+Gdde,Z-GddeZ.dS)N)datetime timedelta)ColumnFloatIntegerStringfuncinsert) DatabaseErrorSQLAlchemyError)declarative_base) sessionmaker)LveStatsPluginLveStatsPluginTerminated) uidconverter)gm_datetime_to_unixtimestamp) get_chunks)fix_lost_keep_alivevalidate_database)history history_x60) history_govz/var/lve/v1_migration_last.ts)idmem mem_limit mem_faultmemphylmemphy memphy_faultmep mep_limit mep_faultnproclnproc nproc_faultiopsliops)usernamesum_cpu sum_writesum_readlimit_cpu_on_period_endlimit_read_on_period_endlimit_write_on_period_endcause_of_restrictcNeZdZdZdZededZededdZ ede Z ed e Z ed e Z ed eZed eZed eZedeZededdZedeZdS) V1HistoryGovz* Mapping out v1 gov history table rtsT primary_keyr(@r)r*r+r,r-r.r/ server_id weightN)__name__ __module__ __qualname____doc__ __tablename__rrr2rr(rr)r*r+r,r-r.r/r6r8/builddir/build/BUILDROOT/lve-stats-4.3.2-1.el9.x86_64/opt/cloudlinux/venv/lib/python3.11/site-packages/lvestats/plugins/other/v1_db_migrator.pyr1r1<s"M g4 0 0 0Bvj&&**$???HfY&&G{E**Ivj%((H$f%>HH%v&@'JJ &'BG L L2G<<{FF2JJDAAAI VHg & &FFFr?r1ceZdZdZdZededZedeZedeZ edeZ ed eZ ed eZ ed eZ ed eZed eZedeZedeZedeZedeZedeZedeZedeZedejjdZedeZededZedeZedeZedeZ edeZ!edeZ"edeZ#edeZ$ed eZ%ed!eZ&ed"eZ'ed#eZ(d$S)% V1Historyz& Mapping out v1 history table rrTr3cpu cpu_limitcpu_maxncpur r!mep_maxioio_maxio_limitrrmem_maxrr"createdr8r6r7rr memphy_maxrr$r# nproc_maxr%r&iops_maxr'N))r9r:r;r<r=rrrrCrDrErFr r!rGrHrIrJrrrKrr" sqlalchemytypesDateTimerLr8rr6rrrMrr$r#rNr%r&rOr'r>r?r@rBrBPs5M g4 0 0 0B & C{G,,IfY((G 6&' " "D & C{G,,IfY((G g  B VHg & &Fvj'**H & C{G,,IfY((G{G,,I{G,,IfY 0 9tLLLG VHg & &F{FF2JJ//IfY((G VHg & &F g..J6.'22L VHg & &F F7G $ $E{G,,I&00K 6&' " "Dvj'**H F7G $ $EEEr?rBceZdZdZedfdZddZedZdZ ddZ dd Z d Z d Z d Zd ZdZdZdZdZdZdZdS)V1TimeIntervala The way it would work - on first run, the /var/lve/v1_migration_last.ts will be non-existant, and we will use latest timestamp from V1 db as the 'starting point' After that on each call of get_data we will use that 'starting point' to get_period from start point to 1 hour before. As soon as our start point is > 30 days old -- we will return as part of get_period third parameter true which means that ok, the rest of data is too old, lets move on. V1DBMigrator will convert data for that period, and then will call save_state(from) -- this will be new starting point for the next plugin run. We will store it in a property (last_ts), and save it to the file. So, that even if software restarted, we don't just ignore it. localhostct||_||_d|_d|_||_|dS)N)ts_filer6last_tslast_uid v1session read_state)selfr[rXr6s r@__init__zV1TimeInterval.__init__s; "  " r?Ncpt|jdd5}|||||_|.|dt |z|pd|_|ddddS#1swxYwYdS)Nwutf-8encoding rW) openrXwritestrftime get_ts_formatrYstrrZclose)r]r2uidfs r@save_ts_to_filezV1TimeInterval.save_ts_to_files $,g 6 6 6 ! GGBKK 2 2 4 455 6 6 6DLs3xx((( # r GGIII                   sBB++B/2B/cdS)Nz%Y-%m-%d %H:%M:%S.%fr>r>r?r@rhzV1TimeInterval.get_ts_formats%%r?c0||dSN) _save_state)r]r2s r@save_timestampzV1TimeInterval.save_timestamps r?c<||j|dSrp)rqrY)r]rks r@save_uidzV1TimeInterval.save_uids  s+++++r?c |||dS#t$r@}tjddt |Yd}~dSd}~wwxYw)N plugin.V1DBMigrator.TimeIntervalz!Unable to save v1 migration TS %s)rmIOErrorlogging getLoggererrorri)r]r2rkes r@rqzV1TimeInterval._save_states u  S ) ) ) ) ) u u u  @ A A G GHkmpqrmsms t t t t t t t t t us A$5AA$c"d} t|jdd5}tj||}t|pd}||fcdddS#1swxYwYdS#t$r|dfcYSt$r<}tj d d|j||dfcYd}~Sd}~wwxYw)NrrarbrWrvzUnable to read %s (%s)) rerXrstrptimereadlinerstriprhintrw ValueErrorrxrywarning)r]r2rlrkr{s r@ _read_statezV1TimeInterval._read_statesg  dlC'::: a&qzz||':':'<'P>P>R>RSS!**,,--//52663w                     r6MMM     @ A A I I(     r6MMMMMM  sGB9BB, B9,B00B93B04B99D D1D D Dc|\|_|_|j|jt jtj tj |j k }|dptddd}|tdz|_dSdS)Nr microseconds)rrYrZr[queryr maxrBrLfilterr6firstrr)r]reslast_ts_from_dbs r@r\zV1TimeInterval.read_states&*&6&6&8&8# dm < $$TXi.?%@%@AA +t~=>>uuww  "!f9Aq(9(9O*YA-F-F-FFDLLL r?cZ||jtdz S)Nrr)r\rYrr]s r@_to_tszV1TimeInterval._to_tss* |iQ77777r?cvtjtdz |kS)N)days)rnowrrrs r@ is_too_oldzV1TimeInterval.is_too_olds+|~~ r 2 2 22T[[]]BBr?c8||jSrp)r\rZrs r@get_uidzV1TimeInterval.get_uids }r?cdSrpr>)r]r(s r@convert_username_to_uidz&V1TimeInterval.convert_username_to_uids r?c|\}}t|}t|}|jttj||tj|jk tj  tj }d|DS)Ncg|] }|j Sr>)r(.0items r@ z9V1TimeInterval._get_history_gov_users..s555$ 555r?) get_periodrr[rr1rr2betweenr6distinctr(group_by)r]from_tsto_tsfrom_ts_to_ts_ usernames_s r@_get_history_gov_usersz%V1TimeInterval._get_history_gov_userss**/88-e44 N  . . VLO++Hf==|?UY]Yg?g h h Xl+ , , Xl+ , ,  65*5555r?c|\}}|jttj||tj|jktj|j k tj tj}d|DS)Ncg|] }|j Sr>)rrs r@rz4V1TimeInterval._get_history_uids..s***D***r?) rr[rrBrrLrr6rrZrr)r]rruids_s r@_get_history_uidsz V1TimeInterval._get_history_uidss** N  + + V!))'599#t~5 t}, Xil # # Xil # # +*E****r?c|}|D]=}||}|$||jkr||vr||>t |Srp)rrrrZappendsorted)r] uids_listr(rks r@get_uidszV1TimeInterval.get_uidss**,, 3355 & &H..x88C3#6#63i;O;O  %%%i   r?cb|}|jtdz }||fS)zEWe want to go 1 hour at a time, up to 1 month back, starting from nowr)hours)rrYr)r]rrs r@rzV1TimeInterval.get_periods0 ,!3!3!33~r?rp)r9r:r;r< STATE_FILEr^rm staticmethodrhrrrtrqrr\rrrrrrrrr>r?r@rTrTws?  +5 &&\&,,,,uuuu " G G G888CCC    6 6 6 + + +!!!r?rTceZdZdS)BreakN)r9r:r;r>r?r@rrsDr?rc eZdZdZdZdZdZdZdZdZ dZ dZ dZ dZ dZd Zd Zefd Zd Zd ZdZdZdZdZdZdZdZdZdZedZedZ edZ!edZ"dZ#dZ$dZ%dZ&dZ'dS) V1DBMigratorz./usr/share/lve-stats/plugins/v1_db_migrator.pyF<i%NTrUctjd|_i|_g|_d|_d|_|jd|jdz|_ d|_ d|_ d|_ dS)Nzplugin.V1DBMigratorrrzV1 Migration Startedg?TF) rxrylog_username_to_uid_cache_no_such_uid_cache_procsrinfotimeout _time_commit control_time_conn_database_does_not_existrs r@r^zV1DBMigrator.__init__ st$%:;;&(#"$   ,--- L3.  (-%%%r?c,|dd|_|dd|_|d|_|dddv|_|dS)N v1_server_idrUr6v1_connect_stringdebugF)tytrueyesr)getr v2_server_idrlowerr init_v1_db)r]configs r@ set_configzV1DBMigrator.set_configs"JJ~{CC"JJ{K@@!',?!@!@ZZ--33559UU  r?c|j d|_dSd}|j|rbtj|jt |ds)|jd|jd|_dS tj |j|j }nF#t$r9}|jt|d|_Yd}~dSd}~wwxYw|j|t"js4|jdt"j|jd|_dSt'|dt(}|ds|dr#|jd d|_dSt+| |_t/|||j|_|j|j_dS) NTz sqlite:///zDatabase "%s" does not exist)echoz*Table "%s" in database "%s" does not exist) hide_loggingbase column_error table_errorz)V1 database malformed, migration skipped.bind)rr startswithospathexistslenrrrPengine create_enginerr ridialect has_tablerBr=rV1Baser V1SessionrTget_v1_sessionr time_intervalr)r]r2sqlite v1_db_enginer{results r@rzV1DBMigrator.init_v1_dbs  ! ),0D ) F  ! , ,V 4 4 RW^^DLbcfgmcncncocoLp=q=q  H  ;T=S T T T,0D ) F %,::4;QX\Xb:ccLL    H  SVV $ $ $,0D ) FFFFF  #--lI|dd|_|jrdS|js|jrD|jd|| dS| dS)NprocsrzV1 Migration Done) rris_donerrrrrcleanupfix_lost_keep_alive_records convert_all)r]lve_datas r@executezV1DBMigrator.executeEsll7A.. <  F  ( D,>,I,I,K,K  H  0 1 1 1 LLNNN  , , . . . . .        r?ct|j}t||j|j|dS)Nr)r6log_)rrrrrrj)r]sessions r@rz(V1DBMigrator.fix_lost_keep_alive_recordsPsG0,DK00022Gt/@txPPPP r?cd|_ tjtjtjtjdznQ#t t f$r=}|jdtjt|Yd}~nd}~wwxYwt|j } | ttj|jk|dS#t&$r|YdSwxYw)z There is not much to do on clean up. Lets just set flag done = True, and remove plugin so that on next restart it would't be running any more :return: TczUnable to remove %s: %sNr)rrremoverPLUGIN_LOCATIONrwOSErrorrrzrirrrrrr6rdeletecommitr rollback)r]r{rs r@rzV1DBMigrator.cleanupUs>   \ Il2 3 3 3 Il2S8 9 9 9 9! \ \ \ HNN4l6RTWXYTZTZ [ [ [ [ [ [ [ [ \0,DK00022  MM+ & & - -k.CtGX.X Y Y ` ` b b b NN                  s*?A B3BB8A&D EEcbt|}t|}|ttj||tj|ktj|j k Srp) rrrr1rr2rr(r6rall)r]rrr(rrs r@get_v1_gov_datazV1DBMigrator.get_v1_gov_datais/88-e44    ! ! U< V''&99%1&$*;; SUU r?c`|ttj||tj|jktj|k tj Srp) rrrBrrLrr6rrorder_byr)r]rrrks r@ get_v1_datazV1DBMigrator.get_v1_datawsz    ! ! U9   V!))'599#t'88 # Xil # # SUU r?c||} g}||||D]2}|||j}||3|r?t |D]/} |jtt| 0g} |rJ|dkrD| |||D],}| |} | | -| r?t | D]1} |jtt| 0dSdS#ttf$rP} ||jdt%| |js| Yd} ~ dSd} ~ wt($rB} ||jdt/| d} ~ wwxYw)Nrootz!Can not save data to database: %szPlugin is terminated.)convert_uid_to_usernamer  convert_rowrextendrrrr rrconvert_gov_rowrr r rrrri skip_on_errorrrrr) r]rrrktransr(v2_rows_insert_listrowv2_rowschunkv2_gov_rows_insert_list v2_gov_rowsr{s r@ _convert_datazV1DBMigrator._convert_datas9//44 !"$ ''<< 4 4**3 <<#**73333" ?'(;<<??EJ&&vg>>>>&( # @H..//II@@C"&"6"6s";";K+22;????& C'(?@@CCEJ&&vk':':EBBBB C CCC/    NN    H  @#a&& I I I%       ' ! ! ! LLNNN HNN2 3 3 3''q  !s%DD77G"AF G" =GG"c8tj|jz Srp)timerrs r@ _work_timezV1DBMigrator._work_timesy{{TX%%r?cR|j|z |jdzkS)Ng333333?)rrrrs r@ _need_breakzV1DBMigrator._need_breaks&|doo///$2Cc2IIIr?c ^|jd|||j}|sdS|j}|D]}||||||j||jd|||||j rO| r;|jd|t|j r| dSdS)NzStart converting from %s to %sz4Converted from %s to %s uid: %s; plugin work time %sz$Stop converting; plugin work time %s)rrrrrbeginrrtrrrr is_activer)r]rruidsrrks r@ convert_datazV1DBMigrator.convert_datas9 7%HHH!**,,  F   ""  C   wsE : : :   ' ' , , , HNNF!!      T%5%5%7%7 :OO%%gg ?  LLNNNNN  r?c|j5|_ |s|jsy|j\}}||||j||s|jyn#t$rYnwxYwtj }dddn #1swxYwYtj |z }t|j ||_ |j d|dS)NzCommit time %s)rrrrrrrr"rrrrrrrr)r]rr time_start commit_times r@rzV1DBMigrator.convert_alls| [    %DJ **,,?T5G5R5R5T5T?%)%7%B%B%D%DNGU%%gu555&55g>>>**,,?T5G5R5R5T5T?    J % % % % % % % % % % % % % % %ikkJ.  1;?? '55555s5C7B&CC7 CC7CC77C;>C;c||krdSdS)Nrrr>)limit_maxs r@ fault_countzV1DBMigrator.fault_counts D==11r?cVt|j|j|d<dS)N iops_fault)rr)r'rOv1_rowv2_rows r@convert_iops_faultsz V1DBMigrator.convert_iops_faultss( ,77 foVV|r?c|jdz|d<|jdz|d<t|j|j|d<dS)NirHrJio_fault)rHrJrr)rIr,s r@ convert_iozV1DBMigrator.convert_iosIy4't #_t3z)55fov}UUzr?ctd|z|z|dzdz}t|||zdz}t|d|z|z}|||fS)a v1 holds CPU relative to total cores, where on 4 core system 1 core is 25% it also limits by ncpu (whatever is less), so on 4 cores system 2 ncpu and 30% is 30% of all cores (as 2ncpu = 50%, and we take smaller), and 2 ncpu and 70% is 50%, as 2ncpu = 50% / we take smaller To switch to new limit, we need to talke old limit and multiply it by 100 So 25% on 4 core system in v1 (1 core), is 25 * 4 * 100 = 10,000 d)minrr))rrCrDrErF v2_cpu_limitv2_cpu v2_cpu_faultss r@ convert_cpu_zV1DBMigrator.convert_cpu_sj3?U2D3J4DEE \3;#455%00sW}u?TUU |]22r?cz|||j|j|j|j\|d<|d<|d<dS)NrCrD cpu_fault)r9rCrDrErF)r]rr.rs r@ convert_cpuzV1DBMigrator.convert_cpusGBFBSBS 37CM3;C C ?u vk*F;,?,?,?r?c||jvr |j|Stj|}||j|<||jd||S)NzCan not find uid for user %s)rrusername_to_uid_localrr)r]r(rks r@rz$V1DBMigrator.convert_username_to_uids^ t2 2 2.x8 80::03#H- ; H  ;X F F F r?c||jvrdS|jD]\}}||kr|cStj|}|6|j||jd|n ||j|<|S)Nz!Can not find user name for uid %s)rritemsruid_to_username_localrrr)r]rk username_uid_s r@r z$V1DBMigrator.convert_uid_to_usernames $) ) ) F#:@@BB ! !OItd{{     6s;;    # * *3 / / / H  @# F F F F58D ' 2r?c*|j}g}td|jD]s}|j|d|zz d}tD]}t ||||<||d}|r||d<||t|S)Nrr)r6r2r(rk) r2ranger8r V2_GOV_KEYSgetattrrpopr)r]rrri v2_gov_rowkeyrks r@rzV1DBMigrator.convert_gov_rowsq#*%% * *A'+'8QOOJ" 4 4")#s"3"3 3..z~~j/I/IJJC *$' 5! j))) r?clt|j}g}td|jD]}|j|d|zz d}t D]}t ||||<|||||||| ||| ||S)Nrr)r6rL) rrLrEr8rV2_KEYSrGr<r2r/r)r]rrrrrIr.rKs r@r zV1DBMigrator.convert_rows,S[99q#*%% " "A#'#4aPPF 0 0%c3//s   S&% 0 0 0 OOC ( ( (  $ $S& 1 1 1 MM& ! ! ! ! r?)(r9r:r;rrrperiodorderrrrrrrrr^rrrrrrrrr rrrr"rrr)r/r2r9r<rr rr r>r?r@rrsFOGG F EIM EMLL . . .'$R$R$R$RL       (        !!!:&&&JJJ6 6 6 6\ WW\WVV\V 33\3"              r?r)/rxrrrrrPrrrrr r sqlalchemy.excr r sqlalchemy.ext.declarativer sqlalchemy.ormrlvestats.core.pluginrr lvestats.librlvestats.lib.commons.dateutilrlvestats.lib.commons.funcrlvestats.lib.dbenginerrlvestats.orm.historyrrlvestats.orm.history_govrrrMrFrr1rBobjectrT Exceptionrrr>r?r@r\si ((((((((CCCCCCCCCCCCCCCC99999999777777''''''IIIIIIII%%%%%%FFFFFF000000HHHHHHHH55555555000000 ,    $        '''''6'''($%$%$%$%$%$%$%$%N}}}}}V}}}@     I   nnnnn>nnnnnr?