@@ -171,6 +171,10 @@ def setup(self):
171
171
self .updateasmdevices ()
172
172
else :
173
173
pass
174
+ if self .ocommon .check_key ("RUN_DATAPATCH" ,self .ora_env_dict ):
175
+ self .run_datapatch ()
176
+ else :
177
+ pass
174
178
175
179
176
180
ct = datetime .datetime .now ()
@@ -786,3 +790,84 @@ def listasminstname(self):
786
790
print (sid )
787
791
else :
788
792
print ("NOT READY" )
793
+
794
+ def run_datapatch (self ):
795
+ """
796
+ Function to check and apply Oracle database patches using OPatch and Datapatch.
797
+ """
798
+ self .ocommon .log_info_message ("Starting run_datapatch()" , self .file_name )
799
+ rundatapatch = self .ora_env_dict .get ("RUN_DATAPATCH" , "" ).strip ().lower () in ["true" , "1" , "yes" ]
800
+
801
+ self .ocommon .log_info_message (f"Running datapatch with passed argument: { rundatapatch } " , self .file_name )
802
+
803
+ if not rundatapatch :
804
+ self .ocommon .log_info_message ("RUN_DATAPATCH is not set to true. Skipping datapatch execution." , self .file_name )
805
+ return
806
+ dbuser , dbhome , dbbase , oinv = self .ocommon .get_db_params ()
807
+ self .ocommon .log_info_message ("ORACLE_HOME set to " + dbhome , self .file_name )
808
+ self .ocommon .log_info_message ("ORACLE_USER set to " + dbuser , self .file_name )
809
+ self .ocommon .log_info_message ("ORACLE_BASE set to " + dbbase , self .file_name )
810
+
811
+ dbname , osid , dbuname = self .ocommon .getdbnameinfo ()
812
+ hostname = self .ocommon .get_public_hostname ()
813
+ inst_sid = self .ocommon .get_inst_sid (dbuser , dbhome , osid , hostname )
814
+ self .ocommon .log_info_message ("ORACLE_SID set to " + inst_sid , self .file_name )
815
+
816
+ if not all ([inst_sid , dbbase , dbhome , dbuser ]):
817
+ self .ocommon .log_info_message ("Missing required Oracle environment variables." , self .file_name )
818
+ return
819
+
820
+ # Export required environment variables
821
+ env_setup_cmd = "export ORACLE_SID={0}; export ORACLE_HOME={1}; export ORACLE_BASE={2}; " .format (inst_sid , dbhome , dbbase )
822
+
823
+ # Fetch patches from OPatch
824
+ cmd_lspatches = '''su - {0} -c "{1} {2}/OPatch/opatch lspatches"''' .format (dbuser , env_setup_cmd , dbhome )
825
+ output , error , retcode = self .ocommon .execute_cmd (cmd_lspatches , None , None )
826
+ self .ocommon .check_os_err (output , error , retcode , None )
827
+
828
+ if retcode != 0 :
829
+ self .ocommon .log_info_message ("Failed to fetch OPatch patches." , self .file_name )
830
+ return
831
+
832
+ opatch_patches = {line .split (";" )[0 ].strip () for line in output .splitlines () if ";" in line }
833
+ self .ocommon .log_info_message ("OPatch Patches: " + str (opatch_patches ), self .file_name )
834
+
835
+ # Fetch patches from DBA_REGISTRY_SQLPATCH with proper ORACLE_SID export
836
+ sql_query = "SELECT PATCH_ID FROM DBA_REGISTRY_SQLPATCH;"
837
+ cmd_sqlpatch = '''su - {0} -c "{1} echo \\ "{2}\\ " | sqlplus -S / as sysdba"''' .format (dbuser , env_setup_cmd , sql_query )
838
+ output , error , retcode = self .ocommon .execute_cmd (cmd_sqlpatch , None , None )
839
+ self .ocommon .check_os_err (output , error , retcode , None )
840
+
841
+ if retcode != 0 :
842
+ self .ocommon .log_info_message ("Failed to fetch DBA_REGISTRY_SQLPATCH patches." , self .file_name )
843
+ return
844
+
845
+ sqlpatch_patches = {line .strip () for line in output .splitlines () if line .strip ().isdigit ()}
846
+
847
+ # Compare patch lists
848
+ missing_patches = opatch_patches - sqlpatch_patches
849
+ extra_patches = sqlpatch_patches - opatch_patches
850
+
851
+ self .ocommon .log_info_message ("OPatch Patches: " + str (opatch_patches ), self .file_name )
852
+ self .ocommon .log_info_message ("SQL Patch Patches: " + str (sqlpatch_patches ), self .file_name )
853
+
854
+ if not missing_patches and not extra_patches :
855
+ self .ocommon .log_info_message ("All patches are correctly applied." , self .file_name )
856
+ else :
857
+ if missing_patches :
858
+ self .ocommon .log_info_message ("These patches are missing in DBA_REGISTRY_SQLPATCH: " + str (missing_patches ), self .file_name )
859
+ self .ocommon .log_info_message ("Running datapatch..." , self .file_name )
860
+
861
+ cmd_datapatch = '''su - {0} -c "{1} {2}/OPatch/datapatch -skip_upgrade_check"''' .format (dbuser , env_setup_cmd , dbhome )
862
+ output , error , retcode = self .ocommon .execute_cmd (cmd_datapatch , None , None )
863
+ self .ocommon .check_os_err (output , error , retcode , None )
864
+
865
+ if retcode == 0 :
866
+ self .ocommon .log_info_message ("Datapatch execution completed successfully." , self .file_name )
867
+ else :
868
+ self .ocommon .log_info_message ("Datapatch execution failed." , self .file_name )
869
+
870
+ if extra_patches :
871
+ self .ocommon .log_info_message ("These patches appear in DBA_REGISTRY_SQLPATCH but not in OPatch: " + str (extra_patches ), self .file_name )
872
+
873
+ self .ocommon .log_info_message ("End run_datapatch()" , self .file_name )
0 commit comments