clh: enable CPU hotplug

With the HTTP API 'vm.resize()', the CPU hotplug with CLH is much simpler
comparing with QEMU. This is because we don't need to distinguish adding from
removing CPUs.

Fixes: #2495

Depends-on: github.com/kata-containers/packaging#968
Depends-on: github.com/kata-containers/tests#2364

Signed-off-by: Bo Chen <chen.bo@intel.com>
This commit is contained in:
Bo Chen 2020-02-25 22:49:37 -08:00
parent 8cffbde514
commit 17b9de140f
2 changed files with 47 additions and 2 deletions

View File

@ -76,6 +76,7 @@ type clhClient interface {
// No lint: golint suggest to rename to VMInfoGet.
VmInfoGet(ctx context.Context) (chclient.VmInfo, *http.Response, error) //nolint:golint
BootVM(ctx context.Context) (*http.Response, error)
VmResizePut(ctx context.Context, vmResize chclient.VmResize) (*http.Response, error)
}
type CloudHypervisorVersion struct {
@ -391,8 +392,47 @@ func (clh *cloudHypervisor) resizeMemory(reqMemMB uint32, memoryBlockSizeMB uint
}
func (clh *cloudHypervisor) resizeVCPUs(reqVCPUs uint32) (currentVCPUs uint32, newVCPUs uint32, err error) {
clh.Logger().WithField("function", "resizeVCPUs").Warn("not supported")
return 0, 0, nil
cl := clh.client()
// Retrieve the number of current vCPUs via HTTP API
ctx, cancel := context.WithTimeout(context.Background(), clhAPITimeout*time.Second)
info, _, err := cl.VmInfoGet(ctx)
if err != nil {
clh.Logger().WithField("function", "resizeVCPUs").WithError(openAPIClientError(err)).Info("[clh] VmInfoGet failed")
return 0, 0, openAPIClientError(err)
}
// Reset the timer after the first HTTP API call
cancel()
currentVCPUs = uint32(info.Config.Cpus.BootVcpus)
newVCPUs = currentVCPUs
// Sanity check
if reqVCPUs == 0 {
clh.Logger().WithField("function", "resizeVCPUs").Debugf("Cannot resize vCPU to 0")
return currentVCPUs, newVCPUs, fmt.Errorf("Cannot resize vCPU to 0")
}
if reqVCPUs > clh.config.DefaultMaxVCPUs || reqVCPUs > uint32(info.Config.Cpus.MaxVcpus) {
clh.Logger().WithFields(log.Fields{
"function": "resizeVCPUs",
"reqVCPUs": reqVCPUs,
"configDefaultMaxVCPUs": clh.config.DefaultMaxVCPUs,
"clhMaxVCPUs": info.Config.Cpus.MaxVcpus,
}).Debug("exceeding the maxVCPUs")
return currentVCPUs, newVCPUs, fmt.Errorf("Cannot resize vCPU to %d: exceeding the maximum amount of vCPUs (%d or %d)",
reqVCPUs, clh.config.DefaultMaxVCPUs, info.Config.Cpus.MaxVcpus)
}
// Resize (hot-plug) vCPUs via HTTP API
ctx, cancel = context.WithTimeout(context.Background(), clhAPITimeout*time.Second)
defer cancel()
if _, err = cl.VmResizePut(ctx, chclient.VmResize{DesiredVcpus: int32(reqVCPUs)}); err != nil {
return currentVCPUs, newVCPUs, errors.Wrap(err, "[clh] VmResizePut failed")
}
newVCPUs = reqVCPUs
return currentVCPUs, newVCPUs, nil
}
func (clh *cloudHypervisor) cleanup() error {

View File

@ -81,6 +81,11 @@ func (c *clhClientMock) BootVM(ctx context.Context) (*http.Response, error) {
return nil, nil
}
//nolint:golint
func (c *clhClientMock) VmResizePut(ctx context.Context, vmResize chclient.VmResize) (*http.Response, error) {
return nil, nil
}
func TestCloudHypervisorAddVSock(t *testing.T) {
assert := assert.New(t)
clh := cloudHypervisor{}