gitee.com/leisunstar/runtime@v0.0.0-20200521203717-5cef3e7b53f9/virtcontainers/acrn.go (about)

     1  // Copyright (c) 2019 Intel Corporation
     2  //
     3  // SPDX-License-Identifier: Apache-2.0
     4  //
     5  
     6  package virtcontainers
     7  
     8  import (
     9  	"context"
    10  	"encoding/json"
    11  	"fmt"
    12  	"os"
    13  	"os/exec"
    14  	"path/filepath"
    15  	"strings"
    16  	"syscall"
    17  	"time"
    18  	"unsafe"
    19  
    20  	opentracing "github.com/opentracing/opentracing-go"
    21  	"github.com/pkg/errors"
    22  	"github.com/sirupsen/logrus"
    23  
    24  	"github.com/kata-containers/runtime/virtcontainers/device/config"
    25  	persistapi "github.com/kata-containers/runtime/virtcontainers/persist/api"
    26  	"github.com/kata-containers/runtime/virtcontainers/pkg/uuid"
    27  	"github.com/kata-containers/runtime/virtcontainers/types"
    28  	"github.com/kata-containers/runtime/virtcontainers/utils"
    29  )
    30  
    31  // Since ACRN is using the store in a quite abnormal way, let's first draw it back from store to here
    32  
    33  // UUIDPathSuffix is the suffix used for uuid storage
    34  const (
    35  	UUIDPathSuffix = "uuid"
    36  	uuidFile       = "uuid.json"
    37  )
    38  
    39  // ACRN currently supports only known UUIDs for security
    40  // reasons (FuSa). When launching VM, only these pre-defined
    41  // UUID should be used else VM launch will fail. The main
    42  // of purpose UUID is is not used for image identification
    43  // but generating vSeed (virtual seed which takes UUID
    44  // as one of the parameter) which is used during VM boot.
    45  
    46  // acrnUUIDsToIdx lists Idx corresponding to the UUID
    47  var acrnUUIDsToIdx = map[string]uint8{
    48  	"a7ada506-1ab0-4b6b-a0da-e513ca9b8c2f": 0,
    49  	"dbeae168-26e4-4084-9227-622193e56325": 1,
    50  	"18ed60cd-e9ea-4bf4-8f87-8523fc8347a3": 2,
    51  	"3f90b6f8-449a-4e72-b99c-063a889fc422": 3,
    52  	"1ae8587b-e599-4b59-8260-6d14ac166a55": 4,
    53  	"75f3b94b-49ed-48fc-b019-577ef45adf2b": 5,
    54  	"ca62cf3c-8359-47e8-a3f7-de2d682dfb02": 6,
    55  	"e3189497-c3f6-4b97-9e2c-18ac0ab9064d": 7,
    56  }
    57  
    58  // acrnIdxToUUIDs lists UUIDs corresponding to the Idx
    59  var acrnIdxToUUIDs = map[uint8]string{
    60  	0: "a7ada506-1ab0-4b6b-a0da-e513ca9b8c2f",
    61  	1: "dbeae168-26e4-4084-9227-622193e56325",
    62  	2: "18ed60cd-e9ea-4bf4-8f87-8523fc8347a3",
    63  	3: "3f90b6f8-449a-4e72-b99c-063a889fc422",
    64  	4: "1ae8587b-e599-4b59-8260-6d14ac166a55",
    65  	5: "75f3b94b-49ed-48fc-b019-577ef45adf2b",
    66  	6: "ca62cf3c-8359-47e8-a3f7-de2d682dfb02",
    67  	7: "e3189497-c3f6-4b97-9e2c-18ac0ab9064d",
    68  }
    69  
    70  // AcrnInfo keeps track of UUID availability
    71  type AcrnInfo struct {
    72  	UUIDAvailability [8]uint8
    73  }
    74  
    75  // AcrnState keeps track of VM UUID, PID.
    76  type AcrnState struct {
    77  	UUID string
    78  	PID  int
    79  }
    80  
    81  // Acrn is an Hypervisor interface implementation for the Linux acrn hypervisor.
    82  type Acrn struct {
    83  	id         string
    84  	config     HypervisorConfig
    85  	acrnConfig Config
    86  	state      AcrnState
    87  	info       AcrnInfo
    88  	arch       acrnArch
    89  	ctx        context.Context
    90  	store      persistapi.PersistDriver
    91  }
    92  
    93  type acrnPlatformInfo struct {
    94  	cpuNum            uint16     //nolint
    95  	reserved0         [126]uint8 //nolint
    96  	maxVCPUsPerVM     uint16     //nolint
    97  	maxKataContainers uint8
    98  	reserved1         [125]uint8 //nolint
    99  }
   100  
   101  const acrnDevice = "/dev/acrn_vhm"
   102  
   103  // ioctl_ACRN_CREATE_VM is the IOCTL to create VM in ACRN.
   104  // Current Linux mainstream kernel doesn't have support for ACRN.
   105  // Due to this several macros are not defined in Linux headers.
   106  // Until the support is available, directly use the value instead
   107  // of macros.
   108  //https://github.com/kata-containers/runtime/issues/1784
   109  const ioctl_ACRN_GET_PLATFORM_INFO = 0x43000003 //nolint
   110  
   111  const (
   112  	acrnConsoleSocket          = "console.sock"
   113  	acrnStopSandboxTimeoutSecs = 15
   114  )
   115  
   116  //UUIDBusy marks a particular UUID as busy
   117  const UUIDBusy = 1
   118  
   119  //UUIDFree marks a particular UUID as free
   120  const UUIDFree = 0
   121  
   122  // agnostic list of kernel parameters
   123  var acrnDefaultKernelParameters = []Param{
   124  	{"panic", "1"},
   125  }
   126  
   127  func (a *Acrn) kernelParameters() string {
   128  	// get a list of arch kernel parameters
   129  	params := a.arch.kernelParameters(a.config.Debug)
   130  
   131  	// use default parameters
   132  	params = append(params, acrnDefaultKernelParameters...)
   133  
   134  	// set the maximum number of vCPUs
   135  	params = append(params, Param{"maxcpus", fmt.Sprintf("%d", a.config.DefaultMaxVCPUs)})
   136  
   137  	// add the params specified by the provided config. As the kernel
   138  	// honours the last parameter value set and since the config-provided
   139  	// params are added here, they will take priority over the defaults.
   140  	params = append(params, a.config.KernelParams...)
   141  
   142  	paramsStr := SerializeParams(params, "=")
   143  
   144  	return strings.Join(paramsStr, " ")
   145  }
   146  
   147  // Adds all capabilities supported by Acrn implementation of hypervisor interface
   148  func (a *Acrn) capabilities() types.Capabilities {
   149  	span, _ := a.trace("capabilities")
   150  	defer span.Finish()
   151  
   152  	return a.arch.capabilities()
   153  }
   154  
   155  func (a *Acrn) hypervisorConfig() HypervisorConfig {
   156  	return a.config
   157  }
   158  
   159  // get the acrn binary path
   160  func (a *Acrn) acrnPath() (string, error) {
   161  	p, err := a.config.HypervisorAssetPath()
   162  	if err != nil {
   163  		return "", err
   164  	}
   165  
   166  	if p == "" {
   167  		p, err = a.arch.acrnPath()
   168  		if err != nil {
   169  			return "", err
   170  		}
   171  	}
   172  
   173  	if _, err = os.Stat(p); os.IsNotExist(err) {
   174  		return "", fmt.Errorf("acrn path (%s) does not exist", p)
   175  	}
   176  
   177  	return p, nil
   178  }
   179  
   180  // get the ACRNCTL binary path
   181  func (a *Acrn) acrnctlPath() (string, error) {
   182  	ctlpath, err := a.config.HypervisorCtlAssetPath()
   183  	if err != nil {
   184  		return "", err
   185  	}
   186  
   187  	if ctlpath == "" {
   188  		ctlpath, err = a.arch.acrnctlPath()
   189  		if err != nil {
   190  			return "", err
   191  		}
   192  	}
   193  
   194  	if _, err = os.Stat(ctlpath); os.IsNotExist(err) {
   195  		return "", fmt.Errorf("acrnctl path (%s) does not exist", ctlpath)
   196  	}
   197  
   198  	return ctlpath, nil
   199  }
   200  
   201  // Logger returns a logrus logger appropriate for logging acrn messages
   202  func (a *Acrn) Logger() *logrus.Entry {
   203  	return virtLog.WithField("subsystem", "acrn")
   204  }
   205  
   206  func (a *Acrn) trace(name string) (opentracing.Span, context.Context) {
   207  	if a.ctx == nil {
   208  		a.Logger().WithField("type", "bug").Error("trace called before context set")
   209  		a.ctx = context.Background()
   210  	}
   211  
   212  	span, ctx := opentracing.StartSpanFromContext(a.ctx, name)
   213  
   214  	span.SetTag("subsystem", "hypervisor")
   215  	span.SetTag("type", "acrn")
   216  
   217  	return span, ctx
   218  }
   219  
   220  func (a *Acrn) memoryTopology() (Memory, error) {
   221  	memMb := uint64(a.config.MemorySize)
   222  
   223  	return a.arch.memoryTopology(memMb), nil
   224  }
   225  
   226  func (a *Acrn) appendImage(devices []Device, imagePath string) ([]Device, error) {
   227  	if imagePath == "" {
   228  		return nil, fmt.Errorf("Image path is empty: %s", imagePath)
   229  	}
   230  
   231  	// Get sandbox and increment the globalIndex.
   232  	// This is to make sure the VM rootfs occupies
   233  	// the first Index which is /dev/vda.
   234  	sandbox, err := globalSandboxList.lookupSandbox(a.id)
   235  	if sandbox == nil && err != nil {
   236  		return nil, err
   237  	}
   238  	sandbox.GetAndSetSandboxBlockIndex()
   239  
   240  	devices, err = a.arch.appendImage(devices, imagePath)
   241  	if err != nil {
   242  		return nil, err
   243  	}
   244  
   245  	return devices, nil
   246  }
   247  
   248  func (a *Acrn) buildDevices(imagePath string) ([]Device, error) {
   249  	var devices []Device
   250  
   251  	if imagePath == "" {
   252  		return nil, fmt.Errorf("Image Path should not be empty: %s", imagePath)
   253  	}
   254  
   255  	console, err := a.getSandboxConsole(a.id)
   256  	if err != nil {
   257  		return nil, err
   258  	}
   259  
   260  	// Add bridges before any other devices. This way we make sure that
   261  	// bridge gets the first available PCI address.
   262  	devices = a.arch.appendBridges(devices)
   263  
   264  	//Add LPC device to the list of other devices.
   265  	devices = a.arch.appendLPC(devices)
   266  
   267  	devices = a.arch.appendConsole(devices, console)
   268  
   269  	devices, err = a.appendImage(devices, imagePath)
   270  	if err != nil {
   271  		return nil, err
   272  	}
   273  
   274  	// Create virtio blk devices with dummy backend as a place
   275  	// holder for container rootfs (as acrn doesn't support hot-plug).
   276  	// Once the container rootfs is known, replace the dummy backend
   277  	// with actual path (using block rescan feature in acrn)
   278  	devices, err = a.createDummyVirtioBlkDev(devices)
   279  	if err != nil {
   280  		return nil, err
   281  	}
   282  
   283  	return devices, nil
   284  }
   285  
   286  // setup sets the Acrn structure up.
   287  func (a *Acrn) setup(id string, hypervisorConfig *HypervisorConfig) error {
   288  	span, _ := a.trace("setup")
   289  	defer span.Finish()
   290  
   291  	err := hypervisorConfig.valid()
   292  	if err != nil {
   293  		return err
   294  	}
   295  
   296  	a.id = id
   297  	a.config = *hypervisorConfig
   298  	a.arch = newAcrnArch(a.config)
   299  
   300  	var create bool
   301  	var uuid string
   302  
   303  	if a.state.UUID == "" {
   304  		create = true
   305  	}
   306  
   307  	if create {
   308  		a.Logger().Debug("Setting UUID")
   309  		if uuid, err = a.GetNextAvailableUUID(); err != nil {
   310  			return err
   311  		}
   312  		a.state.UUID = uuid
   313  		Idx := acrnUUIDsToIdx[uuid]
   314  		a.info.UUIDAvailability[Idx] = UUIDBusy
   315  
   316  		// The path might already exist, but in case of VM templating,
   317  		// we have to create it since the sandbox has not created it yet.
   318  		if err = os.MkdirAll(filepath.Join(a.store.RunStoragePath(), id), DirMode); err != nil {
   319  			return err
   320  		}
   321  
   322  		if err = a.storeInfo(); err != nil {
   323  			return err
   324  		}
   325  	}
   326  
   327  	return nil
   328  }
   329  
   330  func (a *Acrn) createDummyVirtioBlkDev(devices []Device) ([]Device, error) {
   331  	span, _ := a.trace("createDummyVirtioBlkDev")
   332  	defer span.Finish()
   333  
   334  	// Since acrn doesn't support hot-plug, dummy virtio-blk
   335  	// devices are added and later replaced with container-rootfs.
   336  	// Starting from driveIndex 1, as 0 is allocated for VM rootfs.
   337  	for driveIndex := 1; driveIndex <= AcrnBlkDevPoolSz; driveIndex++ {
   338  		drive := config.BlockDrive{
   339  			File:  "nodisk",
   340  			Index: driveIndex,
   341  		}
   342  
   343  		devices = a.arch.appendBlockDevice(devices, drive)
   344  	}
   345  
   346  	return devices, nil
   347  }
   348  
   349  // createSandbox is the Hypervisor sandbox creation.
   350  func (a *Acrn) createSandbox(ctx context.Context, id string, networkNS NetworkNamespace, hypervisorConfig *HypervisorConfig, stateful bool) error {
   351  	// Save the tracing context
   352  	a.ctx = ctx
   353  
   354  	span, _ := a.trace("createSandbox")
   355  	defer span.Finish()
   356  
   357  	if err := a.setup(id, hypervisorConfig); err != nil {
   358  		return err
   359  	}
   360  
   361  	memory, err := a.memoryTopology()
   362  	if err != nil {
   363  		return err
   364  	}
   365  
   366  	kernelPath, err := a.config.KernelAssetPath()
   367  	if err != nil {
   368  		return err
   369  	}
   370  
   371  	imagePath, err := a.config.ImageAssetPath()
   372  	if err != nil {
   373  		return err
   374  	}
   375  
   376  	kernel := Kernel{
   377  		Path:      kernelPath,
   378  		ImagePath: imagePath,
   379  		Params:    a.kernelParameters(),
   380  	}
   381  
   382  	if a.state.UUID == "" {
   383  		return fmt.Errorf("ACRN UUID should not be empty")
   384  	}
   385  
   386  	devices, err := a.buildDevices(imagePath)
   387  	if err != nil {
   388  		return err
   389  	}
   390  
   391  	acrnPath, err := a.acrnPath()
   392  	if err != nil {
   393  		return err
   394  	}
   395  
   396  	acrnctlPath, err := a.acrnctlPath()
   397  	if err != nil {
   398  		return err
   399  	}
   400  
   401  	acrnConfig := Config{
   402  		UUID:     a.state.UUID,
   403  		ACPIVirt: true,
   404  		Path:     acrnPath,
   405  		CtlPath:  acrnctlPath,
   406  		Memory:   memory,
   407  		Devices:  devices,
   408  		Kernel:   kernel,
   409  		Name:     fmt.Sprintf("sandbox-%s", a.id),
   410  	}
   411  
   412  	a.acrnConfig = acrnConfig
   413  
   414  	return nil
   415  }
   416  
   417  // startSandbox will start the Sandbox's VM.
   418  func (a *Acrn) startSandbox(timeoutSecs int) error {
   419  	span, _ := a.trace("startSandbox")
   420  	defer span.Finish()
   421  
   422  	if a.config.Debug {
   423  		params := a.arch.kernelParameters(a.config.Debug)
   424  		strParams := SerializeParams(params, "=")
   425  		formatted := strings.Join(strParams, " ")
   426  
   427  		// The name of this field matches a similar one generated by
   428  		// the runtime and allows users to identify which parameters
   429  		// are set here, which come from the runtime and which are set
   430  		// by the user.
   431  		a.Logger().WithField("default-kernel-parameters", formatted).Debug()
   432  	}
   433  
   434  	vmPath := filepath.Join(a.store.RunVMStoragePath(), a.id)
   435  	err := os.MkdirAll(vmPath, DirMode)
   436  	if err != nil {
   437  		return err
   438  	}
   439  	defer func() {
   440  		if err != nil {
   441  			if err := os.RemoveAll(vmPath); err != nil {
   442  				a.Logger().WithError(err).Error("Failed to clean up vm directory")
   443  			}
   444  		}
   445  	}()
   446  
   447  	var strErr string
   448  	var PID int
   449  	PID, strErr, err = LaunchAcrn(a.acrnConfig, virtLog.WithField("subsystem", "acrn-dm"))
   450  	if err != nil {
   451  		return fmt.Errorf("%s", strErr)
   452  	}
   453  	a.state.PID = PID
   454  
   455  	if err = a.waitSandbox(timeoutSecs); err != nil {
   456  		a.Logger().WithField("acrn wait failed:", err).Debug()
   457  		return err
   458  	}
   459  
   460  	return nil
   461  }
   462  
   463  // waitSandbox will wait for the Sandbox's VM to be up and running.
   464  func (a *Acrn) waitSandbox(timeoutSecs int) error {
   465  	span, _ := a.trace("waitSandbox")
   466  	defer span.Finish()
   467  
   468  	if timeoutSecs < 0 {
   469  		return fmt.Errorf("Invalid timeout %ds", timeoutSecs)
   470  	}
   471  
   472  	time.Sleep(time.Duration(timeoutSecs) * time.Second)
   473  
   474  	return nil
   475  }
   476  
   477  // stopSandbox will stop the Sandbox's VM.
   478  func (a *Acrn) stopSandbox() (err error) {
   479  	span, _ := a.trace("stopSandbox")
   480  	defer span.Finish()
   481  
   482  	a.Logger().Info("Stopping acrn VM")
   483  
   484  	defer func() {
   485  		if err != nil {
   486  			a.Logger().Info("stopSandbox failed")
   487  		} else {
   488  			a.Logger().Info("acrn VM stopped")
   489  		}
   490  	}()
   491  
   492  	// Mark the UUID as free
   493  	uuid := a.state.UUID
   494  	Idx := acrnUUIDsToIdx[uuid]
   495  
   496  	if err = a.loadInfo(); err != nil {
   497  		a.Logger().Info("Failed to load UUID availabiity info")
   498  		return err
   499  	}
   500  
   501  	a.info.UUIDAvailability[Idx] = UUIDFree
   502  
   503  	if err = a.storeInfo(); err != nil {
   504  		a.Logger().Info("Failed to store UUID availabiity info")
   505  		return err
   506  	}
   507  
   508  	pid := a.state.PID
   509  
   510  	// Send signal to the VM process to try to stop it properly
   511  	if err = syscall.Kill(pid, syscall.SIGINT); err != nil {
   512  		if err == syscall.ESRCH {
   513  			return nil
   514  		}
   515  		a.Logger().Info("Sending signal to stop acrn VM failed")
   516  		return err
   517  	}
   518  
   519  	// Wait for the VM process to terminate
   520  	tInit := time.Now()
   521  	for {
   522  		if err = syscall.Kill(pid, syscall.Signal(0)); err != nil {
   523  			a.Logger().Info("acrn VM stopped after sending signal")
   524  			return nil
   525  		}
   526  
   527  		if time.Since(tInit).Seconds() >= acrnStopSandboxTimeoutSecs {
   528  			a.Logger().Warnf("VM still running after waiting %ds", acrnStopSandboxTimeoutSecs)
   529  			break
   530  		}
   531  
   532  		// Let's avoid to run a too busy loop
   533  		time.Sleep(time.Duration(50) * time.Millisecond)
   534  	}
   535  
   536  	// Let's try with a hammer now, a SIGKILL should get rid of the
   537  	// VM process.
   538  	return syscall.Kill(pid, syscall.SIGKILL)
   539  
   540  }
   541  
   542  func (a *Acrn) updateBlockDevice(drive *config.BlockDrive) error {
   543  	var err error
   544  	if drive.File == "" || drive.Index >= AcrnBlkDevPoolSz {
   545  		return fmt.Errorf("Empty filepath or invalid drive index, Dive ID:%s, Drive Index:%d",
   546  			drive.ID, drive.Index)
   547  	}
   548  
   549  	slot := AcrnBlkdDevSlot[drive.Index]
   550  
   551  	//Explicitly set PCIAddr to NULL, so that VirtPath can be used
   552  	drive.PCIAddr = ""
   553  
   554  	args := []string{"blkrescan", a.acrnConfig.Name, fmt.Sprintf("%d,%s", slot, drive.File)}
   555  
   556  	a.Logger().WithFields(logrus.Fields{
   557  		"drive": drive,
   558  		"path":  a.config.HypervisorCtlPath,
   559  	}).Info("updateBlockDevice with acrnctl path")
   560  	cmd := exec.Command(a.config.HypervisorCtlPath, args...)
   561  	if err := cmd.Run(); err != nil {
   562  		a.Logger().WithError(err).Error("updating Block device with newFile path")
   563  	}
   564  
   565  	return err
   566  }
   567  
   568  func (a *Acrn) hotplugAddDevice(devInfo interface{}, devType deviceType) (interface{}, error) {
   569  	span, _ := a.trace("hotplugAddDevice")
   570  	defer span.Finish()
   571  
   572  	switch devType {
   573  	case blockDev:
   574  		//The drive placeholder has to exist prior to Update
   575  		return nil, a.updateBlockDevice(devInfo.(*config.BlockDrive))
   576  	default:
   577  		return nil, fmt.Errorf("hotplugAddDevice: unsupported device: devInfo:%v, deviceType%v",
   578  			devInfo, devType)
   579  	}
   580  }
   581  
   582  func (a *Acrn) hotplugRemoveDevice(devInfo interface{}, devType deviceType) (interface{}, error) {
   583  	span, _ := a.trace("hotplugRemoveDevice")
   584  	defer span.Finish()
   585  
   586  	// Not supported. return success
   587  
   588  	return nil, nil
   589  }
   590  
   591  func (a *Acrn) pauseSandbox() error {
   592  	span, _ := a.trace("pauseSandbox")
   593  	defer span.Finish()
   594  
   595  	// Not supported. return success
   596  
   597  	return nil
   598  }
   599  
   600  func (a *Acrn) resumeSandbox() error {
   601  	span, _ := a.trace("resumeSandbox")
   602  	defer span.Finish()
   603  
   604  	// Not supported. return success
   605  
   606  	return nil
   607  }
   608  
   609  // addDevice will add extra devices to acrn command line.
   610  func (a *Acrn) addDevice(devInfo interface{}, devType deviceType) error {
   611  	var err error
   612  	span, _ := a.trace("addDevice")
   613  	defer span.Finish()
   614  
   615  	switch v := devInfo.(type) {
   616  	case types.Volume:
   617  		// Not supported. return success
   618  		err = nil
   619  	case types.Socket:
   620  		a.acrnConfig.Devices = a.arch.appendSocket(a.acrnConfig.Devices, v)
   621  	case types.VSock:
   622  		// Not supported. return success
   623  		err = nil
   624  	case Endpoint:
   625  		a.acrnConfig.Devices = a.arch.appendNetwork(a.acrnConfig.Devices, v)
   626  	case config.BlockDrive:
   627  		a.acrnConfig.Devices = a.arch.appendBlockDevice(a.acrnConfig.Devices, v)
   628  	case config.VhostUserDeviceAttrs:
   629  		// Not supported. return success
   630  		err = nil
   631  	case config.VFIODev:
   632  		// Not supported. return success
   633  		err = nil
   634  	default:
   635  		err = nil
   636  		a.Logger().WithField("unknown-device-type", devInfo).Error("Adding device")
   637  	}
   638  
   639  	return err
   640  }
   641  
   642  // getSandboxConsole builds the path of the console where we can read
   643  // logs coming from the sandbox.
   644  func (a *Acrn) getSandboxConsole(id string) (string, error) {
   645  	span, _ := a.trace("getSandboxConsole")
   646  	defer span.Finish()
   647  
   648  	return utils.BuildSocketPath(a.store.RunVMStoragePath(), id, acrnConsoleSocket)
   649  }
   650  
   651  func (a *Acrn) saveSandbox() error {
   652  	a.Logger().Info("save sandbox")
   653  
   654  	// Not supported. return success
   655  
   656  	return nil
   657  }
   658  
   659  func (a *Acrn) disconnect() {
   660  	span, _ := a.trace("disconnect")
   661  	defer span.Finish()
   662  
   663  	// Not supported.
   664  }
   665  
   666  func (a *Acrn) getThreadIDs() (vcpuThreadIDs, error) {
   667  	span, _ := a.trace("getThreadIDs")
   668  	defer span.Finish()
   669  
   670  	// Not supported. return success
   671  	//Just allocating an empty map
   672  
   673  	return vcpuThreadIDs{}, nil
   674  }
   675  
   676  func (a *Acrn) resizeMemory(reqMemMB uint32, memoryBlockSizeMB uint32, probe bool) (uint32, memoryDevice, error) {
   677  	return 0, memoryDevice{}, nil
   678  }
   679  
   680  func (a *Acrn) resizeVCPUs(reqVCPUs uint32) (currentVCPUs uint32, newVCPUs uint32, err error) {
   681  	return 0, 0, nil
   682  }
   683  
   684  func (a *Acrn) cleanup() error {
   685  	span, _ := a.trace("cleanup")
   686  	defer span.Finish()
   687  
   688  	return nil
   689  }
   690  
   691  func (a *Acrn) getPids() []int {
   692  	return []int{a.state.PID}
   693  }
   694  
   695  func (a *Acrn) fromGrpc(ctx context.Context, hypervisorConfig *HypervisorConfig, j []byte) error {
   696  	return errors.New("acrn is not supported by VM cache")
   697  }
   698  
   699  func (a *Acrn) toGrpc() ([]byte, error) {
   700  	return nil, errors.New("acrn is not supported by VM cache")
   701  }
   702  
   703  func (a *Acrn) save() (s persistapi.HypervisorState) {
   704  	s.Pid = a.state.PID
   705  	s.Type = string(AcrnHypervisor)
   706  	s.UUID = a.state.UUID
   707  	return
   708  }
   709  
   710  func (a *Acrn) load(s persistapi.HypervisorState) {
   711  	a.state.PID = s.Pid
   712  	a.state.UUID = s.UUID
   713  }
   714  
   715  func (a *Acrn) check() error {
   716  	if err := syscall.Kill(a.state.PID, syscall.Signal(0)); err != nil {
   717  		return errors.Wrapf(err, "failed to ping acrn process")
   718  	}
   719  
   720  	return nil
   721  }
   722  
   723  func (a *Acrn) generateSocket(id string, useVsock bool) (interface{}, error) {
   724  	return generateVMSocket(id, useVsock, a.store.RunVMStoragePath())
   725  }
   726  
   727  // GetACRNUUIDBytes returns UUID bytes that is used for VM creation
   728  func (a *Acrn) GetACRNUUIDBytes(uid string) (uuid.UUID, error) {
   729  	return uuid.Parse(uid)
   730  }
   731  
   732  // GetNextAvailableUUID returns next available UUID VM creation
   733  // If no valid UUIDs are available it returns err.
   734  func (a *Acrn) GetNextAvailableUUID() (string, error) {
   735  	var MaxVMSupported uint8
   736  	var Idx uint8
   737  	var uuidStr string
   738  	var err error
   739  
   740  	if err = a.loadInfo(); err != nil {
   741  		a.Logger().Infof("Load UUID store failed")
   742  	}
   743  
   744  	if MaxVMSupported, err = a.GetMaxSupportedACRNVM(); err != nil {
   745  		return "", fmt.Errorf("IOCTL GetMaxSupportedACRNVM failed")
   746  	}
   747  
   748  	for Idx = 0; Idx < MaxVMSupported; Idx++ {
   749  		if a.info.UUIDAvailability[Idx] == UUIDFree {
   750  			uuidStr = acrnIdxToUUIDs[Idx]
   751  			break
   752  		}
   753  	}
   754  
   755  	if uuidStr == "" {
   756  		return "", fmt.Errorf("Invalid UUID: Max VMs reached")
   757  	}
   758  
   759  	return uuidStr, nil
   760  }
   761  
   762  // GetMaxSupportedACRNVM checks the max number of VMs that can be
   763  // launched from kata-runtime.
   764  func (a *Acrn) GetMaxSupportedACRNVM() (uint8, error) {
   765  	flags := syscall.O_RDWR | syscall.O_CLOEXEC
   766  
   767  	f, err := syscall.Open(acrnDevice, flags, 0)
   768  	if err != nil {
   769  		return 0, err
   770  	}
   771  	defer syscall.Close(f)
   772  
   773  	var platformInfo acrnPlatformInfo
   774  
   775  	ret, _, errno := syscall.Syscall(syscall.SYS_IOCTL,
   776  		uintptr(f),
   777  		uintptr(ioctl_ACRN_GET_PLATFORM_INFO),
   778  		uintptr(unsafe.Pointer(&platformInfo)))
   779  	if ret != 0 || errno != 0 {
   780  		return 0, errno
   781  	}
   782  
   783  	return platformInfo.maxKataContainers, nil
   784  }
   785  
   786  func (a *Acrn) storeInfo() error {
   787  	relPath := filepath.Join(UUIDPathSuffix, uuidFile)
   788  
   789  	jsonOut, err := json.Marshal(a.info)
   790  	if err != nil {
   791  		return fmt.Errorf("Could not marshal data: %s", err)
   792  	}
   793  
   794  	if err := a.store.GlobalWrite(relPath, jsonOut); err != nil {
   795  		return fmt.Errorf("failed to write uuid to file: %v", err)
   796  	}
   797  
   798  	return nil
   799  }
   800  
   801  func (a *Acrn) loadInfo() error {
   802  	relPath := filepath.Join(UUIDPathSuffix, uuidFile)
   803  
   804  	data, err := a.store.GlobalRead(relPath)
   805  	if err != nil {
   806  		return fmt.Errorf("failed to read uuid from file: %v", err)
   807  	}
   808  
   809  	if err := json.Unmarshal(data, &a.info); err != nil {
   810  		return fmt.Errorf("failed to unmarshal uuid info: %v", err)
   811  	}
   812  	return nil
   813  }