Skip to content

Commit 0fd9825

Browse files
committed
Adding support for capturing fifo logs to file.
If Config.LogFifo and Config.MetricsFifo have been set, this will write the contents of the fifo queues to the given paths with ".log" appended to the path.
1 parent 6b08ec7 commit 0fd9825

File tree

4 files changed

+323
-93
lines changed

4 files changed

+323
-93
lines changed

cmd/firectl/main.go

Lines changed: 20 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ type options struct {
117117
FcLogFifo string `long:"vmm-log-fifo" description:"FIFO for firecracker logs"`
118118
FcLogLevel string `long:"log-level" description:"vmm log level" default:"Debug"`
119119
FcMetricsFifo string `long:"metrics-fifo" description:"FIFO for firecracker metrics"`
120+
FcCaptureFifoLogs bool `long:"capture-fifo-logs" description:"pipes fifo and metric fifo's contents to files"`
120121
FcDisableHt bool `long:"disable-hyperthreading" short:"t" description:"Disable CPU Hyperthreading"`
121122
FcCPUCount int64 `long:"ncpus" short:"c" description:"Number of CPUs" default:"1"`
122123
FcCPUTemplate string `long:"cpu-template" description:"Firecracker CPU Template (C3 or T2)"`
@@ -189,22 +190,23 @@ func main() {
189190
}
190191

191192
fcCfg := firecracker.Config{
192-
SocketPath: "./firecracker.sock",
193-
LogFifo: opts.FcLogFifo,
194-
LogLevel: opts.FcLogLevel,
195-
MetricsFifo: opts.FcMetricsFifo,
196-
KernelImagePath: opts.FcKernelImage,
197-
KernelArgs: opts.FcKernelCmdLine,
198-
RootDrive: rootDrive,
199-
RootPartitionUUID: opts.FcRootPartUUID,
200-
AdditionalDrives: blockDevices,
201-
NetworkInterfaces: NICs,
202-
VsockDevices: vsocks,
203-
CPUCount: opts.FcCPUCount,
204-
CPUTemplate: firecracker.CPUTemplate(opts.FcCPUTemplate),
205-
HtEnabled: !opts.FcDisableHt,
206-
MemInMiB: opts.FcMemSz,
207-
Debug: opts.Debug,
193+
SocketPath: "./firecracker.sock",
194+
LogFifo: opts.FcLogFifo,
195+
LogLevel: opts.FcLogLevel,
196+
MetricsFifo: opts.FcMetricsFifo,
197+
CaptureFifoLogsToFile: opts.FcCaptureFifoLogs,
198+
KernelImagePath: opts.FcKernelImage,
199+
KernelArgs: opts.FcKernelCmdLine,
200+
RootDrive: rootDrive,
201+
RootPartitionUUID: opts.FcRootPartUUID,
202+
AdditionalDrives: blockDevices,
203+
NetworkInterfaces: NICs,
204+
VsockDevices: vsocks,
205+
CPUCount: opts.FcCPUCount,
206+
CPUTemplate: firecracker.CPUTemplate(opts.FcCPUTemplate),
207+
HtEnabled: !opts.FcDisableHt,
208+
MemInMiB: opts.FcMemSz,
209+
Debug: opts.Debug,
208210
}
209211

210212
if len(os.Args) == 1 {
@@ -252,8 +254,7 @@ func main() {
252254
log.Fatalf("Failed creating machine: %s", err)
253255
}
254256

255-
errCh, err := m.Init(vmmCtx)
256-
if err != nil {
257+
if err := m.Init(vmmCtx); err != nil {
257258
log.Fatalf("Firecracker Init returned error %s", err)
258259
}
259260

@@ -269,7 +270,7 @@ func main() {
269270
}
270271

271272
// wait for the VMM to exit
272-
if err := <-errCh; err != nil {
273+
if err := <-m.ErrCh; err != nil {
273274
log.Fatalf("startVMM returned error %s", err)
274275
}
275276
log.Printf("startVMM was happy")

handlers.go

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
package firecracker
2+
3+
import (
4+
"context"
5+
"fmt"
6+
)
7+
8+
// Handler name constants
9+
const (
10+
StartVMMHandlerName = "StartVMM"
11+
BootstrapLoggingHandlerName = "BootstrapLogging"
12+
CreateMachineHandlerName = "CreateMachine"
13+
CreateBootSourceHandlerName = "CreateBootSource"
14+
AttachDrivesHandlerName = "AttachDrives"
15+
CreateNetworkInterfacesHandlerName = "CreateNetworkInterfaces"
16+
AddVsocksHandlerName = "AddVsocks"
17+
)
18+
19+
// StartVMMNamedHandler .
20+
var StartVMMNamedHandler = NamedHandler{
21+
Name: StartVMMHandlerName,
22+
Fn: func(ctx context.Context, m *Machine) error {
23+
m.logger.Debugf(fmt.Sprintf("%s handler executing", StartVMMHandlerName))
24+
return m.startVMM(ctx)
25+
},
26+
}
27+
28+
// BootstrapLoggingNamedHandler .
29+
var BootstrapLoggingNamedHandler = NamedHandler{
30+
Name: BootstrapLoggingHandlerName,
31+
Fn: func(ctx context.Context, m *Machine) error {
32+
m.logger.Debugf(fmt.Sprintf("%s handler executing", BootstrapLoggingHandlerName))
33+
if err := m.setupLogging(ctx); err != nil {
34+
m.logger.Warnf("setupLogging() returned %s. Continuing anyway.", err)
35+
} else {
36+
m.logger.Debugf("back from setupLogging")
37+
}
38+
39+
return nil
40+
},
41+
}
42+
43+
// CreateMachineNamedHandler .
44+
var CreateMachineNamedHandler = NamedHandler{
45+
Name: CreateMachineHandlerName,
46+
Fn: func(ctx context.Context, m *Machine) error {
47+
m.logger.Debugf(fmt.Sprintf("%s handler executing", CreateMachineHandlerName))
48+
return m.createMachine(ctx)
49+
},
50+
}
51+
52+
// CreateBootSourceNamedHandler .
53+
var CreateBootSourceNamedHandler = NamedHandler{
54+
Name: CreateBootSourceHandlerName,
55+
Fn: func(ctx context.Context, m *Machine) error {
56+
m.logger.Debugf(fmt.Sprintf("%s handler executing", CreateBootSourceHandlerName))
57+
return m.createBootSource(ctx, m.cfg.KernelImagePath, m.cfg.KernelArgs)
58+
},
59+
}
60+
61+
// AttachDrivesNamedHandler .
62+
var AttachDrivesNamedHandler = NamedHandler{
63+
Name: AttachDrivesHandlerName,
64+
Fn: func(ctx context.Context, m *Machine) error {
65+
m.logger.Debugf(fmt.Sprintf("%s handler executing", AttachDrivesHandlerName))
66+
drives := append([]BlockDevice{m.cfg.RootDrive}, m.cfg.AdditionalDrives...)
67+
rootIndex := 0
68+
69+
return m.attachDrives(ctx, rootIndex, drives...)
70+
},
71+
}
72+
73+
// CreateNetworkInterfacesNamedHandler .
74+
var CreateNetworkInterfacesNamedHandler = NamedHandler{
75+
Name: CreateNetworkInterfacesHandlerName,
76+
Fn: func(ctx context.Context, m *Machine) error {
77+
m.logger.Debugf(fmt.Sprintf("%s handler executing", CreateNetworkInterfacesHandlerName))
78+
return m.createNetworkInterfaces(ctx, m.cfg.NetworkInterfaces...)
79+
},
80+
}
81+
82+
// AddVsocksNamedHandler .
83+
var AddVsocksNamedHandler = NamedHandler{
84+
Name: AddVsocksHandlerName,
85+
Fn: func(ctx context.Context, m *Machine) error {
86+
m.logger.Debugf(fmt.Sprintf("%s handler executing", AddVsocksHandlerName))
87+
return m.addVsocks(ctx, m.cfg.VsockDevices...)
88+
},
89+
}
90+
91+
var defaultHandlerList = HandlerList{}.Append(
92+
StartVMMNamedHandler,
93+
BootstrapLoggingNamedHandler,
94+
CreateMachineNamedHandler,
95+
CreateBootSourceNamedHandler,
96+
AttachDrivesNamedHandler,
97+
CreateNetworkInterfacesNamedHandler,
98+
AddVsocksNamedHandler,
99+
)
100+
101+
// HandlerList represents a list of named handler that
102+
// can be used to execute a flow of instructions for a given
103+
// machine.
104+
type HandlerList struct {
105+
list []NamedHandler
106+
}
107+
108+
// Append will append a new handler to the handler list.
109+
func (l HandlerList) Append(handlers ...NamedHandler) HandlerList {
110+
l.list = append(l.list, handlers...)
111+
112+
return l
113+
}
114+
115+
// Remove will return an updated handler with all instances
116+
// of the specific named handler being removed.
117+
func (l HandlerList) Remove(name string) HandlerList {
118+
newList := HandlerList{}
119+
for _, h := range l.list {
120+
if h.Name != name {
121+
newList.list = append(newList.list, h)
122+
}
123+
}
124+
125+
return newList
126+
}
127+
128+
// Clear clears the whole list of handlers
129+
func (l HandlerList) Clear() HandlerList {
130+
l.list = l.list[0:0]
131+
return l
132+
}
133+
134+
// NamedHandler represents a named handler that contains a
135+
// name and a function which is used to execute during
136+
// the initialization process of a machine.
137+
type NamedHandler struct {
138+
Name string
139+
Fn func(context.Context, *Machine) error
140+
}
141+
142+
// Run will execute each instruction in the handler list. If an
143+
// error occurs in any of the handlers, then the list will halt
144+
// execution and return the error.
145+
func (l HandlerList) Run(ctx context.Context, m *Machine) error {
146+
for _, handler := range l.list {
147+
if err := handler.Fn(ctx, m); err != nil {
148+
return err
149+
}
150+
}
151+
152+
return nil
153+
}

0 commit comments

Comments
 (0)