A következő címkéjű bejegyzések mutatása: non-documented. Összes bejegyzés megjelenítése
A következő címkéjű bejegyzések mutatása: non-documented. Összes bejegyzés megjelenítése

2014. szeptember 28., vasárnap

WTF - Megváltozott filerendszer mount pointok migrálás után

Aki már migrált valaha bármilyen régebbi rendszert bármilyen újra, az kb tudhatja hogy változatosabbnál változatosabb csapdákba futhat bele az ember időnként. Ez most se volt másként...

Adott egy régi Power4es szerver amin épp egy 5.2es AIX futkározik. Tekintve hogy ez a HW már jó ideje nem támogatott, sok helyet is foglal, meg amúgy is lassú, így fent az a döntés született, hogy konszolidálni kéne a szervert egy modernebb Power7es infrastruktúrába.
Hogy hogyan is? Hát van több fajta megoldás, csak tudni kell kiválasztani melyik a legcélravezetőbb:
- Live Partition Mobility: Ha a forrás és a cél rendszerek mind szépen virtualizálva vannak, és a szükséges feltételek mind adottak, akkor kiesés nélkül át lehet költöztetni az LPARt 2 fizikai rendszer között
- Lift and Shift: Ha a rendszer és az adatok is külső SAN-on vannak, akkor minimális leállás után át lehet zónázni a LUN-okat egy másik gépre és ott használni őket.
- Backup and restore: Ez esetben minimum a rendszer belsős lemezekre lett telepítve, így annak költöztetése csak egy mksysb backup segítségével megoldható, amit a távoli gépen aztán vissza lehet tölteni (akár WPAR-ba is). Ha mázlink van, akkor az adatok SAN-on helyezkednek el, így a specifikus LUN-okat át lehet simán zónázni a cél géphez; ha viszont nincs mázlink, akkor ezt is hálózaton keresztül valahogy át kell juttatni a cél gép felé (savevg, GLVM, vagy sima tar+ssh pipe)
- Rebuild from scratch: Ebben az esetben az alap rendszert (illetve opcionálisan a Middleware, Applikációt is) teljesen nulláról építjük újra, majd a szolgáltatáshoz szükséges további adatot átemeljük a forrás rendszerről és beillesztjük az újonnan felépített struktúrába.

Lehet meglepő, de régebbi rendszereknél az utóbbi sokszor a legcélravezetőbb, mivel ezeknél valószínű nem csak a rendszer régi, hanem annak komponensei is, így egy-egy ilyen migráció kiváló alkalmat ad arra, hogy az ember végre kidobálja a régi legacy szutykokat, és egy támogatott megoldással helyettesítse őket.

Ebben az esetben a legcélravezetőbbnek az utolsó 2 megoldás keveréke bizonyult a legjobbnak: Az alaprendszert nem volt értelme átköltöztetni, a régi -már nem támogatott- middleware komponenseket egy részét szerencsére volt lehetőség támogatottra cserélni, más komponenseket viszont simán át lehetett emelni a régi rendszerről a szükséges LUN-ok újrazónázásával.

A tényleges lépésekre most nem térek ki, -a bejegyzés szempontjából érdektelenek- egyet kivéve: Miután a LUN-okat az ember átzónázza Volume Groupot ismét be kell importálni a rendszerbe, hogy az adathoz hozzá lehessen férni. A folyamat részeként a teljes LVM struktúra importálódik a fájlrendszerekkel egyetemben. Igen ám, de volt egy kisebb probléma.. Az importálás után a legtöbb fájlrendszer szépen vissza is került a helyére, viszont volt 1-2 aminek a mount pointja megváltozott (ettől eltekintve az adat szépen a helyén volt). A kérdés adott volt: Miért?

No, a technikai része a blog bejegyzésnek kb. innen indul :)) Lássuk mi és hogy zajlik le egy ilyen importálás során:
- Az importálás során az importvg szépen felolvassa a megjelölt diszk VGDA adatait
- A VGDA adatok alapján ellenőrzi a VG-hez szükséges PV-k elérhetőségét (PVID alapján), illetve összeveti azok VGDA adatait (VG_ID) a többi PV-n találhatóakkal.
- Amennyiben az összes PV elérhető, és a VGDA is konzisztensen azonos adatot mutat, úgy felolvassa a teljes LVM struktúrát
- A struktúra része az adott LV-k definiciói (típus, név, méret, upper bound), azok elhelyezkedése (LP/PP-k elhelyezkedése PV-re lebontva), illetve 1-2 további metaadat (létrehozási idő, utolsó módosítási idő, label, vfs specifikus adatok)
- Miután a teljes struktúrát feltérképezte létrehozza a szükséges bejegyzéseket az ODM-ben, illetve a /etc/filesystems-ben, majd ezek alapján aktiválja a VG-t

Nem tudom kinek tűnik fel, de fájlrendszer specifikus adatokat az importvg nem olvas fel, még is módosítja a /etc/filesystems file-t.. Hogy van ez?

Na igen. Itt van a kutya elásva. Igaz, hogy FS specifikus adatot nem olvas fel, viszont nem is kell neki: A metaadatokban ott van minden amire szüksége van ahhoz, hogy egy fájlrendszert mountolni lehessen.

Itt egy pelda a /home FS (hd1 LV) LVM descriptorának elejéről:

3D8220000 41495820 4C564342 00006A66 73320000 |AIX LVCB..jfs2..| # LVM Control Block, LV type 3D8220010 00000000 00000000 00000000 00000000 |................| 3D8220020 00000000 00000000 00003030 63306164 |..........00c0ad| # LV serial ID 3D8220030 31653030 30303463 30303030 30303031 |1e00004c00000001| 3D8220040 34320068 64310000 00000000 00000000 |42.hd1..........| 3D8220050 00000000 00000000 00000000 00000000 |................| 3D8220060 00000000 00000000 00000000 00000000 |................| 3D8220070 00000000 00000000 00000000 00000000 |................| 3D8220080 00000053 756E204E 6F762031 30203231 |...Sun Nov 10 21| # Creation date 3D8220090 3A30393A 34382032 3031330A 00000000 |:09:48 2013.....| 3D82200A0 00576564 204A756C 20323320 30393A31 |.Wed Jul 23 09:1| # Last modification date 3D82200B0 353A3338 20323031 340A0000 00000030 |5:38 2014......0| 3D82200C0 41443145 34433030 00796D63 00790020 |AD1E4C00.ymc.y. | 3D82200D0 00010001 2F686F6D 65000000 00000000 |..../home.......| # Label 3D82200E0 00000000 00000000 00000000 00000000 |................| 3D82200F0 00000000 00000000 00000000 00000000 |................| 3D8220100 00000000 00000000 00000000 00000000 |................| 3D8220110 00000000 00000000 00000000 00000000 |................| 3D8220120 00000000 00000000 00000000 00000000 |................| 3D8220130 00000000 00000000 00000000 00000000 |................| 3D8220140 00000000 00000000 00000000 00000000 |................| 3D8220150 00000000 7666733D 6A667332 3A6C6F67 |....vfs=jfs2:log| # VFS data 3D8220160 3D2F6465 762F6864 383A6D6F 756E743D |=/dev/hd8:mount=| 3D8220170 74727565 3A636865 636B3D74 7275653A |true:check=true:| 3D8220180 766F6C3D 2F686F6D 653A6672 65653D66 |vol=/home:free=f| 3D8220190 616C7365 3A71756F 74613D75 73657271 |alse:quota=userq| 3D82201A0 756F7461 2C67726F 75707175 6F746100 |uota,groupquota.|

Mielőtt valaki nekem ugrik, hogy de ezek fájlrendszer adatok: Nem, az 8000(h) blokkal arrébb van:

3D8228000 4A324653 00000002 00000000 527FF623 |J2FS........R..#| 3D8228010 00000000 00000000 00000000 00002F68 |............../h| 3D8228020 6F6D6500 00000000 00000000 00000000 |ome.............|

Jó. De ha ott megtalálható az adat, akkor miért nem az alapján dolgozik az importvg? A válasz erre nagyon egyszerű: Mert ott az se a mount point :)

De akkor várjunk csak egy pillanatot.. Itt van 2 olyan példa is, ahol egyértelműen látszik, hogy ott van a /home, de ez mégse a mount point? Hülyén hangzik, mi? :)) Nézzünk egy másik példát, és akkor már talán tisztább lesz. Legyen a példa a /var/adm/ras/livedump filerendszer (livedump LV):

LVM descriptor eleje:

1BC220000 41495820 4C564342 00006A66 73320000 |AIX LVCB..jfs2..| # LVM Control Block, LV type 1BC220010 00000000 00000000 00000000 00000000 |................| 1BC220020 00000000 00000000 00003030 63306164 |..........00c0ad| # LV serial ID 1BC220030 31653030 30303463 30303030 30303031 |1e00004c00000001| 1BC220040 3432006C 69766564 756D7000 00000000 |42.livedump.....| 1BC220050 00000000 00000000 00000000 00000000 |................| 1BC220060 00000000 00000000 00000000 00000000 |................| 1BC220070 00000000 00000000 00000000 00000000 |................| 1BC220080 00000053 756E204E 6F762031 30203231 |...Sun Nov 10 21| # Creation date 1BC220090 3A30393A 35302032 3031330A 00000000 |:09:50 2013.....| 1BC2200A0 0053756E 204E6F76 20313020 32313A31 |.Sun Nov 10 21:1| # Last modification date 1BC2200B0 313A3530 20323031 330A0000 00000030 |1:50 2013......0| 1BC2200C0 41443145 34433030 00796D6D 00790020 |AD1E4C00.ymm.y. | 1BC2200D0 00040001 2F766172 2F61646D 2F726173 |..../var/adm/ras| # Label 1BC2200E0 2F6C6976 6564756D 70000000 00000000 |/livedump.......| 1BC2200F0 00000000 00000000 00000000 00000000 |................| 1BC220100 00000000 00000000 00000000 00000000 |................| 1BC220110 00000000 00000000 00000000 00000000 |................| 1BC220120 00000000 00000000 00000000 00000000 |................| 1BC220130 00000000 00000000 00000000 00000000 |................| 1BC220140 00000000 00000000 00000000 00000000 |................| 1BC220150 00000000 7666733D 6A667332 3A6C6F67 |....vfs=jfs2:log| # VFS data 1BC220160 3D2F6465 762F6864 383A6D6F 756E743D |=/dev/hd8:mount=| 1BC220170 74727565 3A616363 6F756E74 3D66616C |true:account=fal| 1BC220180 73653A71 756F7461 3D6E6F00 00000000 |se:quota=no.....| 1BC220190 00000000 00000000 00000000 00000000 |................| 1BC2201A0 00000000 00000000 00000000 00000000 |................| 1BC2201B0 00000000 00000000 00000000 00000000 |................| 1BC2201C0 00000000 00000000 00000000 00000000 |................| 1BC2201D0 00000000 00000000 00003433 64393432 |..........43d942| 1BC2201E0 62342E31 31000000 00000000 00000000 |b4.11...........| 1BC2201F0 00000000 00000000 00000000 00000000 |................|

FS descriptor eleje:

1BC228000 4A324653 00000002 00000000 527FF62C |J2FS........R..,| 1BC228010 00000000 00000000 00000000 00002F76 |............../v| 1BC228020 61722F61 00000000 00000000 00000000 |ar/a............|

Na, ki veszi észre mi a hiba az utóbbi példában? :) Igen, az FS descriptorban lévő adat nem egyezik meg az LVM descriptorban lévő labellel. Hogy miért? Azért mert az FS descriptorban lévő adat csak 6 karakter hosszú minden eseteben.
Jó, következő kérdés: Ennek így mi értelme? Nos, az AIX a boot folyamán ezt a 6 karaktert használja a boot során (Step 2, nem összekeverni az rc2-vel!) hogy visszaellenőrizze az FS-t adatait (felmerült már bárkiben, hogy a rendszer indításához szükséges fájlrendszerek mount pointja miért olyan rövid mindig? :))
Na jó.. Innentől a kérdés már csak az, hogy a mount pointok akkor hol vannak letárolva? Hát ez az.. A /etc/filesystems file alatt. És csak ott. Minden más csak "tájékoztató jellegű", kb. mint a MÁV menetrendje.

Visszatérve az eredeti szálra már látszik, hogy milyen csapdáról beszéltem: Az importálás során ezek a definíciók nem elérhetőek a /etc/filesystems alatt, az FS descriptorra se lehet támaszkodni ilyenkor, így hát marad az LVM descriptorban lévő Label.
Igen ám, de mi van akkor ha valaki megváltoztatja egy FS mount pointját és ehhez nem a megfelelő chfs parancsot használja, hanem manuálisan szerkeszti a /etc/filesystems filet? Pontosan.. Inkonzisztencia.. Minden szépen működni is fog egészen addig, amíg az ember egy ehhez hasonló VG importot nem akar végrehajtani (hisz a rendszer minden boot során ezen file alapján fogja bootolni a filerendszereket), amikor is az importvg/recreatevg neme egyszerűséggel felülvágja a /etc/filesystems-ben található adatokat a Label-ben található adatokkal.

Jó.. már értem.. Azt hiszem.. Hogy tudok meggyőződni arról, hogy nálam ilyen nem fordul elő?
A legegyszerűbben az lslv kimenetéből tudod megnézni a Label-t. Ha abban a szerencsétlen helyzetben találod magad, hogy nem tudod lslv-vel lekérdezni az LV-ket, de a diszkek még elérhetőek (és nem akarsz egy importvg-t megkockáztatni), akkor ezzel a kis scripttel le tudod kérni direktben a diszkekről a label-eket:

Példa kimenet:

# read_labels_directly_from_disk.sh hdisk0 hdisk0 / smallvg / 64 MB PP size ******************* ....primary_bootlv.............................. / hd5 - 64 MB / 1 (220000) / hdisk0 ....None........................................ / hd6 - 512 MB / 104 (19C220000) / hdisk0 ....None........................................ / hd8 - 64 MB / 206 (334220000) / hdisk0 ..../........................................... / hd4 - 192 MB / 207 (338220000) / hdisk0 .#../usr........................................ / hd2 - 2240 MB / 210 (344220000) / hdisk0 ..../var........................................ / hd9var - 256 MB / 241 (3C0220000) / hdisk0 ..../tmp........................................ / hd3 - 768 MB / 245 (3D0220000) / hdisk0 ..../home....................................... / hd1 - 64 MB / 247 (3D8220000) / hdisk0 ..../opt........................................ / hd10opt - 384 MB / 248 (3DC220000) / hdisk0 ..../admin...................................... / hd11admin - 128 MB / 250 (3E4220000) / hdisk0 ..../var/adm/ras/livedump....................... / livedump - 256 MB / 112 (1BC220000) / hdisk0 ....None........................................ / dumplv - 1280 MB / 479 (778220000) / hdisk0 ....None........................................ / dumplv2 - 1280 MB / 269 (430220000) / hdisk0

# Érdekesség: A módszer kicsit más és más VG típusonként, így aki érdeklődik a tényleges struktúra után, az nyugodtan kukkantson bele a scriptbe :) (kis matek tudás azért nem fog ártani)

2014. január 29., szerda

Solaris - Emulex HBA WWPN check

Régen blogoltam ide, de úgy gondoltam hogy ez még jól jöhet az utókornak, szóval ...

.. Adott egy ősrégi Solaris szerver (az a fajta ami a múzeumba se való már, olyan régi), aminél azt a feladatot kaptam, hogy a Storage szerverek zónázásakor használt WWPN numbert kinézzem. Tekintve hogy ez számomra alap feladatnak hangzott (AIX adminként), így gondoltam gyorsan végzek is a feladattal.. Hát a francokat..

Na nézzük miért is.
1) Mint mondtam a gép meglehetősen régi:
root@server[] # uname -a SunOS server 5.6 Generic_105181-39 sun4u sparc SUNW,Ultra-Enterprise
/* Csak a miheztartás végett - az 5.6ot (aka Solaris 2.6) 1997ben adták ki (bár 2006ig támogatott maradt) */

2) A google jelen esetben nem a barátod
Hiába akad google-n 1-2 használhatónak tűnő tipp*, attól még sajna ez kevés a boldogsághoz ha a tippek közül egyik se működik, mert vagy nem elérhető a parancs amire hivatkozik, vagy nem kapok kimenetet, vagy amit kapok az láthatóan hülyeség.
-> scli, fcinfo, prtpicl, lputil64 nem létezik
-> 'prtconf -vp | grep -i wwn' hülyeséget dob vissza
-> /var/adm/messages* alatt egy bejegyzes sincs amiben a wwn vagy wwpn benne lenne
-> 'luxadm -e port' szerint az összes adapter not-connected state-ben van ami abszolút hülyeség, viszont ez miatt a 'luxadm -e dump_map' se működik.
-> 'iostat -XMzxn' közli, hogy a -X, -z kapcsoló nem értelmezhető

* A leghasználhatóbb talán ez: http://www.sunsolarisadmin.com/hardware/how-to-find-the-wwn-world-wide-name-in-sun-solaris/

3) Nem mindegy hogy milyen adapter van a gépben és hogy milyen driver hajtja
Az egy dolog, hogy csak 1-2 hivatalosan támogatott kártya elérhető, de mocskos módon még az se mindegy, hogy azt a kártyát milyen Storage megvalósításhoz szeretnéd használni, mert mindegyik megvalósításnak más-más driver kell, azok meg hajlamosak meglehetősen válogatósak lenni a támogatott kártyák között. Ehhez jön még hozzá, hogy nincs egységes tool a HBA-k kezelésére, hanem minden driverhez külön-külön utility set van ami így vagy úgy valósítja meg kb ugyan azokat a feladatokat (lscfg, de hiányoltalak én téged..)

4) Az se mindegy, hogy melyik verziójú drivered van fent
Mint utólag kiderült a 2. pontban leírt problémámba ay is erősen közrejátszott, hogz az idők során kiadott különböző driverek/toolok telepítési útvonala hajlamos volt időről időre változni, így ha nincs bent a $PATH-ban az adott tool akkor vagy tudod mi és hol van, vagy keresgélhetsz amíg meg nem találod (már ha tudod mit is kéne pontosan keresni)

Na szóval.. Ha tudni akarod, hogy hogy is kell megtekinteni egy HBA WWPN-jét, akkor:
- Tudnod kell, hogy pontosan milyen kártyáról van szó
- Tudnod kell, hogy az adott kártyát milyen driver hajtja
- Tudnod kell, hogy az adott driver tooljai hol találhatóak
- Tudnod kell, hogz a toolok közül melyik is alkalmazható a te általad megálmodott feladatra, és azt is hogyan.

Hát gyerekek. Aki a Linux alatt sír hogy mennyire össze van gányolva, és hogy mennyire de nem egységes, azt isten bizony odaültetném egy ilyen elé.

Na de vissza térve az én esetemre.
- Milyen HBA van a gépben?
root@server[] # prtdiag -v |grep SBus |grep sd 1 SBus 25 0 lpfs/sd (block) LP9002S 1 SBus 25 3 SUNW,fas/sd (block) 3 SBus 25 1 QLGC,isp/sd (block) QLGC,ISP1000U 3 SBus 25 2 lpfs/sd (block) LP9002S 3 SBus 25 3 SUNW,fas/sd (block) 5 SBus 25 1 QLGC,isp/sd (block) QLGC,ISP1000U 5 SBus 25 2 QLGC,isp/sd (block) QLGC,ISP1000U 5 SBus 25 3 SUNW,fas/sd (block)
- Lehet is nyomban válogatni, tekintve, hogy 2 is van. Az 1ik ránézésre valami QLogic cucc (sd driver-rel), a másik meg csak annyit mond magáról, hogy LP9002S. Kis google után utóbbiról kiderül, hogy 2Gbps Emulex Fibre channel adapter, míg az első egy sima SCSI vezérlő (így azzal most nem foglalkozok). Annyi segítséget a gép adott, hogy az Emulex kártyát az lpfs driver hajtja, így már csak azt kell kitalálni, a driverhez tartozó segédprogramok hol is találhatóak
- Első körben tudni kell a csomag nevét:
root@server[] # pkginfo |grep lpfs system lpfs Emulex LightPulse FC SCSI/IP Host Bus Adapter driver
- Ebből kiindulva aztán érdemes megnézni, hogy mi is van a csomagban:
root@server[] # pkgchk -l lpfs|grep Pathname |egrep "bin|sbin" Pathname: /usr/sbin Pathname: /usr/sbin/lpfs Pathname: /usr/sbin/lpfs/QS_fmw Pathname: /usr/sbin/lpfs/REV_fmw Pathname: /usr/sbin/lpfs/dfc Pathname: /usr/sbin/lpfs/dfc32 Pathname: /usr/sbin/lpfs/dfc64 Pathname: /usr/sbin/lpfs/download_fmw_lpfs Pathname: /usr/sbin/lpfs/lpsutil Pathname: /usr/sbin/lpfs/lpsutil32 Pathname: /usr/sbin/lpfs/lpsutil64 Pathname: /usr/sbin/lpfs/resetqdepth
- Oksi. Akkor a /usr/sbin/lpfs mappában kéne körbenézni. Kérdés, hogy mi is használható ezek közül.

Az mondjuk kb tiszta, hogy a QS_fmw és a REV_fmw valami firmware féleség lehet, így azokhoz inkább nem nyúlok. A download_fmw_lpfs hasonló okok miatt esik ki (lekérdezni akarok, nem módosítani). A dfc-ből, illetve az lpsutil-ból a jelek szerint 3-3 file is elérhető: 1 központi, illetve 1-1 32/64 bit specifikus (Ránézésre a fő bináris feladata, hogy megítélje, hogy a rendszer 32 vagy 64 bites rendszeren fut e, és az alapján meghívja a szükséges binárist). Ezen felül van még a resetqdepth, ami a nevéből illetően piszkálni akar valamit, viszont mint kiderül lényegében csak egy script:
root@server[] # cat /usr/sbin/lpfs/resetqdepth #!/bin/sh # $Id: resetqdepth.sh 1.6 2001/03/07 00:12:00 mks Exp $ case $1 in [0123456789]*) ;; *) echo Usage: resetqdepth adapter_number exit 1 ;; esac /usr/sbin/lpfs/dfc > /dev/null <<! set board $1 rqdepth exit ! exit 0
Természetesen ezt lefuttatni nem akarom, viszont a tény hogy a fentebb említett dfc parancsra támaszkodik egy EOF here tag-el ad némi reményt arra hogy esetleg valami belső parancs készletre támaszkodó programmal van dolgunk.

Így hát elindítva a dfc programot az alábbi kimenetben gyönyörködhetünk:
root@server[] # /usr/sbin/lpfs/dfc LightPulse Engineering Debug Utility Copyright (c) 1999, 2000 Emulex Network Systems, Inc. Do not run this utility unless instructed by Emulex Technical Support Found 0 PCI 2 SBUS adapters: onmask 3f58f offmask 1e7 Driver:4.21x1 Adapter 0: lpfs1 SBUS id df1095f0 Firmware:3.90A7 (R2F3.90A7) Adapter 1: lpfs0 SBUS id df1095f0 Firmware:3.90A7 (R2F3.90A7) cmd>

Szupi.. Szóval kapunk egy belső command line-t.. Nézzük mit lehet benne mókólni (és lehetőleg nem elszúrni :))
cmd> help rdallpci wrpci wrhc wrhs wrha wrca rdpci rdhc rdhs rdha rdca rdmb exit set rring rslim riocb rrpi rbp rmemseg mbox reset rbinfo nddstat fcstat wslim wffreg rffreg sdiag dbg rnode rdevp instance lip linkinfo ioinfo nodeinfo getcfg setcfg failio outfcpio rqdepth ct hbaattr portattr portstat dportattr wportattr iportattr fcpmap fcpbind setmgmt getmgmt rnid getevent resetstat sendscsi refresh els getmpulse setmpulse listn trace help p
Sajna a fejlesztők arra már nem szánták rá magukat, hogy a help parancsot kibővítsék az alparancsok leírásával is, így némi kis próbálkozás után sikerül eljutnom csak az alábbi kimenethez:
cmd> linkinfo Event 0x0 Up 0x1 Down 0x0 Multi 0x0 PortID 0x0 alpa 0x0 topology 0x4 state 0x1 ALPAmap 0: Portname 10:00:00:00:ab:cd:ef:01 Nodename 20:00:00:00:ab:cd:ef:01
Na ez már végre az amit akartam.. Az egyedüli bajom csak az, hogy a parancs ismételt kiadásával ugyan ezt az eredményt kapom vissza, viszont ebben a gépben (ahogy fentebb is látható volt) 2 HBA kártya van.. Valahogy rá kéne venni a programot, hogy a másik kártya adatait is le lehessen kérdezni.

Ekkor ugrott be a fenti script, ami képes volt tetszőleges adapterre lefuttatni az rqdepth parancsot. Mindezt a set board $1 parancsal, úgy hogy nyomban mentem is vissza az újonnan megismert subshellem alá további tesztelésre:
root@server[lpfs] # ./dfc LightPulse Engineering Debug Utility Copyright (c) 1999, 2000 Emulex Network Systems, Inc. Do not run this utility unless instructed by Emulex Technical Support Found 0 PCI 2 SBUS adapters: onmask 3f58f offmask 1e7 Driver:4.21x1 Adapter 0: lpfs1 SBUS id df1095f0 Firmware:3.90A7 (R2F3.90A7) Adapter 1: lpfs0 SBUS id df1095f0 Firmware:3.90A7 (R2F3.90A7) cmd> set board 0 cmd> linkinfo Event 0x1 Up 0x1 Down 0x0 Multi 0x0 PortID 0x633613 alpa 0x13 topology 0x3 state 0x6 ALPAmap 0: Portname 10:00:00:00:ab:fd:08:04 Nodename 20:00:00:00:ab:fd:08:04 cmd> set board 1 cmd> linkinfo Event 0x0 Up 0x1 Down 0x0 Multi 0x0 PortID 0x0 alpa 0x0 topology 0x4 state 0x1 ALPAmap 0: Portname 10:00:00:00:ab:cd:ef:01 Nodename 20:00:00:00:ab:cd:ef:01 cmd> exit
Buli.. Igy mar szepen megy is minden, mint a karika csapás. Akkor már csak az maradt, hogy le is scriptljük a dolgot:
root@server[] # cat /tmp/emulex_wwpn_query.sh #!/usr/bin/ksh PACKAGE_NAME=`pkginfo |grep SCSI |egrep "lpfc|lpfs" |cut -d ' ' -f2` DFC_PATH=`pkgchk -l $PACKAGE_NAME |grep Pathname |grep dfc$ |cut -d ' ' -f2` while true do $DFC_PATH 2>&1 << ! exit ! break done |grep Adapter |cut -d ' ' -f 2 |sed "s/://g" |while read ID do $DFC_PATH 2>&1 << ! set board $ID linkinfo exit ! done |grep Portname |cut -d ' ' -f 2 |sed "s/://g" |tr 'a-z' 'A-Z' root@server[] # sh /tmp/emulex_wwpn_query.sh 10000000ABCDEF01 10000000ABFD0804
Trolloknak előre megjegyzem: ezen az ősrégi vackon a pipe feldolgozási sorrendje nem tudom miért de valahogy eltér a megszokottól; a $() nem működik, helyette van backtick (`), az viszont valamiért nem szeret több parancsot 1 soron belül látni; Talán pont a pipe-olás miatt az awk se működik úgy ahogy azt elvárnám, így fallbackeltem az ódivatú parancsokra, mint cut, grep, sed, tr (amit amúgy egy awk simán ki tudna váltani, viszont ha nincs ló, jó lesz a szamár is.. ). Amúgy ha valakinek van ötlete, hogy while; do ... done módszeren kívül hogy lehet még greppelni egy here tag (jelen esetben !) után az ne fogja vissza magát :)

2013. május 16., csütörtök

Corrupt system dump - Nem bírja a rendszer, szívjál még egyszer..

Sajnos az elmúlt időszakban inkább project jellegű munkákkal kellett foglalkozzak (ami inkább a tervezési munkálatokat fed le), mint sem tényleges rendszer üzemeltetéssel (ami meg az esetleges hibák debugolását), így el kellett telnie némi kis időnek, míg valami fincsi problémára rá tehettem a kezem.
Most viszont végre sikerült valami kellemesbe is belekóstolnom :)

A történet előzménye röviden a következő: Adott egy nem épp up-to-date AIX rendszer, ami hirtelen dobott egy hátast, plusz a hozzá járó kernel dumpot, és ki kéne deríteni, hogy pontosan mi a fene lehetett a háttérben (az applikáció eléggé nem szereti a magasabb AIX levelt, így mielőtt ráböföghetném, hogy "AIX-et kéne frissíteni wazze" még be kell bizonyítanom, hogy valóban az AIX volt e a ludas). Tekintve, hogy az ilyen jellegű vizsgálódások annyira nem állnak tőlem távol, így örömmel kezdtem neki a probléma megoldásának, bár az örömöm nem tartott sokáig..

Kezdésként nézzük a helyzetet:
# oslevel -s
5300-08-02-0822
// No igen.. Ennek a TL-nek a hivatalos supportja még 2010 Áprilisában járt le, ráadásul még 2010 Májusban kiadtak hozzá az SP10-et. Ez az SP még 2008ban jött ki, szóval gondolhatjátok, hogy milyen régi applikáció futhat rajta, ami miatt még az AIX-et se merik upgrade-elni..
# errpt | head -3
IDENTIFIER TIMESTAMP  T C RESOURCE_NAME  DESCRIPTION
67145A39   0325114513 U S SYSDUMP        SYSTEM DUMP
F48137AC   0325114213 U O minidump       COMPRESSED MINIMAL DUMP

Jó.. Szóval legalább az alapok meg vannak.. Nézzük, hogy mire számítsunk:
# errpt -aj 67145A39
---------------------------------------------------------------------------
LABEL:          DUMP_STATS
IDENTIFIER:     67145A39

Date/Time:       Mon Mar 25 11:45:00 NFT 2013
Sequence Number: 900224
Machine Id:      00CD98ED7C00
Node Id:         application_server
Class:           S
Type:            UNKN
Resource Name:   SYSDUMP         

Description
SYSTEM DUMP

Probable Causes
UNEXPECTED SYSTEM HALT

User Causes
SYSTEM DUMP REQUESTED BY USER

        Recommended Actions
        PERFORM PROBLEM DETERMINATION PROCEDURES

Failure Causes
UNEXPECTED SYSTEM HALT

        Recommended Actions
        PERFORM PROBLEM DETERMINATION PROCEDURES

Detail Data
DUMP DEVICE
/dev/dumplv
DUMP SIZE
            2147483136
TIME
Mon Mar 25 11:40:12 2013
DUMP TYPE (1 = PRIMARY, 2 = SECONDARY)
           2
DUMP STATUS
          -2
ERROR CODE
           0
DUMP INTEGRITY
This dump may be unusable - The alloc_kheap component is missing. 
This dump may be unusable - The alloc_other component is missing. 
This dump is incomplete - The end-of-dump component is missing. 

FILE NAME

PROCESSOR ID
           0
Tehát a rendszer váratlanul megállt, de a keletkezett dump nem teljes.. Innen indul a kihívás..

Tekintve, hogy van egy minidump-unk, így legalább abban reménykedhetünk, hogy abból ki tudunk valamit hámozni. Erre a legegyszerűbb az mdmprpt parancs.
# mdmprpt 
MINIDUMP VERSION 4D32
***************************************************
64-bit Kernel, 108 Entries

Last Error Log Entry: 
         Error ID: 9AA1914A      Resource Name: SYSVMM 
         Detail Data: 0000000042000000 00007FFFFFFFD080 
        F10001005DDD11F0 FFFFFFFFFFFFFFF3

This minidump is corrupted
Meg se lepődök.. Tekintve, hogy a dump-unk incomplete, így nem is vártam konzisztens dump-ot, bár a corrupt dump azt jelenti, hogy esélyünk nincs ezt az entry-t ellenőrizni. Egyedül annyi derül ki, hogy az utolsó jegyzett hiba a 9AA1914A error ID-ra mutat, ami a SYSVMM-hez köthető. Gyors segítség: VMM - Virtual Memory Manager, így innentől már sejthető, hogy itt valami memória művelethez köthető dolgon csúszott meg a rendszer. De azért nézzük meg, hogy a 9AA1914A error ID mit is takar a valóságban:
# grep -i 9AA1914A /usr/include/sys/errids.h
#define ERRID_DSI_MEMOVLY    0x9aa1914a /* A kernel memory overlay has been detected */
Memory overlay - teljesen fedi a VMM hatáskörét, úgy hogy eddig ez rendben is van.. Na de hogyan tovább? Ja igen.. Van még egy dumpunk. Ezt mentsük le a dump device-ról amíg lehet, aztán nézzük meg mit találunk benne:
# dd if=/dev/dumplv of=/dump_check/sysdump bs=4096 count=2147483136
// Itt megállnék egy pillanatra: Normális esetben a dump compression be van kapcsolva, ami azt jelenti, hogy a kiszedett dump-ot még ki is kéne tömöríteni a dmpuncompress paranccsal, jelen esetben viszont erre nem volt szükség, mivel a dump compression ezen a gépen nem volt bekapcsolva. Innentől lehet tippelni, hogy miért is nem fért el a dump, és hogy én ez miatt mennyire de boldog voltam.
# kdb /dump_check/sysdump
The specified kernel file is a 64-bit kernel
sysdump mapped from @ 700000000000000 to @ 70000007ffffe00
Preserving 1411195 bytes of symbol table
First symbol __mulh
Component Names:
 1)  minidump [2 entries]
 2)  dmp_minimal [9 entries]
 3)  dump_pad53 [1 entries]
 4)  proc [4101 entries]
 5)  thrd [7291 entries]
 6)  rasct [1 entries]
 7)  ldr [2 entries]
 8)  iplcb [1 entries]
 9)  errlg [3 entries]
10)  mtrc [98 entries]
11)  lfs [1 entries]
12)  bos [4 entries]
13)  ipc [7 entries]
Premature end of data in dump file.
Component Dump Table has 11523 entries
           START              END 
0000000000001000 0000000003E04050 start+000FD8
F00000002FF47600 F00000002FFDC940 __ublock+000000
000000002FF22FF4 000000002FF22FF8 environ+000000
000000002FF22FF8 000000002FF22FFC errno+000000
F100070F00000000 F100070F10000000 pvproc+000000
F100070F10000000 F100070F18000000 pvthread+000000
PFT:
PVT:
id....................0002
raddr.....0000000002000000 eaddr.....F200800090000000
size..............00080000 align.............00001000
valid..1 ros....0 fixlmb.1 seg....0 wimg...2
Unable to establish context with current thread
Unable to establish context with current thread
Unable to find kdb context
Dump analysis on CHRP_SMP_PCI POWER_PC POWER_6 machine with 32 available CPU(s)  (64-bit registers)
Processing symbol table...
.......................done
        ERROR: Unable to acess nfs_syms
(0)> where
Unable to establish context with current thread
Unable to establish context with current thread
[kdb_read_mem] no real storage @ F1000100100EE800
Unable to establish context with current thread
Unable to establish context with current thread
Unable to find kdb context
(0)> f
Unable to establish context with current thread
Unable to establish context with current thread
[kdb_read_mem] no real storage @ F1000100100EE800
Unable to establish context with current thread
Unable to establish context with current thread
Unable to find kdb context
(0)> stat
SYSTEM_CONFIGURATION:
CHRP_SMP_PCI POWER_PC POWER_6 machine with 32 available CPU(s)  (64-bit registers)

SYSTEM STATUS:
sysname... AIX
nodename.. application_server
release... 3
version... 5
build date May 12 2008
build time 23:42:11
label..... 0820A_53N
machine... 00CD98ED7C00
nid....... CD98ED7C
time of crash: Mon Mar 25 11:39:02 2013
age of system: 124 day, 7 hr., 56 min., 32 sec.
xmalloc debug: enabled
Debug kernel error message: A program has tried to store to freed or redzoned xmalloc memory.
Address at fault was 0xF10001005DDD11F0
Na akkor röviden: Az alap parancsok mind elhullanak azon oknál fogva, mert a dump-unk nem teljes, amúgy meg annyit tudunk meg mint előzőleg - memória kezelési gubancok vannak a háttérben.

Egy dolog viszont ott van amit talán lehet használni: a CDT adatok (component-dump tables), amit a kdb az elején jelzett is. Ami nekünk kelhet az jelen esetben a minidump, vagy az errlg tábla, tekintve, hogy ezek még talán tartalmazhatnak valami kis támpontot, hogy merre tovább.

Első körben én a minidump-ra koncentráltam:
(0)> cdt 1
Dump table entries in CDT:

CDT ENTRY VMHANDLE       ALIAS        ADDRESS LENGTH   NAME
  1     1 kernel             0000000002B1AA50 00000046 md head
  1     2 kernel             0000000002F1E9FC 00000E60 minidump
Tekintve, hogy a dump is tartalmazza a minidump-ot, így első körben az volt a tervem, hogy azt fogom kiszedni onnan, majd használható állapotba hozni, viszont egy részről ez -mint utólag kiderült- nem volt kivitelezhető (az okokat most nem tárgyalom), így más útvonalon kellett elinduljak
// Az minidump-al való mókolást szerintem majd egy külön blogban tárgyalom ha lesz rá érdeklődés

Mázlimra az AIX-nek van 1-2 beépített parancsa bizonyos típusú adatok kinyerésére a dump file-okból, csak ezeket valamiért a dokumentációk nem nagyon emlegetik. Az egyik ilyen parancs a dmp_minimal (ami még véletlenül sincs dokumentálva), a másik pedig az errdead (ami még úgy ahogy dokumentált).
Előző célja, hogy az elérhető minidump-ot kinyerje a dump file-ból, és megpróbálja azt értelmezni, utóbbi pedig a boot során keletkezett error logok kinyerésére használható a dump file-ból.
#  /usr/lib/ras/dmprtns/dmp_minimal /dump_check/sysdump|tail -15
traceback:
 iar:0000b920 unknown
  lr:002f7eac slock+148
addr:002f806c slock+308
addr:000090c4 unknown
addr:044901f8 store_packet+70
addr:04490880 pcd_output[DS]+98
addr:044473f8 en_output+1218
addr:0430974c ip_output_post_fw+1f50
addr:04309b04 ip_output+100
addr:0433bb44 tcp_output+2404
addr:0436d2a0 tcp_usrreq+17a8
addr:00223760 sosend+c88
addr:0023b2b8 send+4e0
addr:00003814 unknown
Na, legalább van egy stack-ünk. Megerősítésként azért nem árt átnézni az error logot is. Ehhez simán extractoljuk ki az error logot a dump-ból, majd adjuk oda az errpt-nek:
# /usr/lib/errdead -i ./errpt_out /dump_check/sysdump 
# errpt -i errpt_out
IDENTIFIER TIMESTAMP  T C RESOURCE_NAME  DESCRIPTION
9AA1914A   0325113913 P S SYSVMM         INVALID MEMORY REFERENCE
77EED6D9   0325113913 U S SYSALLOC       Deferred-free or redzoned memory read
Hoppá. Emlékszik még valaki a 9AA1914A-es hibakódra? Igen, ez az amire az mdmprpt is panaszkodott. Legalább ez az infó is megvan akkor. Sajna azonban a 9AA1914A-es error logban nem sok használható infó van, viszont annál több a 77EED6D9-esben:
# errpt -i errpt_out -aj 77EED6D9
---------------------------------------------------------------------------
LABEL:          XM_READ_FREE
IDENTIFIER:     77EED6D9

Date/Time:       Mon Mar 25 11:39:02 NFT 2013
Sequence Number: 1
Machine Id:      00CD98ED7C00
Node Id:         application_server
Class:           S
Type:            UNKN
Resource Name:   SYSALLOC        

Description
Deferred-free or redzoned memory read

Probable Causes
LOADABLE SOFTWARE MODULE
SOFTWARE DEVICE DRIVER
OPERATING SYSTEM

Failure Causes
MEMORY ALLOCATION ERROR

        Recommended Actions
        PERFORM PROBLEM DETERMINATION PROCEDURES
        CONTACT YOUR LOCAL IBM SERVICE REPRESENTATIVE

Detail Data
Stack Trace
slock+11C
slock+304
[90C0]
store_packet+6C
pcd_output[DS]+94
en_output+1214
ip_output_post_fw+1F4C
ip_output+FC
tcp_output+2400
tcp_usrreq+17A4
sosend+C84
send+4DC
[3810]
-errSTKfrm-
Mint látható, a 2 parancs által szerzett stack kb azonos (annyi különbséggel, hogy az errpt az ismeretlen hívások helyére valami -nekünk irreleváns- címet illesztett be), így nyugodtak lehetünk, hogy jó nyomon járunk.

Jó, de innen hova tovább? Azt nem tudjuk megnézni, hogy a regiszterekben milyen adat volt, a forráskódhoz nem férünk hozzá, hogy tudjuk minek és hol is kéne pontosan lennie, csupán egy stack állapotunk van. Ez miatt általában azt szoktam mondani, hogy tessék utána járni, hogy van e olyan APAR, ami hasonló, vagy (ami még jobb) azonos stack-et produkál e, ugyan is ekkor szinte biztosak lehetünk, hogy abba a bug-ba sikerült belebotlanunk, de még hasonlót se találtam ami ilyesmi stack-et írt volna le (a 2 unknown hívás meg pláne nem segít semmit).

Na innentől általában egyenes út a software call felé, de szinte biztos, hogy ilyen dump-al ők se tudnak sokat kezdeni, plusz mivel enyhén outdated AIX level-t futtatunk, így csuklóból közölnék, hogy ez a verzió nem támogatott, illetve ajánlatos lenne azonnal update-elni, mivel azóta már jó pár javítás kijött, és hátha valamelyik erre is megoldást nyújtana.

// Itt akár be is fejezhetném ezt a blog bejegyzést, ugyan is technikailag már sok újdonságot nem fogok leírni, viszont akit érdekel a teljes történet, annak azért leírom, hogy hogy is folytatódik ez a kis történet.

Na szóval. A probléma ezzel a felállással innentől az, hogy az ember 2 szék között a pad alá kerül rövid úton, úgy hogy ez így nem játszható.
Van azonban még 1 kis aranyágacska, amin el lehet indulni: A stackben látható pcd_output hívás nem része a standard AIX hívásoknak, így kis kutakodás után sikerült kideríteni, hogy azt egy extended kernel module biztosítja, ami az IBM RealSecure Server-hez (aka ISS) tartozik, ami akkor szintúgy bekavarhat, úgy hogy ennek a szálnak is utána kell járni.

// Megjegyzés: az ISS egy extra védelmi réteget húz a hálózati kommunikáció elé, és monitorozza a hálózati forgalmat. Ha valami gyanúsat észlel, akkor azt elvileg képes megfogni, így biztosítva némi IDS funkcionalitást. Az outdated AIX verzióra való tekintettel ennek jelenléte még teljesen érthető is..

Első körben a kérdés az, hogy milyen modul biztosítja azt a hívást.. 2 lehetőség van ennek kiderítésére: Vagy rátámaszkodunk a naming convention-re, és azt mondjuk, hogy a pcd_output hívás valószínű valami pcd szerű driver hozza, vagy megnézzük, hogy az ISS csomagban van e, és ha igen, akkor milyen driverek vannak a csomagon belül.
# lslpp -l |grep ISS
  ISSXss.ServerSensor        7.0.0.0  COMMITTED  IBM RealSecure ServerSensor
  ISSXss.ServerSensor        7.0.0.0  COMMITTED  IBM RealSecure ServerSensor
  
# lslpp -f ISSXss.ServerSensor |grep driver
/usr/lib/drivers/
/usr/lib/drivers/pcd.ext
Na.. Így már biztosabbak lehetünk a dolgunkban. Következő kérdés, hogy a modul valóban be volt e töltve a dump pillanatában.. Irány vissza a kdb-be, majd listázzuk ki a betöltött modulokat, és szűrjünk arra amit találtunk:
(0)> lle -k |grep pcd.ext
  9 03EDDB00 0448C000 00016150 00080252 /usr/lib/drivers/pcd.ext
Bingo.. Tehát be volt töltve. Innentől akkor már csak az a kérdés, hogy ez okozta e a hibát, avagy az AIX. 100%-ra pontosan persze nem tudjuk megmondani, de azt azért érdemes megnézni, hogy az ISS-ünk is outdated-e.

Na itt kezdődött a következő problémám.. A hivatalos IBM javítások között a legfrissebb verzió a 7.0.42.2, a rendszeren viszont semmiféle utalás nincs a pontos verzióra nézve, csupán a csomag 7.0.0.0-ás verziószáma, ami viszont véletlenül se használható támpont.
A végleges megoldás végül az lett, hogy leszedtem a javítást az IBM FixCentral oldaláról, kicsomagoltam a base64 encode-olt telepítőt (így kaptam egy BFF csomagot), abból kibontottam a tényleges file-okat, és összehasonlítottam a checksum értékeket a rendszeren lévőkkel: Egyeztek -> Tehát ebből a programból legalább a legfrissebb verzió volt telepítve a gépre.

// Ez úton is üzenném minden programozónak, hogy valami nyamvadt verziózást rakjatok már bele a programotokba, különben lehetetlen lesz lekövetni, hogy épp mikor kell frissíteni az adott szoftvert.

Tehát a felállás innentől a következő: Van egy program, aminek a kernel module-ja szinte biztos, hogy szerepet kapott a hibában, viszont az a jelenlegi legfrissebb verzió, ergo vagy sikerült egy olyan bugba belebotlani, amire még vagy nincs javítás, vagy még nem is ismert, vagy tényleg az AIX outdated státusza okozta a galibát, és kompatibilitási hibával állunk szemben. Utóbbit sajna biztosra meg nem lehet mondani, mivel a hivatalos dokumentum véletlenül se taglalja, hogy van e TL/SP függősége, így nem maradt más hátra, mint közölni a customerrel, hogy nagy eséllyel tényleg frissíteni kéne az AIX-et (Minimum felrakni a legutolsó Service packot ehhez a TL-hez; azt az applikáció nagyobb eséllyel éli túl, mint mondjuk egy TL upgrade-et), bekapcsolni a dump compression-t, és ha az után is előjön a probléma, akkor újabb SW call-t nyitni. Ha ez nem kivitelezhető, akkor sorry, de ez egy olyan known risk amivel együtt kell majd élnie.

2013. március 3., vasárnap

"Mondanám hogy szőke, de sötét mint az éjszaka"

Azt hiszem írtam már ezen a blogon párszor, hogy az ember egy idő tán meglehetősen magasra emeli a mércét ha arról van szó, hogy min is lepődik meg X évnyi pályafutás után de sose mondja senki, hogy még ilyenkor se tudja kiverni semmi a biztosítékot.. Avagy amikor az ember azt hinné, hogy mélyebbre már nem lehet süllyedni, de valaki még is megtalálja a Mariana-árok mélyén a dugót, kihúzza azt, és a lezúduló víztömeg őt is magával ragadja..

Azok a pillanatok amikor az emberi hülyeség extra adag szorgalommal párosul.
Na ez is egy ilyen volt..

A történet ott kezdődik, hogy a /app_fs filerendszer elérhetetlenné vált a rendszeren, és valaki meg (hogy hogy nem) szerette volna viszont látni. Az ember ilyenkor megnézi az alap dolgokat (nincs e overmount, elérhető e a VG egyáltalán, mountolva van e az FS), majd konstatálja, hogy valami tényleg nem kerek:
server1:root:[/] # mount |grep -c /app_fs
0
server1:root:[/] # lsvg -l appvg |grep applv       
applv              jfs2       320     320     1    closed/syncd  /app_fs
server1:root:[/] # lslv -l applv
applv:/app_fs
PV                COPIES        IN BAND       DISTRIBUTION  
hdisk7            320:000:000   27%           000:089:089:089:053 
server1:root:[/] # lsvg -p appvg
appvg:
PV_NAME           PV STATE          TOTAL PPs   FREE PPs    FREE DISTRIBUTION
hdisk2            active            319         0           00..00..00..00..00
hdisk3            active            1599        0           00..00..00..00..00
hdisk4            active            799         0           00..00..00..00..00
hdisk5            active            959         0           00..00..00..00..00
hdisk6            active            319         32          00..00..00..00..32
hdisk7            missing           447         127         90..00..00..00..37
Őő... Jaj... Na szóval.. Van az FS, ami épp closed-ban van (ez meg is magyarázza hova tűnt a filerendszer :)), ami épp a hdisk7en terül el, ami meg kopp hiányzik az lsvg szerint.. AIX mit tud minderről?
server1:root:[/] # lsdev -Cc disk
hdisk0 Available  Virtual SCSI Disk Drive
hdisk1 Available  Virtual SCSI Disk Drive
hdisk2 Available  Virtual SCSI Disk Drive
hdisk3 Available  Virtual SCSI Disk Drive
hdisk4 Available  Virtual SCSI Disk Drive
hdisk5 Available  Virtual SCSI Disk Drive
hdisk6 Available  Virtual SCSI Disk Drive
hdisk7 Available  Virtual SCSI Disk Drive

server1:root:[/] # lspv |grep appvg
hdisk5          00c3b9f4e1709f60                    appvg           active
hdisk2          00c5effd70395ab2                    appvg           active
hdisk3          00c5effd7c2e18d2                    appvg           active
hdisk4          00c3b9f4aeed3ccd                    appvg           active
hdisk7          00c3b9f4b2a59c9b                    appvg           active
hdisk6          00c3b9f47a309de6                    appvg           active
Él és virul, minden szép, akkor meg mi a fene? Olvassunk már rá a VGDA-ra...
server1:root:[/] # for i in $(lsvg -p appvg |awk '/hdisk/{print $1}');do echo "$i \c";readvgda /dev/$i|grep vg_id;done    
hdisk2 vg_id:           00c5effd00004c000000010da807da15
hdisk3 vg_id:           00c5effd00004c000000010da807da15
hdisk4 vg_id:           00c5effd00004c000000010da807da15
hdisk5 vg_id:           00c5effd00004c000000010da807da15
hdisk6 vg_id:           00c5effd00004c000000010da807da15
hdisk7 vg_id:           00c5effd00004c0000000110796187ae
őőő.. What?? Na szóval.. van egy PV, elérhető, elvileg része a VG-nek, gyakorlatilag meg nem (más a vg_id)... Kis gondolkodás hogy is lehet ez, majd szembejött a megvilágosodás hangos kürt szóval: Ezt a PV-t valaki más is használatba vette!

Tekintve, hogy Virtual diszk, így spuri a VIO-hoz, majd gyors lekérdezések után elő is jött a bűnös probléma:
padmin:vios:[/home/padmin] $ lsmap -all |grep -p hdisk108
VTD                   server2_hdisk4
Status                Available
LUN                   0x8700000000000000
Backing device        hdisk108
Physloc               U7311.D20.0637FDC-P1-C02-T1-W5005076801302EA8-L19000000000000

VTD                   server1_hdisk7
Status                Available
LUN                   0x8400000000000000
Backing device        hdisk108
Physloc               U7311.D20.0637FDC-P1-C02-T1-W5005076801302EA8-L19000000000000
És valóban.. És akkor mit csinál a másik gépen a PV?
server2:root:[/] # lspv
hdisk0          00c3b9f42b11232e                    rootvg          active 
hdisk1          00c3b9f4724a36f5                    rootvg          active 
hdisk2          00c5effd70926735                    dbvg        active 
hdisk3          00c3b9f418b7da43                    dbvg        active 
hdisk4          00c3b9f4b2a59c9b                    dbvg        active 
hdisk5          00c3b9f47715582b                    dbvg        active 
Na most alapjáraton ilyenkor jut eszembe tanult kollégám szava járása miszerint: "Some people just need a hug... around their neck... with a rope."

Egy óriási mázlink volt csak.. Ez:
server2:root:[/] # lspv -l hdisk4
server2:root:[/] # 
Tehát.. Ott a másik szerver, valaki idióta kiassignolta ugyan azt a LUN-t neki, majd berakta egy másik VG-be, ami felül is vágta a VGDA-t, de mákunkra nem használja ezen felül semmire, így a PV-n lévő adat a VGDA-t leszámítva sértetlen.

# Azt azért jegyezzük meg, hogy valaminek az ilyen nagyságrendű elcseszése is igen nagy erőfeszítésbe telik, ugyan is mind a VIO szerver, mind az AIX közli, hogy "Ez mintha már használatban lenne, úgy hogy ha biztos vagy a dolgodban, akkor a -force-ot add még meg a parancshoz" ergo 2x is szorgalmas hülyének kell lennie valakinek, hogy ezt összehozza..

Na jó.. akkor a kérdés már csak az, hogy hogy is varázsoljuk vissza a PV-t a helyére..
A hivatalos megoldás kb annyi, hogy "Reméljük van backupod az FS-ről, mert az FS-t/LV-t törölni kell, kiszedni a PV-t mind a 2 VG-ből (a 2. szerveren menni fog, az eredetin csak félig), szedd le a VIO-ról a LUN zónázást, majd aztán extendvg-vel rakd vissza a PV-t az eredeti VG-be, hozd létre a filerendszert, aztán backupból töltsd vissza az adatokat".

Na ez pont az amit nem akarunk :) (Meg ez a blog bejegyzés se született volna akkor meg).. A mi célunk, hogy az adatokat élve visszaszerezzük. A hogyan már jobb kérdés. Ami tiszta az az, hogy az új VG-ben nem maradhat a PV, úgy hogy onnan szedjük ki, aztán meg a VIO-ról szedjük le a LUN allokációt, hogy csak a source szerveren legyen a PV elérhető.

A következő "elméleti" lépés pedig az lenne, hogy rakjuk vissza a VGDA-t az érintett PV alá..
Ennek kivitelezése némi kis elméleti háttérismeretet igényel:
- AIX alatt minden VG felépítése azonos (az elmélet legalább is, a kivitelezésben vannak némi eltérések)
- Minden VG-ben lévő PV tartalmazza a VGDA-t (A PV elején), amely leírja, hogy a VG alatt pontosan milyen PVID-jű diszkek találhatók, azokon belül melyik PV-n milyen LV-k (és milyen kiosztásban) helyezkednek el, van e LV tükrözés (mirroring), és hasonló úri huncutságok.
- Ergo a dolog szépsége, hogy mindenki tud többé kevésbé mindenkiről mindent, 1-2 dolgot leszámítva, és csak 1-2 alapvető dolog különbözik

# Megjegyzem azért, hogy van a VGDA-ban 1-2 olyan adat is, ami meglehetősen szemétnek minősül és PV-nként eltérhet, de azokkal most nem fogok foglalkozni
Na szóval a feladat a következő: Fogjunk a VG-ből egy egészséges diszket, pakoljuk át a VGDA-ját a hibás PV-re, írjuk át azt ami PV specifikus, aztán imádkozzunk, hogy minden menni fog

!!! Had ne mondjam, hogy ez a módszer véletlenül és semmilyen körülmény között sem támogatott hivatalosan, így ha valakinek van IBM-es szerződése az inkább nyisson PMR-t ha tényleg fontos adatról van szó!!!

Akkor kezdjük az első lépést.. VGDA átmásolás.. Hogy ezt meg tudjuk csinálni 1x is tudnunk kell a VGDA méretét, ez viszont VG típusonként más, úgy hogy tudni kell a VG típusát is :) Ehhez kell egy VG-n belüli PV, amin még minden rendben van, legyen ez mondjuk a hdisk2 (mert csak, amúgy bármelyik másik jó lenne)
server1:root:[/] # readvgda /dev/hdisk2 |grep type
.....    readvgda_type: smallvg
vgtype:         0

# Némi kis segítség a VGDA méretének megállapításában:
# Small VG: 17x 128K
# Big VG: 71x 128K
# Scalable: 548x 128K

Jó.. Most hogy tudjuk mi és merre csináljunk egy backupot a jelenlegi VGDA-ról (igen, amit előzőleg nulláztunk, de akkor is legyen lehetőség visszaállítani ami volt), aztán vágjuk is felül :)
server1:root:[/] # dd if=/dev/hdisk7 of=/tmp/hdisk7.smallvg.vgda.save bs=128K count=17
17+0 records in
17+0 records out
server1:root:[/] # dd if=/dev/hdisk2 of=/dev/hdisk7 bs=128K count=17
17+0 records in
17+0 records out
A következő egyedi azonosító a PV ID-ja lenne (nem összekeverendő a PVID-val), ami megmondja, hogy az adott diszk hányadik is a VG-n belül. Ehhez első körben meg kell keresni, hogy az adott adat hol is tárolódik (VG-nként máshol, de mindig az LVM leíró környékén). Én általában az első 1000 szektorcsoportot keresem végig:
server1:root:[/] # lquerypv -h /dev/hdisk2 0 1000 |grep LVM
00000E00   5F4C564D 00C5EFFD 00004C00 0000010D  |_LVM......L.....|
Szupi.. Tehát 0E00 körül keződidik az LVM leíró része.
Akkor most nézzük meg mi van azon a környéken:
server1:root:[/] # lquerypv -h /dev/hdisk2 e00 40
00000E00   5F4C564D 00C5EFFD 00004C00 0000010D  |_LVM......L.....|
00000E10   A807DA15 00001074 00000832 00000088  |.......t...2....|
00000E20   000008C2 013FFEFF 00000100 00010019  |.....?..........|  
00000E30   00000008 00000080 000008BA 001E0000  |................|
Na most ebből lehet nem sok derül ki annak aki nem tudja mit keressen, de ha összenézzük ugyan ezt a többi diszk VGDA-jával, akkor remélhetőleg már könyebben rájön mindenki hol is van a kutya elásva:
server1:root:[/] # for i in $(lsvg -p appvg |grep -v hdisk7 |awk '/hdisk/{print $1}');do echo $i;lquerypv -h /dev/$i e00 40;done
hdisk2
00000E00   5F4C564D 00C5EFFD 00004C00 0000010D  |_LVM......L.....|
00000E10   A807DA15 00001074 00000832 00000088  |.......t...2....|
00000E20   000008C2 013FFEFF 00000100 00010019  |.....?..........|  <= '0001' a 0x0E2C címnél
00000E30   00000008 00000080 000008BA 001E0000  |................|
hdisk3
00000E00   5F4C564D 00C5EFFD 00004C00 0000010D  |_LVM......L.....|
00000E10   A807DA15 00001074 00000832 00000088  |.......t...2....|
00000E20   000008C2 063FFEFF 00000100 00020019  |.....?..........|  <= '0002' a 0x0E2C címnél
00000E30   00000008 00000080 000008BA 001E0000  |................|
hdisk4
00000E00   5F4C564D 00C5EFFD 00004C00 0000010D  |_LVM......L.....|
00000E10   A807DA15 00001074 00000832 00000088  |.......t...2....|
00000E20   000008C2 031FFEFF 00000100 00030019  |................|  <= '0003' a 0x0E2C címnél
00000E30   00000008 00000080 000008BA 001E0000  |................|
hdisk5
00000E00   5F4C564D 00C5EFFD 00004C00 0000010D  |_LVM......L.....|
00000E10   A807DA15 00001074 00000832 00000088  |.......t...2....|
00000E20   000008C2 03BFFEFF 00000100 00040019  |................|  <= '0004' a 0x0E2C címnél
00000E30   00000008 00000080 000008BA 001E0000  |................|
hdisk6
00000E00   5F4C564D 00C5EFFD 00004C00 0000010D  |_LVM......L.....|
00000E10   A807DA15 00001074 00000832 00000088  |.......t...2....|
00000E20   000008C2 013FFEFF 00000100 00050019  |.....?..........|  <= '0005' a 0x0E2C címnél
00000E30   00000008 00000080 000008BA 001E0000  |................|
Ha megfigyelitek, akkor az VGDA leírók ezen része szinte teljesen egyezik, kivétel a 0x0E2D címen lévő érték, ami szépen növekszik 1től 5ig.. Na most ha még emlékeztek a post elejére, akkor 6 PV volt hivatalosan ebben a VG-ben:
server1:root:[/] # readvgda /dev/hdisk2 |grep pv_id |cat -n
     1  pv_id:          00c5effd7c2e18d2
     2  pv_id:          00c5effd70395ab2
     3  pv_id:          00c3b9f4aeed3ccd
     4  pv_id:          00c3b9f4e1709f60
     5  pv_id:          00c3b9f47a309de6
     6  pv_id:          00c3b9f4b2a59c9b 
Tehát, a PV ID (!=PVID) a hiányzó diszkünknél a 6os lesz, amit vissza is kéne írni a megfelelő pontra.. dd-vel ez megoldható, de ahhoz decimálisan tudnunk kell a pontos poziciót:
server1:root:[/] # echo "ibase=16; E2D" |bc
3629
3629.. Jó. Akkor írjuk is be a helyére a megfelelő értéket:
server1:root:[/] # echo "\06" | dd of=/dev/hdisk7 bs=1 count=1 seek=3629
1+0 records in
1+0 records out
Ez után jön akkor a tényleges PVID. Ha még emlékeztek, akkor erre anno mutattam is egy módszert, amit ismét elő is szedek, és visszaírom az eredetileg a PV-n lévő PVID-t:

A script maga:
server1:root:[/] # cat /tmp/chpvid.sh
#!/usr/bin/ksh
pvid=$1
disk=$2
set -A a `echo $pvid|\
awk ' {
 for (f=1; f <= length($0); f=f+2) {
 print "ibase=16\nobase=8\n"toupper(substr($0,f,2))
 }
}'|\
bc 2>/dev/null`
/usr/bin/echo "\0"${a[0]}"\0"${a[1]}"\0"${a[2]}"\0"${a[3]}"\0"\
${a[4]}"\0"${a[5]}"\0"${a[6]}"\0"${a[7]}"\0\0\0\0\0\0\0\0\c"|\
dd bs=1 seek=128 of=/dev/$disk
A futtatás módja:
server1:root:[/] # sh /tmp/chpvid.sh 00c3b9f4b2a59c9b hdisk7
16+0 records in
16+0 records out
Visszaellenőrzés:
server1:root:[/] # od -A n -j 128 -N 8 -x /dev/hdisk7
         00c3 b9f4 b2a5 9c9b
VGDA ellenőrzés:
server1:root:[/] # for i in $(lsvg -p appvg |awk '/hdisk/{print $1}');do echo "$i \c";readvgda /dev/$i|grep vg_id;done    
hdisk2 vg_id:           00c5effd00004c000000010da807da15
hdisk3 vg_id:           00c5effd00004c000000010da807da15
hdisk4 vg_id:           00c5effd00004c000000010da807da15
hdisk5 vg_id:           00c5effd00004c000000010da807da15
hdisk6 vg_id:           00c5effd00004c000000010da807da15
hdisk7 vg_id:           00c5effd00004c000000010da807da15
Még mielött tényleg bármit is csinálnánk nézzük meg, hogy minden tényleg úgy van ahogy volt:
server1:root:[/] # lsvg -p appvg
appvg:
PV_NAME           PV STATE          TOTAL PPs   FREE PPs    FREE DISTRIBUTION
hdisk2            active            319         0           00..00..00..00..00
hdisk3            active            1599        0           00..00..00..00..00
hdisk4            active            799         0           00..00..00..00..00
hdisk5            active            959         0           00..00..00..00..00
hdisk6            active            319         32          00..00..00..00..32
hdisk7            missing           447         127         90..00..00..00..37
Aztán térdre imára, és varyon-oljuk vissza a VG-t:
server1:root:[/] # varyonvg appvg
server1:root:[/] # lsvg -p appvg
appvg:
PV_NAME           PV STATE          TOTAL PPs   FREE PPs    FREE DISTRIBUTION
hdisk2            active            319         0           00..00..00..00..00
hdisk3            active            1599        0           00..00..00..00..00
hdisk4            active            799         0           00..00..00..00..00
hdisk5            active            959         0           00..00..00..00..00
hdisk6            active            319         32          00..00..00..00..32
hdisk7            active            447         127         90..00..00..00..37

Hoppá... alakul a molekula :) Nézzük mi van szeretett filerendszerünkel:
server1:root:[/] # mount /app_fs
Replaying log for /dev/applv.
mount: /dev/applv on /app_fs_rest: Unformatted or incompatible media
The superblock on /dev/applv is dirty.  Run a full fsck to fix.
Na jó.. ez várható volt.. Adjuk meg amit kér:
server1:root:[/] # 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
File system is clean.
Superblock is marked dirty; FIX? y
All observed inconsistencies have been repaired.
Aztán próbáljuk meg újra:
server1:root:[/] # mount /app_fs
server1:root:[/] # 
Profit :))

2012. július 25., szerda

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

2011. október 16., vasárnap

Elvitte a cica.. De hova bújt???

Pénteken olyan hibába botlottam bele, hogy azt hittem ilyen nem is létezhet.. Így hát amikor sikerült megtalálnom mi és hogy is történ(hetet)t persze, hogy úgy gondoltam, hogy ezt le kell blogoljam.. Íme egy némileg összeszedett beszámoló arról, hogy mi és hogy történt a probléma felderítése során:

Nos hát.. Alap probléma: Restart után a szerveren nem használható a /dev/null...
Nézek ki a fejemből, hogy ez miért és hogy, de a hibaüzenet egyértelműen fogalmaz:
server@user:/home/user $ ls > /dev/null
Permission denied
ksh: /dev/null: cannot create
Gyorsan átmásztam root-ba, megnéztem mi a helyzet a környéken:
server@root:/home/root # ls -ld /dev/null
crw-rw-rw-    1 root     system        2,  2 Oct 15 16:29 /dev/null
server@root:/home/root # ls -ld /dev
drw-------    5 root     system       356352 Oct 15 15:00 /dev
Aham.. hogy csak a root-nak van valami joga a mappára.. Ki lehetett az a hülye, aki átlőtte??? Na mind1, rakjuk helyére..
server@root:/home/root # chmod 775 /dev
server@root:/home/root # ls -ld /dev
drwxrwxr-x    5 root     system       356352 Oct 15 15:00 /dev
Kicsit matattam még a gépen, tettem-vettem, amikor is egy újabb parancs kiadásakor ismét ugyan ebbe a hibába botlottam (Permission denied).. Nézem ismét a /dev jogait.. megint 600... Hát mondom ilyen nincs.. valaki ilyen hülye, és még aktívan a gépen is van? Ha megtalálom nem hogy a root jogot veszem el tőle, hanem még a kezét is letöröm.. Ez a kis "lelkesedés" addig tartott, amíg észre nem vettem, hogy rajtam kívül nincs senki a gépen.. Feltételezve, hogy én nem műveltem ilyen hülyeséget néztem hogy akkor ez most WTF.. Valaki távolról, vagy hogy??? Hát mondom akkor játsszuk ezt..

Visszaállítottam a /dev jogait 775-re, majd kb 5-10 mp-enként visszaellenőriztem 'ls -ld /dev'-el, hogy mi is lehet itt.. Kb ezt kaptam:
server@root:/home/root # ls -ld /dev
drwxrwxr-x    5 root     system       356352 Oct 14 15:10 /dev
server@root:/home/root # ls -ld /dev
drwxrwxr-x    5 root     system       356352 Oct 14 15:10 /dev
server@root:/home/root # ls -ld /dev
drwxrwxr-x    5 root     system       356352 Oct 14 15:10 /dev
server@root:/home/root # ls -ld /dev
drw-------    5 root     system       356352 Oct 14 15:10 /dev
Hát mondom ilyen nincs.. valaki garázdálkodik itt, vagy mifene?? Hát a jó nénikéjét.. Fogjuk már meg..
Első gondolatom az volt, hogy az audit subsystem tökéletesen megfelel ennek kiderítésére.. De nézzük hogy is lehet ezt kivitelezni?
- /etc/security/audit/objects alá fel lehet ugyan venni a /dev-et, de az objects alatt csak read/write/execute event-eket lehet vizsgálni.. Itt meg látható, hogy az nem segítene, ergo ez nem nyert hangszórót
- Gondoltam, hogy ha valami itt a /dev jogait piszkálja, akkor a chmod-ot kell hívnia kötelezően.. Hát akkor induljunk el ebbe az irányba: Vegyünk fel a chmod parancsot az objects alá az alábbi módon:
/usr/bin/chmod:
 x = "CHMOD_USE"
Illetve a /etc/security/audit/events alá az új eventünket:
* chmod execution
  CHMOD_USE = printf "pid: %d, command: %s"
Amint ezzel kész vagyunk indítsuk újra az audit subsystem-et:
server@root:/ # audit shutdown
auditing reset
server@root:/ # audit start
server@root:/ # audit query |grep auditing
auditing on
server@root:/ # audit query |tail -2
 /usr/bin/chmod:
  x = "CHMOD_USE"
Oksa.. Tehát akkor elvileg ez is a helyén van.. akkor már csak az kell, hogy realtime nézhessük mi is folyik a gépen. Ezt az alábbi módon oldottam meg:
server@root:/ # /usr/sbin/auditstream | /usr/sbin/auditpr -t0 -heRltc |grep CHMOD
Ezzel a paranccsal lényegében direktbe szűrhetek arra, amire szeretnék.. Ergo fogtam magam, nyitottam egy újabb terminált, majd ott követtem a /dev változásait, miközben ez a stream az 'egyes" terminálon szépen futott. Direkt átírtam a chmod jogait ismét 775-re (megint 600on volt), és konstatáltam, hogy az audit igen is látja a módosításom:
CHMOD_USE       OK          root  Fri Oct 14 17:06:52 2011 chmod
Ezt követően csak vártam, és a másodlagos terminálon követtem a /dev esetleges változásait.. Egészen addig amíg a terminálon láttam, hogy a jogok megváltoztak, de az audit ebből semmit nem vett észre... WTF!? Audit stop, mit szúrtam el?? Lehet van máshol is chmod a rendszeren???
server@root:/ # find / -name chmod -type f -ls
 1057    9 -r-xr-xr-x  1 bin       bin           9216 Jul  9  2009 /usr/bin/chmod
Nincs, csak ez az egy.. Akkor meg hogy a fenébe??? Na jó, mind1.. Az auditról tudni illik, hogy azért nem csak az objects file-ja használható, hanem alapértelmezetten az events-ek között jó pár más event is előre van definálva, mint például ezek:
*       chmod()
        FILE_Mode = printf "mode: %o filename %s"

*       fchmod()
        FILE_Fchmod = printf "mode: %o file descriptor %d"
A rendszer alaptelepítés esetén ezeket nem használja (tekintve, hogy iszonyat sok adatot is generálnának), de nekem most ideiglenesen ezek pont jónak tűntek.. Meg is néztem, hogy a configon belül ezek hol vannak definiálva, és a classes alatt gyönyörűen ott sorakozott az alábbi sor:
files = FILE_Open,FILE_Read,FILE_Write,FILE_Close,FILE_Link,FILE_Unlink,FILE_Rename,FILE_Owner,FILE_Mode,FILE_Acl,FILE_Privilege,DEV_Create
A FILE_Mode alapból ott volt a files class-ban, viszont a FILE_Fchmod nem, így azt is felvettem (biztosra megyek, úgy voltam vele), így kaptam ezt a sort:
files = FILE_Open,FILE_Read,FILE_Write,FILE_Close,FILE_Link,FILE_Unlink,FILE_Rename,FILE_Owner,FILE_Mode,FILE_Acl,FILE_Privilege,DEV_Create,FILE_Fchmod
Ez után már csak az kellett, hogy ezt a class-t felvegyem a users szekció alatt a root-hoz az alábbi módon:
users:
        root = general,files
        default = objects
Rendicsek.. Akkor ez is megvan.. Biztos ami biztos kiszedtem az objests-ből előzőleg definiált chmod figyelést is, majd újraindítottam az auditot, és eljátszottam pontosan ugyan azt mint előzőleg -> egyik konzolon futott az auditing stream-je (immár grep -E "FILE_Mode|FILE_Fchmod" szűréssel), a másikon meg a /dev vizsgálata. Átállítottam ismét a /dev jogait 775-re (ekkor már kifejezetten idegesített az issue), majd örömmel konstatáltam, hogy az audit észrevette ezt a súlyos cselekményt:
FILE_Mode       OK          root  Fri Oct 14 18:05:25 2011 chmod
Újabb 1-2 percnyi várakozás, és minden elvárás ellenére ugyan az az eredmény!!! -> Az audit nem veszi észre azt ami ezt csinálja, csak azt amit én manuálisan ráengedek.. Ekkor sejtettem, hogy ez valószínű nem valami user hülyesége, hanem lehet valami bug, mert a forkot az audit tuti észrevenné.

Innentől viszont nyilvánvalóvá vált, hogy az audit e célra itt nem fog bejönni.. Kénytelen voltam elővenni a nagyágyút: trace
Szerencsémre a trace azért meglehetősen jól használható AIX alatt, feltéve ha az ember tudja hogy is használja.. Az már csak hab a tortán, hogy van egy csomó előre definiált trace event group, amik közül az alábbiak közül választhattam (A / JFS2 típusú)
server@root:/ # trcrpt -G |grep jfs2
jfs2 - JFS2: all JFS2 operations (reserved)
jfs2meta - JFS2: metadata operations (reserved)
jfs2user - JFS2: userdata operations (reserved)
jfs2snap - JFS2: snapshot operations (reserved)
Megvan azért annak az előnye, ha nem kell az embernek fejből tudnia az összes hookot :)) Ami viszont engem illetett - úgy voltam vele, hogy ennyi szívás után nem szórakozok: minden JFS2 módosításról tudni akarok!!! Ergo fogtam magam, és az alábbi módon jártam el:
server@root:/ # chmod 775 /dev
server@root:/ # ls -ld /dev
drwxrwxr-x    5 root     system       356352 Oct 15 15:00 /dev
server@root:/ # trace -a -J jfs2 -o /tmp/trc_raw 
server@root:/ # trcon
A másik konzolon meg az alábbi kis while ciklussal vártam, hogy mikor is történik pontosan (!) a váltás:
server@root:/ # while true;do echo "$(date +"%Y.%m.%d %H:%M:%S") $(ls -ld /dev)";sleep 1;done
2011.10.14 18:42:00 drwxrwxr-x    5 root     system       356352 Oct 14 18:30 /dev
2011.10.14 18:42:01 drwxrwxr-x    5 root     system       356352 Oct 14 18:30 /dev
2011.10.14 18:42:02 drwxrwxr-x    5 root     system       356352 Oct 14 18:30 /dev
2011.10.14 18:42:03 drwxrwxr-x    5 root     system       356352 Oct 14 18:30 /dev
2011.10.14 18:42:04 drwxrwxr-x    5 root     system       356352 Oct 14 18:30 /dev
2011.10.14 18:42:05 drwxrwxr-x    5 root     system       356352 Oct 14 18:30 /dev
2011.10.14 18:42:06 drwxrwxr-x    5 root     system       356352 Oct 14 18:30 /dev
2011.10.14 18:42:07 drwxrwxr-x    5 root     system       356352 Oct 14 18:30 /dev
2011.10.14 18:42:08 drwxrwxr-x    5 root     system       356352 Oct 14 18:30 /dev
2011.10.14 18:42:09 drwxrwxr-x    5 root     system       356352 Oct 14 18:30 /dev
2011.10.14 18:42:10 drwxrwxr-x    5 root     system       356352 Oct 14 18:30 /dev
2011.10.14 18:42:11 drwxrwxr-x    5 root     system       356352 Oct 14 18:30 /dev
2011.10.14 18:42:12 drw-------    5 root     system       356352 Oct 14 18:30 /dev
2011.10.14 18:42:13 drw-------    5 root     system       356352 Oct 14 18:30 /dev
2011.10.14 18:42:14 drw-------    5 root     system       356352 Oct 14 18:30 /dev
Amint erre a pontra jutottam nyomban le is állítottam a trace-t, majd amikor állítottam volna le ezt a while ciklust konstatálhattam, hogy a CTRL+C nem működik!! -> Mint kiderült: Ha belépéskor nincs a /dev-nek elég joga, akkor a CTRL+C nem fog menni, hiába van jól belőve az 'intr' érték az stty alatt:
server@root:/ # stty -a |grep intr
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = 
Amint átállítottam a /dev jogait, és nyitottam egy új shell-t nyomban visszaállt minden a régibe az adott shellen belül.. A másikon meg killelhettem a ciklust.

Na mind1.. Nézzük azt a trace-t
server@root:/ # trcoff
server@root:/ # trcrpt -O "exec=on,pid=on" /tmp/trc_raw > /tmp/trc_raw.out
server@root:/ # ls -l /tmp/trc_raw.out
-rw-------    1 root     system      7213429 Oct 14 18:26 /tmp/trc_raw.out
Kb sejthetitek miért is nem olyan gyakori a trace használata ebből már: kevesebb mint fél perc alatt majd 7 MB adat generálódott a riportban! Na de, ha már megvannak az adatok, akkor igen is nézzük át mi és hogy lehetett.. A probléma csupán az, hogy ~7 MB-ot átnyálazni kicsit sokáig tart, meg jelen esetben amúgy se célravezető.. Jobb volt inkább megnézni, hogy mely processek használták a /dev-et..

Ehhez első körben tudni kell a /dev inode számát, hogy legalább legyen mire szűrnünk:
server@root:/tmp # istat /dev
Inode 12289 on device 10/5      Directory
Protection: rw-------   
Owner: 0(root)          Group: 0(system)
Link count:   5         Length 356352 bytes

Last updated:   Fri Oct 14 18:30:10 2011
Last modified:  Fri Oct 14 18:30:10 2011
Last accessed:  Fri Oct 14 18:30:27 2011
Oks.. Tehát 12289.. Ezt nyomban át is kell váltanunk hexába, ami meg 3001.. Ezt a számot használva meg könnyen szűrhetünk is. Ha viszont csak így magában tesszük, akkor ilyen hosszú rettentő sorokat kapunk:
server@root:/ # grep -w 3001 /tmp/trc_raw.out |head -5
4DF --1-           -1            0.003434251       0.001326                   JFS2 iget: vp = F100011010C3B3E8, count = 0001, ino = 3001, dev = 8000000A00000005, getcaller = 2CF754
4DF --1-           -1            0.003444816       0.005402                   JFS2 iput: vp = F100011010C3B3E8, count = 0000, ino = 3001, nlink = 0005, getcaller = 2CF9DC
4DF --1-           -1            0.003447171       0.000623                   JFS2 iget: vp = F100011010C3B3E8, count = 0001, ino = 3001, dev = 8000000A00000005, getcaller = 2CF754
4DF --1-           -1            0.003452763       0.003297                   JFS2 iput: vp = F100011010C3B3E8, count = 0000, ino = 3001, nlink = 0005, getcaller = 2CF9DC
4DF --1-           -1            0.003455013       0.000683                   JFS2 iget: vp = F100011010C3B3E8, count = 0001, ino = 3001, dev = 8000000A00000005, getcaller = 2CF754
Ergo lehet jobban járunk ha inkább a statisztikára vagyunk kíváncsiak:
server@root:/ #  grep -w 3001 /tmp/trc_raw.out |awk '{print $2}'|sort|uniq -c
   761 --1-
   2 cdromd
   36 init
Mindjárt jobb.. Tehát.. 761 hozzáférés a kernel részéről, 2 hozzáférés a cdromd-től, 36 az inittől.. A kernellel ugye nem sokat tudok kezdeni (az meg csak nem vetemedik ilyenre!), ergo maradt a másik 2 - cdromd, meg init.. Első körben így hát fogtam magam, 'stopsrc -s cdromd'-vel leállítottam a daemon-t, visszalőttem a /dev-et 775-re, majd vártam, hogy változik e a jogosultsága.. Változott.. Ergo akkor nem a cdromd.. Vissza is kapcsoltam.

A másik lehetőség az init volt.. Erről ugye annyit illik tudni, hogy a /etc/inittab file-ban tárolt bejegyzések alapján ténykedik. Amennyiben egy program/script respawn-ra van állítva, akkor az időről időre meg is hívódik, ami meg is magyarázná, hogy hogy lehet az, hogy user interakció nélkül változzon a /dev jogosultsága.. Nade a baj az, hogy az inittab-ban azért csak úgy nem turkálunk, a cdromd-hez hasonló teszteléseket (állítsuk le, aztán nézzük meg jó lesz e úgy) meg itt már nem biztos hogy jó ötletnek tartanám..

Azt viszont tudnunk kell, hogy amennyiben az inittab indít valamit, úgy annak a bejegyzése beleíródik a wtmp-be is.. Én meg az előző mérésemből tudtam a pontos időpontot (18:42:12), így az alapján már könnyen el lehetett indulni:
server@root:/ # cat /var/adm/wtmp |/usr/sbin/acct/fwtmp |grep "Fri Oct 14 18:42:1[012]"
         cons                         8 155664 0000 0001 1318614131                                  Fri Oct 14 18:42:11 2011
cons     cons                         5 58206 0000 0000 1318614131                                  Fri Oct 14 18:42:11 2011
         cons                         8 58206 0000 0001 1318614131                                  Fri Oct 14 18:42:11 2011
cons     cons                         5 58208 0000 0000 1318614131                                  Fri Oct 14 18:42:11 2011
         cons                         8 58208 0000 0001 1318614131                                  Fri Oct 14 18:42:11 2011
cons     cons                         5 221186 0000 0000 1318614131                                  Fri Oct 14 18:42:11 2011
         cons                         8 221186 0000 0001 1318614132                                  Fri Oct 14 18:42:12 2011
cons     cons                         5 57910 0000 0000 1318614132                                  Fri Oct 14 18:42:12 2011
         cons                         8 57910 0000 0001 1318614132                                  Fri Oct 14 18:42:12 2011
cons     cons                         5 221188 0000 0000 1318614132                                  Fri Oct 14 18:42:12 2011
         cons                         8 221188 0000 0001 1318614132                                  Fri Oct 14 18:42:12 2011
cons     cons                         5 221190 0000 0000 1318614132                                  Fri Oct 14 18:42:12 2011
Aham.. Tehát a cons bejegyzés a ludas.. Az meg a getty-t hívogatja..
server@root:/ # lsitab cons
cons:0123456789:respawn:/usr/sbin/getty /dev/console
Respawn is ahogy vártam, de most komolyan a getty okozna nekem ilyen gondokat? Hát nézzük meg:
server@root:/tmp # ls -ld /dev; /usr/sbin/getty /dev/console;ls -ld /dev
drwxrwxr-x    5 root     system       356352 Oct 14 18:30 /dev
/dev/: TSM was unable to open port "/dev/"
drw-------    5 root     system       356352 Oct 14 18:30 /dev
Aham.. Hát most vagy én vagyok nagyon balszerencsés, és pont abban az időben történt más is, vagy a getty tényleg ilyen problémákkal küszködik.. (A TSM-es hibára még visszatérek). Tekintve, hogy a 'getty /dev/console'-t manapság inkább csak virtual console-okhoz használják, így szívfájdalom nélkül kikapcsoltam, majd vártam, hogy történjen valami:
server@root:/tmp # chitab cons:0123456789:off:"/usr/sbin/getty /dev/console"
server@root:/tmp # chmod 755 /dev
server@root:/ # while true;do echo "$(date +"%Y.%m.%d %H:%M:%S") $(ls -ld /dev)";sleep 1;done
2011.10.14 18:46:11 drwxrwxr-x    5 root     system       356352 Oct 14 18:30 /dev
......
2011.10.14 18:46:40 drwxrwxr-x    5 root     system       356352 Oct 14 18:30 /dev
...
2011.10.14 18:46:57 drwxrwxr-x    5 root     system       356352 Oct 14 18:30 /dev
...
2011.10.14 18:47:22 drwxrwxr-x    5 root     system       356352 Oct 14 18:30 /dev
...
2011.10.14 18:47:38 drwxrwxr-x    5 root     system       356352 Oct 14 18:30 /dev
...
2011.10.14 18:47:58 drwxrwxr-x    5 root     system       356352 Oct 14 18:30 /dev
...
2011.10.14 18:48:20 drwxrwxr-x    5 root     system       356352 Oct 14 18:30 /dev
2011.10.14 18:48:21 drwxrwxr-x    5 root     system       356352 Oct 14 18:30 /dev
2011.10.14 18:48:22 drwxrwxr-x    5 root     system       356352 Oct 14 18:30 /dev
2011.10.14 18:48:23 drwxrwxr-x    5 root     system       356352 Oct 14 18:30 /dev
2011.10.14 18:48:24 drwxrwxr-x    5 root     system       356352 Oct 14 18:30 /dev
2011.10.14 18:48:25 drwxrwxr-x    5 root     system       356352 Oct 14 18:30 /dev
2011.10.14 18:48:26 drwxrwxr-x    5 root     system       356352 Oct 14 18:30 /dev
2011.10.14 18:48:27 drwxrwxr-x    5 root     system       356352 Oct 14 18:30 /dev
2011.10.14 18:48:28 drwxrwxr-x    5 root     system       356352 Oct 14 18:30 /dev
2011.10.14 18:48:29 drwxrwxr-x    5 root     system       356352 Oct 14 18:30 /dev
Ctrl+C.. Őszinte leszek.. Még mindig nem értettem a dolgot.. Ezek szerint tényleg a getty okozza a problémát.. De miért?? Nézzük a konzol beállításokat:
server@root:/tmp # lscons -a
 current = NULL
 console_logname = /var/adm/ras/conslog
 console_logsize = 32768
 console_logverb = 1
 console_tagverb = 0
Na jó.. Beismerem.. Ez tényleg nem egészséges.. Ezt azonnal orvosolni kell:
server@root:/tmp # chcons -a login=enable /dev/vty0
chcons: Console login cannot be enabled because the console device
        is not an available lft, tty, or vty.
Hö??? WTF??? Mi van a vty0-val?
server@root:/tmp # lsdev -Cctty
vty0 Defined  Asynchronous Terminal
Jah hogy úgy.. Na ezt rántsuk már be akkor:
server@root:/tmp # cfgmgr -l vty0
Method error (/etc/methods/cfgtty -l vty0 ):
        0514-040 Error initializing a device into the kernel.
Na menj a tudod hova... Van más is amiről tudnom kéne??
server@root:/ # lsdev |grep vs
vsa0        Defined            LPAR Virtual Serial Adapter
vsa1        Defined            LPAR Virtual Serial Adapter
vsa2        Available          LPAR Virtual Serial Adapter
server@root:/ # lsdev |grep vty
vty0        Defined            Asynchronous Terminal
Aham.. LPAR profil alapján csak 1 Virtual Serial Adapter van (ezek szerint az lesz a vsa2), de akkor ez miért lát 3at?? Na mind.. Gyomláljunk, mert ez így gázos:
server@root:/ # for i in vty0 vsa2 vsa1 vsa0;do rmdev -dl $i;done
vty0 deleted
vsa2 deleted
vsa1 deleted
vsa0 deleted
server@root:/ # cfgmgr
server@root:/ # lsdev |egrep "vty|vsa"
vty0        Available          Asynchronous Terminal
vsa0        Available          LPAR Virtual Serial Adapter
server@root:/ # chcons -a login=enable /dev/vty0
chcons: console login enabled, effective on next system boot
chcons: console assigned to: /dev/vty0, effective on next system boot
Oks.. Mindjárt jobb.. Console-al mi van?
server@root:/ # pstart
console DISABLE
vty0 ENABLE
Na ez még gázos lehet.. Akkor ezt is rakjuk helyre:
server@root:/ # penable console
server@root:/ # pstart
console ENABLE
vty0 ENABLE
Ez után ismét megnéztem mi és hogy áll.. Sajna azt kellett tapasztaljam, hogy a penable igaz, hogy helyére rakta a console-t, viszont az inittab-ban is újra engedélyezte a cons bejegyzést.. Ez miatt ismét rakhattam off-ba, illetve lőhettem vissza a /dev-et 775-re.. Viszont sajna a jelek szerint a getty még mindig nem ment normálisan:
server@root:/tmp # ls -ld /dev; /usr/sbin/getty /dev/console;ls -ld /dev
drwxrwxr-x    5 root     system       356352 Oct 14 18:30 /dev
/dev/: TSM was unable to open port "/dev/"
drw-------    5 root     system       356352 Oct 14 18:30 /dev
Hát jó.. akkor nem maradt más restart.. Ami láss csodát.. Megoldotta a problémát!
server@root:/tmp # ls -ld /dev; /usr/sbin/getty /dev/console;ls -ld /dev
drwxrwxr-x    5 root     system       356352 Oct 14 19:10 /dev
drwxrwxr-x    5 root     system       356352 Oct 14 19:10 /dev

Éljen.. akkor problem solved.. Na de azért bennem felmerült 1-2 dolog.. Az első, hogy mint látható, most a TSM nem dobott hibát. Tekintve, hogy a TSM-es hiba direktben a /dev-re hivatkozott, így erősen esélyesnek tartom, hogy a problémának ehhez is köze lehet.. Tekintve, hogy ez egy TSM szerver, így nem csodálkoznék, ha ez egy TSM bug lenne, viszont a neten körbeszaglászva ilyen, vagy ehhez hasonló hibaleírást véletlenül se sikerült találnom.. A gyanúmat még jobban alátámasztja az, hogy a getty által piszkált file-ok a /dev alatt default 622-es jogot kapnak (hacsak ezt az ODM-ben nem bíráljuk felül, de ilyen itt nem volt)
Az viszont a probléma ellen szól, hogy a TSM-nek semmi köze nem szabadna legyen ezen a szinten a rendszerhez, pláne nem a getty futtatásakor. Így az is elképzelhető, hogy ez is csak egy a sok side affect közül (mint pl a CTRL+C-s hiba) ami amúgy egy getty-os bug.
Mindazonáltal a hiba meglehetősen furcsa volta, illetve a hiba keresési mód miatt úgy gondoltam, hogy ez az írás megér egy blog bejegyzés (tudom - jó hosszú lett)

2011. szeptember 15., csütörtök

Dual Network VIO - SEA adapter buktatók

Normálisabb helyeken ugyebár a az ember minimum 2 VIO szervert használ (ha másért nem, hát a redundancia végett), ami meg nyomban meg is követeli a SEA (Shared Ethernet Adapter) használatát control chanellel (plusz persze a megfelelő trunk priority beállításával). Ezzel nincs is semmi gond..
Aztán amikor az embernek valami baja van az egyik VIO-val, akkor meg pont örül, hogy milyen jó is a redundancia, majd teljes lelki nyugalommal nekiáll a hibás dolgot megjavítani.. Az általam tapasztalt esetben a hiba épp egy SEA adapter alatt lévő fizikai adaptereknél jelentkezett. Ebben az esetben az ember 2 dolgot tehet:

- Lebontja a SEA-t (illetve jelen esetben az ether channel-t is), majd elkezdi szépen darabonként szétcincálni az alatta lévő eszközöket, hogy vajon merre is lehet a probléma
- Azt mondja az ember, hogy a végén úgy is újra kell inicializálni az egészet, úgy is redundáns a rendszer, gyorsabb ha újraindítom (amúgy tényleg)

Mind2 esetben persze meg kell bizonyosodni róla, hogy a másik VIO átvette az összes hálózat vezérlését, amit az entstat -all [SEA]-val meg is lehet tenni (padmin alól; root alól standard entstat -d [SEA]).. Amennyiben a másik VIO átvette, akkor az összes hálózaton a SEA-nak a 'PRIMARY' állapotot kell mutatnia. Amint ez a helyzet már nyugodtabbak lehetünk, mert a másik VIO-n kedvünkre lehet matatni, az nem fog kihatni a kliensekre..

Mind emellett persze még van egy dolog amire figyelnünk kell, miszerint hogy az éppen hibás VIO-n a ha_mode hogy is áll.. Nyomban 3 lehetőségünk is van chdev-el ezt megpiszkálni:
chdev -dev [SEA]-attr ha_mode=auto -> ezt használjuk ha azt akarjuk, hogy a Trunk Priority alapján döntse el a 2 VIO egymás között, hogy épp ki szolgálja ki az adott hálózatot. Amennyiben az éppen aktuális VIO ezt mégse tudja megtenni, akkor nyomban átpasszolja a másik VIO-nak a hálózatot.

chdev -dev [SEA]-attr ha_mode=standby -> Ez amolyan "illedelmes (gently)" kérés a VIO felé, hogy hagyjon fel a hálózat kiszolgálásával (ha netán nála lenne). Amennyiben át akarjuk adni a másik VIO-nak a hálózatot, úgy illik ezt használni

chdev -dev [SEA]-attr ha_mode=disable -> Ez a módszer meg azt mondja, hogy a SEA adapter mostantól nincs HA módban, ergo bármiféle hálózati failoverre esély sincs.

Az utóbbi esetben viszont van 1-2 érdekes viselkedés, ami ha jól láttam sehol se volt dokumentálva (kb ezért is született ez a bejegyzés):

Amennyiben egy már bekonfigurált dual-network VIO-s környezet alól szedjük ki a HA módot a chdev-el, úgy attól még az entstat alatt láthatjuk, hogy a VIO még tud a primary VIO-ról, viszont persze nem fogja tudni átvenni a hálózatot, viszont a vicc az, hogy amíg újra nem indítjuk a gépet, addig nem is fog a hálózat átvételére kísérletet tenni. Ergo itt még el lehet játszani, hogy:
chdev -dev [SEA] -attr ha_mode=disable
chdev -dev [SEA] -attr ha_mode=standby ctl_chan=[Control_channel_adapter]
Majd ez után olyan szépen visszaáll a HA módba, hogy öröm nézni. Mellékesen felhívnám a figyelmet arra, hogy ebben az esetben a 2 VIO között használt (dedikált VLAN-al rendelkező) Control Channel adaptert újra kell konfigurálni, mivel a disable azt teljesen kitörli a beállítások közül! (Ez szintén nincs ledokumentálva sehol se)

A másik dolog ami ilyenkor problémát okozhat, ha olyan okosak vagyunk, hogy restartoljuk a gépet.. Ekkor ugyan is a SEA már nem fog semmit tudni arról, hogy ő eredetileg egy HA módban lévő dual network VIO volt, és annak rendje és módja szerint ő is "magáévá" szeretné tenni az adott VLAN taggelt hálózat irányítását.. Ez persze felvet egy olyan alapvető problémát, hogy mi van akkor ha már az adott hálózatot a switch-en használja valaki (tekintve, hogy dual VIO esetén a fentebb sorolt módon nagy eséllyel épp átadtuk a restart előtt a hálózatot a másik VIO-nak így szinte biztos, hogy ez a helyzet)?

Nos.. A helyzet koránt sem vicces -> A HA módból leválasztott SEA egy kisebb ARP tornádót fog a switch felé indítani (network storm) ami miatt meg a switch nem lesz képes kiszolgálni a kéréseket, ergo az a hálózat innentől nem elérhető, aminek a legtöbb customer csak ritkán örül, szóval dual network VIO-s környezetben mindenki felejtse el a ha_mode esetében a disable módot!!

Járulékosan az elmúlt pár napban felmerült részemről az igény egy kis network VIO monitoring scriptre, szóval ha valaki úgy érzi, hogy ez egy háztartásból se hiányozhat, úgy nyugodtan használja egészséggel :))

#!/usr/bin/ksh
# Script created by Gabor Lukacs
# Note - please use the script only on a dual-network VIO environment!
# Version 0.2

# Run as root pls :)
if [ "$(id -u)" != "0" ]; 
then
 echo "You must have root rights to run this script!"
 exit 1
fi

export ODMDIR=/etc/objrepos
NEED_MAIL=0
MAIL_SUBJECT="Warning! Some error(s) detected on $(hostname) VIO server!"
MAIL_ADDRESS=    # Fill this out before use :)

# Checking SEA adapters
if [ $(lsdev -Cc adapter |grep "Shared Ethernet Adapter" |grep -c Defined) -ne 0 ]
then
 echo "Warning! - There are one or more non-available SEA adapters:"
 lsdev -Cc adapter |grep "Shared Ethernet Adapter" |grep Defined
 NEED_MAIL=1
fi

for SEA in $(lsdev -Cc adapter |awk '/Shared Ethernet Adapter/ && /Available/ {print $1}')
do
 echo "\nChecking ${SEA} SEA adapter"
 USED_VLAN=$(odmget -q "name=${SEA} and attribute=pvid" CuAt|awk -F "\"" '/value/ {print $2}')
 SEA_STATE=$(entstat -d ${SEA} 2>&1|grep -E "ETHERNET STATISTICS|State|Priority" |awk '{ gsub("ETH", "\nETH"); print }' |grep -p ${SEA} |grep State)
 SEA_USED_TRUNK_PRIORITY=$(entstat -d ${SEA} 2>&1|grep -E "ETHERNET STATISTICS|State|Priority" |awk '{ gsub("ETH", "\nETH"); print }' |grep -p ${SEA} |grep Priority)
 SEA_USED_CTL_CHAN=$(odmget -q "name=${SEA} and attribute=ctl_chan" CuAt |awk -F "\"" '/value/ {print $2}')
 SEA_HA_MODE=$(odmget -q "name=${SEA} and attribute=ha_mode" CuAt |awk -F "\"" '/value/ {print $2}')
 echo "\tVLAN ID: $USED_VLAN"
 echo "\t${SEA_STATE}"
 echo "\t${SEA_USED_TRUNK_PRIORITY}"
 
 # In case the SEA adapter's state isn't Primary or backup send a mail
 if [[ $(echo "${SEA_STATE}"|awk '{print $NF}') != "BACKUP" && $(echo "${SEA_STATE}"|awk '{print $NF}') != "PRIMARY" ]]
 then
  NEED_MAIL=1
 fi
 
 if [ ${SEA_USED_CTL_CHAN} ]
 then
  echo "\tSEA used control channel adapter: ${SEA_USED_CTL_CHAN}"
 else
  echo "\tSEA used control channel adapter: No adapter defined (Please check in case it's a dual network-VIO setup!)"
 fi
 echo "\tSEA HA mode: ${SEA_HA_MODE}"
 
 REAL_ADAPTER=$(odmget -q "name=${SEA} and attribute=real_adapter" CuAt |awk -F "\"" '/value/ {print $2}')
 
 # Is the adapter in defined state?
 if [ $(lsdev -l ${REAL_ADAPTER} |grep -c Defined) -eq 1 ]
 then
  echo "\WARNING - The ${REAL_ADAPTER} adapter is in defined state!"
  NEED_MAIL=1
 # Ok.. It's not defined.. Move forward
 else
  if [ $(lsdev -l ${REAL_ADAPTER} |grep -c EtherChannel) -eq 1 ]
  # In case SEA using link aggregation
  then
   echo "\tSEA used real adapter: ${REAL_ADAPTER} (Etherchannel)"
   ETH_CHAN_ADAPTERS=$(odmget -q "name=${REAL_ADAPTER} and attribute=adapter_names" CuAt|awk -F "\"" '/value/ {print $2}' |sed "s/,/ /g")
   echo "\tUsed physical adapters under ${REAL_ADAPTER} Etherchannel adapters:"
   for ETH_CHAN_ADAPTER in ${ETH_CHAN_ADAPTERS}
   do
    # 2nd check - is any of the etherchannel used physical adapter in defined state?
    if [ $(lsdev -l ${ETH_CHAN_ADAPTER} |grep -c Defined) -eq 1 ]
    then
     echo "WARNING - The ${ETH_CHAN_ADAPTER} adapter is in Defined state!"
    # No.. Grand.. move forward
    else
     echo "\t\t${ETH_CHAN_ADAPTER}"
     ADAPTER_STATUS=$(entstat -d ${SEA} 2>&1|grep -E "ETHERNET STATISTICS|Link Status|Media Speed Running" |awk '{ gsub("ETH", "\nETH"); print }' |grep -p ${ETH_CHAN_ADAPTER} |awk '/Link Status/ {print $NF}')
     ADAPTER_MEDIA_SPEED=$(entstat -d ${SEA} 2>&1|grep -E "ETHERNET STATISTICS|Link Status :|Media Speed Running" |awk '{ gsub("ETH", "\nETH"); print }' |grep -p ${ETH_CHAN_ADAPTER} |grep Media)
     echo "\t\t\tStatus: ${ADAPTER_STATUS}"
     echo "\t\t\t${ADAPTER_MEDIA_SPEED}"
     # If adapter Status isn't up, send a mail
     if [ ${ADAPTER_STATUS} != "Up" ]
     then
      NEED_MAIL=1
     fi
    fi
   done
  # In case it not using Link aggregation
  else
   echo "\tSEA used real adapter: ${REAL_ADAPTER} (physical adapter)"
   ADAPTER_STATUS=$(entstat -d ${SEA} 2>&1|grep -E "ETHERNET STATISTICS|Link Status|Media Speed Running" |awk '{ gsub("ETH", "\nETH"); print }' |grep -p ${REAL_ADAPTER} |awk '/Link Status/ {print $NF}')
   ADAPTER_MEDIA_SPEED=$(entstat -d ${SEA} 2>&1|grep -E "ETHERNET STATISTICS|Link Status|Media Speed Running" |awk '{ gsub("ETH", "\nETH"); print }' |grep -p ${REAL_ADAPTER} |grep Media)
   echo "\t\tStatus: ${ADAPTER_STATUS}"
   echo "\t\t${ADAPTER_MEDIA_SPEED}"
   # If adapter Status isn't up, send a mail
   if [ ${ADAPTER_STATUS} != "Up" ]
   then
    NEED_MAIL=1
   fi
  fi
 fi
done > /tmp/vio_status.output

if [ ${NEED_MAIL} -eq 1 ]
then
 mail -s "${MAIL_SUBJECT}" "${MAIL_ADDRESS}" < /tmp/vio_status.output
fi