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  }