~nskaggs/+junk/juju-packaging-test

« back to all changes in this revision

Viewing changes to src/github.com/lxc/lxd/lxc/init.go

  • Committer: Nicholas Skaggs
  • Date: 2016-10-27 20:23:11 UTC
  • Revision ID: nicholas.skaggs@canonical.com-20161027202311-sux4jk2o73p1d6rg
Re-add src

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
package main
 
2
 
 
3
import (
 
4
        "fmt"
 
5
        "os"
 
6
        "strings"
 
7
 
 
8
        "github.com/lxc/lxd"
 
9
        "github.com/lxc/lxd/shared"
 
10
        "github.com/lxc/lxd/shared/gnuflag"
 
11
        "github.com/lxc/lxd/shared/i18n"
 
12
)
 
13
 
 
14
type profileList []string
 
15
 
 
16
var configMap map[string]string
 
17
 
 
18
func (f *profileList) String() string {
 
19
        return fmt.Sprint(*f)
 
20
}
 
21
 
 
22
type configList []string
 
23
 
 
24
func (f *configList) String() string {
 
25
        return fmt.Sprint(configMap)
 
26
}
 
27
 
 
28
func (f *configList) Set(value string) error {
 
29
        if value == "" {
 
30
                return fmt.Errorf(i18n.G("Invalid configuration key"))
 
31
        }
 
32
 
 
33
        items := strings.SplitN(value, "=", 2)
 
34
        if len(items) < 2 {
 
35
                return fmt.Errorf(i18n.G("Invalid configuration key"))
 
36
        }
 
37
 
 
38
        if configMap == nil {
 
39
                configMap = map[string]string{}
 
40
        }
 
41
 
 
42
        configMap[items[0]] = items[1]
 
43
 
 
44
        return nil
 
45
}
 
46
 
 
47
func (f *profileList) Set(value string) error {
 
48
        if value == "" {
 
49
                initRequestedEmptyProfiles = true
 
50
                return nil
 
51
        }
 
52
        if f == nil {
 
53
                *f = make(profileList, 1)
 
54
        } else {
 
55
                *f = append(*f, value)
 
56
        }
 
57
        return nil
 
58
}
 
59
 
 
60
var initRequestedEmptyProfiles bool
 
61
 
 
62
type initCmd struct {
 
63
        profArgs profileList
 
64
        confArgs configList
 
65
        ephem    bool
 
66
}
 
67
 
 
68
func (c *initCmd) showByDefault() bool {
 
69
        return false
 
70
}
 
71
 
 
72
func (c *initCmd) usage() string {
 
73
        return i18n.G(
 
74
                `Initialize a container from a particular image.
 
75
 
 
76
lxc init [remote:]<image> [remote:][<name>] [--ephemeral|-e] [--profile|-p <profile>...] [--config|-c <key=value>...]
 
77
 
 
78
Initializes a container using the specified image and name.
 
79
 
 
80
Not specifying -p will result in the default profile.
 
81
Specifying "-p" with no argument will result in no profile.
 
82
 
 
83
Example:
 
84
lxc init ubuntu u1`)
 
85
}
 
86
 
 
87
func (c *initCmd) is_ephem(s string) bool {
 
88
        switch s {
 
89
        case "-e":
 
90
                return true
 
91
        case "--ephemeral":
 
92
                return true
 
93
        }
 
94
        return false
 
95
}
 
96
 
 
97
func (c *initCmd) is_profile(s string) bool {
 
98
        switch s {
 
99
        case "-p":
 
100
                return true
 
101
        case "--profile":
 
102
                return true
 
103
        }
 
104
        return false
 
105
}
 
106
 
 
107
func (c *initCmd) massage_args() {
 
108
        l := len(os.Args)
 
109
        if l < 2 {
 
110
                return
 
111
        }
 
112
 
 
113
        if c.is_profile(os.Args[l-1]) {
 
114
                initRequestedEmptyProfiles = true
 
115
                os.Args = os.Args[0 : l-1]
 
116
                return
 
117
        }
 
118
 
 
119
        if l < 3 {
 
120
                return
 
121
        }
 
122
 
 
123
        /* catch "lxc init ubuntu -p -e */
 
124
        if c.is_ephem(os.Args[l-1]) && c.is_profile(os.Args[l-2]) {
 
125
                initRequestedEmptyProfiles = true
 
126
                newargs := os.Args[0 : l-2]
 
127
                newargs = append(newargs, os.Args[l-1])
 
128
                return
 
129
        }
 
130
}
 
131
 
 
132
func (c *initCmd) flags() {
 
133
        c.massage_args()
 
134
        gnuflag.Var(&c.confArgs, "config", i18n.G("Config key/value to apply to the new container"))
 
135
        gnuflag.Var(&c.confArgs, "c", i18n.G("Config key/value to apply to the new container"))
 
136
        gnuflag.Var(&c.profArgs, "profile", i18n.G("Profile to apply to the new container"))
 
137
        gnuflag.Var(&c.profArgs, "p", i18n.G("Profile to apply to the new container"))
 
138
        gnuflag.BoolVar(&c.ephem, "ephemeral", false, i18n.G("Ephemeral container"))
 
139
        gnuflag.BoolVar(&c.ephem, "e", false, i18n.G("Ephemeral container"))
 
140
}
 
141
 
 
142
func (c *initCmd) run(config *lxd.Config, args []string) error {
 
143
        if len(args) > 2 || len(args) < 1 {
 
144
                return errArgs
 
145
        }
 
146
 
 
147
        iremote, image := config.ParseRemoteAndContainer(args[0])
 
148
 
 
149
        var name string
 
150
        var remote string
 
151
        if len(args) == 2 {
 
152
                remote, name = config.ParseRemoteAndContainer(args[1])
 
153
        } else {
 
154
                remote, name = config.ParseRemoteAndContainer("")
 
155
        }
 
156
 
 
157
        d, err := lxd.NewClient(config, remote)
 
158
        if err != nil {
 
159
                return err
 
160
        }
 
161
 
 
162
        // TODO: implement the syntax for supporting other image types/remotes
 
163
 
 
164
        /*
 
165
         * initRequestedEmptyProfiles means user requested empty
 
166
         * !initRequestedEmptyProfiles but len(profArgs) == 0 means use profile default
 
167
         */
 
168
        profiles := []string{}
 
169
        for _, p := range c.profArgs {
 
170
                profiles = append(profiles, p)
 
171
        }
 
172
 
 
173
        var resp *lxd.Response
 
174
        if name == "" {
 
175
                fmt.Printf(i18n.G("Creating the container") + "\n")
 
176
        } else {
 
177
                fmt.Printf(i18n.G("Creating %s")+"\n", name)
 
178
        }
 
179
 
 
180
        if !initRequestedEmptyProfiles && len(profiles) == 0 {
 
181
                resp, err = d.Init(name, iremote, image, nil, configMap, c.ephem)
 
182
        } else {
 
183
                resp, err = d.Init(name, iremote, image, &profiles, configMap, c.ephem)
 
184
        }
 
185
 
 
186
        if err != nil {
 
187
                return err
 
188
        }
 
189
 
 
190
        c.initProgressTracker(d, resp.Operation)
 
191
 
 
192
        err = d.WaitForSuccess(resp.Operation)
 
193
 
 
194
        if err != nil {
 
195
                return err
 
196
        } else {
 
197
                op, err := resp.MetadataAsOperation()
 
198
                if err != nil {
 
199
                        return fmt.Errorf(i18n.G("didn't get any affected image, container or snapshot from server"))
 
200
                }
 
201
 
 
202
                containers, ok := op.Resources["containers"]
 
203
                if !ok || len(containers) == 0 {
 
204
                        return fmt.Errorf(i18n.G("didn't get any affected image, container or snapshot from server"))
 
205
                }
 
206
 
 
207
                if len(containers) == 1 && name == "" {
 
208
                        fields := strings.Split(containers[0], "/")
 
209
                        fmt.Printf(i18n.G("Container name is: %s")+"\n", fields[len(fields)-1])
 
210
                }
 
211
        }
 
212
        return nil
 
213
}
 
214
 
 
215
func (c *initCmd) initProgressTracker(d *lxd.Client, operation string) {
 
216
        handler := func(msg interface{}) {
 
217
                if msg == nil {
 
218
                        return
 
219
                }
 
220
 
 
221
                event := msg.(map[string]interface{})
 
222
                if event["type"].(string) != "operation" {
 
223
                        return
 
224
                }
 
225
 
 
226
                if event["metadata"] == nil {
 
227
                        return
 
228
                }
 
229
 
 
230
                md := event["metadata"].(map[string]interface{})
 
231
                if !strings.HasSuffix(operation, md["id"].(string)) {
 
232
                        return
 
233
                }
 
234
 
 
235
                if md["metadata"] == nil {
 
236
                        return
 
237
                }
 
238
 
 
239
                if shared.StatusCode(md["status_code"].(float64)).IsFinal() {
 
240
                        return
 
241
                }
 
242
 
 
243
                opMd := md["metadata"].(map[string]interface{})
 
244
                _, ok := opMd["download_progress"]
 
245
                if ok {
 
246
                        fmt.Printf(i18n.G("Retrieving image: %s")+"\r", opMd["download_progress"].(string))
 
247
                }
 
248
 
 
249
                if opMd["download_progress"].(string) == "100%" {
 
250
                        fmt.Printf("\n")
 
251
                }
 
252
        }
 
253
        go d.Monitor([]string{"operation"}, handler)
 
254
}