github.com/cloud-foundations/dominator@v0.0.0-20221004181915-6e4fee580046/cmd/vm-control/main.go (about)

     1  package main
     2  
     3  import (
     4  	"flag"
     5  	"fmt"
     6  	"net"
     7  	"os"
     8  	"time"
     9  
    10  	"github.com/Cloud-Foundations/Dominator/lib/constants"
    11  	"github.com/Cloud-Foundations/Dominator/lib/flags/commands"
    12  	"github.com/Cloud-Foundations/Dominator/lib/flags/loadflags"
    13  	"github.com/Cloud-Foundations/Dominator/lib/flagutil"
    14  	"github.com/Cloud-Foundations/Dominator/lib/log"
    15  	"github.com/Cloud-Foundations/Dominator/lib/log/cmdlogger"
    16  	"github.com/Cloud-Foundations/Dominator/lib/net/rrdialer"
    17  	"github.com/Cloud-Foundations/Dominator/lib/srpc/setupclient"
    18  	"github.com/Cloud-Foundations/Dominator/lib/tags"
    19  	hyper_proto "github.com/Cloud-Foundations/Dominator/proto/hypervisor"
    20  )
    21  
    22  var (
    23  	adjacentVM = flag.String("adjacentVM", "",
    24  		"IP address of VM adjacent (same Hypervisor) to VM being created")
    25  	consoleType       hyper_proto.ConsoleType
    26  	destroyProtection = flag.Bool("destroyProtection", false,
    27  		"If true, do not destroy running VM")
    28  	disableVirtIO = flag.Bool("disableVirtIO", false,
    29  		"If true, disable virtio drivers, reducing I/O performance")
    30  	dhcpTimeout = flag.Duration("dhcpTimeout", time.Minute,
    31  		"Time to wait before timing out on DHCP request from VM")
    32  	enableNetboot = flag.Bool("enableNetboot", false,
    33  		"If true, enable boot from network for first boot")
    34  	fleetManagerHostname = flag.String("fleetManagerHostname", "",
    35  		"Hostname of Fleet Manager")
    36  	fleetManagerPortNum = flag.Uint("fleetManagerPortNum",
    37  		constants.FleetManagerPortNumber,
    38  		"Port number of Fleet Resource Manager")
    39  	forceIfNotStopped = flag.Bool("forceIfNotStopped", false,
    40  		"If true, snapshot or restore VM even if not stopped")
    41  	hypervisorHostname = flag.String("hypervisorHostname", "",
    42  		"Hostname of hypervisor")
    43  	hypervisorPortNum = flag.Uint("hypervisorPortNum",
    44  		constants.HypervisorPortNumber, "Port number of hypervisor")
    45  	includeUnhealthy = flag.Bool("includeUnhealthy", false,
    46  		"If true, list connected but unhealthy hypervisors")
    47  	imageFile = flag.String("imageFile", "",
    48  		"Name of RAW image file to boot with")
    49  	imageName    = flag.String("imageName", "", "Name of image to boot with")
    50  	imageTimeout = flag.Duration("imageTimeout", time.Minute,
    51  		"Time to wait before timing out on image fetch")
    52  	imageURL = flag.String("imageURL", "",
    53  		"Name of URL of image to boot with")
    54  	localVmCreate = flag.String("localVmCreate", "",
    55  		"Command to make local VM when exporting. The VM name is given as the argument. The VM JSON is available on stdin")
    56  	localVmDestroy = flag.String("localVmDestroy", "",
    57  		"Command to destroy local VM when exporting. The VM name is given as the argument")
    58  	location = flag.String("location", "",
    59  		"Location to search for hypervisors")
    60  	memory       flagutil.Size
    61  	milliCPUs    = flag.Uint("milliCPUs", 0, "milli CPUs (default 250)")
    62  	minFreeBytes = flagutil.Size(256 << 20)
    63  	ownerGroups  flagutil.StringList
    64  	ownerUsers   flagutil.StringList
    65  	probePortNum = flag.Uint("probePortNum", 0, "Port number on VM to probe")
    66  	probeTimeout = flag.Duration("probeTimeout", time.Minute*5,
    67  		"Time to wait before timing out on probing VM port")
    68  	secondarySubnetIDs   flagutil.StringList
    69  	secondaryVolumeSizes flagutil.SizeList
    70  	serialPort           = flag.Uint("serialPort", 0,
    71  		"Serial port number on VM")
    72  	skipBootloader = flag.Bool("skipBootloader", false,
    73  		"If true, directly boot into the kernel")
    74  	subnetId = flag.String("subnetId", "",
    75  		"Subnet ID to launch VM in")
    76  	requestIPs   flagutil.StringList
    77  	roundupPower = flag.Uint64("roundupPower", 28,
    78  		"power of 2 to round up root volume size")
    79  	scanFilename = flag.String("scanFilename", "",
    80  		"Name of file to write scanned VM root to")
    81  	snapshotRootOnly = flag.Bool("snapshotRootOnly", false,
    82  		"If true, snapshot only the root volume")
    83  	traceMetadata = flag.Bool("traceMetadata", false,
    84  		"If true, trace metadata calls until interrupted")
    85  	userDataFile = flag.String("userDataFile", "",
    86  		"Name file containing user-data accessible from the metadata server")
    87  	vmHostname = flag.String("vmHostname", "", "Hostname for VM")
    88  	vmTags     tags.Tags
    89  	vncViewer  = flag.String("vncViewer", defaultVncViewer,
    90  		"Path to VNC viewer")
    91  	volumeFilename = flag.String("volumeFilename", "",
    92  		"Name of file to write volume data to")
    93  	volumeIndex = flag.Uint("volumeIndex", 0,
    94  		"Index of volume to get or delete")
    95  
    96  	logger   log.DebugLogger
    97  	rrDialer *rrdialer.Dialer
    98  )
    99  
   100  func init() {
   101  	flag.Var(&consoleType, "consoleType",
   102  		"type of graphical console (default none)")
   103  	flag.Var(&memory, "memory", "memory (default 1GiB)")
   104  	flag.Var(&minFreeBytes, "minFreeBytes",
   105  		"minimum number of free bytes in root volume")
   106  	flag.Var(&ownerGroups, "ownerGroups", "Groups who own the VM")
   107  	flag.Var(&ownerUsers, "ownerUsers", "Extra users who own the VM")
   108  	flag.Var(&requestIPs, "requestIPs", "Request specific IPs, if available")
   109  	flag.Var(&secondarySubnetIDs, "secondarySubnetIDs", "Secondary Subnet IDs")
   110  	flag.Var(&secondaryVolumeSizes, "secondaryVolumeSizes",
   111  		"Sizes for secondary volumes")
   112  	flag.Var(&vmTags, "vmTags", "Tags to apply to VM")
   113  }
   114  
   115  func printUsage() {
   116  	w := flag.CommandLine.Output()
   117  	fmt.Fprintln(w, "Usage: vm-control [flags...] command [args...]")
   118  	fmt.Fprintln(w, "Common flags:")
   119  	flag.PrintDefaults()
   120  	fmt.Fprintln(w, "Commands:")
   121  	commands.PrintCommands(w, subcommands)
   122  }
   123  
   124  var subcommands = []commands.Command{
   125  	{"add-vm-volumes", "IPaddr", 1, 1, addVmVolumesSubcommand},
   126  	{"become-primary-vm-owner", "IPaddr", 1, 1, becomePrimaryVmOwnerSubcommand},
   127  	{"change-vm-console-type", "IPaddr", 1, 1, changeVmConsoleTypeSubcommand},
   128  	{"change-vm-cpus", "IPaddr", 1, 1, changeVmCPUsSubcommand},
   129  	{"change-vm-destroy-protection", "IPaddr", 1, 1,
   130  		changeVmDestroyProtectionSubcommand},
   131  	{"change-vm-memory", "IPaddr", 1, 1, changeVmMemorySubcommand},
   132  	{"change-vm-owner-users", "IPaddr", 1, 1, changeVmOwnerUsersSubcommand},
   133  	{"change-vm-tags", "IPaddr", 1, 1, changeVmTagsSubcommand},
   134  	{"connect-to-vm-console", "IPaddr", 1, 1, connectToVmConsoleSubcommand},
   135  	{"connect-to-vm-serial-port", "IPaddr", 1, 1,
   136  		connectToVmSerialPortSubcommand},
   137  	{"copy-vm", "IPaddr", 1, 1, copyVmSubcommand},
   138  	{"create-vm", "", 0, 0, createVmSubcommand},
   139  	{"delete-vm-volume", "IPaddr", 1, 1, deleteVmVolumeSubcommand},
   140  	{"destroy-vm", "IPaddr", 1, 1, destroyVmSubcommand},
   141  	{"discard-vm-old-image", "IPaddr", 1, 1, discardVmOldImageSubcommand},
   142  	{"discard-vm-old-user-data", "IPaddr", 1, 1,
   143  		discardVmOldUserDataSubcommand},
   144  	{"discard-vm-snapshot", "IPaddr", 1, 1, discardVmSnapshotSubcommand},
   145  	{"export-local-vm", "IPaddr", 1, 1, exportLocalVmSubcommand},
   146  	{"export-virsh-vm", "IPaddr", 1, 1, exportVirshVmSubcommand},
   147  	{"get-vm-info", "IPaddr", 1, 1, getVmInfoSubcommand},
   148  	{"get-vm-user-data", "IPaddr", 1, 1, getVmUserDataSubcommand},
   149  	{"get-vm-volume", "IPaddr", 1, 1, getVmVolumeSubcommand},
   150  	{"import-local-vm", "info-file root-volume", 2, 2, importLocalVmSubcommand},
   151  	{"import-virsh-vm", "MACaddr domain [[MAC IP]...]", 2, -1,
   152  		importVirshVmSubcommand},
   153  	{"list-hypervisors", "", 0, 0, listHypervisorsSubcommand},
   154  	{"list-locations", "[TopLocation]", 0, 1, listLocationsSubcommand},
   155  	{"list-vms", "", 0, 0, listVMsSubcommand},
   156  	{"migrate-vm", "IPaddr", 1, 1, migrateVmSubcommand},
   157  	{"patch-vm-image", "IPaddr", 1, 1, patchVmImageSubcommand},
   158  	{"probe-vm-port", "IPaddr", 1, 1, probeVmPortSubcommand},
   159  	{"replace-vm-image", "IPaddr", 1, 1, replaceVmImageSubcommand},
   160  	{"replace-vm-user-data", "IPaddr", 1, 1, replaceVmUserDataSubcommand},
   161  	{"restore-vm", "source", 1, 1, restoreVmSubcommand},
   162  	{"restore-vm-from-snapshot", "IPaddr", 1, 1,
   163  		restoreVmFromSnapshotSubcommand},
   164  	{"restore-vm-image", "IPaddr", 1, 1, restoreVmImageSubcommand},
   165  	{"restore-vm-user-data", "IPaddr", 1, 1, restoreVmUserDataSubcommand},
   166  	{"set-vm-migrating", "IPaddr", 1, 1, setVmMigratingSubcommand},
   167  	{"snapshot-vm", "IPaddr", 1, 1, snapshotVmSubcommand},
   168  	{"save-vm", "IPaddr destination", 2, 2, saveVmSubcommand},
   169  	{"scan-vm-root", "IPaddr", 1, 1, scanVmRootSubcommand},
   170  	{"start-vm", "IPaddr", 1, 1, startVmSubcommand},
   171  	{"stop-vm", "IPaddr", 1, 1, stopVmSubcommand},
   172  	{"trace-vm-metadata", "IPaddr", 1, 1, traceVmMetadataSubcommand},
   173  	{"unset-vm-migrating", "IPaddr", 1, 1, unsetVmMigratingSubcommand},
   174  }
   175  
   176  func doMain() int {
   177  	if err := loadflags.LoadForCli("vm-control"); err != nil {
   178  		fmt.Fprintln(os.Stderr, err)
   179  		return 1
   180  	}
   181  	flag.Usage = printUsage
   182  	flag.Parse()
   183  	if flag.NArg() < 1 {
   184  		printUsage()
   185  		return 2
   186  	}
   187  	if memory > 0 && memory < 1<<20 {
   188  		fmt.Fprintf(os.Stderr, "unreasonably small memory: %s\n",
   189  			memory.String())
   190  		return 3
   191  	}
   192  	logger = cmdlogger.New()
   193  	if err := setupclient.SetupTls(false); err != nil {
   194  		fmt.Fprintln(os.Stderr, err)
   195  		return 1
   196  	}
   197  	var err error
   198  	rrDialer, err = rrdialer.New(&net.Dialer{Timeout: time.Second * 10}, "",
   199  		logger)
   200  	if err != nil {
   201  		fmt.Fprintln(os.Stderr, err)
   202  		return 1
   203  	}
   204  	defer rrDialer.WaitForBackgroundResults(time.Second)
   205  	return commands.RunCommands(subcommands, printUsage, logger)
   206  }
   207  
   208  func main() {
   209  	os.Exit(doMain())
   210  }