~ubuntu-branches/ubuntu/trusty/juju-core/trusty

« back to all changes in this revision

Viewing changes to src/launchpad.net/juju-core/environs/sync/sync.go

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2014-03-24 16:05:44 UTC
  • mfrom: (1.1.20)
  • Revision ID: package-import@ubuntu.com-20140324160544-g8lsfufby18d5fj4
Tags: 1.17.6-0ubuntu1
* New upstream point release, including fixes for:
  - br0 not bought up by cloud-init with MAAS provider (LP: #1271144).
  - ppc64el enablement for juju/lxc (LP: #1273769).
  - juju userdata should not restart networking (LP: #1248283).
  - error detecting hardware characteristics (LP: #1276909).
  - juju instances not including the default security group (LP: #1129720).
  - juju bootstrap does not honor https_proxy (LP: #1240260).
* d/control,rules: Drop BD on bash-completion, install bash-completion
  direct from upstream source code.
* d/rules: Set HOME prior to generating man pages.
* d/control: Drop alternative dependency on mongodb-server; juju now only
  works on trusty with juju-mongodb.

Show diffs side-by-side

added added

removed removed

Lines of Context:
12
12
        "os"
13
13
        "path/filepath"
14
14
 
15
 
        "github.com/loggo/loggo"
 
15
        "github.com/juju/loggo"
16
16
 
17
17
        "launchpad.net/juju-core/environs/filestorage"
18
18
        "launchpad.net/juju-core/environs/simplestreams"
140
140
                return nil, err
141
141
        }
142
142
        logger.Infof("using sync tools source: %v", sourceURL)
143
 
        return simplestreams.NewURLDataSource(sourceURL, simplestreams.VerifySSLHostnames), nil
 
143
        return simplestreams.NewURLDataSource("sync tools source", sourceURL, simplestreams.VerifySSLHostnames), nil
144
144
}
145
145
 
146
146
// copyTools copies a set of tools from the source to the target.
193
193
var Upload UploadFunc = upload
194
194
 
195
195
func upload(stor storage.Storage, forceVersion *version.Number, fakeSeries ...string) (*coretools.Tools, error) {
196
 
        // TODO(rog) find binaries from $PATH when not using a development
197
 
        // version of juju within a $GOPATH.
198
 
 
 
196
        builtTools, err := BuildToolsTarball(forceVersion)
 
197
        if err != nil {
 
198
                return nil, err
 
199
        }
 
200
        defer os.RemoveAll(builtTools.Dir)
199
201
        logger.Debugf("Uploading tools for %v", fakeSeries)
200
 
        // We create the entire archive before asking the environment to
201
 
        // start uploading so that we can be sure we have archived
202
 
        // correctly.
203
 
        f, err := ioutil.TempFile("", "juju-tgz")
204
 
        if err != nil {
205
 
                return nil, err
206
 
        }
207
 
        defer f.Close()
208
 
        defer os.Remove(f.Name())
209
 
        toolsVersion, sha256Hash, err := envtools.BundleTools(f, forceVersion)
210
 
        if err != nil {
211
 
                return nil, err
212
 
        }
213
 
        fileInfo, err := f.Stat()
214
 
        if err != nil {
215
 
                return nil, fmt.Errorf("cannot stat newly made tools archive: %v", err)
216
 
        }
217
 
        size := fileInfo.Size()
218
 
        logger.Infof("built tools %v (%dkB)", toolsVersion, (size+512)/1024)
219
 
        baseToolsDir, err := ioutil.TempDir("", "")
220
 
        if err != nil {
221
 
                return nil, err
222
 
        }
223
 
        defer os.RemoveAll(baseToolsDir)
 
202
        return SyncBuiltTools(stor, builtTools, fakeSeries...)
 
203
}
224
204
 
 
205
// cloneToolsForSeries copies the built tools tarball into a tarball for the specified
 
206
// series and generates corresponding metadata.
 
207
func cloneToolsForSeries(toolsInfo *BuiltTools, series ...string) error {
225
208
        // Copy the tools to the target storage, recording a Tools struct for each one.
226
209
        var targetTools coretools.List
 
210
        targetTools = append(targetTools, &coretools.Tools{
 
211
                Version: toolsInfo.Version,
 
212
                Size:    toolsInfo.Size,
 
213
                SHA256:  toolsInfo.Sha256Hash,
 
214
        })
227
215
        putTools := func(vers version.Binary) (string, error) {
228
216
                name := envtools.StorageName(vers)
229
 
                err = utils.CopyFile(filepath.Join(baseToolsDir, name), f.Name())
 
217
                src := filepath.Join(toolsInfo.Dir, toolsInfo.StorageName)
 
218
                dest := filepath.Join(toolsInfo.Dir, name)
 
219
                err := utils.CopyFile(dest, src)
230
220
                if err != nil {
231
221
                        return "", err
232
222
                }
233
223
                // Append to targetTools the attributes required to write out tools metadata.
234
224
                targetTools = append(targetTools, &coretools.Tools{
235
225
                        Version: vers,
236
 
                        Size:    size,
237
 
                        SHA256:  sha256Hash,
 
226
                        Size:    toolsInfo.Size,
 
227
                        SHA256:  toolsInfo.Sha256Hash,
238
228
                })
239
229
                return name, nil
240
230
        }
241
 
        err = os.MkdirAll(filepath.Join(baseToolsDir, storage.BaseToolsPath, "releases"), 0755)
242
 
        if err != nil {
243
 
                return nil, err
244
 
        }
245
 
        logger.Debugf("generating tarballs for %v", fakeSeries)
246
 
        for _, series := range fakeSeries {
 
231
        logger.Debugf("generating tarballs for %v", series)
 
232
        for _, series := range series {
247
233
                _, err := simplestreams.SeriesVersion(series)
248
234
                if err != nil {
249
 
                        return nil, err
 
235
                        return err
250
236
                }
251
 
                if series != toolsVersion.Series {
252
 
                        fakeVersion := toolsVersion
 
237
                if series != toolsInfo.Version.Series {
 
238
                        fakeVersion := toolsInfo.Version
253
239
                        fakeVersion.Series = series
254
240
                        if _, err := putTools(fakeVersion); err != nil {
255
 
                                return nil, err
 
241
                                return err
256
242
                        }
257
243
                }
258
244
        }
259
 
        name, err := putTools(toolsVersion)
260
 
        if err != nil {
261
 
                return nil, err
262
 
        }
263
245
        // The tools have been copied to a temp location from which they will be uploaded,
264
246
        // now write out the matching simplestreams metadata so that SyncTools can find them.
265
 
        metadataStore, err := filestorage.NewFileStorageWriter(baseToolsDir, filestorage.UseDefaultTmpDir)
 
247
        metadataStore, err := filestorage.NewFileStorageWriter(toolsInfo.Dir)
266
248
        if err != nil {
267
 
                return nil, err
 
249
                return err
268
250
        }
269
251
        logger.Debugf("generating tools metadata")
270
 
        err = envtools.MergeAndWriteMetadata(metadataStore, targetTools, false)
271
 
        if err != nil {
272
 
                return nil, err
273
 
        }
274
 
 
 
252
        return envtools.MergeAndWriteMetadata(metadataStore, targetTools, false)
 
253
}
 
254
 
 
255
// BuiltTools contains metadata for a tools tarball resulting from
 
256
// a call to BundleTools.
 
257
type BuiltTools struct {
 
258
        Version     version.Binary
 
259
        Dir         string
 
260
        StorageName string
 
261
        Sha256Hash  string
 
262
        Size        int64
 
263
}
 
264
 
 
265
// BuildToolsTarballFunc is a function which can build a tools tarball.
 
266
type BuildToolsTarballFunc func(forceVersion *version.Number) (*BuiltTools, error)
 
267
 
 
268
// Override for testing.
 
269
var BuildToolsTarball BuildToolsTarballFunc = buildToolsTarball
 
270
 
 
271
// buildToolsTarball bundles a tools tarball and places it in a temp directory in
 
272
// the expected tools path.
 
273
func buildToolsTarball(forceVersion *version.Number) (builtTools *BuiltTools, err error) {
 
274
        // TODO(rog) find binaries from $PATH when not using a development
 
275
        // version of juju within a $GOPATH.
 
276
 
 
277
        logger.Debugf("Building tools")
 
278
        // We create the entire archive before asking the environment to
 
279
        // start uploading so that we can be sure we have archived
 
280
        // correctly.
 
281
        f, err := ioutil.TempFile("", "juju-tgz")
 
282
        if err != nil {
 
283
                return nil, err
 
284
        }
 
285
        defer f.Close()
 
286
        defer os.Remove(f.Name())
 
287
        toolsVersion, sha256Hash, err := envtools.BundleTools(f, forceVersion)
 
288
        if err != nil {
 
289
                return nil, err
 
290
        }
 
291
        fileInfo, err := f.Stat()
 
292
        if err != nil {
 
293
                return nil, fmt.Errorf("cannot stat newly made tools archive: %v", err)
 
294
        }
 
295
        size := fileInfo.Size()
 
296
        logger.Infof("built tools %v (%dkB)", toolsVersion, (size+512)/1024)
 
297
        baseToolsDir, err := ioutil.TempDir("", "")
 
298
        if err != nil {
 
299
                return nil, err
 
300
        }
 
301
 
 
302
        // If we exit with an error, clean up the built tools directory.
 
303
        defer func() {
 
304
                if err != nil {
 
305
                        os.RemoveAll(baseToolsDir)
 
306
                }
 
307
        }()
 
308
 
 
309
        err = os.MkdirAll(filepath.Join(baseToolsDir, storage.BaseToolsPath, "releases"), 0755)
 
310
        if err != nil {
 
311
                return nil, err
 
312
        }
 
313
        storageName := envtools.StorageName(toolsVersion)
 
314
        err = utils.CopyFile(filepath.Join(baseToolsDir, storageName), f.Name())
 
315
        if err != nil {
 
316
                return nil, err
 
317
        }
 
318
        return &BuiltTools{
 
319
                Version:     toolsVersion,
 
320
                Dir:         baseToolsDir,
 
321
                StorageName: storageName,
 
322
                Size:        size,
 
323
                Sha256Hash:  sha256Hash,
 
324
        }, nil
 
325
}
 
326
 
 
327
// SyncBuiltTools copies to storage a tools tarball and cloned copies for each series.
 
328
func SyncBuiltTools(stor storage.Storage, builtTools *BuiltTools, fakeSeries ...string) (*coretools.Tools, error) {
 
329
        if err := cloneToolsForSeries(builtTools, fakeSeries...); err != nil {
 
330
                return nil, err
 
331
        }
275
332
        syncContext := &SyncContext{
276
 
                Source:       baseToolsDir,
 
333
                Source:       builtTools.Dir,
277
334
                Target:       stor,
278
335
                AllVersions:  true,
279
 
                Dev:          toolsVersion.IsDev(),
280
 
                MajorVersion: toolsVersion.Major,
 
336
                Dev:          builtTools.Version.IsDev(),
 
337
                MajorVersion: builtTools.Version.Major,
281
338
                MinorVersion: -1,
282
339
        }
283
340
        logger.Debugf("uploading tools to cloud storage")
284
 
        err = SyncTools(syncContext)
 
341
        err := SyncTools(syncContext)
285
342
        if err != nil {
286
343
                return nil, err
287
344
        }
288
 
        url, err := stor.URL(name)
 
345
        url, err := stor.URL(builtTools.StorageName)
289
346
        if err != nil {
290
347
                return nil, err
291
348
        }
292
349
        return &coretools.Tools{
293
 
                Version: toolsVersion,
 
350
                Version: builtTools.Version,
294
351
                URL:     url,
295
 
                Size:    size,
296
 
                SHA256:  sha256Hash,
 
352
                Size:    builtTools.Size,
 
353
                SHA256:  builtTools.Sha256Hash,
297
354
        }, nil
298
355
}