@@ -35,6 +35,10 @@ import (
35
35
"github.com/firecracker-microvm/firecracker-containerd/internal/vm"
36
36
)
37
37
38
+ const (
39
+ networkNamespaceRuncName = "network"
40
+ )
41
+
38
42
// runcJailer uses runc to set up a jailed environment for the Firecracker VM.
39
43
type runcJailer struct {
40
44
ctx context.Context
@@ -46,6 +50,7 @@ type runcJailer struct {
46
50
runcBinaryPath string
47
51
uid uint32
48
52
gid uint32
53
+ configSpec specs.Spec
49
54
}
50
55
51
56
const firecrackerFileName = "firecracker"
@@ -63,6 +68,19 @@ func newRuncJailer(ctx context.Context, logger *logrus.Entry, ociBundlePath, run
63
68
gid : gid ,
64
69
}
65
70
71
+ spec := specs.Spec {}
72
+ var configBytes []byte
73
+ configBytes , err := ioutil .ReadFile (runcConfigPath )
74
+ if err != nil {
75
+ return nil , errors .Wrapf (err , "failed to read %s" , runcConfigPath )
76
+ }
77
+
78
+ if err = json .Unmarshal (configBytes , & spec ); err != nil {
79
+ return nil , errors .Wrapf (err , "failed to unmarshal %s" , runcConfigPath )
80
+ }
81
+
82
+ j .configSpec = spec
83
+
66
84
rootPath := j .RootPath ()
67
85
68
86
const mode = os .FileMode (0700 )
@@ -77,29 +95,35 @@ func newRuncJailer(ctx context.Context, logger *logrus.Entry, ociBundlePath, run
77
95
78
96
// JailPath returns the base directory from where the jail binary will be ran
79
97
// from
80
- func (j runcJailer ) OCIBundlePath () string {
98
+ func (j * runcJailer ) OCIBundlePath () string {
81
99
return j .ociBundlePath
82
100
}
83
101
84
102
// RootPath returns the root fs of the jailed system.
85
- func (j runcJailer ) RootPath () string {
103
+ func (j * runcJailer ) RootPath () string {
86
104
return filepath .Join (j .OCIBundlePath (), rootfsFolder )
87
105
}
88
106
89
107
// JailPath will return the OCI bundle rootfs path
90
- func (j runcJailer ) JailPath () vm.Dir {
108
+ func (j * runcJailer ) JailPath () vm.Dir {
91
109
return vm .Dir (j .RootPath ())
92
110
}
93
111
94
112
// BuildJailedMachine will return the needed options for a jailed Firecracker
95
113
// instance. In addition, some configuration values will be overwritten to the
96
114
// jailed values, like SocketPath in the machineConfig.
97
115
func (j * runcJailer ) BuildJailedMachine (cfg * Config , machineConfig * firecracker.Config , vmID string ) ([]firecracker.Opt , error ) {
98
- handler := j .BuildJailedRootHandler (cfg , & machineConfig . SocketPath , vmID )
116
+ handler := j .BuildJailedRootHandler (cfg , machineConfig , vmID )
99
117
fifoHandler := j .BuildLinkFifoHandler ()
100
118
// Build a new client since BuildJailedRootHandler modifies the socket path value.
101
119
client := firecracker .NewClient (machineConfig .SocketPath , j .logger , machineConfig .Debug )
102
120
121
+ if machineConfig .NetNS == "" {
122
+ if netns := getNetNS (j .configSpec ); netns != "" {
123
+ machineConfig .NetNS = netns
124
+ }
125
+ }
126
+
103
127
opts := []firecracker.Opt {
104
128
firecracker .WithProcessRunner (j .jailerCommand (vmID , cfg .Debug )),
105
129
firecracker .WithClient (client ),
@@ -120,10 +144,10 @@ func (j *runcJailer) BuildJailedMachine(cfg *Config, machineConfig *firecracker.
120
144
121
145
// BuildJailedRootHandler will populate the jail with the necessary files, which may be
122
146
// device nodes, hard links, and/or bind-mount targets
123
- func (j * runcJailer ) BuildJailedRootHandler (cfg * Config , socketPath * string , vmID string ) firecracker.Handler {
147
+ func (j * runcJailer ) BuildJailedRootHandler (cfg * Config , machineConfig * firecracker. Config , vmID string ) firecracker.Handler {
124
148
ociBundlePath := j .OCIBundlePath ()
125
149
rootPath := j .RootPath ()
126
- * socketPath = filepath .Join (rootPath , "api.socket" )
150
+ machineConfig . SocketPath = filepath .Join (rootPath , "api.socket" )
127
151
128
152
return firecracker.Handler {
129
153
Name : jailerHandlerName ,
@@ -136,7 +160,9 @@ func (j *runcJailer) BuildJailedRootHandler(cfg *Config, socketPath *string, vmI
136
160
}
137
161
138
162
j .logger .Debug ("Overwritting process args of config" )
139
- if err := j .overwriteConfig (cfg , filepath .Base (m .Cfg .SocketPath ), rootPathToConfig ); err != nil {
163
+ // we pass m.Cfg as opposed to machineConfig as we want the populated
164
+ // config defaults when calling NewMachine
165
+ if err := j .overwriteConfig (cfg , & m .Cfg , filepath .Base (m .Cfg .SocketPath ), rootPathToConfig ); err != nil {
140
166
return errors .Wrap (err , "failed to overwrite config.json" )
141
167
}
142
168
@@ -206,7 +232,7 @@ func (j *runcJailer) BuildJailedRootHandler(cfg *Config, socketPath *string, vmI
206
232
207
233
// BuildLinkFifoHandler will return a new firecracker.Handler with the function
208
234
// that will allow linking of the fifos making them visible to Firecracker.
209
- func (j runcJailer ) BuildLinkFifoHandler () firecracker.Handler {
235
+ func (j * runcJailer ) BuildLinkFifoHandler () firecracker.Handler {
210
236
return firecracker.Handler {
211
237
Name : jailerFifoHandlerName ,
212
238
Fn : func (ctx context.Context , m * firecracker.Machine ) error {
@@ -232,7 +258,7 @@ func (j runcJailer) BuildLinkFifoHandler() firecracker.Handler {
232
258
233
259
// StubDrivesOptions will return a set of options used to create a new stub
234
260
// drive handler.
235
- func (j runcJailer ) StubDrivesOptions () []stubDrivesOpt {
261
+ func (j * runcJailer ) StubDrivesOptions () []stubDrivesOpt {
236
262
return []stubDrivesOpt {
237
263
func (drives []models.Drive ) error {
238
264
for _ , drive := range drives {
@@ -251,7 +277,7 @@ func (j runcJailer) StubDrivesOptions() []stubDrivesOpt {
251
277
// the jail. For block devices we will use mknod to create the device and then
252
278
// set the correct permissions to ensure visibility in the jail. Regular files
253
279
// will be copied into the jail.
254
- func (j runcJailer ) ExposeFileToJail (srcPath string ) error {
280
+ func (j * runcJailer ) ExposeFileToJail (srcPath string ) error {
255
281
uid := j .uid
256
282
gid := j .gid
257
283
@@ -292,7 +318,7 @@ func (j runcJailer) ExposeFileToJail(srcPath string) error {
292
318
}
293
319
294
320
// copyFileToJail will copy a file from src to dst, and chown the new file to the jail user.
295
- func (j runcJailer ) copyFileToJail (src , dst string , mode os.FileMode ) error {
321
+ func (j * runcJailer ) copyFileToJail (src , dst string , mode os.FileMode ) error {
296
322
if err := copyFile (src , dst , mode ); err != nil {
297
323
return err
298
324
}
@@ -340,7 +366,7 @@ func copyFile(src, dst string, mode os.FileMode) error {
340
366
return nil
341
367
}
342
368
343
- func (j runcJailer ) jailerCommand (containerName string , isDebug bool ) * exec.Cmd {
369
+ func (j * runcJailer ) jailerCommand (containerName string , isDebug bool ) * exec.Cmd {
344
370
cmd := exec .CommandContext (j .ctx , j .runcBinaryPath , "run" , containerName )
345
371
cmd .Dir = j .OCIBundlePath ()
346
372
@@ -353,19 +379,8 @@ func (j runcJailer) jailerCommand(containerName string, isDebug bool) *exec.Cmd
353
379
}
354
380
355
381
// overwriteConfig will set the proper default values if a field had not been set.
356
- //
357
- // TODO: Add netns
358
- func (j runcJailer ) overwriteConfig (cfg * Config , socketPath , configPath string ) error {
359
- spec := specs.Spec {}
360
- configBytes , err := ioutil .ReadFile (configPath )
361
- if err != nil {
362
- return err
363
- }
364
-
365
- if err := json .Unmarshal (configBytes , & spec ); err != nil {
366
- return err
367
- }
368
-
382
+ func (j * runcJailer ) overwriteConfig (cfg * Config , machineConfig * firecracker.Config , socketPath , configPath string ) error {
383
+ spec := j .configSpec
369
384
if spec .Process .User .UID != 0 ||
370
385
spec .Process .User .GID != 0 {
371
386
return fmt .Errorf (
@@ -376,13 +391,22 @@ func (j runcJailer) overwriteConfig(cfg *Config, socketPath, configPath string)
376
391
}
377
392
378
393
spec = j .setDefaultConfigValues (cfg , socketPath , spec )
379
-
380
394
spec .Root .Path = rootfsFolder
381
395
spec .Root .Readonly = false
382
396
spec .Process .User .UID = j .uid
383
397
spec .Process .User .GID = j .gid
384
398
385
- configBytes , err = json .Marshal (& spec )
399
+ if machineConfig .NetNS != "" {
400
+ for i , ns := range spec .Linux .Namespaces {
401
+ if ns .Type == networkNamespaceRuncName {
402
+ ns .Path = machineConfig .NetNS
403
+ spec .Linux .Namespaces [i ] = ns
404
+ break
405
+ }
406
+ }
407
+ }
408
+
409
+ configBytes , err := json .Marshal (& spec )
386
410
if err != nil {
387
411
return err
388
412
}
@@ -396,7 +420,7 @@ func (j runcJailer) overwriteConfig(cfg *Config, socketPath, configPath string)
396
420
397
421
// setDefaultConfigValues will process the spec file provided and allow any
398
422
// empty/zero values to be replaced with default values.
399
- func (j runcJailer ) setDefaultConfigValues (cfg * Config , socketPath string , spec specs.Spec ) specs.Spec {
423
+ func (j * runcJailer ) setDefaultConfigValues (cfg * Config , socketPath string , spec specs.Spec ) specs.Spec {
400
424
if spec .Process == nil {
401
425
spec .Process = & specs.Process {}
402
426
}
@@ -448,3 +472,13 @@ func mkdirAllWithPermissions(path string, mode os.FileMode, uid, gid uint32) err
448
472
449
473
return nil
450
474
}
475
+
476
+ func getNetNS (spec specs.Spec ) string {
477
+ for _ , ns := range spec .Linux .Namespaces {
478
+ if ns .Type == networkNamespaceRuncName {
479
+ return ns .Path
480
+ }
481
+ }
482
+
483
+ return ""
484
+ }
0 commit comments