github.com/mhilton/juju-juju@v0.0.0-20150901100907-a94dd2c73455/apiserver/backups/restore.go (about) 1 // Copyright 2015 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package backups 5 6 import ( 7 "os" 8 9 "github.com/juju/errors" 10 11 "github.com/juju/juju/apiserver/params" 12 "github.com/juju/juju/network" 13 "github.com/juju/juju/state" 14 "github.com/juju/juju/state/backups" 15 ) 16 17 // Restore implements the server side of Backups.Restore. 18 func (a *API) Restore(p params.RestoreArgs) error { 19 20 // Get hold of a backup file Reader 21 backup, closer := newBackups(a.st) 22 defer closer.Close() 23 24 // Obtain the address of current machine, where we will be performing restore. 25 machine, err := a.st.Machine(a.machineID) 26 if err != nil { 27 return errors.Trace(err) 28 } 29 30 addr := network.SelectInternalAddress(machine.Addresses(), false) 31 if addr == "" { 32 return errors.Errorf("machine %q has no internal address", machine) 33 } 34 35 publicAddress := network.SelectPublicAddress(machine.Addresses()) 36 if publicAddress == "" { 37 return errors.Errorf("machine %q has no public address", machine) 38 } 39 40 info, err := a.st.RestoreInfoSetter() 41 if err != nil { 42 return errors.Trace(err) 43 } 44 // Signal to current state and api server that restore will begin 45 err = info.SetStatus(state.RestoreInProgress) 46 if err != nil { 47 return errors.Annotatef(err, "cannot set the server to %q mode", state.RestoreInProgress) 48 } 49 // Any abnormal termination of this function will mark restore as failed, 50 // succesful termination will call Exit and never run this. 51 defer info.SetStatus(state.RestoreFailed) 52 53 instanceId, err := machine.InstanceId() 54 if err != nil { 55 return errors.Annotate(err, "cannot obtain instance id for machine to be restored") 56 } 57 58 logger.Infof("beginning server side restore of backup %q", p.BackupId) 59 // Restore 60 restoreArgs := backups.RestoreArgs{ 61 PrivateAddress: addr, 62 PublicAddress: publicAddress, 63 NewInstId: instanceId, 64 NewInstTag: machine.Tag(), 65 NewInstSeries: machine.Series(), 66 } 67 if err := backup.Restore(p.BackupId, restoreArgs); err != nil { 68 return errors.Annotate(err, "restore failed") 69 } 70 71 // After restoring, the api server needs a forced restart, tomb will not work 72 // this is because we change all of juju configuration files and mongo too. 73 // Exiting with 0 would prevent upstart to respawn the process 74 os.Exit(1) 75 return nil 76 } 77 78 // PrepareRestore implements the server side of Backups.PrepareRestore. 79 func (a *API) PrepareRestore() error { 80 info, err := a.st.RestoreInfoSetter() 81 if err != nil { 82 return errors.Trace(err) 83 } 84 logger.Infof("entering restore preparation mode") 85 return info.SetStatus(state.RestorePending) 86 } 87 88 // FinishRestore implements the server side of Backups.FinishRestore. 89 func (a *API) FinishRestore() error { 90 info, err := a.st.RestoreInfoSetter() 91 if err != nil { 92 return errors.Trace(err) 93 } 94 currentStatus := info.Status() 95 if currentStatus != state.RestoreFinished { 96 info.SetStatus(state.RestoreFailed) 97 return errors.Errorf("Restore did not finish succesfuly") 98 } 99 logger.Infof("Succesfully restored") 100 return info.SetStatus(state.RestoreChecked) 101 }