github.com/Cloud-Foundations/Dominator@v0.3.4/cmd/imagetool/addImagesub.go (about) 1 package main 2 3 import ( 4 "errors" 5 "fmt" 6 "io" 7 "os" 8 9 "github.com/Cloud-Foundations/Dominator/imageserver/client" 10 "github.com/Cloud-Foundations/Dominator/lib/constants" 11 "github.com/Cloud-Foundations/Dominator/lib/filesystem" 12 "github.com/Cloud-Foundations/Dominator/lib/filter" 13 "github.com/Cloud-Foundations/Dominator/lib/hash" 14 "github.com/Cloud-Foundations/Dominator/lib/image" 15 "github.com/Cloud-Foundations/Dominator/lib/log" 16 objectclient "github.com/Cloud-Foundations/Dominator/lib/objectserver/client" 17 "github.com/Cloud-Foundations/Dominator/lib/srpc" 18 subclient "github.com/Cloud-Foundations/Dominator/sub/client" 19 ) 20 21 func addImagesubSubcommand(args []string, logger log.DebugLogger) error { 22 imageSClient, objectClient := getClients() 23 err := addImagesub(imageSClient, objectClient, args[0], args[1], args[2], 24 args[3], logger) 25 if err != nil { 26 return fmt.Errorf("error adding image: \"%s\": %s", args[0], err) 27 } 28 return nil 29 } 30 31 func addImagesub(imageSClient *srpc.Client, 32 objectClient *objectclient.ObjectClient, 33 name, subName, filterFilename, triggersFilename string, 34 logger log.DebugLogger) error { 35 imageExists, err := client.CheckImage(imageSClient, name) 36 if err != nil { 37 return errors.New("error checking for image existence: " + err.Error()) 38 } 39 if imageExists { 40 return errors.New("image exists") 41 } 42 newImage := new(image.Image) 43 if err := loadImageFiles(newImage, objectClient, filterFilename, 44 triggersFilename); err != nil { 45 return err 46 } 47 fs, err := pollImage(subName) 48 if err != nil { 49 return err 50 } 51 fs = fs.Filter(newImage.Filter) 52 if err := spliceComputedFiles(fs); err != nil { 53 return err 54 } 55 if err := copyMissingObjects(fs, imageSClient, objectClient, 56 subName); err != nil { 57 return err 58 } 59 newImage.FileSystem = fs 60 return addImage(imageSClient, name, newImage, logger) 61 } 62 63 func applyDeleteFilter(fs *filesystem.FileSystem, filt *filter.Filter) ( 64 *filesystem.FileSystem, error) { 65 if *deleteFilter == "" { 66 if filt == nil { 67 return fs, nil 68 } 69 return fs.Filter(filt), nil 70 } 71 filt, err := filter.Load(*deleteFilter) 72 if err != nil { 73 return nil, err 74 } 75 return fs.Filter(filt), nil 76 } 77 78 func copyMissingObjects(fs *filesystem.FileSystem, imageSClient *srpc.Client, 79 objectClient *objectclient.ObjectClient, subName string) error { 80 // Check to see which objects are in the objectserver. 81 hashes := make([]hash.Hash, 0, fs.NumRegularInodes) 82 for hash := range fs.HashToInodesTable() { 83 hashes = append(hashes, hash) 84 } 85 objectSizes, err := objectClient.CheckObjects(hashes) 86 if err != nil { 87 return err 88 } 89 missingHashes := make(map[hash.Hash]struct{}) 90 for index, size := range objectSizes { 91 if size < 1 { 92 missingHashes[hashes[index]] = struct{}{} 93 } 94 } 95 if len(missingHashes) < 1 { 96 return nil 97 } 98 // Get missing objects from sub. 99 filesForMissingObjects := make([]string, 0, len(missingHashes)) 100 hashToFilename := make(map[hash.Hash]string) 101 for hashVal := range missingHashes { 102 if inums, ok := fs.HashToInodesTable()[hashVal]; !ok { 103 return fmt.Errorf("no inode for object: %x", hashVal) 104 } else if files, ok := fs.InodeToFilenamesTable()[inums[0]]; !ok { 105 return fmt.Errorf("no file for inode: %d", inums[0]) 106 } else { 107 filesForMissingObjects = append(filesForMissingObjects, files[0]) 108 hashToFilename[hashVal] = files[0] 109 } 110 } 111 objAdderQueue, err := objectclient.NewObjectAdderQueue(imageSClient) 112 if err != nil { 113 return err 114 } 115 subClient, err := srpc.DialHTTP("tcp", 116 fmt.Sprintf("%s:%d", subName, constants.SubPortNumber), 0) 117 if err != nil { 118 return fmt.Errorf("error dialing %s", err) 119 } 120 defer subClient.Close() 121 err = subclient.GetFiles(subClient, filesForMissingObjects, 122 func(reader io.Reader, size uint64) error { 123 hashVal, err := objAdderQueue.Add(reader, size) 124 if err != nil { 125 return err 126 } 127 delete(missingHashes, hashVal) 128 return nil 129 }) 130 if err != nil { 131 return err 132 } 133 if len(missingHashes) > 0 { 134 for hashVal := range missingHashes { 135 fmt.Fprintf(os.Stderr, "Contents for file changed: %s\n", 136 hashToFilename[hashVal]) 137 } 138 return errors.New("one or more files on the sub changed") 139 } 140 return objAdderQueue.Close() 141 }