func()

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
}