Shore up the logic for migrations to allow multiple passes if needed

This commit is contained in:
Dane Everitt 2021-07-04 14:07:03 -07:00 committed by DaneEveritt
parent f8a25cb040
commit 37c52dd439
No known key found for this signature in database
GPG Key ID: EEA66103B3D71F53
2 changed files with 51 additions and 19 deletions

View File

@ -54,10 +54,12 @@ func (m *MigrateVHDCommand) Run(ctx context.Context) error {
s.Log().Debug("starting migration of server contents to virtual disk...")
v := vhd.New(s.DiskSpace(), filesystem.VirtualDiskPath(s.Id()), s.Filesystem().Path())
s.Log().WithField("disk_image", v.Path()).Info("creating virtual disk for server")
if err := v.Allocate(ctx); err != nil {
return errors.WithStackIf(err)
}
s.Log().Info("creating virtual filesystem for server")
if err := v.MakeFilesystem(ctx); err != nil {
// If the filesystem already exists no worries, just move on with our
// day here.
@ -67,19 +69,26 @@ func (m *MigrateVHDCommand) Run(ctx context.Context) error {
}
bak := strings.TrimSuffix(s.Filesystem().Path(), "/") + "_bak"
// Create a backup directory of the server files if one does not already exist
// at that location. If one does exists we'll just assume it is good to go and
// rely on it to provide the files we'll need.
if _, err := os.Lstat(bak); os.IsNotExist(err) {
if err := os.Rename(s.Filesystem().Path(), bak); err != nil {
return errors.Wrap(err, "failed to rename existing data directory for backup")
mounted, err := v.IsMounted(ctx)
if err != nil {
return err
} else if !mounted {
s.Log().WithField("backup_dir", bak).Debug("virtual disk is not yet mounted, creating backup directory")
// Create a backup directory of the server files if one does not already exist
// at that location. If one does exists we'll just assume it is good to go and
// rely on it to provide the files we'll need.
if _, err := os.Lstat(bak); os.IsNotExist(err) {
if err := os.Rename(s.Filesystem().Path(), bak); err != nil {
return errors.Wrap(err, "failed to rename existing data directory for backup")
}
} else if err != nil {
return errors.WithStack(err)
}
} else if err != nil {
return errors.WithStack(err)
}
if err := os.RemoveAll(s.Filesystem().Path()); err != nil && !os.IsNotExist(err) {
return errors.Wrap(err, "failed to remove base server files path")
if err := os.RemoveAll(s.Filesystem().Path()); err != nil && !os.IsNotExist(err) {
return errors.Wrap(err, "failed to remove base server files path")
}
} else {
s.Log().Warn("server appears to already have existing mount, not creating data backup")
}
// Attempt to mount the disk at the expected path now that we've created
@ -88,14 +97,29 @@ func (m *MigrateVHDCommand) Run(ctx context.Context) error {
return errors.WithStackIf(err)
}
// Copy over the files from the backup for this server.
cmd := exec.CommandContext(ctx, "mv", bak + "/*", s.Filesystem().Path())
s.Log().Debug(cmd.String())
if err := cmd.Run(); err != nil {
return errors.Wrap(err, "migrate: failed to move old server files into new direcotry")
// Copy over the files from the backup for this server but only
// if we have a backup directory currently.
_, err = os.Lstat(bak)
if err != nil {
if !os.IsNotExist(err) {
s.Log().WithField("error", err).Warn("failed to stat backup directory")
} else {
s.Log().Info("no backup data directory exists, not restoring files")
}
} else {
cmd := exec.CommandContext(ctx, "cp", "-r", bak+"/.", s.Filesystem().Path())
if err := cmd.Run(); err != nil {
return errors.Wrap(err, "migrate: failed to move old server files into new direcotry")
} else {
if err := os.RemoveAll(bak); err != nil {
s.Log().WithField("directory", bak).WithField("error", err).Warn("failed to remove backup directory")
}
}
}
if err := os.Remove(bak); err != nil {
s.Log().WithField("directory", bak).Warn("failed to remove backup directory")
s.Log().Info("updating server file ownership...")
if err := s.Filesystem().Chown("/"); err != nil {
s.Log().WithField("error", err).Warn("failed to update ownership of new server files")
}
s.Log().Info("finished migration to virtual disk...")

View File

@ -95,6 +95,14 @@ func WithCommander(c CommanderProvider) func(*Disk) {
}
}
func (d *Disk) Path() string {
return d.diskPath
}
func (d *Disk) MountPath() string {
return d.mountAt
}
// Exists reports if the disk exists on the system yet or not. This only verifies
// the presence of the disk image, not the validity of it. An error is returned
// if the path exists but the destination is not a file or is a symlink.