github.com/Cloud-Foundations/Dominator@v0.3.4/cmd/imagetool/main.go (about)

     1  package main
     2  
     3  import (
     4  	"flag"
     5  	"fmt"
     6  	"os"
     7  	"time"
     8  
     9  	"github.com/Cloud-Foundations/Dominator/lib/constants"
    10  	"github.com/Cloud-Foundations/Dominator/lib/filesystem"
    11  	"github.com/Cloud-Foundations/Dominator/lib/filter"
    12  	"github.com/Cloud-Foundations/Dominator/lib/flags/commands"
    13  	"github.com/Cloud-Foundations/Dominator/lib/flags/loadflags"
    14  	"github.com/Cloud-Foundations/Dominator/lib/flagutil"
    15  	"github.com/Cloud-Foundations/Dominator/lib/log"
    16  	"github.com/Cloud-Foundations/Dominator/lib/log/cmdlogger"
    17  	"github.com/Cloud-Foundations/Dominator/lib/mbr"
    18  	objectclient "github.com/Cloud-Foundations/Dominator/lib/objectserver/client"
    19  	"github.com/Cloud-Foundations/Dominator/lib/srpc"
    20  	"github.com/Cloud-Foundations/Dominator/lib/srpc/setupclient"
    21  	"github.com/Cloud-Foundations/Dominator/lib/tags"
    22  )
    23  
    24  var (
    25  	allocateBlocks = flag.Bool("allocateBlocks", false,
    26  		"If true, allocate blocks when making raw image")
    27  	buildCommitId = flag.String("buildCommitId", "",
    28  		"build Commit Id to match when finding latest image")
    29  	buildLog = flag.String("buildLog", "",
    30  		"Filename or URL containing build log")
    31  	compress      = flag.Bool("compress", false, "If true, compress tar output")
    32  	computedFiles = flag.String("computedFiles", "",
    33  		"Name of file containing computed files list")
    34  	computedFilesRoot = flag.String("computedFilesRoot", "",
    35  		"Name of directory tree containing computed files to replace on unpack")
    36  	copyMtimesFrom = flag.String("copyMtimesFrom", "",
    37  		"Name of image to copy mtimes for otherwise unchanged files/devices")
    38  	debug = flag.Bool("debug", false,
    39  		"If true, show debugging output")
    40  	deleteFilter = flag.String("deleteFilter", "",
    41  		"Name of delete filter file for addi, adds and diff subcommands")
    42  	expiresIn = flag.Duration("expiresIn", 0,
    43  		"How long before the image expires (auto deletes). Default: never")
    44  	filterFile = flag.String("filterFile", "",
    45  		"Filter file to apply when adding images")
    46  	fleetManagerHostname = flag.String("fleetManagerHostname", "",
    47  		"Hostname of Fleet Manager (to find VM to scan)")
    48  	fleetManagerPortNum = flag.Uint("fleetManagerPortNum",
    49  		constants.FleetManagerPortNumber, "Port number of Fleet Manager")
    50  	hypervisorHostname = flag.String("hypervisorHostname", "",
    51  		"Hostname of hypervisor (for VM to scan)")
    52  	hypervisorPortNum = flag.Uint("hypervisorPortNum",
    53  		constants.HypervisorPortNumber, "Port number of hypervisor")
    54  	ignoreExpiring = flag.Bool("ignoreExpiring", false,
    55  		"If true, ignore expiring images when finding images")
    56  	ignoreFilters = flag.Bool("ignoreFilters", false,
    57  		"If true, ignore filters when diffing")
    58  	imageServerHostname = flag.String("imageServerHostname", "localhost",
    59  		"Hostname of image server")
    60  	imageServerPortNum = flag.Uint("imageServerPortNum",
    61  		constants.ImageServerPortNumber,
    62  		"Port number of image server")
    63  	makeBootable = flag.Bool("makeBootable", true,
    64  		"If true, make raw image bootable by installing GRUB")
    65  	masterImageServerHostname = flag.String("masterImageServerHostname", "",
    66  		"Hostname of master image server (if different)")
    67  	mdbServerHostname = flag.String("mdbServerHostname", "localhost",
    68  		"Hostname of MDB server")
    69  	mdbServerPortNum = flag.Uint("mdbServerPortNum",
    70  		constants.SimpleMdbServerPortNumber,
    71  		"Port number of MDB server")
    72  	minFreeBytes = flag.Uint64("minFreeBytes", 4<<20,
    73  		"minimum number of free bytes in raw image")
    74  	overlayDirectory = flag.String("overlayDirectory", "",
    75  		"Directory tree of files to overlay on top of the image when making raw image")
    76  	releaseNotes = flag.String("releaseNotes", "",
    77  		"Filename or URL containing release notes")
    78  	requiredPaths = flagutil.StringToRuneMap(constants.RequiredPaths)
    79  	rootLabel     = flag.String("rootLabel", "",
    80  		"Label to write for root file-system when making raw image")
    81  	roundupPower = flag.Uint64("roundupPower", 24,
    82  		"power of 2 to round up raw image size")
    83  	scanExcludeList flagutil.StringList = constants.ScanExcludeList
    84  	skipFields                          = flag.String("skipFields", "",
    85  		"Fields to skip when showing or diffing images")
    86  	tableType   mbr.TableType = mbr.TABLE_TYPE_MSDOS
    87  	tagsToMatch tags.MatchTags
    88  	timeout     = flag.Duration("timeout", 0,
    89  		"Timeout for get subcommand")
    90  
    91  	logger            log.DebugLogger
    92  	minimumExpiration = 15 * time.Minute
    93  )
    94  
    95  func init() {
    96  	flag.Var(&requiredPaths, "requiredPaths",
    97  		"Comma separated list of required path:type entries")
    98  	flag.Var(&scanExcludeList, "scanExcludeList",
    99  		"Comma separated list of patterns to exclude from scanning")
   100  	flag.Var(&tableType, "tableType", "partition table type for make-raw-image")
   101  	flag.Var(&tagsToMatch, "tagsToMatch", "Tags to match when finding/listing")
   102  }
   103  
   104  func printUsage() {
   105  	w := flag.CommandLine.Output()
   106  	fmt.Fprintln(w,
   107  		"Usage: imagetool [flags...] add|check|delete|list [args...]")
   108  	fmt.Fprintln(w, "Common flags:")
   109  	flag.PrintDefaults()
   110  	fmt.Fprintln(w, "Commands:")
   111  	commands.PrintCommands(w, subcommands)
   112  	fmt.Fprintln(w, "Images can be specified as name:type. Supported types:")
   113  	fmt.Fprintln(w, "  d: name of directory tree to scan")
   114  	fmt.Fprintln(w, "  f: name of file containing a FileSystem")
   115  	fmt.Fprintln(w, "  i: name of an image on the imageserver")
   116  	fmt.Fprintln(w, "  I: name of an image stream on the imageserver (latest)")
   117  	fmt.Fprintln(w, "  l: name of file containing an Image")
   118  	fmt.Fprintln(w, "  s: name of sub to poll")
   119  	fmt.Fprintln(w, "  v: hostname/IP of SmallStack VM to scan")
   120  	fmt.Fprintln(w, "SkipFields:")
   121  	fmt.Fprintln(w, "  m: mode")
   122  	fmt.Fprintln(w, "  l: number of hardlinks")
   123  	fmt.Fprintln(w, "  u: UID")
   124  	fmt.Fprintln(w, "  g: GID")
   125  	fmt.Fprintln(w, "  s: size/Rdev")
   126  	fmt.Fprintln(w, "  t: time of last modification")
   127  	fmt.Fprintln(w, "  n: name")
   128  	fmt.Fprintln(w, "  d: data (hash or symlink target)")
   129  }
   130  
   131  var subcommands = []commands.Command{
   132  	{"add", "                    name imagefile filterfile triggerfile", 4, 4,
   133  		addImagefileSubcommand},
   134  	{"addi", "                   name imagename filterfile triggerfile", 4, 4,
   135  		addImageimageSubcommand},
   136  	{"addrep", "                 name baseimage layerimage...", 3, -1,
   137  		addReplaceImageSubcommand},
   138  	{"adds", "                   name subname filterfile triggerfile", 4, 4,
   139  		addImagesubSubcommand},
   140  	{"bulk-addrep", "            layerimage...", 1, -1,
   141  		bulkAddReplaceImagesSubcommand},
   142  	{"change-image-expiration", "name", 1, 1, changeImageExpirationSubcommand},
   143  	{"check", "                  name", 1, 1, checkImageSubcommand},
   144  	{"check-directory", "        dirname", 1, 1, checkDirectorySubcommand},
   145  	{"chown", "                  dirname ownerGroup", 2, 2,
   146  		chownDirectorySubcommand},
   147  	{"copy", "                   name oldimagename", 2, 2, copyImageSubcommand},
   148  	{"copy-filtered-files", "    name srcdir destdir", 3, 3,
   149  		copyFilteredFilesSubcommand},
   150  	{"delete", "                 name", 1, 1, deleteImageSubcommand},
   151  	{"delunrefobj", "            percentage bytes", 2, 2,
   152  		deleteUnreferencedObjectsSubcommand},
   153  	{"diff", "                   tool left right", 3, 3, diffSubcommand},
   154  	{"diff-build-logs", "        tool left right", 3, 3,
   155  		diffBuildLogsInImagesSubcommand},
   156  	{"diff-files", "             tool left right filename", 4, 4,
   157  		diffFileInImagesSubcommand},
   158  	{"diff-filters", "           tool left right", 3, 3,
   159  		diffFilterInImagesSubcommand},
   160  	{"diff-package-lists", "     tool left right", 3, 3,
   161  		diffImagePackageListsSubcommand},
   162  	{"diff-triggers", "          tool left right", 3, 3,
   163  		diffTriggersInImagesSubcommand},
   164  	{"estimate-usage", "         name", 1, 1, estimateImageUsageSubcommand},
   165  	{"find-latest-image", "      directory", 1, 1, findLatestImageSubcommand},
   166  	{"get", "                    name directory", 2, 2, getImageSubcommand},
   167  	{"get-archive-data", "       name outfile", 2, 2,
   168  		getImageArchiveDataSubcommand},
   169  	{"get-build-log", "          name [outfile]", 1, 2,
   170  		getImageBuildLogSubcommand},
   171  	{"get-file-in-image", "      name imageFile [outfile]", 2, 3,
   172  		getFileInImageSubcommand},
   173  	{"get-image-expiration", "   name", 1, 1, getImageExpirationSubcommand},
   174  	{"get-image-updates", "", 0, 0, getImageUpdatesSubcommand},
   175  	{"get-package-list", "       name [outfile]", 1, 2,
   176  		getImagePackageListSubcommand},
   177  	{"get-replication-master", "", 0, 0, getReplicationMasterSubcommand},
   178  	{"list", "", 0, 0, listImagesSubcommand},
   179  	{"listdirs", "", 0, 0, listDirectoriesSubcommand},
   180  	{"listunrefobj", "", 0, 0, listUnreferencedObjectsSubcommand},
   181  	{"list-mdb", "", 0, 0, listMdbImagesSubcommand},
   182  	{"list-not-in-mdb", "", 0, 0, listImagesNotInMdbSubcommand},
   183  	{"make-raw-image", "         name rawfile", 2, 2, makeRawImageSubcommand},
   184  	{"match-triggers", "         name triggers-file", 2, 2,
   185  		matchTriggersSubcommand},
   186  	{"merge-filters", "          filter-file...", 1, -1, mergeFiltersSubcommand},
   187  	{"merge-triggers", "         triggers-file...", 1, -1,
   188  		mergeTriggersSubcommand},
   189  	{"mkdir", "                  name", 1, 1, makeDirectorySubcommand},
   190  	{"patch-directory", "        name directory", 2, 2,
   191  		patchDirectorySubcommand},
   192  	{"scan-filtered-files", "    name directory", 2, 2,
   193  		scanFilteredFilesSubcommand},
   194  	{"show", "                   name", 1, 1, showImageSubcommand},
   195  	{"show-filter", "            name", 1, 1, showImageFilterSubcommand},
   196  	{"show-inode", "             name inodePath", 2, 2,
   197  		showImageInodeSubcommand},
   198  	{"show-metadata", "          name", 1, 1, showImageMetadataSubcommand},
   199  	{"show-triggers", "          name", 1, 1, showImageTriggersSubcommand},
   200  	{"showunrefobj", "", 0, 0, showUnreferencedObjectsSubcommand},
   201  	{"tar", "                    name [file]", 1, 2, tarImageSubcommand},
   202  	{"test-download-speed", "    name", 1, 1, testDownloadSpeedSubcommand},
   203  	{"trace-inode-history", "    name inodePath", 2, 2,
   204  		traceInodeHistorySubcommand},
   205  }
   206  
   207  var (
   208  	imageSrpcClient       *srpc.Client
   209  	masterImageSrpcClient *srpc.Client
   210  	theObjectClient       *objectclient.ObjectClient
   211  	theMasterObjectClient *objectclient.ObjectClient
   212  
   213  	listSelector filesystem.ListSelector
   214  )
   215  
   216  func getClients() (*srpc.Client, *objectclient.ObjectClient) {
   217  	getPointedClients(*imageServerHostname, &imageSrpcClient, &theObjectClient)
   218  	return imageSrpcClient, theObjectClient
   219  }
   220  
   221  func getMasterClients() (*srpc.Client, *objectclient.ObjectClient) {
   222  	if *masterImageServerHostname == "" {
   223  		return getClients()
   224  	}
   225  	getPointedClients(*masterImageServerHostname,
   226  		&masterImageSrpcClient, &theMasterObjectClient)
   227  	return masterImageSrpcClient, theMasterObjectClient
   228  }
   229  
   230  func getPointedClients(hostname string, iClient **srpc.Client,
   231  	oClient **objectclient.ObjectClient) {
   232  	if *iClient == nil {
   233  		var err error
   234  		clientName := fmt.Sprintf("%s:%d", hostname, *imageServerPortNum)
   235  		*iClient, err = srpc.DialHTTP("tcp", clientName, 0)
   236  		if err != nil {
   237  			fmt.Fprintf(os.Stderr, "Error dialing: %s: %s\n", clientName, err)
   238  			os.Exit(1)
   239  		}
   240  		*oClient = objectclient.AttachObjectClient(imageSrpcClient)
   241  	}
   242  }
   243  
   244  func makeListSelector(arg string) filesystem.ListSelector {
   245  	var mask filesystem.ListSelector = filesystem.ListSelectAll
   246  	for _, char := range arg {
   247  		switch char {
   248  		case 'm':
   249  			mask |= filesystem.ListSelectSkipMode
   250  		case 'l':
   251  			mask |= filesystem.ListSelectSkipNumLinks
   252  		case 'u':
   253  			mask |= filesystem.ListSelectSkipUid
   254  		case 'g':
   255  			mask |= filesystem.ListSelectSkipGid
   256  		case 's':
   257  			mask |= filesystem.ListSelectSkipSizeDevnum
   258  		case 't':
   259  			mask |= filesystem.ListSelectSkipMtime
   260  		case 'n':
   261  			mask |= filesystem.ListSelectSkipName
   262  		case 'd':
   263  			mask |= filesystem.ListSelectSkipData
   264  		}
   265  	}
   266  	return mask
   267  }
   268  
   269  var listFilter *filter.Filter
   270  
   271  func doMain() int {
   272  	if err := loadflags.LoadForCli("imagetool"); err != nil {
   273  		fmt.Fprintln(os.Stderr, err)
   274  		return 1
   275  	}
   276  	flag.Usage = printUsage
   277  	flag.Parse()
   278  	if flag.NArg() < 1 {
   279  		printUsage()
   280  		return 2
   281  	}
   282  	logger = cmdlogger.New()
   283  	srpc.SetDefaultLogger(logger)
   284  	if *expiresIn > 0 && *expiresIn < minimumExpiration {
   285  		fmt.Fprintf(os.Stderr, "Minimum expiration: %s\n", minimumExpiration)
   286  		return 2
   287  	}
   288  	listSelector = makeListSelector(*skipFields)
   289  	var err error
   290  	if *filterFile != "" {
   291  		listFilter, err = filter.Load(*filterFile)
   292  		if err != nil {
   293  			fmt.Fprintln(os.Stderr, err)
   294  			return 2
   295  		}
   296  	}
   297  	if err := setupclient.SetupTls(true); err != nil {
   298  		fmt.Fprintln(os.Stderr, err)
   299  		return 1
   300  	}
   301  	return commands.RunCommands(subcommands, printUsage, logger)
   302  }
   303  
   304  func main() {
   305  	os.Exit(doMain())
   306  }