9
"github.com/lxc/lxd/shared"
10
"github.com/lxc/lxd/shared/gnuflag"
11
"github.com/lxc/lxd/shared/i18n"
14
type profileList []string
16
var configMap map[string]string
18
func (f *profileList) String() string {
22
type configList []string
24
func (f *configList) String() string {
25
return fmt.Sprint(configMap)
28
func (f *configList) Set(value string) error {
30
return fmt.Errorf(i18n.G("Invalid configuration key"))
33
items := strings.SplitN(value, "=", 2)
35
return fmt.Errorf(i18n.G("Invalid configuration key"))
39
configMap = map[string]string{}
42
configMap[items[0]] = items[1]
47
func (f *profileList) Set(value string) error {
49
initRequestedEmptyProfiles = true
53
*f = make(profileList, 1)
55
*f = append(*f, value)
60
var initRequestedEmptyProfiles bool
68
func (c *initCmd) showByDefault() bool {
72
func (c *initCmd) usage() string {
74
`Initialize a container from a particular image.
76
lxc init [remote:]<image> [remote:][<name>] [--ephemeral|-e] [--profile|-p <profile>...] [--config|-c <key=value>...]
78
Initializes a container using the specified image and name.
80
Not specifying -p will result in the default profile.
81
Specifying "-p" with no argument will result in no profile.
87
func (c *initCmd) is_ephem(s string) bool {
97
func (c *initCmd) is_profile(s string) bool {
107
func (c *initCmd) massage_args() {
113
if c.is_profile(os.Args[l-1]) {
114
initRequestedEmptyProfiles = true
115
os.Args = os.Args[0 : l-1]
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])
132
func (c *initCmd) flags() {
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"))
142
func (c *initCmd) run(config *lxd.Config, args []string) error {
143
if len(args) > 2 || len(args) < 1 {
147
iremote, image := config.ParseRemoteAndContainer(args[0])
152
remote, name = config.ParseRemoteAndContainer(args[1])
154
remote, name = config.ParseRemoteAndContainer("")
157
d, err := lxd.NewClient(config, remote)
162
// TODO: implement the syntax for supporting other image types/remotes
165
* initRequestedEmptyProfiles means user requested empty
166
* !initRequestedEmptyProfiles but len(profArgs) == 0 means use profile default
168
profiles := []string{}
169
for _, p := range c.profArgs {
170
profiles = append(profiles, p)
173
var resp *lxd.Response
175
fmt.Printf(i18n.G("Creating the container") + "\n")
177
fmt.Printf(i18n.G("Creating %s")+"\n", name)
180
if !initRequestedEmptyProfiles && len(profiles) == 0 {
181
resp, err = d.Init(name, iremote, image, nil, configMap, c.ephem)
183
resp, err = d.Init(name, iremote, image, &profiles, configMap, c.ephem)
190
c.initProgressTracker(d, resp.Operation)
192
err = d.WaitForSuccess(resp.Operation)
197
op, err := resp.MetadataAsOperation()
199
return fmt.Errorf(i18n.G("didn't get any affected image, container or snapshot from server"))
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"))
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])
215
func (c *initCmd) initProgressTracker(d *lxd.Client, operation string) {
216
handler := func(msg interface{}) {
221
event := msg.(map[string]interface{})
222
if event["type"].(string) != "operation" {
226
if event["metadata"] == nil {
230
md := event["metadata"].(map[string]interface{})
231
if !strings.HasSuffix(operation, md["id"].(string)) {
235
if md["metadata"] == nil {
239
if shared.StatusCode(md["status_code"].(float64)).IsFinal() {
243
opMd := md["metadata"].(map[string]interface{})
244
_, ok := opMd["download_progress"]
246
fmt.Printf(i18n.G("Retrieving image: %s")+"\r", opMd["download_progress"].(string))
249
if opMd["download_progress"].(string) == "100%" {
253
go d.Monitor([]string{"operation"}, handler)