def get_necessary_info(self): log.info('begin get_necessary_info!!!') split_result = '|awk -F \'[=]\' \'{print $2}\'' get_instance = '|grep TINSTANCE{}'.format(split_result) dir_instance = '|grep DIR_INSTANCE{}'.format(split_result) get_instance_cmd = "su - {} -c 'env'{}".format(self.hana_adm, get_instance) get_dir_instance_cmd = "su - {} -c 'env'{}".format( self.hana_adm, dir_instance) try: log.info('get_instance_cmd:{}'.format(get_instance_cmd)) log.info('get_dir_instance_cmd:{}'.format(get_dir_instance_cmd)) instance_result = exec_cmd2(get_instance_cmd) if instance_result['ret'] != 0: raise DbfenError( 20120073, instance_result['msg'] + instance_result['errmsg']) dir_instance_result = exec_cmd2(get_dir_instance_cmd) if dir_instance_result['ret'] != 0: raise DbfenError( 20120074, dir_instance_result['msg'] + dir_instance_result['errmsg']) except Exception as ex: log.exception(ex) raise ex return { 'instance': instance_result['msg'], 'dir_instance': dir_instance_result['msg'] }
def backup_redo_log(self, save_path): dir_log_source = 'SYSTEMDB' if self.target_db.upper( ) == 'SYSTEMDB' else 'DB_{}'.format(self.target_db.upper()) default_log_path = '{}/backup/log/{}'.format(self.dir_instance, dir_log_source) cp_redo_log = "su - {} -c 'cp {}/* {}'".format(self.hana_adm, default_log_path, save_path) try_times = 3 try: while try_times <= 3: result = exec_cmd2(cp_redo_log) status = result['ret'] output = result['msg'].strip() if status == 0: return True else: log.warn('[TASK_ID:' + str(self.task_id) + '] backup_redo_log cmd fail! dump_cmd:' + cp_redo_log + 'status:' + str(status) + ' output:' + output) exec_cmd2('rm -rf {}/log_*'.format(self.backup_dir)) return False except Exception as ex: error() log.error('[backup_redo_log]' + str(type(ex)) + ":" + str(ex)) return False
def start_back_hana_db(self): log.info('begin start_back_hana_db') backup_count = 0 config = getconf() save_path = os.path.join(self.backup_dir, self.target_db) if self.transfer_method != 'tcp': mount_result = apply_source_and_mount(mount_path=self.backup_dir, backup_mode=self.backup_mode) if not mount_result: return False self.mount_path = self.backup_dir if not os.path.exists(save_path): os.makedirs(save_path) exec_cmd2('chown {}:sapsys {}'.format(self.hana_adm, save_path)) while 1: result = self.hana_db_backup() if result is True: break else: backup_count += 1 if backup_count > config.DB_BACKUP_RETRY_TIMES: log.error('[TASK_ID:' + str(self.task_id) + '] hana backup error! exit.') return False return True
def check_customize_recovery(self, is_create_db): if is_create_db: self.stop_tenant_database(self.to_db) sql_cmd = r'drop database {}'.format(self.to_db) drop_tenant_cmd = self.system_db_exec_command_str(sql_cmd) exec_cmd2(drop_tenant_cmd) log.info('recovery fail!!!drop customize database:{}'.format( self.to_db))
def create_tenant_db(self): sql_cmd = r"CREATE DATABASE {} SYSTEM USER PASSWORD Suj000123".format( self.to_db) exec_command = self.system_db_exec_command_str(sql_cmd) result = exec_cmd2(exec_command) if result['ret'] != 0: raise DbfenError(20120080, result['msg'] + result['errmsg'])
def show_hana_databases(self, is_show=True): log.info('begin show_hana_databases!!!') sql_cmd = r"select DATABASE_NAME from SYS.M_DATABASES where ACTIVE_STATUS=\'YES\'" exec_command = self.system_db_exec_command_str(sql_cmd) exec_command_log = exec_command.replace( r'-p \"{}\"'.format(self.system_db_pwd), '-p ******') log.info('check_system_db_cmd:{}'.format(exec_command_log)) try: result = exec_cmd2(exec_command) log.info('result is:{}'.format(result)) status = result['ret'] output = result['msg'].strip() if status != 0 and self.tenant_user == '': log.error( 'system db abnormal,please check system db!!!,maybe is password not correct or others!!!' ) raise DbfenError(20120082, result['msg'] + result['errmsg']) databases = self.split_result_database_str(output) if len(databases) == 1: log.error( 'system db abnormal,please check system db!!!,maybe is password not correct or others!!!' ) raise DbfenError(20120082, result['msg'] + result['errmsg']) if is_show: return databases exec_command = self.system_db_exec_command_str(sql_cmd, False) exec_command_log = exec_command.replace( r'-p \"{}\"'.format(self.tenant_passwd), '-p ******') log.info('check target db {} is whether normal!!!'.format( exec_command_log)) result = exec_cmd2(exec_command) status = result['ret'] output = result['msg'].strip() tenant = self.split_result_database_str(output) if len(tenant) == 0: log.error( 'tenant db not active!!!please check tenant {} status!!!'. format(self.target_db)) raise DbfenError(20120083, result['msg'] + result['errmsg']) if status != 0: log.error('maybe is db: {} password incorrect!!!'.format( self.target_db)) raise DbfenError(20120076, result['msg'] + result['errmsg']) return tenant except Exception as ex: log.exception(ex) raise ex
def reset_tenant_database_password(self): # 暂时不用 default_new_pwd = 'Suj000123' sql_cmd = r"ALTER DATABASE {} SYSTEM USER PASSWORD {}".format( self.target_db, default_new_pwd) self.stop_tenant_database(self.target_db) exec_command = self.system_db_exec_command_str(sql_cmd) result = exec_cmd2(exec_command) if result['ret'] != 0: raise DbfenError(20120079, result['msg'] + result['errmsg'])
def obtain_full_backup_id_from_full_backup_file(self): full_backup_file = os.path.join(self.recv_file_dir, 'full_databackup_0_1') exec_command = "su - {} -c \"hdbbackupcheck -v {} | grep backupId\"|awk -F : \'{{print $2}}\'".format( self.hana_adm, full_backup_file) log.info('obtain_full_backup_id_from_full_backup_file exec_command:{}'. format(exec_command)) result = exec_cmd2(exec_command) if result['ret'] != 0: raise DbfenError(20120081, result['msg'] + result['errmsg']) return result['msg'].replace(' ', '')
def hana_check_version(self): # check hana database version hdb = '{}/HDB'.format(self.dir_instance) find_version_cmd = "su - {} -c '{} version'".format(self.hana_adm, hdb) find_version_result = exec_cmd2(find_version_cmd) if find_version_result['ret'] != 0: raise DbfenError( 20120075, find_version_result['msg'] + find_version_result['errmsg']) version = '' for i in find_version_result['msg'].split(os.linesep): if 'version' in i and 'HDB' not in i: version = i.split(':')[1].replace(' ', '') break return version
def check_hdb_daemon(self): # check hana hdb is normal running log.info('begin check_hdb_daemon!!!') sap_control = '{}/exe/sapcontrol'.format(self.dir_instance) get_processlist_cmd = "su - {} -c '{} -nr {} -function GetProcessList'".format( self.hana_adm, sap_control, self.instance) log.info('begin check_hdb_daemon:{}'.format(get_processlist_cmd)) get_processlist_result = exec_cmd2(get_processlist_cmd) for i in get_processlist_result['msg'].split(os.linesep): if 'hdbdaemon' in i: split_i = i.split(',') if split_i[3] == 'Stopped': return False else: return True else: return False
def hana_db_backup(self): try: config = getconf() try_times = 0 save_path = os.path.join(self.backup_dir, self.target_db) if self.backup_mode == config.DB_BACKUP_TYPE_FULL: self.full_backup_clear_old_log() backup_command = r"\"backup data for {} using file ('{}/full')\"".format( self.target_db, save_path) else: backup_command = r"\"backup data DIFFERENTIAL for {} using file ('{}/diff')\"".format( self.target_db, save_path) exec_command = self.system_db_exec_command_str(backup_command) exec_command_log = exec_command.replace( r'-p \"{}\"'.format(self.system_db_pwd), '-p ******') log.info('backup cmd is {}:'.format(exec_command_log)) while try_times < 3: log.debug('[TASK_ID:' + str(self.task_id) + '] hana_db_backup cmd execute. cmd:' + exec_command_log + '') result = exec_cmd2(exec_command) status = result['ret'] output = result['msg'].strip() log.debug('[TASK_ID:' + str(self.task_id) + '] hana_db_backup cmd finish! status:' + str(status) + ' output:' + output) try_times += 1 if status != 0: log.warn('[TASK_ID:' + str(self.task_id) + '] hana_db_backup cmd fail! dump_cmd:' + exec_command_log + 'status:' + str(status) + ' output:' + output) continue if self.backup_mode == config.DB_BACKUP_TYPE_FULL: self.gen_hana_fullback_info_file() return True if self.backup_mode == config.DB_BACKUP_TYPE_DIFF: if self.backup_redo_log(save_path): return True return False except Exception as ex: error() log.error('[HANA_DB_BACKUP]' + str(type(ex)) + ":" + str(ex)) return False
def get_hana_last_fullback_backup_id(self): sql_cmd = r'select BACKUP_ID from sys.M_BACKUP_CATALOG where ENTRY_TYPE_NAME=\'complete data backup\' and ' \ r'STATE_NAME = \'successful\' order by SYS_START_TIME desc limit 1' user, passpwd = (self.tenant_user, self.tenant_passwd) if self.target_db.upper() != 'SYSTEMDB' else \ (self.system_db_user, self.system_db_pwd) exec_command = r'su - {} -c "{} -n localhost -i {} -d {} -u {} -p \"{}\" -x {}"'.format( self.hana_adm, self.hdb_sql, self.instance, self.target_db, user, passpwd, sql_cmd) result = exec_cmd2(exec_command) exec_command_log = exec_command.replace( r'-p \"{}\"'.format(self.system_db_pwd), '-p ******') log.info('exec_command:{},{}'.format(result, exec_command_log)) if result['ret'] != 0: raise DbfenError(20120077, result['msg'] + result['errmsg']) else: msg_info = result['msg'].split(os.linesep) # 0 Indicates that a full backup of the database has not been done before last_fullback_backup_id = msg_info[1] if len(msg_info) == 2 else 0 return last_fullback_backup_id
def real_recovery_db(self): try: config = getconf() db_recovery_idx_file = os.path.join(self.backup_dir, config.client.db_idx_name) if self.transfer_method != 'tcp': mount_result = apply_source_and_mount( re_id=self.re_id, mount_path=self.backup_dir) self.mount_path = self.backup_dir if not mount_result: log.info('mount {} fail!!!'.format(self.recv_file_dir)) return False, 0 if not os.path.exists(db_recovery_idx_file): log.error( 'TASKID:{},db recovery index file not exist! recovery fail!' .format(self.task_id)) return False, 0 log.info('db_recovery_idx_file:{},recv_file_dir:{}'.format( db_recovery_idx_file, self.recv_file_dir)) sqlite_conn = get_sqlite_conn(db_recovery_idx_file) task_info = get_db_info_record(sqlite_conn) backup_type = int(task_info[2]) sqlite_conn.close() log.info('recovery backup_type is:{}'.format(backup_type)) if not self.check_source_db_target_db(): log.error('target_db and to_db wrong relationship!!!') return False, 0 hdb_setting = os.path.join(self.dir_instance, 'HDBSettings.sh') recover_sys = os.path.join(self.dir_instance, 'exe/python_support/recoverSys.py') is_create_db = False if self.to_db != 'systemdb': if self.to_db not in self.show_hana_databases(): self.create_tenant_db() is_create_db = True self.stop_tenant_database(self.to_db) if backup_type == config.DB_BACKUP_TYPE_FULL: # full recovery log.info( 'begin login hana recovery!!!,recv_file_dir:{}'.format( self.recv_file_dir)) file_path = os.path.join(self.recv_file_dir, 'full') if self.target_db == 'systemdb': recovery_command = r"\"RECOVER DATA ALL USING FILE ('{}') " \ r"CLEAR LOG\"".format(file_path) exec_command = 'su - {} -c "{} {} --command={}"'.format( self.hana_adm, hdb_setting, recover_sys, recovery_command) result = exec_cmd2(exec_command) else: recovery_command = r"\"RECOVER DATA for {} ALL USING FILE ('{}') CLEAR LOG\"".format( self.to_db, file_path) exec_command = self.system_db_exec_command_str( recovery_command) result = exec_cmd2(exec_command) if result['ret'] != 0: log.error('recovery {} fail!!!'.format(self.target_db)) self.check_customize_recovery(is_create_db) return False, 0 return True, 1 else: # diff recovery future_time = ( datetime.datetime.now() + datetime.timedelta(days=365)).strftime("%Y-%m-%d %H:%M:%S") full_backup_id = self.obtain_full_backup_id_from_full_backup_file( ) if self.target_db == 'systemdb': recovery_command = r"\"RECOVER DATABASE UNTIL TIMESTAMP '{future_time}' clear log USING CATALOG PATH " \ r"('{recv_file_path}') USING LOG PATH ('{recv_file_path}') USING DATA PATH " \ r"('{recv_file_path}') USING BACKUP_ID {full_backup_id} CHECK ACCESS USING FILE\"". \ format(future_time=future_time, full_backup_id=full_backup_id, recv_file_path=self.recv_file_dir) exec_command = 'su - {} -c "{} {} --command={}"'.format( self.hana_adm, hdb_setting, recover_sys, recovery_command) exec_command_log = exec_command else: recovery_command = r"\"RECOVER DATABASE for {new_db_name} UNTIL TIMESTAMP '{future_time}' clear log " \ r"USING CATALOG PATH ('{recv_file_path}') USING LOG PATH ('{recv_file_path}') " \ r"USING DATA PATH ('{recv_file_path}') USING BACKUP_ID {full_backup_id} CHECK " \ r"ACCESS USING FILE\"".format(new_db_name=self.to_db, future_time=future_time, full_backup_id=full_backup_id, recv_file_path=self.recv_file_dir) exec_command = self.system_db_exec_command_str( recovery_command) exec_command_log = exec_command.replace( r'-p \"{}\"'.format(self.system_db_pwd), '-p ******') log.info('exec_command is:{}'.format(exec_command_log)) result = exec_cmd2(exec_command) if result['ret'] != 0: log.error('recovery {} fail!!!'.format(self.target_db)) self.check_customize_recovery(is_create_db) return False, 0 return True, 1 except Exception as ex: log.exception(ex) raise ex
def stop_tenant_database(self, db_name): sql_cmd = r"ALTER SYSTEM STOP DATABASE {}".format(db_name) exec_command = self.system_db_exec_command_str(sql_cmd) result = exec_cmd2(exec_command) if result['ret'] != 0: raise DbfenError(20120078, result['msg'] + result['errmsg'])