github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/apiserver/backups/backups.go (about)

     1  // Copyright 2014 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package backups
     5  
     6  import (
     7  	"io"
     8  
     9  	"github.com/juju/errors"
    10  	"github.com/juju/loggo"
    11  
    12  	"github.com/juju/juju/apiserver/common"
    13  	"github.com/juju/juju/apiserver/params"
    14  	"github.com/juju/juju/state"
    15  	"github.com/juju/juju/state/backups"
    16  )
    17  
    18  func init() {
    19  	common.RegisterStandardFacade("Backups", 1, NewAPI)
    20  }
    21  
    22  var logger = loggo.GetLogger("juju.apiserver.backups")
    23  
    24  // API serves backup-specific API methods.
    25  type API struct {
    26  	st    *state.State
    27  	paths *backups.Paths
    28  
    29  	// machineID is the ID of the machine where the API server is running.
    30  	machineID string
    31  }
    32  
    33  // NewAPI creates a new instance of the Backups API facade.
    34  func NewAPI(st *state.State, resources *common.Resources, authorizer common.Authorizer) (*API, error) {
    35  	if !authorizer.AuthClient() {
    36  		return nil, errors.Trace(common.ErrPerm)
    37  	}
    38  
    39  	// For now, backup operations are only permitted on the controller environment.
    40  	if !st.IsController() {
    41  		return nil, errors.New("backups are not supported for hosted models")
    42  	}
    43  
    44  	// Get the backup paths.
    45  	dataDir, err := extractResourceValue(resources, "dataDir")
    46  	if err != nil {
    47  		return nil, errors.Trace(err)
    48  	}
    49  	logsDir, err := extractResourceValue(resources, "logDir")
    50  	if err != nil {
    51  		return nil, errors.Trace(err)
    52  	}
    53  	paths := backups.Paths{
    54  		DataDir: dataDir,
    55  		LogsDir: logsDir,
    56  	}
    57  
    58  	// Build the API.
    59  	machineID, err := extractResourceValue(resources, "machineID")
    60  	if err != nil {
    61  		return nil, errors.Trace(err)
    62  	}
    63  	b := API{
    64  		st:        st,
    65  		paths:     &paths,
    66  		machineID: machineID,
    67  	}
    68  	return &b, nil
    69  }
    70  
    71  func extractResourceValue(resources *common.Resources, key string) (string, error) {
    72  	res := resources.Get(key)
    73  	strRes, ok := res.(common.StringResource)
    74  	if !ok {
    75  		if res == nil {
    76  			strRes = ""
    77  		} else {
    78  			return "", errors.Errorf("invalid %s resource: %v", key, res)
    79  		}
    80  	}
    81  	return strRes.String(), nil
    82  }
    83  
    84  var newBackups = func(st *state.State) (backups.Backups, io.Closer) {
    85  	stor := backups.NewStorage(st)
    86  	return backups.NewBackups(stor), stor
    87  }
    88  
    89  // ResultFromMetadata updates the result with the information in the
    90  // metadata value.
    91  func ResultFromMetadata(meta *backups.Metadata) params.BackupsMetadataResult {
    92  	var result params.BackupsMetadataResult
    93  
    94  	result.ID = meta.ID()
    95  
    96  	result.Checksum = meta.Checksum()
    97  	result.ChecksumFormat = meta.ChecksumFormat()
    98  	result.Size = meta.Size()
    99  	if meta.Stored() != nil {
   100  		result.Stored = *(meta.Stored())
   101  	}
   102  
   103  	result.Started = meta.Started
   104  	if meta.Finished != nil {
   105  		result.Finished = *meta.Finished
   106  	}
   107  	result.Notes = meta.Notes
   108  
   109  	result.Model = meta.Origin.Model
   110  	result.Machine = meta.Origin.Machine
   111  	result.Hostname = meta.Origin.Hostname
   112  	result.Version = meta.Origin.Version
   113  
   114  	// TODO(wallyworld) - remove these ASAP
   115  	// These are only used by the restore CLI when re-bootstrapping.
   116  	// We will use a better solution but the way restore currently
   117  	// works, we need them and they are no longer available via
   118  	// bootstrap config. We will need to ifx how re-bootstrap deals
   119  	// with these keys to address the issue.
   120  	result.CACert = meta.CACert
   121  	result.CAPrivateKey = meta.CAPrivateKey
   122  
   123  	return result
   124  }
   125  
   126  // MetadataFromResult returns a new Metadata based on the result. The ID
   127  // of the metadata is not set. Call meta.SetID() if that is desired.
   128  // Likewise with Stored and meta.SetStored().
   129  func MetadataFromResult(result params.BackupsMetadataResult) *backups.Metadata {
   130  	meta := backups.NewMetadata()
   131  	meta.Started = result.Started
   132  	if !result.Finished.IsZero() {
   133  		meta.Finished = &result.Finished
   134  	}
   135  	meta.Origin.Model = result.Model
   136  	meta.Origin.Machine = result.Machine
   137  	meta.Origin.Hostname = result.Hostname
   138  	meta.Origin.Version = result.Version
   139  	meta.Notes = result.Notes
   140  	meta.SetFileInfo(result.Size, result.Checksum, result.ChecksumFormat)
   141  	return meta
   142  }