func bundlerNew(bm *BundleManager) *bundler { self := &bundler{bm: bm, wake: sync.NewCond(&sync.Mutex{})} err := bm.BundleStateChangeWatchSet(BundleState_ToBundle, func(user string, bundle_id int, state BundleState) { self.Wakeup() }) if err != nil { log.Printf("Failed to register wakeup callback with the bundle manager.") return nil } go func() { for { found := false ids, err := self.bm.bundleIdsForStateGet(BundleState_ToBundle) if err == nil && ids != nil { for user, list := range ids { for _, id := range list { log.Printf("Got bundles %v %v\n", user, id) bundle_filename := filepath.Join(common.BaseDir, "bundles", "inprogress", strconv.Itoa(id)+".tar") file, err := os.Create(bundle_filename) if err != nil { log.Printf("Could not open temp file. %v", err) continue } file.Close() if common.System { if platform.PlatformGet() == platform.Linux { cmd := exec.Command("setfacl", "-m", "user:"******":rw", bundle_filename) err = cmd.Run() if err != nil { log.Printf("Failed to set acl on bundle. %v\n", err) continue } } else if platform.PlatformGet() == platform.Windows { //TODO - remove or fix so that permissions are set for system user only. /*userstr := common.UserdDefaultUsername() + ":C" err = common.Cacls(bundle_filename, "/p", "NT AUTHORITY\\SYSTEM:f", userstr, "BUILTIN\\Administrators:F") if err != nil { log.Printf("Failed to run cacls %v\n", err) continue }*/ } } err = bundleFiles(bundle_filename, user, id) if err != nil { continue } var newstate BundleState metadata_filename := filepath.Join(common.BaseDir, "bundles", "inprogress", strconv.Itoa(id)+".txt") file, err = os.Create(metadata_filename) if err != nil { log.Printf("Could not open temp file. %v", err) continue } else { err = writeMetadata(self.bm, user, id, file) file.Close() if err != nil { continue } _, _, fe, _, err := common.UserBundleFile(user, bundle_filename, metadata_filename, "metadata.txt") if err != nil || rpc.BundleFileErrorIsError(fe) { log.Printf("Failed to add metadata to bundle. %v", err) continue } newstate = BundleState_ToUpload } if common.System { if platform.PlatformGet() == platform.Linux { cmd := exec.Command("setfacl", "-x", "user:"******"Failed to remove acl on bundle. %v\n", err) continue } } else if platform.PlatformGet() == platform.Windows { err = common.Cacls(bundle_filename, "/p", "NT AUTHORITY\\SYSTEM:f", "BUILTIN\\Administrators:F") if err != nil { log.Printf("Failed to run cacls %v\n", err) continue } } } bundle_new_filename := filepath.Join(common.BaseDir, "bundles", strconv.Itoa(id)+".tar") os.Remove(bundle_new_filename) err = os.Rename(bundle_filename, bundle_new_filename) if err != nil { log.Printf("Failed to rename bundle. %v\n", err) continue } err = bm.bundleStringSet(user, id, "bundle_location", bundle_new_filename) if err != nil { log.Printf("Failed to set bundle location. %v\n", err) continue } err = bm.BundleStateSet(user, id, newstate) if err != nil { log.Printf("Failed to transition bundle from bundling to upload. %v\n", err) continue } found = true } } } if found == false { self.wake.L.Lock() count, err := self.bm.bundleIdsForStateCount(BundleState_ToBundle) if err == nil && count < 1 { self.wake.Wait() } self.wake.L.Unlock() } } }() return self }
func bundleFiles(bundle_filename string, user string, bundle_id int) error { b, err := bm.BundleGet(user, bundle_id) if err != nil { return err } bfs, err := b.FilesGet() if err != nil { log.Printf("Failed to get files from bundle.\n") return nil } for _, bf := range bfs { pacifica_filename, err := bf.PacificaFilenameGet() if err != nil { return err } if strings.HasPrefix(pacifica_filename, "/") { pacifica_filename = pacifica_filename[1:] } local_filename, err := bf.LocalFilenameGet() if err != nil { return err } disable_on_error, err := bf.DisableOnErrorGet() if err != nil { return err } log.Printf("To bundle: %v %v %v\n", bundle_filename, local_filename, pacifica_filename) result, sha1, fe, mtime, err := common.UserBundleFile(user, bundle_filename, local_filename, pacifica_filename) if err != nil { log.Printf("Failed to talk to the userd bundler. %v\n", err) return err } if rpc.BundleFileErrorIsError(fe) { if rpc.BundleFileErrorIsTransient(fe, !disable_on_error) { log.Printf("Transient issue. %v\n", fe) return errors.New("Transient error.") } else if disable_on_error && rpc.BundleFileErrorIsTransientError(fe) { //FIXME better error message. log.Printf("Transient error. %v\n", fe) err = bm.BundleFileStringSet(user, bf.bundle.id, bf.id, "disable_on_error_msg", strconv.Itoa(int(fe))) if err != nil { return err } continue } else if rpc.BundleFileErrorIsPermanentError(fe, !disable_on_error) { log.Printf("Permanent error. %v\n", fe) err = bm.BundleStateSet(user, bundle_id, BundleState_Error) if err != nil { log.Printf("Failed to transition bundle to error state. %v\n", err) return err } err = bm.bundleStringSet(user, bundle_id, "error", "Bundle Error") if err != nil { log.Printf("Failed to set error message. %v\n", err) return err } //FIXME better error message. err = bm.BundleFileStringSet(user, bf.bundle.id, bf.id, "disable_on_error_msg", strconv.Itoa(int(fe))) if err != nil { return err } return errors.New("PermanentError") } } err = bf.Sha1Set(sha1) if err != nil { log.Printf("Failed to set sha1. %v\n", err) return errors.New("Sha1") } err = bf.MtimeSet(mtime) if err != nil { log.Printf("Failed to set mtime. %v\n", err) return errors.New("Mtime") } log.Printf("Got from bundler: %v %v %v\n", fe, result, sha1) } return nil }