func CreateDatabase()

in oracle/controllers/config_agent_helpers.go [231:352]


func CreateDatabase(ctx context.Context, r client.Reader, dbClientFactory DatabaseClientFactory, namespace, instName string, req CreateDatabaseRequest) (string, error) {
	klog.InfoS("config_agent_helpers/CreateDatabase", "namespace", namespace, "instName", instName, "cdbName", req.CdbName, "pdbName", req.Name)

	var pwd string
	var err error

	toUpdatePlaintextAdminPwd := req.Password != "" && req.Password != req.LastPassword
	if toUpdatePlaintextAdminPwd {
		pwd = req.Password
	}

	toUpdateGsmAdminPwd := req.AdminPasswordGsmSecretRef != nil && (req.AdminPasswordGsmSecretRef.Version != req.AdminPasswordGsmSecretRef.LastVersion || req.AdminPasswordGsmSecretRef.Version == "latest")
	if toUpdateGsmAdminPwd {
		pwd, err = AccessSecretVersionFunc(ctx, fmt.Sprintf(gsmSecretStr, req.AdminPasswordGsmSecretRef.ProjectId, req.AdminPasswordGsmSecretRef.SecretId, req.AdminPasswordGsmSecretRef.Version))
		if err != nil {
			return "", fmt.Errorf("config_agent_helpers/CreateDatabase: failed to retrieve secret from Google Secret Manager: %v", err)
		}
	}

	p, err := buildPDB(req.CdbName, req.Name, pwd, version, consts.ListenerNames, true)
	if err != nil {
		return "", err
	}

	dbClient, closeConn, err := dbClientFactory.New(ctx, r, namespace, instName)
	if err != nil {
		return "", fmt.Errorf("config_agent_helpers/CreateDatabase: failed to create database daemon dbdClient: %v", err)
	}
	defer closeConn()
	klog.InfoS("config_agent_helpers/CreateDatabase: checking CDB state")

	_, err = dbClient.CheckDatabaseState(ctx, &dbdpb.CheckDatabaseStateRequest{IsCdb: true, DatabaseName: req.CdbName, DbDomain: req.DbDomain})
	if err != nil {
		return "", fmt.Errorf("config_agent_helpers/CreateDatabase: failed to check a CDB state: %v", err)
	}
	klog.InfoS("config_agent_helpers/CreateDatabase: pre-flight check#1: CDB is up and running")

	pdbCheckCmd := []string{fmt.Sprintf("select open_mode, restricted from v$pdbs where name = '%s'", sql.StringParam(p.pluggableDatabaseName))}
	resp, err := dbClient.RunSQLPlusFormatted(ctx, &dbdpb.RunSQLPlusCMDRequest{Commands: pdbCheckCmd, Suppress: false})
	if err != nil {
		return "", fmt.Errorf("config_agent_helpers/CreateDatabase: failed to check if a PDB called %s already exists: %v", p.pluggableDatabaseName, err)
	}
	klog.InfoS("config_agent_helpers/CreateDatabase pre-flight check#2", "pdb", p.pluggableDatabaseName, "resp", resp)

	if resp != nil && resp.Msg != nil {
		if toUpdateGsmAdminPwd || toUpdatePlaintextAdminPwd {
			sqls := append([]string{sql.QuerySetSessionContainer(p.pluggableDatabaseName)}, []string{sql.QueryAlterUser(pdbAdmin, pwd)}...)
			if _, err := dbClient.RunSQLPlus(ctx, &dbdpb.RunSQLPlusCMDRequest{
				Commands: sqls,
				Suppress: true,
			}); err != nil {
				return "", fmt.Errorf("failed to alter user %s: %v", pdbAdmin, err)
			}
			klog.InfoS("config_agent_helpers/CreateDatabase update pdb admin user succeeded", "user", pdbAdmin)
			return "AdminUserSyncCompleted", nil
		}
		klog.InfoS("config_agent_helpers/CreateDatabase pre-flight check#2", "pdb", p.pluggableDatabaseName, "respMsg", resp.Msg)
		return "AlreadyExists", nil
	}
	klog.InfoS("config_agent_helpers/CreateDatabase pre-flight check#2: pdb doesn't exist, proceeding to create", "pdb", p.pluggableDatabaseName)

	cdbDir := fmt.Sprintf(consts.DataDir, consts.DataMount, req.CdbName)
	pdbDir := filepath.Join(cdbDir, strings.ToUpper(req.Name))
	toCreate := []string{
		fmt.Sprintf("%s/data", pdbDir),
		fmt.Sprintf("%s/%s", pdbDir, consts.DpdumpDir.Linux),
		fmt.Sprintf("%s/rman", consts.OracleBase),
	}

	var dirs []*dbdpb.CreateDirsRequest_DirInfo
	for _, d := range toCreate {
		dirs = append(dirs, &dbdpb.CreateDirsRequest_DirInfo{
			Path: d,
			Perm: 0760,
		})
	}

	if _, err := dbClient.CreateDirs(ctx, &dbdpb.CreateDirsRequest{Dirs: dirs}); err != nil {
		return "", fmt.Errorf("failed to create PDB dirs: %v", err)
	}

	pdbCmd := []string{sql.QueryCreatePDB(p.pluggableDatabaseName, pdbAdmin, p.pluggableAdminPasswd, p.dataFilesDir, p.defaultTablespace, p.defaultTablespaceDatafile, p.fileConvertFrom, p.fileConvertTo)}
	_, err = dbClient.RunSQLPlus(ctx, &dbdpb.RunSQLPlusCMDRequest{Commands: pdbCmd, Suppress: false})
	if err != nil {
		return "", fmt.Errorf("config_agent_helpers/CreateDatabase: failed to create a PDB %s: %v", p.pluggableDatabaseName, err)
	}
	klog.InfoS("config_agent_helpers/CreateDatabase create a PDB Done", "pdb", p.pluggableDatabaseName)

	pdbOpen := []string{
		fmt.Sprintf("alter pluggable database %s open read write", sql.MustBeObjectName(p.pluggableDatabaseName)),
		fmt.Sprintf("alter pluggable database %s save state", sql.MustBeObjectName(p.pluggableDatabaseName)),
	}
	_, err = dbClient.RunSQLPlus(ctx, &dbdpb.RunSQLPlusCMDRequest{Commands: pdbOpen, Suppress: false})
	if err != nil {
		return "", fmt.Errorf("config_agent_helpers/CreatePDBDatabase: PDB %s open failed: %v", p.pluggableDatabaseName, err)
	}
	klog.InfoS("config_agent_helpers/CreateDatabase PDB open", "pdb", p.pluggableDatabaseName)

	_, err = dbClient.RunSQLPlus(ctx, &dbdpb.RunSQLPlusCMDRequest{Commands: []string{
		sql.QuerySetSessionContainer(p.pluggableDatabaseName),
		sql.QueryGrantPrivileges("create session, dba", pdbAdmin),
		sql.QueryGrantPrivileges("create session, resource, datapump_imp_full_database, datapump_exp_full_database, unlimited tablespace", consts.PDBLoaderUser),
	}, Suppress: false})
	if err != nil {
		// Until we have a proper error handling, just log an error here.
		klog.ErrorS(err, "CreateDatabase: failed to create a PDB_ADMIN user and/or PDB loader user")
	}
	klog.InfoS("config_agent_helpers/CreateDatabase: created PDB_ADMIN and PDB Loader users")

	// Separate out the directory treatment for the ease of troubleshooting.
	_, err = dbClient.RunSQLPlus(ctx, &dbdpb.RunSQLPlusCMDRequest{Commands: []string{
		sql.QuerySetSessionContainer(p.pluggableDatabaseName),
		sql.QueryCreateDir(consts.DpdumpDir.Oracle, filepath.Join(p.pathPrefix, consts.DpdumpDir.Linux)),
		sql.QueryGrantPrivileges(fmt.Sprintf("read,write on directory %s", consts.DpdumpDir.Oracle), consts.PDBLoaderUser),
	}, Suppress: false})
	if err != nil {
		klog.ErrorS(err, "CreateDatabase: failed to create a Data Pump directory", "datapumpDir", consts.DpdumpDir)
	}
	klog.InfoS("config_agent_helpers/CreateDatabase: DONE", "pdb", p.pluggableDatabaseName)

	return "Ready", nil
}