Revision $Id: webjob-manage-config-files.base,v 1.14 2006/03/10 15:20:35 klm Exp $ Purpose This recipe demonstrates a solution for centrally managing system config files and rc scripts across multiple WebJob clients. This solution will be referred to as the config_manager approach. Motivation Generally speaking, ad hoc administration practices lead to system drift, and that is bad. When you manage large server populations, drift seems to be unavoidable -- even if all systems originate from a common image/build. Also, the problem tends to get worse over time and as the population grows. Why would you want to use this solution instead of rsync or any other file distribution/synchronizing solution? The answer to that may well be: "You wouldn't." For me, the answer was (and still is) not that simple. I wanted something that would approach the efficiency of rsync for small to medium size files, but with some added features. In particular, I was looking for a solution that would record the difference between actual and target files. Having this information could potentially help me determine why drift was occurring and, more importantly, if it was negatively impacting the systems. I also wanted a solution that would: - automatically update or restore files that have drifted - minimize the amount of effort required to manage a given target file across multiple systems where all, or a large number, of those systems were expected to have identical file content - minimize the amount of effort required to add new files, clients, and groups - allow for customized file content on a per client/group basis Requirements Cooking with this recipe requires an operational WebJob server. If you do not have one of those, refer to the instructions provided in the README.INSTALL file that comes with the source distribution. The latest source distribution is available here: http://sourceforge.net/project/showfiles.php?group_id=40788 The server must be running UNIX and have basic system utilities, Apache, PaD tools, and WebJob (1.5.0 or higher) installed. PaD tools are included in the WebJob distribution. Each client must be running UNIX and have basic system utilities and WebJob (1.5.0 or higher) installed. Actually, this recipe was tested on Linux systems, so there may be some porting issues to deal with on other UNIX platforms. This recipe assumes that you have read and implemented the hourly script from the following recipe: http://webjob.sourceforge.net/Files/Recipes/webjob-run-periodic.txt Time to Implement Assuming that you have satisfied all the requirements/prerequisites, this recipe should take less than one hour to implement. Plan on 1-3 hours for testing. Solution The solution is to install the attached config_manager project, populate it with the files that you want to manage, build and install the necessary PaD files and manager scripts, create a custom config file (nph-webjob.cfg) to handle uploaded data, and test the implementation out on a small set of clients. If all goes well, you can begin managing files in a limited production environment with a goal of migrating to a full production environment at some point down the road. The following steps describe how to implement this solution. 1. Set WEBJOB_BASE_DIR as appropriate for your server. Then, extract config_manager.tgz.uu from this recipe (Appendix 1), uudecode it, and unpack its contents in a suitable location. # WEBJOB_BASE_DIR=/var/webjob # sed -e '1,/^--- config_manager.tgz.uu ---$/d; /^--- config_manager.tgz.uu ---$/,$d' webjob-manage-config-files.txt > config_manager.tgz.uu # uudecode config_manager.tgz.uu # tar -C ${WEBJOB_BASE_DIR} -zxf config_manager.tgz If you don't have uudecode on your system, try the following: # perl -ne 'next if (/^begin/); last if (/^end/); chomp; print unpack("u",$_);' < config_manager.tgz.uu > config_manager.tgz At this point, you should have a tree that looks like this: config_manager config_manager/Makefile config_manager/Mk config_manager/Mk.config_manager.base config_manager/Mk.files.base config_manager/Mk.groups config_manager/Mk.subdirs config_manager/Mk/common-file.mk.base config_manager/Mk/common-macros.mk config_manager/Mk/common-pad.mk config_manager/Mk/common.mk config_manager/MkScripts config_manager/MkScripts/mode2perms config_manager/MkScripts/pad_make_kvp config_manager/MkScripts/pad_make_manager config_manager/README Change to the config_manager directory and read the README. This file contains additional information about the project and tools. # cd config_manager # less README 2. Edit ${WEBJOB_BASE_DIR}/config_manager/Mk/common-macros.mk and check/set the following variables as appropriate for your environment: PAD_MAKE_SCRIPT=/usr/local/webjob/bin/pad-make-script WEBJOB=/usr/local/webjob/bin/webjob PROJECT_DEFAULT_INSTALL_ROOT=/var/webjob # vi ${WEBJOB_BASE_DIR}/config_manager/Mk/common-macros.mk 3. Pick a file to manage and add it to your project. This recipe assumes that you want to manage a fictitious file called rc.sample. Modify TARGET_FILE and TARGET_DIR as desired before executing the following command. # make create-file TARGET_FILE=rc.sample TARGET_DIR=/etc/rc.d Note: If you already have a sub-directory with the same name as your new TARGET_FILE (e.g, rc.sample), you'll need to alter the above command so that it contains an alias. The new command would look like this: # make create-file TARGET_FILE=rc.sample TARGET_DIR=/etc/rc.d TARGET_ALIAS=rc.sample.2 At this point, a new sub-directory (rc.sample or rc.sample.2) has been created, and you should see output similar to the following: --- make-create-file-output --- >>>> create-file (rc.sample) Tasks that remain: cp ... targets/rc.sample/ vi Mk.groups (update existing or define new groups -- if required) vi targets/rc.sample/Mk.files (define file-to-client/group mappings -- required) vi targets/rc.sample/Makefile (modify default attributes -- if required) make clean all (check output) make install --- make-create-file-output --- Perform the tasks listed in the output above. Take note of the following information as you go. a. While it is possible to use multiple source files, this recipe assumes that all clients will use a single source file called (f_test) -- the content of which is provided here: --- targets/rc.sample/f_test --- #!/bin/sh echo "This is a test of the emergency broadcast system." --- targets/rc.sample/f_test --- Put this content in place with: # echo '#\!/bin/sh' > targets/rc.sample/f_test # echo 'echo "This is a test of the emergency broadcast system."' >> targets/rc.sample/f_test b. Read the information provided in Mk.groups. Pay special attention to the syntax rules and notes. Then, define one group variable, g_test, and assign a small subset (no more than three) of your clients to it. This recipe assumes that you have used a total of three clients: client_host[1-3]. Once your edits are complete, Mk.groups should have an entry that looks like this: --- Mk.groups --- g_test="client_host1,client_host2,client_host3" --- Mk.groups --- c. Read the information provided in targets/rc.sample/Mk.files. Pay special attention to the syntax rules and notes. Then, define one file variable, f_test, and assign it a value of $g_test. Once your edits are complete, Mk.files should have an entry that looks like this: --- targets/rc.sample/Mk.files --- f_test="$g_test" --- targets/rc.sample/Mk.files --- d. It is not necessary to modify targets/rc.sample/Makefile for this recipe. Just be aware that you can. This file defines the following attributes, which can be tuned as needed for your environment: TARGET_DIR=/etc/rc.d TARGET_MODE=0755 TARGET_UID=0 TARGET_GID=0 TARGET_HASH_TYPE=md5 e. At this point, running 'make clean all' should yield the following output: # make clean all >>>> pads ===> targets/rc.sample ---> client_host1=f_test ---> client_host2=f_test ---> client_host3=f_test >>>> managers ---> client_host1 ---> client_host2 ---> client_host3 and running 'find profiles' should yield: # find profiles profiles profiles/client_host1 profiles/client_host1/commands profiles/client_host1/commands/rc.sample.pad profiles/client_host1/commands/config_manager profiles/client_host2 profiles/client_host2/commands profiles/client_host2/commands/rc.sample.pad profiles/client_host2/commands/config_manager profiles/client_host3 profiles/client_host3/commands profiles/client_host3/commands/rc.sample.pad profiles/client_host3/commands/config_manager Review the scripts, and get familiar with their content and structure. Note: You could have run 'make all' or 'make managers' instead of 'make clean all', but the clean target ensures a fresh build. f. To install these scripts in your production profiles tree, run the following command: # make install Note: This will produce a file called _install_manifest. As long as this file exists (assuming it has not been altered), you can back out the previous install with: # make deinstall 4. Next, you need to create a custom nph-webjob.cfg file to control the way config_manager data will be stored as it is uploaded to the server. If this file already exists, you'll need to manually edit it and set OverwriteExistingFiles and PutNameFormat to the values shown below. This config file is used to override default CGI behavior. Refer to the comments associated with ConfigSearchOrder in nph-webjob.cgi to get all the details. # mkdir -p ${WEBJOB_BASE_DIR}/config/nph-webjob/commands/config_manager # vi ${WEBJOB_BASE_DIR}/config/nph-webjob/commands/config_manager/nph-webjob.cfg At this point, your custom nph-webjob.cfg file should look like this: --- nph-webjob.cfg --- OverwriteExistingFiles=N PutNameFormat=custom/%cmd/%Y-%m-%d/%H/%cid_%Y-%m-%d_%H.%M.%S.%pid --- nph-webjob.cfg --- Note: This step is optional. Its purpose is to collate data by command rather than client ID, and that may make viewing and processing the data easier. Another benefit of changing PutNameFormat is that you can impose a limit on the number of uploads that will be preserved. For example, the following configuration produces a single upload directory that holds one upload per client per hour (or 24 uploads per client). --- nph-webjob.cfg --- OverwriteExistingFiles=Y PutNameFormat=custom/%cmd/%cid_%H --- nph-webjob.cfg --- 5. Test the manager scripts on a small group of clients. To do this, edit the hourly script and add the hostnames of each client to MY_GROUP1 (or any available group). # vi ${WEBJOB_BASE_DIR}/profiles/common/commands/hourly Note: Group variables are defined in GetHostGroups(). Assuming your clients are named host1, host2, and host3, your group variable would look like this: MY_GROUP1="host1 host2 host3" Next, insert the following job under the appropriate group case statement in Run01HourJobs(): ${WEBJOB_HOME}/bin/webjob -e -f ${WEBJOB_HOME}/etc/upload.cfg config_manager -m update -n The group case statement should look similar to the one shown here: --- snip --- for GROUP in `GetHostGroups` ; do case "${GROUP}" in MY_GROUP1) : # REPLACE WITH ONE OR MORE MY_GROUP1 JOBS ${WEBJOB_HOME}/bin/webjob -e -f ${WEBJOB_HOME}/etc/upload.cfg config_manager -m update -n ;; MY_GROUP2) : # REPLACE WITH ONE OR MORE MY_GROUP2 JOBS ;; done --- snip --- Note: The '-n' option causes the config_manager to perform a dry run -- i.e., no changes will be made, and diffs of what would have changed will be uploaded to the WebJob server. If the actual file does not exist on the client, /dev/null will be used to calculate the diff. Otherwise, the actual file is used. Once the dry run is complete, inspect the WebJob output to see what diffs it produced. The expected result is no change to any client. Also, you should have diffs for each client in the uploaded data. Since rc.sample was not present on the clients, the diffs should have all been calculated against /dev/null. Next, remove the '-n' option in your hourly script, sit back and wait for the next job to run. This time, the expected result is that rc.sample will be deployed to each client -- again with diffs uploaded to the WebJob server. Finally, make an unsolicited change to rc.sample on one of the clients. At the next hourly invocation, rc.sample on that client should get updated, and a diff of the change will be uploaded to the WebJob server. No other clients should be affected, nor should they return any diff output. 6. Once you're satisfied that the process is working, you can start to scale up the number of clients and files being managed. Over time, you can migrate from a limited to a full production environment. Closing Remarks The config_manager approach is experimental. It should not be used to manage critical files without adequate, backups, planning, and testing. For improved control, use CVS to manage the files in your project. There is a README in config_manager.tgz that provides quick start commands and describes several common work-flows -- both sections include relevant CVS commands and documentation. The solution described in this recipe does not have the ability to restart daemons or send signals. The solution described in this recipe can be used to manage binary files, but the config_manager was designed specifically for text-based files since they are easier to edit, diff, and track. Both Mk.groups and Mk.files work on an opt-in basis. In other words, there is no convenient way to manage a particular file on all hosts without active involvement. You must add the appropriate client IDs to Mk.groups/Mk.files before any new systems will be able to participate. With that said, it is possible to define a group variable that includes all clients. However, you must manage this variable as clients come and go. If back-end alerting/reporting is desired/needed, a cron- or daemon-based script could be written to process any data that shows up in the incoming directory. If event-driven back-end alerting/reporting is desired/needed, server-side PUT triggers can be used to launch a command as soon as the client's upload is complete. Note, however, that GET/PUT triggers require nph-webjob.cgi 1.40 or higher. For example, suppose that you want to receive an email containing the uploaded diff(s) each time managed files drift from their official content. In this case, you could define the following PUT trigger: PutTriggerCommandLine=if test -s %out ; then mail -s "Config Manager Report -- Files have drifted on %cid." you@yourhost < %out ; fi The as-deployed file on a given client can be recovered by patching the target file living in your config_manager tree. This is done by applying the uploaded diff to the target file like so: # patch --reverse Credits This recipe was brought to you by Klayton Monroe. References Appendix 1 --- config_manager.tgz.uu --- begin 644 config_manager.tgz M'XL(`*3S%D0``^P]:WO;ML[[&O\*3O46I_4]<;(Y<=8L]ZVY/+F<;6^3.8I$ MVSJQ)4^7I%GJ__X"("51%^=RYG;G.:OZM)8H$@1`$`!!4#46%I*_,KKJP;4:;56&LM8WFBVFJVO6.N38).Z`L_7 M7<:^NAF.GJC'7>]S(/1Y+R,Y_@ M->35T4WU6O?X7^RCWJC7EU/CKH[_TM)R:OR76_##ZC.A\(GK'S[^A>.3HY^V M-\^Z)T='9YUJM5:M%@IG&R>[VV?=G?UWVYVWP)X^][LH#V^C5UO[)]$;TW+C M%QOO]C=.HU?ZT-*]^.7!T58,<.28"L#S_:WH36"9\8M=Y45??;&W<;K7/?OM M.(8XT+U!U[\?(]C]P\UWYUO;I]WCD^V=_5\[Q0>5T`D(>J%@V<8P,#DK/J1J M3\)),-9-F`.%PM\]2I_NFCK_1[KA.AY0_]?[>&+^-QNMQ?3\;ZRTOLS_SW&] MFLE5@#^L>,(-:\SWS39+RU#YEC6JBZP)".'8^WV2:AP@[T&XXJC$F<9M=;8?/H<&=_MWNP<;BQNWW22%:8]^KH6ILCKD[@@;'&UM=!-'] M^5_'CS0!3=7%3KHWMV.ET<'NR7,:1^QWJ.RX[U+4:*?Y:.@+)LZFZ^VP=M MBD9>*9U4C:'%;=^+ZH)-BZO0VFE2!:ZI[[N;.[MQ'2@`*+U^H:`/AVW6A MUW1L7B@80Z[;[4(A+FNS.\>]`;M3F'N+5%L^'S'+9E=@!A6W8A+K>%8A+7_A MO:G5^JO,ZK%2K5-;8`]CU[)]IEW8VNJ$;1]N)4OF(P@V0M!L_L%G@0W\]4JU MW]__WKE\`U!6&;59U:[8*C.=B\+`UI@ M=<&^[M#R_,>J-V5U0/\]/()U"^T9]01&[1(P\`? M-Y$UY1H#SLS'),S-"0L:&D[1;-+)]+DJ:L-P*&Z(=$S(;LN6I(%UV_3"%D3& MUT`;@B=7)('^W-P(QQA'+WPO&_:L\$X9<.'935C%8"D4V7H(H):0MQ"(LLSN M7'F#*96+#\(;A!X&K.*SZ&VT8)^P;\;Z_=#13=9<9S63W];L8#B\2M!;^1.= M$G7R:*SB)(N1<=E2=+%SBL_WMW)*=W-+8U3C=Q&OD/ZT"(5"P/#:=EW'[DJIRDL)Q+3SDQUN7$&)=SQK:<&=/\"8`:.#NG4,&*VVBP\MEWD58_ M%QK9'G:G>RP4#%`\!S=5,DEE!IP%73WOL9'E>9;=9SW7&>%`,<"-&[[CWJ=X MK3!:(BAL@M3_;3``L9+(*)]GA,+^Q\-@_]AKFO\_*]\?KZ?B_ZWEI93_O[32 M6/GB_W^.:T:^;Z[_'_K^]`?]_U:M_EVMNBLABH7^=ZG1]/R7G)II'X_/_\9*8S&]_[?46&E^F?^?XYK1!$C-_U",:/HW ME^*U_PIK?-]>:K67EC_%W$]M9CYO%S`,W^^>='_<.-W.J5--3A+:$A=Q?5KJ M3VF5MY$.K7XF9_=T:E]"-8G*\%)4!G_VATY=*=C%@D8BY/!#)WX\>K>U?:(4 M@).G/%&<07E&EQK`K[1:ZG8L=1A[T.ICY$+_T!F94:-3VA46CJY7*`SX<(Q^ M)SG%Z)&&WO&YQWO!D)V)BEKB725Q)=_%%X4^;,<=Z4/PE:VA*9U.Z,@`PF#.7Z[#6T9D1N"Z&"5!E7*,A<7KDEH]=Y]\` M:0H0,PG$A!_S)2`L&W04DBQOV!A6SKIM,BF0@IIL2Y-'+27Q\AFZ?R8(-P;! M/W`#5WR(++%4,AV,ZG#HW`',ZWMZ&6+YV)@PD@X1#X)&L(H<<<\#3'*J2Q2] MMAR[9Z).%X;"U'94ESGV\#[=0`P/S=8VTTWH@MG\3BS4?&?Z$)E\R+&=,S2Y M&S$:N,,_6)Y/BS=Z%:_ALF#@1H;S0EIE2$\-Y77E6DZ\DO-*6X>+J-2@*`P4 M>;B6%#M.7F*-'\W%"'T1I`#^VPX,`V`+M)I.E9VY]\@%+%$8<6?Y@[:F0$C` MPJ&ZX2HGF9I)LF;K([[.8I7461OK_F`]`R]>S,):]A7;V=YO"S0N*-F,`H^C#?CN!ZO`H^,.[-S-;XS,8"'[J!@ M$P7^E`@FQD!?55\7B[7:*DM&,R^\UZ6+TS<+\!N%-'&CJTRAT'FVIC`_CA(6 M']1=0KDWI^PY3N)%^]Q;WPF,02*V*^18+4F*2N)=0C;":IJ,`8?$]BR80ME0 M`*N,X`4?`W\;<*]_B.XQL8:9,44B6MFY0E.%(QN&3JY4H4@%1>50NR.,RG;] MT;@;!\3DV`.*.%$?03$W5%HA%"Y>8_2<572);D\)TXH8LP@27Y0QJ(R(076* MIXBS!<'+><,.![+G62<@6**(]C24J@%CR2 M209,\2'EKU#4]ED\JL5M1:I"0N9RQR26Q91BBG5R^HWB*5IZKZ6 M;2-;TY5WH:RKCYDN$^(N:VHQ16%;:&3UN.?_%\T#TC^N09KRI0)_44K)O".? MLZ-\L9`_([!Z$F^)3!1!-CV?IDV,4U[*19Q&D2]VQ0>$/TG-%PE;3);T(*EU M-=4)PET0()40BGQC&*V^6K1+12,&BTF5*K77<#LF`KLU$["IZ9S4YTFA5KRS M/!E59#JJ&>KP2&`,W<\VCD=885^D>%3JDX4YVB"#5T%Q"(43*!_C4'/*42DD M'I\(1*-9E,Q*`I&K"@$_?@B[2)6D>E&6)VH/&3`)%S#S6KI7S]^7>MSQ.D=O MM_UBCPG066?O$\FVHM9E5$I9MFNX+Z(48G[M6F"92A%FUJ[U$T5Q3NT#+.P^ M>@.],;E\Q-^C*X&,@CXKF;RG!T-_X9D0"'%$(NA1+/"JU(,P#Y%.+)E'UXRM=^`N"N;KQG M:W[\*`:N(6@+4RS([F"6A%>^4`?RXFTY369_5TGZ^X^5C=*YE=;*'NW43N1XAA%XF060V8T MHM"VS"1!PY`(QDVF-),AN:B9LK2.;ZO@THH:#RQT<+("L6LYG7OQ@/IA%YGS?7&?5:C6? M&UH:R*V%J/5=)QA[K!2,,;@5AS[0SZ8-;@HAR%J5"N85N?R/P'*YN9`'\O&1 M*$F8^%3QG8KP.&L$'K-1Q]`U=?,?]!$*20EF@=6[9U*]*XD;3^(O3#HY1^A9 MEHP!-VZ8$_CCP)]2._3O4H,5)A;DAFWB7`"*8Z`=09S`2^,BSE5.9!Z(27^A MH>H$S6K>BU'RJBF,,/#C!K:-PRR=@7C`>@R"8E%9A.S!DF#[A0\]E?#\/0V%S#+PZ,F:'4%+$IV-V M)8]S=LV!O`64Y<#C@A/`2J3<&SAW-L,(VJR)3SI5:]3C=(Z<*2197H@\C.*3 M:"6BEQ%BM'V0,:YI6#T+%S%J]#/?1R9H+_*''\-*,.SO\;8(GT[:B4@1JD2' MY>I-)::4KKZ@.!T)ET,T2/H;84PE4^F9QDE$M"JW(JB5A%$L:NDV"6,$WHSO M!OP)H_2XRDHI*>J8U%2**:BF3(>+>4R3\B^H*0+Y$D7U:"+B@F2^4]7O_ZF%\268 M?"_H@':=.E=DGK4WW_Q6^694^<;4GNX:?Z'1)-7WEX2Q_XTKD_^5M]G]%_MX M(O^CL93)_UA>7OER_N.S7*^^IC-ZWF"6^5=J)DBN0(FTL,2!T$:KW5QL+WWW MJ7+"-IWQO6OU!SXEHE7P'S))O_#KGYQK=BPV9HM/%(>RN[)QH%J:>I7A5DRZ9Q6DCOH+J\)`8(5ZE@WZ5]_ M`#\4X(0G3/V&7_#$.?C-:[0*A%^,'\`/1A#69\C'&*_20N&AP-C!;Y@>+ISY M8D,4X!:>*&B*@BB7'#A?7`3_=">@-`YP680AI34'`$5>5A-M*"A:7$K"$>>' M6XG"HU\.T6E?3A3NGAR='W>**XE"C*)TBM^)LJW]W>W3,Q'0+'X/J)4.MEH? M3_H2D^),F(_=("^DWQRZW]G1U):+I)JB8%(9'?T_/ M-L[.3SN:Z5H]\!PU>(^.YM2NHS,E4[O,U$AW)5/OL2OT[B0GB@];1]WSP_V= M_>TMZF_"*OP/ULAP@W`Y.C[;/SH$8)4@C7+BO>@C+M\\V.IH#^#+]23CU=J3 MQ%A$-"N':E;91!/0#G!7)007C'3OAM6;3:@0!2ZOX%>&>E-C<*7`V3P.@<`: M`Z0AZBHK%DJC/9#=J-T`YFNB.H45GP``,AT#P+6V6IT$?M)6BTC<'P=Z7`E='!UF2DZ99%^1>$VN0H'1Z+T"<*+]RK[NR'*E M'98GA$@L2C8=V\>,,ZJ>E-$)Q7TRM+;9AN$'^G`/%"`N-U/=+V#O(O=.J:$B MLJ!1_[&\;YT`V\X/A:C7DU@2O_:W.E>6&9^1^SVPS,Y%Z7V]\OWEQ4.CW+J8 M7"R4JJ^+M8M&;77^2K94&(2GL'YEP)9ZF@VR"SJ&@^,6SP=XQ(%]$"R(1#T\ M]QY*K?(<"J1:)$5LPA`6E0D)F6BR^VC6?AI,IG5+"B'1^Z-]9T%(`*'X\DB+ MA^9*RFYHK)1'!!+I/2A[=]JY&GJL,K1SU$1RS@C3),]0/E!;#&_K=S=L7AX9 M+38F\_GS0QQHRYD@T8N<&;(1G44CZP"K=Q\<.0HO/#([CND<6RG;NS(_U#H) M1%XX0YZM^^)QBU@O<1/&_7&V+DYCJU"4.6R-7LR,K4?HA279*CI1V*K622#R M8K;F6X27\%7X1X_S=6D:7X6UR>%K]&)F?-VEO8U2MG>%KVJ=!"(OYFO?';,L MF"?X.OE$_K_W2;QWC]SWMV+#BLYXOYTU!1C0GB7N"$\N.DB4\/AG>*_)\#FE MU.#2;,+>5^S@$O[=DR:@,G!&'`N,L,#H]2\QG^E!<&&B)4"&][2#/6/>'.BP MBIP=:V*1QD,**0\=B^"-6$B%GRJBCRH4"G<#^BH$]YTQK/2-2+ M4,VM9(M*"L&-:+=#;K[J]GUXOBUJ%D3-$IQIQ#5>BQI":*-2[NE&0>9F"NV! M+#C$-#C@6_&5JCI$4U2P>8+41,14%"VC6)^*GM&A02?$S`G M->X;-<\WG<"G+V,@"N&(A=P48R8XA)2JZH5H)?I#ZN&9*/\'Q*^S\=_X`-*L M^GCB_&]K<3GS_9_ZXI?SOY_EFI$*SD9]8S%*?_QOA366VZWOVO5/%NO%N"X& M-;SP<-6M[EKZ-497+5OND=.W`&'PF>&X+O?&CDVI`3JY6P!#!&.I.H_.?<4I M%Y@$4N75<@1:=@A:"!]T\%H8Z3E6LAV*]'D+483/J[(CFS-K-'9<7[F4H].4P$(PM4S!GQ$AW0HLR?5(Q&AFW2.!P@`<;9-W379CT[@@N)^ MQ;P!Q]P'?81!1ICOMT`)=`0K&U[M`P4VGOCQO3(;W(]!U<(-*-3J0I7]*^0: M`,GR[1JI]*P^?=:$3GSKN'-JC2ST9M&C0NZ''SQZA4>V:N#BBB2@*ML#?.<] MXFX/3_+Y;1HZQM:PBW7686NB[4<9T7U?SI14J]7+2VIV1^3+IG)8;80;GMT2 M>[_(`9?W@R%,>?YA#&SW@!-AS^\W*O^G5_Z\E+_URO?=R]?T3B)+I[KTT7C( MPR:]KCX<@JGN=RD]&POW):=DS;(\,$=LB#D&:(E&Z'U@%)JIJ^QGNE*Y8^#"159)CE>@Y@$OYHLDE]7&CB>#^_4I["&;9D>M<*; MLJSAV5:OQ]W&RWD-?3^?UXCH,WF-V@9G&3=0A<`[T`Z8&`0(L,"V_@AXF),6 M*PV57#&O$00>2PP_1"5&C@,9%OR5V`I:%C!Y&V0`?B9`QPJ@$,_XYS6ZI7[%^*FV3V"+?>D!=A9@YT MCB**='D8IQ8[)#&J>T)ID1Q3UI<\C`KCE52454P M:JBRWP`N*2EP*J2I$;J<1ATI&?(^L$UH[F@<8*`=-Y9U3'@#2R&%)^R;TM_P MH=(0'=W1V"%K%"(PDPTP%O4T3([1`4;84YG0O\8401A!'+>0%U-`T22\U82-LH3)K]F"4;C'[!P$;!)C2ZW`J64@@\UW=]H1M0,F16:WCH6Z@ MY`!CYBOS,JUKOCOO584D$HX`!'0[YFW*[F/U'])8"S%LAXSHQE,^!()D"GE2 M1>X=AEO(PH'UU>^QULAQ,;-)-XDKR#VN>Q:H0F`0-V$%#0YV@',432GY)/?S MI'@-,$4@/<`)WT))NA?:&1D:J\\A=BB^>B>4(TMHD'*VK!F6@8G,OCV419I" MU`9,6*D58(Z#/K<-=$(P]S&R]Q&ZJJ%0.7/HD-JQN)>P*]=Q'BVH0!Q(&+AK M;NB1[%BH"W#:C_T*`!<>SRSWW86A%D;O'["L>_:57?^)49UE'T]^_WVEF?[^ MR^+BE___X;-?Z';/OJ8;%ZJ25(NDTE.5P(SM^>T35V9EU@%X M+;![6_5L$*H\(R/CSLA,>T@)L]H4ZI*N/G53;4J'PWR>-E6F[HQ.J&Q&7F_: M?*=JE>L[Y3;M\_\[>3+K?_CBZ?,W+U;.@"F+:>G4!'&$U_&23`%Y3,[:`\&-D5O+G!\ M'GJ'W?[#`X$VCY8P&$`R'>/97GR=%>`H,/34*SP.= M9\W$A:'@P,`QD>,"#3&#DUV7EHD$`H$:?#64-I(QVHUT)91A@O=SCD*!WFGL MH8_R$=ILJ$-M+OWLJ6`F-9T^+&[J"!,68IN6D&5@C.860K(![,P(._&=(>#! M/`\O&U#.L5]`GC"^"AG*QNPOYQ.8)YF8],"A&?*DB$I@FB,C%BQ]/:+<0<_> M'C7:2KU*S%FUIAJ+60N:D,Z=ONW>M$5]$0%ZTC^ZAR(!%< MEM+&M)\UMKZXZS8[O2X>S>AN[\"'5%V#=OKJ1Q)B`882I$KP/PIX+CT4*7-/ M2FRLDNVBLNDH[9+]HI+Y<:15BBI`E?]>AH,S=00[*Z$DP9BHR*Y5/"2[%IX4 M+ZY:.$:GP[='134WBX?ZC`G3&[FBRRI?/$BWO(EIT+6VRGJA3,D_1XNSUDL\ M)6E7*>EHF22<'_`0"+D7.[V4K=1H5%ZE"`#J!6A%6$4.Z"@=LV%5*QB>J68L M$9DJ^>&9*I[$TYDLMIFJ^6$65!4'N%.U"/3J*2=9E'KYV14!7U?R[&J96@43 M+*H%^$'?S=13/.3M-+)=O"VGT;G;#)V3K53ZQ;M*T^18VD4Z[H6SV'!>NY9. M&@:4"O=@^8:KT*EW[-XC#9NR30S1A8"Y925WTPYS%3K4BV8`J<7I0-*X! M3)0,2$I`-!@LZDA/-XB^9H9-K2LZ095-DV?FA*$'6[8#E_SR4 M--V#G6:V'`NN/\\NK8K0"T94(>JM1SZ)VB$H-%V;0+XN42W;.8 MMX.'-$Z2^4ZGQF44PC^*0XH"NWNGZE)45 M]@CMTSOXC?D>W#>=QVG3+<8ED!P3&0?'"TF.Y9"LESX(FY-H/J60`1`:I>,; M-\XMMJ:J^E@2,#^ITM'*)0;2/`;MPX\6K<3#TY<+9MGTEX:,3FU#-NLY@(-M MX9?1$H@A+,II]+ZAU!2*"H,X\T@4C:LC4"KF)3"OX6DR*A41^P:I&0 M8J.C4/-%819U^`^$,C:N\M`."Y!#B7J[T0'!.:P117:-O=DH(%7',QDB[0E8 M@Z6*K:4$3.G%A'T4)I_5CE1QFD'I7ES^(P6,WV0HNK8UK%#<%/#'9!G?K!4I MZS0$*,N^$1W45U(7RSV&'RV;*O+V[XB^C\T\(Q"]CD9IU?Y@TIX#.]_,RNL5 M%$\+9?(*YT01PX,6(<9>G(E86%)HO_3DF.O*8ORMF'ZL1EL(/T"Y&/3\<,A( M%>C#85@KC3JONQ2G9>0_'0?FKAXTXPJ&6B!,,\B7Z?H_CX,96@X0-2M:S)"M2&%: MO-6@%8II!#;$H3/B`!L0#48&)<,ER]C+MM+?JCX9!@H/DD?(2I8GXU(FUY MP9<3TD/]TT5T%LRH.Z@4S@81K-!"GW,`C*5%8#BU,6 M05S(ID8I!?ME2%@N^$RIM+1BA]29_)MYV2LQ>K^-G0X/01F$3V7XSF`6P1"M MQ*5+TJX6I"FVZ?DA$M)E*04FVD`]P0?VPZ.*34C'E^6TOE"6HI&-H]Y`C`Z$*%3LDFM>L2>$OIM;9@ M^:R(>Q?D9MXBFUS6P@+57J#9,`FG`0?;$:G05$TD'MG),&8A<$Q,XB!AL[&% M<`3V1I/-CFD,.^UD;+^0V4(30G;:0A0HT$'T]?G"@[8'`5N,HWEBHL-"B>B, MA2Y"@2$@_#\"Y>Z_#$]7*#!9IE,UCT*ZWA6;`$#`(%X#JBTX8AA'C",W$<.B M)RQC1H7@/8G)"!VQ78H%'055QD*9U!2H3IR"`MM98&`P,R^D601+)@^`;+@Q M`M\L!C#%&6I1Y%P94^3=8.R8H#5O560;X+GDS-XP[JP0@5/4D2&$2-=N"Q:\ MJU*NVE35DRJ3A>K;*@>IAC!,#%--%JC>[2INBU86&MAJ^>$(UN\R`/C+60.T M*C>@(/3&"-"70L"F0;J64MT>EH'!0"M.*=^[=,K@:&"X7`B:B!(0XUFE2+U& MT(CXC6A=B.(B7L/"]MBB#LVVE0X/QNUA'"NR,#%CCG;(0/DFYT[.)):43@.% M0,2@(61V@=Y]M%!6I,X(.#["C]=%JTFX4D(1,I+IM4OFA`<7TAC477#V&$+$ MFP<$!(-^,'5$K!DM4ZO;@W\E0\`")]T>_GO;0\JS66*HK;!]-F^.%5-<`-1* MZUO.#K;(!')LB]"D@:/("3/Z.,;9D%-$Z*T"#!BPU#[QD*-H*HB1V/":_`O6 M!BL2@W#PEA&$#7YG+(',`I17/.A9"VN"GZ#$=?1E0!7M\FKJ=+A>FA!7'[?) MFULL$8ST;`(/1@EQU+,L33Q&:=VV<\L!WMIW6JPUWKU%D"P7,XE``\AN=#?: M(A_@!"[PA+@#7$[," M[SUC^X67\AO=YV!">I3DO+"O[0%E^P?SKEYK8&@J/$^!S@K#3 M"%('2#!R:,<#HVB%E+//`]%>C,%^2"L.LA1[5;0X):)_5MDO5!91F#2G(QS5 M#;`5(+_ABOD;3,3;60U6Z)JEV+"*QNN9*G4954)'.X:T`8J(+MJA.)K1"GC` MEGV0=,1&SV<$&(-)27#E_C)%Q=PNDA*E]#L]`4T[0+U:#A#J($&B1H,`THR8 M5TM`@*0V?\.,H6'LG0)-#4&3F[&T8:K9"IM<>)<#,4JQ=JQ(1>E[X1AB]E5P MI?:`$$DCW@.N*4&N&]H2>!H'>9G!<"8&Q.+P_6G`JB-R#&P$,'JBL\V1[EL0 MAV"IE+>EH0EG(I[,L)?P;)Q+:XA!((RH(ILO4H6%PK(QO,=U-QOUTR*7:QZ/3V5\LPT(805?Y"(QQ:YF#RH4_A1:/0MZ26*_MC M-?L"`[WB`G-/SG!SO;W&,E_DA!);#$:]4\[)$2/B`Z"VZPWKX:4S;6V.92NX MR,L<](V>BNCL*H:%F^.9+&%9!]7K@93G/80QZBW\[RL5U/ M\[\1BQ#'>)2'=/S_H`3:V$;'9WI:32@NJ:5'X+I'*K,("MPG%K MA6%JOR/RR<87[)+`GV1"040J,O3G2R.O6'NU[[7AU!!$J;1YD%ID5YHFAJSA MIDWJ:D.39%I'8)CT-6E4A>6X0Q))N2XD#D/"M`DRF#Z=OHP6X0A]2"J&-1ND MYG?C$;K`)!8T>WTM.ZH=%HW^D55(G4,&R$:`"Q3)C4[HBTA$SQP(1T%:AN30 MFPCYX30]VJX+2!W@-HO8OC)%H=:G/"%(YZ!>+`8=@(.VX7*^#U$7"9@AV:8" M7[H`/,$T,KA1XP&PH448\8[5+DN^-QN';8$B/=%=$^?X&?^&SI)?C(WBGML2( ME8-$EDQD`YL.+5<^4F.JZPS4><67)KL%]%W'ZJ,R-QY!;^\*Y1&*+Y1Z:9@& ML82J-E,,F>(!FK,QD.)`M#5&AX)D7:264[6BG)`!!$.^]#4>^8JZRB?OBB_] M8F<\\[P27_SO2>B`"=XDF+W"837,]LE';4WG'U'G'`2PAMB(/2Z"]>G(\;D94,W@\"V-5\H1V=2^)T-P\V M.#/+3E9H4>K!*@.WL;F;LB<1T?.T&QNQB4U6EB][GYZ^R!$;&E>6-MAC+B8. M$G==3AT>7$D=ZE[[K.VUE;33R).+W]D^VK[B-`=)Z=J!:?8*AY#;]FN^-<<6 M1Z02TW.D,>>X]6Y@^4;RQGFB9,7($!T+2YRYO9@(>,J#DL MR"='="H,F_N]Z">'!M)9\*:2/LV6_7=X8#>,Q^D)4VF3+\(H8*0?K]DP1D5* M,$\93MA$OFARFR*#"03U[9M+8<`,*VM^^B[+@J%D9EV`EM:=A+8<*=]],^88 MAHN?;BUMC:'$=&V*>:HZMA817C_/VG(HW5BMYG8OBSEK<\K7I\A?X?Q_+O_' M$3NA.ROLH]O=0O_'9^7_@%]J>X5C*'W^X/D?2MV=[?[.5N]. M[GY\B'<_/OS:=S\^PSS<"]$^T[.M!":1XZ)!@J(PR&ZQ1"VM\D)(%%0YZ?@N M?4;]>6?G+W*?(W^W3Q=C[.P<)?[NRN__`&:X!`Z^RBM2E%I).]`,_H?%FF$@ M%)\^&44F?Z\NL(J^T+]ZJ>JU&)`0XQX;N_B5^5/M*7W%9OV$-/B3$RZRDM[U M3&&AU0&'/=[&[/XTEL9YZ.%0U>_)I2OUC>G.1E,=IT7P(HX/)#7QC3]X.8+6/(ZF>GC>DT#YGAQM`%.O:8[CW3]7YK?O=+]W6HU\_;'VJ==(V M^%:LHQ^?OS@\5%73UHYZ@0'#>QM4W^D_OAWWJ+^_=/# M_;<-]41U[QK--<.ATY4N4[D-_'X=V\C-?P%FXZ_^Z[@..\Y%T=T,`IM*-T>\ MGV8F1;L]5Z>?NT*T'VBL$5N5)1?YJ@'-\*AJ0-'$5HXU:`19SC4'I,P(*YY& M#T:]4MF"46R%8D6\/#6M?BB@X(#7WY_L%I'1QZJK/GYTJ#ML_4?PI&@M9S*$ MC@LR0A>U^*?#OX0)L@.GS7]7J$]WH=<]_>D[55U4@1=46X3;7/GGLLI]4[DO ME2]RE?]>5KEG*O>X_%0$B8-R M2'3[IG*_&!('Y9#H]DSE7B$D>F9J/3VUY`I(%!3_,0<)PU/^-PIG]6J5DPM" M$?X@V\?\\;/]Q]^M/_;M8OMVL7V[V(%=[,`N=I`68WXG.UH/<1W`/H?0(@_A&NW?MF MGE+[W]SS3]!*?G)V/O_"/JZV_W7[C[:R]M]'W=[FVOYW%\_]>V3[B\>W9/:S MT8@,?_W4\+>E>G_>V>KO]._&\+>-AK_MKVWXVZ=#WTF@SH++#A_$G7OA0M5U ML'M'7\C%-P>LTN;WZN71WH;ZM\J&W-':B6'M=\@`G'[B%%K\M_DR\Y;N;)6; MAO?>:0N5JG7?K931_8`!K.$L']6X2J"\^1O?;WVTUVYWX)\5=,BWT@[QXFM= MZ)-])6W;>4,7SZYH5/;LR41LAW12T!P'(M,[Q),50P0MC4=[:6BC`PEZ600( M?E'A;,-\#\4[]BK,5"M0&W'G^'[[0:W3V>6XT>4,&H_KG=^.XP?U7W[;^_4_ M&O!IK]/8%3&AUFN2B+`!FI35P[M5@_IU%,TEH<:8X4DGMBGA!VY1257M+Z=S MI3,PR8W#*X0[NK5U/:.:UP`@[4/5.)3 ME>]MOH[^7\__Y=47\)CK^'^_OYGE_P_[O37_OXOGSOQ_67PB86#+]@+VMG=Z MFSN;?_X#"0//F(H7QG*OE,G9WKY5._)6.$PV/E'D#8PSF@>S^LN_-E45J#\: MSG_I_EIMT,&%,%!5>JV_;X#>>8^TR8LQDM`ZVPCP?,">>OSRKT\:I-P"J9S. MZ_RBL:NUW6&SYC=K\V9MVJQ-FK5ELS9JUI)F;8SJ;SR?@'+::7::RJJGAZG: M>ZIJWR>OCJO'SB7VQU7XJC;G7WZG-N1/4_XUX5]+_C7B7V/^E1RS?ORI,I@` MN@`HT+Z@I\!=`JN\KUZ8:RU,."&>PPDY(VV8I)>88MPCHG,!;'LEL.W=%+;Z MJW\JX//?<^0D,;#C[SMZN)W4!,#%L[/K[:ZU__6S?M;/^ED_ZV?]K)_ULW[6 BS_I9/^MG_:R?];-^UL_Z63_K9_VLGR]Y_@7@O;Z?`/`````` ` end --- config_manager.tgz.uu ---