Twitter

Showing posts with label exadata. Show all posts
Showing posts with label exadata. Show all posts

Exadata: resize (increase and decrease) ASM diskgroups

Disk space is scarce -- always. It is true that when one buys an Exadata for example, he is told that there is 750 TB of disk space which looks huge (almost infinite ?) at first sight but this quickly drops to only 250 TB when in HIGH redundancy and even less than that if you use some for RECO and you then often have to juggle with disk space between disk groups. Hopefully, this juggling challenge is pretty easy and, most importantely, online !

Before jumping into the procedure describing how to increase/decrease a diskgroup size, one need to understand some Exadata storage concepts and vocabulary:
  • Each storage sever (aka cell) has 12 disks (except Extreme Flash which has 8 disks) -- you can remember this one, it has been a question in any Exadata certification I took :)
  • This means that on a 5 cells configuration, you will have 5*12=60 physical disks (of 12TB each for example on a X8 thus 12*60=720 TB)
  • Each of the 12 physical disk in a cell is called a cell disk (makes sense, it is a disk in a cell :)); cell disks are numbered from 0 to 11
  • When you allocate some space on a cell disk for a diskgroup, a slice on each cell disk is taken, this is called a grid disk
  • And ASM uses theses grid disks as ASM disks in its diskgroup and manages the redundancy you want (or "the redundancy you have inherited from a default installation" may be more accurate here :))

Following my previous explanations, let's start by having a look at the available disk space on the celll disks before increasing a RECOPROD diskgroup (this has to be done from a physical database node or a dom0/KVM Host if you use virtualization):
[root@exa01db01 ]# dcli -g ~/cell_group -l root "cellcli -e list celldisk attributes name,size,status,freespace where name like \'CD_.*\'"
exa01cel01: CD_00_exa01cel01     12.4737091064453125T    normal  1.409210205078125T
exa01cel01: CD_01_exa01cel01     12.4737091064453125T    normal  1.409210205078125T
. . .
exa01cel05: CD_10_exa01cel05     12.4737091064453125T    normal  1.409210205078125T
exa01cel05: CD_11_exa01cel05     12.4737091064453125T    normal  1.409210205078125T
[root@exa01db01 ]# 
Very cool, 1.4 TB free on each cell disk, this is plenty of available space !

Note that I use the where name like syntax to only show the CD_* disks which are the Cell Disks and not the FD_* which are the Flash Disks nor the PM_* which are the Persistent memory.

Let's look at the size of the current grid disks for this diskgroup:
[root@exa01db01 ]#  dcli -g ~/cell_group -l root "cellcli -e list griddisk attributes name,size,status where name like \'RECOPROD.*\'"
exa01cel01: RECOPROD_CD_00_exa01cel01     32G    active
exa01cel01: RECOPROD_CD_01_exa01cel01     32G    active
. . .
exa01cel05: RECOPROD_CD_10_exa01cel05     32G    active
exa01cel05: RECOPROD_CD_11_exa01cel05     32G    active
[root@exa01db01 ]# 
RECOPROD currently has 32GB grid disks which means that RECOPROD (let's say it is NORMAL redundancy) is ... 32*12*5/2 = ... ? (let's use this opportunity to show a bit of bc here)
32 => each grid disk is 32 GB
12 => each cell has 12 disks
5  => our system has 5 cells
2  => we divide by 2 as the diskgroup is NORMAL redundancy
[root@exa01db01 ]#  echo "32*12*5/2" | bc
960
[root@exa01db01 ]# 
So the current size of our RECOPROD is 960 GB; it is indeed not that big. Question now is how big should each grid disk be if we would like to have a 15 TB NORNMAL redundancy RECOPROD diskgroup ?
[root@exa01db01 ]# echo "15*1024*2/5/12" | bc
512
[root@exa01db01 ]# 
512 GB it is; we know we have enough space available on the cell disks, we can increase the size of all the grid disks:
[root@exa01db01 ]# dcli -g ~/cell_group -l root "cellcli -e alter griddisk size=512G where name like \'RECOPROD.*\'"
exa01cel01: GridDisk RECOPROD_CD_00_exa01cel01 successfully altered
exa01cel01: GridDisk RECOPROD_CD_01_exa01cel01 successfully altered
. . .
exa01cel05: GridDisk RECOPROD_CD_10_exa01cel05 successfully altered
exa01cel05: GridDisk RECOPROD_CD_11_exa01cel05 successfully altered
[root@exa01db01 ]#
And then we can increase the ASM disks (this has to be done connected to the ASM instance so on a VM or on a physical database node):
[oracle@exa01db01:~]$ sqlplus / as sysasm
SQL> alter diskgroup RECOPROD resize all size 512G rebalance power 64 ;
Diskgroup altered.
Elapsed: 00:00:02.62
SQL>
Note that this will trigger a rebalance operation which you want to monitore using select * from gv$asm_operation. Also note that 64 is an aggressive rebalance power, you may want to reduce it to 8 or 16 if you are doing this live during heavy production hours. Once the rebalance is done, you are done !
[root@exa01db01 ~]# ./asmdu.sh   <== asmdu.sh available here
Instances running on exa01db01 : +ASM1, PROD1, PROD2, BLABLA1, APP1, REPORT1
        DiskGroup      Redundancy        Total TB       Usable TB        % Free
        ---------     -----------        --------       ---------        ------
        DATAPROD        HIGH              150.01          100.03          33
        RECOPROD        NORMAL             15.00            0.50          99
[root@exa01db01 ~]#
That was easy; now how can we decrease the size of this RECOPROD ? just by doing the opposite:
[oracle@exa01db01:~]$ sqlplus / as sysasm
SQL> alter diskgroup RECOPROD resize all size 32G rebalance power 64 ;
SQL> select * from gv$asm_operation ;
[root@exa01db01 ]# dcli -g ~/cell_group -l root "cellcli -e alter griddisk size=32G where name like \'RECOPROD.*\'"
That's it for today, one more string in our Exadata bow !

Exadata: add extra disk and extend a FS on a VM

There's always a day you'll need more space on a filesystem. I you run Exadata physical (no VM), it is pretty straightforward as it is like on any Linux system and the disk space is already available in the Volume Group (as shown here). But when it comes to running Exadata in a virtual configuration, this is another story as the non-ASM physical storage is managed by the Hypervisor (dom0, KVM Host) but the disk space is used by the VMs. I'll show below an example of increasing a /u01 filesystem on a KVM Guest VM.

Speaking of non-ASM physical space, we first need to understand that this one is located in the /EXAVMIMAGES filesystem on the KVM host:
[root@kvmhost01 ~]# df -h /EXAVMIMAGES/
Filesystem                           Size  Used Avail Use% Mounted on
/dev/mapper/VGExaDb-LVDbExaVMImages  1.5T  443G  1.1T  30% /EXAVMIMAGES
[root@kvmhost01 ~]#
Then it is a good idea to start by checking how much space is left on this FS before thinking about adding more disk space to a VM (please have a look at this post if you need to increase the size of /EXAVIMAGES).

Also worth understanding that all the files related to the VMs are located in /EXAVMIMAGES/GuestImages then all the files of a prodvm VM of a domain.com domain stay in:
/EXAVMIMAGES/GuestImages/prodvm.domain.com
We will then use vm_maker to create a new file which will be presented to the VM as a physical volume (like a new disk). I will name it pv3_vgexadb.img as my vgexadb volume group on the VM already has 2 physical volumes and I would recommend keeping the naming convention clear and neat to avoid future confusion; let's make this new disk 100GB:
[root@kvmhost01 ~]# vm_maker --create --disk-image /EXAVMIMAGES/GuestImages/prodvm.domain.com/pv3_vgexadb.img --size 100G --attach --domain prodvm.domain.com
[INFO] Allocating an image for /EXAVMIMAGES/GuestImages/prodvm.domain.com/pv3_vgexadb.img, size 100.000000G...
. . .
[INFO] Created image /EXAVMIMAGES/GuestImages/prodvm.domain.com/pv3_vgexadb.img
[INFO] Running 'vgscan --cache'...
[INFO] -------- MANUAL STEPS TO BE COMPLETED FOR MOUNTING THE DISK WITHIN DOMU prodvm.domain.com --------
[INFO] 1. Check a disk with name /dev/VGExaDbDisk.pv3_vgexadb.img/LVDBDisk exists.
[INFO] -  Check for the existence of a disk named: /dev/VGExaDbDisk.pv3_vgexadb.img/LVDBDisk. Use the 'lvdisplay' command and check the output. 
[INFO] 2. Create a mount directory for the new disk
[INFO] 3. Add the following line to /etc/fstab: /dev/VGExaDbDisk.pv3_vgexadb.img/LVDBDisk   defaults 1 1
[INFO] 4. Mount the new disk. Use the 'mount -a' command.
[root@kvmhost01 ~]# 
If you want to create a new FS on the VM, you want to follow the instructions provided at the end of the previous output. In the case of this blog, we want to extend the /u01 and not create a new FS so we will skip these instructions. Before continuing further, let's verify that our new disk is correctly attached to the VM:
[root@kvmhost01 ~]# vm_maker --list --disk-image --domain prodvm.domain.com
File /EXAVMIMAGES/GuestImages/prodvm.domain.com/System.img
File /EXAVMIMAGES/GuestImages/prodvm.domain.com/grid19.11.0.0.210420.img
File /EXAVMIMAGES/GuestImages/prodvm.domain.com/db19.11.0.0.210420_3.img
File /EXAVMIMAGES/GuestImages/prodvm.domain.com/pv1_vgexadb.img
File /EXAVMIMAGES/GuestImages/prodvm.domain.com/pv2_vgexadb.img
File /EXAVMIMAGES/GuestImages/prodvm.domain.com/pv3_vgexadb.img  <== this one
[root@kvmhost01 ~]# 
Great. Now that the new disk exists at the Hypervisor level, let's check it at the VM level:
[root@kvmhost01 ~]# ssh prodvm
[root@prodvm ~]# lvdisplay /dev/VGExaDbDisk.pv3_vgexadb.img/LVDBDisk  
  --- Logical volume ---
  LV Path                /dev/VGExaDbDisk.pv3_vgexadb.img/LVDBDisk  <== LV
  LV Name                LVDBDisk
  VG Name                VGExaDbDisk.pv3_vgexadb.img                <== VG
  LV UUID                xxxxxxxxxxxxxxxxx
  LV Write Access        read/write
  LV Creation host, time kvmhost01.domain.com, 2022-01-21 14:51:22 +0100
  LV Status              available
  # open                 0
  LV Size                100.00 GiB    <== the size we want to add
  . . .
[root@prodvm ~]#
Everything is here as expected; now it is important to note the name of the LV and the VG as we will delete them -- indeed, we are only interested in the physical volume and not in the LV nor in the VG:
[root@prodvm ~]# lvremove /dev/VGExaDbDisk.pv3_vgexadb.img/LVDBDisk
Do you really want to remove active logical volume VGExaDbDisk.pv3_vgexadb.img/LVDBDisk? [y/n]: y
  Logical volume "LVDBDisk" successfully removed
[root@prodvm ~]# vgremove VGExaDbDisk.pv3_vgexadb.img
  Volume group "VGExaDbDisk.pv3_vgexadb.img" successfully removed
[root@prodvm ~]#
Note that you can use lvremove -f to bypass the "do you really want ..." confirmation when dropping the logical volume; just be careful not dropping the wrong one :)

Now we need to get the name of the disk which has been added; you'll find it at the end of the output of the pvdisplay command:
[root@prodvm ~]# pvdisplay
. . .
  "/dev/sdf1" is a new physical volume of "100.00 GiB" <== here
  --- NEW Physical volume ---
  PV Name               /dev/sdf1
  VG Name
  PV Size               100.00 GiB
  . . .
[root@prodvm ~]#
Great, we have our new disk on the VM which we can add to the VGExaDb volume groupe:
[root@prodvm ~]# vgdisplay VGExaDb -s
  "VGExaDb" <141.24 GiB [118.00 GiB used / <23.24 GiB free]  <== Before adding the 100 GB
[root@prodvm ~]# vgextend VGExaDb /dev/sdf1
  Volume group "VGExaDb" successfully extended
[root@prodvm ~]# vgdisplay VGExaDb -s
  "VGExaDb" 193.23 GiB [118.00 GiB used / 123.24 GiB free]   <== +100 GB added
[root@prodvm ~]#
We are now good to extend the FS:
[root@prodvm ~]# df -h /u01
Filesystem                    Size  Used Avail Use% Mounted on
/dev/mapper/VGExaDb-LVDbOra1   50G   40G   10G  80% /u01       <== FS is 50 GB
[root@prodvm ~]# lvextend -L +100G /dev/VGExaDb/LVDbOra1
  Size of logical volume VGExaDb/LVDbOra1 changed from 50.00 GiB to 150.00 GiB.
  Logical volume VGExaDb/LVDbOra1 successfully resized.
[root@prodvm ~]# xfs_growfs /u01
meta-data=/dev/mapper/VGExaDb-LVDbOra1 isize=256    agcount=8, agsize=1310720 blks
. . .
data blocks changed from 10485760 to 26214400
[root@prodvm ~]# df -h /u01
Filesystem                    Size  Used Avail Use% Mounted on
/dev/mapper/VGExaDb-LVDbOra1  150G   40G   120G  20% /u01      <== 100 GB added
[root@prodvm ~]#
And keep in mind that all of this is obviously 100% online !

Exadata: increase the size of /EXAVMIMAGES

In the Exadata virtual configuration world, the disk space available for the VMs for installating the systems, having applicative FS, etc... is located in on the hypervisor in /EXAVIMAGES which looks like this on a default X8M installation:
[root@kvmhost01 ~]# df -h /EXAVMIMAGES/
Filesystem                           Size  Used Avail Use% Mounted on
/dev/mapper/VGExaDb-LVDbExaVMImages  1.5T  443G  1.1T  30% /EXAVMIMAGES
[root@kvmhost01 ~]#
This one is default sized but some VMs are already created thus the disk space already used. Point is that there is "only" 1.1TB left and I often get the question "it is not much for more VMs, more ORACLE_HOMEs and we need tons of space for the logs !". Not sure why people need so much space for [ORACLE|GRID]_HOMEs which are around 12 GB in size but... anyway, let's address the client's fear not to underestimate the psychologic aspect of our job :) and allocate disk space before increasing VM filesystems.

We can see below that there is much more space not allocated but ready to be allocated on top of this free space:
[root@kvmhost01 ]# pvs
  PV         VG      Fmt  Attr PSize PFree
  /dev/sda3  VGExaDb lvm2 a--  3.27t 1.73t    <== 1.73 TB available
[root@kvmhost01 ]#
So here there is 1.73 TB available on top of the already allocated and free 1.1 TB (and again this specific KVM host has already 5 VMs running) so there is plenty of disk space available to install many [ORACLE|GRID]_HOMEs and store months of logfiles !

Below for example how to resize /EXAVIMAGES to let's say using 90% of what is available:
[root@kvmhost01 ]# lvextend -l +90%FREE /dev/VGExaDb/LVDbExaVMImages
[root@kvmhost01 ]# xfs_growfs /EXAVMIMAGES
Easy and 100% online ! plenty of space to free to use !

Shared memory segments cleanup

I thought that having to manually remove shared memory segments was an old problem; I remember having this kind of issue with Oracle 7 and 8 but not much after that but it seems that this is happenning (back) on VMs from time to time after some instances crash for example (never on bare metal as far as I remember -- well, nothing crashes on bare metal).
A scenario for example is that an Oracle instance crashes on a VM and cannot restart because there are not enough Huge Pages (the instance has use_large_pages=only) so we need to find the stuck shared memory segments and clean them up to free this memory.

Hopefully, it is easy to identify using the ipcs -ma command and the dest status:
# ipcs -ma
------ Message Queues --------
key        msqid      owner      perms      used-bytes   messages
------ Shared Memory Segments --------
key        shmid      owner      perms      bytes      nattch     status
0x00000000 333381638  oracle     600        40802189312 7245
0x00000000 333414407  oracle     600        140509184  2415
0x35854b58 333447176  oracle     600        2097152    2415
0x00000000 333971465  oracle     600        6291456     11         dest
0x00000000 334004234  oracle     600        40265318400 33         dest
0x00000000 334037003  oracle     600        140509184   11         dest
0x00000000 334069772  oracle     600        2097152     11         dest
0x00000000 334102541  oracle     600        6291456    1575
0x00000000 334135310  oracle     600        39191576576 4725
0x00000000 1741914130 oracle     600        5335154688 774
0x00000000 333774870  oracle     600        40265318400 4455
#
The dest status means destroy letting the system know that it can free these shared memory segments. So why are they not freed ? this is because of the number of processes still attached to this memory segment which are shown in the nattch column. We then have to identify these processes and kill them which is also easy thanks to lsof:
# lsof | grep <shmid>
Which could looks like below for the above 4 shared memory segments to clean up (all in one command is better than 4 commands):
# lsof | egrep '333971465|334004234|334037003|334069772'
As you may have a lot of processes to kill, knowing that the process will be the second column of the lsof output, you can generate all the kill commands automatically:
# lsof | egrep '333971465|334004234|334037003|334069772' | awk '{print "kill -9 "$2 }' | sort | uniq
kill -9 15692
kill -9 27132
kill -9 33037
kill -9 33725
kill -9 384913
kill -9 388064
kill -9 4602
kill -9 53630
kill -9 63605
# 
You can even | bash the output to kill all the processes in one command and the OS will then automatically release this stuck memory (see below, no more dest status):
# ipcs -ma
------ Message Queues --------
key        msqid      owner      perms      used-bytes   messages
------ Shared Memory Segments --------
key        shmid      owner      perms      bytes      nattch     status
0x00000000 333381638  oracle     600        40802189312 7245
0x00000000 333414407  oracle     600        140509184  2415
0x35854b58 333447176  oracle     600        2097152    2415
0x00000000 334102541  oracle     600        6291456    1575
0x00000000 334135310  oracle     600        39191576576 4725
0x00000000 1741914130 oracle     600        5335154688 774
0x00000000 333774870  oracle     600        40265318400 4455
#
That's all for today !

Exadata: shutdown or a reboot a cell without impacting ASM

Redundancy is an important feature of any system and Exadata is not an exception. At storage level, Exadata uses ASM to ensure a software redundancy based on failgroup. This is how we can patch the Exadata storage online and also perform some maintenance online (replacing a failed DIMM, a flash card for models < X6, a motherboard, etc ...). The below blog shows real life example on how to shutdown or reboot a cell without impacting ASM (Oracle official note about this is 1188080.1).

First of all, let's check the status of the disks before starting the maintenance (you can also use cell-status.sh for this):
[root@exa01db01 ~]# ssh exa01cel04
Last login: Tue Oct 13 20:14:28 AEDT 2020 from 10.248.6.210 on pts/0
Last login: Tue Oct 13 20:14:54 2020 from 10.248.6.210
[root@exa01cel04 ~]# cellcli
CellCLI: Release 19.2.4.0.0 - Production on Tue Oct 13 20:14:57 AEDT 2020
Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
CellCLI> list griddisk attributes name,asmmodestatus,asmdeactivationoutcome
         DATA_exa01C1_CD_00_exa01cel04     ONLINE  Yes
         DATA_exa01C1_CD_01_exa01cel04     ONLINE  Yes
         . . .
         DBFS_DGC2_CD_02_exa01cel04       ONLINE  Yes
         DBFS_DGC2_CD_03_exa01cel04       ONLINE  Yes
         . . .
         RECO_exa01C1_CD_00_exa01cel04     ONLINE  Yes
         RECO_exa01C1_CD_01_exa01cel04     ONLINE  Yes
         . . .
CellCLI>
Now we need to deactivate the grid disks:
CellCLI> alter griddisk all inactive
         GridDisk DATA_exa01C1_CD_00_exa01cel04 successfully altered
         GridDisk DATA_exa01C1_CD_01_exa01cel04 successfully altered
         . . .
         GridDisk RECO_exa01C2_CD_10_exa01cel04 successfully altered
         GridDisk RECO_exa01C2_CD_11_exa01cel04 successfully altered
CellCLI> 
The grid disks are now inactive:
CellCLI> list griddisk
         DATA_exa01C1_CD_00_exa01cel04     inactive
         DATA_exa01C1_CD_01_exa01cel04     inactive
         . . .
         RECO_exa01C2_CD_10_exa01cel04     inactive
         RECO_exa01C2_CD_11_exa01cel04     inactive
CellCLI> 
If you want to shutdown the cell:
[root@exa01cel04 ~]# shutdown -h now
Connection to exa01cel04 closed by remote host.
Connection to exa01cel04 closed.
[root@exa01db01 ~]#
If you want to reboot the cell:
[root@exa01cel04 ~]#  shutdown -Fr now
Once the cell is back, the disks are inactive:
CellCLI> list griddisk
         DATA_exa01C1_CD_00_exa01cel04     inactive
         DATA_exa01C1_CD_01_exa01cel04     inactive
         . . .
         RECO_exa01C2_CD_10_exa01cel04     inactive
         RECO_exa01C2_CD_11_exa01cel04     inactive
CellCLI> 
Now activate the grid disks:
CellCLI> alter griddisk all active
         GridDisk DATA_exa01C1_CD_00_exa01cel04 successfully altered
         GridDisk DATA_exa01C1_CD_01_exa01cel04 successfully altered
         . . .
         GridDisk RECO_exa01C2_CD_10_exa01cel04 successfully altered
         GridDisk RECO_exa01C2_CD_11_exa01cel04 successfully altered
CellCLI>
Disks are now SYNCING (this is the fast mirror resync feature, it should be fast as it will resync only the data modified durnig the maintenance -- usually not much):
CellCLI>  list griddisk attributes name,asmmodestatus,asmdeactivationoutcome
         DATA_exa01C1_CD_00_exa01cel04     SYNCING         Yes
         DATA_exa01C1_CD_01_exa01cel04     SYNCING         Yes
         DATA_exa01C1_CD_02_exa01cel04     SYNCING         Yes
         DATA_exa01C1_CD_03_exa01cel04     SYNCING         Yes
         DATA_exa01C1_CD_04_exa01cel04     SYNCING         Yes
         . . .
CellCLI> 
Once the disks have finished SYNCING, you are all done !
If you did a shutdown to change a flash disk, verify the new device is here
CellCLI> list physicaldisk
         8:0             ABXDNV          normal
         8:1             ABV1XV          normal
         8:2             ABT38V          normal
         8:3             ABYU6V          normal
         8:4             ABPRAV          normal
         8:5             ABA8DV          normal
         8:6             PX6JKV          normal
         8:7             ABW08V          normal
         8:8             AV0SHV          normal
         8:9             BCVZ3V          normal
         8:10            ABD6LV          normal
         8:11            ABYM1V          normal
         FLASH_1_1       S2T7NHJK800123  normal
         FLASH_2_1       S2T7NHJK800456  normal    <=== In my example, we have replaced this flash disk
         FLASH_4_1       S2T7NHJK800789  normal
         FLASH_5_1       S2T7NHJK800246  normal
CellCLI> 
Check the new disk details:
CellCLI> list physicaldisk FLASH_2_1 detail
         name:                   FLASH_2_1
         deviceName:             /dev/nvme2n1
         diskType:               FlashDisk
         luns:                   2_1
         makeModel:              "Oracle Flash Accelerator F320 PCIe Card"
         physicalFirmware:       KPYAIR3Q
         physicalInsertTime:     2020-10-13T20:40:11+11:00
         physicalSerial:         S2T7NHJK800456
         physicalSize:           2.910957656800746917724609375T
         slotNumber:             "PCI Slot: 2; FDOM: 1"
         status:                 normal
CellCLI>
One more useful procedure for some more online maintenance !

Exadata: Infiniband Switches ILOM -- stop, start, restart, status

Database nodes and storage servers in an Exadata have a dedicated ILOM running independantly from the OS. Each ILOM is a PCI card adapter (number 12 on the below picture which comes from this oracle documentation, you'll also find in this documentation the description of all the below numbers).







But this is a different story for the Infiniband Switches; indeed, the IB switches have a software ILOM (and not a hardware ILOM) which you access using the spsh command (you'll find an example in this post).

So when this ILOM is hung (which can hang your IB switches patching for example), you can restart it easily; first of all, we can check its status:
[root@exa01sw-ib3 ~]# service ilom status
ILOM stack is partly started with 16 processes.
ILOM daemons that failed to start are :  stdiscoverer  <== something wrong here
However, ILOM stack subsystem is locked..... OK!
[root@exa01sw-ib3 ~]#
And then restart the ILOM:
[root@exa01sw-ib3 ~]# service ilom restart
Stopping ILOM stack
Stopping Servicetags listener: stlistener.
. . .
Running ntpdate...
29 Oct 00:10:25 ntpdate[5508]: step time server 10.55.111.125 offset 0.001666 sec
Starting Servicetags listener: stlistener.
Starting platform_logger
[root@exa01sw-ib3 ~]# service ilom status
ILOM stack is running.
[root@exa01sw-ib3 ~]#
You can also stop/start the ILOM instead of restart; let's do that on another switch:
[root@exa01sw-ib2 ~]# service ilom stop
Stopping ILOM stack
. . .
Stopping capidirect daemon: capidirectd  Done
Created dump file: /coredump/sp_trace/reboot/dump.gz
[root@exa01sw-ib2 ~]# service ilom start
Creating home directories
Updating FW version
. . .
Running ntpdate...
29 Oct 00:06:45 ntpdate[8892]: step time server 10.55.111.125 offset -0.000279 sec
Starting Servicetags listener: stlistener.
Starting platform_logger
[root@exa01sw-ib2 ~]#
That's all folks, another issue easily fixed !

My Exadata patches download cheat sheet

It has been a while since I wanted to share my Exadata patches download cheat sheet I use to download all the patches I need when patching Exadata from the storage up to the GI. Indeed, looking for the correct mix of patches sometimes looks like:
So let's try to clarify this and have a look at everything needed to patch an Exadata with some explanations; you will also find a short sumup at the end of this blog as well.

  • A note about switches and cells patches:
  • From 19.3.0.0.0, the switches patch and the cells patch are delivered in two different patches, there was only one patch containing the switches and the cells patch before 19.3.0.0.0 (up to 19.2.22.0.0)

  • Switches -- monthly:
  • Note 888828.1 will give you the link to the switches patches as example Patch 32957082: EXADATA 21.2.2.0.0 SWITCH PATCH; patchmgr for this patch (not the same as others) is included in this patch, the patch is for Infiniband and ROCE switches. You can find more info on how to patch the IB switches here and the ROCE switches here.

  • Cells -- monthly:
  • Note 888828.1 will give you the link to the cells patch as example Patch 33120692: EXADATA RELEASE UPDATE 21.2.2.0.0 (MOS NOTE 2781458.1); patchmgr for this patch (not the same as others) is included in this patch. More info on the procedure to patch the cells here.

  • Database nodes (physical and VM) -- monthly:
  • Note 888828.1 will provide you with this patch number. Note that the database nodes and the VMs share the same patch whether the hypervisor is XEN or KVM. From Exadata 19.3, you can have VM running with KVM as hypervisor; in this case, the same patch applies to the KVM hosts (hypervisor); example: Patch 32957083: EXADATA COMPUTE NODE 21.2.2.0.0 OL7 BASE REPO ISO; this is the zip of an ISO containing RPMs; do not unzip it, patchmgr will do it for you. This patch does NOT include patchmgr which has to be downloaded separately (see below). More info on how to patch the DB nodes here.

  • dom0s -- monthly:
  • Note 888828.1 will provide you with this patch number. Note that xen dom0s require a dedicated patch like Patch 32957084: EXADATA COMPUTE NODE 21.2.2.0.0 DOM0 BASE REPO ISO; this is the zip of an ISO containing RPMs; do not unzip it, patchmgr will do ot for you. This patch does NOT include patchmgr which has to be downloaded separately (see below).

  • patchmgr -- quite often but not regularly:
  • patchmgr for DB nodes, VM, KVM hosts and xen dom0s needs to be downloaded separately in Patch 21634633: DBSERVER.PATCH.ZIP ORCHESTRATOR PLUS DBNU - ARU PLACEHOLDER. It is the same patchmgr for xen dom0s and the DB nodes/VM even if they do not share the same patch :)

  • ksplice -- quite often but not regularly:
  • If for any reason (the latest patch you apply does not include a patch you need), you may need to apply some extra ksplice patches, you'll find the documentation in Uptrack: HOWTO: Install ksplice kernel updates for Exadata Database Nodes (Doc ID 2207063.1); you'll need a user on https://linux.oracle.com (as far as I remember it is not the same as your MOS user . . .) and download the required ksplice patch.

  • JDK -- monthly:
  • If you patch the JDK on the DB nodes, VMs, hypervisors and cells (Oracle always provides patches with old JDK so depending on your compliance requirements, the JDK from a brand new patch is already... not compliant :)), you'll find it in JDK: Supported Java SE Downloads on MOS (Doc ID 1439822.1), search for Oracle JDK 8 Update XXX

  • Grid Infrastructure - quarterly:
  • You will find the link of the GI version you want to install in Note 888828.1 (example: Patch 32895426: GI RELEASE UPDATE 19.12.0.0.0). Be careful, Oracle maintains 3 GI versions at a time backporting some patches to two previous versions so you will end up with 3 different current versions each quarter with this kind of naming convention: X.Y.0, X.Y.1 and X.Y.2 so the ".2" is supposed to be the most mature and final version of the "X.Y" GI version except when a version is so buggy that they have to quickly release a ".1" version very quickly after a ".0" like GI 19.10 for example which now has a 19.10.3 version -- but it it supposed to be exceptional. To sum up, here is the GI versions you will have in July 2021:
    • 19.12.0.0.210720
    • 19.11.1.0.210720
    • 19.10.3.0.210720
    Once you got your GI, you are not done yet, indeed, this piece of software has many bugs and you have to closely study the below notes to find out which patches are included, which new critical issues are found, etc ...
    • Oracle Database 19c Important Recommended One-off Patches (555.1)
    • This note is indeed about "Database" but Oracle took the bad habit to more or less include GI in DB . . . sometimes :)
    • Grid Infrastructure 19 Release Updates and Revisions Bugs Fixed Lists (Doc ID 2523221.1)
    • Oracle Database 19c Release Update & Release Update Revision July 2021 Known Issues (Doc ID 19202107.9)
    • There will be a new note for this every 3 months (for every GI release) and it can be updated with new critical issues / patches to apply at any time. For example, April's was Oracle Database 19c Release Update & Release Update Revision April 2021 Known Issues (Doc ID 19202104.9). More info on GI parching here.


  • GI JDK -- quarterly:
  • If you need to ensure a certain compliance, as I was mentioning earlier, the JDK provided with the GI is kind of old for compliance point of view so you will need to patch it; you'll find it in JDK and PERL Patches for Oracle Database Home and Grid Home (Doc ID 2584628.1), paragraph 2.1 Latest JDK Patches for Database

  • RPMs -- not regularly:
  • If you want to install some specific (non-default) RPM (I like to install screen for example), you can find them here:
    • OL7: https://yum.oracle.com/repo/OracleLinux/OL7/latest/x86_64/index.html
    • OL6: https://yum.oracle.com/repo/OracleLinux/OL6/latest/x86_64/index.html
    • Mainly for the xen dom0s.

And this should be all !

To sumup, the notes numbers:

Happy patching !

So you have removed a trace file and your FS is still filling (very fast)

So you have a FS filling very fast on a server, someone connects, finds some big trace files growing very fast and delete them which frees some space on the FS and few minutes later, the FS is back to a dangerous threshold but you are unable to see the trace files any more (hey no, they have been deleted !) and a few moment later, your FS is full which is not what we want. Oftently, people panic and finish by rebooting the application(s) and/or server(s) supposed to fill these trace files -- which is also not what anyone wants but this is often seen as the best (less worse ?) way of "saving the system".
cat /dev/null > tace_file would obviously have been better here but what is done is done and you have to deal with the situation, you cannot unrm the file. Having said that, in a specific case I faced, it was due to a 19c oracle bug (what ? an Oracle bug ? yeah it happens from time to time . . . :D) where the oracle processes are tracing too much (you bet !) and only a very aggressive (every minute) cronjob to empty these trace files may fix the issue (if this can be considered as a fix) so the below solution still applies the time you can organize applying a patch (which would obviously more or less need a downtime . . .).

Back to the situations df can show that the FS is full:
[root@linux01]# df -h /u01
Filesystem                    Size  Used Avail Use% Mounted on
/dev/mapper/VGExaDb-LVDbOra1  237G  227G     0 100% /u01
[root@linux01]#
but not du (you can do the maths, according to du, the FS is far from being full):
[root@linux01]# du -sh *
144G    app
4.0K    crashfiles
16K     lost+found
612M    oracle.ExaWatcher
547M    tmp
[root@linux01]#
Before jumping into the solution, we need to understand how writing into a file works on Un*x systems and what file descriptors are.

Let's start with this simple ls example which shows a file and when redirected to /dev/null shows nothing -- obviously, the output is redirected to /dev/null.
$ ls
a_file
$ ls > /dev/null
$
Now let's do the same as above but with a syntax error:
$ ls -z > /dev/null
ls: invalid option -- 'z'
Try 'ls --help' for more information.
$ ls -z > /dev/null 2>&1
$
Here, we can see that the error is not redirected to /dev/null when doing > /dev/null but only when doing > /dev/null 2>&1 !? This is because > /dev/null redirects the "1" file descriptor (stdout -- your screen) to /dev/null but not the "2" file descriptor which is stderr and also your screen by default.

If everyone knows more or less these special 1 and 2 file descriptors, you can create and use any other file descriptors and read/write from it; lets create a "3" file descriptor and write in it:
$ exec 3>fd3.log
$ echo "to fd3" >&3
$ cat fd3.log
to fd3
$
To kind of simulate a process (an Oracle process or any other) writing into a file through its file descriptor, let's run this while true command inserting the current date every 5 seconds:
$ while true; do echo $(date)" to fd 3 again" >&3; sleep 5; done
The trace file is well updated every 5 seconds:
$ tail -f fd3.log
to fd3
Thu Mar 18 14:28:03 AEDT 2021 to fd 3 again
Thu Mar 18 14:28:08 AEDT 2021 to fd 3 again
Thu Mar 18 14:28:13 AEDT 2021 to fd 3 again
Thu Mar 18 14:28:18 AEDT 2021 to fd 3 again
Now let's remove that file:
$ ls -ltr | grep fd
-rw-r--r-- 1 fred fred 535 Mar 18 14:28 fd3.log
$ date; rm fd3.log
Thu Mar 18 14:28:28 AEDT 2021   <== the date I have removed the file
$ ls -ltr fd3.log
ls: cannot access 'fd3.log': No such file or directory    <=== the file does not exist anymore
$
And if I go back to my session tailing the logfile:
$ tail -f fd3.log
Thu Mar 18 14:28:03 AEDT 2021 to fd 3 again
Thu Mar 18 14:28:08 AEDT 2021 to fd 3 again
Thu Mar 18 14:28:13 AEDT 2021 to fd 3 again
Thu Mar 18 14:28:18 AEDT 2021 to fd 3 again
Thu Mar 18 14:28:23 AEDT 2021 to fd 3 again
Thu Mar 18 14:28:18 AEDT 2021 to fd 3 again  
Thu Mar 18 14:28:23 AEDT 2021 to fd 3 again
Thu Mar 18 14:28:28 AEDT 2021 to fd 3 again  <=== file has been deleted on Thu Mar 18 14:28:28 AEDT 2021
Thu Mar 18 14:28:33 AEDT 2021 to fd 3 again  <=== still things are inserted in it !
Thu Mar 18 14:28:38 AEDT 2021 to fd 3 again
Thu Mar 18 14:28:43 AEDT 2021 to fd 3 again
Thu Mar 18 14:28:48 AEDT 2021 to fd 3 again
Thu Mar 18 14:28:53 AEDT 2021 to fd 3 again
Thu Mar 18 14:28:58 AEDT 2021 to fd 3 again
Thu Mar 18 14:29:03 AEDT 2021 to fd 3 again
Thu Mar 18 14:29:08 AEDT 2021 to fd 3 again
I can see that my file is still being filled by the while true I started !? this is because the file descriptor is still opened and then the process is still writing in it -- but you cannot see the file as his physical enveloppe (wow this is becoming mystic ! :D) does not exist any more -- this is the situation I was describing earlier.

Indeed, the full process of writing into a file is:
1/ open the file (open a file descriptor)
2/ write in it (write into a file descriptor)
3/ close the file (close the file descriptor)
Now that we know this and as my example as shown, it looks obvious that we have a (far) better (and easier and safer and better . . . name it . . .) solution than restarting the application or rebooting the database or server, right ?

Let's move further into the investigation (as you also most likely don't know which trace files have been removed) and see the correct solution later on.

First of all, we need to find the biggest deleted files thanks to lsof +aL1 (see man lsof):
[root@linux01 u01]# lsof +aL1 /u01 sort -nk 7 | tail -10
oracle    263797 oracle  271w   REG  252,2    4915555     0 1059311 /u01/app/oracle/diag/rdbms/db01/SID01/trace/SID01_ora_263797.trm (deleted)
diskmon    25690 oracle  363w   REG  252,2    5736792     0  942591 /u01/app/oracle/diag/crs/linux01/crs/trace/diskmon_68.trm (deleted)
oracle    316046 oracle   68w   REG  252,2    8536422     0 1488777 /u01/app/oracle/diag/rdbms/db01/SID01/trace/SID01_ora_316046.trc (deleted)
oracle    116391 oracle   90w   REG  252,2    9324380     0 4873097 /u01/app/oracle/diag/rdbms/db01/SID01/trace/SID01_ora_116391.trc (deleted)
oracle    116379 oracle   89w   REG  252,2    9621504     0 4876403 /u01/app/oracle/diag/rdbms/db01/SID01/trace/SID01_ora_116379.trc (deleted)
oracle    116340 oracle   86w   REG  252,2    9664646     0 4873104 /u01/app/oracle/diag/rdbms/db01/SID01/trace/SID01_ora_116340.trc (deleted)
diskmon    25690 oracle  362w   REG  252,2   27203987     0  942489 /u01/app/oracle/diag/crs/linux01/crs/trace/diskmon_68.trc (deleted)
oracle    263797 oracle  270w   REG  252,2   36228291     0 1059304 /u01/app/oracle/diag/rdbms/db01/SID01/trace/SID01_ora_263797.trc (deleted)
ora_p02l_ 371508 oracle   49w   REG  252,2  209219823     0 5767946 /u01/app/oracle/diag/rdbms/db02/SID02/trace/SID02_p02l_371508.trm (deleted)
ora_p02l_ 371508 oracle   48w   REG  252,2 3959405542     0 5767945 /u01/app/oracle/diag/rdbms/db02/SID02/trace/SID02_p02l_371508.trc (deleted)
[root@linux01 u01]#
We can find from /proc the process ID and the file descriptors of these files:
[root@linux01 u01]# ls -ltr /proc/371508/fd | grep SID02
l-wx------ 1 oracle dba 64 Nov  4 21:32 49 -> /u01/app/oracle/diag/rdbms/db02/SID02/trace/SID02_p02l_371508.trm (deleted)
l-wx------ 1 oracle dba 64 Nov  4 21:32 48 -> /u01/app/oracle/diag/rdbms/db02/SID02/trace/SID02_p02l_371508.trc (deleted)
[root@linux01 u01]#
We then just have to apply the 3rd step on how to write into a file: close these file descriptors ! then the process would no mode write into it -- easy !

If it is easy to do in a program you write, we have here to close a file descriptor into another running PID (which is still doing tons of stuff we do not want to stop). For this purpoise, we will be using gdb which is the GNU debugger (default on any Linux):
[root@linux01 u01]# gdb -p 371508
. . .
(gdb) call close(48)
$1 = 0
(gdb) call close(49)
$2 = 0
(gdb) quit
A debugging session is active.

        Inferior 1 [process 371508] will be detached.

Quit anyway? (y or n) y
Detaching from program: /u01/app/oracle/product/19.0.0.0/db_1/bin/oracle, process 371508
[Inferior 1 (process 371508) detached]
[root@linux01 u01]#
We can verify that these file descriptors have been well closed
[root@linux01 u01]# ls -ltr /proc/371508/fd | grep SID02
[root@linux01 u01]#

You have then properly closed these file descriptors, no more space issue on your system, problem fixed !

IB Switches: May the --force be with you !

Patching Infiniband Switches is usually really hassle free but you may one day face a (very) reluctant to be patched IB Switch. Note that this blog is part of a more general Exadata patching troubleshooting blog.
This journey started with some failed IB Switches pre-requisites:
FAILED : DONE: Initiate pre-upgrade validation check on InfiniBand switch(es).
ERROR : FAILED run of command:/patches/20.1.6.0.0/patch_switch_20.1.6.0.0.210113/patchmgr -ibswitches /root/ib_group -upgrade -ibswitch_precheck
INFO : upgrade attempted on nodes in file /root/ib_group: [exa-ib1 exa-ib2 exa-ib3]
Looking at patchmgr.trc, I could find:
[patchmgr_send_notification_to_all_nodes][702]  Arguments: Failed 808 ibswitch
And in upgradeIBSwitch.trc:
[TRACE][/patches/20.1.6.0.0/patch_switch_20.1.6.0.0.210113/upgradeIBSwitch.sh - 1740][copyToIBSwitch][1740]   Arguments: exa-ib1 xcp /usr/local/bin/xcp
[WARNING][/patches/20.1.6.0.0/patch_switch_20.1.6.0.0.210113/upgradeIBSwitch.sh - 1749][copyToIBSwitch][]  [CMD: scp xcp root@\[exa-ib1\]:/usr/local/bin/xcp] [CMD_STATUS: 1]
    ----- START STDERR -----
    xcp: No such file or directory
    ----- END STDERR -----
[TRACE][/patches/20.1.6.0.0/patch_switch_20.1.6.0.0.210113/upgradeIBSwitch.sh - 1740][copyToIBSwitch][1740]   Arguments: exa-ib1 libxcp.so.1 /usr/local/lib/libxcp.so.1
[WARNING][/patches/20.1.6.0.0/patch_switch_20.1.6.0.0.210113/upgradeIBSwitch.sh - 1749][copyToIBSwitch][]  [CMD: scp libxcp.so.1 root@\[exa-ib1\]:/usr/local/lib/libxcp.so.1] [CMD_STATUS: 1]
    ----- START STDERR -----
    libxcp.so.1: No such file or directory
This was looking like if patchmgr was unable to copy xcp and libxcp.so.1 to the switches so it could be a SSH passwordless connectivity issue (patchmgr tries to connect back to the database node used to patch it which may be impossible depending on what is in the switch /etc/hosts or your SSH security config defined in /etc/ssh/sshd_config -- you can find notes like this one Exadata: Patchmgr fails during the InfiniBand patching precheck. (Doc ID 2356026.1) on MOS about this. But well I know this and I was able SSH to my Switch which also could SSH back properly on any network interfaces to the DB node I was using to patch; I could also manually scp the famous xcp and libxcp.so.1. All was supposed to be OK.

Checking further, I found that this reluctant switch was with a very old version:
[root@exadb01 ~]# ./exa-versions.sh -I ~/ib_group
       Cluster is a X5-2 Quarter Rack HC 8TB
         -- Infiniband Switches
       exa-ib1        exa-ib2        exa-ib3
----------------------------------------------------
       2.1.8-1       2.2.15-1        2.2.15-1
----------------------------------------------------
[root@exadb01 ~]#
Indeed, if you look into Note 888828.1, you will find that Switch firmware 2.1.8-1 - Supplied with Exadata 12.1.2.3.x; 12.1.2.3 being released in April 2016 (keep in mind that patchmgr has been released in version 12.2.1.1.0 which was shipping IB Switch version 2.2.4-3 then ** after ** this 2.1.8-1 -- more on that later); It was then indeed an old version and it also meant that I was not really the first one facing this issue which then had not been resolved before :)

After investigating all of this with Oracle support which basically wanted to be sure that the SSH config was working, I have been pointed to the manual way of patching an IB Switch (which was the way of patching a Switch before patchmgr) described here : https://docs.oracle.com/cd/E76424_01/html/E76431/z400029a1775330.html#scrolltoc. It is pretty straightforward: you load the package, the switch installs and reboot and that's it; so I gave it a go (you cannot directly upgrade to 2.2.16-1 which was my target version but you first have to upgrade to 2.2.7-2):
-> load -source fhttp://10.11.12.13/patches/20.1.6.0.0/patch_switch_20.1.6.0.0.210113/sundcs_36p_repository_upgrade_2.1_to_2.2.7_2.pkg
Downloading firmware image. This will take a few minutes.
Error: Couldn't connect to server
-> load -source http://10.11.12.13/patches/20.1.6.0.0/patch_switch_20.1.6.0.0.210113/sundcs_36p_repository_upgrade_2.1_to_2.2.7_2.pkg
Downloading firmware image. This will take a few minutes.
Error: Couldn't connect to server
which failed miserably; I then realized that this could not work, there is no FTP nor HTTP running on my database server where I want to load that package to the switch. The (very good) MOS engineer told me there was no other way: FTP or HTTP -- wow, FTP ? really ? you mean that old buddy running on port 21 ? no way I can have this to run on my DB node; FTP is a bit like Nokia 3210 -- you remember it was great but no way you can use it nowadays :D

As I could obviously not install a FTP or a HTTP server anywhere close to that switch, I tried to scp the package to the switch itself and load it from there -- locally:
-> load -source ftp://10.20.21.22/tmp/sundcs_36p_repository_2.2.7_2.pkg
Error: Insufficient disk space/memory. Firmware update requires minimum of
120 MB space in /tmp directory
80 MB space in / filesystem
120 MB of free memory 
It also failed miserably as obviously there is not enough space on the Switch to save a 180M package -- this started to be tough:
  • patchmgr fails at pre-requisites
  • No way to have a FTP server to load the package to the switch
  • No way to have a HTTP server to load the package to the switch
  • Not enough space to copy the package to the switch to load it locally
  • Not sure how patchmgr manages it but he can somehow load the package to the switch as this is what he usually does (I have to check patchmgr code to see what is that magic trick)

But still well, I had to patch this switch even if it was actually looking a bit like that to me:

So we (MOS engineer and I) thought that as patchmgr was released after this switch version, it may just not be aware of this switch version and then the pre-requisites could fail just because he didnt't know that version -- so I tried the upgrade (of that switch only) ignoring the pre-requisites with the -- force option !:
[root@exadb01 patch_switch_20.1.6.0.0.210113]# ./patchmgr -ibswitches ~/ib1 -upgrade --force yes
. . .
[INFO     ] Package will be downloaded at firmware update time via scp  <== a clue about how patchmgr does it -- but where does it find the disk space ? this is another story :)
[SUCCESS  ] Execute plugin check for Patching on exa-ib1
[INFO     ] Starting upgrade on exa-ib1 to 2.2.7_2. Please give upto 15 mins for the process to complete. DO NOT INTERRUPT or HIT CTRL+C during the upgrade
[INFO     ] Additional firmware load required. Starting secondary firmware load. DO NOT INTERRUPT or HIT CTRL+C
[INFO     ] Rebooting exa-ib1 to complete the firmware update. Wait for 15 minutes before continuing. DO NOT MANUALLY REBOOT THE INFINIBAND SWITCH
. . . looking good so far . . . 
[INFO     ] Validating the current firmware on the InfiniBand Switch
[SUCCESS  ] Firmware verification on InfiniBand switch exa-ib1
[INFO     ] Finished post-update validation on exa-ib1
[FAIL     ] Post-update validation on exa-ib1
[ERROR    ] Failed to upgrade exa-ib1 to 2.2.7-2. Cannot proceed with upgrading switch to 2.2.16_1
[FAIL     ] Update switch exa-ib1 to 2.2.16_1
[INFO     ] Aborting the process. Not going to try anymore switches. Retry after resolving the problems.
[FAIL     ] Overall status
OK so here it seems that the upgrade to 2.2.7-2 was OK but the post steps were KO -- may be also because of the fact that the original version of the Switch was too old; I could verify the version which was now good:
[root@exa-ib1 ~]# version
SUN DCS 36p version: 2.2.7-2 <================ looks good
Build time: Nov 2 2017 09:21:37
. . .
[root@exa-ib1 ~]#
OKay, now I could run the upgrade to 2.2.16-1 pre-requisites on Switch -- which were OK:
----- InfiniBand switch update process ended 2021-02-12 12:19:33 +1100 -----
2021-02-12 12:19:33 +1100 1 of 1 :SUCCESS: Initiate pre-upgrade validation check on InfiniBand switch(es).
2021-02-12 12:19:33 +1100 :SUCCESS: Completed run of command: /patches/20.1.6.0.0/patch_switch_20.1.6.0.0.210113/patchmgr -ibswitches /root/ib1 -upgrade -ibswitch_precheck
2021-02-12 12:19:33 +1100 :INFO : upgrade attempted on nodes in file /root/ib1: [exa-ib1] 
And then I could upgrade all the 3 switches in a row, patchmgr now taking care of the version difference to upgrade all these switches to the target version: 2.2.16-1 which worked like a charm !

I could then finally patch this reluctant to be patched Infiniband Switch thanks to the -- force option because he was older than patchmgr -- May the -- force be with you !

Exadata: patchmgr -- dbnodeupdate.sh backup failed on one or more nodes

Patchmgr is nice enough to backup a databae node system before patching it which is a very cool feature. You can also only backup (and not patch)a database node (patchmgr -backup) or patch a database node without backing it up (patchmgr -nobackup) -- but the default is to backup the system just before patching it which is perfectly fine.

But every feature can eventually fail and the whole patching session is not started if the backup fails like in the below log:
2021-02-03 07:31:32 +1100        :Working: dbnodeupdate.sh running a backup on 2 node(s).
2021-02-03 07:34:26 +1100        :ERROR  : dbnodeupdate.sh backup failed on one or more nodes 
SUMMARY OF ERRORS FOR dbnode01:
dbnode01: ERROR: Backup failed investigate logfiles /var/log/cellos/dbnodeupdate.log and /var/log/cellos/dbserver_backup.sh.log
SUMMARY OF ERRORS FOR dbnode02:
dbnode02: ERROR: Backup failed investigate logfiles /var/log/cellos/dbnodeupdate.log and /var/log/cellos/dbserver_backup.sh.log

You can then check the logfile pointed by patchmgr in the error stack:
[root@dbnode01 ~]# cat /var/log/cellos/dbserver_backup.sh.log
Feb 03 07:34:09  [INFO]
Feb 03 07:34:09  [INFO] Start to backup root /dev/VGExaDb/LVDbSys1 and boot partitions
Feb 03 07:34:09  [INFO] Check for Volume Group "VGExaDb"
Feb 03 07:34:09  [INFO] Check for the LVM root partition "VGExaDb/LVDbSys1"
Feb 03 07:34:10  [INFO] LVM snapshot Logical Volume
Feb 03 07:34:10  [ERROR] LVM snapshot Logical Volume "VGExaDb/LVDbSys1Snap" already exists
Feb 03 07:34:10  [ERROR] Remove snapshot manually and then restart this utility
[root@dbnode01 ~]#
The issue is very clear here, the LVM snapshot used for the backup already exists most likely due to something wrong during a previous patching session. We even have the solution which is to remove it manually which is an easy procedure:
[root@dbnode01 ~]# lvm lvscan | grep -i snap
inactive Snapshot '/dev/VGExaDb/LVDbSys1Snap' [10.00 GiB] inherit
[root@dbnode01 ~]# lvremove -f /dev/VGExaDb/LVDbSys1Snap
Logical volume "LVDbSys1Snap" successfully removed
[root@dbnode01 ~]# lvm lvscan | grep -i snap
[root@dbnode01 ~]#

Now that the snapshot LVM is removed, you can restart your database nodes patching which now will be successful !

Exadata: make a cell or a DB node blink !

Hardware issues happen and when it happens on Exadata systems, you need to have an Oracle Field Engineer to go into your Datacenter and replace the faulty part. What also happens is that you have many Exadatas in your datacenter, your CMDB is not really up to date and as a result, the Field Engineer is in trouble locating the Exadata component he needs to replace something faulty in.
Hopefully, the ILOMs have a very cool feature and you can make a cell or a DB node blink ! (then easy to locate)

First of all, connect to the ILOM and check the /SP/LOCATE property:
-> show /SYS/LOCATE
/SYS/LOCATE
    Targets:
    Properties:
        type = Indicator
        ipmi_name = LOCATE
        value = Off            <=== OFF
    Commands:
        cd
        set
        show
->
Let's make it blink:
-> set /SYS/LOCATE value=fast_blink
Set 'value' to 'fast_blink' [Fast Blink]
-> show /SYS/LOCATE
/SYS/LOCATE
    Targets:
    Properties:
        type = Indicator
        ipmi_name = LOCATE
        value = Fast Blink     <=== It blinks !
    Commands:
        cd
        set
        show
->
Once the Field Engineer has located your blinking component, it is time to stop the blinking -- I know it is very fun so let it a couple more minutes and then stop it:
-> set /SYS/LOCATE value=off
Set 'value' to 'off' [Off]
-> show /SYS/LOCATE
/SYS/LOCATE
    Targets:
    Properties:
        type = Indicator
        ipmi_name = LOCATE
        value = Off            <=== OFF
    Commands:
        cd
        set
        show
->

This is be very useful, I use it a lot !

Exadata: Hack patchmgr

Do no try this at home, this blog is for educational (and fun) purpose only.

Let's take as an example that weird patchmgr behavior when patching Exadata:
  • 1/ patchmgr uses the /etc/hosts IP of a host to start the patching
  • 2/ patchmgr uses the DNS ip of a host when waiting for a host to reboot
So if it happens that the DNS IP is blocked by a firewall for example (this would be most likely due to a wrong configuration but let's assume this is the situation we are in) then patchmgr will wait for the host te be back after reboot forever -- and you will be in trouble.

To work this around, you can still comment the DNS server(s) out of the /etc/resolv.conf file from the host you start patchmgr from (no DNS server then patchmgr would not be able to use the DNS IP to ping the host waiting to come back after reboot then would use the /etc/hosts IP instead) but, by doing that, the whole host would be unable to use DNS during this patch session and this is not what you want; indeed, if you use an external server to start patchmgr, you will most likely create an incident on this system.

Another way is to ... "adapt" patchmgr to make it not to use the DNS IP when pinging the patched host to wait for it to come back online after reboot. And this kind of easy as patchmgr is made out of Shell script -- great news, right ?
So looking into patchmgr code, you will find that patchmgr uses the host command to resolve the target server IP:
host_name_or_ip=$(host -t A $target | awk '/has address/ {print $NF; exit}')
And if you look at man host, you'll see that host resolves using DNS:
host - DNS lookup utility
So this is where the described issue comes from; we would not have this issue if patchmgr would resolve the host from the /etc/hosts file using for example a simple ping:
host_name_or_ip=$(ping -qc1 $target | head -1 | awk -F "[()]" '{print $2}')
Note that the resolution from /etc/hosts before DNS is default as you can see in /etc/nsswitch.conf:
# grep hosts /etc/nsswitch.conf
hosts:          files dns    <=== we resolve using files before DNS
All that said, we can then update patchmgr to resolve using ping and no more host:
#host_name_or_ip=$(host -t A $target | awk '/has address/ {print $NF; exit}')
host_name_or_ip=$(ping -qc1 $target | head -1 | awk -F "[()]" '{print $2}')
And let's run a test (just a precheck) to see how it goes:
# ./patchmgr -dbnodes ~/dbs_group -precheck -nomodify_at_prereq -target_version 19.3.12.0.0.200905 -iso_repo ../p31720221_193000_Linux-x86-64.zip -allow_active_network_mounts
2020-11-05 15:22:45 +1100        :ERROR  : Incorrect md5sum of /patches/dbserver_patch_20.200911/patchmgr
#
Hey, patchmgr has detected that we have modified it, clever ! Indeed, patchmgr checks the md5 of all the files before starting a patching sesssion; these md5 values are saved in the md5sum_files.lst file, so we just have to get the md5 of our "patched" patchmgr and update md5sum_files.lst with it:
# md5sum patchmgr
8e75bf3c1cae3e2d75229c85e84f8e0e  patchmgr
# cp md5sum_files.lst md5sum_files.lst.orig
# vi md5sum_files.lst
# grep patchmgr md5sum_files.lst
8e75bf3c1cae3e2d75229c85e84f8e0e  patchmgr
40acc292fec697492dd40a6938fb60c4  patchmgr_functions
#

And you are now good to go, you can now run your patched patchmgr !

Again, do no try this at home, this blog is for educational (and fun) purpose only. Nothing here would be supported by Oracle -- but it is still good to know ! :)

Exadata: Repair a corrupted / broken RPM database

Storage servers and DB nodes are Linux machines which use RPM as package manager. This RPM has a database to store the installed packages, etc ... It happened a few times that this database became corrupted after an Exadata patching. And you usually discover this during your next patching session with this kind of complaint from the pre-requisites:
2020-11-12 13:12:15 +1100        :FAILED : Check space and state of cell services.
You can note that the error message is Check space and state of cell services so the first thing is to check whether you have a space issue or not then once you have verified it is not that (dcli -g ~/cell_group -l root "df -h /" -- / needs 3 GB for patching), you know that the issue is with the state of your component (cell or DB node).

You then have to check the hostname.log of the culprit in the patchmgr directory (usually all the "hostname.log" logfiles have a very similar size so if one is bigger, you most likely have the culprit with a simple ls) and you may find:
cel02: [ERROR] Can not continue. Runtime configuration is not consistent with values configured in /opt/oracle.cellos/cell.conf.
cel02: [ERROR] Run ipconf to correct the inconsistencies. Failed check: /root/_cellupd_dpullec_/_p_/ipconf -check-consistency -at-runtime -semantic -verbose
This is not excessively verbose but it gives you a good hint and the command which has failed, you can then re execute this command and see how it goes:
[root@cel02 ~]# /root/_cellupd_dpullec_/_p_/ipconf -check-consistency -at-runtime -semantic -verbose
error: rpmdb: BDB0113 Thread/process 23845/140082556999744 failed: BDB1507 Thread died in Berkeley DB library
error: db5 error(-30973) from dbenv->failchk: BDB0087 DB_RUNRECOVERY: Fatal error, run database recovery
error: cannot open Packages index using db5 -  (-30973)
error: cannot open Packages database in /var/lib/rpm
error: rpmdb: BDB0113 Thread/process 23845/140082556999744 failed: BDB1507 Thread died in Berkeley DB library
error: db5 error(-30973) from dbenv->failchk: BDB0087 DB_RUNRECOVERY: Fatal error, run database recovery
error: cannot open Packages database in /var/lib/rpm
[Info]: ipconf command line: /root/_cellupd_dpullec_/_p_/ipconf.pl -check-consistency -at-runtime -semantic -verbose -nocodes
Logging started to /var/log/cellos/ipconf.log
[Warning]: File not found /etc/ntp.conf
. . . many more info not useful in this scenario . . .

We can clearly see 2 issues here:
  • Missing /etc/ntp.conf: this can be ignored, it is documented in note 2689297.1
  • A RPM issue

We can confirm the RPM issue just by queying the RPM database:
[root@cel02 ~]# rpm -qa
error: rpmdb: BDB0113 Thread/process 23845/140082556999744 failed: BDB1507 Thread died in Berkeley DB library
error: db5 error(-30973) from dbenv->failchk: BDB0087 DB_RUNRECOVERY: Fatal error, run database recovery
error: cannot open Packages index using db5 -  (-30973)
error: cannot open Packages database in /var/lib/rpm
error: rpmdb: BDB0113 Thread/process 23845/140082556999744 failed: BDB1507 Thread died in Berkeley DB library
error: db5 error(-30973) from dbenv->failchk: BDB0087 DB_RUNRECOVERY: Fatal error, run database recovery
error: cannot open Packages database in /var/lib/rpm
[root@cel02 ~]#
So here we have to rebuild this corrupted RPM database and the good is that it ca be done 100% onlin with no disruption:
[root@cel02 ~]# mkdir /var/lib/rpm/backup
[root@cel02 ~]# cp -a /var/lib/rpm/__db* /var/lib/rpm/backup/
[root@cel02 ~]# rm -f /var/lib/rpm/__db*
[root@cel02 ~]# rpm --rebuilddb
[root@cel02 ~]#
Easy, right ? you can now verify the good health of your RPM database:
[root@cel02 ~]# rpm -qa | wc -l
455
[root@cel02 ~]#
You can revalidate the whole configuration:
[root@cel02 ~]# cellcli -e alter cell validate configuration
Cell cel02 successfully altered
[root@cel02 ~]#

And you are good to go, everything is now fixed and clean, your pre-requisites and future patch will now be working !
Note that this example is with a cell but it works the same way with a database node (and any Linux server).

Exadata: reinstall a broken system RPM

The Exadata compute nodes and storage servers are some Linux servers with a specific software which optimizes everything for the Oracle database, the Oracle clusterware, etc... it means that the software is a mix of RPMs like any other Red Hat system and when we patch these servers, Oracle provides an ISO (in note 888828.1) containing the new version of all these RPMs and patchmgr updates all these RPMs. And usually, our job stops here.

But . . . it may happen that a RPM needs to be reinstalled as it may be become corrupted or broken. Let's take as an example the Exadata Management Package which provides the ability to monitor the Exadata compute nodes and storage cells. This Exadata Management Package software is located in /etc/oracle/dbserver so if you remove this directory (don't do that :)), the dbmcli command won't work any more and you will be in trouble (for patching and more).

The situation will then be that the RPM wil still be installed at the system level but dbmcli is not here any more:
[root@node01]# rpm -qa | grep exadata-dbmmgmt
exadata-dbmmgmt-19.2.8.0.0.191119-1.noarch
[root@node01]# dbmcli
dbmcli: command not found
To fix this situation, you need to reinstall this RPM and to start with, you need to get it for your current version (imageinfo or exa-versions.sh will give you the current version of your system). If you have patched your Exadata yourself, you will have the patch already somewhere; if not, you'll find it in note 888828.1.

To get the ISO out of the patch, you need to unzip the patch (thing that patchmgr does for us when patching):
[root@node01]# unzip -q p30398147_192000_Linux-x86-64.zip
[root@node01]# ls -ltr exa*
-rw-rw-r-- 1 root root 1421932544 Nov 20  2019 exadata_ol7_base_repo_19.2.8.0.0.191119.iso
Now, we will mount the ISO:
[root@node01]# mkdir /mnt
[root@node01]# mount -o loop exadata_ol7_base_repo_19.2.8.0.0.191119.iso /mnt
mount: /dev/loop0 is write-protected, mounting read-only
We can now copy the RPM somewhere for future use and umount the ISO (we are done with it, you can delete it):
[root@node01]# cp /mnt/x86_64/exadata-dbmmgmt-19.2.8.0.0.191119-1.noarch.rpm /tmp/.
[root@node01]# umount /mnt
Let's now deinstall the broken RPM:
[root@node01]# rpm -e exadata-dbmmgmt-19.2.8.0.0.191119-1.noarch --nodeps
tee: /opt/oracle/dbserver_19.2.8.0.0.191119/.install_log.txt: No such file or directory
2020-11-03 15:00:05 +1100: Pre uninstallation steps in progress ...
Uninstalling version 19.2.8.0.0.191119.
. . . many errors as the directory has been dropped . . .
And reinstall the good RPM:
[root@node01]# rpm -ivh /tmp/exadata-dbmmgmt-19.2.8.0.0.191119-1.noarch.rpm
Preparing...                          ################################# [100%]
2020-11-03 15:00:24 +1100: Pre Installation steps in progress ...
2020-11-03 15:00:24 +1100: This is a fresh install.
Updating / installing...
   1:exadata-dbmmgmt-19.2.8.0.0.191119################################# [100%]
2020-11-03 15:00:34 +1100: Post Installation steps in progress ...
. . .
[root@node01]#
In the specific case of the management package, we also need to restart the services (dbmcli -e alter dbserver restart services all) and you are good to go as if /etc/oracle/dbserver has never been dropped !

The important thing to understand here is that the patches provided in the note 888828.1 to patch your Exadatas servers are ISO containing RPMs which can then be used to reinstall some RPMs in case of something wrong happens on your systems -- and this can be very very useful !

Exadata: ILOM hostname change

I am not sure about the root cause of this one but it was very weird finding that an ILOM had a wrong hostname (yes, wrong hostname) -- below the logs from a cell patching pre-requisites session:
cel01: [ERROR] Details:
cel01: ILOM hostname cel01.domain.com must match cel01-ilom.domain.com in /opt/oracle.cellos/cell.conf  : FAILED
cel01: [Info]: Consistency check FAILED
Indeed, the ILOM had the same hostname as the cell which obviously is not what we want:
[root@db01 ~]# ssh cel01-ilom
Password:
Hostname: cel01
-> show /SP hostname
/SP
    Properties:
        hostname = cel01         <===== bad, this is the cell hostname !
->
The cool thing with ILOMs is that we can change this online with no disruption:
-> set /sp hostname=cel01-ilom
Set 'hostname' to 'cel01-ilom'
-> show /SP hostname
/SP
    Properties:
        hostname = cel01-ilom   <===== good
->
One more easy online fix (for a weird issue :))!

Exadata: ILOM NTP change / fix

A recent cell patching showed me this error during the pre-requisites phase:
cel01: ILOM use NTP servers "disabled" must match "enabled" in /opt/oracle.cellos/cell.conf              : FAILED
cel01: ILOM first NTP server 0.0.0.0 must have non-empty value                                           : FAILED
This was due to a bad NTP configuration on the ILOM:
[root@db01 ~]# ssh cel01-ilom
Password:
Hostname: cel01
-> show /sp/clients/ntp
/SP/clients/ntp
    Targets:
        server
    Properties:         <===== nothing here
->
You can set the NTP servers as below:
-> set /SP/clients/ntp/server/1 address=10.11.12.13
Set 'address' to '10.11.12.13'
-> set /SP/clients/ntp/server/2 address=10.11.12.14
Set 'address' to '10.11.12.14'
->
And a quick check to verify the setting:
-> show /sp/clients/ntp/server/1
/SP/clients/ntp/server/1
    Targets:
    Properties:
        address = 10.11.12.13   <===== good       
-> show /sp/clients/ntp/server/2
/SP/clients/ntp/server/2
    Targets:
    Properties:
        address = 10.11.12.14   <===== good
->
This is good but not enough as we also have to check that the use of NTP is enabled:
-> show /SP/clock usentpserver
/SP/clock
    Targets:
    Properties:
        usentpserver = disabled     <===== disabled (bad)
->
Let's enable it:
-> set /SP/clock usentpserver=enabled
Set 'usentpserver' to 'enabled'
-> show /SP/clock usentpserver
/SP/clock
    Targets:
    Properties:
        usentpserver = enabled     <===== enabled (good)
->

An easy and 100% online fix !

How to Patch / Upgrade Exadata to any version -- Part 5 -- Troubleshooting

It does not seem possible to me to write an exhaustive blog about troubleshooting an Exadata patching session which would go bad (or it would be incredibly pretentious). Indeed, an Exadata stack is a complete and complex mix of software and hardware which can, on top of that, be configured very differently depending in each company needs, norms, compliance rules, etc....

The best way, in my humble opinion, to be able to efficiently troubleshoot a failure during an Exadata patching session is to:
  • Know vi and grep to check the logfiles :)
  • Have the full picture of the Exadata patching procedure
  • Keep in mind that, in case of rolling patches, even a crash or a non reponsive server does not impact the uptime of the applications as everything is (at least) redundant so take your time to troubleshoot and stay cool (as a cucumber)
  • Have access to well documented procedures from the real life which help setting and/or manage Exadata components; indeed, the main reasons for problems during Exadata patching sessions are:
    • Failed pre-requisites:
    • - Due to hardware alerts; open a SR to have the failed hardware fixed

      - Due to a misconfiguration of one of the component; you'll find the the procedure below

    • A crash / timeout / non responsive server during the patching:
    • - A space issue but they are usually detected by the pre-requisites

      - Usually, rebooting the server will be needed; you'll find the the procedure below

      - If a SR has to be opened, ILOM snapshot will be needed; you'll find the the procedure below

    • Again, this is not exhaustive and this is the beauty of it ! and this is why this blog is a living blog and will be updated when new issues and solutions appear.


Troubleshooting a failed patch starts with checking the logfiles to get more informatio about the issue you just faced; below a list of the most commn logfiles:
  • patchmgr.log -- the main patchmgr logfile
  • patchmgr.trc -- a more detailed patchmgr output
  • nodename.log --
  • /var/log/cellos/dbnodeupdate.log -- located on the node (not in the patchmgr directory), detailed log of the patch application on this specific node

Each procedure listed below has been executed on real life production Exadatas at least once (many have been used far more than once)
Hope it helps !



Quick links to Part 1 / Part 2 / Part 3 / Part 4 / Part 5 / Part 6

OCI: Datapump between 23ai ADB and 19c ADB using database link

Now that we know how to manually create a 23ai ADB in OCI , that we also know how to create a database link between a 23ai ADB and a 19C AD...