Skip to content

Commit 8913865

Browse files
authored
Merge pull request #177 from smira/network-conf
Allow parsed CNI config to be passed in
2 parents 26c7282 + b31570e commit 8913865

File tree

2 files changed

+64
-19
lines changed

2 files changed

+64
-19
lines changed

network.go

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -227,11 +227,18 @@ type NetworkInterface struct {
227227
// Currently, CNIConfiguration can only be specified for VMs that have a
228228
// single network interface.
229229
type CNIConfiguration struct {
230-
// NetworkName (required) corresponds to the "name" parameter in the
231-
// CNI spec's Network Configuration List structure. It selects the name
230+
// NetworkName (either NetworkName or NetworkConfig are required)
231+
// corresponds to the "name" parameter in the CNI spec's
232+
// Network Configuration List structure. It selects the name
232233
// of the network whose configuration will be used when invoking CNI.
233234
NetworkName string
234235

236+
// NetworkConfig (either NetworkName or NetworkConfig are required)
237+
// replaces the NetworkName with parsed CNI network configuration
238+
// skipping the requirement to store network config file in CNI
239+
// configuration directory.
240+
NetworkConfig *libcni.NetworkConfigList
241+
235242
// IfName (optional) corresponds to the CNI_IFNAME parameter as specified
236243
// in the CNI spec. It generally specifies the name of the interface to be
237244
// created by a CNI plugin being invoked.
@@ -282,8 +289,12 @@ type CNIConfiguration struct {
282289
}
283290

284291
func (cniConf CNIConfiguration) validate() error {
285-
if cniConf.NetworkName == "" {
286-
return errors.Errorf("must specify NetworkName in CNIConfiguration: %+v", cniConf)
292+
if cniConf.NetworkName == "" && cniConf.NetworkConfig == nil {
293+
return errors.Errorf("must specify either NetworkName or NetworkConfig in CNIConfiguration: %+v", cniConf)
294+
}
295+
296+
if cniConf.NetworkName != "" && cniConf.NetworkConfig != nil {
297+
return errors.Errorf("must not specify both NetworkName and NetworkConfig in CNIConfiguration: %+v", cniConf)
287298
}
288299

289300
return nil
@@ -317,10 +328,16 @@ func (cniConf CNIConfiguration) invokeCNI(ctx context.Context, logger *log.Entry
317328

318329
cniPlugin := libcni.NewCNIConfigWithCacheDir(cniConf.BinPath, cniConf.CacheDir, nil)
319330

320-
networkConf, err := libcni.LoadConfList(cniConf.ConfDir, cniConf.NetworkName)
321-
if err != nil {
322-
return nil, errors.Wrapf(err, "failed to load CNI configuration from dir %q for network %q",
323-
cniConf.ConfDir, cniConf.NetworkName), cleanupFuncs
331+
networkConf := cniConf.NetworkConfig
332+
333+
var err error
334+
335+
if networkConf == nil {
336+
networkConf, err = libcni.LoadConfList(cniConf.ConfDir, cniConf.NetworkName)
337+
if err != nil {
338+
return nil, errors.Wrapf(err, "failed to load CNI configuration from dir %q for network %q",
339+
cniConf.ConfDir, cniConf.NetworkName), cleanupFuncs
340+
}
324341
}
325342

326343
runtimeConf := cniConf.asCNIRuntimeConf()

network_test.go

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424
"testing"
2525
"time"
2626

27+
"github.com/containernetworking/cni/libcni"
2728
models "github.com/firecracker-microvm/firecracker-go-sdk/client/models"
2829
"github.com/firecracker-microvm/firecracker-go-sdk/fctesting"
2930
"github.com/sparrc/go-ping"
@@ -238,7 +239,15 @@ func TestNetworkInterfacesValidationFails_BothSpecified(t *testing.T) {
238239
assert.Error(t, err, "invalid network config with both static and cni configuration did not result in validation error")
239240
}
240241

241-
func TestNetworkMachineCNI(t *testing.T) {
242+
func TestNetworkMachineCNIWithConfFile(t *testing.T) {
243+
testNetworkMachineCNI(t, true)
244+
}
245+
246+
func TestNetworkMachineCNIWithParsedConfig(t *testing.T) {
247+
testNetworkMachineCNI(t, false)
248+
}
249+
250+
func testNetworkMachineCNI(t *testing.T, useConfFile bool) {
242251
if testing.Short() {
243252
t.Skip()
244253
}
@@ -281,10 +290,23 @@ func TestNetworkMachineCNI(t *testing.T) {
281290
]
282291
}`, networkName)
283292

293+
var networkConf *libcni.NetworkConfigList
294+
284295
cniConfPath := filepath.Join(cniConfDir, fmt.Sprintf("%s.conflist", networkName))
285-
require.NoError(t,
286-
ioutil.WriteFile(cniConfPath, []byte(cniConf), 0666), // broad permissions for tests
287-
"failed to write cni conf file")
296+
if useConfFile {
297+
require.NoError(t,
298+
ioutil.WriteFile(cniConfPath, []byte(cniConf), 0666), // broad permissions for tests
299+
"failed to write cni conf file")
300+
} else {
301+
// make sure config file doesn't exist
302+
err := os.Remove(cniConfPath)
303+
if err != nil && !os.IsNotExist(err) {
304+
require.NoError(t, err, "failed to delete cni conf file")
305+
}
306+
307+
networkConf, err = libcni.ConfListFromBytes([]byte(cniConf))
308+
require.NoError(t, err, "cni conf should parse")
309+
}
288310

289311
numVMs := 10
290312
vmIPs := make(chan string, numVMs)
@@ -304,7 +326,7 @@ func TestNetworkMachineCNI(t *testing.T) {
304326
ctx, cancel := context.WithCancel(context.Background())
305327
// NewMachine cannot be in the goroutine below, since go-openapi/runtime has a globally-shared mutable logger...
306328
// https://github.com/go-openapi/runtime/blob/553c9d1fb273d9550562d9f76949a413af265138/client/runtime.go#L463
307-
m := newCNIMachine(t, ctx, firecrackerSockPath, rootfsPath, cniConfDir, cniCacheDir, networkName, ifName, vmID, cniBinPath)
329+
m := newCNIMachine(t, ctx, firecrackerSockPath, rootfsPath, cniConfDir, cniCacheDir, networkName, ifName, vmID, cniBinPath, networkConf)
308330

309331
go func(ctx context.Context, cancel func(), m *Machine, vmID string) {
310332
defer vmWg.Done()
@@ -357,12 +379,17 @@ func newCNIMachine(t *testing.T,
357379
ifName,
358380
vmID string,
359381
cniBinPath []string,
382+
networkConf *libcni.NetworkConfigList,
360383
) *Machine {
361384
rootfsBytes, err := ioutil.ReadFile(testRootfs)
362385
require.NoError(t, err, "failed to read rootfs file")
363386
err = ioutil.WriteFile(rootfsPath, rootfsBytes, 0666)
364387
require.NoError(t, err, "failed to copy vm rootfs to %s", rootfsPath)
365388

389+
if networkConf != nil {
390+
networkName = ""
391+
}
392+
366393
cmd := VMCommandBuilder{}.
367394
WithSocketPath(firecrackerSockPath).
368395
WithBin(getFirecrackerBinaryPath()).
@@ -386,12 +413,13 @@ func newCNIMachine(t *testing.T,
386413
},
387414
NetworkInterfaces: []NetworkInterface{{
388415
CNIConfiguration: &CNIConfiguration{
389-
ConfDir: cniConfDir,
390-
BinPath: cniBinPath,
391-
CacheDir: cniCacheDir,
392-
NetworkName: networkName,
393-
IfName: ifName,
394-
VMIfName: "eth0",
416+
ConfDir: cniConfDir,
417+
BinPath: cniBinPath,
418+
CacheDir: cniCacheDir,
419+
NetworkName: networkName,
420+
NetworkConfig: networkConf,
421+
IfName: ifName,
422+
VMIfName: "eth0",
395423
},
396424
}},
397425
VMID: vmID,

0 commit comments

Comments
 (0)