2012. november 4., vasárnap

HACMP failover issue - Unable to unmount the filesystem

Az ember egy idő után már hajlamos azt hiszi, hogy azért nem lehet könnyen meglepni, ha már egy csomó szívást átélt, meg már a kdb-s bugyrokat is megjárta.. Hiába tudjuk, hogy Murphy csak az ilyen jelekre vár, mindig azt hisszük, hogy fel tudjuk venni vele a kesztyűt.. Aztán az ember szembe kap egy általánosnak tűnő problémát, elkezdi a saját kis módján investigálni, majd akkor koppan amikor rájön, hogy valami mégse úgy megy ahogy kéne, vagy valami még így is van amire nem gondolt előzőleg.

Ez se volt most másként.. Felhívtak kollégák, hogy lenne egy HACMP failover probléma: Szegény RG nem tud átállni, és meg kéne már nézni, hogy mi a rákért nem..
Hát jó.. hacmp.out túrás , és elég gyorsan szembejön az első gyanús jel:
***************************
Nov 3 2012 19:42:13 !!!!!!!!!! ERROR !!!!!!!!!!
***************************
Nov 3 2012 19:42:13 cl_deactivate_vgs: Failed varyoff of appvg.
Aham.. na jó.. nézzük mi van még itt, ami miatt ez előjöhetett:
+app_rg:cl_deactivate_vgs(5.910):appvg[vgs_varyoff+282] varyoffvg appvg
0516-012 lvaryoffvg: Logical volume must be closed.  If the logical
        volume contains a filesystem, the umount command will close
        the LV device.
0516-942 varyoffvg: Unable to vary off volume group appvg.
Ahh.. haladunk.. Mi törpént az FS-el?
+app_rg:cl_deactivate_fs(.160)[fs_umount+58] umount /var/mqm/RGmount
umount: error unmounting /dev/RG_LV: Device busy
+app_rg:cl_deactivate_fs(2.160)[fs_umount+66] : At this point, unmount of /var/mqm/RGmount has not worked. So,
+app_rg:cl_deactivate_fs(2.160)[fs_umount+67] : Send a SIGKILL to all processes having open file
+app_rg:cl_deactivate_fs(2.160)[fs_umount+68] : descriptors within this logical volume to allow
+app_rg:cl_deactivate_fs(2.160)[fs_umount+69] : the umount to succeed.
+app_rg:cl_deactivate_fs(2.160)[fs_umount+71] date '+%h %d %H:%M:%S.000'
Nov 03 19:38:46.000
+app_rg:cl_deactivate_fs(2.160)[fs_umount+72] fuser -k -u -x /dev/RG_LV
/dev/RG_LV:   782460(wasRGuser)  782460(wasRGuser)  868596(wasRGuser)  868596(wasRGuser)  938078(wasRGuser)  938078(wasRGuser) 1081448(wasRGuser) 1081448(wasRGuser)
+app_rg:cl_deactivate_fs(2.740)[fs_umount+73] fuser -c -k -u -x /var/mqm/RGmount
/var/mqm/RGmount:
+app_rg:cl_deactivate_fs(3.260)[fs_umount+74] date '+%h %d %H:%M:%S.000'
Nov 03 19:38:47.000
+app_rg:cl_deactivate_fs(3.260)[fs_umount+77] : Wait 2 seconds for the kills to be effective
+app_rg:cl_deactivate_fs(3.260)[fs_umount+79] sleep 2
+app_rg:cl_deactivate_fs(5.260)[fs_umount+82] : Unmount of /var/mqm/RGmount failed. If the force option can be used, try it here.
+app_rg:cl_deactivate_fs(5.260)[fs_umount+84] [[ -n '' ]]
+app_rg:cl_deactivate_fs(5.260)[fs_umount+99] (( 0 == 57 ))
+app_rg:cl_deactivate_fs(5.260)[fs_umount+123] (( 0 == 60 ))
+app_rg:cl_deactivate_fs(5.260)[fs_umount+52] ((count++ ))
+app_rg:cl_deactivate_fs(5.260)[fs_umount+52] (( count <= 60))
+app_rg:cl_deactivate_fs(5.260)[fs_umount+55] : Try to unmount the file system
+app_rg:cl_deactivate_fs(5.270)[fs_umount+56] date '+%h %d %H:%M:%S.000'
+app_rg:cl_deactivate_fs(5.270)[fs_umount+56] : Attempt 2 of 61 to unmount at Nov 03 19:38:49.000
+app_rg:cl_deactivate_fs(5.270)[fs_umount+58] umount /var/mqm/RGmount
umount: error unmounting /dev/RG_LV: Device busy.
Ez a fázis már az application stop után van, ergo a HACMP joggal van felháborodva, hogy miért nem szabad már a device, ha ő azt át akarja adni a másik node-na.. Sebaj, 5.3 óta fel van készítve a HA erre is, gyenge fuser -kux az LV-re megoldja.. fuser -ckux után látszik, hogy tényleg nem maradt process ami használná az FS-t, úgy hogy semmi gáz, mehet az umount..
De álj.. Megint device busy?? Na innen indul a vicces rész.. Főleg amikor az ember eljut a logban eddig:
+app_rg:cl_deactivate_fs(194.630)[fs_umount+56] : Attempt 61 of 61 to unmount at Nov 03 19:41:58.000
+app_rg:cl_deactivate_fs(194.630)[fs_umount+58] umount /var/mqm/RGmount
umount: error unmounting /dev/RG_LV: Device busy
+app_rg:cl_deactivate_fs(194.760)[fs_umount+66] : At this point, unmount of /var/mqm/RGmount has not worked. So,
+app_rg:cl_deactivate_fs(194.760)[fs_umount+67] : Send a SIGKILL to all processes having open file
+app_rg:cl_deactivate_fs(194.760)[fs_umount+68] : descriptors within this logical volume to allow
+app_rg:cl_deactivate_fs(194.760)[fs_umount+69] : the umount to succeed.
+app_rg:cl_deactivate_fs(194.760)[fs_umount+71] date '+%h %d %H:%M:%S.000'
Nov 03 19:41:58.000
+app_rg:cl_deactivate_fs(194.770)[fs_umount+72] fuser -k -u -x /dev/RG_LV
/dev/RG_LV:
+app_rg:cl_deactivate_fs(195.300)[fs_umount+73] fuser -c -k -u -x /var/mqm/RGmount
/var/mqm/RGmount:
+app_rg:cl_deactivate_fs(195.810)[fs_umount+74] date '+%h %d %H:%M:%S.000'
Nov 03 19:41:59.000
+app_rg:cl_deactivate_fs(195.810)[fs_umount+77] : Wait 2 seconds for the kills to be effective
+app_rg:cl_deactivate_fs(195.810)[fs_umount+79] sleep 2
+app_rg:cl_deactivate_fs(197.810)[fs_umount+82] : Unmount of /var/mqm/RGmount failed. If the force option can be used, try it here.
+app_rg:cl_deactivate_fs(197.810)[fs_umount+84] [[ -n '' ]]
+app_rg:cl_deactivate_fs(197.810)[fs_umount+99] (( 60 == 57 ))
+app_rg:cl_deactivate_fs(197.810)[fs_umount+123] (( 60 == 60 ))
+app_rg:cl_deactivate_fs(197.810)[fs_umount+126] : Out of retries to unmount /var/mqm/RGmount. Game over, man, game over.
+app_rg:cl_deactivate_fs(197.810)[fs_umount+128] cl_echo 25 'cl_deactivate_fs: Failed umount of /var/mqm/RGmount.\n' cl_deactivate_fs /var/mqm/RGmount
A "Game over, man, game over" kedves kis üzenet a fejlesztőktől, és meg meg is mosolyogtatna ha nem látnám, hogy szegény HA-m 61x próbálta meg lenyomni a szerencsétlen FS-t de mind végig Device busy-t kapott.

OS oldalról elnézve az FS valóban ott van a mount alatt, és ha én akarom leszedni akkor ugyan azt kapom:
server@root:/ # mount |grep RGmount
         /dev/RG_LV     /var/mqm/RGmount   jfs2   Nov 03 19:22 rw,log=INLINE
server@root:/ # fuser -cux /dev/RG_LV
server@root:/ # umount /var/mqm/RGmount
umount: 0506-349 Cannot unmount /dev/RG_LV: The requested resource is busy.
Na akkor áljunk meg itt picit.. Mi az amit érdemes megnézni ilyenkor?
- Használja e valami az FS-t
- Megtettem, nem dobott semmit..
- Haszmálja e az LV-t valami?
- Ez az amit a HACMP is megnézett, és aminek amúgy több értelme is van, mint az FS-t nézni -> van 1-2 olyan parancs ami az LV-ket cseszteti direktben, ergo ha a /dev/LV-re ráengedünk egy fuser-t akkor azokat is meg tudjuk fogni.. A HA 1x ezeket le is gyilkolta, viszont utána már nem talált semmit
- Nincs e submount az adott FS alatt
- Amennyiben egy másik FS van a lemountolandó alá felhúzva, úgy persze, hogy a kernel nem engedi nekünk az umountot (Ilyenkor a submountot kell első körben leszedni). Ezt könnyen ellenőrizhetjük is a mount paranccsal, de itt sajna ez se játszik, mivel nem volt egy submount se
- AIO/CIO használatban van?
- Ezen a rendszeren konkrétan pont egyik sincs, viszont ezek is képesek ilyen szintű lockokat összehozni. Viszont a HA épp ezért is próbálkozik 61x (ami itt közel 3 percig ment is), hogy az ilyen dolgokkal se legyen gáz, ha ne adj isten az AIO/CIO nem volt elég gyors adott pillanatban. Mint látható ez itt szintén nem jött be.
- Named Pipe?
- Egzotikum, viszont nem szabad figyelmen kívül hagyni.. Alapvetően Inter-process communication célokra szolgál olyan esetekben ahol a jogosultság szeparáció nem teszi lehetővé a normális IPC kommunikációt direkt memórián keresztül (Hozzáteszem, hogy ez inkább a régebbi appoknál bevett eljárá. Az AIX jó ideje tud direktben memóriában adatot átadni különböző jogosultsági szinteken futó alkalmazásoknak Shared Memory-n keresztül (szintén az IPC része). Ilyen esetekben az applikáció képes egy ilyen "pipe" file-t létrehozni, és sima chmod-os/ACL-es megoldással másik user alatt futó applikációnak átadni az adatot direktben. A probléma ezekkel viszont annyi, hogy nincs tényleges file írás/olvasás, mivel az egész hóbelebancot az AIX memórián belül képes lezongorázni, így meg a fuser se veszi észre, hogy a háttérben szopatják a népet, mivel az fopen/fwrite/fclose és hasonló eventekre figyel főként.

Persze kérdés, hogy hogy járunk ezeknek utána.
- Egyik módszer a http://p1ngw1n.blogspot.hu/2012/02/fuser-nemileg-maskent.html-ban felvázolt módszer
- Másik meg az lsof :)

Mivel az első módszert anno már lefedtem, így maradjunk az egyszerűbbnél, és nézzük, hogy az lsof-el mit is látunk ilyenkor :)
server@root:/ # lsof |grep /var/mqm/RGmount
runmqlsr_  933958 wasRGuser    6u  unix              35,13                0t0 5255524237690535936 /var/mqm/RGmount/qmgrs/APILOT!PRT!QMGR/@qmpersist/spipe/ccc.933958
runmqlsr_  933958 wasRGuser    9u  unix 0xf100020000837c08             0t1728                     /var/mqm/RGmount/qmgrs/APILOT!PRT!QMGR/@qmpersist/spipe/pmpipe
runmqlsr_  933958 wasRGuser   12u  unix 0xf100020000736408             0t1852                     /var/mqm/RGmount/qmgrs/APILOT!PRT!QMGR/@qmpersist/spipe/pmpipe
amqzmgr0  1093830 wasRGuser    8u  unix              35,13                0t0 5255524237690535936 /var/mqm/RGmount/qmgrs/MQRG/@qmpersist/spipe/pmpipe
amqzmgr0  1200368 wasRGuser    8u  unix              35,13                0t0 5255524237690535936 /var/mqm/RGmount/qmgrs/APILOT!PRT!QMGR/@qmpersist/spipe/pmpipe
runmqlsr_ 1605678 wasRGuser    6u  unix              35,13                0t0 5255524237690535936 /var/mqm/RGmount/qmgrs/MQRG/@qmpersist/spipe/ccc.1605678
runmqlsr_ 1605678 wasRGuser    9u  unix 0xf100020002275408             0t1728                     /var/mqm/RGmount/qmgrs/MQRG/@qmpersist/spipe/pmpipe
runmqlsr_ 1605678 wasRGuser   12u  unix 0xf100020001ee7808             0t1852                     /var/mqm/RGmount/qmgrs/MQRG/@qmpersist/spipe/pmpipe

BINGO.. Innen már akkor csak akkor gyilkolásznunk kell :)
server@root:/ # kill -9 933958 1093830 1200368 1605678
server@root:/ # umount /var/mqm/RGmount
server@root:/ #
Innen pedig tovább lehet akkor lökni a HA-t is a túloldalra

A történet tanulsága:
- lusta embereknek kötelező az lsof (az experteknek meg a kdb :))
- A HACMP (attól függetlenül, hogy az idők során szinte mindenre próbálták felkészíteni) se tud mindent lekezelni
- A fejlesztőknek is van humora :)
- Murphy lehet, hogy köcsög mindig, de valahogy még is az ilyen szívásokkal tanulja meg az ember, hogy mennyire is halandó, és lényegében így tanulja csak meg azokat a leckéket, amikre más nem lenne képes megtanítani (se iskola, se oktatás, se certifikációk)

2012. augusztus 26., vasárnap

EPIC moments - Avagy miért születetthetett meg a pokoli operátor?

Az ember néha tényleg azt hinné, hogy a hülyeségnek azért valahol csak van határa, de időről időre rá kell döbbenjek, hogy az ami még tegnap tényleg jó viccnek tűnt, ma már lehet komor valóságként materializálódik a szemem előtt.

Álljon hát itt néhány kis szösszenet azokból az "URAM ISTEN" pillanatokból, amiket az elmúlt időszakban sikerült megtapasztalnom.

1) - "Van e elég hely a /dev/null alatt?"

Anno volt ez egy elszólása egy némileg távoli kollégámnak, amin sikerült jót vigadni. A dolog apropója annyi volt, hogy az egyik logfile-t átirányítottuk a /dev/null alá (mondván, hogy úgy se használjuk, csak ha debugolni kell) erre ő -féltve, hogy az FS megtelik- megkérdezte, hogy van e elég hely alatta.. Ez anno tényleg vicces volt, viszont amikor az ember ilyet lát, de most már kezdem azt hinni, hogy ilyen felszólalásokat Murphy felhívásnak érzi, hogy megcáfolja őket ; főleg amikor ilyesmi issue jön az emberrel szembe:
server@root:/ # df -m /
Filesystem    MB blocks      Free %Used    Iused %Iused Mounted on
/dev/hd4         192.00      0.00  100%     3694    85% /
server@root:/ # du -axk / |sort -rn |head -5
193860  /
109992  /dev
109956  /dev/null
27160   /etc
24272   /lpp
server@root:/ # ls -l /dev/null
-rw-------    1 root     system    112590848 Aug 23 19:55 /dev/null
server@root:/ # du -m /dev/null
107.38  /dev/null
server@root:/ # file /dev/null
/dev/null: commands text
Hogy az a jó élet.. WTF?? A /dev/null nem egy character file-nak kéne lennie? Dehogynem.. Akkor miért nem az?? A válasz: Mert valaki letörölte.. Az első jött ment process meg nyomban létre is hozta a file-t egy átirányítás révén ($command 2>/dev/null - szerintem mindenki látott már hasonlót :)), ami aztán lassan meg is telítette a / filerendszert..

* facepalm * ... Aztán akkor meg a gyógyszer:
rm /dev/null; mknod /dev/null c 2 2; chmod 666 /dev/null
Ha azt hiszitek, itt vége a sztorinak tévedtek!! Murphy úgy gondolta, hogy lesz 2. felvonás is:
server@root:/ # ls -l /dev/null*
crw-rw-rw-    1 root     system        2,  2 Aug 23 15:09 /dev/null
-rw-r--r--    1 root     system     20057274 Aug 23 13:54 /dev/null 2>&1
*sigh* Ez meg mi a lóturó...

Kis turkálás, majd az oka is megvan: http://www-01.ibm.com/support/docview.wss?uid=nas74d33539b559cc0308625792900533a8f
Igen.. A programozók ilyet is tudnak...

2) - Forkbomb sudo-val

A szituáció a következő: Megpróbálsz belépni a rendszerre, de a belépés sikertelen. HMC-ről látod, hogy a gép megy, de a gépet a virtuális terminálon át se sikerül elérni (a terminál megnyílik, de login screen-t nem kapsz). A gép lényegében vegetál, úgy hogy nincs más mint előre - force restart HMC-ről. A gép vissza is jön az életbe, persze az okot ekkor még nem tudjuk, tehát elkezdünk nézegelődni a logokban, hogy mi a fene van.. Rövid vizsgálódás után a shell közli velem, hogy "unable to fork"..
Őőő... Mi van??? És a gép tényleg ismét elkezdi azt amit előtte is: nem lehet vele semmit se kezdeni..
Újabb újraindítás, svmon-al nézzük, hogy mi zabálja a memóriát, de semmi különöset nem látok.. topas.. detto semmi.. ps lista.... állj..
server@user:/ # ps -ef
     UID      PID     PPID   C    STIME    TTY  TIME CMD
    root        1        0   0   Jul 05      -  0:06 /etc/init
    root  1441896        1   0   Jul 05      - 21:51 /usr/sbin/syncd 60
    root  1638488        1   0   Jul 05      -  0:00 /usr/ccs/bin/shlap64
    root  1769656        1   0   Jul 05      -  0:00 /usr/lib/errdemon
    root  2359508  8192170   0 17:57:36  pts/0  0:00 -ksh
    root  2424966  3145848   0   Jul 05      -  0:00 /usr/sbin/biod 6
    root  2556062  3145848   0   Jul 05      -  0:01 /usr/sbin/hostmibd
    root  2752642  3145848   0   Jul 05      -  0:02 /usr/sbin/syslogd
    root  2818192  3145848   0   Jul 05      -  1:35 sendmail: accepting connections
    root  2883696  3145848   0   Jul 05      -  0:02 /usr/sbin/snmpmibd
    root  2949226  3145848   0   Jul 05      -  0:26 /usr/sbin/aixmibd
    root  3014786 15335476   0 17:57:32  pts/0  0:00 -ksh
    root  3080398  4391120   0 17:57:29  pts/0  0:00 -ksh
    root  3145848        1   0   Jul 05      -  0:00 /usr/sbin/srcmstr
    root  3211378  3145848   0   Jul 05      -  0:00 /usr/sbin/snmpd
    root  3342544  4194544   0 17:57:33  pts/0  0:00 -ksh
    root  3407976  3145848   0   Jul 05      -  0:00 /usr/sbin/portmap
    root  3473514  3145848   0   Jul 05      -  0:00 /usr/sbin/inetd
    root  3539066  7864376   0 17:57:32  pts/0  0:00 -ksh
    root  3604658 10420352   0 17:57:33  pts/0  0:00 -ksh
    root  3735804  7536670   0 17:57:34  pts/0  0:00 -ksh
    root  3801268  7340182   0 17:57:32  pts/0  0:00 -ksh
    root  3866832  9044146   0 17:57:31  pts/0  0:00 -ksh
    root  3932166  7667938   0 17:57:34  pts/0  0:00 -ksh
    root  3997750  9764978   0 17:57:30  pts/0  0:00 -ksh
    root  4063286  4259944   0 17:57:31  pts/0  0:00 -ksh
    root  4128854 12910818   0 17:57:34  pts/0  0:00 -ksh
    root  4194544 12320872   0 17:57:33  pts/0  0:00 -ksh
    root  4259944  8978666   0 17:57:31  pts/0  0:00 -ksh
    root  4325470 13041670   0 17:57:35  pts/0  0:00 -ksh
    root  4391120 10223744   0 17:57:29  pts/0  0:00 -ksh
    root  4456662  3604658   0 17:57:34  pts/0  0:00 -ksh
...
    root 15335476 11337968   0 17:57:32  pts/0  0:00 -ksh
    root 15401026 12648676   0 17:57:36  pts/0  0:00 -ksh
    root 15532266 15204356   0 17:57:37  pts/0  0:00 -ksh
server@user:/ # ps -ef |grep -c ksh
245
őő.. ez kicsit sok nem?? Plusz mi a fenétől jöttek ezek elő??? Közben persze telik az idő, és ismét beüt a krach ; újabb restart, de most már sejtem, hogy mi a probléma , valamiért túl sok ksh forkolódik és sok kicsi sokra megy alapon mindegyik lefoglal magának egy kis memóriát, ami azért ekkora léptékben már képes megzabálni a gépet.. Úgy hogy az újraindítás után nyomban proctree-vel kezdem a játékot, s mit látok?
server@user:/ # ps -ef |grep ksh |tail -1
    root 1478878 1466588   0 18:20:10  pts/0  0:00 -ksh
server@user:/ # proctree 1478878
434214    /bin/ksh /etc/rc.itm1
   389164    -ksh -c /opt/IBM/ITM/bin/itmcmd agent start ul >/dev/null 2>&1
      462944    -ksh
         385246    -ksh
            405732    -ksh
               176296    -ksh
                  442614    -ksh
                     381148    -ksh
                        94260    -ksh
És innen meg végtelen sorokban ksh hegyek..

Na nézzük mi jön le ebből: Van egy 434214 PID-ű process-ünk ami épp egy ITM6-os indító script, ami meghívja az UL agent startupját, ami meg aztán hegyekben szórja a ksh-s forkokat.. Ahogy a hívásból látjuk egy ksh futtatja magában a /opt/IBM/ITM/bin/itmcmd file-t is (ergo az is script), ami meg init-ből indul..
Scriptet megnéztem - semmi különös - a szokásos hívások vannak csak benne.. Fejvakarás, wattafák.. Majd megpróbálok én is felmenni root szintre sudo-val, és furcsa módon tapasztalom, hogy bizony, shell-t azt nem kapok... Ctrl+C hegyekben, aztán csak kaptam shell-t..
Ez volt az a pillanat amikor már kezdtem azt hinni, hogy a root user-el van csak gond ( a user shellem gond nélkül ment), ergo belekukkantottam a root profile file-jába, és ezt a gyönyörűséget láttam:
server@root:/ # cat .profile
export ENV=.kshrc
# Define initial prompt to include hostname
export PS1=`hostname`@$USER':$PWD # '
sudo su -
ŐŐ.. Álj.. 'sudo su -' a root profiljában???? KI VOLT AZ A MARHA???? Profil átír, 'sudo su -' sor eltávolít, rendszer ujraindít, minden működik szépen.

Na de mi is történt? - valamelyik ökör belerakta a root profiljába a 'sudo su -' sort.. Miért is gond ez? Mert a 'sudo su -' a root user alatt kérdés (meg jelszó kérés) nélkül lefut, és egy újabb shell-t nyit, ami meg megint beolvassa a root .profile-ját, ami így megint lefuttatja a 'sudo su -'-t és így tovább amíg a szerver bírta...
Ergo valaki ügyesen fork bomb-á alakította a sudo-t root alatt :)

3) - Az öngyilkos java alkalmazás

Anno még írtam is az egyik szép kis kamikáze kódról, ami sikeresen szembe jött velem.. Most újra elő kell vegyem a témát, mert az amit láttam az nem hogy ennek egy emeltebb formája volt, mintsem egy komplett seppuku :)
Na szóval... Van egy szerver, egy rajta futó Websphere (Web's Fear) alkalmazással rajta, amin belül meg fut egy valaki által írt applikáció jópár éve..
Egyik nap megszólal a vészharang, ügyfél sikoltozik, hogy a hőn szeretett alkalmazása nem működik.. Jó, rendben nézzünk utána.. Kis nyomozás, közös munka az application support group-al, majd kiderül, hogy hiányzik az alkalmazás "magja". Pontosabban ott van, csak nem úgy működik, ahogy kéne (azaz sehogy).
Az elején még nem értettem miről van szó, de aztán lassacsakán megvilágosodtam.. Íme egy röpke összefoglaló arról, hogy mi történt (időrendi sorrendben)
- Jópár éve már, hogy valami fejlesztő palánta megírta az alkalmazás core modulját
- Ez a modul jópár évig gond nélkül, aztán beütött a krach - Az applikáció összeomlott, majd nem volt képes újraindulni.
- Az applikáció HOME könyvtárában lévő core file elemzése után kiderült, hogy az alkalmazás egy verem hiba miatt esett össze, majd a szokásos módon dobott egy java core-t. Mindezt egy olyan applikációs almodul játszotta el, amit közvetlenül a fő mag hívott
- Aki még nem találta ki, annak itt a csattanó - Igen, az applikáció magját 'core'-nak hívták.. Ezt volt a file neve..

Tehát mi is történt: Volt egy core nevű alkalmazásunk, ami szépen futott, míg az egyik almodulja (ugyan abból a HOME-ból futtatva) nem dobott egy coredumpot, ezzel szimplán felülvágva az eredeti 'core' file-t, innentől meg az alkalmazás központi magja nem volt elérhető, ergo persze, hogy nem is indult el ez után.

És egyesek még csodálkoznak, hogy az IT-sok néha "kicsit" idegesek.. El nem tudom képzelni miért..

2012. július 25., szerda

AIX - booby trap

Az ember azt hinné, hogy az AIX-el nem lehet vicces dolgokat csinálni, de olykor olykor kellemesen tud csalódni abban amit el lehet ténylegesen érni vele.
Múltkor például sikerült rájönnöm, hogy IPsec-el lehet olyan szabályt létrehozni, ami annyit csinál, hogy ha egy kliens megpróbál az adott portra csatlakozni, akkor kap egy X sec-es ban-t mindenféle hálózati forgalommal együtt..
Belegondolva ez egy standard támadó ellen teljesen jó kis csapda -> Csupán annyit kell csinálnunk, hogy egy meglehetősen alacsony portra kirakunk egy sérülékeny szolgáltatást (rsh, telnet, csak hogy finoman is nézzen ki), majd rádefiniálunk egy szabályt, hogy aki megpróbál bejönni, annak mondjuk 1 napig csend legyen.. Amennyiben a támadónk valamiféle scanneléssel próbálkozik (sima nmap is elég :)) már bele is esett a csapdába.. Csodálatos, mit ne mondjak :))

Hogy ez a valóságban hogy is néz ki? Nos van 1-2 alapfeltétel:
- clic.rte alatti csomagoknak fent kell legyenek a gépen
- Be kell legyen töltve az Ipsec modul (ipsec_v4, ha IPv4et akarunk védeni)
- A szabályokat nekünk kell beállítani.

Tehát a feladat szimplán ennyi:
server # installp -avXYgd /source clic.rte.lib clic.rte.kernext  
    # Alap csomagok telepítése
server # smitty ips4_start # Indítsuk el az Ipsec IPv4es támogatását
server # lsdev -l ipsec_v4 # Nézzük meg elérhetővé vált e az ipsec_v4 device
ipsec_v4 Available  IP Version 4 Security Extension
A szabály beállítás némileg macerásabb. Csinálhatjuk 'smitty ips4_add_filter'-el, vagy genfilt-en keresztül parancssorból is.
Smitty-ből így néz ki a konfigolás:
* Rule Action                                                                   [shunHost]            
* IP Source Address                                                         [0.0.0.0]
* IP Source Mask                                                             [0.0.0.0]
  IP Destination Address                                                   [10.1.0.100]
  IP Destination Mask                                                       []
* Apply to Source Routing? (PERMIT/inbound only)    [yes]                 
* Protocol                                                                         [all]                 
* Source Port / ICMP Type Operation                             [any]                 
* Source Port Number / ICMP Type                                [0]                   
* Destination Port / ICMP Code Operation                     [eq]                  
* Destination Port Number / ICMP Type                        [23]                  
* Routing                                                                         [both]                
* Direction                                                                       [inbound]             
* Log Control                                                                  [yes]                 
* Fragmentation Control                                                 [0]                   
* Interface                                                                       [all]                 
  Expiration Time (sec)                                                   [300]                 
  Pattern Type                                                                 [none]                
  Pattern / Pattern File                                                     []
  Description                                                                   [telnet_boobytrap]
Ugyan ez parancssorból:
server # genfilt -v 4 -a H -s '0.0.0.0' -m '0.0.0.0' -d 10.1.0.100 -g y -c all -o any -p 0 -O eq -P 23 -r B -w I -l Y -t 0 -i all -e 300 -D 'telnet_boobytrap'
Némi kis magyarázat a kapcsolókról:
-v 4 -> IP version 4
-a H -> ShunHost
-s 0.0.0.0 -> Source address (0.0.0.0 == bárhonnét)
-m 0.0.0.0 -> Source Mask (0.0.0.0 == mindenhonnan)
-d 10.1.0.100 -> Destination IP (nem kötelező, de a tapasztalatok alapján érdemes megadni, mert nélküle mintha nem menne (nem tudtam rájönni miért))
-g y -> Source packet átroute-olása
-c all -> Minden protokolon (udp/tcp/icmp/ospf/ipip/esp/ah)
-o any -> Source port (0 == bármelyik)
-p 0 -> Source port (0 == bármelyik)
-O eq -> Milyen tipusú operátort használjuk (eq == equal -> megyegező port)
-P 23 -> Port száma (23 == telnet)
-r B -> Routing-ot pontosan mely láncokra érvényesítsük (route forward, local routing, avagy mind2 (both)
-w I -> Direction. Jelen esetben csak a bejövő csomagokkal foglalkozunk
-l Y -> Loggolás.. Persze, hogy akarunk loggolni :) (For the record - a logok a local4:err, local4:info és local4:notice alá mennek)
-t 0 -> Fragmenation Control, avagy melyik ID-jű tunnelbe toljuk majd bele a csomagot ( a 0 default)
-i all -> Interface.. Mindenhol halgatózni akarunk természetesen :)
-e 300 -> Expiration time másodpercben (kíméletesek leszünk, most csak 5 perces bann jár :))
-D 'telnet_boobytrap' -> Description.. Hogy kb a leírás alapján tudjuk mit is akarhatott a költő amikor ezt a szabályt létrehozta..

Ennek az eredménye egy olyan rule lesz, ami bárhonnét jövő IPv4-es kapcsolatot kitilt 5 percre, ha én a 23-as portra próbálok csatlakozni.
Szerverről lekérve pedig láthatjuk is a kis szabályunkat:
server # lsfilt -v4 -O
1|permit|0.0.0.0|0.0.0.0|0.0.0.0|0.0.0.0|no|udp|eq|4001|eq|4001|both|both|no|all packets|0|all|0|||Default Rule
2|*** Dynamic filter placement rule for IKE tunnels ***|no
3|shunHost|0.0.0.0|0.0.0.0|0.0.0.0|255.255.255.255|yes|all|any|0|eq|23|both|inbound|yes|all packets|0|all|300|||telnet_boobytrap
0|permit|0.0.0.0|0.0.0.0|0.0.0.0|0.0.0.0|yes|all|any|0|any|0|both|both|no|all packets|0|all|0|||Default Rule
Na most azért van itt még 1-2 dolgot amire ki kell térni:
- A 0ás,1es,2es szabályok állandóak, ergo a legkisebb ID amit kaphatunk az 3as lesz 1 szabályhoz, illetve afölött
- Azzal, hogy a rule-t létrehoztuk még nem jelenti, hogy életbe is léptettük azonnal -> azt külön meg kell tenni :)
- Ráadásként a loggolást is hiába állítottuk be, ha nem engedélyezzük azt is :)

Mázlinkra ez összesen 2 új parancsot jelent:
server # mkfilt -v4 -g start  # Loggolás aktiválása
server # mkfilt -v4 -u    # A felvitt rule-ok aktiválása
Innentől fogva viszont életbe léptek a változtatásaink, és mindenféle bajkeverő ilyen következményekkel kell szembenézzen

Mit jelent ez a gyakorlatban?
"telnet_boobytrap" szabály nélkül az nmap ezt dobja vissza:
pentester # nmap -sS 10.1.0.100

Starting Nmap 5.51 ( http://nmap.org ) at 2012-07-25 22:15 Central Europe Daylight Time
Nmap scan report for 10.1.0.100
Host is up (0.061s latency).
Not shown: 994 closed ports
PORT     STATE SERVICE
23/tcp   open  telnet
111/tcp  open  rpcbind
514/tcp  open  shell
1334/tcp open  writesrv
2049/tcp open  nfs
9090/tcp open  zeus-admin
MAC Address: 00:00:00:41:47:4E (Xerox)

Nmap done: 1 IP address (1 host up) scanned in 1.72 seconds
"telnet_boobytrap"-al ugyan ez:
pentester # nmap -sS 10.1.0.100

Starting Nmap 5.51 ( http://nmap.org ) at 2012-07-25 21:46 Central Europe Dayliht Time
Nmap scan report for 10.1.0.100
Host is up (0.063s latency).
Not shown: 919 closed ports, 76 filtered ports
PORT     STATE SERVICE
111/tcp  open  rpcbind
514/tcp  open  shell
1334/tcp open  writesrv
2049/tcp open  nfs
9090/tcp open  zeus-admin
MAC Address: 00:00:00:41:47:4E (Xerox)

Nmap done: 1 IP address (1 host up) scanned in 1521.31 seconds
1.72 sec VS 1521.32 sec (több mint 25 perc :)) és csak egy 5 perces tiltást állítottunk be.. Képzeld el mi lesz ha "kicsit" emeljük a tétet, mondjuk 86400-ra (24 óra) :))

Nézzük mi van akkor ha valaki csak simán be akar telnetelni:
pentester  # telnet 10.1.0.100
Trying...
telnet: connect: A remote host did not respond within the timeout period.

Mindeközben a logban:
server  # tail -f /var/log/syslog.out |grep ipsec
Jul 25 20:29:42 server local4:info ipsec_logd: #:2 R:d  I:10.1.0.100 S:10.1.0.153 D:10.1.0.100 P:tcp/ack SP:53688 DP:23 R:l I:en1 F:n T:0 L:60
Jul 25 20:29:42 server local4:info ipsec_logd: #:1 R:d  O:995:46f4:995:46d2:995:46f4:600:d1b8 S:17:0:0:1::2 D:0:1::656e:3100:f100:500 P:(1) -:54272 -:61696 R:l I: F:n T:3935892 L:18472
Jul 25 20:29:43 server local4:info ipsec_logd: #:0 R:d  I:10.1.0.100 S:10.1.0.153 D:10.1.0.100 P:tcp/ack SP:53688 DP:23 R:l I:en1 F:n T:0 L:60
Jul 25 20:29:43 server local4:info ipsec_logd: #:-2010349502 R:d  O:995:46f4:995:46d2:995:46f4:600:d1b8 S:17:0:0:1:: D:0:1::656e:3100:f100:500 P:ip -:12288 -:61696 R:l I: F:n T:3935892 L:0
Jul 25 20:29:46 server local4:info ipsec_logd: #:0 R:d  I:10.1.0.100 S:10.1.0.153 D:10.1.0.100 P:tcp/ack SP:53688 DP:23 R:l I:en1 F:n T:0 L:60
Jul 25 20:29:46 server local4:info ipsec_logd: #:-2010349502 R:d  O:995:46f4:995:46d2:995:46f4:600:d1b8 S:17:0:0:1:: D:0:1::656e:3100:f100:500 P:ip -:12288 -:61696 R:l I: F:n T:3935892 L:0
Jul 25 20:29:52 server local4:info ipsec_logd: #:0 R:d  I:10.1.0.100 S:10.1.0.153 D:10.1.0.100 P:tcp/ack SP:53688 DP:23 R:l I:en1 F:n T:0 L:60
Jul 25 20:29:52 server local4:info ipsec_logd: #:0 R:d  O:995:46f4:995:46d2:995:46f4:600:d1b8 S:17:0:0:1:: D:0:1::656e:3100:f100:500 P:ip -:27136 -:61696 R:l I: F:n T:3935892 L:0
Jul 25 20:30:04 server local4:info ipsec_logd: #:0 R:d  I:10.1.0.100 S:10.1.0.153 D:10.1.0.100 P:tcp/ack SP:53688 DP:23 R:l I:en1 F:n T:0 L:60
Jul 25 20:30:04 server local4:info ipsec_logd: #:1 R:d  O:995:46f4:995:46d2:995:46f4:600:d1b8 S:17:0:0:1:: D:0:1::656e:3100:f100:500 P:(1) -:9216 -:61696 R:l I: F:n T:3935892 L:0
Jul 25 20:30:28 server local4:info ipsec_logd: #:0 R:d  I:10.1.0.100 S:10.1.0.153 D:10.1.0.100 P:tcp/ack SP:53688 DP:23 R:l I:en1 F:n T:0 L:60
Jul 25 20:30:28 server local4:info ipsec_logd: #:0 R:d  O:995:46f4:995:46d2:995:46f4:600:d1b8 S:17:0:0:1:: D:0:1::656e:3100:f100:500 P:ip -:27136 -:61696 R:l I: F:n T:3935892 L:0
Jul 25 20:30:57 server local4:info ipsec_logd: #:0 R:d  I:10.1.0.100 S:10.1.0.153 D:10.1.0.100 P:tcp/ack SP:53697 DP:23 R:l I:en1 F:n T:0 L:60
Jul 25 20:30:57 server local4:info ipsec_logd: #:-2010349502 R:d  O:995:46f4:995:46d2:995:46f4:600:d1c1 S:17:0:0:1:: D:0:1::656e:3100:f100:500 P:ip -:12288 -:61696 R:l I: F:n T:3935892 L:0
Jul 25 20:30:58 server local4:info ipsec_logd: #:0 R:d  I:10.1.0.100 S:10.1.0.153 D:10.1.0.100 P:tcp/ack SP:53697 DP:23 R:l I:en1 F:n T:0 L:60
Jul 25 20:30:58 server local4:info ipsec_logd: #:0 R:d  O:995:46f4:995:46d2:995:46f4:600:d1c1 S:17:0:0:1:: D:0:1::656e:3100:f100:500 P:ip -:27136 -:61696 R:l I: F:n T:3935892 L:0
Jul 25 20:31:01 server local4:info ipsec_logd: #:0 R:d  I:10.1.0.100 S:10.1.0.153 D:10.1.0.100 P:tcp/ack SP:53697 DP:23 R:l I:en1 F:n T:0 L:60
Jul 25 20:31:01 server local4:info ipsec_logd: #:-2010349502 R:d  O:995:46f4:995:46d2:995:46f4:600:d1c1 S:17:0:0:1:: D:0:1::656e:3100:f100:500 P:ip -:12288 -:61696 R:l I: F:n T:3935892 L:0
Jul 25 20:31:07 server local4:info ipsec_logd: #:0 R:d  I:10.1.0.100 S:10.1.0.153 D:10.1.0.100 P:tcp/ack SP:53697 DP:23 R:l I:en1 F:n T:0 L:60
Jul 25 20:31:07 server local4:info ipsec_logd: #:0 R:d  O:995:46f4:995:46d2:995:46f4:600:d1c1 S:17:0:0:1:: D:0:1::656e:3100:f100:500 P:ip -:27136 -:61696 R:l I: F:n T:3935892 L:0
Jul 25 20:31:19 server local4:info ipsec_logd: #:0 R:d  I:10.1.0.100 S:10.1.0.153 D:10.1.0.100 P:tcp/ack SP:53697 DP:23 R:l I:en1 F:n T:0 L:60
Jul 25 20:31:19 server local4:info ipsec_logd: #:1 R:d  O:995:46f4:995:46d2:995:46f4:600:d1c1 S:17:0:0:1:: D:0:1::656e:3100:f100:500 P:(1) -:9216 -:61696 R:l I: F:n T:3935892 L:0
Jul 25 20:31:43 server local4:info ipsec_logd: #:0 R:d  I:10.1.0.100 S:10.1.0.153 D:10.1.0.100 P:tcp/ack SP:53697 DP:23 R:l I:en1 F:n T:0 L:60
Jul 25 20:31:43 server local4:info ipsec_logd: #:0 R:d  O:995:46f4:995:46d2:995:46f4:600:d1c1 S:17:0:0:1:: D:0:1::656e:3100:f100:500 P:ip -:27136 -:61696 R:l I: F:n T:3935892 L:0
Amire tessék figyelni: Amint az egyik szabály érvényesül egy bejövő címre, az ipsec elkezdi logolni az összes próbálkozását a node-nak, miután ki lett tiltva (az nmap kellemes kis 2 MB-os logot generált nekem a ~25 perc alatt :)) de innentől már nem csak a megadott portra (23), hanem mindre amire a támadó gép bepróbálkozott

Ami a nagykönyvben nincs leírva..

Vannak helyzetek, amikor az ember elkezd azon agyalni, hogy a hivatalos utakon kívűl vannak e mások is.. Utak, amiken szintén el lehet indulni, és amin keresztül el lehet jutni A-ból B pontba.. Lehetőleg még gyorsabban is, vagy kevésbé fájdalmasan 1-1 issue alkalmával..
És vannak alkalmak amikor az ember igen is az ilyen utakon akar járni, főleg ha rájön, hogy azok sokkalta kifizetődőbbek, mint a hivatalosak. Na ez az eset pontosan ilyen volt :)

A szituáció adott: Van egy JFS2 filesystem, kellemes kis 2 TB-os mérettel, alatta "egy pár" LUN-al (diszkkel), és egy csúnya üzenettel az errpt-ben, miszerint:
server # errpt |head -2
IDENTIFIER TIMESTAMP  T C RESOURCE_NAME  DESCRIPTION
E86653C3   0723123112 P H LVDD           I/O ERROR DETECTED BY LVM
Nem kell sokat találgatnotok -> Igen, az az I/O error az adott 2 TB-os FS-re jött.. Tekintve, hogy az FS DS8K-s LUN-okra építkezik így ez még viccesebbé teszi a helyzetet, mivel ez csak az alábbi scenario-k között jöhet létre:
- Disk management issue (ez esetben a driver szopat)
- Fibre adapter issue (már ha nincs normális redundancia)
- Disk locking issue (ha ne adj isten a LUN több helyre van kizónázva, és más is használja az adott LUN-t, főleg ha még írni is akar rá)
- SAN box oldali issue (a DS oldali kötet hibás ottani adapter, vagy diszk hiba miatt)

Egyik se kellemes, mit ne mondjak..
Az első amit ilyenkor tudnunk kell, hogy a hiba milyen körülmények között jön elő. Jelen esetben annyit kell még tudni, hogy csak 1 LUN-ja jött a hiba, de arra állandóan, így az első 2 hibalehetőséget nyomban ki is lehet zárni (a driver CSAK 1 diszket nem köhög meg, hanem akkor konzisztensen szívatja az összeset, a HBA meg dettó nem hajlamos kispécizni magának LUN-okat :)).

A másik 2 lehetőség felderítéséhez meg a Storage szerveren kell turkálni ami meg jelen esetben másik team hatásköre volt, ám némi kis nyomozás után kiderült, hogy a zónázással nincs gond, viszont a kiosztott LUN alatt lévő fizikai réteg bizony kehés, ergo azt ők gyorsan orvosolják..

Egy részről ez jó mert egy elég komoly hibát sikerül megoldani, más részről viszont kliens oldalon (igen, nálam) még mindig ott az a fránya kis probléma, minek eredete, hogy nem férek hozzá az adatomhoz, és esélyes, hogy a javítás után se tudnék, ergo ezt nekem is valahogy orvosolni kéne..

A kérdés persze, hogy hogyan.. A probléma ugyan is az, hogy van minimum 1 blokkom a diszken, amit garantáltan nem tudok olvasni, azt kitiltani nem tudom, migrálni szintúgy nem (pont az olvasási hiba miatt), szóval 2 szék között sikerült a pad alá kerülnöm.. Ilyen esetben a hivatalos megoldás az lenne, hogy töröljem az FS-t, hozzam létre újra (és figyeljek, hogy az a LUN véletlenül se legyen ismét része az új FS-nek), majd backup-ból restore-oljam.. Ok, de 2 TB adatról beszélünk, a restore sok idő, a downtime meg drága..

Így hát adott a kérdés - hogy a francba minimalizáljuk a downtime-ot? Ez a kis leírás kb egy scenario-t mutat be arra amit sikerült kiötlenem :)

Na szóval.. Mondtam, hogy a migrálás zsákutca.. Ezt persze nem hasra ütés alapján merem kijelenteni, hanem fájdalmas tapasztalatból, ugyan is sikerült így járjak az adott LUN-al:
server # migratepv vpath59 vpath91
0516-076 lmigratelv: Cannot remove last good copy of stale partition.
Resynchronize the partitions with syncvg and try again.
0516-812 migratepv: Warning, migratepv did not completely succeed;
all physical partitions have not been moved off the PV.
őő.. Egen.. Egy próbát megért, be is bukott.. (akinek a vpath nem lenne ismerős -> tekintve, hogy DS-ről beszélünk, így SDD driver megy az AIX alatt, ami meg hdisk-ek helyett vpath-okat használ) Megnézve a VG/LV adatokat meg ilyen randaságok jöttek szembe:
server # lsvg -l appvg |grep applv
0516-1147 : Warning - logical volume applv may be partially mirrored.
applv         jfs2       8192    9216    9    open/stale    /appdata
A VG PP size-a 256 MB, az FS pont 2 TB (8192 PP), és 9216 PP-nyi hely van felhasználva, tekintve, hogy az egyik PV-t épp át akartuk migrálni egy 9. 256 GB méretű LUN-ra (ami alapjáraton a LUN mirrorozását jelenti). Sajna a partíció open/stale helyzetben van, és ezen egy syncvg se segít
server # syncvg -l applv
0516-934 /usr/sbin/syncvg: Unable to synchronize logical volume applvg.
Ez a helyzet már magában is vicces, mivel nyomban plusz egy problémát hoz be a képbe, miszerint "Hogy a francba szedjem le a mirrort arról a LUN-ról".. unmirrorvg nem segít, az teljes VG-re van, rmlvcopy se, mert az meg teljesen kimirrorozott LV-re használható csak (itt meg csak 2 PV van "mirrorban" a 9ből), más hivatalos módszer meg nincs (vagy csak nekem nem jut eszembe)..

Ha viszont még valaki emlékszik, akkor én írtam egy módszerről anno, hogy hogy is lehet LV-t csökkenteni Na.. Ez a módszer most épp kapóra jön, csak kicsit másként kell használni, de a recept hasonló:

- Olvassuk ki az LV mappolását egy külön file-ba
- Szűrjük le, hogy mit akarunk kiszedni az LV alól
- Umountoljuk az FS-t (és tegyük closed-ba így az LV-t)
- Dobjuk ki ami nem kell
Ez kb így nézett nálam ki:
server # lquerylv -L $(getlvodm -l applv) -r > /tmp/mapfile
server # grep $(lspv |grep -w vpath91|awk '{print $2}') /tmp/mapfile >/tmp/mapfile2
server # wc -l /tmp/mapfile2
     1024 /tmp/mapfile2
server # umount /appdata
server # lreducelv -l $(getlvodm -l applv) -s 1024 /tmp/mapfile2
Ezt még persze megfejelhetjük egy fsck-val mount előtt, de itt még nem lesz probléma garantáltan.. Viszont innentől az FS visszaáll open/syncd-be :)
server # lsvg -l appvg |grep applv
applv         jfs2       8192    8192    8    open/syncd    /appdata
Ezzel egy problémát megoldottunk, viszont az eredeti még mindig megvan.. Viszont a fenti koktél némileg másként keverve itt is segíteni tud -> a módszer használható PP-k/LP-k teljes "lecserélésére" is ha összekombózzuk az lextendlv-vel :) A módszer kb így néz ki:

- 1x is pakoljunk át mindent amit tudunk a hibás LUN-ról (diszkről, ha úgy jobban tetszik) egy másik használható LUN-ra
- A pakolás közben 1, vagy több LP garantáltan nem fog átmenni, de nem is kell, elég ha a használható adat átballag a másik helyre
- Miután megvan, hogy mely LP-k nem teljesen elérhetőek, azokat kidobjuk a fenti módon
- Majd ezután ugyan annyi LP-t adunk az új diszkről, csupán az LP számozásra kell figyeljünk
Ennek a módszernek egyik nagy előnye, hogy nem kell a teljes FS-t backupból visszahozni, a másik oldalról viszont az elvesztett PP-ket üres PP-vel fogjuk feltölteni, ami meg elég durva adatvesztést/adatinkonzisztenciát jelent, amit viszont valahogy le kell kezelni. Tekintve, hogy az adat már most se nagyon elérhető, így ez még mindig a leghasználhatóbb útvonal a hiba javításához (lehet dönteni, hogy az adat nem elérhető, vagy 0-val van feltöltve -> restore mind a 2 esetben kell).

Ehhez persze tudni kell, hogy mely file-ok lesznek érintettek, ergo be kell vetni még 1-2 plusz lépést, hogy tudjuk mi és merre.. A legegyszerűbb erre az, hogy a file-okból egy checksum-ot generálunk (az legalább végigmegy a file-okon, és nem az attribútumok alapján próbál tájékozódni) a művelet előtt, majd utána, aztán összevetjük a kettőt egy diff-el, majd ami változott azt visszahozzuk backupból. Ez alapján a fenti terv az alábbi módon módosul:

- Checksum generálás minden FS-ben lévő file-ról
- LP-k migrálása egy másik LUN-ra (vpath91 a mi esetünkben) az eredeti LUN-ról (vpath59)
- FS umountolása (LV closed-ba tétele)
- Hibás PP-k/LP-k kidobása (azaz, ami marad a migráció után)
- Új "üres" PP/LP hozzáadása az LV-hez
- Újabb checksum generálás a file-okról
- A 2 checksum kimenet összevetése
- TSM restore a változott file-okról
Parancsokra lebontva ez az alábbi módon néz ki:
server # find /appdata -type f -exec sum {} \; >/tmp/checksum1
server # lslv -m applv |grep vpath59 > /tmp/applv_lslv_out
server # for i in $(awk '{print $1}' /tmp/applv_lslv_out);do migratelp applv/${i}/1 vpath91;done
....
server # lquerylv -L $(getlvodm -l applv) -r |grep $(lspv |grep -w vpath59|awk '{print $2}') > /tmp/mapfile_remove
server # umount /appdata
server # export LP_ERRORS=$(wc -l /tmp/mapfile_remove|awk '{print $1}')
server # lreducelv -l $(getlvodm -l applv) -s ${LP_ERRORS} /tmp/mapfile_remove
server # sed "s/$(lspv |grep -w vpath59 |awk '{print $2}')/$(lspv |grep -w vpath91|awk '{print $2}')/g" /tmp/mapfile_remove > /tmp/mapfile_add
server # lslv -m applv |grep -w vpath91 |awk '{print $2}' |sort -n|tail -1
1022
 # Azon LP-k száma, amit sikerült átmigrálnunk a migratelp-vel a vpath91re
server # vi /tmp/mapfile_add  
 # Itt kell átírjuk az LP számozást, nehogy ütközzön az előzővel (tehát a 2 LP-nk (Ennyi volt az $LP_ERRORS nálam) száma 1022 fölött kell legyen. 
 # Én maradtam az 1023 és az 1024-nél :)
server # lextendlv -l $(getlvodm -l applv) -s ${LP_ERRORS} /tmp/mapfile_add
server # fsck /dev/applv
The current volume is: /dev/applv
Primary superblock is valid.
*** Phase 1 - Initial inode scan
*** Phase 2 - Process remaining directories
*** Phase 3 - Process remaining files
*** Phase 4 - Check and repair inode allocation map
*** Phase 5 - Check and repair block allocation map
server # mount /appdata
server # find /appdata -type f -exec sum {} \; >/tmp/checksum2
server # diff /tmp/checksum1 /tmp/checksum2 > /tmp/checksum_difference
server # for FILE in $(awk '/^</ {print $3}' /tmp/checksum_difference);do dsmc rest $FILE;done

... PROFIT ...

# A folyamat persze feltételezi azt, hogy az FS alatt nem történik ilyenkor más változás, ergo az applikációs team-et a folyamat alatt illik távol tartani.. Viszont ez a módszer egész türhetően levitte számomra a visszaállítandó adat mennyiségét 2 TB-ról 3,2 GBra (2 db 256 MB-os PP sérülés volt az adott PV-n, azok közül az egyik meg pont egy nagyobb file-ban, ergo azt teljesen vissza kellett állítani)

Mi is történt? Kicseréltünk 2 LP-t 1 LV alól, úgy hogy azt a hivatalos módszerekkel elvileg meg se lehet oldani (legalább is nem ilyen módon). Mindebben pedig a legszebb, hogy az egészből az FS szinte alig vesz észre valamit, max némi adat nullázódik ki, de azt meg TSM-ről visszahozzuk..

Azt azért persze hozzá kell tennem, hogy ez a módszer véletlenül se támogatott hivatalosan, és ha az IBM support észreveszi, hogy nem a normál módon járunk el, akkor az ebből fakadó hibákra semmiféle felelősséget nem vállal, szóval óvatosan játszadozzon ezzel a módszerrel bárki is, és csak is saját felelősségre!

***********
Némi kis bónusz - ha az lvextend előtt kérjük le az LV állapotát, akkor ilyen kellemes helyzetben találhatjuk magunkat :))
server # lsvg -l appvg |grep applv
0516-1147 : Warning - logical volume applv may be partially mirrored.
applv         jfs2       8192    8190    8    open/stale    /appdata

2012. június 14., csütörtök

Hardening AIX - tűzfal

Anno amikor megismerkedtem az AIX-el még úgy tanították, hogy az AIX egy nagyvállalati rendszer, és azért nincs alatta tűzfal, mert azért az infrastruktúrának kell felelnie (persze van IPsec, de az nem tűzfal megoldás). Némi kis Linuxos múlttal a hátam mögött ezt anno nagyon furcsának éreztem, de aztán csak megszoktam, hogy ha nagyvállalat, akkor tényleg lesz valahol egy CISCO eszköz is a közelben, az meg tényleg egész jó tűzfal lehetőségeket biztosít.
Viszont -mint kiderült- az AIX alatt még is van elérhető "támogatott" tűzfal és NAT (!) megoldás a híresztelésekkel ellentétben.. Igen, nem káprázik a szemetek - az AIX-ra ugyan is portolták a BSD rendszerek alatt is ismert ipfilter-t!
Csupán 2 szépséghibája van a dolognak:
- Nem része az alap rendszernek - csupán az Expansion Pack részeként lehet elérni
- A fejlesztés kicsit mintha megállt volna (vagy csak elérték a tökéletességet :)) és a csomag megragadt az 5.3.0.3 verziónál (mázlira ettől még 5.3/6.1/7.1 alatt is gond nélkül lehet használni)

Amennyiben valaki úgy érzi, hogy ez kell neki (és ismét át akarja élni a tűzfal piszkálás okozta izgalmakat :)), az az alábbi módon telepítheti/tesztelheti a tool-t

Szedjük ki az expansion pack-ből a 'ipfl' file-t, meg ha már ott járunk, akkor töltsük le a legfrissebb javítást is a csomaghoz
Töltsük fel a 2 file-unkat a szerverünk alá (nálam ez lesz a test_server)
scp ipfl* test_server:/tmp/ipfilter
Csináljuk meg a .toc file-unkat (avagy ha már csinálunk valamit, akkor csináljuk normálisan)
ssh test_server
test_server@root:/ # cd /tmp/ipfilter
test_server@root:/tmp/ipfilter # inutoc .
Rakjuk fel a csomagunkat
test_server@root:/tmp/ipfilter # installp -avXYgd /tmp/ipfilter ipfl.rte
A telepítés után inicializáljuk a telepített kernel modult
test_server@root:/tmp/ipfilter # /usr/lib/methods/cfg_ipf -l
Innen indul a jó rész: Csináljuk meg a saját szabályainkat :) Személy szerint úgy vagyok vele, hogy jobban szeretem a láncaimat file-ban látni, de persze lehetne nyomban gépelgetni is a láncokat. Én az egyszerűség kedvéért csak 1 magas portot engedélyeztem 2 gépről (és mint jó rendszergazda nyomban úgy indultam neki, hogy mindent tiltok, kivétel amit engedek )
test_server@root:/ # vi /etc/ipf.conf
block in proto tcp/udp all
pass in proto tcp/udp from 10.1.0.1 to port = 22222 keep state
pass in proto tcp/udp from 10.1.0.2 to port = 22222 keep state
Ha készen vagyunk a szabály láncainkkal, akkor adjuk is hozzá azokat a jelenleg üres láncokhoz
test_server@root:/ # ipf -f /etc/ipf.conf
# Megjegyzés - Amennyiben a konfig file-t többször piszkáljuk, akkor a '-Fa' (Flush All) kapcsolóval érdemes a file-t újraolvastatni, különben az ipfilter simán hozzáfűzi a szabályokat a már meglévő láncokhoz)
# Megjegyzés #2: Amennyiben olyan ügyesek voltunk, hogy valami írdatlan nagy hülyeséget csináltunk, akkor simán a '-Fa'-val flusholhatjuk a teljes szabályrendszert (Aki dolgozott már remote tűzfal konfigurálással, az tudja, hogy egy megfelelően megírt script mennyit tud segíteni egy ilyne flush-al, amennyiben valahogy sikerült magunk alól kifürészelni a fát)
test_server@root:/ # ipf -Fa -f /etc/ipf.conf
Ellenőrzés: Nézzük meg az incoming/outgoing láncainkat:
test_server@root:/ # ipfstat -in
@1 block in proto tcp/udp from any to any
@2 pass in proto tcp/udp from 10.1.0.1/32 to any port = 22222 keep state
@3 pass in proto tcp/udp from 10.1.0.2/32 to any port = 22222 keep state
test_server@root:/ # ipfstat -on
empty list for ipfilter(out)
Ha minden szép és jó, akkor kedvünk szerint lehet az indításról gondoskodni (rc script, inittab bejegyzés, vagy a /etc/rc.net szerkesztése), azt viszont ne felejtsük el, hogy ez után illik egy 'bosboot -ad'-t futtatni, hogy a következő bootoláskor ne kelljen a module-t manuálisan betöltenünk

További infók: http://www-304.ibm.com/support/docview.wss?uid=isg3T1011144

2012. május 28., hétfő

Sudo te drága.. De sokat kell érted fizetni időnként :)

A sudo nevű utility-t szerintem nem kell senkinek se bemutatnom.
Segítségével (minimum féldisznóért) root hozzáférést kaphatunk kedvenc adminisztrátorunktól az adott (természetesen teszt) rendszerünkhöz (NOPASSWD-s rule-al, mert jelszót beírni senki nem szeret :)), így szabadon garázdálkodhatunk és nézelődhetünk, hogy ha valami gáz van a kódban (avagy "De hisz ez még tegnap működött!").
Persze azt se szabad elfelejteni, hogy ezen eszköz révén némileg le tudjuk korlátozni az olyan usereket is, akiknek helyenként root jogosultság kéne, hogy elindítsanak valamit ("Hogy hogy nem képes a WAS support team elindítani a 80as portra bindelő WAS-t root hozzáférés nélkül? Felháborító!")

Lényeg ami lényeg: AIX/Linux alatt ez a progi több mint kötelező, hacsak némileg is törődünk a gép biztonságával. Persze ennek telepítése után se lesz kolbászból a kerítés, sőt, még plusz melót is vartunk a nyakunkba azzal, hogy a /etc/sudoers-t karban kell tartani, de hát istenem, ki mondta, hogy a security fenékig tejföl?

Az issue amivel jelen esetben sikerült szembetalálkoznom kb úgy kezdődött mint minden szokásos "ÚR ISTEN, SECURITY HOLE!!!!" jellegű felkiáltás:
Az IBM által hivatalosan elérhetővé tett sudo 1.6.9p23-as szinten van, viszont pár napja felütötte a fejét egy olyan hiba, ami ezt a verziót is érinti, a customer meg persze az ilyeneket olvasva sikoltozva kiabálja, hogy azonnal tedd fel a javítást. A probléma persze csak az, hogy a hivatalos IBM-es csomag nem elérhető, ergo hivatalos javítást nem tudsz feltenni, ha akarsz se. Customer-t ez persze nem hatja meg, a sudo amúgy sem IBM product, forgass egyet magadtól, az annyira amúgy se nehéz..

Így is lett. Az ember forgat magának 1.7.9es csomagot (hivatalos IBM support innentől sudo-t ne akarjon supportolni :)), customer örül, And so once again the day is saved. Murphy persze hogy erre az alkalomra vár és bedobja az "I don't think so" kártyáját, aztán az admin már meg se lepődik, amikor a customer ismét telefonál, hogy "Őőő.. ez most miért nem megy"? *sigh*

A történet kb az alábbi: Az 1.7.9es sudo óta bejött AIX alatt egy regresszió az alábbi change miatt:
- If none of the standard input, output or error are connected to a tty device, sudo will now check its parent's standard input, output or error for the tty name on systems with /proc and BSD systems that support the KERN_PROC_PID sysctl. This allows tty-based tickets to work properly even when, e.g. standard input, output and error are redirected to /dev/null.

Ez AIX alatt kb úgy néz ki, hogy amennyiben nincs tty device-od a sudo hívásakkor, úgy pityiszt kapsz az orrodra, nemhogy lefutott parancsot.. Persze az ember valami hibaüzenet féleséget várna minimum, de a sudo-val meghívott process ez helyett szimplán csak hang-el, és nem csinál semmit.. Ez persze kifejezetten kellemetlen amikor a customer által futtatott rendszer egy DB2 osztott cluster, ami rah parancsokat használva szeretne a node-okkal kommunikálni, ami persze hogy tty nélküli kulcs alapú ssh chanelleket használ(na), így nem csoda ha a rah parancs is beáll, mint a gerely.

Mondanom se kell, hogy az ember ilyenkor mennyire fel van dobva, és már a telefonálás pillanatában elönti az adrenalin, és a tettvágy, hogy egy ilyen kaliberű hibát kinyomozzon anélkül hogy tudná mit és hol keressen :)
Röviden: pár óra kellemes orális szerelmeskedés (értsd: szopás) után megvan, hogy valószínű az új sudo a hibás, visszarakod a régit, és láss csodát, minden megy ahogy kéne..
Csak a rendszered lett megint non-compliant, tehát amit nyertél a réven, azt veszted a vámon, mert valahogy csak meg kell nézni, hogy mi a fene okozza ezt a hibát..

Újabb kellemes órák, újabb kellemes tesztelgetés, sudo.c turkálás, és hasonló jóságok után az ember eljut oda, hogy a hiba tényleg az 1.7.9ben jött be ( 1.7.8p1en még minden szépen megy), és ha a tty kezelési részt kicsit visszapiszkálja, akkor megy is minden szépen:
devel_box@root:/ # diff /tmp/sudo-src/sudo-1.7.9.gabor/sudo.c /tmp/sudo-src/sudo-1.7.9/sudo.c
628,631c628,630
<
<     if ((p = ttyname(STDIN_FILENO)) || (p = ttyname(STDOUT_FILENO)) ||
<         (p = ttyname(STDERR_FILENO))) {
<         user_tty = user_ttypath = estrdup(p);
---
>
>     if ((p = get_process_ttyname()) != NULL) {
>       user_tty = user_ttypath = p;
Oks.. akkor most már bizonyított: software bug.. nyissunk rá ticketet, aztán a fejlesztő majd megszakérti mi is a probléma -> Bug #557 a sudo-s bugtrackerben, megidézlek!

S lőn fél napon belül megvilágosodás: Valóban regressziót találtunk, sőt régebben már más is jelentette ezt a problémát, csak nem az 1.7-es, hanem az 1.8as szériához. Külön öröm, hogy a következő 1.7.10es verzióban már ez is javítva lesz, sőt, már a béta el is érhető, úgy hogy akinek ilyen igényei vannak, az használhatja azt..

A customer meg döntse el, hogy mit és hogy is akar ezek után :) Aki meg hasonlóval szív, az tegye vissza a régit, vagy használjon béta release-t, amíg az új ki nem jön :)

2012. május 6., vasárnap

Murphy és a "jó" design

Elég mozgalmas volt ez az április, így nem sok időm volt blogolni bármiről is, de azért egy "emlékezetes" issue úgy érzem megérdemel annyit, hogy megmaradjon az utókornak.

Hol volt, hol nem volt (az óperenciás rendszeren is túl) volt egy szerver, aminek a design-ját okos emberek kialakították, és megítélendék jónak. Persze az okos emberek teljesen másra szánták a gépet mint amire azt később a customer nevű állatfaj elképzelte. Így alakulnak ki a természetben az olyan félvér állatfajok, amik inkább csak a hibáikkal tűnnek ki, mint sem a használhatóságukkal, és tuti biztos, hogy a lelkes adminisztrátorok előbb utóbb rájönnek, hogy az ilyen szerverek is inkább csak elrettentő példának jók, min tsem produktív dolgok futtatására, de hát a customert ez a legkisebb mértékben se szokta érdekelni, neki csak az a fontos, hogy az über-fontos dolgok menjenek a gépen..

Na most.. Ha még vannak olvasók akik nálam jobb emlékezettel vannak megáldva, akkor nekik lehet dereng valami a múltból, amikor a design hibákat ecsetelgettem, és már akkor is elmondtam, hogy az adott architect-nek jó rejszolást kívánok egy sajtreszelő társaságában, hogy ezt a design-t képes volt megálmodni

Hogy, hogy nem, most Áprilisban jött el az ideje annak, hogy Murphy ismét szórakozni akarjon, és kitalálta, hogy ez az igen fontos gép amúgy is billeg a szakadék szélén, hát miért ne lökjön rajta egy kicsit.. Persze ha már ott van, akkor a mentőalakulatok útjába is felállít 1-2 csapdát, mert az úgy még is csak nagyobb a FUN faktor.

A valóságban mindez a következőképp realizálódott:
Első körben a fenti design-ban szereplő RAID 5 tömb alól 2 diszk úgy gondolta, hogy őt már nem becsülik meg eléggé, így Seppuku-t hajt végre. "Mázlira" csak az Egyik diszk volt aktív, a másik csak Hotspare, így elméletben még itt nem kéne nagy problémának lennie. Így hát új diszk beszerez, hotplug manager elő, aztán cseréljük on-the-fly a temetőbe szánt Hotplug diszket, ahogy az a nagykönyvben is meg van írva.

Sajna azonban a Nagykönyvekkel mindig az a baj, hogy az emberek elfogadják a benne leírtakat egyfajta axiómának, ami -ha Murphy is a képben van- általában nem teljesen szokta lefedni a valóságot: Így hát persze így se minden úgy működött ahogy kellett volna.. Történt ugyan is, hogy a teljesen szabályosan kicserélt új diszket a rendszer nem volt képes lekezelni, mivel a régi konnekciós azonosítót valamiért nem akarta felszámolni.
Hogy szemléletesebb legyen a dolog, kb ezt látja a szerencsétlen adminisztrátor:
# sissasraidmgr -L -j1 -l sissas5
------------------------------------------------------------------------
Name      Resource  State       Description              Size                  
------------------------------------------------------------------------
sissas5   FFFFFFFF  Primary     PCI-X266 Ext Tri-x4 3Gb SAS RAID Adapter
 sissas6  00000000  AWC linked  Redundant cache protection for sissas5  

hdisk3    00FF0000  Degraded    RAID 5 Array            1135GB                 
 pdisk0   00000200  Failed      Array Member           283.8GB                 
 pdisk1   00000300  Active      Array Member           283.8GB                 
 pdisk3   00000500  Active      Array Member           283.8GB                 
 pdisk2   00000400  Active      Array Member           283.8GB                 
 pdisk4   00000600  Active      Array Member           283.8GB                 

*unknwn*  00000700  RWProtected Array Candidate            N/A                 
pdisk5    00000700  Missing     Disk                   283.8GB
Na szóval.. Vagy egy hdisk3 néven létező RAID 5 tömbünk, ami épp Degrad állapotban leledzik, mindez a sissas5 adapteren. Van 2 halott diszkünk (pdisk0,pdisk5), ami közül pdisk5-öt igyekszünk épp kicserélni, ami jelenleg épp Missing státuszban leledzik. A pdisk5 kapcsolati címén (00000700) azonban van még egy diszk, ami épp RWProtected, amúgy meg unknown (tehát a rendszer nem tud róla semmit). Így meg persze még neki se lehet állni új Hotspare-t definiálni (hogy aztán azt majd bedobjuk a pdisk0 helyére)

Na ez az a rész, amiről a nagykönyv nem ír semmit (Murphy viszont a Pop-corn egy részét már elfogyasztotta).. Ergo akkor nincs más, csak kidobni a vak hitet, és menni az ember saját feje után.
Első körben az előzőleg kicserélt diszk-et kivéve a slotból lehetőség nyílt az unknown device "elvesztésére" ám a rendszer pofátlan módon ragaszkodott a pdisk5 jelenlétéhez, attól függetlenül, hogy az már közel, s távol nem volt a gépben. Külön poénként ezt a meggyőződését még akkor se volt hajlandó elfelejteni amikor a pdisk5-öt 'rmdev -dl'-el lelőttem, majd a config managert (cfgmgr) futtattam, mivelhogy az rendkívül ragaszkodóan visszahozta a pdisk5-öt "Available" státuszban (a RAID vezérlő persze még mindig Missing-nek látta).

Na akkor itt álljunk meg egy picit.. Felmerül a kérdés -gondolom- az olvasóban, hogy biztosan a jó diszk lett kihúzva? Igen, ez volt az első felmerülő kérdés bennem is, de többszöri vizsgálat után is csak az jött ki, hogy valóban a jó diszket piszkálom és az AIX (VIO, de a lényegen semmit nem változtat) az aki foggal körömmel ragaszkodik ahhoz a diszkhez.

Fejvakarás, cseresznyefák, és wattafák.. Avagy csak fák.. Kinek mi esik jól.. Murphy közben a Pop-corn mellett már elindította a háttérben a Kokaku Kidotai (Ghost in the Shell) OST-t is, mert ehhez a jelenethez ez illik a legjobban..

Adminisztrátor részről persze teljes értetlenség, keresés, látott e már valaki valami ilyesmit? Aztán szembejön ez a bug, és fény gyúlik a katakombákban : IZ72353 - SAS PDISK DISPLAYED AS *UNKNWN* AFTER REPLACE/REBUILD APPLIES TO AIX 6100-03

Jah hogy úgy... Hát úgy.. A gáz csak annyi, hogy a patch magában nem elérhető (mivel VIO-ról beszélünk, így csak VIO frissítéssel együtt oldható meg a csótányirtás), így (mivel már mindenki a hátunk mögött van, és a messzeségben már a mesterlövészek is a mi monitorunkat lesik a fejünk mellett) a leggyorsabb megoldás a restart marad. Persze előtte minden kliens azonnal állj, addig a VIO se mozduljon semerre..

Restart, öröm és boduttá.. A pdisk5 végre defined-ban jön fel, sőt az újonnan beletett vinyót is már látja a rendszer.. Sínen vagyunk mint József Attila..
HotPlug diszk megformáz 528 Byte Szektor mérettel, majd a pdisk0 kipöccintése után nyomban be is áll a helyére az immár hamvaiból feltámadt pdisk5 Főnix madár, indulhat az Array Rebuild, semmi ok a pánikra, minden a Ctrl billentyű alatt van

Hátradőlünk, és szépen várjuk, hogy a tömb újjáépítése befejeződjön. A háttérben viszont Murphy ráadást követel, így hát újabb szám zendül fel a hangszórókból.

A moziban ilyenkor kezdenének el villogni a piros villogók, felharsognának a szirénák, és valami kis rangú emberke kétségbe esve megszólalna, hogy "Sir, Something is wrong!" (Thank you, Caption obvious). A valóságban azonban az embert csak egy ilyen hibaüzenet fogadja a fekete putty ablak mögött:
# sissasraidmgr -L -j1 -l sissas5
------------------------------------------------------------------------
Name      Resource  State       Description              Size                  
------------------------------------------------------------------------
sissas5   FFFFFFFF  Primary     PCI-X266 Ext Tri-x4 3Gb SAS RAID Adapter
 sissas6  00000000  AWC linked  Redundant cache protection for sissas5  

hdisk3    00FF0000  Failed      RAID 5 Array            1135GB Rebuild Failed 04
 pdisk5   00000700  Failed      Array Member           283.8GB                 
 pdisk4   00000600  RWProtected Array Member           283.8GB                 
 pdisk3   00000500  RWProtected Array Member           283.8GB                 
 pdisk2   00000400  RWProtected Array Member           283.8GB                 
 pdisk1   00000300  Failed      Array Member           283.8GB                 

pdisk0    00000200  RWProtected Array Candidate        283.8GB

Őőő.. 'nyádat... Újratervezés..
- A pdisk5 most lett kicserélve, leformázva, leellenőrizve, így az garantáltan nem lehet halott (hacsak nem a vezérlő halt meg, de akkor már az ima is édeskevés lesz)
- A pdisk1re eddig nem jött egy hibajelentés se, így azt vessük górcső alá.
- Az errpt entry-jeit elnézegetve (54E8A127 error code (DEVICE OR MEDIA ERROR), ha valakit érdekel) az összes hibajegy a pdisk1-el megegyező Serial ID-ra jön, így tételezzük fel, hogy a pdisk5 Failed státusza az újraépítés során tapasztalt pdisk1 hibájának mellékhatása csak.

Ezzel viszont egy újabb probléma üti fel a fejét: A RAID5 tömb egyszerre csak 1 aktív diszk halált bír ki, kettőt már nem. Amennyiben a pdisk1-et is ki kell cserélni, akkor kalap,kabát, búcsút lehet mondani az adatainknak, mert 3 diszkből már nem engedi a vezérlő se helyreállítani a tömböt (Én megpróbáltam, de hát ez nem linux).
Egy mázli volt - amennyiben az ember újraindítja ebben a fázisban a VIO-t, akkor a SAS RAID vezérlő újra megpróbálja a tömböt össze-eszkábálni, ami viszont kitűnő alkalmat teremt arra, hogy az ember megpróbálja menteni ami menthető.

És itt most álljunk meg ismét egy pillanatra.
- Adott egy fél lábbal már a sírban lévő RAID5 tömb
- A tömbön lévő adatok egy része már garantáltan nem elérhető, tehát a disaster recovery elkerülhetetlen (ugye van disaster recovery plan? :) Megsúgom, az ilyen rendszereknél rendszerint nincs.. Itt a remek alkalom, hogy most fejben összeüss egyet, és imádkozz, hogy az a minimális backup process ami eddig volt elégséges legyen :D )
- Ha mindenképpen kell DR, akkor minek akarok én menteni bármit is?

Nos, a válasz némileg komikus: Az egyik kliens egy Linux rendszer (SLES 10), amely system VG-je 1 VIO-n található LV-re lett ráhúzva (az LVM kell, ha az ember normálisan akarja skálázni a meglévő erőforrásokat, szóval ez még érthető is). Ahhoz, hogy ezt visszaimádkozzuk 3 út maradt:
- Csinálni egy low level mentést byte szinten a "Guest" System VG-jét tartalmazó PV-ről (azaz a VIO-n lévő LV-ről) valahova a RAID tömbön kívűl, és azt megpróbálni visszatölteni amint az új RAID tömbünket kénytelenek voltunk újra kreálni
- Csinálni egy FS szintű backupot (SLES gyárilag tud ilyet), a RAID tömb 0ról való építése után pedig felhúzni egy alap SLES rendszert, és arra visszatölteni az itt készült backup-ot
- Megpróbálni csinálni egy bootolható ISO file-t, azt odaadni a VIO-nak, majd mint CD/DVD-t kiallokálni a kliens felé, és arról visszatölteni az adatokat (Standard Linux környezetben ez szépen megy is, de amúgy vannak direkt erre a célra elkészített programok is, mint pl a Mondo Rescue)

A baj csak az volt, hogy mind3 út buktatókkal volt kikövezve:
- Bootolható ISO készítés: Az elmélet jó, de az egyik verzióban fel kéne raknom a Mondo Rescue (vagy azzal egyenértékű) progit, ami sajna PPC-re nem elérhető. A Debian féle módszer még működne is, de sajna a pSeries gépeken a boot loader nem grub, hanem Yaboot, ami meg nyomban úgy kezdi, hogy külön FAT16 típusú partíció neki, ami az ISO image-em szempontjából így nem járható.
- Az FS szintű backup azért necces, mert egy teljesen új rendszer felinstallálása szükséges hozzá, ami meg iszonyat nagy macera.
- A low-level (dd) szintű backup tűnt a legjobbnak (és akkor még az LVM struktúra is megmarad), ám amennyiben a RAID5 tömb ezen belül hibásodott meg, akkor meg megint ott vagyok ahol a part szakad..

Nem volt mit tenni: Úgy döntöttem, hogy amit lehet menteni kell (lehetőleg minél többféle képen), mivel a jelenlegi állapotot tutira újra is kell építeni. Tehát csináltam egy dd szintű mentést (LPAR lekapcsolva természetesen), meg egy FS szintűt is, felkészülve a legrosszabbra (az applikációs adatokért nem tudtam semmit se tenni, azt majd remélhetőleg a standard backup process által készített backup lefedi az adat visszaállítás során)

Ez után jött a másik 2 diszk cseréje (pdisk0, pdisk1), majd a halott RAID tömb törlése, és egy új készítése. Mindeközben sűrű miatyánk Mekka irányába..
Amint az új RAID tömb elkészült (immár hiba nélkül) lehetett visszahozni a régi LVM struktúrát, majd nekilendülni az adat visszaállításnak..
És igen.. Mázlim volt.. nettó 40 perc alatt a ~100 GB-os system VG-ről készített dd backup visszatöltődött (yaboot-al együtt), és az LPAR képes volt felbootolni (igaz RC 2ig nem jutott el, de ezen már lehetett segíteni), ergo már csak a tényleges applikációs adatok visszatöltése maradt vissza (meglepő módon azok visszatöltése közben nem nagyon akadt probléma)

Tapasztalatok a jövőre nézve:
- Ha tényleg über fontos adatról/alkalmazásról beszélünk, akkor erőltessük már meg magunkat, és a környezetet tényleg redundánsan alakítsuk már ki
- A RAID 5 addig jó, amíg kevés diszk van alatta. A tömb növekedésével együtt növekszik a teljes tömb meghalásának esélye is (mivel nagyobb az esélye, hogy 1 időn belül 2 aktív diszk hal ki, ahogy itt is történt (nagy eséllyel a használt diszkek ugyan abból a sorozatból valóak, ergo közel ugyan annyi idő alatt is halnak meg))
- Disaster recovery plan még akkor se árt ha van, ha amúgy a rendszer nem indokolja azt meg. A probléma a jelen setuppal az, hogy nem nagyon lehet rá 100%-os plan-t készíteni (ami effektíven használható lenne), a bootolható backup hiánya miatt (személyes véleményem szerint SLES pSeries-re nem való)
- Nagykönyv lehet, hogy létezik, de inkább tekintsünk rá amolyan "Kalóz Kódexként" ami inkább csak útmutatás, mintsem sérthetetlen szabály.. Valami úgy is valamikor el fog romlani, amire persze hogy nem leszünk felkészülve
- A szokásos halandzsa - update, update, update. Tudom, hogy az überfontos applikáció überfontos uptime-al kell üzemeljen, de kalkuláljunk már maintenance window-t is a rendszerhez, hogy az ilyen hülye önszopatásoktól megkíméljük magunkat.
- Murphy sose alszik, és mindig pörgős zenét hallgat :)

2012. április 8., vasárnap

AIX 5.3 + WAS 6.0, Round #2 - Avagy miért is lenne fontos a doksikat karban tartani...

Bő fél éve blogoltam a IV07564-es bogárkáról, ami hajlamos a WAS6.0 adminok életét megkeseríteni. Azóta ugye jó sok idő eltelt, így az ember azt hinné, hogy ezt az issue-t is le lehet zárni. Főként mert a bug az AIX 5.3 TL12 SP05ben már elvileg javítva van.

Mint ahogy a hivatalos doksik is írják (IV07564, Java application hang after applying AIX maintenance) a hiba csak a 5.3.12.1-es szinten lévő bos.rte.libpthreads-et érinti, és mivel az 5.3 TL12 SP05-ben már a 5.3.12.2-es van, így lelki nyugalommal mondhatjuk, hogy igen, ez a hiba már tényleg nem fenyegeti a WAS6 rendszereket futtatók életét..

A valóság sajnos az, hogy holott minden a fentiek mellett szól, a gyakorlat még is csak a makacs tényeket részesíti előnyben. Hogy megértsük hol vált külön az elmélet a gyakorlattól, nézzük át kicsit ennek a bugnak az életét (illetve azt is ami nem egészen van dokumentálva). Mázlira a file nevek meglehetősen beszédesek:

IV07564s03 - IV07564s03.111005.epkg.Z
Ez alapján ez a file még 2011.10.05.-én kijött (Anno még én is ezt a verziót töltöttem le). A fixbe belekukkantva az alábbi Abstract-ot találjuk az ecfile-ban: "Ifix for apar IV07564 at 53X SP04."

IV07564s04 - IV07564s04.111005.epkg.Z
Hibajavítás az előző verzióra. A filenév alapján ugyan azon a napon kreálták. A fix-be belenézve az Abstract is azonos (fix for apar IV07564 at 53X SP04.)

IV07564s05 - IV07564s05.111107.epkg.Z
Na innen indul a buli. Az ecfile-ban itt már a "Ifix for apar IV07564 at 53X SP05." leírást olvashatjuk, ami azt jelenti, hogy ez a fix már az SP5-re lett kihozva. A filenév alapján ezt a fix-et 2011.11.07.-én készítették

A probléma ott kezdődik, hogy a hivatalos doksik - amik erre a bugra mutatnak - nem követték a folt fejlesztéseinek változásait:

Java application hang after applying AIX maintenance - Modified date: 2011-10-27
IV07564: HANG IN _EVENT_NOTIFY(). - Modified date: 2011-12-09

- Az elsőnél egyértelműen látszódik, hogy a doksi leragadt a IV07564s03/IV07564s04(?)-es fixnél, így aki az alapján próbál információt szerezni alapból megszívta.
- A másodiknál látszik, hogy valaki Dec 09.-én módosított valamit, de ha megnézzük a letöltési helyre mutató linket (ftp://public.dhe.ibm.com/aix/efixes/iv07564/) nyomban láthatjuk, hogy a file feltöltési dátuma azonos, így gondolom csak egy új lokációt adtak meg a file számára, de elfelejtették a doksi többi részét frissíteni

A vicc az, hogy az ember a turpisságra csak akkor jön rá, ha ténylegesen bele is néz a fixbe és az ecfile-t végigbogozva rájön, hogy ...
- A doksik nem up-to-date-ek
- Az 5.3 TL12 SP5 is érintett a problémában
- A 6.0-ás WAS rendszerek lehet pont ezért hullanak mint a legyek 5.3 alatt (Azt azért hozzá kell persze tenni, hogy a 6.0-ás WAS Supportja 2010 Szeptember 30.-án lejárt így ne csodálkozzanak azok akik outdated SW esetén inkompatibilitást tapasztalnak )
- Ezt lehet le kéne blogolni, hogy más ne szívjon vele annyit :)

For the record - Az eredeti blogbejegyzésemben szóltam, hogy AIX 6.1 is érintett - ott ezeket az APARokat tessék keresni
AIX 6.1 TL07 - IV09681
AIX 6.1 TL06 - IV08153
AIX 6.1 TL05 - IV07839

# Megjegyzem, hogy a 6.1-es AIX-hez kiadott javításokat nem tudtam átnézni, így a hiba ott is fenn álhat (bár az announcement-ek modification date-je azért ad némi bizalomra okot)

2012. március 3., szombat

Élménybeszámoló - Molylepke vadászat.

Noh. Eljött ez a nap is.. Végre ez a bug vadászat is lezárult, és hivatalos ticket is nyílt róla, így most már írhatok kicsit a részletekről..

A történet ott kezdődött amikor is az egyik HACMP clusterünk failover közben mondhatni "totál beakadt" -> A Resource group-ban (RG) definiált összes resource-t leadta a primary node, a secondary is elkezdte szépen átvenni, illetve az RG is szépen átment, de a folyamat során egy nem várt esemény is előjött: A primary node ez után teljesen elérhetetlen lett. Nézzük hirtelen mit is próbál az ember amikor ilyennel találkozik:
- Nyissunk újabb SSH kapcsolatot a gépre, hátha az előző megszakadt - No response...
- Oks.. elérhető a gép? Nézzünk rá egy ping tesztet - no ping reply.. (előtte volt)
- Jó.. Nézzünk be HMC-re. Az LPAR állapota "running". Tehát elvileg az LPAR megy.. De akkor meg mi a fene?
- Hátha csak a hálózat nyekkent meg. Menjünk be soros terminálról (vterm) - Semmi nem történik.

Ilyenkor ül ki az ember a kertbe, és elkezdi nagy, kikerekedett szemmel nézni a wattafákat, és azon filózni, hogy mikor szüretelheti le majd a fáról a vattát..

Összefoglalva: Az OS se előre, se hátra, az LPAR fut.. Nincs mit tenni.. Indítsuk újra a teljes LPAR-t.
Gép újraindul, log túrás.. Semmi, ami alapján el lehetne indulni.. Jó.. Akkor nézzük meg, hogy egyáltalán tudom e reprodukálni az esetet..
RG visszarak a primary node-ra (szépen visszamegy), majd újabb failover a primary-ról a secondary-re.. Ugyan az.. De legalább tudom, hogy reprodukálható az issue, ami azért sokkal jobb, mintha valami szellemet kéne kergetnem. Mázlimra a gépen szabadon lehetett egy ideig garázdálkodni, így kedvem szerint tesztelgethettem.

Kezdés képen szerettem volna kideríteni, hogy az RG-ben lévő applikációk okozzák e a problémát, vagy mélyebben kell keresgélni. Így fogtam magam, és a HACMP-ben definiált start/stop scripteket ideiglenesen kisöpörtem a színről (így csak a diszkek, LV-k, FS-ek, mount pointok, meg a service IP maradt) és megnéztem így is összeszakad e a gép.. Hát össze..

Jó, akkor nézzük tovább.. Következő ötletem az volt, hogy akkor ráengedek egy trace-t a gépre, úgy futtatok egy ilyen lecsupaszított failover-t, és akkor hátha észreveszem, hogy hol akad meg.. Sajna ez se nyert, mert amint a gép összerogyott a memóriában lévő trace bejegyzések se kerültek kiírásra, így a trace-em teljesen hiányos volt, és csak a standard folyamatok voltak benne, amit amúgy is vár az ember.

1-2 felesleges kísérlet után eljutottam addig, hogy mivel a hálózatom egy idő után úgy is elmegy, így azon keresztül felesleges bármit nézzek, mert simán előfordulhat, hogy a hálózat megszűnése után még a gép csinál valamit a háttérben. Tehát bejelentkeztem virtuális terminálon keresztül (mondván, hogy ami ott van azt csak látnom kell), és úgy elkezdtem monitorozni, hogy a gép meddig jut.. Furcsa mód a HA (illetve az OS) az alábbi parancs után dőlt le:

ifconfig en2 delete ${HACMP_MANAGED_SERVICE_IP_ADDRESS}

Kicsit furcsálltam a dolgot, de gondoltam üsse kutya, mit veszíthetek, ha ezt a lehetőséget is megnézem. Gép újraindul, HA RG ismét a helyére, majd csodálkozva konstatáltam, hogy a fenti parancs futtatásával a gép tényleg ugyan úgy bedől, annak rendje és módja szerint..

Ez egy részről jót jelentett, mert innentől tudtam, hogy a HACMP-nek köze nincs az issue-hoz, más részről viszont bajban voltam, mert az ifconfig-nak ilyet elméletileg még véletlenül se kéne okoznia (az tuti, hogy ezt semmiféle dokumentációban nem említik :))

Ez volt az a pont amikor ez már software call-ért kiáltott.. Tehát hivatalosan is jelentettem a hibát az IBM-es fejlesztők felé, hogy akkor kérem ennek tessék utánanézni. A kezdeti adminisztrációs útvesztőkön, és issue leírás+hiba bizonyítás után aztán a hivatalos IBM supportal eljutottunk addig, hogy itt valami tényleg nem kóser. Első körben ők már egy full system dump-ot kértek tőlem -az után, hogy a gép összecsuklott- hogy megnézzék, hogy a memóriában mi van. Azt analizálva aztán kijött, hogy az összes LPAR-hoz assignolt processzor szál LOCK állapotban van, tehát nem mozdul senki semerre..

Ez persze megmagyarázza, hogy a gép ez után miért nem csinált semmit, de azt nem, hogy hogy jutott el eddig az állapotig. A következő lépésként a fejlesztők küldtek nekem egy kissé átberhelt kernelt, amiben az elérhető összes debug opciót bekapcsolták, hogy aztán az a memóriában (és így a dumpban) is könnyebben követhető legyen.

Az új kernelt életbe léptetve (majd a gépet ismételten megakasztva) immár látható volt, hogy routing lock ált be, tehát kernel szinten volt valami megkergülve. Ez már elég volt a fejlesztőknek, hogy megfelelően e tudják szűkíteni a lehetséges problémák forrását, és ki tudják ténylegesen debugolni, hogy honnan is ered a hiba.

Rövidesen meg is született az eredmény - "A" patch. Megkaptam, telepítettem, és csodák csodájára működött.. Öröm és bóduttá.. Na jó.. Nem teljesen.. Volt még 1-2 dolog amit meg kellett oldani.
-> A patch csak AIX 5.3 TL12 SP04 alá készült el. Sajna a latest SP 05ön állt, és ezen a rendszeren is hamarosan telepíteni kellett, ám mint kiderült az SP05 is érintett volt az issue kapcsán. Sőt mi több, a 6.1es AIX is (TL07,SP2 a latest). Így arra kértem a fejlesztőket, hogy a hivatalos úton olvasszák be ezt a patch-et az érintett AIX verziókba, hogy aztán a következő TL/SP-kben már benne is lehessen.

Így született aztán meg a IV16037-es patch (IBM ID szükséges a megtekintéséhez)

Ha ne adj isten valaki más is hasonló problémákba ütközik a közeljövőben (amíg a fix nem lesz elérhető hivatalosan), akkor némi kis segítség a gyors probléma megoldáshoz:
- teljes system dump force-olása a HMC-ről restartal egybekötve
- Dump analízis kdb-vel. A stack nálam így nézett ki:
pvthread+031300 STACK:
[0000932C].unlock_enable_mem+000020 ()
[00204F50]rt_setgate+0001F8 (??, ??, ??)
[043D6A08]in_ifscrub+000488 (??, ??)
[043D8050]in_control+0009A8 (??, ??, ??, ??)
[04436B38]udp_usrreq+000214 (??, ??, ??, ??, ??)
[0020E7F4]ifioctl+00075C (??, ??, ??)
[0025FDFC]soo_ioctl+000494 (??, ??, ??)
[004A8968]common_ioctl+0000C0 (??, ??, ??, ??)
[00003810].svc_instr+000110 ()
[kdb_get_memory] no real storage @ 2FF22390
[D03B1D14]D03B1D14 ()
- Ha ilyesmi, vagy a ticketben leírthoz hasonló stack-el találkozol, nyiss egy SW call-t az IBM felé, és hivatkozz a fenti fix-re.
- Ők persze ugyan úgy el fogják kérni a dump-ot, hogy megbizonyosodjanak róla, hogy a 2 eset valóban 1 tőről származik e. Ha úgy találják, hogy igen, akkor elérhetővé teszik számodra a patch-et.

2012. február 14., kedd

fuser - némileg másként

A múltkor blogbejegyzés után kedvet kaptam némi kis turkászásban a kernel térben, úgy hogy íme egy újabb szösszenet arról, hogy a rendszernek mit is kell csinálnia amikor mi csak úgy dobálózunk a parancsokkal :)

Na szóval.. A mostani alkalomra a fuser nevű parancsot néztem ki magamnak.. Sokat nem kell róla mondani: Általános ismérve, hogy ha egy FS nyitva van, akkor ezt szoktuk meghívni, hogy megnézzük mi is fogja. Nézzük, hogy ezt a funkciót a kernel térből hogy is lehetne elérni:

Első körben kell nekünk egy mount point.. Az én esetemben ez a /opt/IBM lesz, mert miért ne :)

Első körben a kontroll teszt: Nézzük, hogy a rendszer mit is tud róla:
test_server@root:/ # fuser -cux /opt/IBM
/opt/IBM:  1130574c(root) 1253494c(root)
Szupi.. Na akkor nézzük ugyan ezt a kernel térben. A módszer az alábbi dióhéjban:
- Meg kell keresni az adott mount point memória pointerjét
- Ezt a pointert használva megnézni az elérhető I-node bejegyzések pointereit, majd leválogatni amire van bármiféle hivatkozás
- A leválogatott hivatkozásokat alapul véve meg kell nézni, hogy melyiknek mi a Gnode (generic node structure) szegmense
- Ezen segmensekből már le tudjuk válogatni, hogy melyiknek milyen thread a szülője, amiből meg direkt megtalálhatjuk a thread-hez rendelt PID-et.

A valóságban:
Első körben ugye a mount-hoz tartozó cím kell. Annyi probléma van, hogy a mount-ot kikérve ilyen összevisszaságot kapunk:
(0)> mount
                           GFS             DATA TYPE    FLAGS
  1 F10001001D6868B0 014D4D60 F1000100206D2080 JFS2    DEVMOUNT
... /dev/hd4 mounted over /
  2 F10001001D686950 014D4D60 F1000100206A4480 JFS2    DEVMOUNT
... /dev/hd2 mounted over /usr
  3 F10001001D6869F0 014D4D60 F1000100206FB080 JFS2    DEVMOUNT
... /dev/hd9var mounted over /var
  4 F10001001D686810 014D4D60 F1000100206FC880 JFS2    DEVMOUNT
... /dev/hd3 mounted over /tmp
És így tovább.. Ez persze felvet 2 gondot:
- Komolyan végig kell mindent böngésszek, úgy hogy közben kifolyik a szemem?
- Miért nem lehet ezt 1 sorban kirakni, hogy legalább greppelni lehessen rá?

Persze azért annyira mégse rossz a helyzet, csak kicsit bűvészkedni kell az awk-al, és nyomban meglesz az ami nekünk kell:
(0)> mount |awk '{a[NR]=$0} /\/opt\/IBM$/ {print a[NR],a[NR-1]}'
... /dev/IBMlv mounted over /opt/IBM  14 F100010020684550 014D4D60 F1000100226C2C80 JFS2    DEVMOUNT

Ugye hogy így szebb.. Na szóval megvan a pointerünk (F100010020684550). Akkor kérjük le milyen i-node bejegyzések vannak alatta:
(0)> mount F100010020684550 |grep -E "DIR|REG|SOCK" |tail -5
 648 F1000100241643E8     0 F1000100241640B0 F100010020684550 DIR
 649 F1000100240E03E8     0 F1000100240E00B0 F100010020684550 DIR
 650 F100010024092FE8     1 F100010024092CB0 F100010020684550 REG
 651 F10001002411B7E8     2 F10001002411B4B0 F100010020684550 DIR
 652 F1000100226D2FE8     1 F1000100226D2CB0 F100010020684550 DIR  ROOT
Na itt egy újabb probléma.. Mi ez a sok szám, és mit jelentenek? Nos A válasz a következő:
- Az első és második oszlop lényegében ugyan azt takarja. Az első az index-szám, a második pedig a VFS_VNODE pointer.
- A 3. szám egy úgy nevezett counter. Ez mutatja, hogy hány kernel thread használja éppen az adott VFS_VNODE-ot.
- A 4. lesz a VFS_VNODE-hoz tartozó GNODE.
- Az 5.-et most bocs de kihagyom, mert érdektelen jelen szempontból

Ami nekünk ezek közül kell, az azok a GNODE regiszterek, amelyeknek COUNT-ja nagyobb mint 0. Ezt kb az alábbi scriptelési módszerrel tudjuk előhozni:
(0)> mount F100010020684550|grep -E "DIR|REG|SOCK" |awk ' { if ($3 != "0") print }'
 154 F100010036F6A3E8     1 F100010036F6A0B0 F100010020684550 REG
 157 F100010036F3A3E8     1 F100010036F3A0B0 F100010020684550 REG
 160 F100010036F99FE8     1 F100010036F99CB0 F100010020684550 REG
 163 F100010036F69FE8     1 F100010036F69CB0 F100010020684550 REG
 266 F100010036FA6FE8     1 F100010036FA6CB0 F100010020684550 REG
 556 F1000100244D2FE8     1 F1000100244D2CB0 F100010020684550 REG
 557 F1000100243B57E8     1 F1000100243B54B0 F100010020684550 REG
 558 F1000100244CC3E8     1 F1000100244CC0B0 F100010020684550 REG
 559 F1000100244EBBE8     1 F1000100244EB8B0 F100010020684550 REG
 560 F1000100243B0BE8     1 F1000100243B08B0 F100010020684550 REG
 561 F1000100244CB7E8     1 F1000100244CB4B0 F100010020684550 REG
 562 F1000100244A93E8     1 F1000100244A90B0 F100010020684550 REG
 563 F1000100244C8BE8     1 F1000100244C88B0 F100010020684550 REG
 652 F1000100226D2FE8     1 F1000100226D2CB0 F100010020684550 DIR  ROOT

Egy baj van - Ez a lista helyenként iszonyat nagy.. Itt se épp rövid.. A problémám meg az, hogy az itt található GNODE ID-kat kéne mind végigjárjam az alábbi módon:
(0)> gnode F1000100243B08B0 |grep gn_seg
gn_seg........ 00000000000086A6
(0)> scb 2 00000000000086A6 |grep pvproc
pvproc pointer           (pvproc)   : 0000000000000000

(0)> gnode F1000100244C88B0 |grep gn_seg
gn_seg........ 00000000000246AD
(0)> scb 2 00000000000246AD |grep pvproc
pvproc pointer           (pvproc)   : 0000000000000000

(0)> gnode F100010036F99CB0 |grep gn_seg
gn_seg........ 00000000000732D8
(0)> scb 2 00000000000732D8 |grep pvproc
pvproc pointer           (pvproc)   : F100070F00045000
3.-ra csak ráhibáztam az egyikre, de persze ezt így egyesével végigjátszani valami halál.. Mindenesetre ha megvan a pvproc cím, akkor abból már az egyik process-t meg is találhatjuk:
(0)> proc F100070F00045000 |grep ^pvproc
pvproc+045000  276 java     ACTIVE 011404E 0132076 0000000030588400   0 0013
(0)> hcal 011404E
Value hexa: 0011404E          Value decimal: 1130574
Bingo.. 1130574 az egyik PID amint fentebb is láttunk.. Na de akkor hogy is lehet ezt normálisan végignézni, úgy hogy az összes GNODE ID-t végigjátsszuk? Hát, a szomorú hír, hogy a kdb nem tud belső scriptelést, így a shell-re kell támaszkodjunk, ami meg egy részről iszonyat erőforrás zabáló, más részről meg a sok fork miatt ágyúval verébre módszer is. Annyi segítségünk mondjuk van, hogy a kdbnek van '-script' kapcsolója, ami pont az ilyen munkákat igyekszik megkönnyíteni, de azért ez még mindig kevés az optimális működéshez.
test_server@root:/ # for GN_SEG in $(
>       for GNODE_ID in $(echo mount F100010020684550|kdb -script |grep -E "DIR|REG|SOCK" |awk ' { if ($3 != "0") print }')
>       do
>               echo gnode $GNODE_ID|kdb -script|awk '/gn_seg/ {print $NF}'
>       done)
> do
>       echo scb 2 $GN_SEG |kdb -script|awk '/pvproc/ {print}'
> done|sort -u|grep -v 0000000000000000
pvproc pointer           (pvproc)   : F100070F00045000
pvproc pointer           (pvproc)   : F100070F0004C800
Ebből kiindulva már nem nehéz megtalálni azt amire végső soron pályázunk (viszalépés kdb-be, majd.. )
(0)> proc F100070F00045000 |grep ^pvproc
pvproc+045000  276 java     ACTIVE 011404E 0132076 0000000030588400   0 000E
(0)> hcal 011404E
Value hexa: 0011404E          Value decimal: 1130574

(0)> proc F100070F0004C800 |grep ^pvproc
pvproc+04C800  306 sh       ACTIVE 0132076 0000001 0000000008466400   0 0001
(0)> hcal 0132076
Value hexa: 00132076          Value decimal: 1253494

1130574, 1253494. Amiket fentebb is láttunk.. Sőt, még azt is tudjuk, hogy egy sh, meg egy java processről van szó :)
Ha ne adj isten lusták vagyunk visszamenni a fenti script után a kdb-be, akkor némi kis módosítással nyomban ki is lehet kérni az ID-ket:

test_server@root:/ # MOUNT=$(echo mount |kdb -script|awk '{a[NR]=$0} /\/opt\/IBM$/ {print a[NR-1]}'|awk '{print $2}')
test_server@root:/ # for PVPROC in $(
>       for GN_SEG in $(
>               for GNODE_ID in $(echo "mount $MOUNT" |kdb -script|grep -E "DIR|REG|SOCK" |awk ' { if ($3 != "0") print $4}')
>               do
>                       echo gnode $GNODE_ID|kdb -script|awk '/gn_seg/ {print $NF}'
>               done)
>       do
>               echo scb 2 $GN_SEG |kdb -script|awk '/pvproc/ {print $NF}'
>       done|sort -u|grep -v 0000000000000000)
> do
>       echo proc $PVPROC|kdb -script|grep ^pvproc
> done
pvproc+045000  276 java     ACTIVE 011404E 0132076 0000000030588400   0 0017
pvproc+04C800  306 sh       ACTIVE 0132076 0000001 0000000008466400   0 0001

# Mint fent említettem: A módszer csak azokra a GNODE-okra működik aminek a countere (aktív thread-je) nagyobb mint 0. Ez azért problémás, mert ha egy process használ egy file-t, de az épp nem aktív (írás nélküli file, pl tail esetén), akkor ez a módszer is hibádzik. További probléma, hogy a submount-okat (amik szintén fogják az FS-t umount esetén) szintén nem képes kijelezni, szóval nyugodtan tekintsétek ezt is amolyan érdekességnek, tekintve, hogy mind a fuser, mind az lsof bőven alkalmasabb ezeknek a megkeresésére (általában - volt amikor ez a módszer talált meg nekem egy olyan thread-et, amiről más program sose hallott)

2012. január 31., kedd

Adott program által nyitott port (nem épp hagyományos módszerrel :))

Nemrég szegeztek nekem egy érdekes kérdést az AIX működésével kapcsolatban, ténylegesen, hogy hogyan lehet megtudni, hogy egy program milyen TCP portot tart nyitva.
Persze mondhatnánk, hogy a standard módszer a válasz a kérdésre, miszerint:

- Megnézzük, hogy az adott portot melyik socket címen lehet elérni:
testsystem:root # netstat -Aan |grep LISTEN |grep "\*\.22"
f1000200032b7b98 tcp4       0      0  *.22               *.*                LISTEN
- Majd a socketra ráengedve egy rmsock-ot nyomban meg is tudjuk az eredményt..
testsystem:root # rmsock f1000200032b7b98 tcpcb
The socket 0x32b7808 is being held by proccess 1290348 (sshd).
- Azaz, hogy jelen esetben az sshd fogja a 22es portot.
testsystem:root # ps -fp 1290348
     UID     PID    PPID   C    STIME    TTY  TIME CMD
    root 1290348  475196   0 03:32:57      -  0:00 /usr/sbin/sshd
Na de, itt nem errol volt szó!

A probléma ugyan is az, hogy mi azt szeretnénk tudni, hogy egy program milyen TCP portot fog, nem pedig, hogy egy elérhető portot mely alkalmazás tart nyitva. Ez persze megfordítja az egész kérdést, és a netstat-os lehetőséget is totál megtorpedózza.

Persze mondhatnánk, hogy ott az lsof, az tudja e, de tételezzük fel, hogy nem rendelkezünk ilyen eszközzel, hanem csak az alap AIX-hez adott base toolokkal.. Ez esetben ki mihez nyúlna??

Nos.. Én úgy gondoltam, hogy ha lúd, legalább legyen kövér: Menjünk le kernel szintre, és túrjunk benne könyékig amennyire csak lehet. Nézzük, hogy ez mit is eredményezett esetemben:

Első körben ugye indítsuk el a kdb-t, majd ha már bent vagyunk kapcsoljuk ki a Symbolic name Translation-t, mert engem személy szerint zavarni szokott amikor nem a teljes címet írja ki a kdb, hanem csak egy részét (pvthread+??????)
testsystem:root # kdb
(0)> ns
Symbolic name translation off
Ez után térjünk a lényegre.. Azt ugye tudjuk, hogy most az SSH programról beszélünk, aminek meg mint fentebb láthattuk a PID-je 1290348. Nézzük ez milyen címen tanyázik épp:
(0)> tpid -d 1290348|grep "0  $"
                SLOT NAME     STATE    TID PRI   RQ CPUID  CL  WCHAN
F100070F10023A00  570*sshd     SLEEP 23A099 03C    1         0
Oks.. Akkor ez is megvan . Menjünk tovább.. Tudni kéne, hogy az adott process milyen descriptorokat tart nyitva.. Ezt viszonylag könnyen megnézhetjük a user (u) paranccsal:
(0)> u -f F100070F10023A00 |grep -w fd
   fd      0 fp..F1000714500DAE58 count..00000000 flags. ALLOCATED
   fd      1 fp..F1000714500293E0 count..00000000 flags. ALLOCATED
   fd      2 fp..F1000714503CFE60 count..00000000 flags. ALLOCATED
   fd      3 fp..F100071450926220 count..00000001 flags. ALLOCATED
Ezek közül az egyik címen egy socket referenciának kell lennie, amennyiben az adott program valóban nyitott portot.. Sajna nem tudhatjuk pontosan melyik az, így muszáj ezen végigmennünk egyesével.. Mázlimra csak 4 van, így ez nem olyan nagy probléma..
(0)> file F1000714500DAE58 |grep -w ^SOCKET
(0)> file F1000714500293E0 |grep -w ^SOCKET
(0)> file F1000714503CFE60 |grep -w ^SOCKET
(0)> file F100071450926220 |grep -w ^SOCKET
SOCKET......... F1000200032B7808
BINGO.. Nézzük mit találtunk.. Első körben menjünk biztosra, és ellenőrizzük vissza, hogy a socket melyik process-hoz van rendelve
(0)> sock F1000200032B7808 |grep proc
proc/fd:  315/3
A 3as fd az még fentebbről ismerős lehet, de hogy kerül ide a 315? Egyszerűen úgy, hogy a socketet nyitáshoz is kell egy thread, ergo valószínű, hogy a 315ös SLOT alatt az ssh-nak egy subthread-je kell legyen. Tehát nézzük meg azt a subthread-et
(0)> th F100070F10023A00 |grep -w pvprocp |grep ">$"
DATA...........pvprocp :F100070F0004EC00 <F100070F0004EC00>
És ez alatt vajon milyen SLOT ID lapul?
(0)> proc F100070F0004EC00
             SLOT NAME     STATE      PID    PPID          ADSPACE  CL #THS
F100070F0004EC00  315*sshd     ACTIVE 013B06C 007403C 0000000041E95400   0 0001
315. BINGO.. Tehát akkor jó irányba haladtunk.. Akkor irány tova..

Tehát tudjuk, hogy a socketünk a F1000200032B7808 címen foglal helyet. Nézzük, hogy ez alá milyen pcb címet rendelt a rendszer:
(0)> sock F1000200032B7808 |grep -w pcb
    pcb.....@F1000200032B7A90  proto...@0000000004444880
Stimt.. Akkor még az is kell, hogy ez alatt a milyen PPCB cím van:
(0)>  tcb F1000200032B7A90 |grep ppcb
    ppcb........@F1000200032B7B98  route_6.....@F1000200032B7AE8
32B7B98.. Nem jött ez már szembe velünk valahol??? Ááá.. megvan.. az rmsock-nál! Dehogynem.. Tehát megvan a socket amit ténylegesen kerestünk.. Lehet tippelni milyen porton figyel :)
(0)> si F1000200032B7B98 tcpcb |grep lport
    oflowinfo... 00000000 lport....... 00000016 latype...... 00000000
(0)> hcal 16
Value hexa: 00000016          Value decimal: 22
16(hex) == 22(dec). Tehát a 22es porton.. Pontosan ez kellett nekünk!

Ha ezek után se hisszük, hogy jó socketre leltünk, akkor könnyű szerrel visszaellenőrizhetjük ezt is:
(0)> si F1000200032B7B98 tcpcb |grep socket
   laddr_6.....@F1000200032B7AC8  socket......@F1000200032B7808
F1000200032B7808.. Ez stimmel.. Tehát jól csináltunk mindent :))

Persze mondanom se kell, hogy ezt persze le lehet scriptelni, csak kérdés, hogy megéri e :) Az tény, hogy ha nincs a kezünk ügyében semmi használható eszköz, akkor használható ez is, de elég durva turkálást kell elkövetnünk, hogy ezt megtudjuk.. Arról nem is szólva, hogy ehhez eléggé mély szintre kell lemennünk, és a sok hülye számtól az ember szeme könnyen golyózni kezd :)