~nskaggs/+junk/xenial-test

« back to all changes in this revision

Viewing changes to src/github.com/juju/juju/cmd/juju/backups/backups.go

  • Committer: Nicholas Skaggs
  • Date: 2016-10-24 20:56:05 UTC
  • Revision ID: nicholas.skaggs@canonical.com-20161024205605-z8lta0uvuhtxwzwl
Initi with beta15

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright 2014 Canonical Ltd.
 
2
// Licensed under the AGPLv3, see LICENCE file for details.
 
3
 
 
4
package backups
 
5
 
 
6
import (
 
7
        "fmt"
 
8
        "io"
 
9
        "os"
 
10
 
 
11
        "github.com/juju/cmd"
 
12
        "github.com/juju/errors"
 
13
        "launchpad.net/gnuflag"
 
14
 
 
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"
 
20
)
 
21
 
 
22
// APIClient represents the backups API client functionality used by
 
23
// the backups command.
 
24
type APIClient interface {
 
25
        io.Closer
 
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
 
42
}
 
43
 
 
44
// CommandBase is the base type for backups sub-commands.
 
45
type CommandBase struct {
 
46
        // TODO(wallyworld) - remove Log when backup command is flattened.
 
47
        Log *cmd.Log
 
48
        modelcmd.ModelCommandBase
 
49
}
 
50
 
 
51
// NewAPIClient returns a client for the backups api endpoint.
 
52
func (c *CommandBase) NewAPIClient() (APIClient, error) {
 
53
        return newAPIClient(c)
 
54
}
 
55
 
 
56
// SetFlags implements Command.SetFlags.
 
57
func (c *CommandBase) SetFlags(f *gnuflag.FlagSet) {
 
58
        if c.Log != nil {
 
59
                c.Log.AddFlags(f)
 
60
        }
 
61
}
 
62
 
 
63
var newAPIClient = func(c *CommandBase) (APIClient, error) {
 
64
        root, err := c.NewAPIRoot()
 
65
        if err != nil {
 
66
                return nil, errors.Trace(err)
 
67
        }
 
68
        return backups.NewClient(root)
 
69
}
 
70
 
 
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)
 
78
 
 
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)
 
82
 
 
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)
 
87
}
 
88
 
 
89
// ArchiveReader can read a backup archive.
 
90
type ArchiveReader interface {
 
91
        io.ReadSeeker
 
92
        io.Closer
 
93
}
 
94
 
 
95
func getArchive(filename string) (rc ArchiveReader, metaResult *params.BackupsMetadataResult, err error) {
 
96
        defer func() {
 
97
                if err != nil && rc != nil {
 
98
                        rc.Close()
 
99
                }
 
100
        }()
 
101
        archive, err := os.Open(filename)
 
102
        rc = archive
 
103
        if err != nil {
 
104
                return nil, nil, errors.Trace(err)
 
105
        }
 
106
 
 
107
        // Extract the metadata.
 
108
        ad, err := statebackups.NewArchiveDataReader(archive)
 
109
        if err != nil {
 
110
                return nil, nil, errors.Trace(err)
 
111
        }
 
112
        _, err = archive.Seek(0, os.SEEK_SET)
 
113
        if err != nil {
 
114
                return nil, nil, errors.Trace(err)
 
115
        }
 
116
        meta, err := ad.Metadata()
 
117
        if err != nil {
 
118
                if !errors.IsNotFound(err) {
 
119
                        return nil, nil, errors.Trace(err)
 
120
                }
 
121
                meta, err = statebackups.BuildMetadata(archive)
 
122
                if err != nil {
 
123
                        return nil, nil, errors.Trace(err)
 
124
                }
 
125
        }
 
126
        // Make sure the file info is set.
 
127
        fileMeta, err := statebackups.BuildMetadata(archive)
 
128
        if err != nil {
 
129
                return nil, nil, errors.Trace(err)
 
130
        }
 
131
        if meta.Size() == int64(0) {
 
132
                if err := meta.SetFileInfo(fileMeta.Size(), "", ""); err != nil {
 
133
                        return nil, nil, errors.Trace(err)
 
134
                }
 
135
        }
 
136
        if meta.Checksum() == "" {
 
137
                err := meta.SetFileInfo(0, fileMeta.Checksum(), fileMeta.ChecksumFormat())
 
138
                if err != nil {
 
139
                        return nil, nil, errors.Trace(err)
 
140
                }
 
141
        }
 
142
        if meta.Finished == nil || meta.Finished.IsZero() {
 
143
                meta.Finished = fileMeta.Finished
 
144
        }
 
145
        _, err = archive.Seek(0, os.SEEK_SET)
 
146
        if err != nil {
 
147
                return nil, nil, errors.Trace(err)
 
148
        }
 
149
 
 
150
        // Pack the metadata into a result.
 
151
        // TODO(perrito666) change the identity of ResultfromMetadata to
 
152
        // return a pointer.
 
153
        mResult := apiserverbackups.ResultFromMetadata(meta)
 
154
        metaResult = &mResult
 
155
 
 
156
        return archive, metaResult, nil
 
157
}