1
// Copyright 2014 Canonical Ltd.
2
// Licensed under the AGPLv3, see LICENCE file for details.
12
"github.com/juju/errors"
13
"launchpad.net/gnuflag"
15
"github.com/juju/juju/api/backups"
16
apiserverbackups "github.com/juju/juju/apiserver/backups"
17
"github.com/juju/juju/apiserver/params"
18
"github.com/juju/juju/cmd/modelcmd"
19
statebackups "github.com/juju/juju/state/backups"
22
// APIClient represents the backups API client functionality used by
23
// the backups command.
24
type APIClient interface {
26
// Create sends an RPC request to create a new backup.
27
Create(notes string) (*params.BackupsMetadataResult, error)
28
// Info gets the backup's metadata.
29
Info(id string) (*params.BackupsMetadataResult, error)
30
// List gets all stored metadata.
31
List() (*params.BackupsListResult, error)
32
// Download pulls the backup archive file.
33
Download(id string) (io.ReadCloser, error)
34
// Upload pushes a backup archive to storage.
35
Upload(ar io.ReadSeeker, meta params.BackupsMetadataResult) (string, error)
36
// Remove removes the stored backup.
37
Remove(id string) error
38
// Restore will restore a backup with the given id into the controller.
39
Restore(string, backups.ClientConnection) error
40
// RestoreReader will restore a backup file into the controller.
41
RestoreReader(io.ReadSeeker, *params.BackupsMetadataResult, backups.ClientConnection) error
44
// CommandBase is the base type for backups sub-commands.
45
type CommandBase struct {
46
// TODO(wallyworld) - remove Log when backup command is flattened.
48
modelcmd.ModelCommandBase
51
// NewAPIClient returns a client for the backups api endpoint.
52
func (c *CommandBase) NewAPIClient() (APIClient, error) {
53
return newAPIClient(c)
56
// SetFlags implements Command.SetFlags.
57
func (c *CommandBase) SetFlags(f *gnuflag.FlagSet) {
63
var newAPIClient = func(c *CommandBase) (APIClient, error) {
64
root, err := c.NewAPIRoot()
66
return nil, errors.Trace(err)
68
return backups.NewClient(root)
71
// dumpMetadata writes the formatted backup metadata to stdout.
72
func (c *CommandBase) dumpMetadata(ctx *cmd.Context, result *params.BackupsMetadataResult) {
73
fmt.Fprintf(ctx.Stdout, "backup ID: %q\n", result.ID)
74
fmt.Fprintf(ctx.Stdout, "checksum: %q\n", result.Checksum)
75
fmt.Fprintf(ctx.Stdout, "checksum format: %q\n", result.ChecksumFormat)
76
fmt.Fprintf(ctx.Stdout, "size (B): %d\n", result.Size)
77
fmt.Fprintf(ctx.Stdout, "stored: %v\n", result.Stored)
79
fmt.Fprintf(ctx.Stdout, "started: %v\n", result.Started)
80
fmt.Fprintf(ctx.Stdout, "finished: %v\n", result.Finished)
81
fmt.Fprintf(ctx.Stdout, "notes: %q\n", result.Notes)
83
fmt.Fprintf(ctx.Stdout, "model ID: %q\n", result.Model)
84
fmt.Fprintf(ctx.Stdout, "machine ID: %q\n", result.Machine)
85
fmt.Fprintf(ctx.Stdout, "created on host: %q\n", result.Hostname)
86
fmt.Fprintf(ctx.Stdout, "juju version: %v\n", result.Version)
89
// ArchiveReader can read a backup archive.
90
type ArchiveReader interface {
95
func getArchive(filename string) (rc ArchiveReader, metaResult *params.BackupsMetadataResult, err error) {
97
if err != nil && rc != nil {
101
archive, err := os.Open(filename)
104
return nil, nil, errors.Trace(err)
107
// Extract the metadata.
108
ad, err := statebackups.NewArchiveDataReader(archive)
110
return nil, nil, errors.Trace(err)
112
_, err = archive.Seek(0, os.SEEK_SET)
114
return nil, nil, errors.Trace(err)
116
meta, err := ad.Metadata()
118
if !errors.IsNotFound(err) {
119
return nil, nil, errors.Trace(err)
121
meta, err = statebackups.BuildMetadata(archive)
123
return nil, nil, errors.Trace(err)
126
// Make sure the file info is set.
127
fileMeta, err := statebackups.BuildMetadata(archive)
129
return nil, nil, errors.Trace(err)
131
if meta.Size() == int64(0) {
132
if err := meta.SetFileInfo(fileMeta.Size(), "", ""); err != nil {
133
return nil, nil, errors.Trace(err)
136
if meta.Checksum() == "" {
137
err := meta.SetFileInfo(0, fileMeta.Checksum(), fileMeta.ChecksumFormat())
139
return nil, nil, errors.Trace(err)
142
if meta.Finished == nil || meta.Finished.IsZero() {
143
meta.Finished = fileMeta.Finished
145
_, err = archive.Seek(0, os.SEEK_SET)
147
return nil, nil, errors.Trace(err)
150
// Pack the metadata into a result.
151
// TODO(perrito666) change the identity of ResultfromMetadata to
153
mResult := apiserverbackups.ResultFromMetadata(meta)
154
metaResult = &mResult
156
return archive, metaResult, nil