in oracle/pkg/database/dbdaemonproxy/dbdaemon_proxy.go [226:294]
func (s *Server) BounceDatabase(ctx context.Context, req *dbdpb.BounceDatabaseRequest) (*dbdpb.BounceDatabaseResponse, error) {
klog.InfoS("dbdaemon/BounceDatabase", "req", req, "serverObj", s)
reqDatabaseName := req.GetDatabaseName()
var ls dbdpb.DatabaseState
var operation string
// Allowed commands: startup [nomount|mount|open|force_nomount] or shutdown [immediate|transactional|abort].
validStartupOptions := map[string]bool{"nomount": true, "mount": true, "open": true, "force_nomount": true}
// validShutdownOptions keys should match shutdownEnumMap below to prevent nil.
validShutdownOptions := map[string]bool{"immediate": true, "transactional": true, "abort": true}
switch req.Operation {
case dbdpb.BounceDatabaseRequest_STARTUP:
ls = dbdpb.DatabaseState_READY
if req.Option != "" && !validStartupOptions[req.Option] {
e := []string{fmt.Sprintf("illegal option %q requested for operation %q", req.Option, req.Operation)}
return &dbdpb.BounceDatabaseResponse{
DatabaseState: dbdpb.DatabaseState_DATABASE_STATE_ERROR,
ErrorMsg: e,
}, nil
}
operation = "startup"
case dbdpb.BounceDatabaseRequest_SHUTDOWN:
ls = dbdpb.DatabaseState_STOPPED
if req.Option != "" && !validShutdownOptions[req.Option] {
e := []string{fmt.Sprintf("illegal option %q requested for operation %q", req.Option, req.Operation)}
return &dbdpb.BounceDatabaseResponse{
DatabaseState: dbdpb.DatabaseState_DATABASE_STATE_ERROR,
ErrorMsg: e,
}, nil
}
operation = "shutdown"
default:
return nil, fmt.Errorf("illegal operation requested: %q", req.Operation)
}
// Add lock to protect server state "databaseSid" and os env variable "ORACLE_SID".
// When bouncing the DB, DB is not ready to run cmds or SQLs, it seems to be ok to block all other APIs for now.
s.databaseSid.Lock()
defer s.databaseSid.Unlock()
// Sets env to bounce a database, needed for start and shutdown.
os.Setenv("ORACLE_SID", reqDatabaseName)
var err error
shutdownEnumMap := map[string]godror.ShutdownMode{
"immediate": godror.ShutdownImmediate,
"transactional": godror.ShutdownTransactional,
"abort": godror.ShutdownAbort,
}
if operation == "shutdown" {
// shutdownEnumMap keys should match validShutdownOptions above to prevent nil.
err = s.shutdownDatabase(ctx, shutdownEnumMap[req.Option])
if err != nil && strings.Contains(err.Error(), "ORA-01034:") {
klog.InfoS("dbdaemon/shutdownDatabase: database is already down", "err", err)
err = nil
}
} else { // startup
switch req.Option {
case "force_nomount":
err = s.startupDatabase(ctx, godror.StartupForce, "nomount")
default:
err = s.startupDatabase(ctx, godror.StartupDefault, req.Option)
}
}
return &dbdpb.BounceDatabaseResponse{
DatabaseState: ls,
ErrorMsg: nil,
}, err
}