WIP migration on running jail with minimized downtime
This commit is contained in:
parent
542d2f96f6
commit
0bf825ee5a
@ -3,10 +3,10 @@ package cmd
|
|||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
|
||||||
"bufio"
|
"bufio"
|
||||||
/* "errors"
|
"errors"
|
||||||
"regexp"
|
"strings"
|
||||||
|
/* "regexp"
|
||||||
"time"
|
"time"
|
||||||
*/
|
*/
|
||||||
)
|
)
|
||||||
@ -45,7 +45,7 @@ func MigrateJail(args []string) {
|
|||||||
|
|
||||||
if cj.Running == true {
|
if cj.Running == true {
|
||||||
fmt.Printf("WARNING: Jail %s is running\n", cj.Name)
|
fmt.Printf("WARNING: Jail %s is running\n", cj.Name)
|
||||||
fmt.Printf("Migration will stop it for data sync before starting on the new pool. You will be prompted for shutdown\n")
|
fmt.Printf("Migration will stop it for data sync before starting on the new pool. You will be prompted for shutdown.\n")
|
||||||
fmt.Printf("Continue? (y/n) ")
|
fmt.Printf("Continue? (y/n) ")
|
||||||
scanr := bufio.NewScanner(os.Stdin)
|
scanr := bufio.NewScanner(os.Stdin)
|
||||||
scanr.Scan()
|
scanr.Scan()
|
||||||
@ -59,11 +59,11 @@ func MigrateJail(args []string) {
|
|||||||
zfs snapshot /iocage/jails/$jail@gocage_mig_first_snap
|
zfs snapshot /iocage/jails/$jail@gocage_mig_first_snap
|
||||||
zfs snapshot /iocage/jails/$jail/root@gocage_mig_first_snap
|
zfs snapshot /iocage/jails/$jail/root@gocage_mig_first_snap
|
||||||
zfs send jail@gocage_mig_first_snap | zfs receive destpool/jails/jail_name
|
zfs send jail@gocage_mig_first_snap | zfs receive destpool/jails/jail_name
|
||||||
zfs send jail/root@@gocage_mig_first_snap | zfs receive destpool/jails/jail_name/root
|
zfs send jail/root@gocage_mig_first_snap | zfs receive destpool/jails/jail_name/root
|
||||||
shutdown jail if needed
|
shutdown jail if needed
|
||||||
if jail was shutdown
|
if jail was shutdown
|
||||||
zfs snapshot /iocage/jails/$jail@gocage_mig_last_snap to get last data
|
zfs snapshot /iocage/jails/$jail@gocage_mig_last_snap to get last data
|
||||||
zfs send jail/root@gocage_mig_last_snap | zfs receive -F destpool/jails/jail_name
|
zfs send -i jail@gocage_mig_first_snap jail/root@gocage_mig_last_snap | zfs receive -F destpool/jails/jail_name
|
||||||
start jail on new dest
|
start jail on new dest
|
||||||
zfs destroy destpool/jails/jail_name@gocage_mig_first_snap
|
zfs destroy destpool/jails/jail_name@gocage_mig_first_snap
|
||||||
zfs destroy destpool/jails/jail_name/root@gocage_mig_first_snap
|
zfs destroy destpool/jails/jail_name/root@gocage_mig_first_snap
|
||||||
@ -100,11 +100,64 @@ func MigrateJail(args []string) {
|
|||||||
fmt.Printf("Error: %v\n", err)
|
fmt.Printf("Error: %v\n", err)
|
||||||
}
|
}
|
||||||
fmt.Printf("Done\n")
|
fmt.Printf("Done\n")
|
||||||
|
|
||||||
|
// Running jail needs a last snapshot for an incremental send/recv after shutting down.
|
||||||
|
if cj.Running == true {
|
||||||
|
fmt.Printf("Shutdown jail %s for last data sync, this could take some time.\n", cj.Name)
|
||||||
|
fmt.Printf("Continue? (y/n) ")
|
||||||
|
scanr := bufio.NewScanner(os.Stdin)
|
||||||
|
scanr.Scan()
|
||||||
|
if false == strings.EqualFold(scanr.Text(), "y") {
|
||||||
|
fmt.Printf("Migration aborted. Now cleaning destination pool.\n")
|
||||||
|
if err := CleanMigrateMess([]string{cj.Name}); err != nil {
|
||||||
|
fmt.Printf("Error: %v\n", err)
|
||||||
|
}
|
||||||
|
// TODO : Remove destination datasets, or handle the cas at the beginning of current function
|
||||||
|
// (when snapshot already exist on source and dest)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
StopJail([]string{cj.Name})
|
||||||
|
|
||||||
|
fmt.Printf("Snapshot %s: ", dsconf)
|
||||||
|
if err = zfsSnapshot(dsconf, "gocage_mig_last_sync"); err != nil {
|
||||||
|
fmt.Printf("Error: %v\n", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fmt.Printf("Done\n")
|
||||||
|
fmt.Printf("Snapshot %s: ", dsdata)
|
||||||
|
if err := zfsSnapshot(dsdata, "gocage_mig_last_sync"); err != nil {
|
||||||
|
fmt.Printf("Error: %v\n", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fmt.Printf("Done\n")
|
||||||
|
|
||||||
|
fmt.Printf("Synchronize jail config to %s: ", dsconfdest)
|
||||||
|
if err := zfsCopyIncremental(fmt.Sprintf("%s@gocage_mig_init", dsconf),
|
||||||
|
fmt.Sprintf("%s@gocage_mig_last_sync", dsconf),
|
||||||
|
dsconfdest); err != nil {
|
||||||
|
fmt.Printf("Error: %v\n", err)
|
||||||
|
}
|
||||||
|
fmt.Printf("Done\n")
|
||||||
|
fmt.Printf("Synchronize jail filesystem dataset to %s: ", dsdatadest)
|
||||||
|
if err := zfsCopyIncremental(fmt.Sprintf("%s@gocage_mig_init", dsdata),
|
||||||
|
fmt.Sprintf("%s@gocage_mig_last_sync", dsdata),
|
||||||
|
dsdatadest); err != nil {
|
||||||
|
fmt.Printf("Error: %v\n", err)
|
||||||
|
}
|
||||||
|
fmt.Printf("Done\n")
|
||||||
|
|
||||||
|
// TODO : Start jail on new datastore (! Currently ListJails won't support the double with same name !)
|
||||||
|
|
||||||
|
// TODO : zfs destroy destpool/jails/jail_name@gocage_mig_first_snap
|
||||||
|
// TODO : zfs destroy destpool/jails/jail_name/root@gocage_mig_first_snap
|
||||||
|
// TODO : zfs destroy -r srcpool/iocage/jails/$jail
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clean snapshots from an aborted migration
|
// Clean snapshots from an aborted migration
|
||||||
func CleanMigrateMess(args []string) {
|
func CleanMigrateMess(args []string) error {
|
||||||
var jailNames []string
|
var jailNames []string
|
||||||
|
|
||||||
if len(args) > 0 {
|
if len(args) > 0 {
|
||||||
@ -117,7 +170,7 @@ func CleanMigrateMess(args []string) {
|
|||||||
cj, err := getJailFromArray(jn, gJails)
|
cj, err := getJailFromArray(jn, gJails)
|
||||||
if cj == nil {
|
if cj == nil {
|
||||||
fmt.Printf("Error getting jail %s: Not found\n", jn)
|
fmt.Printf("Error getting jail %s: Not found\n", jn)
|
||||||
return
|
return errors.New(fmt.Sprintf("Error getting jail %s: Not found\n", jn))
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd := fmt.Sprintf("zfs destroy %s@gocage_mig_init", strings.Join([]string{cj.Zpool, "iocage", "jails", jn}, "/"))
|
cmd := fmt.Sprintf("zfs destroy %s@gocage_mig_init", strings.Join([]string{cj.Zpool, "iocage", "jails", jn}, "/"))
|
||||||
@ -125,7 +178,7 @@ func CleanMigrateMess(args []string) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
if false == strings.HasSuffix(out, "could not find any snapshots to destroy; check snapshot names.\n") {
|
if false == strings.HasSuffix(out, "could not find any snapshots to destroy; check snapshot names.\n") {
|
||||||
fmt.Printf("Error executing command %s: %v; command returned: %s\n", cmd, err, out)
|
fmt.Printf("Error executing command %s: %v; command returned: %s\n", cmd, err, out)
|
||||||
return
|
return errors.New(fmt.Sprintf("Error executing command %s: %v; command returned: %s\n", cmd, err, out))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cmd = fmt.Sprintf("zfs destroy %s@gocage_mig_init", strings.Join([]string{cj.Zpool, "iocage", "jails", jn, "root"}, "/"))
|
cmd = fmt.Sprintf("zfs destroy %s@gocage_mig_init", strings.Join([]string{cj.Zpool, "iocage", "jails", jn, "root"}, "/"))
|
||||||
@ -133,8 +186,26 @@ func CleanMigrateMess(args []string) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
if false == strings.HasSuffix(out, "could not find any snapshots to destroy; check snapshot names.\n") {
|
if false == strings.HasSuffix(out, "could not find any snapshots to destroy; check snapshot names.\n") {
|
||||||
fmt.Printf("Error executing command %s: %v; command returned: %s\n", cmd, err, out)
|
fmt.Printf("Error executing command %s: %v; command returned: %s\n", cmd, err, out)
|
||||||
return
|
return errors.New(fmt.Sprintf("Error executing command %s: %v; command returned: %s\n", cmd, err, out))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cmd = fmt.Sprintf("zfs destroy %s@gocage_mig_last_sync", strings.Join([]string{cj.Zpool, "iocage", "jails", jn}, "/"))
|
||||||
|
out, err = executeCommand(cmd)
|
||||||
|
if err != nil {
|
||||||
|
if false == strings.HasSuffix(out, "could not find any snapshots to destroy; check snapshot names.\n") {
|
||||||
|
fmt.Printf("Error executing command %s: %v; command returned: %s\n", cmd, err, out)
|
||||||
|
return errors.New(fmt.Sprintf("Error executing command %s: %v; command returned: %s\n", cmd, err, out))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cmd = fmt.Sprintf("zfs destroy %s@gocage_mig_last_sync", strings.Join([]string{cj.Zpool, "iocage", "jails", jn, "root"}, "/"))
|
||||||
|
out, err = executeCommand(cmd)
|
||||||
|
if err != nil {
|
||||||
|
if false == strings.HasSuffix(out, "could not find any snapshots to destroy; check snapshot names.\n") {
|
||||||
|
fmt.Printf("Error executing command %s: %v; command returned: %s\n", cmd, err, out)
|
||||||
|
return errors.New(fmt.Sprintf("Error executing command %s: %v; command returned: %s\n", cmd, err, out))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user