Esempio n. 1
0
 def sync_data_to_slaves(self, context):
     """Trigger an archive log switch and flush transactions down to the
     slaves.
     """
     LOG.debug("sync_data_to_slaves - switching log file")
     with ora_service.LocalOracleClient(self.ORA_CONF.db_name) as client:
         client.execute("ALTER SYSTEM SWITCH LOGFILE")
Esempio n. 2
0
    def _complete_new_slave_setup(self, master_host, dbs):
        ora_conf = ora_service.OracleConfig()
        sys_password = ora_conf.sys_password
        with ora_service.OracleConnection(
                self.ORA_CONF.db_name,
                mode=(cx_Oracle.SYSDBA | cx_Oracle.PRELIM_AUTH)) as conn:
            conn.startup()
        db_list = [db['db_unique_name'] for db in dbs]
        fal_server_list = ",".join("'%s'" % db for db in db_list)
        log_archive_dest = []
        dest_index = 1
        for db in db_list:
            if db != self.ORA_CONF.db_unique_name:
                dest_index += 1
                log_archive_dest.append("SET LOG_ARCHIVE_DEST_%(dest_index)s="
                                        "'SERVICE=%(db)s ASYNC VALID_FOR="
                                        "(ONLINE_LOGFILES,PRIMARY_ROLE) "
                                        "DB_UNIQUE_NAME=%(db)s'" % {
                                            'dest_index': dest_index,
                                            'db': db
                                        })
        # The RMAN DUPLICATE command requires connecting to target with the
        # 'sys' user. If we use any other user, such as 'os_admin', even with
        # the sysdba and sysoper roles assigned, it will still fail with:
        # ORA-01017: invalid username/password; logon denied
        cmd = ("""\"\
rman target %(admin_user)s/%(admin_pswd)s@%(host)s/%(db_name)s \
auxiliary %(admin_user)s/%(admin_pswd)s@%(db_unique_name)s <<EOF
run {
DUPLICATE TARGET DATABASE FOR STANDBY
FROM ACTIVE DATABASE DORECOVER SPFILE
SET db_unique_name='%(db_unique_name)s' COMMENT 'Is standby'
%(log_archive_dest)s
SET FAL_SERVER=%(fal_server_list)s COMMENT 'Is primary'
NOFILENAMECHECK;
}
EXIT;
EOF\"
""")
        duplicate_cmd = (cmd % {
            'admin_user': '******',
            'admin_pswd': sys_password,
            'host': master_host,
            'db_name': self.ORA_CONF.db_name,
            'db_unique_name': self.ORA_CONF.db_unique_name,
            'fal_server_list': fal_server_list,
            'log_archive_dest': "\n".join(log_archive_dest)
        })
        utils.execute_with_timeout("su - oracle -c " + duplicate_cmd,
                                   run_as_root=True,
                                   root_helper='sudo',
                                   timeout=CONF.restore_usage_timeout,
                                   shell=True,
                                   log_output_on_error=True)
        with ora_service.LocalOracleClient(self.ORA_CONF.db_name) as client:
            client.execute("ALTER SYSTEM SET REDO_TRANSPORT_USER = %s "
                           "SCOPE = BOTH" % ora_service.ADMIN_USER_NAME)
            client.execute("ALTER DATABASE OPEN READ ONLY")
            client.execute("ALTER DATABASE RECOVER MANAGED STANDBY DATABASE "
                           "USING CURRENT LOGFILE DISCONNECT FROM SESSION")
Esempio n. 3
0
 def _log_apply_is_running(self):
     with ora_service.LocalOracleClient(
             self._get_config().db_name) as client:
         client.execute("select count(*) from v$managed_standby "
                        "where process like 'MRP%'")
         row = client.fetchone()
         return int(row[0]) > 0
Esempio n. 4
0
    def get_master_ref(self, service, snapshot_info):
        """Capture information from a master node"""
        pfile = '/tmp/init%s_stby.ora' % self._get_config().db_name
        pwfile = ('%(ora_home)s/dbs/orapw%(db_name)s' % {
            'ora_home': CONF.get(MANAGER).oracle_home,
            'db_name': self._get_config().db_name
        })
        ctlfile = '/tmp/%s_stby.ctl' % self._get_config().db_name
        oratabfile = '/etc/oratab'
        oracnffile = CONF.get(MANAGER).conf_file
        datafile = '/tmp/oradata.tar.gz'

        def _cleanup_tmp_files():
            operating_system.remove(ctlfile, force=True, as_root=True)
            operating_system.remove(pfile, force=True, as_root=True)
            operating_system.remove(datafile, force=True, as_root=True)

        _cleanup_tmp_files()

        with ora_service.LocalOracleClient(self._get_config().db_name,
                                           service=True) as client:
            client.execute("ALTER DATABASE CREATE STANDBY CONTROLFILE AS "
                           "'%s'" % ctlfile)
            ora_service.OracleAdmin().create_parameter_file(target=pfile,
                                                            client=client)
            q = sql_query.Query()
            q.columns = ["value"]
            q.tables = ["v$parameter"]
            q.where = ["name = 'fal_server'"]
            client.execute(str(q))
            row = client.fetchone()
            db_list = []
            if row is not None and row[0] is not None:
                db_list = str(row[0]).split(",")
            db_list.insert(0, self._get_config().db_name)

        # Create a tar file containing files needed for slave creation
        utils.execute_with_timeout('tar',
                                   '-Pczvf',
                                   datafile,
                                   ctlfile,
                                   pwfile,
                                   pfile,
                                   oratabfile,
                                   oracnffile,
                                   run_as_root=True,
                                   root_helper='sudo')
        oradata_encoded = operating_system.read_file(
            datafile,
            codec=stream_codecs.Base64Codec(),
            as_root=True,
            decode=False)
        _cleanup_tmp_files()
        master_ref = {
            'host': netutils.get_my_ipv4(),
            'db_name': self._get_config().db_name,
            'db_list': db_list,
            'oradata': oradata_encoded,
        }
        return master_ref
Esempio n. 5
0
 def detach_slave(self, service, for_failover=False):
     """Detach this slave by disabling the log apply process"""
     if not for_failover:
         LOG.debug('detach_slave - Disabling the log apply process.')
         with ora_service.LocalOracleClient(
                 self.ORA_CONF.db_name) as client:
             client.execute("ALTER DATABASE RECOVER MANAGED STANDBY "
                            "DATABASE CANCEL")
Esempio n. 6
0
 def enable_as_master(self, service, master_config):
     # Turn this slave node into master when failing over
     # (eject-replica-source)
     if self._log_apply_is_running():
         with ora_service.LocalOracleClient(
                 self._get_config().db_name) as client:
             client.execute("ALTER DATABASE RECOVER MANAGED STANDBY "
                            "DATABASE FINISH")
             client.execute("ALTER DATABASE ACTIVATE STANDBY DATABASE")
             client.execute("ALTER DATABASE OPEN")
             client.execute("ALTER SYSTEM SWITCH LOGFILE")
Esempio n. 7
0
 def complete_slave_setup(self, context, master_detail, slave_detail):
     """Finalize slave setup and start the slave Oracle processes."""
     dbs = [master_detail]
     dbs.extend(slave_detail)
     is_new_repl_node = self._is_new_replication_node()
     self._create_tns_file(dbs)
     if is_new_repl_node:
         self._complete_new_slave_setup(master_detail['host'], dbs)
     else:
         with ora_service.LocalOracleClient(self.ORA_CONF.db_name,
                                            service=True) as ora_client:
             self._update_dynamic_params(ora_client, dbs)
Esempio n. 8
0
 def estimate_backup_size(self):
     """Estimate the backup size. The estimation is 1/3 the total size
     of datafiles, which is a conservative figure derived from the
     Oracle RMAN backupset compression ratio."""
     with oracle_service.LocalOracleClient(self.db_name,
                                           service=True) as client:
         q = sql_query.Query()
         q.columns = ["sum(bytes)"]
         q.tables = ["dba_data_files"]
         client.execute(str(q))
         result = client.fetchall()
         return result[0][0] / 3
Esempio n. 9
0
 def complete_master_setup(self, context, slave_detail):
     """Finalize master setup and start the master Oracle processes."""
     dbs = [self.get_replication_detail(None)]
     dbs.extend(slave_detail)
     with ora_service.LocalOracleClient(self.ORA_CONF.db_name,
                                        service=True) as ora_client:
         if self._is_new_replication_node():
             self._create_lsnr_file()
             self._create_standby_log_files(ora_client)
             self._create_static_params(ora_client)
         self._create_tns_file(dbs)
         self._update_dynamic_params(ora_client, dbs)
         ora_client.execute("ALTER SYSTEM SWITCH LOGFILE")
Esempio n. 10
0
 def detach_slave(self, service, for_failover=False):
     """Detach this slave by disabling the log apply process,
     setting it to read/write.
     """
     if not for_failover:
         with ora_service.LocalOracleClient(
                 self._get_config().db_name) as client:
             client.execute("ALTER DATABASE RECOVER MANAGED STANDBY "
                            "DATABASE CANCEL")
             client.execute("ALTER DATABASE ACTIVATE STANDBY DATABASE")
             client.execute("ALTER DATABASE OPEN")
             for index in range(2, 31):
                 client.execute("ALTER SYSTEM SET LOG_ARCHIVE_DEST_%s=''" %
                                index)
             client.execute("ALTER SYSTEM SET LOG_ARCHIVE_CONFIG=''")
             client.execute("ALTER SYSTEM SET FAL_SERVER=''")
Esempio n. 11
0
    def enable_as_master(self, service, master_config, for_failover=False):
        """Turn a running slave node into a master node"""
        if for_failover:
            # Turn this slave node into master when failing over
            # (eject-replica-source)
            with ora_service.LocalOracleClient(
                    self.ORA_CONF.db_name) as client:
                client.execute("ALTER DATABASE RECOVER MANAGED STANDBY "
                               "DATABASE FINISH")
                client.execute("ALTER DATABASE ACTIVATE STANDBY DATABASE")
                client.execute("ALTER DATABASE OPEN")
                client.execute("ALTER SYSTEM SWITCH LOGFILE")
        else:
            # Turn this slave node into master when switching over
            # (promote-to-replica-source)
            if self._log_apply_is_running():
                # Switchover from slave to master only if the current
                # instance is already a slave
                with ora_service.OracleConnection(
                        self.ORA_CONF.db_name) as conn:
                    cursor = conn.cursor()
                    cursor.execute("ALTER DATABASE COMMIT TO SWITCHOVER TO "
                                   "PRIMARY WITH SESSION SHUTDOWN")
                    conn.shutdown(mode=cx_Oracle.DBSHUTDOWN_IMMEDIATE)
                    cursor.execute("alter database dismount")
                    conn.shutdown(mode=cx_Oracle.DBSHUTDOWN_FINAL)

                # The DB has been shut down at this point, need to establish a
                # new connection in PRELIM_AUTH mode in order to start it up.
                with ora_service.OracleConnection(
                        self.ORA_CONF.db_name,
                        mode=(cx_Oracle.SYSDBA
                              | cx_Oracle.PRELIM_AUTH)) as conn:
                    conn.startup()

                # DB is now up but not open, re-connect to the DB in SYSDBA
                # mode to open it.
                with ora_service.OracleConnection(
                        self.ORA_CONF.db_name) as conn:
                    cursor = conn.cursor()
                    cursor.execute("alter database mount")
                    cursor.execute("alter database open")
                    cursor.execute("ALTER SYSTEM SWITCH LOGFILE")
Esempio n. 12
0
 def enable_as_slave(self, service, snapshot, slave_config):
     """Turn this node into slave by enabling the log apply process."""
     with ora_service.LocalOracleClient(self.ORA_CONF.db_name) as client:
         client.execute("select count(*) from v$managed_standby "
                        "where process like 'MRP%'")
         row = client.fetchone()
         if int(row[0]) == 0:
             # Only attempt to enable log apply if it is not already
             # running
             LOG.debug('Slave processes does not exist in '
                       'v$managed_standy, switching on LOG APPLY')
             client.execute("ALTER DATABASE RECOVER MANAGED STANDBY "
                            "DATABASE USING CURRENT LOGFILE DISCONNECT "
                            "FROM SESSION")
     utils.execute_with_timeout("sudo",
                                "su",
                                "-",
                                "oracle",
                                "-c",
                                "lsnrctl reload",
                                timeout=CONF.usage_timeout)