Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(178)

Side by Side Diff: container/lxc/lxc.go

Issue 12801044: Faster container creation via lxc-clone
Patch Set: Created 10 years, 7 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
« no previous file with comments | « [revision details] ('k') | container/lxc/mock/mock-lxc.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 Canonical Ltd. 1 // Copyright 2013 Canonical Ltd.
2 // Licensed under the AGPLv3, see LICENCE file for details. 2 // Licensed under the AGPLv3, see LICENCE file for details.
3 3
4 package lxc 4 package lxc
5 5
6 import ( 6 import (
7 "fmt" 7 "fmt"
8 "io/ioutil" 8 "io/ioutil"
9 "os" 9 "os"
10 "path/filepath" 10 "path/filepath"
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
113 } 113 }
114 114
115 func (manager *containerManager) StartContainer( 115 func (manager *containerManager) StartContainer(
116 machineId, series, nonce string, 116 machineId, series, nonce string,
117 network *NetworkConfig, 117 network *NetworkConfig,
118 tools *tools.Tools, 118 tools *tools.Tools,
119 environConfig *config.Config, 119 environConfig *config.Config,
120 stateInfo *state.Info, 120 stateInfo *state.Info,
121 apiInfo *api.Info) (instance.Instance, error) { 121 apiInfo *api.Info) (instance.Instance, error) {
122 122
123 var container golxc.Container
124
123 name := names.MachineTag(machineId) 125 name := names.MachineTag(machineId)
124 if manager.name != "" { 126 if manager.name != "" {
125 name = fmt.Sprintf("%s-%s", manager.name, name) 127 name = fmt.Sprintf("%s-%s", manager.name, name)
126 } 128 }
127 » // Note here that the lxcObjectFacotry only returns a valid container 129 » // Note here that the lxcObjectFactory only returns a valid container
128 // object, and doesn't actually construct the underlying lxc container o n 130 // object, and doesn't actually construct the underlying lxc container o n
129 // disk. 131 // disk.
130 » container := lxcObjectFactory.New(name) 132 » templateName := fmt.Sprintf("%s-%s-template", manager.name, series)
133 » template := lxcObjectFactory.New(templateName)
wallyworld 2013/11/04 02:51:35 What if manager.name is ""? There's a few lines of
134 » if !template.IsConstructed() {
fwereade 2013/11/06 12:28:44 Would it be reasonable to extract this block as a
135 » » templateDirectory := jujuContainerDirectory(templateName)
136 » » logger.Debugf("create directory: %s", templateDirectory)
137 » » if err := os.MkdirAll(templateDirectory, 0755); err != nil {
138 » » » logger.Errorf("failed to create template container direc tory: %v", err)
139 » » » return nil, err
140 » » }
141 » » logger.Debugf("write the lxc.conf file")
142 » » configFile, err := writeLxcConfig(network, templateDirectory, ma nager.logdir)
143 » » if err != nil {
144 » » » logger.Errorf("failed to write config file: %v", err)
145 » » » return nil, err
146 » » }
147 » » templateParams := []string{
148 » » » "--debug", // Debug errors in the cloud i mage
149 » » » "--hostid", templateName, // Use the container name as t he hostid
150 » » » "-r", series,
151 » » }
152 » » // Create the container.
153 » » logger.Debugf("create the container template")
154 » » if err := template.Create(configFile, defaultTemplate, templateP arams...); err != nil {
155 » » » logger.Errorf("lxc template container creation failed: % v", err)
156 » » » return nil, err
157 » » }
158 » » // Make sure that the mount dir has been created.
159 » » logger.Debugf("make the mount dir for the shard logs")
160 » » if err := os.MkdirAll(internalLogDir(templateName), 0755); err ! = nil {
161 » » » logger.Errorf("failed to create internal /var/log/juju m ount dir: %v", err)
162 » » » return nil, err
163 » » }
164 » }
131 165
132 // Create the cloud-init. 166 // Create the cloud-init.
133 directory := jujuContainerDirectory(name) 167 directory := jujuContainerDirectory(name)
134 » logger.Tracef("create directory: %s", directory) 168 » logger.Debugf("create directory: %s", directory)
135 if err := os.MkdirAll(directory, 0755); err != nil { 169 if err := os.MkdirAll(directory, 0755); err != nil {
136 logger.Errorf("failed to create container directory: %v", err) 170 logger.Errorf("failed to create container directory: %v", err)
137 return nil, err 171 return nil, err
138 } 172 }
139 » logger.Tracef("write cloud-init") 173 » logger.Debugf("write cloud-init")
140 userDataFilename, err := writeUserData(directory, machineId, nonce, tool s, environConfig, stateInfo, apiInfo) 174 userDataFilename, err := writeUserData(directory, machineId, nonce, tool s, environConfig, stateInfo, apiInfo)
141 if err != nil { 175 if err != nil {
142 logger.Errorf("failed to write user data: %v", err) 176 logger.Errorf("failed to write user data: %v", err)
143 return nil, err 177 return nil, err
144 } 178 }
145 » logger.Tracef("write the lxc.conf file") 179 » templateParams := []string{
146 » configFile, err := writeLxcConfig(network, directory, manager.logdir) 180 » » "--userdata", userDataFilename, // Our groovey cloud-init
147 » if err != nil { 181 » }
148 » » logger.Errorf("failed to write config file: %v", err) 182 » // Clone existing template into a new container.
183 » logger.Debugf("create the container clone")
184 » if container, err = template.Clone(name, true, golxc.BackingStoreOverlay FS, templateParams...); err != nil {
185 » » logger.Errorf("lxc container clone creation failed: %v", err)
149 return nil, err 186 return nil, err
150 } 187 }
151 » templateParams := []string{ 188
152 » » "--debug", // Debug errors in the cloud ima ge 189 » logger.Debugf("lxc container clone created")
153 » » "--userdata", userDataFilename, // Our groovey cloud-init
154 » » "--hostid", name, // Use the container name as the hostid
155 » » "-r", series,
156 » }
157 » // Create the container.
158 » logger.Tracef("create the container")
159 » if err := container.Create(configFile, defaultTemplate, templateParams.. .); err != nil {
160 » » logger.Errorf("lxc container creation failed: %v", err)
161 » » return nil, err
162 » }
163 » // Make sure that the mount dir has been created.
164 » logger.Tracef("make the mount dir for the shard logs")
165 » if err := os.MkdirAll(internalLogDir(name), 0755); err != nil {
166 » » logger.Errorf("failed to create internal /var/log/juju mount dir : %v", err)
167 » » return nil, err
168 » }
169 » logger.Tracef("lxc container created")
170 // Now symlink the config file into the restart directory. 190 // Now symlink the config file into the restart directory.
171 containerConfigFile := filepath.Join(lxcContainerDir, name, "config") 191 containerConfigFile := filepath.Join(lxcContainerDir, name, "config")
172 if err := os.Symlink(containerConfigFile, restartSymlink(name)); err != nil { 192 if err := os.Symlink(containerConfigFile, restartSymlink(name)); err != nil {
173 return nil, err 193 return nil, err
174 } 194 }
175 » logger.Tracef("auto-restart link created") 195 » logger.Debugf("auto-restart link created")
176 196
177 // Start the lxc container with the appropriate settings for grabbing th e 197 // Start the lxc container with the appropriate settings for grabbing th e
178 // console output and a log file. 198 // console output and a log file.
179 consoleFile := filepath.Join(directory, "console.log") 199 consoleFile := filepath.Join(directory, "console.log")
180 container.SetLogFile(filepath.Join(directory, "container.log"), golxc.Lo gDebug) 200 container.SetLogFile(filepath.Join(directory, "container.log"), golxc.Lo gDebug)
181 » logger.Tracef("start the container") 201 » logger.Debugf("start the container")
182 // We explicitly don't pass through the config file to the container.Sta rt 202 // We explicitly don't pass through the config file to the container.Sta rt
183 // method as we have passed it through at container creation time. This 203 // method as we have passed it through at container creation time. This
184 // is necessary to get the appropriate rootfs reference without explicit ly 204 // is necessary to get the appropriate rootfs reference without explicit ly
185 // setting it ourselves. 205 // setting it ourselves.
186 if err = container.Start("", consoleFile); err != nil { 206 if err = container.Start("", consoleFile); err != nil {
187 logger.Errorf("container failed to start: %v", err) 207 logger.Errorf("container failed to start: %v", err)
188 return nil, err 208 return nil, err
189 } 209 }
190 » logger.Tracef("container started") 210 » logger.Debugf("container started")
191 return &lxcInstance{container, name}, nil 211 return &lxcInstance{container, name}, nil
192 } 212 }
193 213
194 func (manager *containerManager) StopContainer(instance instance.Instance) error { 214 func (manager *containerManager) StopContainer(instance instance.Instance) error {
195 name := string(instance.Id()) 215 name := string(instance.Id())
196 container := lxcObjectFactory.New(name) 216 container := lxcObjectFactory.New(name)
197 if err := container.Stop(); err != nil { 217 if err := container.Stop(); err != nil {
198 logger.Errorf("failed to stop lxc container: %v", err) 218 logger.Errorf("failed to stop lxc container: %v", err)
199 return err 219 return err
200 } 220 }
201 // Destroy removes the restart symlink for us. 221 // Destroy removes the restart symlink for us.
202 if err := container.Destroy(); err != nil { 222 if err := container.Destroy(); err != nil {
203 logger.Errorf("failed to destroy lxc container: %v", err) 223 logger.Errorf("failed to destroy lxc container: %v", err)
204 return err 224 return err
205 } 225 }
206 226
207 // Move the directory. 227 // Move the directory.
208 » logger.Tracef("create old container dir: %s", removedContainerDir) 228 » logger.Debugf("create old container dir: %s", removedContainerDir)
209 if err := os.MkdirAll(removedContainerDir, 0755); err != nil { 229 if err := os.MkdirAll(removedContainerDir, 0755); err != nil {
210 logger.Errorf("failed to create removed container directory: %v" , err) 230 logger.Errorf("failed to create removed container directory: %v" , err)
211 return err 231 return err
212 } 232 }
213 removedDir, err := uniqueDirectory(removedContainerDir, name) 233 removedDir, err := uniqueDirectory(removedContainerDir, name)
214 if err != nil { 234 if err != nil {
215 logger.Errorf("was not able to generate a unique directory: %v", err) 235 logger.Errorf("was not able to generate a unique directory: %v", err)
216 return err 236 return err
217 } 237 }
218 if err := os.Rename(jujuContainerDirectory(name), removedDir); err != ni l { 238 if err := os.Rename(jujuContainerDirectory(name), removedDir); err != ni l {
(...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after
393 for i := 1; ; i++ { 413 for i := 1; ; i++ {
394 dir := filepath.Join(path, fmt.Sprintf("%s.%d", name, i)) 414 dir := filepath.Join(path, fmt.Sprintf("%s.%d", name, i))
395 _, err := os.Stat(dir) 415 _, err := os.Stat(dir)
396 if os.IsNotExist(err) { 416 if os.IsNotExist(err) {
397 return dir, nil 417 return dir, nil
398 } else if err != nil { 418 } else if err != nil {
399 return "", err 419 return "", err
400 } 420 }
401 } 421 }
402 } 422 }
OLDNEW
« no previous file with comments | « [revision details] ('k') | container/lxc/mock/mock-lxc.go » ('j') | no next file with comments »

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b