mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2024-12-22 19:40:37 +00:00
Adding ability to override directory permissions for db backup (#8888)
* Adding ability to override directory permissions for db backup * adding new flag to usage.go * Backup now has its own directory handling method to reduce footprint of prospective change * removing unneeded test * fixing build error * switching to url param for override * stripping flag * adding in unit tests * fixing a test * minor changes for testing Co-authored-by: Raul Jordan <raul@prysmaticlabs.com>
This commit is contained in:
parent
fbed11b380
commit
ae7e2764e0
@ -25,8 +25,8 @@ func (e Exporter) ClearDB() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Backup -- passthrough.
|
// Backup -- passthrough.
|
||||||
func (e Exporter) Backup(ctx context.Context, outputDir string) error {
|
func (e Exporter) Backup(ctx context.Context, outputDir string, overridePermission bool) error {
|
||||||
return e.db.Backup(ctx, outputDir)
|
return e.db.Backup(ctx, outputDir, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Block -- passthrough.
|
// Block -- passthrough.
|
||||||
|
@ -16,7 +16,7 @@ const backupsDirectoryName = "backups"
|
|||||||
|
|
||||||
// Backup the database to the datadir backup directory.
|
// Backup the database to the datadir backup directory.
|
||||||
// Example for backup at slot 345: $DATADIR/backups/prysm_beacondb_at_slot_0000345.backup
|
// Example for backup at slot 345: $DATADIR/backups/prysm_beacondb_at_slot_0000345.backup
|
||||||
func (s *Store) Backup(ctx context.Context, outputDir string) error {
|
func (s *Store) Backup(ctx context.Context, outputDir string, permissionOverride bool) error {
|
||||||
ctx, span := trace.StartSpan(ctx, "BeaconDB.Backup")
|
ctx, span := trace.StartSpan(ctx, "BeaconDB.Backup")
|
||||||
defer span.End()
|
defer span.End()
|
||||||
|
|
||||||
@ -38,7 +38,7 @@ func (s *Store) Backup(ctx context.Context, outputDir string) error {
|
|||||||
return errors.New("no head block")
|
return errors.New("no head block")
|
||||||
}
|
}
|
||||||
// Ensure the backups directory exists.
|
// Ensure the backups directory exists.
|
||||||
if err := fileutil.MkdirAll(backupsDir); err != nil {
|
if err := fileutil.HandleBackupDir(backupsDir, permissionOverride); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
backupPath := path.Join(backupsDir, fmt.Sprintf("prysm_beacondb_at_slot_%07d.backup", head.Block().Slot()))
|
backupPath := path.Join(backupsDir, fmt.Sprintf("prysm_beacondb_at_slot_%07d.backup", head.Block().Slot()))
|
||||||
|
@ -29,7 +29,7 @@ func TestStore_Backup(t *testing.T) {
|
|||||||
require.NoError(t, db.SaveState(ctx, st, root))
|
require.NoError(t, db.SaveState(ctx, st, root))
|
||||||
require.NoError(t, db.SaveHeadBlockRoot(ctx, root))
|
require.NoError(t, db.SaveHeadBlockRoot(ctx, root))
|
||||||
|
|
||||||
require.NoError(t, db.Backup(ctx, ""))
|
require.NoError(t, db.Backup(ctx, "", false))
|
||||||
|
|
||||||
backupsPath := filepath.Join(db.databasePath, backupsDirectoryName)
|
backupsPath := filepath.Join(db.databasePath, backupsDirectoryName)
|
||||||
files, err := ioutil.ReadDir(backupsPath)
|
files, err := ioutil.ReadDir(backupsPath)
|
||||||
@ -71,7 +71,7 @@ func TestStore_BackupMultipleBuckets(t *testing.T) {
|
|||||||
require.NoError(t, db.SaveHeadBlockRoot(ctx, root))
|
require.NoError(t, db.SaveHeadBlockRoot(ctx, root))
|
||||||
}
|
}
|
||||||
|
|
||||||
require.NoError(t, db.Backup(ctx, ""))
|
require.NoError(t, db.Backup(ctx, "", false))
|
||||||
|
|
||||||
backupsPath := filepath.Join(db.databasePath, backupsDirectoryName)
|
backupsPath := filepath.Join(db.databasePath, backupsDirectoryName)
|
||||||
files, err := ioutil.ReadDir(backupsPath)
|
files, err := ioutil.ReadDir(backupsPath)
|
||||||
|
@ -10,17 +10,19 @@ import (
|
|||||||
|
|
||||||
// BackupExporter defines a backup exporter methods.
|
// BackupExporter defines a backup exporter methods.
|
||||||
type BackupExporter interface {
|
type BackupExporter interface {
|
||||||
Backup(ctx context.Context, outputPath string) error
|
Backup(ctx context.Context, outputPath string, permissionOverride bool) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// BackupHandler for accepting requests to initiate a new database backup.
|
// BackupHandler for accepting requests to initiate a new database backup.
|
||||||
func BackupHandler(bk BackupExporter, outputDir string) func(http.ResponseWriter, *http.Request) {
|
func BackupHandler(bk BackupExporter, outputDir string) func(http.ResponseWriter, *http.Request) {
|
||||||
log := logrus.WithField("prefix", "db")
|
log := logrus.WithField("prefix", "db")
|
||||||
|
|
||||||
return func(w http.ResponseWriter, _ *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
log.Debug("Creating database backup from HTTP webhook")
|
log.Debug("Creating database backup from HTTP webhook")
|
||||||
|
|
||||||
if err := bk.Backup(context.Background(), outputDir); err != nil {
|
_, permissionOverride := r.URL.Query()["permissionOverride"]
|
||||||
|
|
||||||
|
if err := bk.Backup(context.Background(), outputDir, permissionOverride); err != nil {
|
||||||
log.WithError(err).Error("Failed to create backup")
|
log.WithError(err).Error("Failed to create backup")
|
||||||
w.WriteHeader(http.StatusInternalServerError)
|
w.WriteHeader(http.StatusInternalServerError)
|
||||||
return
|
return
|
||||||
|
@ -32,6 +32,34 @@ func ExpandPath(p string) (string, error) {
|
|||||||
return filepath.Abs(path.Clean(os.ExpandEnv(p)))
|
return filepath.Abs(path.Clean(os.ExpandEnv(p)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HandleBackupDir takes an input directory path and either alters its permissions to be usable if it already exists, creates it if not
|
||||||
|
func HandleBackupDir(dirPath string, permissionOverride bool) error {
|
||||||
|
expanded, err := ExpandPath(dirPath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
exists, err := HasDir(expanded)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if exists {
|
||||||
|
info, err := os.Stat(expanded)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if info.Mode().Perm() != params.BeaconIoConfig().ReadWriteExecutePermissions {
|
||||||
|
if permissionOverride {
|
||||||
|
if err := os.Chmod(expanded, params.BeaconIoConfig().ReadWriteExecutePermissions); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return errors.New("dir already exists without proper 0700 permissions")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return os.MkdirAll(expanded, params.BeaconIoConfig().ReadWriteExecutePermissions)
|
||||||
|
}
|
||||||
|
|
||||||
// MkdirAll takes in a path, expands it if necessary, and looks through the
|
// MkdirAll takes in a path, expands it if necessary, and looks through the
|
||||||
// permissions of every directory along the path, ensuring we are not attempting
|
// permissions of every directory along the path, ensuring we are not attempting
|
||||||
// to overwrite any existing permissions. Finally, creates the directory accordingly
|
// to overwrite any existing permissions. Finally, creates the directory accordingly
|
||||||
|
@ -56,13 +56,48 @@ func TestMkdirAll_AlreadyExists_WrongPermissions(t *testing.T) {
|
|||||||
assert.ErrorContains(t, "already exists without proper 0700 permissions", err)
|
assert.ErrorContains(t, "already exists without proper 0700 permissions", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestMkdirAll_AlreadyExists_OK(t *testing.T) {
|
func TestMkdirAll_AlreadyExists_Override(t *testing.T) {
|
||||||
dirName := t.TempDir() + "somedir"
|
dirName := t.TempDir() + "somedir"
|
||||||
err := os.MkdirAll(dirName, params.BeaconIoConfig().ReadWriteExecutePermissions)
|
err := os.MkdirAll(dirName, params.BeaconIoConfig().ReadWriteExecutePermissions)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.NoError(t, fileutil.MkdirAll(dirName))
|
assert.NoError(t, fileutil.MkdirAll(dirName))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestHandleBackupDir_AlreadyExists_Override(t *testing.T) {
|
||||||
|
dirName := t.TempDir() + "somedir"
|
||||||
|
err := os.MkdirAll(dirName, os.ModePerm)
|
||||||
|
require.NoError(t, err)
|
||||||
|
info, err := os.Stat(dirName)
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Equal(t, "drwxr-xr-x", info.Mode().String())
|
||||||
|
assert.NoError(t, fileutil.HandleBackupDir(dirName, true))
|
||||||
|
info, err = os.Stat(dirName)
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Equal(t, "drwx------", info.Mode().String())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestHandleBackupDir_AlreadyExists_No_Override(t *testing.T) {
|
||||||
|
dirName := t.TempDir() + "somedir"
|
||||||
|
err := os.MkdirAll(dirName, os.ModePerm)
|
||||||
|
require.NoError(t, err)
|
||||||
|
info, err := os.Stat(dirName)
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Equal(t, "drwxr-xr-x", info.Mode().String())
|
||||||
|
err = fileutil.HandleBackupDir(dirName, false)
|
||||||
|
assert.ErrorContains(t, "dir already exists without proper 0700 permissions", err)
|
||||||
|
info, err = os.Stat(dirName)
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Equal(t, "drwxr-xr-x", info.Mode().String())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestHandleBackupDir_NewDir(t *testing.T) {
|
||||||
|
dirName := t.TempDir() + "somedir"
|
||||||
|
require.NoError(t, fileutil.HandleBackupDir(dirName, true))
|
||||||
|
info, err := os.Stat(dirName)
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Equal(t, "drwx------", info.Mode().String())
|
||||||
|
}
|
||||||
|
|
||||||
func TestMkdirAll_OK(t *testing.T) {
|
func TestMkdirAll_OK(t *testing.T) {
|
||||||
dirName := t.TempDir() + "somedir"
|
dirName := t.TempDir() + "somedir"
|
||||||
err := fileutil.MkdirAll(dirName)
|
err := fileutil.MkdirAll(dirName)
|
||||||
|
@ -16,7 +16,7 @@ const backupsDirectoryName = "backups"
|
|||||||
|
|
||||||
// Backup the database to the datadir backup directory.
|
// Backup the database to the datadir backup directory.
|
||||||
// Example for backup: $DATADIR/backups/prysm_slasherdb_10291092.backup
|
// Example for backup: $DATADIR/backups/prysm_slasherdb_10291092.backup
|
||||||
func (s *Store) Backup(ctx context.Context, outputDir string) error {
|
func (s *Store) Backup(ctx context.Context, outputDir string, overridePermission bool) error {
|
||||||
ctx, span := trace.StartSpan(ctx, "SlasherDB.Backup")
|
ctx, span := trace.StartSpan(ctx, "SlasherDB.Backup")
|
||||||
defer span.End()
|
defer span.End()
|
||||||
|
|
||||||
@ -31,7 +31,7 @@ func (s *Store) Backup(ctx context.Context, outputDir string) error {
|
|||||||
backupsDir = path.Join(s.databasePath, backupsDirectoryName)
|
backupsDir = path.Join(s.databasePath, backupsDirectoryName)
|
||||||
}
|
}
|
||||||
// Ensure the backups directory exists.
|
// Ensure the backups directory exists.
|
||||||
if err := fileutil.MkdirAll(backupsDir); err != nil {
|
if err := fileutil.HandleBackupDir(backupsDir, overridePermission); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
backupPath := path.Join(backupsDir, fmt.Sprintf("prysm_slasherdb_%d.backup", time.Now().Unix()))
|
backupPath := path.Join(backupsDir, fmt.Sprintf("prysm_slasherdb_%d.backup", time.Now().Unix()))
|
||||||
|
@ -16,7 +16,7 @@ func TestStore_Backup(t *testing.T) {
|
|||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
pubKey := []byte("hello")
|
pubKey := []byte("hello")
|
||||||
require.NoError(t, db.SavePubKey(ctx, types.ValidatorIndex(1), pubKey))
|
require.NoError(t, db.SavePubKey(ctx, types.ValidatorIndex(1), pubKey))
|
||||||
require.NoError(t, db.Backup(ctx, ""))
|
require.NoError(t, db.Backup(ctx, "", false))
|
||||||
|
|
||||||
backupsPath := filepath.Join(db.databasePath, backupsDirectoryName)
|
backupsPath := filepath.Join(db.databasePath, backupsDirectoryName)
|
||||||
files, err := ioutil.ReadDir(backupsPath)
|
files, err := ioutil.ReadDir(backupsPath)
|
||||||
|
@ -16,7 +16,7 @@ const backupsDirectoryName = "backups"
|
|||||||
|
|
||||||
// Backup the database to the datadir backup directory.
|
// Backup the database to the datadir backup directory.
|
||||||
// Example for backup: $DATADIR/backups/prysm_validatordb_1029019.backup
|
// Example for backup: $DATADIR/backups/prysm_validatordb_1029019.backup
|
||||||
func (s *Store) Backup(ctx context.Context, outputDir string) error {
|
func (s *Store) Backup(ctx context.Context, outputDir string, permissionOverride bool) error {
|
||||||
ctx, span := trace.StartSpan(ctx, "ValidatorDB.Backup")
|
ctx, span := trace.StartSpan(ctx, "ValidatorDB.Backup")
|
||||||
defer span.End()
|
defer span.End()
|
||||||
|
|
||||||
@ -31,7 +31,7 @@ func (s *Store) Backup(ctx context.Context, outputDir string) error {
|
|||||||
backupsDir = path.Join(s.databasePath, backupsDirectoryName)
|
backupsDir = path.Join(s.databasePath, backupsDirectoryName)
|
||||||
}
|
}
|
||||||
// Ensure the backups directory exists.
|
// Ensure the backups directory exists.
|
||||||
if err := fileutil.MkdirAll(backupsDir); err != nil {
|
if err := fileutil.HandleBackupDir(backupsDir, permissionOverride); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
backupPath := path.Join(backupsDir, fmt.Sprintf("prysm_validatordb_%d.backup", time.Now().Unix()))
|
backupPath := path.Join(backupsDir, fmt.Sprintf("prysm_validatordb_%d.backup", time.Now().Unix()))
|
||||||
|
@ -15,7 +15,7 @@ func TestStore_Backup(t *testing.T) {
|
|||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
root := [32]byte{1}
|
root := [32]byte{1}
|
||||||
require.NoError(t, db.SaveGenesisValidatorsRoot(ctx, root[:]))
|
require.NoError(t, db.SaveGenesisValidatorsRoot(ctx, root[:]))
|
||||||
require.NoError(t, db.Backup(ctx, ""))
|
require.NoError(t, db.Backup(ctx, "", true))
|
||||||
|
|
||||||
backupsPath := filepath.Join(db.databasePath, backupsDirectoryName)
|
backupsPath := filepath.Join(db.databasePath, backupsDirectoryName)
|
||||||
files, err := ioutil.ReadDir(backupsPath)
|
files, err := ioutil.ReadDir(backupsPath)
|
||||||
|
Loading…
Reference in New Issue
Block a user