1
2
3 package main
4
5 import (
6 "context"
7 "errors"
8 "fmt"
9 "os"
10 "strings"
11 "time"
12
13 "github.com/Microsoft/go-winio/pkg/etw"
14 "github.com/Microsoft/go-winio/pkg/etwlogrus"
15 "github.com/Microsoft/go-winio/pkg/guid"
16 "github.com/Microsoft/hcsshim/internal/log"
17 "github.com/Microsoft/hcsshim/internal/oc"
18 "github.com/Microsoft/hcsshim/internal/shimdiag"
19 specs "github.com/opencontainers/runtime-spec/specs-go"
20 "github.com/sirupsen/logrus"
21 "github.com/urfave/cli"
22 "go.opencensus.io/trace"
23 )
24
25 const usage = ``
26 const ttrpcAddressEnv = "TTRPC_ADDRESS"
27
28
29
30
31
32
33 var version = ""
34
35
36
37 var gitCommit = ""
38
39 var (
40 namespaceFlag string
41 addressFlag string
42 containerdBinaryFlag string
43
44 idFlag string
45
46
47 gracefulShutdownTimeout = 3 * time.Second
48 )
49
50 func etwCallback(sourceID guid.GUID, state etw.ProviderState, level etw.Level, matchAnyKeyword uint64, matchAllKeyword uint64, filterData uintptr) {
51 if state == etw.ProviderStateCaptureState {
52 resp, err := svc.DiagStacks(context.Background(), &shimdiag.StacksRequest{})
53 if err != nil {
54 return
55 }
56 log := logrus.WithField("tid", svc.tid)
57 log.WithField("stack", resp.Stacks).Info("goroutine stack dump")
58 if resp.GuestStacks != "" {
59 log.WithField("stack", resp.GuestStacks).Info("guest stack dump")
60 }
61 }
62 }
63
64 func main() {
65 logrus.AddHook(log.NewHook())
66
67
68
69 provider, err := etw.NewProvider("Microsoft.Virtualization.RunHCS", etwCallback)
70 if err != nil {
71 logrus.Error(err)
72 } else {
73 if hook, err := etwlogrus.NewHookFromProvider(provider); err == nil {
74 logrus.AddHook(hook)
75 } else {
76 logrus.Error(err)
77 }
78 }
79
80 _ = provider.WriteEvent(
81 "ShimLaunched",
82 nil,
83 etw.WithFields(
84 etw.StringArray("Args", os.Args),
85 ),
86 )
87
88
89 trace.ApplyConfig(trace.Config{DefaultSampler: oc.DefaultSampler})
90 trace.RegisterExporter(&oc.LogrusExporter{})
91
92 app := cli.NewApp()
93 app.Name = "containerd-shim-runhcs-v1"
94 app.Usage = usage
95
96 var v []string
97 if version != "" {
98 v = append(v, version)
99 }
100 if gitCommit != "" {
101 v = append(v, fmt.Sprintf("commit: %s", gitCommit))
102 }
103 v = append(v, fmt.Sprintf("spec: %s", specs.Version))
104 app.Version = strings.Join(v, "\n")
105
106 app.Flags = []cli.Flag{
107 cli.StringFlag{
108 Name: "namespace",
109 Usage: "the namespace of the container",
110 },
111 cli.StringFlag{
112 Name: "address",
113 Usage: "the address of the containerd's main socket",
114 },
115 cli.StringFlag{
116 Name: "publish-binary",
117 Usage: "the binary path to publish events back to containerd",
118 },
119 cli.StringFlag{
120 Name: "id",
121 Usage: "the id of the container",
122 },
123 cli.StringFlag{
124 Name: "bundle",
125 Usage: "the bundle path to delete (delete command only).",
126 },
127 cli.BoolFlag{
128 Name: "debug",
129 Usage: "run the shim in debug mode",
130 },
131 }
132 app.Commands = []cli.Command{
133 startCommand,
134 deleteCommand,
135 serveCommand,
136 }
137 app.Before = func(context *cli.Context) error {
138 if namespaceFlag = context.GlobalString("namespace"); namespaceFlag == "" {
139 return errors.New("namespace is required")
140 }
141 if addressFlag = context.GlobalString("address"); addressFlag == "" {
142 return errors.New("address is required")
143 }
144 if containerdBinaryFlag = context.GlobalString("publish-binary"); containerdBinaryFlag == "" {
145 return errors.New("publish-binary is required")
146 }
147 if idFlag = context.GlobalString("id"); idFlag == "" {
148 return errors.New("id is required")
149 }
150 return nil
151 }
152
153 if err := app.Run(os.Args); err != nil {
154 fmt.Fprintln(cli.ErrWriter, err)
155 os.Exit(1)
156 }
157 }
158
View as plain text