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