clh: Hotplug the network devices

Instead of creating the VM with the network device already plugged in,
let's actually add the network device *after* the VM is created, but
*before* the Vm is actually booted.

Although it looks like it doesn't make any functional difference between
what's done in the past and what this commit introduces, this will be
used to workaround a limitation on OpenAPI when it comes to passing down
the network device's file descriptor to Cloud Hypervisor, so Cloud
Hypervisor can use it instead of opening the device by its name on the
VMM side.

Signed-off-by: Fabiano Fidêncio <fabiano.fidencio@intel.com>
This commit is contained in:
Fabiano Fidêncio 2022-05-11 09:33:51 +02:00
parent 2e07538334
commit 01fe09a4ee
2 changed files with 49 additions and 11 deletions

View File

@ -148,6 +148,21 @@ func (c *clhClientApi) VmAddNetPut(ctx context.Context, netConfig chclient.NetCo
return c.ApiInternal.VmAddNetPut(ctx).NetConfig(netConfig).Execute()
}
// This is done in order to be able to override such a function as part of
// our unit tests, as when testing bootVM we're on a mocked scenario already.
var vmAddNetPutRequest = func(clh *cloudHypervisor, ctx context.Context) error {
cl := clh.client()
for _, netDevice := range *clh.netDevices {
_, _, err := cl.VmAddNetPut(ctx, netDevice)
if err != nil {
return err
}
}
return nil
}
//
// Cloud hypervisor state
//
@ -170,6 +185,7 @@ type cloudHypervisor struct {
APIClient clhClient
ctx context.Context
id string
netDevices *[]chclient.NetConfig
devicesIds map[string]string
vmconfig chclient.VmConfig
state CloudHypervisorState
@ -1267,6 +1283,10 @@ func openAPIClientError(err error) error {
return fmt.Errorf("error: %v reason: %s", err, reason)
}
func (clh *cloudHypervisor) vmAddNetPut(ctx context.Context) error {
return vmAddNetPutRequest(clh, ctx)
}
func (clh *cloudHypervisor) bootVM(ctx context.Context) error {
cl := clh.client()
@ -1294,6 +1314,11 @@ func (clh *cloudHypervisor) bootVM(ctx context.Context) error {
return fmt.Errorf("VM state is not 'Created' after 'CreateVM'")
}
err = clh.vmAddNetPut(ctx)
if err != nil {
return err
}
clh.Logger().Debug("Booting VM")
_, err = cl.BootVM(ctx)
if err != nil {
@ -1397,10 +1422,10 @@ func (clh *cloudHypervisor) addNet(e Endpoint) error {
net.SetRateLimiterConfig(*netRateLimiterConfig)
}
if clh.vmconfig.Net != nil {
*clh.vmconfig.Net = append(*clh.vmconfig.Net, *net)
if clh.netDevices != nil {
*clh.netDevices = append(*clh.netDevices, *net)
} else {
clh.vmconfig.Net = &[]chclient.NetConfig{*net}
clh.netDevices = &[]chclient.NetConfig{*net}
}
return nil

View File

@ -148,19 +148,19 @@ func TestCloudHypervisorAddNetCheckNetConfigListValues(t *testing.T) {
err := clh.addNet(e)
assert.Nil(err)
assert.Equal(len(*clh.vmconfig.Net), 1)
assert.Equal(len(*clh.netDevices), 1)
if err == nil {
assert.Equal(*(*clh.vmconfig.Net)[0].Mac, macTest)
assert.Equal(*(*clh.vmconfig.Net)[0].Tap, tapPath)
assert.Equal(*(*clh.netDevices)[0].Mac, macTest)
assert.Equal(*(*clh.netDevices)[0].Tap, tapPath)
}
err = clh.addNet(e)
assert.Nil(err)
assert.Equal(len(*clh.vmconfig.Net), 2)
assert.Equal(len(*clh.netDevices), 2)
if err == nil {
assert.Equal(*(*clh.vmconfig.Net)[1].Mac, macTest)
assert.Equal(*(*clh.vmconfig.Net)[1].Tap, tapPath)
assert.Equal(*(*clh.netDevices)[1].Mac, macTest)
assert.Equal(*(*clh.netDevices)[1].Tap, tapPath)
}
}
@ -194,7 +194,7 @@ func TestCloudHypervisorAddNetCheckEnpointTypes(t *testing.T) {
t.Errorf("cloudHypervisor.addNet() error = %v, wantErr %v", err, tt.wantErr)
} else if err == nil {
assert.Equal(*(*clh.vmconfig.Net)[0].Tap, tapPath)
assert.Equal(*(*clh.netDevices)[0].Tap, tapPath)
}
})
}
@ -350,7 +350,7 @@ func TestCloudHypervisorNetRateLimiter(t *testing.T) {
if err := clh.addNet(validVeth); err != nil {
t.Errorf("cloudHypervisor.addNet() error = %v", err)
} else {
netConfig := (*clh.vmconfig.Net)[0]
netConfig := (*clh.netDevices)[0]
assert.Equal(netConfig.HasRateLimiterConfig(), tt.expectsRateLimiter)
if tt.expectsRateLimiter {
@ -378,6 +378,13 @@ func TestCloudHypervisorNetRateLimiter(t *testing.T) {
func TestCloudHypervisorBootVM(t *testing.T) {
clh := &cloudHypervisor{}
clh.APIClient = &clhClientMock{}
savedVmAddNetPutRequestFunc := vmAddNetPutRequest
vmAddNetPutRequest = func(clh *cloudHypervisor, ctx context.Context) error { return nil }
defer func() {
vmAddNetPutRequest = savedVmAddNetPutRequestFunc
}()
var ctx context.Context
if err := clh.bootVM(ctx); err != nil {
t.Errorf("cloudHypervisor.bootVM() error = %v", err)
@ -491,6 +498,12 @@ func TestCloudHypervisorStartSandbox(t *testing.T) {
store, err := persist.GetDriver()
assert.NoError(err)
savedVmAddNetPutRequestFunc := vmAddNetPutRequest
vmAddNetPutRequest = func(clh *cloudHypervisor, ctx context.Context) error { return nil }
defer func() {
vmAddNetPutRequest = savedVmAddNetPutRequestFunc
}()
clhConfig.VMStorePath = store.RunVMStoragePath()
clhConfig.RunStorePath = store.RunStoragePath()