...
1
2
3 package main
4
5 import (
6 "fmt"
7 "log"
8 "os"
9 "sync"
10 "time"
11
12 "github.com/Microsoft/hcsshim/internal/uvm"
13 "github.com/Microsoft/hcsshim/internal/winapi"
14 "github.com/sirupsen/logrus"
15 "github.com/urfave/cli"
16 )
17
18 const (
19 cpusArgName = "cpus"
20 memoryArgName = "memory"
21 allowOvercommitArgName = "allow-overcommit"
22 enableDeferredCommitArgName = "enable-deferred-commit"
23 measureArgName = "measure"
24 parallelArgName = "parallel"
25 countArgName = "count"
26
27 execCommandLineArgName = "exec"
28 )
29
30 var (
31 debug bool
32 useGCS bool
33 )
34
35 type uvmRunFunc func(string) error
36
37 func main() {
38 app := cli.NewApp()
39 app.Name = "uvmboot"
40 app.Usage = "Boot a utility VM"
41
42 app.Flags = []cli.Flag{
43 cli.Uint64Flag{
44 Name: cpusArgName,
45 Usage: "Number of CPUs on the UVM. Uses hcsshim default if not specified",
46 },
47 cli.UintFlag{
48 Name: memoryArgName,
49 Usage: "Amount of memory on the UVM, in MB. Uses hcsshim default if not specified",
50 },
51 cli.BoolFlag{
52 Name: measureArgName,
53 Usage: "Measure wall clock time of the UVM run",
54 },
55 cli.IntFlag{
56 Name: parallelArgName,
57 Value: 1,
58 Usage: "Number of UVMs to boot in parallel",
59 },
60 cli.IntFlag{
61 Name: countArgName,
62 Value: 1,
63 Usage: "Total number of UVMs to run",
64 },
65 cli.BoolFlag{
66 Name: allowOvercommitArgName,
67 Usage: "Allow memory overcommit on the UVM",
68 },
69 cli.BoolFlag{
70 Name: enableDeferredCommitArgName,
71 Usage: "Enable deferred commit on the UVM",
72 },
73 cli.BoolFlag{
74 Name: "debug",
75 Usage: "Enable debug information",
76 Destination: &debug,
77 },
78 cli.BoolFlag{
79 Name: "gcs",
80 Usage: "Launch the GCS and perform requested operations via its RPC interface",
81 Destination: &useGCS,
82 },
83 }
84
85 app.Commands = []cli.Command{
86 lcowCommand,
87 wcowCommand,
88 }
89
90 app.Before = func(c *cli.Context) error {
91 if !winapi.IsElevated() {
92 log.Fatal(c.App.Name + " must be run in an elevated context")
93 }
94
95 if debug {
96 logrus.SetLevel(logrus.DebugLevel)
97 } else {
98 logrus.SetLevel(logrus.WarnLevel)
99 }
100
101 return nil
102 }
103
104 if err := app.Run(os.Args); err != nil {
105 logrus.Fatalf("%v\n", err)
106 }
107 }
108
109 func setGlobalOptions(c *cli.Context, options *uvm.Options) {
110 if c.GlobalIsSet(cpusArgName) {
111 options.ProcessorCount = int32(c.GlobalUint64(cpusArgName))
112 }
113 if c.GlobalIsSet(memoryArgName) {
114 options.MemorySizeInMB = c.GlobalUint64(memoryArgName)
115 }
116 if c.GlobalIsSet(allowOvercommitArgName) {
117 options.AllowOvercommit = c.GlobalBool(allowOvercommitArgName)
118 }
119 if c.GlobalIsSet(enableDeferredCommitArgName) {
120 options.EnableDeferredCommit = c.GlobalBool(enableDeferredCommitArgName)
121 }
122 }
123
124
125
126 func runMany(c *cli.Context, runFunc uvmRunFunc) {
127 parallelCount := c.GlobalInt(parallelArgName)
128
129 var wg sync.WaitGroup
130 wg.Add(parallelCount)
131 workChan := make(chan int)
132 for i := 0; i < parallelCount; i++ {
133 go func() {
134 for i := range workChan {
135 id := fmt.Sprintf("uvmboot-%d", i)
136 if err := runFunc(id); err != nil {
137 logrus.WithField("uvm-id", id).WithError(err).Error("failed to run UVM")
138 }
139 }
140 wg.Done()
141 }()
142 }
143
144 start := time.Now()
145 for i := 0; i < c.GlobalInt(countArgName); i++ {
146 workChan <- i
147 }
148
149 close(workChan)
150 wg.Wait()
151 if c.GlobalBool(measureArgName) {
152 fmt.Println("Elapsed time:", time.Since(start))
153 }
154 }
155
156 func unrecognizedError(name, value string) error {
157 return fmt.Errorf("unrecognized value '%s' for option %s", name, value)
158 }
159
View as plain text