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 }