mirror of
https://hubproxy.babadafafafafa.cn/https://github.com/yunionio/cloudpods.git
synced 2026-09-20 08:03:53 +08:00
feat(region,host,scheduler): isolated device refactor and hami support (#25129)
This commit is contained in:
@@ -26,8 +26,12 @@ func init() {
|
||||
cmd.List(&compute.DeviceListOptions{})
|
||||
cmd.Update(&compute.DeviceUpdateOptions{})
|
||||
cmd.Show(&compute.DeviceShowOptions{})
|
||||
cmd.Create(&compute.DeviceCreateOptions{})
|
||||
cmd.BatchDelete(&compute.DeviceDeleteOptions{})
|
||||
cmd.BatchPerform("purge", &compute.DevicePurgeOptions{})
|
||||
cmd.Perform("public", &options.SharableResourcePublicOptions{})
|
||||
cmd.Perform("private", &options.BaseIdOptions{})
|
||||
|
||||
scmd := shell.NewResourceCmd(&modules.ServerIsolatedDevices)
|
||||
scmd.List(&compute.ServerDeviceListOptions{})
|
||||
}
|
||||
|
||||
@@ -23,15 +23,15 @@ import (
|
||||
|
||||
func init() {
|
||||
type ServerAttachDeviceOptions struct {
|
||||
SERVER string `help:"ID or name of server"`
|
||||
DEVICE string `help:"ID of isolated device to attach"`
|
||||
Type string `help:"Device type" choices:"GPU-HPC|GPU-VGA|PCI"`
|
||||
SERVER string `help:"ID or name of server"`
|
||||
DEVICE string `help:"ID of isolated device to attach"`
|
||||
GpuType string `help:"Type of GPU to attach to" choices:"HPC|VGA"`
|
||||
}
|
||||
R(&ServerAttachDeviceOptions{}, "server-attach-isolated-device", "Attach an existing isolated device to a virtual server", func(s *mcclient.ClientSession, args *ServerAttachDeviceOptions) error {
|
||||
params := jsonutils.NewDict()
|
||||
params.Add(jsonutils.NewString(args.DEVICE), "device")
|
||||
if len(args.Type) > 0 {
|
||||
params.Add(jsonutils.NewString(args.Type), "dev_type")
|
||||
if args.GpuType != "" {
|
||||
params.Add(jsonutils.NewString(args.GpuType), "gpu_type")
|
||||
}
|
||||
srv, err := modules.Servers.PerformAction(s, args.SERVER, "attach-isolated-device", params)
|
||||
if err != nil {
|
||||
@@ -44,11 +44,13 @@ func init() {
|
||||
type ServerDetachDeviceOptions struct {
|
||||
SERVER string `help:"ID or name of server"`
|
||||
DEVICE string `help:"ID of isolated device to detach"`
|
||||
INDEX int `help:"Index of isolated device to detach"`
|
||||
IsForce bool `help:"Force detach isolated device"`
|
||||
}
|
||||
R(&ServerDetachDeviceOptions{}, "server-detach-isolated-device", "Detach a isolated device from a virtual server", func(s *mcclient.ClientSession, args *ServerDetachDeviceOptions) error {
|
||||
params := jsonutils.NewDict()
|
||||
params.Add(jsonutils.NewString(args.DEVICE), "device")
|
||||
params.Add(jsonutils.NewInt(int64(args.INDEX)), "index")
|
||||
if args.IsForce {
|
||||
params.Set("is_force", jsonutils.JSONTrue)
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ import (
|
||||
"yunion.io/x/pkg/util/signalutils"
|
||||
"yunion.io/x/pkg/utils"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/hostman/isolated_device"
|
||||
"yunion.io/x/onecloud/pkg/hostman/isolated_device/container_device"
|
||||
"yunion.io/x/onecloud/pkg/hostman/options"
|
||||
@@ -67,7 +68,7 @@ func NewDaemon() (*Daemon, error) {
|
||||
}
|
||||
for i := range devCfg.Devices {
|
||||
if devCfg.Devices[i].Type == isolated_device.ContainerDeviceTypeNvidiaMps {
|
||||
dev, err := container_device.NewPCIGPURenderBaseDevice(devCfg.Devices[i].Path, 0, isolated_device.ContainerDeviceTypeNvidiaMps)
|
||||
dev, err := container_device.NewPCIGPURenderBaseDevice(devCfg.Devices[i].Path, 0, api.GPU_TYPE, api.DEVICE_SHARING_MODE_MPS)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "parse pci device %s", devCfg.Devices[i].Path)
|
||||
}
|
||||
|
||||
@@ -315,17 +315,22 @@ type IsolatedDeviceConfig struct {
|
||||
Id string `json:"id"`
|
||||
DevType string `json:"dev_type"`
|
||||
Model string `json:"model"`
|
||||
SharingMode string `json:"sharing_mode"`
|
||||
Vendor string `json:"vendor"`
|
||||
NetworkIndex *int `json:"network_index"`
|
||||
WireId string `json:"wire_id"`
|
||||
DiskIndex *int8 `json:"disk_index"`
|
||||
DevicePath string `json:"device_path"`
|
||||
GpuType string `json:"gpu_type"`
|
||||
// MemoryMb is the minimum on-device memory in MiB required from the
|
||||
// candidate isolated_device (e.g. NVIDIA GPU VRAM). 0 means no constraint.
|
||||
// The scheduler excludes devices whose memory_size > 0 and is below this
|
||||
// threshold; devices with memory_size == 0 are treated as unknown and
|
||||
// allowed through to avoid penalising hosts that haven't reported yet.
|
||||
MemoryMb int `json:"memory_mb,omitempty"`
|
||||
// Memory request for Devices allocate by Memory size
|
||||
MemoryRequest int `json:"memory_request,omitempty"`
|
||||
SmUtilLimit int `json:"sm_util_limit,omitempty"`
|
||||
}
|
||||
|
||||
type BaremetalDiskConfig struct {
|
||||
|
||||
@@ -40,6 +40,7 @@ const (
|
||||
CONTAINER_DEV_NVIDIA_GPU = "NVIDIA_GPU"
|
||||
CONTAINER_DEV_NVIDIA_MPS = "NVIDIA_MPS"
|
||||
CONTAINER_DEV_NVIDIA_GPU_SHARE = "NVIDIA_GPU_SHARE"
|
||||
CONTAINER_DEV_NVIDIA_HAMI = "NVIDIA_HAMI"
|
||||
CONTAINER_DEV_ASCEND_NPU = "ASCEND_NPU"
|
||||
CONTAINER_DEV_VASTAITECH_GPU = "VASTAITECH_GPU"
|
||||
)
|
||||
@@ -49,14 +50,16 @@ var (
|
||||
CONTAINER_DEV_CPH_AMD_GPU,
|
||||
CONTAINER_DEV_NVIDIA_GPU,
|
||||
CONTAINER_DEV_NVIDIA_MPS,
|
||||
CONTAINER_DEV_NVIDIA_HAMI,
|
||||
CONTAINER_DEV_NVIDIA_GPU_SHARE,
|
||||
CONTAINER_DEV_VASTAITECH_GPU,
|
||||
}
|
||||
)
|
||||
|
||||
var NVIDIA_GPU_TYPES = []string{
|
||||
var CONTAINER_NVIDIA_GPU_TYPES = []string{
|
||||
CONTAINER_DEV_NVIDIA_GPU,
|
||||
CONTAINER_DEV_NVIDIA_MPS,
|
||||
CONTAINER_DEV_NVIDIA_HAMI,
|
||||
CONTAINER_DEV_NVIDIA_GPU_SHARE,
|
||||
}
|
||||
|
||||
@@ -198,10 +201,11 @@ type ContainerHostDevice struct {
|
||||
}
|
||||
|
||||
type ContainerIsolatedDevice struct {
|
||||
Index *int `json:"index"`
|
||||
Id string `json:"id"`
|
||||
OnlyEnv []*apis.ContainerIsolatedDeviceOnlyEnv `json:"only_env"`
|
||||
CDI *apis.ContainerIsolatedDeviceCDI `json:"cdi"`
|
||||
Index *int `json:"index"`
|
||||
Id string `json:"id"`
|
||||
GuestIsolatedDeviceIndex int `json:"guest_isolated_device_index"`
|
||||
OnlyEnv []*apis.ContainerIsolatedDeviceOnlyEnv `json:"only_env"`
|
||||
CDI *apis.ContainerIsolatedDeviceCDI `json:"cdi"`
|
||||
}
|
||||
|
||||
type ContainerDevice struct {
|
||||
|
||||
@@ -131,6 +131,8 @@ type ServerListInput struct {
|
||||
|
||||
SnapshotpolicyId string `json:"snapshotpolicy_id"`
|
||||
|
||||
IsolatedDeviceId string `json:"isolated_device_id"`
|
||||
|
||||
// 是否调度到宿主机上
|
||||
WithHost *bool `json:"with_host"`
|
||||
|
||||
@@ -1571,8 +1573,25 @@ func (conf ServerChangeConfigSettings) AddedDisk() int {
|
||||
}
|
||||
|
||||
type ServerReleasedIsolatedDevice struct {
|
||||
DevType string `json:"dev_type"`
|
||||
Model string `json:"model"`
|
||||
DevType string `json:"dev_type"`
|
||||
Model string `json:"model"`
|
||||
GpuType string `json:"gpu_type"`
|
||||
SharingMode string `json:"sharing_mode"`
|
||||
MemoryRequest int `json:"memory_request"`
|
||||
}
|
||||
|
||||
type ServerAttachIsolatedDeviceBase struct {
|
||||
AutoStart bool `json:"auto_start"`
|
||||
GpuType string `json:"gpu_type"`
|
||||
MemoryRequest *int `json:"memory_request"`
|
||||
SharingMode string `json:"sharing_mode"`
|
||||
Count *int `json:"count"`
|
||||
}
|
||||
|
||||
type ServerAttachIsolatedDeviceInput struct {
|
||||
ServerAttachIsolatedDeviceBase
|
||||
Device string `json:"device"`
|
||||
Model string `json:"model"`
|
||||
}
|
||||
|
||||
type ServerChangeBillingTypeInput struct {
|
||||
|
||||
@@ -775,7 +775,7 @@ type HostUploadGuestsStatusInput struct {
|
||||
}
|
||||
|
||||
type HostIsolatedDeviceNumaStatsInput struct {
|
||||
DevType string
|
||||
Model string
|
||||
}
|
||||
|
||||
type GuestUploadContainerStatusResponse struct {
|
||||
|
||||
@@ -34,10 +34,13 @@ type IsolateDeviceDetails struct {
|
||||
|
||||
SIsolatedDevice
|
||||
|
||||
MemoryAllocated int
|
||||
AllocatedCount int
|
||||
|
||||
// 云主机名称
|
||||
Guest string `json:"guest"`
|
||||
Guest []string `json:"guest"`
|
||||
// 云主机状态
|
||||
GuestStatus string `json:"guest_status"`
|
||||
GuestStatus []string `json:"guest_status"`
|
||||
}
|
||||
|
||||
type IsolatedDeviceListInput struct {
|
||||
@@ -95,6 +98,9 @@ type IsolatedDeviceCreateInput struct {
|
||||
// example: GPU
|
||||
DevType string `json:"dev_type"`
|
||||
|
||||
// DEVICE sharing mode
|
||||
SharingMode string `json:"sharing_mode"`
|
||||
|
||||
// 设备型号
|
||||
// # Specific device name read from lspci command, e.g. `Tesla K40m` ...
|
||||
Model string `json:"model"`
|
||||
@@ -137,9 +143,28 @@ type IsolatedDeviceUpdateInput struct {
|
||||
DeviceMinor int `json:"device_minor"`
|
||||
}
|
||||
|
||||
type SDelIsolatedDeviceInput struct {
|
||||
Device string
|
||||
Index int
|
||||
}
|
||||
|
||||
type SAddIsolatedDeviceInput struct {
|
||||
Device string
|
||||
GpuType string
|
||||
MemoryRequest *int
|
||||
}
|
||||
|
||||
type SetIsolatedDeviceInput struct {
|
||||
AddDevices []SAddIsolatedDeviceInput
|
||||
DelDevices []SDelIsolatedDeviceInput
|
||||
AutoStart bool
|
||||
}
|
||||
|
||||
type IsolatedDeviceJsonDesc struct {
|
||||
Id string `json:"id"`
|
||||
DevType string `json:"dev_type"`
|
||||
GpuType string `json:"gpu_type"`
|
||||
SharingMode string `json:"sharing_mode"`
|
||||
Model string `json:"model"`
|
||||
Addr string `json:"addr"`
|
||||
VendorDeviceId string `json:"vendor_device_id"`
|
||||
@@ -152,6 +177,8 @@ type IsolatedDeviceJsonDesc struct {
|
||||
MemorySize int `json:"memory_size"`
|
||||
MdevId string `json:"mdev_id"`
|
||||
NumaNode int8 `json:"numa_node"`
|
||||
MemoryLimit int `json:"memory_limit"`
|
||||
SmUtilLimit int `json:"sm_util_limit"`
|
||||
}
|
||||
|
||||
type IsolatedDeviceModelCreateInput struct {
|
||||
@@ -368,3 +395,22 @@ type HostIsolatedDeviceModelDetails struct {
|
||||
HotPluggable bool
|
||||
DisableAutoDetect bool
|
||||
}
|
||||
|
||||
type IsolatedDeviceFilterListInput struct {
|
||||
IsolateDeviceIds []string `json:"isolate_device_ids"`
|
||||
}
|
||||
|
||||
type GuestIsolatedDeviceListInput struct {
|
||||
GuestJointsListInput
|
||||
|
||||
IsolatedDeviceListInput
|
||||
IsolatedDeviceFilterListInput
|
||||
}
|
||||
|
||||
type GuestIsolatedDeviceDetails struct {
|
||||
GuestJointResourceDetails
|
||||
SGuestIsolatedDevice
|
||||
SIsolatedDevice
|
||||
HostResourceInfo
|
||||
apis.SharableResourceBaseInfo
|
||||
}
|
||||
|
||||
@@ -15,25 +15,83 @@
|
||||
package compute
|
||||
|
||||
const (
|
||||
DIRECT_PCI_TYPE = "PCI"
|
||||
GPU_HPC_TYPE = "GPU-HPC" // # for compute
|
||||
GPU_VGA_TYPE = "GPU-VGA" // # for display
|
||||
SRIOV_VGPU_TYPE = "SRIOV-VGPU"
|
||||
LEGACY_VGPU_TYPE = "LEGACY-VGPU"
|
||||
USB_TYPE = "USB"
|
||||
NIC_TYPE = "NIC" // nic sriov
|
||||
NVME_PT_TYPE = "NVME-PT" // nvme passthrough
|
||||
|
||||
NVIDIA_VENDOR_ID = "10de"
|
||||
AMD_VENDOR_ID = "1002"
|
||||
DIRECT_PCI_TYPE = "PCI"
|
||||
GPU_TYPE = "GPU"
|
||||
USB_TYPE = "USB"
|
||||
NIC_TYPE = "NIC" // nic sriov
|
||||
NVME_PT_TYPE = "NVME-PT" // nvme passthrough
|
||||
NETINT_TYPE = "NETINT"
|
||||
NPU_TYPE = "NPU"
|
||||
BINDER_TYPE = "BINDER"
|
||||
)
|
||||
|
||||
var VALID_GPU_TYPES = []string{GPU_HPC_TYPE, GPU_VGA_TYPE}
|
||||
var VALID_ATTACH_TYPES = []string{GPU_HPC_TYPE, GPU_VGA_TYPE, USB_TYPE, SRIOV_VGPU_TYPE, LEGACY_VGPU_TYPE}
|
||||
var VALID_TYPES = []string{DIRECT_PCI_TYPE, GPU_TYPE, USB_TYPE, NIC_TYPE, NVME_PT_TYPE, NETINT_TYPE, NPU_TYPE, BINDER_TYPE}
|
||||
|
||||
const (
|
||||
DEVICE_SHARING_MODE_EXCLUSIVE = "EXCLUSIVE"
|
||||
DEVICE_SHARING_MODE_SRIOV = "SRIOV"
|
||||
DEVICE_SHARING_MODE_MPS = "MPS"
|
||||
DEVICE_SHARING_MODE_HAMI = "HAMI"
|
||||
DEVICE_SHARING_MODE_UNLIMITED = "UNLIMITED"
|
||||
DEVICE_SHARING_MODE_MDEV = "MDEV"
|
||||
)
|
||||
|
||||
var VIRTUAL_SHARING_MODES = []string{DEVICE_SHARING_MODE_HAMI, DEVICE_SHARING_MODE_UNLIMITED, DEVICE_SHARING_MODE_MPS}
|
||||
var VAILD_SHARING_MODES = []string{DEVICE_SHARING_MODE_EXCLUSIVE, DEVICE_SHARING_MODE_SRIOV, DEVICE_SHARING_MODE_MDEV, DEVICE_SHARING_MODE_HAMI, DEVICE_SHARING_MODE_UNLIMITED, DEVICE_SHARING_MODE_MPS}
|
||||
|
||||
const (
|
||||
GPU_HPC = "HPC"
|
||||
GPU_VGA = "VGA"
|
||||
)
|
||||
|
||||
const (
|
||||
NVIDIA_VENDOR_ID = "10de"
|
||||
AMD_VENDOR_ID = "1002"
|
||||
VASTAITECH_VENDOR_ID = "1ec6"
|
||||
)
|
||||
|
||||
var ID_VENDOR_MAP = map[string]string{
|
||||
NVIDIA_VENDOR_ID: "NVIDIA",
|
||||
AMD_VENDOR_ID: "AMD",
|
||||
VASTAITECH_VENDOR_ID: "VASTAITECH",
|
||||
}
|
||||
|
||||
var VENDOR_ID_MAP = map[string]string{
|
||||
"NVIDIA": NVIDIA_VENDOR_ID,
|
||||
"AMD": AMD_VENDOR_ID,
|
||||
}
|
||||
|
||||
const (
|
||||
ISOLATED_DEVICE_MODEL_METADATA_BANDWIDTH = "bandwidth"
|
||||
ISOLATED_DEVICE_MODEL_METADATA_MEMORY_MB = "memory_mb"
|
||||
ISOLATED_DEVICE_MODEL_METADATA_TFLOPS = "tflops"
|
||||
)
|
||||
|
||||
////////////// deprecated
|
||||
|
||||
const (
|
||||
GPU_HPC_TYPE = "GPU-HPC" // # for compute
|
||||
GPU_VGA_TYPE = "GPU-VGA" // # for display
|
||||
SRIOV_VGPU_TYPE = "SRIOV-VGPU" //done
|
||||
LEGACY_VGPU_TYPE = "LEGACY-VGPU" //done
|
||||
)
|
||||
|
||||
var VALID_GPU_TYPES = []string{GPU_HPC_TYPE, GPU_VGA_TYPE} //done
|
||||
var VALID_ATTACH_TYPES = []string{GPU_HPC_TYPE, GPU_VGA_TYPE, USB_TYPE, SRIOV_VGPU_TYPE, LEGACY_VGPU_TYPE} //done
|
||||
|
||||
var GPU_TYPES = []string{
|
||||
GPU_HPC_TYPE, GPU_VGA_TYPE, SRIOV_VGPU_TYPE, LEGACY_VGPU_TYPE,
|
||||
CONTAINER_DEV_CPH_AMD_GPU, CONTAINER_DEV_NVIDIA_GPU, CONTAINER_DEV_NVIDIA_MPS, CONTAINER_DEV_NVIDIA_GPU_SHARE,
|
||||
CONTAINER_DEV_NVIDIA_HAMI, CONTAINER_DEV_VASTAITECH_GPU,
|
||||
}
|
||||
|
||||
var NETINT_TYPES = []string{
|
||||
CONTAINER_DEV_NETINT_CA_QUADRA, CONTAINER_DEV_NETINT_CA_ASIC,
|
||||
}
|
||||
|
||||
var VALID_CONTAINER_DEVICE_TYPES = []string{
|
||||
CONTAINER_DEV_CPH_AMD_GPU, CONTAINER_DEV_CPH_AOSP_BINDER, CONTAINER_DEV_NETINT_CA_QUADRA,
|
||||
CONTAINER_DEV_NETINT_CA_ASIC, CONTAINER_DEV_NVIDIA_GPU, CONTAINER_DEV_NVIDIA_MPS, CONTAINER_DEV_NVIDIA_GPU_SHARE,
|
||||
CONTAINER_DEV_NETINT_CA_ASIC, CONTAINER_DEV_NVIDIA_GPU, CONTAINER_DEV_NVIDIA_MPS, CONTAINER_DEV_NVIDIA_GPU_SHARE, CONTAINER_DEV_NVIDIA_HAMI,
|
||||
CONTAINER_DEV_ASCEND_NPU, CONTAINER_DEV_VASTAITECH_GPU,
|
||||
}
|
||||
|
||||
@@ -49,27 +107,12 @@ var VITRUAL_DEVICE_TYPES = []string{
|
||||
CONTAINER_DEV_NETINT_CA_QUADRA,
|
||||
CONTAINER_DEV_NETINT_CA_ASIC,
|
||||
CONTAINER_DEV_NVIDIA_MPS,
|
||||
CONTAINER_DEV_NVIDIA_HAMI,
|
||||
CONTAINER_DEV_ASCEND_NPU,
|
||||
CONTAINER_DEV_NVIDIA_GPU_SHARE,
|
||||
CONTAINER_DEV_VASTAITECH_GPU,
|
||||
}
|
||||
|
||||
var ID_VENDOR_MAP = map[string]string{
|
||||
NVIDIA_VENDOR_ID: "NVIDIA",
|
||||
AMD_VENDOR_ID: "AMD",
|
||||
}
|
||||
|
||||
var VENDOR_ID_MAP = map[string]string{
|
||||
"NVIDIA": NVIDIA_VENDOR_ID,
|
||||
"AMD": AMD_VENDOR_ID,
|
||||
}
|
||||
|
||||
const (
|
||||
ISOLATED_DEVICE_MODEL_METADATA_BANDWIDTH = "bandwidth"
|
||||
ISOLATED_DEVICE_MODEL_METADATA_MEMORY_MB = "memory_mb"
|
||||
ISOLATED_DEVICE_MODEL_METADATA_TFLOPS = "tflops"
|
||||
)
|
||||
|
||||
func init() {
|
||||
VALID_PASSTHROUGH_TYPES = append(VALID_PASSTHROUGH_TYPES, VALID_CONTAINER_DEVICE_TYPES...)
|
||||
VALID_ATTACH_TYPES = append(VALID_ATTACH_TYPES, VALID_CONTAINER_DEVICE_TYPES...)
|
||||
|
||||
@@ -23,6 +23,13 @@ import (
|
||||
"yunion.io/x/onecloud/pkg/apis/cloudprovider"
|
||||
)
|
||||
|
||||
// IsolatedDeviceAllocateStat is an autogenerated struct via yunion.io/x/onecloud/pkg/compute/models.IsolatedDeviceAllocateStat.
|
||||
type IsolatedDeviceAllocateStat struct {
|
||||
SIsolatedDevice
|
||||
GuestCount int `json:"guest_count"`
|
||||
MemoryAllocated int `json:"memory_allocated"`
|
||||
}
|
||||
|
||||
// SAccessGroup is an autogenerated struct via yunion.io/x/onecloud/pkg/compute/models.SAccessGroup.
|
||||
type SAccessGroup struct {
|
||||
apis.SStatusInfrasResourceBase
|
||||
@@ -167,6 +174,7 @@ type SBucket struct {
|
||||
SizeBytesLimit int64 `json:"size_bytes_limit"`
|
||||
ObjectCntLimit int `json:"object_cnt_limit"`
|
||||
AccessUrls jsonutils.JSONObject `json:"access_urls"`
|
||||
EnablePerfMon bool `json:"enable_perf_mon"`
|
||||
}
|
||||
|
||||
// SCDNDomain is an autogenerated struct via yunion.io/x/onecloud/pkg/compute/models.SCDNDomain.
|
||||
@@ -650,6 +658,8 @@ type SDnsRecord struct {
|
||||
DnsValue string `json:"dns_value"`
|
||||
TTL int64 `json:"ttl"`
|
||||
MxPriority int64 `json:"mx_priority"`
|
||||
// cloudflare 特有
|
||||
Proxied *bool `json:"proxied,omitempty"`
|
||||
// 解析线路类型
|
||||
PolicyType string `json:"policy_type"`
|
||||
// 解析线路
|
||||
@@ -940,6 +950,10 @@ type SElasticip struct {
|
||||
BgpType string `json:"bgp_type"`
|
||||
// 是否跟随主机删除而自动释放
|
||||
AutoDellocate *bool `json:"auto_dellocate,omitempty"`
|
||||
// 下行带宽限制,单位mbps
|
||||
RxBwLimit int `json:"rx_bw_limit"`
|
||||
// 上行带宽限制,单位mbps
|
||||
TxBwLimit int `json:"tx_bw_limit"`
|
||||
}
|
||||
|
||||
// SExternalProject is an autogenerated struct via yunion.io/x/onecloud/pkg/compute/models.SExternalProject.
|
||||
@@ -1114,6 +1128,23 @@ type SGuest struct {
|
||||
ResourcePool string `json:"resource_pool"`
|
||||
}
|
||||
|
||||
// SGuestIsolatedDevice is an autogenerated struct via yunion.io/x/onecloud/pkg/compute/models.SGuestIsolatedDevice.
|
||||
type SGuestIsolatedDevice struct {
|
||||
SGuestJointsBase
|
||||
SIsolatedDeviceResourceBase
|
||||
// guest isolated device memory size limit
|
||||
DeviceMemorySize int `json:"device_memory_size"`
|
||||
// guest isolated device Streaming Multiprocessor Utilization limit
|
||||
SmUtilLimit int `json:"sm_util_limit"`
|
||||
// gpu device work type: HPC VGA
|
||||
GpuType string `json:"gpu_type"`
|
||||
// guest network index
|
||||
NetworkIndex int `json:"network_index"`
|
||||
// guest disk index
|
||||
DiskIndex byte `json:"disk_index"`
|
||||
Index byte `json:"index"`
|
||||
}
|
||||
|
||||
// SGuestJointsBase is an autogenerated struct via yunion.io/x/onecloud/pkg/compute/models.SGuestJointsBase.
|
||||
type SGuestJointsBase struct {
|
||||
apis.SVirtualJointResourceBase
|
||||
@@ -1125,11 +1156,13 @@ type SGuestNetworkTrafficLog struct {
|
||||
apis.SLogBase
|
||||
apis.SProjectizedResourceBase
|
||||
SGuestResourceBase
|
||||
SNetworkResourceBase
|
||||
// MAC地址
|
||||
Mac string `json:"mac"`
|
||||
// IPv4地址
|
||||
IpAddr string `json:"ip_addr"`
|
||||
// IPv6地址
|
||||
Ip6Addr string `json:"ip6_addr"`
|
||||
RowId int64 `json:"row_id"`
|
||||
// 下行流量,单位 bytes
|
||||
RxBytes int64 `json:"rx_bytes"`
|
||||
// 上行流量,单位 bytes
|
||||
@@ -1144,7 +1177,7 @@ type SGuestResourceBase struct {
|
||||
}
|
||||
|
||||
// SGuestScreenDump is an autogenerated struct via yunion.io/x/onecloud/pkg/compute/models.SGuestScreenDump.
|
||||
/* type SGuestScreenDump struct {
|
||||
type SGuestScreenDump struct {
|
||||
apis.SResourceBase
|
||||
RowId int64 `json:"row_id"`
|
||||
GuestId string `json:"guest_id"`
|
||||
@@ -1155,7 +1188,7 @@ type SGuestResourceBase struct {
|
||||
S3Endpoint string `json:"s3_endpoint"`
|
||||
S3BucketName string `json:"s3_bucket_name"`
|
||||
S3UseSsl bool `json:"s3_use_ssl"`
|
||||
} */
|
||||
}
|
||||
|
||||
// SGuestTemplate is an autogenerated struct via yunion.io/x/onecloud/pkg/compute/models.SGuestTemplate.
|
||||
type SGuestTemplate struct {
|
||||
@@ -1248,6 +1281,20 @@ type SGuestnetwork struct {
|
||||
PortMappings []*GuestPortMapping `json:"port_mappings"`
|
||||
SBillingTypeBase
|
||||
SBillingChargeTypeBase
|
||||
// 下行带宽限制,单位mbps
|
||||
RxBwLimit int `json:"rx_bw_limit"`
|
||||
// 上行带宽限制,单位mbps
|
||||
TxBwLimit int `json:"tx_bw_limit"`
|
||||
}
|
||||
|
||||
// SGuestnetworksecgroup is an autogenerated struct via yunion.io/x/onecloud/pkg/compute/models.SGuestnetworksecgroup.
|
||||
type SGuestnetworksecgroup struct {
|
||||
apis.SResourceBase
|
||||
RowId int64 `json:"row_id"`
|
||||
GuestId string `json:"guest_id"`
|
||||
SSecurityGroupResourceBase
|
||||
NetworkIndex int `json:"network_index"`
|
||||
Admin bool `json:"admin"`
|
||||
}
|
||||
|
||||
// SGuestsecgroup is an autogenerated struct via yunion.io/x/onecloud/pkg/compute/models.SGuestsecgroup.
|
||||
@@ -1523,7 +1570,7 @@ type SInstanceSnapshot struct {
|
||||
// 套餐名称
|
||||
InstanceType string `json:"instance_type"`
|
||||
// 主机快照磁盘容量和
|
||||
SizeMb int `json:"size_mb"`
|
||||
// SizeMb int `nullable:"false" list:"user"`
|
||||
// 镜像ID
|
||||
ImageId string `json:"image_id"`
|
||||
// 是否保存内存
|
||||
@@ -1575,15 +1622,15 @@ type SIsolatedDevice struct {
|
||||
apis.SExternalizedResourceBase
|
||||
apis.SSharableBaseResource
|
||||
SHostResourceBase
|
||||
// # PCI / GPU-HPC / GPU-VGA / USB / NIC
|
||||
// # PCI / GPU / USB / NIC ...
|
||||
// 设备类型
|
||||
DevType string `json:"dev_type"`
|
||||
// EXCLUSIVE / SRIOV / MPS / HAMI / SHARE / MIG
|
||||
SharingMode string `json:"sharing_mode"`
|
||||
// Device is hot pluggable
|
||||
HotPluggable bool `json:"hot_pluggable"`
|
||||
// # Specific device name read from lspci command, e.g. `Tesla K40m` ...
|
||||
Model string `json:"model"`
|
||||
// 云主机Id
|
||||
GuestId string `json:"guest_id"`
|
||||
// guest network index
|
||||
NetworkIndex int `json:"network_index"`
|
||||
// Nic wire id
|
||||
WireId string `json:"wire_id"`
|
||||
// Offload interface name
|
||||
@@ -1592,9 +1639,7 @@ type SIsolatedDevice struct {
|
||||
IsInfinibandNic bool `json:"is_infiniband_nic"`
|
||||
// NVME disk size
|
||||
NvmeSizeMB int `json:"nvme_size_mb"`
|
||||
// guest disk index
|
||||
DiskIndex byte `json:"disk_index"`
|
||||
// # pci address of `Bus:Device.Function` format, or usb bus address of `bus.addr`
|
||||
// # pci address of `Bus:Device.Function` format, or usb bus address of `bus:addr:port`
|
||||
Addr string `json:"addr"`
|
||||
DevicePath string `json:"device_path"`
|
||||
// GPU card path, like /dev/dri/cardX
|
||||
@@ -1640,6 +1685,11 @@ type SIsolatedDevice struct {
|
||||
PcieInfo *IsolatedDevicePCIEInfo `json:"pcie_info"`
|
||||
// device numa node
|
||||
NumaNode byte `json:"numa_node"`
|
||||
// On-device memory in MiB (NVIDIA GPU VRAM via `nvidia-smi memory.total`,
|
||||
// or per-slice quota for MPS share mode). 0 means unknown / not applicable.
|
||||
MemorySize int `json:"memory_size"`
|
||||
// some of isolated device type support virtual num, like NVIDIA_GPU_SHARE, NVIDIA_MPS
|
||||
VirtualNum int `json:"virtual_num"`
|
||||
}
|
||||
|
||||
// SIsolatedDeviceModel is an autogenerated struct via yunion.io/x/onecloud/pkg/compute/models.SIsolatedDeviceModel.
|
||||
@@ -1654,6 +1704,11 @@ type SIsolatedDeviceModel struct {
|
||||
DisableAutoDetect *bool `json:"disable_auto_detect,omitempty"`
|
||||
}
|
||||
|
||||
// SIsolatedDeviceResourceBase is an autogenerated struct via yunion.io/x/onecloud/pkg/compute/models.SIsolatedDeviceResourceBase.
|
||||
type SIsolatedDeviceResourceBase struct {
|
||||
IsolatedDeviceId string `json:"isolated_device_id"`
|
||||
}
|
||||
|
||||
// SKafka is an autogenerated struct via yunion.io/x/onecloud/pkg/compute/models.SKafka.
|
||||
type SKafka struct {
|
||||
apis.SVirtualResourceBase
|
||||
@@ -1763,7 +1818,7 @@ type SLoadbalancer struct {
|
||||
NetworkType string `json:"network_type"`
|
||||
SLoadbalancerClusterResourceBase
|
||||
// 计费类型
|
||||
ChargeType string `json:"charge_type"`
|
||||
SBillingChargeTypeBase
|
||||
// 套餐名称
|
||||
LoadbalancerSpec string `json:"loadbalancer_spec"`
|
||||
// 默认后端服务器组Id
|
||||
@@ -2724,7 +2779,6 @@ type SServerSku struct {
|
||||
apis.SExternalizedResourceBase
|
||||
SCloudregionResourceBase
|
||||
SZoneResourceBase
|
||||
// SkuId string `width:"64" charset:"ascii" nullable:"false" list:"user" create:"admin_required"` // x2.large
|
||||
InstanceTypeFamily string `json:"instance_type_family"`
|
||||
// x2
|
||||
InstanceTypeCategory string `json:"instance_type_category"`
|
||||
@@ -2780,7 +2834,9 @@ type SSnapshot struct {
|
||||
CreatedBy string `json:"created_by"`
|
||||
Location string `json:"location"`
|
||||
// 快照大小,单位Mb
|
||||
Size int `json:"size"`
|
||||
Size int `json:"size"`
|
||||
// Virtual size, for kvm is origin disk size
|
||||
VirtualSize int `json:"virtual_size"`
|
||||
OutOfChain bool `json:"out_of_chain"`
|
||||
FakeDeleted bool `json:"fake_deleted"`
|
||||
DiskType string `json:"disk_type"`
|
||||
@@ -2799,18 +2855,15 @@ type SSnapshotPolicy struct {
|
||||
apis.SExternalizedResourceBase
|
||||
SManagedResourceBase
|
||||
SCloudregionResourceBase
|
||||
// 快照保留天数, -1: 表示永久保留
|
||||
// 快照保留天数
|
||||
RetentionDays int `json:"retention_days"`
|
||||
// 快照保留数量, 优先级高于 RetentionDays, 且仅对本地IDC资源有效
|
||||
RetentionCount int `json:"retention_count"`
|
||||
// 快照类型, 目前支持 disk, server
|
||||
// disk: 自动磁盘快照策略, 只能关联磁盘
|
||||
// server: 自动主机快照策略, 只能关联主机
|
||||
Type string `json:"type"`
|
||||
// 1~7, 1 is Monday, 7 is Sunday
|
||||
// 1~7, 1 is Monday
|
||||
RepeatWeekdays []int `json:"repeat_weekdays"`
|
||||
// 0~23, 每小时
|
||||
// 创建自动快照策略的时间必须与 RepeatWeekdays 对应的创建周期相一致
|
||||
// 0~23
|
||||
TimePoints []int `json:"time_points"`
|
||||
}
|
||||
|
||||
|
||||
@@ -93,8 +93,11 @@ type ContainerIsolatedDevice struct {
|
||||
Addr string `json:"addr"`
|
||||
Path string `json:"path"`
|
||||
DeviceType string `json:"device_type"`
|
||||
SharingMode string `json:"sharing_mode"`
|
||||
CardPath string `json:"card_path"`
|
||||
RenderPath string `json:"render_path"`
|
||||
MemoryLimit int `json:"memory_limit"`
|
||||
SmUtilLimit int `json:"sm_util_limit"`
|
||||
Index int `json:"index"`
|
||||
DeviceMinor int `json:"device_minor"`
|
||||
OnlyEnv []*apis.ContainerIsolatedDeviceOnlyEnv `json:"only_env"`
|
||||
|
||||
@@ -849,7 +849,7 @@ func (task *sBaremetalPrepareTask) sendIsolatedDevicesInfo(
|
||||
|
||||
gpuDevs := make([]isolated_device.IDevice, len(devs))
|
||||
for i := 0; i < len(devs); i++ {
|
||||
gpuDevs[i] = isolated_device.NewGPUHPCDevice(devs[i])
|
||||
gpuDevs[i] = isolated_device.NewGPUHPCDevice(devs[i], api.DEVICE_SHARING_MODE_EXCLUSIVE)
|
||||
}
|
||||
|
||||
for _, obj := range objs {
|
||||
|
||||
@@ -513,8 +513,7 @@ func ParseIsolatedDevice(desc string, idx int) (*compute.IsolatedDeviceConfig, e
|
||||
}
|
||||
dev := new(compute.IsolatedDeviceConfig)
|
||||
parts := strings.Split(desc, ":")
|
||||
devTypes := sets.NewString(compute.VALID_PASSTHROUGH_TYPES...)
|
||||
devTypes.Insert(compute.VALID_CONTAINER_DEVICE_TYPES...)
|
||||
devTypes := sets.NewString(compute.VALID_TYPES...)
|
||||
for _, p := range parts {
|
||||
if regutils.MatchUUIDExact(p) {
|
||||
dev.Id = p
|
||||
|
||||
@@ -70,7 +70,7 @@ func (h hostDevice) ValidateCreateData(ctx context.Context, userCred mcclient.To
|
||||
return dev, nil
|
||||
}
|
||||
|
||||
func (h hostDevice) ToHostDevice(dev *api.ContainerDevice) (*hostapi.ContainerDevice, error) {
|
||||
func (h hostDevice) ToHostDevice(dev *api.ContainerDevice, guestId string) (*hostapi.ContainerDevice, error) {
|
||||
return &hostapi.ContainerDevice{
|
||||
Type: apis.CONTAINER_DEVICE_TYPE_HOST,
|
||||
ContainerPath: dev.Host.ContainerPath,
|
||||
|
||||
@@ -19,7 +19,6 @@ import (
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/util/sets"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/apis"
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
@@ -87,7 +86,7 @@ func (i isolatedDevice) ValidateCreateData(ctx context.Context, userCred mcclien
|
||||
return nil, errors.Wrapf(err, "validate create data %s", jsonutils.Marshal(dev))
|
||||
}
|
||||
isoDev := dev.IsolatedDevice
|
||||
podDevs, err := pod.GetIsolatedDevices()
|
||||
podDevs, err := pod.GetGuestIsolatedDevices()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "get isolated devices")
|
||||
}
|
||||
@@ -96,7 +95,7 @@ func (i isolatedDevice) ValidateCreateData(ctx context.Context, userCred mcclien
|
||||
if index >= len(podDevs) {
|
||||
return nil, httperrors.NewInputParameterError("index %d is large than isolated device size %d", index, len(podDevs))
|
||||
}
|
||||
isoDev.Id = podDevs[index].GetId()
|
||||
isoDev.Id = podDevs[index].IsolatedDeviceId
|
||||
// remove index
|
||||
isoDev.Index = nil
|
||||
} else {
|
||||
@@ -104,13 +103,14 @@ func (i isolatedDevice) ValidateCreateData(ctx context.Context, userCred mcclien
|
||||
return nil, httperrors.NewNotEmptyError("id is empty")
|
||||
}
|
||||
foundDisk := false
|
||||
for _, d := range podDevs {
|
||||
for i := range podDevs {
|
||||
d := podDevs[i].GetIsolatedDevice()
|
||||
if d.GetId() == isoDev.Id || d.GetName() == isoDev.Id {
|
||||
isoDev.Id = d.GetId()
|
||||
foundDisk = true
|
||||
devType := d.DevType
|
||||
if !sets.NewString(api.VALID_CONTAINER_DEVICE_TYPES...).Has(devType) {
|
||||
return nil, httperrors.NewInputParameterError("device type %s is not supported by container", devType)
|
||||
host := d.GetHost()
|
||||
if host.HostType != api.HOST_TYPE_CONTAINER {
|
||||
return nil, httperrors.NewInputParameterError("device %s is not supported by container", isoDev.Id)
|
||||
}
|
||||
break
|
||||
}
|
||||
@@ -123,13 +123,17 @@ func (i isolatedDevice) ValidateCreateData(ctx context.Context, userCred mcclien
|
||||
return dev, nil
|
||||
}
|
||||
|
||||
func (i isolatedDevice) ToHostDevice(dev *api.ContainerDevice) (*hostapi.ContainerDevice, error) {
|
||||
func (i isolatedDevice) ToHostDevice(dev *api.ContainerDevice, guestId string) (*hostapi.ContainerDevice, error) {
|
||||
input := dev.IsolatedDevice
|
||||
isoDevObj, err := models.IsolatedDeviceManager.FetchById(input.Id)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "Fetch isolated device by id %s", input.Id)
|
||||
}
|
||||
isoDev := isoDevObj.(*models.SIsolatedDevice)
|
||||
gdev, err := isoDev.GetGuestIsolatedDevice(guestId, input.GuestIsolatedDeviceIndex)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "GetGuestIsolatedDevice")
|
||||
}
|
||||
return &hostapi.ContainerDevice{
|
||||
Type: dev.Type,
|
||||
IsolatedDevice: &hostapi.ContainerIsolatedDevice{
|
||||
@@ -138,7 +142,10 @@ func (i isolatedDevice) ToHostDevice(dev *api.ContainerDevice) (*hostapi.Contain
|
||||
Path: isoDev.DevicePath,
|
||||
CardPath: isoDev.CardPath,
|
||||
DeviceType: isoDev.DevType,
|
||||
SharingMode: isoDev.SharingMode,
|
||||
RenderPath: isoDev.RenderPath,
|
||||
MemoryLimit: gdev.DeviceMemorySize,
|
||||
SmUtilLimit: gdev.SmUtilLimit,
|
||||
Index: isoDev.Index,
|
||||
DeviceMinor: isoDev.DeviceMinor,
|
||||
OnlyEnv: input.OnlyEnv,
|
||||
|
||||
@@ -710,11 +710,11 @@ func (base *SBaseGuestDriver) ValidateGuestHotChangeConfigInput(ctx context.Cont
|
||||
return confs, nil
|
||||
}
|
||||
|
||||
func (base *SBaseGuestDriver) BeforeDetachIsolatedDevice(ctx context.Context, cred mcclient.TokenCredential, guest *models.SGuest, dev *models.SIsolatedDevice) error {
|
||||
func (base *SBaseGuestDriver) BeforeDetachIsolatedDevice(ctx context.Context, cred mcclient.TokenCredential, guest *models.SGuest, dev *models.SGuestIsolatedDevice) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (base *SBaseGuestDriver) BeforeAttachIsolatedDevice(ctx context.Context, cred mcclient.TokenCredential, guest *models.SGuest, dev *models.SIsolatedDevice) error {
|
||||
func (base *SBaseGuestDriver) BeforeAttachIsolatedDevice(ctx context.Context, cred mcclient.TokenCredential, guest *models.SGuest, dev *models.SGuestIsolatedDevice) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -851,7 +851,7 @@ func (self *SKVMGuestDriver) CheckMigrate(ctx context.Context, guest *models.SGu
|
||||
}
|
||||
}
|
||||
}
|
||||
devices, err := guest.GetIsolatedDevices()
|
||||
devices, err := guest.GetGuestIsolatedDevices()
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "GetIsolatedDevices")
|
||||
}
|
||||
@@ -879,7 +879,7 @@ func (self *SKVMGuestDriver) CheckLiveMigrate(ctx context.Context, guest *models
|
||||
if cdrom != nil && len(cdrom.ImageId) > 0 {
|
||||
return httperrors.NewBadRequestError("Cannot live migrate with cdrom")
|
||||
}
|
||||
devices, err := guest.GetIsolatedDevices()
|
||||
devices, err := guest.GetGuestIsolatedDevices()
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "GetIsolatedDevices")
|
||||
}
|
||||
|
||||
@@ -646,12 +646,13 @@ func (drv *SManagedVirtualizedGuestDriver) RemoteDeployGuestForCreate(ctx contex
|
||||
}
|
||||
}
|
||||
|
||||
devs, err := guest.GetIsolatedDevices()
|
||||
devs, err := guest.GetGuestIsolatedDevices()
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "GetIsolatedDevices")
|
||||
}
|
||||
desc.IsolateDevices = []cloudprovider.SIsolateDevice{}
|
||||
for _, dev := range devs {
|
||||
for i := range devs {
|
||||
dev := devs[i].GetIsolatedDevice()
|
||||
desc.IsolateDevices = append(desc.IsolateDevices, cloudprovider.SIsolateDevice{
|
||||
Id: dev.ExternalId,
|
||||
Name: dev.Name,
|
||||
|
||||
@@ -608,7 +608,7 @@ func (p *SPodDriver) RequestDeleteSnapshot(ctx context.Context, guest *models.SG
|
||||
return p.SKVMGuestDriver.RequestDeleteSnapshot(ctx, guest, task, params)
|
||||
}
|
||||
|
||||
func (p *SPodDriver) BeforeDetachIsolatedDevice(ctx context.Context, userCred mcclient.TokenCredential, guest *models.SGuest, dev *models.SIsolatedDevice) error {
|
||||
func (p *SPodDriver) BeforeDetachIsolatedDevice(ctx context.Context, userCred mcclient.TokenCredential, guest *models.SGuest, gdev *models.SGuestIsolatedDevice) error {
|
||||
ctrs, err := models.GetContainerManager().GetContainersByPod(guest.GetId())
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "get containers by pod %s", guest.GetId())
|
||||
@@ -620,10 +620,11 @@ func (p *SPodDriver) BeforeDetachIsolatedDevice(ctx context.Context, userCred mc
|
||||
newDevs := make([]*api.ContainerDevice, 0)
|
||||
releasedDevs := make(map[string]models.ContainerReleasedDevice)
|
||||
for _, curDev := range devs {
|
||||
if curDev.IsolatedDevice == nil || curDev.IsolatedDevice.Id != dev.GetId() {
|
||||
if curDev.IsolatedDevice == nil || (curDev.IsolatedDevice.Id != gdev.IsolatedDeviceId && curDev.IsolatedDevice.GuestIsolatedDeviceIndex == int(gdev.Index)) {
|
||||
tmpDev := curDev
|
||||
newDevs = append(newDevs, tmpDev)
|
||||
} else {
|
||||
dev := gdev.GetIsolatedDevice()
|
||||
releasedDevs[curDev.IsolatedDevice.Id] = *models.NewContainerReleasedDevice(curDev, dev.DevType, dev.Model)
|
||||
}
|
||||
}
|
||||
@@ -640,7 +641,7 @@ func (p *SPodDriver) BeforeDetachIsolatedDevice(ctx context.Context, userCred mc
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *SPodDriver) BeforeAttachIsolatedDevice(ctx context.Context, userCred mcclient.TokenCredential, guest *models.SGuest, dev *models.SIsolatedDevice) error {
|
||||
func (p *SPodDriver) BeforeAttachIsolatedDevice(ctx context.Context, userCred mcclient.TokenCredential, guest *models.SGuest, dev *models.SGuestIsolatedDevice) error {
|
||||
ctrs, err := models.GetContainerManager().GetContainersByPod(guest.GetId())
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "get containers by pod %s", guest.GetId())
|
||||
@@ -654,7 +655,7 @@ func (p *SPodDriver) BeforeAttachIsolatedDevice(ctx context.Context, userCred mc
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *SPodDriver) attachIsolatedDeviceToContainer(ctx context.Context, userCred mcclient.TokenCredential, ctrPtr *models.SContainer, dev *models.SIsolatedDevice) error {
|
||||
func (p *SPodDriver) attachIsolatedDeviceToContainer(ctx context.Context, userCred mcclient.TokenCredential, ctrPtr *models.SContainer, gdev *models.SGuestIsolatedDevice) error {
|
||||
rlsDevs, err := ctrPtr.GetReleasedDevices(ctx, userCred)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "get release devices for container %s", ctrPtr.GetId())
|
||||
@@ -672,7 +673,7 @@ func (p *SPodDriver) attachIsolatedDeviceToContainer(ctx context.Context, userCr
|
||||
if curDev.IsolatedDevice == nil {
|
||||
continue
|
||||
}
|
||||
if curDev.IsolatedDevice.Id == dev.GetId() {
|
||||
if curDev.IsolatedDevice.Id == gdev.IsolatedDeviceId && curDev.IsolatedDevice.GuestIsolatedDeviceIndex == int(gdev.Index) {
|
||||
shouldUpdate = false
|
||||
break
|
||||
}
|
||||
@@ -681,7 +682,8 @@ func (p *SPodDriver) attachIsolatedDeviceToContainer(ctx context.Context, userCr
|
||||
spec.Devices = append(spec.Devices, &api.ContainerDevice{
|
||||
Type: apis.CONTAINER_DEVICE_TYPE_ISOLATED_DEVICE,
|
||||
IsolatedDevice: &api.ContainerIsolatedDevice{
|
||||
Id: dev.GetId(),
|
||||
Id: gdev.IsolatedDeviceId,
|
||||
GuestIsolatedDeviceIndex: int(gdev.Index),
|
||||
},
|
||||
})
|
||||
if _, err := db.Update(ctrPtr, func() error {
|
||||
@@ -695,6 +697,7 @@ func (p *SPodDriver) attachIsolatedDeviceToContainer(ctx context.Context, userCr
|
||||
if rlsDev.IsolatedDevice == nil {
|
||||
continue
|
||||
}
|
||||
dev := gdev.GetIsolatedDevice()
|
||||
if rlsDev.DeviceModel == dev.Model && rlsDev.DeviceType == dev.DevType {
|
||||
delete(rlsDevs, id)
|
||||
if err := ctrPtr.SaveReleasedDevices(ctx, userCred, rlsDevs); err != nil {
|
||||
|
||||
@@ -119,9 +119,9 @@ func (self *SVirtualizedGuestDriver) Attach2RandomNetwork(guest *models.SGuest,
|
||||
dev, _ := idev.(*models.SIsolatedDevice)
|
||||
sriovWires = []string{dev.WireId}
|
||||
} else {
|
||||
wires, err := models.IsolatedDeviceManager.FindUnusedNicWiresByModel(netConfig.SriovDevice.Model)
|
||||
wires, err := models.IsolatedDeviceManager.FindAvailableNicWiresByModel(netConfig.SriovDevice.Model)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "FindUnusedNicWiresByModel")
|
||||
return nil, errors.Wrap(err, "FindAvailableNicWiresByModel")
|
||||
}
|
||||
sriovWires = wires
|
||||
}
|
||||
|
||||
@@ -869,9 +869,11 @@ func getStorageTypes(
|
||||
}
|
||||
|
||||
type PCIDevModelTypes struct {
|
||||
Model string
|
||||
DevType string
|
||||
SizeMB int
|
||||
Model string
|
||||
DevType string
|
||||
SharingMode string
|
||||
NvmeSizeMB int
|
||||
DevMemorySize int
|
||||
|
||||
VirtualDev bool
|
||||
Hypervisor string
|
||||
@@ -885,7 +887,7 @@ func getIsolatedDeviceInfo(ctx context.Context, userCred mcclient.TokenCredentia
|
||||
hostQuery = StorageManager.FilterByOwner(ctx, hostQuery, StorageManager, userCred, ownerId, rbacscope.ScopeDomain)
|
||||
}
|
||||
if len(tenantId) > 0 {
|
||||
devicesQ = devicesQ.IsNullOrEmpty("guest_id")
|
||||
devicesQ = IsolatedDeviceManager.GetAvailableIsolatedDeviceQuery(devicesQ)
|
||||
subq := db.SharedResourceManager.Query("resource_id")
|
||||
subq = subq.Equals("resource_type", IsolatedDeviceManager.Keyword())
|
||||
subq = subq.Equals("target_project_id", tenantId)
|
||||
@@ -916,7 +918,7 @@ func getIsolatedDeviceInfo(ctx context.Context, userCred mcclient.TokenCredentia
|
||||
devices := devicesQ.SubQuery()
|
||||
hosts := hostQuery.SubQuery()
|
||||
|
||||
q := devices.Query(hosts.Field("host_type"), devices.Field("model"), devices.Field("dev_type"), devices.Field("nvme_size_mb"))
|
||||
q := devices.Query(hosts.Field("host_type"), devices.Field("model"), devices.Field("dev_type"), devices.Field("sharing_mode"), devices.Field("nvme_size_mb"), devices.Field("memory_size"))
|
||||
q = q.Filter(sqlchemy.NotIn(devices.Field("dev_type"), []string{api.USB_TYPE, api.NIC_TYPE}))
|
||||
if zone != nil {
|
||||
q = q.Join(hosts, sqlchemy.Equals(devices.Field("host_id"), hosts.Field("id")))
|
||||
@@ -935,7 +937,7 @@ func getIsolatedDeviceInfo(ctx context.Context, userCred mcclient.TokenCredentia
|
||||
sqlchemy.IsNullOrEmpty(hosts.Field("manager_id")),
|
||||
))
|
||||
}*/
|
||||
q = q.GroupBy(hosts.Field("host_type"), devices.Field("model"), devices.Field("dev_type"), devices.Field("nvme_size_mb"))
|
||||
q = q.GroupBy(hosts.Field("host_type"), devices.Field("model"), devices.Field("dev_type"), devices.Field("sharing_mode"), devices.Field("nvme_size_mb"), devices.Field("memory_size"))
|
||||
|
||||
rows, err := q.Rows()
|
||||
if err != nil {
|
||||
@@ -946,20 +948,21 @@ func getIsolatedDeviceInfo(ctx context.Context, userCred mcclient.TokenCredentia
|
||||
gpus := make([]PCIDevModelTypes, 0)
|
||||
gpuModels := make([]string, 0)
|
||||
for rows.Next() {
|
||||
var m, t string
|
||||
var sizeMB int
|
||||
var m, t, sharingMode string
|
||||
var nvmeSizeMB int
|
||||
var memSizeMB int
|
||||
var vdev bool
|
||||
var hypervisor string
|
||||
var hostType string
|
||||
rows.Scan(&hostType, &m, &t, &sizeMB)
|
||||
rows.Scan(&hostType, &m, &t, &sharingMode, &nvmeSizeMB, &memSizeMB)
|
||||
|
||||
if m == "" {
|
||||
continue
|
||||
}
|
||||
if utils.IsInStringArray(t, api.VITRUAL_DEVICE_TYPES) {
|
||||
if utils.IsInStringArray(sharingMode, api.VIRTUAL_SHARING_MODES) {
|
||||
vdev = true
|
||||
}
|
||||
if utils.IsInStringArray(t, api.VALID_CONTAINER_DEVICE_TYPES) {
|
||||
if hostType == api.HOST_TYPE_CONTAINER {
|
||||
hypervisor = api.HYPERVISOR_POD
|
||||
} else {
|
||||
hypervisor = api.HYPERVISOR_KVM
|
||||
@@ -969,7 +972,7 @@ func getIsolatedDeviceInfo(ctx context.Context, userCred mcclient.TokenCredentia
|
||||
hypervisor = api.HYPERVISOR_ZETTAKIT
|
||||
}
|
||||
|
||||
gpus = append(gpus, PCIDevModelTypes{m, t, sizeMB, vdev, hypervisor})
|
||||
gpus = append(gpus, PCIDevModelTypes{m, t, sharingMode, nvmeSizeMB, memSizeMB, vdev, hypervisor})
|
||||
|
||||
if !utils.IsInStringArray(m, gpuModels) {
|
||||
gpuModels = append(gpuModels, m)
|
||||
|
||||
@@ -1294,35 +1294,31 @@ func (self *SGuest) SyncVMIsolateDevices(ctx context.Context, userCred mcclient.
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
devs, err := self.GetIsolatedDevices()
|
||||
gdevs, err := self.GetGuestIsolatedDevices()
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "GetIsolatedDevices")
|
||||
}
|
||||
result := compare.SyncResult{}
|
||||
for i := range devs {
|
||||
if !utils.IsInStringArray(devs[i].ExternalId, externalIds) {
|
||||
_, err = db.Update(&devs[i], func() error {
|
||||
devs[i].GuestId = ""
|
||||
return nil
|
||||
})
|
||||
for i := range gdevs {
|
||||
dev := gdevs[i].GetIsolatedDevice()
|
||||
if !utils.IsInStringArray(dev.ExternalId, externalIds) {
|
||||
err = gdevs[i].Detach(ctx, userCred)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
result.Delete()
|
||||
}
|
||||
}
|
||||
devs = []SIsolatedDevice{}
|
||||
devs := []SIsolatedDevice{}
|
||||
sq := HostManager.Query("id").Equals("manager_id", host.ManagerId).SubQuery()
|
||||
q := IsolatedDeviceManager.Query().In("host_id", sq).In("external_id", externalIds)
|
||||
err = db.FetchModelObjects(IsolatedDeviceManager, q, &devs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for i := range devs {
|
||||
_, err = db.Update(&devs[i], func() error {
|
||||
devs[i].GuestId = self.Id
|
||||
return nil
|
||||
})
|
||||
err = self.attachIsolatedDevice(ctx, userCred, &devs[i], nil, nil, nil, "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -134,7 +134,7 @@ type IContainerDeviceDriver interface {
|
||||
GetType() apis.ContainerDeviceType
|
||||
ValidatePodCreateData(ctx context.Context, userCred mcclient.TokenCredential, dev *api.ContainerDevice, input *api.ServerCreateInput) error
|
||||
ValidateCreateData(ctx context.Context, userCred mcclient.TokenCredential, pod *SGuest, dev *api.ContainerDevice) (*api.ContainerDevice, error)
|
||||
ToHostDevice(dev *api.ContainerDevice) (*hostapi.ContainerDevice, error)
|
||||
ToHostDevice(dev *api.ContainerDevice, guestId string) (*hostapi.ContainerDevice, error)
|
||||
}
|
||||
|
||||
type IContainerLifecyleDriver interface {
|
||||
|
||||
@@ -944,7 +944,7 @@ func (c *SContainer) ToHostContainerSpec(ctx context.Context, userCred mcclient.
|
||||
}
|
||||
ctrDevs := make([]*hostapi.ContainerDevice, 0)
|
||||
for _, dev := range c.Spec.Devices {
|
||||
ctrDev, err := GetContainerDeviceDriver(dev.Type).ToHostDevice(dev)
|
||||
ctrDev, err := GetContainerDeviceDriver(dev.Type).ToHostDevice(dev, c.GuestId)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "ToHostDevice %s", jsonutils.Marshal(dev))
|
||||
}
|
||||
|
||||
@@ -1178,7 +1178,7 @@ func (self *SGuest) PerformRestoreVirtualIsolatedDevices(ctx context.Context, us
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "unmarshal virtual dev configs")
|
||||
}
|
||||
devs, err := self.GetIsolatedDevices()
|
||||
devs, err := self.GetGuestIsolatedDevices()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "GetIsolatedDevices")
|
||||
}
|
||||
@@ -1689,11 +1689,11 @@ func (self *SGuest) StartInsertVfdTask(ctx context.Context, floppyOrdinal int64,
|
||||
}
|
||||
|
||||
func (self *SGuest) RebalanceVirtualIsolatedDevices(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
devs, err := self.GetIsolatedDevices()
|
||||
guestDevs, err := self.GetGuestIsolatedDevices()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "guest get isolated devices")
|
||||
}
|
||||
if len(devs) == 0 {
|
||||
if len(guestDevs) == 0 {
|
||||
return nil
|
||||
}
|
||||
host, err := self.GetHost()
|
||||
@@ -1701,16 +1701,19 @@ func (self *SGuest) RebalanceVirtualIsolatedDevices(ctx context.Context, userCre
|
||||
return errors.Wrap(err, "guest get host")
|
||||
}
|
||||
var numaNodeBalance = true
|
||||
detachDevs := make([]SIsolatedDevice, 0)
|
||||
detachDevs := make([]SGuestIsolatedDevice, 0)
|
||||
originDevConfigs := make([]api.IsolatedDeviceConfig, 0)
|
||||
for i := range devs {
|
||||
if utils.IsInStringArray(devs[i].DevType, api.VITRUAL_DEVICE_TYPES) {
|
||||
for i := range guestDevs {
|
||||
dev := guestDevs[i].GetIsolatedDevice()
|
||||
if dev.SharingMode == api.DEVICE_SHARING_MODE_UNLIMITED {
|
||||
originDevConfigs = append(originDevConfigs, api.IsolatedDeviceConfig{
|
||||
Model: devs[i].Model,
|
||||
DevType: devs[i].DevType,
|
||||
Model: dev.Model,
|
||||
DevType: dev.DevType,
|
||||
MemoryRequest: guestDevs[i].DeviceMemorySize,
|
||||
SmUtilLimit: guestDevs[i].SmUtilLimit,
|
||||
})
|
||||
detachDevs = append(detachDevs, devs[i])
|
||||
isBalance, err := host.VirtualDeviceNumaBalance(devs[i].DevType, devs[i].NumaNode)
|
||||
detachDevs = append(detachDevs, guestDevs[i])
|
||||
isBalance, err := host.VirtualDeviceNumaBalance(dev.Model, dev.NumaNode)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "VirtualDeviceNumaBalance")
|
||||
}
|
||||
@@ -1728,20 +1731,24 @@ func (self *SGuest) RebalanceVirtualIsolatedDevices(ctx context.Context, userCre
|
||||
lockman.LockObject(ctx, host)
|
||||
defer lockman.ReleaseObject(ctx, host)
|
||||
|
||||
detachedDevConfigs := []*api.IsolatedDeviceConfig{}
|
||||
for i := 0; i < len(detachDevs); i++ {
|
||||
err := self.detachIsolateDevice(ctx, userCred, &detachDevs[i])
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "detach device %s", detachDevs[i].GetId())
|
||||
}
|
||||
dev := detachDevs[i].GetIsolatedDevice()
|
||||
detachedDevConfigs = append(detachedDevConfigs, &api.IsolatedDeviceConfig{
|
||||
Model: dev.Model,
|
||||
DevType: dev.DevType,
|
||||
MemoryRequest: detachDevs[i].DeviceMemorySize,
|
||||
SmUtilLimit: detachDevs[i].SmUtilLimit,
|
||||
})
|
||||
}
|
||||
|
||||
usedDeviceMap := map[string]*SIsolatedDevice{}
|
||||
for i := range detachDevs {
|
||||
devConfig := &api.IsolatedDeviceConfig{
|
||||
Model: detachDevs[i].Model,
|
||||
DevType: detachDevs[i].DevType,
|
||||
}
|
||||
err := IsolatedDeviceManager.attachHostDeviceToGuestByModel(ctx, self, host, devConfig, userCred, usedDeviceMap, nil)
|
||||
for i := range detachedDevConfigs {
|
||||
err := IsolatedDeviceManager.attachHostDeviceToGuestByModel(ctx, self, host, detachedDevConfigs[i], userCred, usedDeviceMap, nil)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "attachHostDeviceToGuestByModel")
|
||||
}
|
||||
@@ -2347,12 +2354,16 @@ func (self *SGuest) GetReleasedIsolatedDevices(ctx context.Context, userCred mcc
|
||||
return devs, nil
|
||||
}
|
||||
|
||||
func (self *SGuest) SetReleasedIsolatedDevices(ctx context.Context, userCred mcclient.TokenCredential, devs []SIsolatedDevice) error {
|
||||
func (self *SGuest) SetReleasedIsolatedDevices(ctx context.Context, userCred mcclient.TokenCredential, devs []SGuestIsolatedDevice) error {
|
||||
records := make([]api.ServerReleasedIsolatedDevice, 0)
|
||||
for _, dev := range devs {
|
||||
for i := range devs {
|
||||
dev := devs[i].GetIsolatedDevice()
|
||||
record := api.ServerReleasedIsolatedDevice{
|
||||
DevType: dev.DevType,
|
||||
Model: dev.Model,
|
||||
DevType: dev.DevType,
|
||||
Model: dev.Model,
|
||||
GpuType: devs[i].GpuType,
|
||||
SharingMode: dev.SharingMode,
|
||||
MemoryRequest: devs[i].DeviceMemorySize,
|
||||
}
|
||||
records = append(records, record)
|
||||
}
|
||||
@@ -2362,14 +2373,14 @@ func (self *SGuest) SetReleasedIsolatedDevices(ctx context.Context, userCred mcc
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SGuest) DetachIsolatedDevices(ctx context.Context, userCred mcclient.TokenCredential, devs []SIsolatedDevice) error {
|
||||
func (self *SGuest) DetachIsolatedDevices(ctx context.Context, userCred mcclient.TokenCredential, devs []SGuestIsolatedDevice) error {
|
||||
host, _ := self.GetHost()
|
||||
lockman.LockObject(ctx, host)
|
||||
defer lockman.ReleaseObject(ctx, host)
|
||||
for i := 0; i < len(devs); i++ {
|
||||
// check first
|
||||
dev := devs[i]
|
||||
if !utils.IsInStringArray(dev.DevType, api.VALID_ATTACH_TYPES) {
|
||||
dev := devs[i].GetIsolatedDevice()
|
||||
if !dev.IsValidAttachDev() {
|
||||
if devModel, err := IsolatedDeviceModelManager.GetByDevType(dev.DevType); err != nil {
|
||||
msg := fmt.Sprintf("Can't separately detach dev type %s", dev.DevType)
|
||||
logclient.AddActionLogWithContext(ctx, self, logclient.ACT_GUEST_DETACH_ISOLATED_DEVICE, msg, userCred, false)
|
||||
@@ -2414,7 +2425,7 @@ func (self *SGuest) PerformDetachIsolatedDevice(ctx context.Context, userCred mc
|
||||
}
|
||||
|
||||
var detachAllDevice = jsonutils.QueryBoolean(data, "detach_all", false)
|
||||
devs := make([]SIsolatedDevice, 0)
|
||||
devs := make([]SGuestIsolatedDevice, 0)
|
||||
if !detachAllDevice {
|
||||
device, err := data.GetString("device")
|
||||
if err != nil {
|
||||
@@ -2422,6 +2433,12 @@ func (self *SGuest) PerformDetachIsolatedDevice(ctx context.Context, userCred mc
|
||||
logclient.AddActionLogWithContext(ctx, self, logclient.ACT_GUEST_DETACH_ISOLATED_DEVICE, msg, userCred, false)
|
||||
return nil, httperrors.NewBadRequestError("%s", msg)
|
||||
}
|
||||
index, err := data.Int("index")
|
||||
if err != nil {
|
||||
msg := "Missing isolated device index"
|
||||
logclient.AddActionLogWithContext(ctx, self, logclient.ACT_GUEST_DETACH_ISOLATED_DEVICE, msg, userCred, false)
|
||||
return nil, httperrors.NewBadRequestError("%s", msg)
|
||||
}
|
||||
iDev, err := IsolatedDeviceManager.FetchByIdOrName(ctx, userCred, device)
|
||||
if err != nil {
|
||||
msgFmt := "Isolated device %s not found"
|
||||
@@ -2429,9 +2446,16 @@ func (self *SGuest) PerformDetachIsolatedDevice(ctx context.Context, userCred mc
|
||||
logclient.AddActionLogWithContext(ctx, self, logclient.ACT_GUEST_DETACH_ISOLATED_DEVICE, msg, userCred, false)
|
||||
return nil, httperrors.NewBadRequestError(msgFmt, device)
|
||||
}
|
||||
devs = append(devs, *iDev.(*SIsolatedDevice))
|
||||
dev := iDev.(*SIsolatedDevice)
|
||||
gdev, err := dev.GetGuestIsolatedDevice(self.Id, int(index))
|
||||
if err != nil {
|
||||
msg := err.Error()
|
||||
logclient.AddActionLogWithContext(ctx, self, logclient.ACT_GUEST_DETACH_ISOLATED_DEVICE, msg, userCred, false)
|
||||
return nil, httperrors.NewBadRequestError("%s", msg)
|
||||
}
|
||||
devs = append(devs, *gdev)
|
||||
} else {
|
||||
devs, _ = self.GetIsolatedDevices()
|
||||
devs, _ = self.GetGuestIsolatedDevices()
|
||||
}
|
||||
if err := self.DetachIsolatedDevices(ctx, userCred, devs); err != nil {
|
||||
return nil, err
|
||||
@@ -2442,7 +2466,7 @@ func (self *SGuest) PerformDetachIsolatedDevice(ctx context.Context, userCred mc
|
||||
return nil, self.StartIsolatedDevicesSyncTask(ctx, userCred, jsonutils.QueryBoolean(data, "auto_start", false), "")
|
||||
}
|
||||
|
||||
func (self *SGuest) startDetachIsolateDeviceWithoutNic(ctx context.Context, userCred mcclient.TokenCredential, device string) error {
|
||||
func (self *SGuest) startDetachIsolateDeviceWithoutNic(ctx context.Context, userCred mcclient.TokenCredential, device string, index int) error {
|
||||
iDev, err := IsolatedDeviceManager.FetchByIdOrName(ctx, userCred, device)
|
||||
if err != nil {
|
||||
msgFmt := "Isolated device %s not found"
|
||||
@@ -2451,25 +2475,28 @@ func (self *SGuest) startDetachIsolateDeviceWithoutNic(ctx context.Context, user
|
||||
return httperrors.NewBadRequestError(msgFmt, device)
|
||||
}
|
||||
dev := iDev.(*SIsolatedDevice)
|
||||
return self.DetachIsolatedDevices(ctx, userCred, []SIsolatedDevice{*dev})
|
||||
gdev, err := dev.GetGuestIsolatedDevice(self.Id, index)
|
||||
if err != nil {
|
||||
msgFmt := "Isolated device %s index %d not found"
|
||||
msg := fmt.Sprintf(msgFmt, device, index)
|
||||
logclient.AddActionLogWithContext(ctx, self, logclient.ACT_GUEST_DETACH_ISOLATED_DEVICE, msg, userCred, false)
|
||||
return httperrors.NewBadRequestError(msgFmt, device)
|
||||
}
|
||||
return self.DetachIsolatedDevices(ctx, userCred, []SGuestIsolatedDevice{*gdev})
|
||||
}
|
||||
|
||||
func (self *SGuest) detachIsolateDevice(ctx context.Context, userCred mcclient.TokenCredential, dev *SIsolatedDevice) error {
|
||||
if dev.GuestId != self.Id {
|
||||
func (self *SGuest) detachIsolateDevice(ctx context.Context, userCred mcclient.TokenCredential, gdev *SGuestIsolatedDevice) error {
|
||||
if gdev.GuestId != self.Id {
|
||||
msg := "Isolated device is not attached to this guest"
|
||||
logclient.AddActionLogWithContext(ctx, self, logclient.ACT_GUEST_DETACH_ISOLATED_DEVICE, msg, userCred, false)
|
||||
return httperrors.NewBadRequestError("%s", msg)
|
||||
}
|
||||
dev := gdev.GetIsolatedDevice()
|
||||
drv, _ := self.GetDriver()
|
||||
if err := drv.BeforeDetachIsolatedDevice(ctx, userCred, self, dev); err != nil {
|
||||
return errors.Wrapf(err, "BeforeDetachIsolatedDevice %s of guest %s", jsonutils.Marshal(dev), self.GetId())
|
||||
if err := drv.BeforeDetachIsolatedDevice(ctx, userCred, self, gdev); err != nil {
|
||||
return errors.Wrapf(err, "BeforeDetachIsolatedDevice %s of guest %s", jsonutils.Marshal(gdev), self.GetId())
|
||||
}
|
||||
_, err := db.Update(dev, func() error {
|
||||
dev.GuestId = ""
|
||||
dev.NetworkIndex = -1
|
||||
dev.DiskIndex = -1
|
||||
return nil
|
||||
})
|
||||
err := gdev.Detach(ctx, userCred)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -2478,7 +2505,7 @@ func (self *SGuest) detachIsolateDevice(ctx context.Context, userCred mcclient.T
|
||||
}
|
||||
|
||||
// 挂载透传设备
|
||||
func (self *SGuest) PerformAttachIsolatedDevice(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
func (self *SGuest) PerformAttachIsolatedDevice(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input *api.ServerAttachIsolatedDeviceInput) (jsonutils.JSONObject, error) {
|
||||
if self.Hypervisor != api.HYPERVISOR_KVM && self.Hypervisor != api.HYPERVISOR_POD {
|
||||
return nil, httperrors.NewNotAcceptableError("Not allow for hypervisor %s", self.Hypervisor)
|
||||
}
|
||||
@@ -2489,20 +2516,29 @@ func (self *SGuest) PerformAttachIsolatedDevice(ctx context.Context, userCred mc
|
||||
return nil, httperrors.NewInvalidStatusError("%s", msg)
|
||||
}
|
||||
var err error
|
||||
autoStart := jsonutils.QueryBoolean(data, "auto_start", false)
|
||||
if data.Contains("device") {
|
||||
device, _ := data.GetString("device")
|
||||
err = self.StartAttachIsolatedDeviceGpuOrUsb(ctx, userCred, device, autoStart)
|
||||
} else if data.Contains("model") {
|
||||
vmodel, _ := data.GetString("model")
|
||||
var count int64 = 1
|
||||
if data.Contains("count") {
|
||||
count, _ = data.Int("count")
|
||||
if input.GpuType != "" && !utils.IsInStringArray(input.GpuType, []string{api.GPU_VGA, api.GPU_HPC}) {
|
||||
return nil, httperrors.NewInputParameterError("gpu_type %s not vaild", input.GpuType)
|
||||
}
|
||||
if input.MemoryRequest != nil && *input.MemoryRequest <= 0 {
|
||||
return nil, httperrors.NewBadRequestError("guest attach gpu memory request count must > 0")
|
||||
}
|
||||
|
||||
if input.Device != "" {
|
||||
err = self.StartAttachIsolatedDeviceGpuOrUsb(ctx, userCred, input.Device, input.GpuType, input.MemoryRequest, input.AutoStart)
|
||||
} else if input.Model != "" {
|
||||
if !utils.IsInStringArray(input.SharingMode, api.VAILD_SHARING_MODES) {
|
||||
return nil, httperrors.NewInputParameterError("shaing_mode %s not valid", input.SharingMode)
|
||||
}
|
||||
|
||||
var count int = 1
|
||||
if input.Count != nil {
|
||||
count = *input.Count
|
||||
}
|
||||
if count < 1 {
|
||||
return nil, httperrors.NewBadRequestError("guest attach gpu count must > 0")
|
||||
}
|
||||
err = self.StartAttachIsolatedDevices(ctx, userCred, vmodel, int(count), autoStart)
|
||||
input.Count = &count
|
||||
err = self.StartAttachIsolatedDevices(ctx, userCred, input.Model, input.GpuType, input.SharingMode, count, input.MemoryRequest, input.AutoStart)
|
||||
} else {
|
||||
return nil, httperrors.NewMissingParameterError("device||model")
|
||||
}
|
||||
@@ -2513,101 +2549,104 @@ func (self *SGuest) PerformAttachIsolatedDevice(ctx context.Context, userCred mc
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (self *SGuest) StartAttachIsolatedDevices(ctx context.Context, userCred mcclient.TokenCredential, devModel string, count int, autoStart bool) error {
|
||||
if err := self.startAttachIsolatedDevices(ctx, userCred, devModel, count); err != nil {
|
||||
func (self *SGuest) StartAttachIsolatedDevices(ctx context.Context, userCred mcclient.TokenCredential, devModel, gpuType, sharingMode string, count int, memoryRequest *int, autoStart bool) error {
|
||||
if err := self.startAttachIsolatedDevices(ctx, userCred, devModel, gpuType, sharingMode, count, memoryRequest); err != nil {
|
||||
return err
|
||||
}
|
||||
// perform post attach task
|
||||
return self.StartIsolatedDevicesSyncTask(ctx, userCred, autoStart, "")
|
||||
}
|
||||
|
||||
func (self *SGuest) AttachIsolatedDevices(ctx context.Context, userCred mcclient.TokenCredential, devModelCount map[string]int) error {
|
||||
func (self *SGuest) AttachIsolatedDevices(ctx context.Context, userCred mcclient.TokenCredential, devModelCount map[string]int, gpuType, sharingMode string, memoryRequest *int) error {
|
||||
host, _ := self.GetHost()
|
||||
lockman.LockObject(ctx, host)
|
||||
defer lockman.ReleaseObject(ctx, host)
|
||||
attachedGpus, err := self.GetGuestIsolatedDevices()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "get isolated devices")
|
||||
}
|
||||
attachedAddrs := map[string]struct{}{}
|
||||
for i := range attachedGpus {
|
||||
dev := attachedGpus[i].GetIsolatedDevice()
|
||||
attachedAddrs[dev.Addr] = struct{}{}
|
||||
gdev := attachedGpus[i].GetIsolatedDevice()
|
||||
if sharingMode == api.DEVICE_SHARING_MODE_MDEV {
|
||||
if gdev.SharingMode == api.DEVICE_SHARING_MODE_MDEV {
|
||||
return httperrors.NewBadRequestError("Nvidia vgpu count exceed > 1")
|
||||
} else if gdev.DevType == api.GPU_TYPE {
|
||||
return httperrors.NewBadRequestError("Nvidia vgpu can't passthrough with other gpus")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unusedDevs := []SIsolatedDevice{}
|
||||
for devModel, count := range devModelCount {
|
||||
devs, err := IsolatedDeviceManager.GetUnusedDevsOnHost(host.Id, devModel, count)
|
||||
devs, err := IsolatedDeviceManager.GetAvailableIsolatedDeviceOnHost(host.Id, devModel, sharingMode)
|
||||
if err != nil {
|
||||
return httperrors.NewInternalServerError("fetch gpu failed %s", err)
|
||||
}
|
||||
if len(devs) == 0 || len(devs) != count {
|
||||
if len(devs) == 0 {
|
||||
return httperrors.NewBadRequestError("required %d %s isolated devices on host %s, but not enough are available", count, devModel, host.GetName())
|
||||
}
|
||||
dev := devs[0]
|
||||
if !utils.IsInStringArray(dev.DevType, api.VALID_ATTACH_TYPES) {
|
||||
if devModel, err := IsolatedDeviceModelManager.GetByDevType(dev.DevType); err != nil {
|
||||
return httperrors.NewBadRequestError("Can't separately attach dev type %s", dev.DevType)
|
||||
avaDevs := make([]SIsolatedDevice, 0)
|
||||
avaDevCnt := 0
|
||||
for i := range devs {
|
||||
dev := devs[i]
|
||||
if _, ok := attachedAddrs[dev.Addr]; ok {
|
||||
continue
|
||||
}
|
||||
if dev.SharingMode == api.DEVICE_SHARING_MODE_HAMI {
|
||||
if memoryRequest == nil || *memoryRequest <= 0 {
|
||||
return httperrors.NewBadRequestError("dev sharing_mode %s memory request invalid", dev.SharingMode)
|
||||
}
|
||||
if dev.IsEnough(*memoryRequest) {
|
||||
avaDevs = append(avaDevs, dev)
|
||||
avaDevCnt += 1
|
||||
}
|
||||
} else {
|
||||
if !devModel.HotPluggable.Bool() && self.GetStatus() == api.VM_RUNNING {
|
||||
return httperrors.NewBadRequestError("dev type %s model %s unhotpluggable", dev.DevType, devModel.Model)
|
||||
cnt, err := dev.getAllocatedCount()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "getAllocatedCount")
|
||||
}
|
||||
if dev.VirtualNum > cnt {
|
||||
avaCnt := dev.VirtualNum - cnt
|
||||
avaDevCnt += avaCnt
|
||||
for j := 0; j < avaCnt; j++ {
|
||||
avaDevs = append(avaDevs, dev)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if dev.DevType == api.LEGACY_VGPU_TYPE {
|
||||
attachedGpus, err := self.GetIsolatedDevices()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "get isolated devices")
|
||||
}
|
||||
for i := range attachedGpus {
|
||||
if attachedGpus[i].DevType == api.LEGACY_VGPU_TYPE {
|
||||
return httperrors.NewBadRequestError("Nvidia vGPU count cannot exceed 1")
|
||||
} else if utils.IsInStringArray(attachedGpus[i].DevType, api.VALID_GPU_TYPES) {
|
||||
return httperrors.NewBadRequestError("Nvidia vGPU cannot passthrough with other gpus")
|
||||
}
|
||||
}
|
||||
} else if dev.DevType == api.CONTAINER_DEV_NVIDIA_MPS {
|
||||
allDevs, err := IsolatedDeviceManager.GetUnusedDevsOnHost(host.Id, devModel, -1)
|
||||
if err != nil {
|
||||
return httperrors.NewInternalServerError("fetch gpu failed %s", err)
|
||||
}
|
||||
attachedGpus, err := self.GetIsolatedDevices()
|
||||
if err != nil {
|
||||
return httperrors.NewInternalServerError("get attached isolated devices %s", err)
|
||||
}
|
||||
attachedAddrs := map[string]struct{}{}
|
||||
for i := range attachedGpus {
|
||||
addr := strings.Split(attachedGpus[i].Addr, "-")[0]
|
||||
attachedAddrs[addr] = struct{}{}
|
||||
}
|
||||
validDevs := []SIsolatedDevice{}
|
||||
for i := range allDevs {
|
||||
devAddr := strings.Split(allDevs[i].Addr, "-")[0]
|
||||
if _, ok := attachedAddrs[devAddr]; ok {
|
||||
continue
|
||||
}
|
||||
validDevs = append(validDevs, allDevs[i])
|
||||
}
|
||||
if len(validDevs) < count {
|
||||
return httperrors.NewInsufficientResourceError("required %d %s isolated devices on host %s, but not enough are available", count, devModel, host.GetName())
|
||||
}
|
||||
devs = validDevs[:count]
|
||||
if avaDevCnt < count {
|
||||
return httperrors.NewInsufficientResourceError("Available device count %d less then request count %d", avaDevCnt, count)
|
||||
}
|
||||
unusedDevs = append(unusedDevs, devs...)
|
||||
}
|
||||
defer func() { go host.ClearSchedDescCache() }()
|
||||
for i := 0; i < len(unusedDevs); i++ {
|
||||
if err := self.attachIsolatedDevice(ctx, userCred, &unusedDevs[i], nil, nil); err != nil {
|
||||
return errors.Wrapf(err, "attach device %s", unusedDevs[i].GetId())
|
||||
dev := avaDevs[0]
|
||||
if !dev.HotPluggable && self.GetStatus() == api.VM_RUNNING {
|
||||
return httperrors.NewBadRequestError("dev type %s model %s unhotpluggable", dev.DevType, dev.Model)
|
||||
}
|
||||
|
||||
for k := 0; k < count; k++ {
|
||||
if err := self.attachIsolatedDevice(ctx, userCred, &avaDevs[k], nil, nil, memoryRequest, gpuType); err != nil {
|
||||
return errors.Wrapf(err, "attach device %s", avaDevs[k].GetId())
|
||||
}
|
||||
}
|
||||
}
|
||||
go host.ClearSchedDescCache()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (self *SGuest) startAttachIsolatedDevices(ctx context.Context, userCred mcclient.TokenCredential, devModel string, count int) error {
|
||||
return self.AttachIsolatedDevices(ctx, userCred, map[string]int{devModel: count})
|
||||
func (self *SGuest) startAttachIsolatedDevices(ctx context.Context, userCred mcclient.TokenCredential, devModel, gpuType, sharingMode string, count int, memoryRequest *int) error {
|
||||
return self.AttachIsolatedDevices(ctx, userCred, map[string]int{devModel: count}, gpuType, sharingMode, memoryRequest)
|
||||
}
|
||||
|
||||
func (self *SGuest) StartAttachIsolatedDeviceGpuOrUsb(ctx context.Context, userCred mcclient.TokenCredential, device string, autoStart bool) error {
|
||||
if err := self.startAttachIsolatedDevGeneral(ctx, userCred, device); err != nil {
|
||||
func (self *SGuest) StartAttachIsolatedDeviceGpuOrUsb(ctx context.Context, userCred mcclient.TokenCredential, device, gpuType string, memoryRequest *int, autoStart bool) error {
|
||||
if err := self.startAttachIsolatedDevGeneral(ctx, userCred, device, gpuType, memoryRequest); err != nil {
|
||||
return err
|
||||
}
|
||||
// perform post attach task
|
||||
return self.StartIsolatedDevicesSyncTask(ctx, userCred, autoStart, "")
|
||||
}
|
||||
|
||||
func (self *SGuest) startAttachIsolatedDevGeneral(ctx context.Context, userCred mcclient.TokenCredential, device string) error {
|
||||
func (self *SGuest) startAttachIsolatedDevGeneral(ctx context.Context, userCred mcclient.TokenCredential, device, gpuType string, memoryRequest *int) error {
|
||||
iDev, err := IsolatedDeviceManager.FetchByIdOrName(ctx, userCred, device)
|
||||
if err != nil {
|
||||
msgFmt := "Isolated device %s not found"
|
||||
@@ -2616,29 +2655,45 @@ func (self *SGuest) startAttachIsolatedDevGeneral(ctx context.Context, userCred
|
||||
return httperrors.NewBadRequestError(msgFmt, device)
|
||||
}
|
||||
dev := iDev.(*SIsolatedDevice)
|
||||
if !utils.IsInStringArray(dev.DevType, api.VALID_ATTACH_TYPES) {
|
||||
if devModel, err := IsolatedDeviceModelManager.GetByDevType(dev.DevType); err != nil {
|
||||
return httperrors.NewBadRequestError("Can't separately attach dev type %s", dev.DevType)
|
||||
} else {
|
||||
if !devModel.HotPluggable.Bool() && self.GetStatus() == api.VM_RUNNING {
|
||||
return httperrors.NewBadRequestError("dev type %s model %s unhotpluggable", dev.DevType, devModel.Model)
|
||||
}
|
||||
gdevs, err := self.GetGuestIsolatedDevices()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for i := range gdevs {
|
||||
if gdevs[i].IsolatedDeviceId == dev.Id {
|
||||
return httperrors.NewBadRequestError("device %s is already in used by guest %s", dev.Id, self.GetName())
|
||||
}
|
||||
}
|
||||
if !utils.IsInStringArray(self.GetStatus(), []string{api.VM_READY, api.VM_RUNNING}) {
|
||||
return httperrors.NewInvalidStatusError("Can't attach GPU when status is %q", self.GetStatus())
|
||||
if !dev.HotPluggable && self.GetStatus() == api.VM_RUNNING {
|
||||
return httperrors.NewBadRequestError("dev type %s model %s unhotpluggable", dev.DevType, dev.Model)
|
||||
}
|
||||
|
||||
if dev.DevType == api.LEGACY_VGPU_TYPE {
|
||||
devs, err := self.GetIsolatedDevices()
|
||||
if !utils.IsInStringArray(self.GetStatus(), []string{api.VM_READY, api.VM_RUNNING}) {
|
||||
return httperrors.NewInvalidStatusError("Can't attach isolated device when status is %q", self.GetStatus())
|
||||
}
|
||||
|
||||
reqCnt := 1
|
||||
if dev.SharingMode == api.DEVICE_SHARING_MODE_HAMI {
|
||||
if memoryRequest == nil || *memoryRequest <= 0 {
|
||||
return httperrors.NewBadRequestError("Dev sharing_mode %s memory request invalid", dev.SharingMode)
|
||||
}
|
||||
reqCnt = *memoryRequest
|
||||
}
|
||||
if !dev.IsEnough(reqCnt) {
|
||||
return httperrors.NewBadRequestError("Dev %s is not enough", dev.GetName())
|
||||
}
|
||||
|
||||
if dev.SharingMode == api.DEVICE_SHARING_MODE_MDEV {
|
||||
devs, err := self.GetGuestIsolatedDevices()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "get isolated devices")
|
||||
}
|
||||
for i := range devs {
|
||||
if devs[i].DevType == api.LEGACY_VGPU_TYPE {
|
||||
return httperrors.NewBadRequestError("Nvidia vGPU count cannot exceed 1")
|
||||
} else if utils.IsInStringArray(devs[i].DevType, api.VALID_GPU_TYPES) {
|
||||
return httperrors.NewBadRequestError("Nvidia vGPU cannot passthrough with other gpus")
|
||||
gdev := devs[i].GetIsolatedDevice()
|
||||
if gdev.SharingMode == api.DEVICE_SHARING_MODE_MDEV {
|
||||
return httperrors.NewBadRequestError("Nvidia vgpu count exceed > 1")
|
||||
} else if gdev.DevType == api.GPU_TYPE {
|
||||
return httperrors.NewBadRequestError("Nvidia vgpu can't passthrough with other gpus")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2646,7 +2701,7 @@ func (self *SGuest) startAttachIsolatedDevGeneral(ctx context.Context, userCred
|
||||
host, _ := self.GetHost()
|
||||
lockman.LockObject(ctx, host)
|
||||
defer lockman.ReleaseObject(ctx, host)
|
||||
err = self.attachIsolatedDevice(ctx, userCred, dev, nil, nil)
|
||||
err = self.attachIsolatedDevice(ctx, userCred, dev, nil, nil, memoryRequest, gpuType)
|
||||
var msg string
|
||||
if err != nil {
|
||||
msg = err.Error()
|
||||
@@ -2657,39 +2712,52 @@ func (self *SGuest) startAttachIsolatedDevGeneral(ctx context.Context, userCred
|
||||
return err
|
||||
}
|
||||
|
||||
func (self *SGuest) attachIsolatedDevice(ctx context.Context, userCred mcclient.TokenCredential, dev *SIsolatedDevice, networkIndex *int, diskIndex *int8) error {
|
||||
if len(dev.GuestId) > 0 {
|
||||
return fmt.Errorf("Isolated device already attached to another guest: %s", dev.GuestId)
|
||||
func (self *SGuest) attachIsolatedDevice(ctx context.Context, userCred mcclient.TokenCredential, dev *SIsolatedDevice, networkIndex *int, diskIndex *int8, memoryRequest *int, gpuType string) error {
|
||||
if dev.IsFull() {
|
||||
return fmt.Errorf("Isolated device already allocated")
|
||||
}
|
||||
if dev.HostId != self.HostId {
|
||||
return fmt.Errorf("Isolated device and guest are not located in the same host")
|
||||
}
|
||||
|
||||
lockman.LockObject(ctx, self)
|
||||
defer lockman.ReleaseObject(ctx, self)
|
||||
// guest isolated device attach
|
||||
guestIsolatedDevice := SGuestIsolatedDevice{}
|
||||
guestIsolatedDevice.SetModelManager(GuestIsolatedDeviceManager, &guestIsolatedDevice)
|
||||
guestIsolatedDevice.GuestId = self.Id
|
||||
guestIsolatedDevice.IsolatedDeviceId = dev.Id
|
||||
guestIsolatedDevice.Index = self.getIsolatedDeviceIndex()
|
||||
|
||||
if networkIndex != nil {
|
||||
guestIsolatedDevice.NetworkIndex = *networkIndex
|
||||
}
|
||||
if diskIndex != nil {
|
||||
guestIsolatedDevice.DiskIndex = *diskIndex
|
||||
}
|
||||
if dev.SharingMode == api.DEVICE_SHARING_MODE_HAMI && memoryRequest != nil {
|
||||
guestIsolatedDevice.DeviceMemorySize = *memoryRequest
|
||||
}
|
||||
if utils.IsInStringArray(gpuType, []string{api.GPU_HPC, api.GPU_VGA}) {
|
||||
guestIsolatedDevice.GpuType = gpuType
|
||||
}
|
||||
|
||||
drv, _ := self.GetDriver()
|
||||
if err := drv.BeforeAttachIsolatedDevice(ctx, userCred, self, dev); err != nil {
|
||||
return errors.Wrapf(err, "BeforeAttachIsolatedDevice %s of guest %s", jsonutils.Marshal(dev), self.GetId())
|
||||
if err := drv.BeforeAttachIsolatedDevice(ctx, userCred, self, &guestIsolatedDevice); err != nil {
|
||||
return errors.Wrapf(err, "BeforeAttachIsolatedDevice %s of guest %s", jsonutils.Marshal(guestIsolatedDevice), self.GetId())
|
||||
}
|
||||
if _, err := db.Update(dev, func() error {
|
||||
dev.GuestId = self.Id
|
||||
if networkIndex != nil {
|
||||
dev.NetworkIndex = *networkIndex
|
||||
} else {
|
||||
dev.NetworkIndex = -1
|
||||
}
|
||||
if diskIndex != nil {
|
||||
dev.DiskIndex = *diskIndex
|
||||
} else {
|
||||
dev.DiskIndex = -1
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
return errors.Wrap(err, "db.Update")
|
||||
|
||||
err := GuestIsolatedDeviceManager.TableSpec().Insert(ctx, &guestIsolatedDevice)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
db.OpsLog.LogEvent(self, db.ACT_GUEST_ATTACH_ISOLATED_DEVICE, dev.GetShortDesc(ctx), userCred)
|
||||
return nil
|
||||
}
|
||||
|
||||
// 设置透传设备
|
||||
func (self *SGuest) PerformSetIsolatedDevice(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, data jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
func (self *SGuest) PerformSetIsolatedDevice(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject, input *api.SetIsolatedDeviceInput) (jsonutils.JSONObject, error) {
|
||||
if self.Hypervisor != api.HYPERVISOR_KVM && self.Hypervisor != api.HYPERVISOR_POD {
|
||||
return nil, httperrors.NewNotAcceptableError("Not allow for hypervisor %s", self.Hypervisor)
|
||||
}
|
||||
@@ -2697,46 +2765,27 @@ func (self *SGuest) PerformSetIsolatedDevice(ctx context.Context, userCred mccli
|
||||
(self.Hypervisor == api.HYPERVISOR_POD && self.GetStatus() != api.VM_READY) {
|
||||
return nil, httperrors.NewInvalidStatusError("Can't set isolated device when guest is %s", self.GetStatus())
|
||||
}
|
||||
var addDevs []string
|
||||
{
|
||||
addDevices, err := data.Get("add_devices")
|
||||
if err == nil {
|
||||
arrAddDev, ok := addDevices.(*jsonutils.JSONArray)
|
||||
if ok {
|
||||
addDevs = arrAddDev.GetStringArray()
|
||||
} else {
|
||||
return nil, httperrors.NewInputParameterError("attach devices is not string array")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var delDevs []string
|
||||
{
|
||||
delDevices, err := data.Get("del_devices")
|
||||
if err == nil {
|
||||
arrDelDev, ok := delDevices.(*jsonutils.JSONArray)
|
||||
if ok {
|
||||
delDevs = arrDelDev.GetStringArray()
|
||||
} else {
|
||||
return nil, httperrors.NewInputParameterError("detach devices is not string array")
|
||||
}
|
||||
}
|
||||
}
|
||||
var addDevs = input.AddDevices
|
||||
var delDevs = input.DelDevices
|
||||
|
||||
// detach first
|
||||
for i := 0; i < len(delDevs); i++ {
|
||||
err := self.startDetachIsolateDeviceWithoutNic(ctx, userCred, delDevs[i])
|
||||
err := self.startDetachIsolateDeviceWithoutNic(ctx, userCred, delDevs[i].Device, delDevs[i].Index)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
for i := 0; i < len(addDevs); i++ {
|
||||
err := self.startAttachIsolatedDevGeneral(ctx, userCred, addDevs[i])
|
||||
if addDevs[i].GpuType != "" && !utils.IsInStringArray(addDevs[i].GpuType, []string{api.GPU_VGA, api.GPU_HPC}) {
|
||||
return nil, httperrors.NewInputParameterError("gpu_type %s not vaild", addDevs[i].GpuType)
|
||||
}
|
||||
|
||||
err := self.startAttachIsolatedDevGeneral(ctx, userCred, addDevs[i].Device, addDevs[i].GpuType, addDevs[i].MemoryRequest)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return nil, self.StartIsolatedDevicesSyncTask(ctx, userCred, jsonutils.QueryBoolean(data, "auto_start", false), "")
|
||||
return nil, self.StartIsolatedDevicesSyncTask(ctx, userCred, input.AutoStart, "")
|
||||
}
|
||||
|
||||
func (self *SGuest) StartIsolatedDevicesSyncTask(ctx context.Context, userCred mcclient.TokenCredential, autoStart bool, parentId string) error {
|
||||
@@ -3569,7 +3618,7 @@ func (self *SGuest) PerformChangeConfig(ctx context.Context, userCred mcclient.T
|
||||
|
||||
func (self *SGuest) ChangeConfToSchedDesc(addCpu, addExtraCpu, addMem int, schedInputDisks []*api.DiskConfig) *schedapi.ScheduleInput {
|
||||
region, _ := self.GetRegion()
|
||||
devs, _ := self.GetIsolatedDevices()
|
||||
devs, _ := self.GetGuestIsolatedDevices()
|
||||
desc := &schedapi.ScheduleInput{
|
||||
ServerConfig: schedapi.ServerConfig{
|
||||
ServerConfigs: &api.ServerConfigs{
|
||||
@@ -4644,7 +4693,7 @@ func (self *SGuest) PerformCreateBackup(
|
||||
if self.Hypervisor != api.HYPERVISOR_KVM {
|
||||
return nil, httperrors.NewBadRequestError("Backup only support hypervisor kvm")
|
||||
}
|
||||
devs, _ := self.GetIsolatedDevices()
|
||||
devs, _ := self.GetGuestIsolatedDevices()
|
||||
if len(devs) > 0 {
|
||||
return nil, httperrors.NewBadRequestError("Cannot create backup with isolated devices")
|
||||
}
|
||||
@@ -5264,9 +5313,10 @@ func (self *SGuest) GenerateVirtInstallCommandLine(
|
||||
}
|
||||
|
||||
// isolated devices
|
||||
isolatedDevices, _ := self.GetIsolatedDevices()
|
||||
isolatedDevices, _ := self.GetGuestIsolatedDevices()
|
||||
for _, isolatedDev := range isolatedDevices {
|
||||
cmd += L(fmt.Sprintf("--hostdev %s", isolatedDev.Addr))
|
||||
dev := isolatedDev.GetIsolatedDevice()
|
||||
cmd += L(fmt.Sprintf("--hostdev %s", dev.Addr))
|
||||
}
|
||||
|
||||
if utils.IsInStringArray(self.Status, []string{api.VM_RUNNING, api.VM_BLOCK_STREAM}) {
|
||||
@@ -5532,7 +5582,7 @@ func (self *SGuest) validateForBatchMigrate(ctx context.Context, rescueMode bool
|
||||
if len(guest.BackupHostId) > 0 {
|
||||
return guest, httperrors.NewBadRequestError("guest %s has backup, can't migrate", guest.Name)
|
||||
}
|
||||
devs, _ := guest.GetIsolatedDevices()
|
||||
devs, _ := guest.GetGuestIsolatedDevices()
|
||||
if len(devs) > 0 {
|
||||
return guest, httperrors.NewBadRequestError("guest %s has isolated device, can't migrate", guest.Name)
|
||||
}
|
||||
@@ -5930,7 +5980,6 @@ func (self *SGuest) StartSnapshotResetTask(ctx context.Context, userCred mcclien
|
||||
data.Add(jsonutils.NewBool(withMemory), "with_memory")
|
||||
self.SetStatus(ctx, userCred, api.VM_START_SNAPSHOT_RESET, "start snapshot reset task")
|
||||
instanceSnapshot.SetStatus(ctx, userCred, api.INSTANCE_SNAPSHOT_RESET, "start snapshot reset task")
|
||||
log.Errorf("====data: %s", data)
|
||||
if task, err := taskman.TaskManager.NewTask(
|
||||
ctx, "InstanceSnapshotResetTask", instanceSnapshot, userCred, data, "", "", nil,
|
||||
); err != nil {
|
||||
@@ -6969,7 +7018,7 @@ func (self *SGuest) PerformProbeIsolatedDevices(ctx context.Context, userCred mc
|
||||
return nil, errors.Wrapf(err, "FetchById %q", id)
|
||||
}
|
||||
dev := devObj.(*SIsolatedDevice)
|
||||
if dev.GuestId == "" {
|
||||
if !dev.IsFull() {
|
||||
devs = append(devs, dev)
|
||||
}
|
||||
}
|
||||
@@ -7107,12 +7156,13 @@ func (self *SGuest) GetDetailsCpusetCores(ctx context.Context, userCred mcclient
|
||||
|
||||
func (self *SGuest) GetDetailsNumaInfo(ctx context.Context, userCred mcclient.TokenCredential, _ *api.ServerGetNumaInfoInput) (*api.ServerGetNumaInfoResp, error) {
|
||||
ret := new(api.ServerGetNumaInfoResp)
|
||||
devs, _ := self.GetIsolatedDevices()
|
||||
devs, _ := self.GetGuestIsolatedDevices()
|
||||
if len(devs) > 0 {
|
||||
ret.IsolatedDevicesNumaNode = make([]int8, 0)
|
||||
for i := range devs {
|
||||
if devs[i].NumaNode > 0 {
|
||||
ret.IsolatedDevicesNumaNode = append(ret.IsolatedDevicesNumaNode, devs[i].NumaNode)
|
||||
dev := devs[i].GetIsolatedDevice()
|
||||
if dev.NumaNode > 0 {
|
||||
ret.IsolatedDevicesNumaNode = append(ret.IsolatedDevicesNumaNode, dev.NumaNode)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7178,12 +7228,13 @@ func (self *SGuest) GetDetailsHardwareInfo(ctx context.Context, userCred mcclien
|
||||
}
|
||||
|
||||
// fill GPU info
|
||||
devs, err := self.GetIsolatedDevices()
|
||||
devs, err := self.GetGuestIsolatedDevices()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "get isolated devices")
|
||||
}
|
||||
gpuInfos := make([]*api.ServerHardwareInfoGPU, 0)
|
||||
for _, dev := range devs {
|
||||
for i := range devs {
|
||||
dev := devs[i].GetIsolatedDevice()
|
||||
if !dev.IsGPU() {
|
||||
continue
|
||||
}
|
||||
|
||||
316
pkg/compute/models/guest_isolated_devices.go
Normal file
316
pkg/compute/models/guest_isolated_devices.go
Normal file
@@ -0,0 +1,316 @@
|
||||
package models
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/sqlchemy"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/util/stringutils2"
|
||||
)
|
||||
|
||||
// +onecloud:swagger-gen-ignore
|
||||
type SGuestIsolatedDeviceManager struct {
|
||||
SGuestJointsManager
|
||||
SIsolatedDeviceResourceBaseManager
|
||||
}
|
||||
|
||||
var GuestIsolatedDeviceManager *SGuestIsolatedDeviceManager
|
||||
|
||||
func init() {
|
||||
db.InitManager(func() {
|
||||
GuestIsolatedDeviceManager = &SGuestIsolatedDeviceManager{
|
||||
SGuestJointsManager: NewGuestJointsManager(
|
||||
SGuestIsolatedDevice{},
|
||||
"guestisolateddevices_tbl",
|
||||
"guestisolateddevice",
|
||||
"guestisolateddevices",
|
||||
IsolatedDeviceManager,
|
||||
),
|
||||
}
|
||||
GuestIsolatedDeviceManager.SetVirtualObject(GuestIsolatedDeviceManager)
|
||||
GuestIsolatedDeviceManager.TableSpec().AddIndex(false, "isolated_device_id", "guest_id")
|
||||
})
|
||||
}
|
||||
|
||||
// +onecloud:model-api-gen
|
||||
type SGuestIsolatedDevice struct {
|
||||
SGuestJointsBase
|
||||
SIsolatedDeviceResourceBase
|
||||
|
||||
// guest isolated device memory size limit
|
||||
DeviceMemorySize int `nullable:"true" default:"0" list:"user" update:"user" create:"optional"`
|
||||
// guest isolated device Streaming Multiprocessor Utilization limit
|
||||
SmUtilLimit int `nullable:"true" default:"0" list:"user" update:"user" create:"optional"`
|
||||
// gpu device work type: HPC VGA
|
||||
GpuType string `width:"16" charset:"ascii" nullable:"true" default:"" index:"true" list:"user" create:"optional" update:"user"`
|
||||
|
||||
// guest network index
|
||||
NetworkIndex int `nullable:"true" default:"-1" list:"user"`
|
||||
// guest disk index
|
||||
DiskIndex int8 `nullable:"true" default:"-1" list:"user"`
|
||||
|
||||
Index int8 `nullable:"false" default:"0" list:"user"`
|
||||
}
|
||||
|
||||
func (manager *SGuestIsolatedDeviceManager) GetSlaveFieldName() string {
|
||||
return "isolated_device_id"
|
||||
}
|
||||
|
||||
func (self *SGuestIsolatedDevice) Delete(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
return db.DeleteModel(ctx, userCred, self)
|
||||
}
|
||||
|
||||
func (self *SGuestIsolatedDevice) Detach(ctx context.Context, userCred mcclient.TokenCredential) error {
|
||||
return db.DetachJoint(ctx, userCred, self)
|
||||
}
|
||||
|
||||
func (manager *SGuestIsolatedDeviceManager) ListItemFilter(
|
||||
ctx context.Context,
|
||||
q *sqlchemy.SQuery,
|
||||
userCred mcclient.TokenCredential,
|
||||
query api.GuestIsolatedDeviceListInput,
|
||||
) (*sqlchemy.SQuery, error) {
|
||||
var err error
|
||||
q, err = manager.SGuestJointsManager.ListItemFilter(ctx, q, userCred, query.GuestJointsListInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SGuestJointsManager.ListItemFilter")
|
||||
}
|
||||
if len(query.IsolateDeviceIds) > 0 {
|
||||
query.IsolatedDeviceListInput.Ids = query.IsolateDeviceIds
|
||||
}
|
||||
q, err = manager.SIsolatedDeviceResourceBaseManager.ListItemFilter(ctx, q, userCred, query)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SGuestJointsManager.ListItemFilter")
|
||||
}
|
||||
return q, nil
|
||||
}
|
||||
|
||||
func (manager *SGuestIsolatedDeviceManager) ListItemExportKeys(ctx context.Context,
|
||||
q *sqlchemy.SQuery,
|
||||
userCred mcclient.TokenCredential,
|
||||
keys stringutils2.SSortedStrings,
|
||||
) (*sqlchemy.SQuery, error) {
|
||||
var err error
|
||||
|
||||
q, err = manager.SGuestJointsManager.ListItemExportKeys(ctx, q, userCred, keys)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SGuestJointsManager.ListItemExportKeys")
|
||||
}
|
||||
if keys.ContainsAny(manager.SIsolatedDeviceResourceBaseManager.GetExportKeys()...) {
|
||||
q, err = manager.SIsolatedDeviceResourceBaseManager.ListItemExportKeys(ctx, q, userCred, keys)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SIsolatedDeviceManager.ListItemExportKeys")
|
||||
}
|
||||
}
|
||||
|
||||
return q, nil
|
||||
}
|
||||
|
||||
func (manager *SGuestIsolatedDeviceManager) CreateByInsertOrUpdate() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (manager *SGuestIsolatedDeviceManager) FetchCustomizeColumns(
|
||||
ctx context.Context,
|
||||
userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject,
|
||||
objs []interface{},
|
||||
fields stringutils2.SSortedStrings,
|
||||
isList bool,
|
||||
) []api.GuestIsolatedDeviceDetails {
|
||||
rows := make([]api.GuestIsolatedDeviceDetails, len(objs))
|
||||
guestRows := manager.SGuestJointsManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
|
||||
isolatedDeviceRows := manager.SIsolatedDeviceResourceBaseManager.FetchCustomizeColumns(ctx, userCred, query, objs, fields, isList)
|
||||
for i := range rows {
|
||||
rows[i].GuestJointResourceDetails = guestRows[i]
|
||||
rows[i].SIsolatedDevice = isolatedDeviceRows[i].SIsolatedDevice
|
||||
rows[i].HostResourceInfo = isolatedDeviceRows[i].HostResourceInfo
|
||||
rows[i].SharableResourceBaseInfo = isolatedDeviceRows[i].SharableResourceBaseInfo
|
||||
}
|
||||
|
||||
return rows
|
||||
}
|
||||
|
||||
func (manager *SGuestIsolatedDeviceManager) OrderByExtraFields(
|
||||
ctx context.Context,
|
||||
q *sqlchemy.SQuery,
|
||||
userCred mcclient.TokenCredential,
|
||||
query api.GuestIsolatedDeviceListInput,
|
||||
) (*sqlchemy.SQuery, error) {
|
||||
var err error
|
||||
|
||||
q, err = manager.SGuestJointsManager.OrderByExtraFields(ctx, q, userCred, query.GuestJointsListInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SGuestJointsManager.OrderByExtraFields")
|
||||
}
|
||||
q, err = manager.SIsolatedDeviceResourceBaseManager.OrderByExtraFields(ctx, q, userCred, query)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SNetworkResourceBaseManager.OrderByExtraFields")
|
||||
}
|
||||
|
||||
return q, nil
|
||||
}
|
||||
|
||||
func (dev *SIsolatedDevice) getAllocatedMemorySize() (int, error) {
|
||||
sq := GuestIsolatedDeviceManager.Query().
|
||||
Equals("isolated_device_id", dev.Id).
|
||||
SubQuery()
|
||||
|
||||
q := sq.Query(
|
||||
sqlchemy.SUM("memory_used", sq.Field("device_memory_size")),
|
||||
)
|
||||
|
||||
var result struct {
|
||||
MemoryUsed int
|
||||
}
|
||||
|
||||
err := q.First(&result)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return result.MemoryUsed, nil
|
||||
}
|
||||
|
||||
func (dev *SIsolatedDevice) getAllocatedCount() (int, error) {
|
||||
return GuestIsolatedDeviceManager.Query().Equals("isolated_device_id", dev.Id).CountWithError()
|
||||
}
|
||||
|
||||
func (dev *SIsolatedDevice) getAttachedGuestIds() []string {
|
||||
q := GuestIsolatedDeviceManager.Query("guest_id").Equals("isolated_device_id", dev.Id)
|
||||
type sGuestId struct {
|
||||
GuestId string
|
||||
}
|
||||
|
||||
guestIsolatedDevices := make([]sGuestId, 0)
|
||||
err := q.All(&guestIsolatedDevices)
|
||||
if err != nil {
|
||||
log.Errorf("failed get guest isolated devices %s", err)
|
||||
return nil
|
||||
}
|
||||
ret := make([]string, len(guestIsolatedDevices))
|
||||
for i := range guestIsolatedDevices {
|
||||
ret[i] = guestIsolatedDevices[i].GuestId
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func (dev *SIsolatedDevice) getAttachedGuests() []SGuestIsolatedDevice {
|
||||
q := GuestIsolatedDeviceManager.Query().Equals("isolated_device_id", dev.Id)
|
||||
guestIsolatedDevices := make([]SGuestIsolatedDevice, 0)
|
||||
err := db.FetchModelObjects(GuestIsolatedDeviceManager, q, &guestIsolatedDevices)
|
||||
if err != nil {
|
||||
log.Errorf("failed get guest isolated devices %s", err)
|
||||
return nil
|
||||
}
|
||||
return guestIsolatedDevices
|
||||
}
|
||||
|
||||
func (guest *SGuest) GetIsolatedDevicesQuery() *sqlchemy.SQuery {
|
||||
return GuestIsolatedDeviceManager.Query().Equals("guest_id", guest.Id)
|
||||
}
|
||||
|
||||
func (guest *SGuest) GetGuestIsolatedDevices() ([]SGuestIsolatedDevice, error) {
|
||||
gdevs := make([]SGuestIsolatedDevice, 0)
|
||||
q := guest.GetIsolatedDevicesQuery().Asc("index")
|
||||
err := db.FetchModelObjects(GuestIsolatedDeviceManager, q, &gdevs)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "db.FetchModelObjects")
|
||||
}
|
||||
return gdevs, nil
|
||||
}
|
||||
|
||||
func (guest *SGuest) GetGuestGpuIsolatedDevices() ([]SGuestIsolatedDevice, error) {
|
||||
gdevs := make([]SGuestIsolatedDevice, 0)
|
||||
q := guest.GetIsolatedDevicesQuery()
|
||||
isq := IsolatedDeviceManager.Query()
|
||||
|
||||
cond := sqlchemy.Equals(isq.Field("dev_type"), api.GPU_TYPE)
|
||||
isq = isq.Filter(cond)
|
||||
sidq := isq.SubQuery()
|
||||
q = q.Join(sidq, sqlchemy.Equals(q.Field("isolated_device_id"), sidq.Field("id")))
|
||||
q = q.Asc("index")
|
||||
err := db.FetchModelObjects(GuestIsolatedDeviceManager, q, &gdevs)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "db.FetchModelObjects")
|
||||
}
|
||||
return gdevs, nil
|
||||
}
|
||||
|
||||
func (self *SGuest) getIsolatedDeviceIndex() int8 {
|
||||
guestDevs, _ := self.GetGuestIsolatedDevices()
|
||||
var max uint
|
||||
for i := 0; i < len(guestDevs); i++ {
|
||||
if uint(guestDevs[i].Index) > max {
|
||||
max = uint(guestDevs[i].Index)
|
||||
}
|
||||
}
|
||||
|
||||
idxs := make([]int, max+1)
|
||||
for i := 0; i < len(guestDevs); i++ {
|
||||
idxs[guestDevs[i].Index] = 1
|
||||
}
|
||||
|
||||
// find first idx not set
|
||||
for i := 0; i < len(idxs); i++ {
|
||||
if idxs[i] != 1 {
|
||||
return int8(i)
|
||||
}
|
||||
}
|
||||
|
||||
return int8(max + 1)
|
||||
}
|
||||
|
||||
func (self *SGuestIsolatedDevice) GetIsolatedDevice() *SIsolatedDevice {
|
||||
dev, err := IsolatedDeviceManager.FetchById(self.IsolatedDeviceId)
|
||||
if err != nil {
|
||||
log.Errorf("IsolatedDeviceManager.FetchById %s", err)
|
||||
return nil
|
||||
}
|
||||
return dev.(*SIsolatedDevice)
|
||||
}
|
||||
|
||||
func (self *SIsolatedDevice) GetGuestIsolatedDevice(guestId string, index int) (*SGuestIsolatedDevice, error) {
|
||||
q := GuestIsolatedDeviceManager.Query().Equals("isolated_device_id", self.Id).Equals("guest_id", guestId).Equals("index", index)
|
||||
ret := &SGuestIsolatedDevice{}
|
||||
err := q.First(ret)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "fetch guest %s isolated device by id %s index %d", guestId, self.Id, index)
|
||||
}
|
||||
ret.SetModelManager(GuestIsolatedDeviceManager, ret)
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (self *SIsolatedDevice) GetAllGuestIsolatedDevices() ([]SGuestIsolatedDevice, error) {
|
||||
q := GuestIsolatedDeviceManager.Query().Equals("isolated_device_id", self.Id)
|
||||
ret := []SGuestIsolatedDevice{}
|
||||
err := db.FetchModelObjects(GuestIsolatedDeviceManager, q, &ret)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "fetch guest isolated device by id %s", self.Id)
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (self *SGuestIsolatedDevice) getDesc() *api.IsolatedDeviceJsonDesc {
|
||||
dev := self.GetIsolatedDevice()
|
||||
devDesc := dev.getDesc()
|
||||
devDesc.DiskIndex = self.DiskIndex
|
||||
devDesc.NetworkIndex = self.NetworkIndex
|
||||
devDesc.MemoryLimit = self.DeviceMemorySize
|
||||
devDesc.SmUtilLimit = self.SmUtilLimit
|
||||
devDesc.GpuType = self.GpuType
|
||||
return devDesc
|
||||
}
|
||||
|
||||
func (self *SGuestIsolatedDevice) GetShortDesc(ctx context.Context) *jsonutils.JSONDict {
|
||||
devDesc := self.getDesc()
|
||||
desc := jsonutils.NewDict()
|
||||
desc.Update(jsonutils.Marshal(devDesc))
|
||||
desc.Add(jsonutils.NewString(GuestIsolatedDeviceManager.Keyword()), "res_name")
|
||||
return desc
|
||||
}
|
||||
@@ -952,8 +952,8 @@ func fetchContainers(guestIds []string) (map[string][]*api.PodContainerDesc, err
|
||||
}
|
||||
|
||||
func fetchGuestIsolatedDevices(guestIds []string) map[string][]api.SIsolatedDevice {
|
||||
q := IsolatedDeviceManager.Query().In("guest_id", guestIds)
|
||||
devs := make([]SIsolatedDevice, 0)
|
||||
q := GuestIsolatedDeviceManager.Query().In("guest_id", guestIds)
|
||||
devs := make([]SGuestIsolatedDevice, 0)
|
||||
err := q.All(&devs)
|
||||
if err != nil {
|
||||
return nil
|
||||
@@ -961,14 +961,14 @@ func fetchGuestIsolatedDevices(guestIds []string) map[string][]api.SIsolatedDevi
|
||||
ret := make(map[string][]api.SIsolatedDevice)
|
||||
for i := range devs {
|
||||
dev := api.SIsolatedDevice{}
|
||||
dev.Id = devs[i].Id
|
||||
dev.HostId = devs[i].HostId
|
||||
dev.DevType = devs[i].DevType
|
||||
dev.Model = devs[i].Model
|
||||
dev.GuestId = devs[i].GuestId
|
||||
dev.Addr = devs[i].Addr
|
||||
dev.VendorDeviceId = devs[i].VendorDeviceId
|
||||
dev.NumaNode = byte(devs[i].NumaNode)
|
||||
gdev := devs[i].GetIsolatedDevice()
|
||||
dev.Id = gdev.Id
|
||||
dev.HostId = gdev.HostId
|
||||
dev.DevType = gdev.DevType
|
||||
dev.Model = gdev.Model
|
||||
dev.Addr = gdev.Addr
|
||||
dev.VendorDeviceId = gdev.VendorDeviceId
|
||||
dev.NumaNode = byte(gdev.NumaNode)
|
||||
gdevs, ok := ret[devs[i].GuestId]
|
||||
if !ok {
|
||||
gdevs = make([]api.SIsolatedDevice, 0)
|
||||
|
||||
@@ -258,8 +258,8 @@ type IGuestDriver interface {
|
||||
ValidateSyncOSInfo(ctx context.Context, userCred mcclient.TokenCredential, guest *SGuest) error
|
||||
RequestStartRescue(ctx context.Context, task taskman.ITask, body jsonutils.JSONObject, host *SHost, guest *SGuest) error
|
||||
|
||||
BeforeDetachIsolatedDevice(ctx context.Context, cred mcclient.TokenCredential, guest *SGuest, dev *SIsolatedDevice) error
|
||||
BeforeAttachIsolatedDevice(ctx context.Context, cred mcclient.TokenCredential, guest *SGuest, dev *SIsolatedDevice) error
|
||||
BeforeDetachIsolatedDevice(ctx context.Context, cred mcclient.TokenCredential, guest *SGuest, dev *SGuestIsolatedDevice) error
|
||||
BeforeAttachIsolatedDevice(ctx context.Context, cred mcclient.TokenCredential, guest *SGuest, dev *SGuestIsolatedDevice) error
|
||||
|
||||
RequestGuestScreenDump(ctx context.Context, userCred mcclient.TokenCredential, body jsonutils.JSONObject, host *SHost, guest *SGuest) (jsonutils.JSONObject, error)
|
||||
|
||||
|
||||
@@ -1010,7 +1010,7 @@ func (manager *SGuestnetworkManager) DeleteGuestNics(ctx context.Context, userCr
|
||||
return errors.Wrapf(httperrors.ErrInvalidStatus, "eip associate with %s", gn.IpAddr)
|
||||
}
|
||||
guest := gn.GetGuest()
|
||||
dev, err := guest.GetIsolatedDeviceByNetworkIndex(gn.Index)
|
||||
dev, err := guest.GetGuestIsolatedDeviceByNetworkIndex(gn.Index)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "GetIsolatedDeviceByNetworkIndex")
|
||||
}
|
||||
@@ -1274,7 +1274,10 @@ func (gn *SGuestnetwork) GetVirtualIPs() []string {
|
||||
|
||||
func (gn *SGuestnetwork) GetIsolatedDevice() (*SIsolatedDevice, error) {
|
||||
dev := SIsolatedDevice{}
|
||||
q := IsolatedDeviceManager.Query().Equals("guest_id", gn.GuestId).Equals("network_index", gn.Index)
|
||||
q := IsolatedDeviceManager.Query()
|
||||
gidq := GuestIsolatedDeviceManager.Query().
|
||||
Equals("guest_id", gn.GuestId).Equals("network_index", gn.Index).SubQuery()
|
||||
q = q.Join(gidq, sqlchemy.Equals(q.Field("id"), gidq.Field("isolated_device_id")))
|
||||
if cnt, err := q.CountWithError(); err != nil {
|
||||
return nil, err
|
||||
} else if cnt == 0 {
|
||||
|
||||
@@ -561,12 +561,14 @@ func (manager *SGuestManager) ListItemFilter(
|
||||
|
||||
devTypeQ := func(q *sqlchemy.SQuery, checkType, backup *bool, dType string, conditions []sqlchemy.ICondition) []sqlchemy.ICondition {
|
||||
if checkType != nil {
|
||||
isodev := IsolatedDeviceManager.Query().SubQuery()
|
||||
isodevCons := []sqlchemy.ICondition{sqlchemy.IsNotNull(isodev.Field("guest_id"))}
|
||||
guestIdev := GuestIsolatedDeviceManager.Query().SubQuery()
|
||||
sgq := guestIdev.Query(guestIdev.Field("guest_id")).GroupBy(guestIdev.Field("guest_id"))
|
||||
|
||||
if len(dType) > 0 {
|
||||
isodevCons = append(isodevCons, sqlchemy.Startswith(isodev.Field("dev_type"), dType))
|
||||
isodev := IsolatedDeviceManager.Query().SubQuery()
|
||||
sgq = sgq.Join(isodev, sqlchemy.Equals(guestIdev.Field("isolated_device_id"), isodev.Field("id")))
|
||||
sgq = sgq.Filter(sqlchemy.Startswith(isodev.Field("dev_type"), dType))
|
||||
}
|
||||
sgq := isodev.Query(isodev.Field("guest_id")).Filter(sqlchemy.AND(isodevCons...))
|
||||
cond := sqlchemy.NotIn
|
||||
if *checkType {
|
||||
cond = sqlchemy.In
|
||||
@@ -729,6 +731,12 @@ func (manager *SGuestManager) ListItemFilter(
|
||||
q = q.IsNullOrEmpty("host_id")
|
||||
}
|
||||
}
|
||||
if len(query.IsolatedDeviceId) > 0 {
|
||||
sq := GuestIsolatedDeviceManager.Query("guest_id").
|
||||
Equals("isolated_device_id", query.IsolatedDeviceId).SubQuery()
|
||||
q = q.In("id", sq)
|
||||
}
|
||||
|
||||
if len(query.SnapshotpolicyId) > 0 {
|
||||
sp := SnapshotPolicyResourceManager.Query("resource_id").
|
||||
Equals("resource_type", api.SNAPSHOT_POLICY_TYPE_SERVER).
|
||||
@@ -2008,7 +2016,7 @@ func (manager *SGuestManager) validateCreateData(
|
||||
|
||||
hasGpuVga := func() bool {
|
||||
for i := 0; i < len(input.IsolatedDevices); i++ {
|
||||
if input.IsolatedDevices[i].DevType == api.GPU_VGA_TYPE {
|
||||
if input.IsolatedDevices[i].GpuType == api.GPU_VGA {
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -2314,9 +2322,9 @@ func (manager *SGuestManager) validateCreateData(
|
||||
nvidiaVgpuCnt := 0
|
||||
gpuCnt := 0
|
||||
for i := 0; i < len(input.IsolatedDevices); i++ {
|
||||
if input.IsolatedDevices[i].DevType == api.LEGACY_VGPU_TYPE {
|
||||
if input.IsolatedDevices[i].SharingMode == api.DEVICE_SHARING_MODE_MDEV {
|
||||
nvidiaVgpuCnt += 1
|
||||
} else if utils.IsInStringArray(input.IsolatedDevices[i].DevType, api.VALID_GPU_TYPES) {
|
||||
} else if input.IsolatedDevices[i].DevType == api.GPU_TYPE {
|
||||
gpuCnt += 1
|
||||
}
|
||||
}
|
||||
@@ -4740,11 +4748,10 @@ func _guestResourceCountQuery(
|
||||
diskBackupSubQuery := backupDiskQuery.SubQuery()
|
||||
// diskBackupSubQuery := diskQuery.IsNotEmpty("backup_storage_id").SubQuery()
|
||||
|
||||
isolated := IsolatedDeviceManager.Query().SubQuery()
|
||||
guestIdevs := GuestIsolatedDeviceManager.Query().SubQuery()
|
||||
|
||||
isoDevQuery := isolated.Query(isolated.Field("guest_id"), sqlchemy.COUNT("device_sum"))
|
||||
isoDevQuery = isoDevQuery.Filter(sqlchemy.IsNotNull(isolated.Field("guest_id")))
|
||||
isoDevQuery = isoDevQuery.GroupBy(isolated.Field("guest_id"))
|
||||
isoDevQuery := guestIdevs.Query(guestIdevs.Field("guest_id"), sqlchemy.COUNT("device_sum"))
|
||||
isoDevQuery = isoDevQuery.GroupBy(guestIdevs.Field("guest_id"))
|
||||
|
||||
isoDevSubQuery := isoDevQuery.SubQuery()
|
||||
|
||||
@@ -4896,10 +4903,11 @@ func (self *SGuest) allocSriovNicDevice(
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "self.createIsolatedDeviceOnHost")
|
||||
}
|
||||
dev, err := self.GetIsolatedDeviceByNetworkIndex(gn.Index)
|
||||
gdev, err := self.GetGuestIsolatedDeviceByNetworkIndex(gn.Index)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "self.GetIsolatedDeviceByNetworkIndex")
|
||||
}
|
||||
dev := gdev.GetIsolatedDevice()
|
||||
if dev.OvsOffloadInterface != "" {
|
||||
_, err = db.Update(gn, func() error {
|
||||
gn.Ifname = dev.OvsOffloadInterface
|
||||
@@ -4976,9 +4984,9 @@ func (self *SGuest) attach2NamedNetworkDesc(ctx context.Context, userCred mcclie
|
||||
dev, _ := idev.(*SIsolatedDevice)
|
||||
sriovWires = []string{dev.WireId}
|
||||
} else {
|
||||
wires, err := IsolatedDeviceManager.FindUnusedNicWiresByModel(netConfig.SriovDevice.Model)
|
||||
wires, err := IsolatedDeviceManager.FindAvailableNicWiresByModel(netConfig.SriovDevice.Model)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "FindUnusedNicWiresByModel")
|
||||
return nil, errors.Wrap(err, "FindAvailableNicWiresByModel")
|
||||
}
|
||||
sriovWires = wires
|
||||
}
|
||||
@@ -5718,7 +5726,9 @@ func (self *SGuest) getExtraOptions(ctx context.Context) jsonutils.JSONObject {
|
||||
}
|
||||
|
||||
func (self *SGuest) GetIsolatedDevices() ([]SIsolatedDevice, error) {
|
||||
q := IsolatedDeviceManager.Query().Equals("guest_id", self.Id)
|
||||
gq := GuestIsolatedDeviceManager.Query().Equals("guest_id", self.Id).SubQuery()
|
||||
q := IsolatedDeviceManager.Query()
|
||||
q = q.Join(gq, sqlchemy.Equals(q.Field("id"), gq.Field("isolated_device_id")))
|
||||
devs := []SIsolatedDevice{}
|
||||
err := db.FetchModelObjects(IsolatedDeviceManager, q, &devs)
|
||||
if err != nil {
|
||||
@@ -5727,9 +5737,10 @@ func (self *SGuest) GetIsolatedDevices() ([]SIsolatedDevice, error) {
|
||||
return devs, nil
|
||||
}
|
||||
|
||||
func (self *SGuest) GetIsolatedDeviceByNetworkIndex(index int) (*SIsolatedDevice, error) {
|
||||
dev := SIsolatedDevice{}
|
||||
q := IsolatedDeviceManager.Query().Equals("guest_id", self.Id).Equals("network_index", index)
|
||||
func (self *SGuest) GetGuestIsolatedDeviceByNetworkIndex(index int) (*SGuestIsolatedDevice, error) {
|
||||
dev := SGuestIsolatedDevice{}
|
||||
q := GuestIsolatedDeviceManager.Query().Equals("network_index", index).Equals("guest_id", self.Id)
|
||||
|
||||
if cnt, err := q.CountWithError(); err != nil {
|
||||
return nil, err
|
||||
} else if cnt == 0 {
|
||||
@@ -5739,13 +5750,17 @@ func (self *SGuest) GetIsolatedDeviceByNetworkIndex(index int) (*SIsolatedDevice
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dev.SetModelManager(IsolatedDeviceManager, &dev)
|
||||
dev.SetModelManager(GuestIsolatedDeviceManager, &dev)
|
||||
return &dev, nil
|
||||
}
|
||||
|
||||
func (self *SGuest) GetIsolatedDeviceByDiskIndex(index int8) (*SIsolatedDevice, error) {
|
||||
dev := SIsolatedDevice{}
|
||||
q := IsolatedDeviceManager.Query().Equals("guest_id", self.Id).Equals("disk_index", index)
|
||||
q := IsolatedDeviceManager.Query()
|
||||
gidq := GuestIsolatedDeviceManager.Query().
|
||||
Equals("guest_id", self.Id).Equals("disk_index", index).SubQuery()
|
||||
q = q.Join(gidq, sqlchemy.Equals(q.Field("id"), gidq.Field("isolated_device_id")))
|
||||
|
||||
if cnt, err := q.CountWithError(); err != nil {
|
||||
return nil, err
|
||||
} else if cnt == 0 {
|
||||
@@ -5803,8 +5818,7 @@ func (self *SGuest) GetJsonDescAtHypervisor(ctx context.Context, host *SHost) *a
|
||||
desc.IsVolatileHost = true
|
||||
}
|
||||
|
||||
// isolated devices
|
||||
isolatedDevs, _ := self.GetIsolatedDevices()
|
||||
isolatedDevs, _ := self.GetGuestIsolatedDevices()
|
||||
for _, dev := range isolatedDevs {
|
||||
desc.IsolatedDevices = append(desc.IsolatedDevices, dev.getDesc())
|
||||
}
|
||||
@@ -6064,10 +6078,11 @@ func (self *SGuest) GetSpec(checkStatus bool) *jsonutils.JSONDict {
|
||||
spec.Set("nic", nicSpecs)
|
||||
|
||||
// get isolate device spec
|
||||
guestgpus, _ := self.GetIsolatedDevices()
|
||||
guestgpus, _ := self.GetGuestIsolatedDevices()
|
||||
gpuSpecs := []GpuSpec{}
|
||||
for _, guestgpu := range guestgpus {
|
||||
if strings.HasPrefix(guestgpu.DevType, "GPU") {
|
||||
for i := range guestgpus {
|
||||
guestgpu := guestgpus[i].GetIsolatedDevice()
|
||||
if guestgpu.DevType == api.GPU_TYPE {
|
||||
gs := guestgpu.GetGpuSpec()
|
||||
gpuSpecs = append(gpuSpecs, *gs)
|
||||
}
|
||||
@@ -7197,16 +7212,17 @@ func (self *SGuest) ToNetworksConfig() []*api.NetworkConfig {
|
||||
}
|
||||
|
||||
func (self *SGuest) ToIsolatedDevicesConfig() []*api.IsolatedDeviceConfig {
|
||||
guestIsolatedDevices, _ := self.GetIsolatedDevices()
|
||||
guestIsolatedDevices, _ := self.GetGuestIsolatedDevices()
|
||||
if len(guestIsolatedDevices) == 0 {
|
||||
return nil
|
||||
}
|
||||
ret := make([]*api.IsolatedDeviceConfig, len(guestIsolatedDevices))
|
||||
for idx, guestIsolatedDevice := range guestIsolatedDevices {
|
||||
for idx := range guestIsolatedDevices {
|
||||
dev := guestIsolatedDevices[idx].GetIsolatedDevice()
|
||||
devConf := new(api.IsolatedDeviceConfig)
|
||||
devConf.Model = guestIsolatedDevice.Model
|
||||
devConf.Vendor = guestIsolatedDevice.getVendor()
|
||||
devConf.DevType = guestIsolatedDevice.DevType
|
||||
devConf.Model = dev.Model
|
||||
devConf.Vendor = dev.getVendor()
|
||||
devConf.DevType = dev.DevType
|
||||
ret[idx] = devConf
|
||||
}
|
||||
return ret
|
||||
|
||||
@@ -3526,13 +3526,13 @@ func (manager *SHostManager) totalCountQ(
|
||||
|
||||
q = db.ObjectIdQueryWithPolicyResult(ctx, q, HostManager, policyResult)
|
||||
|
||||
isolatedDevices := IsolatedDeviceManager.Query().SubQuery()
|
||||
isolatedDevices := IsolatedDeviceManager.queryWithoutGuest(IsolatedDeviceManager.Query()).SubQuery()
|
||||
iq := isolatedDevices.Query(
|
||||
isolatedDevices.Field("host_id"),
|
||||
sqlchemy.SUM("isolated_reserved_memory", isolatedDevices.Field("reserved_memory")),
|
||||
sqlchemy.SUM("isolated_reserved_cpu", isolatedDevices.Field("reserved_cpu")),
|
||||
sqlchemy.SUM("isolated_reserved_storage", isolatedDevices.Field("reserved_storage")),
|
||||
).IsNullOrEmpty("guest_id").GroupBy(isolatedDevices.Field("host_id")).SubQuery()
|
||||
).GroupBy(isolatedDevices.Field("host_id")).SubQuery()
|
||||
q = q.LeftJoin(iq, sqlchemy.Equals(q.Field("id"), iq.Field("host_id")))
|
||||
q.AppendField(
|
||||
iq.Field("isolated_reserved_memory"),
|
||||
@@ -4110,7 +4110,25 @@ func (hh *SHost) GetDevsReservedResource(devs []SIsolatedDevice) *api.IsolatedDe
|
||||
ReservedCpu: &reservedCpu,
|
||||
}
|
||||
for _, dev := range devs {
|
||||
if !utils.IsInStringArray(dev.DevType, api.VALID_GPU_TYPES) {
|
||||
if !dev.IsKvmExclusiveGPU() {
|
||||
continue
|
||||
}
|
||||
reservedCpu += dev.ReservedCpu
|
||||
reservedMem += dev.ReservedMemory
|
||||
reservedStorage += dev.ReservedStorage
|
||||
}
|
||||
return &reservedResourceForGpu
|
||||
}
|
||||
|
||||
func (hh *SHost) GetDevsReservedResourceByDevStats(devs []IsolatedDeviceAllocateStat) *api.IsolatedDeviceReservedResourceInput {
|
||||
reservedCpu, reservedMem, reservedStorage := 0, 0, 0
|
||||
reservedResourceForGpu := api.IsolatedDeviceReservedResourceInput{
|
||||
ReservedStorage: &reservedStorage,
|
||||
ReservedMemory: &reservedMem,
|
||||
ReservedCpu: &reservedCpu,
|
||||
}
|
||||
for _, dev := range devs {
|
||||
if !dev.IsKvmExclusiveGPU() {
|
||||
continue
|
||||
}
|
||||
reservedCpu += dev.ReservedCpu
|
||||
@@ -4422,6 +4440,19 @@ func (hh *SHost) GetDetailsIpmi(ctx context.Context, userCred mcclient.TokenCred
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (hh *SHost) GetDetailsGuestIsolatedDevicesInitialized(ctx context.Context, userCred mcclient.TokenCredential, query jsonutils.JSONObject) (jsonutils.JSONObject, error) {
|
||||
inited, err := IsolatedDeviceManager.isInitializeDataDone()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !inited {
|
||||
return nil, httperrors.NewResourceNotReadyError("isolated device not isitialized")
|
||||
}
|
||||
ret := jsonutils.NewDict()
|
||||
ret.Set("initialized", jsonutils.NewString("ok"))
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (manager *SHostManager) GetHostsByManagerAndRegion(managerId string, regionId string) []SHost {
|
||||
zones := ZoneManager.Query().Equals("cloudregion_id", regionId).SubQuery()
|
||||
hosts := HostManager.Query()
|
||||
@@ -8202,10 +8233,10 @@ func (h *SHost) GetDetailsApiStats(ctx context.Context, userCred mcclient.TokenC
|
||||
}
|
||||
|
||||
func (hh *SHost) GetDetailsIsolatedDeviceNumaStats(ctx context.Context, userCred mcclient.TokenCredential, input *api.HostIsolatedDeviceNumaStatsInput) (jsonutils.JSONObject, error) {
|
||||
if !utils.IsInStringArray(input.DevType, api.VALID_PASSTHROUGH_TYPES) {
|
||||
return nil, httperrors.NewInputParameterError("dev_type %s is invalid", input.DevType)
|
||||
if input.Model == "" {
|
||||
return nil, httperrors.NewMissingParameterError("model")
|
||||
}
|
||||
stats, err := IsolatedDeviceManager.GetHostAllocatedIsolatedDeviceNumaStats(input.DevType, hh.Id)
|
||||
stats, err := IsolatedDeviceManager.GetHostAllocatedIsolatedDeviceNumaStats(input.Model, hh.Id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -51,6 +51,8 @@ func InitDB() error {
|
||||
GuestManager,
|
||||
GuestnetworkManager,
|
||||
HostManager,
|
||||
GuestIsolatedDeviceManager,
|
||||
IsolatedDeviceManager,
|
||||
HostDmesgLogManager,
|
||||
LoadbalancerCertificateManager,
|
||||
LoadbalancerAclManager,
|
||||
|
||||
@@ -24,7 +24,6 @@ import (
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/tristate"
|
||||
"yunion.io/x/pkg/utils"
|
||||
"yunion.io/x/sqlchemy"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
@@ -77,10 +76,6 @@ func (manager *SIsolatedDeviceModelManager) ValidateCreateData(ctx context.Conte
|
||||
query jsonutils.JSONObject,
|
||||
input api.IsolatedDeviceModelCreateInput,
|
||||
) (api.IsolatedDeviceModelCreateInput, error) {
|
||||
if utils.IsInStringArray(input.DevType, api.VALID_PASSTHROUGH_TYPES) {
|
||||
return input, httperrors.NewInputParameterError("device type %q is not supported", input.DevType)
|
||||
}
|
||||
|
||||
input.VendorId = strings.ToLower(input.VendorId)
|
||||
input.DeviceId = strings.ToLower(input.DeviceId)
|
||||
deviceVendorReg := regexp.MustCompile(`^[a-f0-9]{4}$`)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
198
pkg/compute/models/isolateddeviceresouce.go
Normal file
198
pkg/compute/models/isolateddeviceresouce.go
Normal file
@@ -0,0 +1,198 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package models
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/util/reflectutils"
|
||||
"yunion.io/x/sqlchemy"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db"
|
||||
"yunion.io/x/onecloud/pkg/httperrors"
|
||||
"yunion.io/x/onecloud/pkg/mcclient"
|
||||
"yunion.io/x/onecloud/pkg/util/stringutils2"
|
||||
)
|
||||
|
||||
type SIsolatedDeviceResourceBase struct {
|
||||
IsolatedDeviceId string `width:"36" charset:"ascii" nullable:"false" list:"user" create:"required"`
|
||||
}
|
||||
|
||||
type SIsolatedDeviceResourceBaseManager struct {
|
||||
}
|
||||
|
||||
func (manager *SIsolatedDeviceResourceBaseManager) FetchCustomizeColumns(
|
||||
ctx context.Context,
|
||||
userCred mcclient.TokenCredential,
|
||||
query jsonutils.JSONObject,
|
||||
objs []interface{},
|
||||
fields stringutils2.SSortedStrings,
|
||||
isList bool,
|
||||
) []api.IsolateDeviceDetails {
|
||||
rows := make([]api.IsolateDeviceDetails, len(objs))
|
||||
devIds := make([]string, len(objs))
|
||||
for i := range objs {
|
||||
var base *SIsolatedDeviceResourceBase
|
||||
err := reflectutils.FindAnonymouStructPointer(objs[i], &base)
|
||||
if err != nil {
|
||||
log.Errorf("Cannot find SIsolatedDeviceResourceBase in object %s", objs[i])
|
||||
continue
|
||||
}
|
||||
devIds[i] = base.IsolatedDeviceId
|
||||
}
|
||||
|
||||
devMap := make(map[string]SIsolatedDevice)
|
||||
err := db.FetchStandaloneObjectsByIds(IsolatedDeviceManager, devIds, devMap)
|
||||
if err != nil {
|
||||
log.Errorf("FetchStandaloneObjectsByIds fail %s", err)
|
||||
return rows
|
||||
}
|
||||
|
||||
devObjs := make([]interface{}, len(objs))
|
||||
devs := make([]SIsolatedDevice, len(objs))
|
||||
for i := range rows {
|
||||
if dev, ok := devMap[devIds[i]]; ok {
|
||||
devs[i] = dev
|
||||
if err := jsonutils.Marshal(dev).Unmarshal(&rows[i].SIsolatedDevice); err != nil {
|
||||
log.Errorf("unmarshal isolated device %s details failed %s", dev.Id, err)
|
||||
}
|
||||
}
|
||||
devObjs[i] = &devs[i]
|
||||
}
|
||||
|
||||
devRows := IsolatedDeviceManager.FetchCustomizeColumns(ctx, userCred, query, devObjs, fields, isList)
|
||||
for i := range rows {
|
||||
rows[i].StandaloneResourceDetails = devRows[i].StandaloneResourceDetails
|
||||
rows[i].SharableResourceBaseInfo = devRows[i].SharableResourceBaseInfo
|
||||
rows[i].HostResourceInfo = devRows[i].HostResourceInfo
|
||||
rows[i].Guest = devRows[i].Guest
|
||||
rows[i].GuestStatus = devRows[i].GuestStatus
|
||||
}
|
||||
return rows
|
||||
}
|
||||
|
||||
func (manager *SIsolatedDeviceResourceBaseManager) ListItemFilter(
|
||||
ctx context.Context,
|
||||
q *sqlchemy.SQuery,
|
||||
userCred mcclient.TokenCredential,
|
||||
query api.GuestIsolatedDeviceListInput,
|
||||
) (*sqlchemy.SQuery, error) {
|
||||
devQ := IsolatedDeviceManager.Query("id")
|
||||
devQ, err := IsolatedDeviceManager.ListItemFilter(ctx, devQ, userCred, query.IsolatedDeviceListInput)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "IsolatedDeviceManager.ListItemFilter")
|
||||
}
|
||||
q = q.Filter(sqlchemy.In(q.Field("isolated_device_id"), devQ.SubQuery()))
|
||||
return q, nil
|
||||
}
|
||||
|
||||
func (manager *SIsolatedDeviceResourceBaseManager) QueryDistinctExtraField(q *sqlchemy.SQuery, field string) (*sqlchemy.SQuery, error) {
|
||||
switch field {
|
||||
case "isolated_device":
|
||||
devQ := IsolatedDeviceManager.Query("name", "id").SubQuery()
|
||||
q = q.AppendField(devQ.Field("name", field)).Distinct()
|
||||
q = q.Join(devQ, sqlchemy.Equals(q.Field("isolated_device_id"), devQ.Field("id")))
|
||||
return q, nil
|
||||
case "dev_type", "model", "addr", "device_path", "vendor_device_id", "numa_node":
|
||||
devQ := IsolatedDeviceManager.Query(field, "id").SubQuery()
|
||||
q = q.AppendField(devQ.Field(field)).Distinct()
|
||||
q = q.Join(devQ, sqlchemy.Equals(q.Field("isolated_device_id"), devQ.Field("id")))
|
||||
return q, nil
|
||||
default:
|
||||
devQ := IsolatedDeviceManager.Query("id", "host_id").SubQuery()
|
||||
q = q.LeftJoin(devQ, sqlchemy.Equals(q.Field("isolated_device_id"), devQ.Field("id")))
|
||||
q, err := IsolatedDeviceManager.SHostResourceBaseManager.QueryDistinctExtraField(q, field)
|
||||
if err == nil {
|
||||
return q, nil
|
||||
}
|
||||
}
|
||||
return q, httperrors.ErrNotFound
|
||||
}
|
||||
|
||||
func (manager *SIsolatedDeviceResourceBaseManager) OrderByExtraFields(
|
||||
ctx context.Context,
|
||||
q *sqlchemy.SQuery,
|
||||
userCred mcclient.TokenCredential,
|
||||
query api.GuestIsolatedDeviceListInput,
|
||||
) (*sqlchemy.SQuery, error) {
|
||||
if !db.NeedOrderQuery(manager.GetOrderByFields(query)) {
|
||||
return q, nil
|
||||
}
|
||||
orderQ := IsolatedDeviceManager.Query("id")
|
||||
orderSubQ := orderQ.SubQuery()
|
||||
orderQ, orders, fields := manager.GetOrderBySubQuery(orderQ, orderSubQ, orderQ.Field("id"), userCred, query, nil, nil)
|
||||
q = q.LeftJoin(orderSubQ, sqlchemy.Equals(q.Field("isolated_device_id"), orderSubQ.Field("id")))
|
||||
q = db.OrderByFields(q, orders, fields)
|
||||
return q, nil
|
||||
}
|
||||
|
||||
func (manager *SIsolatedDeviceResourceBaseManager) GetOrderBySubQuery(
|
||||
q *sqlchemy.SQuery,
|
||||
subq *sqlchemy.SSubQuery,
|
||||
joinField sqlchemy.IQueryField,
|
||||
userCred mcclient.TokenCredential,
|
||||
query api.GuestIsolatedDeviceListInput,
|
||||
orders []string,
|
||||
fields []sqlchemy.IQueryField,
|
||||
) (*sqlchemy.SQuery, []string, []sqlchemy.IQueryField) {
|
||||
if !db.NeedOrderQuery(manager.GetOrderByFields(query)) {
|
||||
return q, orders, fields
|
||||
}
|
||||
devQ := IsolatedDeviceManager.Query().SubQuery()
|
||||
q = q.LeftJoin(devQ, sqlchemy.Equals(joinField, devQ.Field("id")))
|
||||
q, orders, fields = IsolatedDeviceManager.SHostResourceBaseManager.GetOrderBySubQuery(q, subq, devQ.Field("host_id"), userCred, query.HostFilterListInput, orders, fields)
|
||||
return q, orders, fields
|
||||
}
|
||||
|
||||
func (manager *SIsolatedDeviceResourceBaseManager) GetOrderByFields(query api.GuestIsolatedDeviceListInput) []string {
|
||||
return IsolatedDeviceManager.SHostResourceBaseManager.GetOrderByFields(query.HostFilterListInput)
|
||||
}
|
||||
|
||||
func (manager *SIsolatedDeviceResourceBaseManager) ListItemExportKeys(ctx context.Context,
|
||||
q *sqlchemy.SQuery,
|
||||
userCred mcclient.TokenCredential,
|
||||
keys stringutils2.SSortedStrings,
|
||||
) (*sqlchemy.SQuery, error) {
|
||||
if keys.ContainsAny(manager.GetExportKeys()...) {
|
||||
devQ := IsolatedDeviceManager.Query("id", "name", "dev_type", "model", "addr", "device_path", "vendor_device_id", "numa_node", "host_id").SubQuery()
|
||||
q = q.LeftJoin(devQ, sqlchemy.Equals(q.Field("isolated_device_id"), devQ.Field("id")))
|
||||
if keys.Contains("isolated_device") {
|
||||
q = q.AppendField(devQ.Field("name", "isolated_device"))
|
||||
}
|
||||
for _, key := range []string{"dev_type", "model", "addr", "device_path", "vendor_device_id", "numa_node"} {
|
||||
if keys.Contains(key) {
|
||||
q = q.AppendField(devQ.Field(key))
|
||||
}
|
||||
}
|
||||
if keys.ContainsAny(IsolatedDeviceManager.SHostResourceBaseManager.GetExportKeys()...) {
|
||||
var err error
|
||||
q, err = IsolatedDeviceManager.SHostResourceBaseManager.ListItemExportKeys(ctx, q, userCred, keys)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "SHostResourceBaseManager.ListItemExportKeys")
|
||||
}
|
||||
}
|
||||
}
|
||||
return q, nil
|
||||
}
|
||||
|
||||
func (manager *SIsolatedDeviceResourceBaseManager) GetExportKeys() []string {
|
||||
keys := []string{"isolated_device", "dev_type", "model", "addr", "device_path", "vendor_device_id", "numa_node"}
|
||||
keys = append(keys, IsolatedDeviceManager.SHostResourceBaseManager.GetExportKeys()...)
|
||||
return keys
|
||||
}
|
||||
@@ -288,6 +288,7 @@ func InitHandlers(app *appsrv.Application, isSlave bool) {
|
||||
models.GuestsecgroupManager,
|
||||
models.LoadbalancernetworkManager,
|
||||
models.GuestdiskManager,
|
||||
models.GuestIsolatedDeviceManager,
|
||||
models.GroupnetworkManager,
|
||||
models.GroupguestManager,
|
||||
models.StoragecachedimageManager,
|
||||
|
||||
@@ -140,7 +140,7 @@ func queryHosts(
|
||||
}
|
||||
|
||||
if len(gpuModels) != 0 {
|
||||
devs, err := models.IsolatedDeviceManager.FindUnusedByModels(gpuModels)
|
||||
devs, err := models.IsolatedDeviceManager.FindAvailableByModels(gpuModels)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -154,7 +154,7 @@ func queryHosts(
|
||||
if !sets.NewString(gpuHostIds...).Has(obj.GetId()) {
|
||||
return false
|
||||
}
|
||||
gpus, _ := models.IsolatedDeviceManager.FindUnusedGpusOnHost(obj.GetId())
|
||||
gpus, _ := models.IsolatedDeviceManager.FindAvailableGpusOnHost(obj.GetId())
|
||||
if len(gpus) == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -91,11 +91,12 @@ func (task *GuestMigrateTask) GetSchedParams() (*schedapi.ScheduleInput, error)
|
||||
}
|
||||
res := guest.GetSchedMigrateParams(task.GetUserCred(), input)
|
||||
|
||||
if devs, _ := guest.GetIsolatedDevices(); len(devs) > 0 {
|
||||
if devs, _ := guest.GetGuestIsolatedDevices(); len(devs) > 0 {
|
||||
preferNumaNodesSet := cpuset.NewBuilder()
|
||||
for i := range devs {
|
||||
if devs[i].NumaNode >= 0 {
|
||||
preferNumaNodesSet.Add(int(devs[i].NumaNode))
|
||||
dev := devs[i].GetIsolatedDevice()
|
||||
if dev.NumaNode >= 0 {
|
||||
preferNumaNodesSet.Add(int(dev.NumaNode))
|
||||
}
|
||||
}
|
||||
res.PreferNumaNodes = preferNumaNodesSet.Result().ToSlice()
|
||||
|
||||
@@ -53,18 +53,32 @@ func (self *GuestStartTask) attachReleasedDevices(ctx context.Context, guest *mo
|
||||
if len(devs) == 0 {
|
||||
return self.ScheduleRun(nil)
|
||||
}
|
||||
attachReq := make(map[string]int)
|
||||
|
||||
type DevRequest struct {
|
||||
Model string
|
||||
GpuType string
|
||||
SharingMode string
|
||||
MemoryRequest int
|
||||
}
|
||||
|
||||
devGroup := map[DevRequest]int{}
|
||||
for _, dev := range devs {
|
||||
count, ok := attachReq[dev.Model]
|
||||
devReq := DevRequest{dev.Model, dev.GpuType, dev.SharingMode, dev.MemoryRequest}
|
||||
|
||||
cnt, ok := devGroup[devReq]
|
||||
if !ok {
|
||||
attachReq[dev.Model] = 1
|
||||
devGroup[devReq] = 1
|
||||
} else {
|
||||
attachReq[dev.Model] = count + 1
|
||||
devGroup[devReq] = cnt + 1
|
||||
}
|
||||
}
|
||||
if err := guest.AttachIsolatedDevices(ctx, self.GetUserCred(), attachReq); err != nil {
|
||||
return errors.Wrap(err, "attach isolated devices")
|
||||
for devReq, cnt := range devGroup {
|
||||
attachReq := map[string]int{devReq.Model: cnt}
|
||||
if err := guest.AttachIsolatedDevices(ctx, self.GetUserCred(), attachReq, devReq.GpuType, devReq.SharingMode, &devReq.MemoryRequest); err != nil {
|
||||
return errors.Wrap(err, "attach isolated devices")
|
||||
}
|
||||
}
|
||||
|
||||
return guest.StartIsolatedDevicesSyncTask(ctx, self.GetUserCred(), false, self.GetTaskId())
|
||||
}
|
||||
|
||||
|
||||
@@ -93,25 +93,18 @@ func (self *GuestStopTask) releaseDevices(ctx context.Context, guest *models.SGu
|
||||
if guest.ShutdownBehavior != api.SHUTDOWN_STOP_RELEASE_GPU {
|
||||
return self.ScheduleRun(nil)
|
||||
}
|
||||
devs, err := guest.GetIsolatedDevices()
|
||||
devs, err := guest.GetGuestGpuIsolatedDevices()
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "GetIsolatedDevices of guest %s", guest.GetId())
|
||||
}
|
||||
gpus := make([]models.SIsolatedDevice, 0)
|
||||
for _, dev := range devs {
|
||||
if dev.IsGPU() {
|
||||
tmpDev := dev
|
||||
gpus = append(gpus, tmpDev)
|
||||
}
|
||||
}
|
||||
if len(gpus) == 0 {
|
||||
if len(devs) == 0 {
|
||||
return self.ScheduleRun(nil)
|
||||
}
|
||||
if err := guest.SetReleasedIsolatedDevices(ctx, self.GetUserCred(), gpus); err != nil {
|
||||
if err := guest.SetReleasedIsolatedDevices(ctx, self.GetUserCred(), devs); err != nil {
|
||||
return errors.Wrapf(err, "SetReleasedIsolatedDevices of guest %s", guest.GetId())
|
||||
}
|
||||
|
||||
if err := guest.DetachIsolatedDevices(ctx, self.GetUserCred(), gpus); err != nil {
|
||||
if err := guest.DetachIsolatedDevices(ctx, self.GetUserCred(), devs); err != nil {
|
||||
return errors.Wrapf(err, "DetachIsolatedDevices of guest %s", guest.GetId())
|
||||
}
|
||||
return guest.StartIsolatedDevicesSyncTask(ctx, self.GetUserCred(), false, self.GetTaskId())
|
||||
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
|
||||
"yunion.io/x/onecloud/pkg/apis"
|
||||
hostapi "yunion.io/x/onecloud/pkg/apis/host"
|
||||
"yunion.io/x/onecloud/pkg/hostman/hostinfo"
|
||||
"yunion.io/x/onecloud/pkg/hostman/isolated_device"
|
||||
)
|
||||
|
||||
@@ -42,28 +43,29 @@ func (i isolatedDevice) GetRuntimeDevices(input *hostapi.ContainerCreateInput, d
|
||||
if len(devs) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
devsMap := map[string][]*hostapi.ContainerDevice{}
|
||||
devsMap := map[isolated_device.IContainerDeviceManager][]*hostapi.ContainerDevice{}
|
||||
for _, dev := range devs {
|
||||
if mapDevs, ok := devsMap[dev.IsolatedDevice.DeviceType]; ok {
|
||||
devsMap[dev.IsolatedDevice.DeviceType] = append(mapDevs, dev)
|
||||
iDev := hostinfo.Instance().IsolatedDeviceMan.GetDeviceByCloudId(dev.IsolatedDevice.Id)
|
||||
if iDev == nil {
|
||||
return nil, errors.Wrapf(errors.ErrNotFound, "device %s not exist", dev.IsolatedDevice.Id)
|
||||
}
|
||||
devMan := iDev.GetContainerDeviceManager()
|
||||
|
||||
if mapDevs, ok := devsMap[devMan]; ok {
|
||||
devsMap[devMan] = append(mapDevs, dev)
|
||||
} else {
|
||||
devsMap[dev.IsolatedDevice.DeviceType] = []*hostapi.ContainerDevice{dev}
|
||||
devsMap[devMan] = []*hostapi.ContainerDevice{dev}
|
||||
}
|
||||
}
|
||||
|
||||
ret := make([]*runtimeapi.Device, 0)
|
||||
for devType, mappedDevs := range devsMap {
|
||||
man, err := isolated_device.GetContainerDeviceManager(isolated_device.ContainerDeviceType(devType))
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "GetContainerDeviceManager by type %q", devType)
|
||||
}
|
||||
|
||||
for devMan, mappedDevs := range devsMap {
|
||||
for idx := range mappedDevs {
|
||||
mDev := mappedDevs[idx]
|
||||
if mDev.IsolatedDevice != nil && mDev.IsolatedDevice.OnlyEnv != nil {
|
||||
continue
|
||||
}
|
||||
ctrDevs, commonDevs, err := man.NewContainerDevices(input, mappedDevs[idx])
|
||||
ctrDevs, commonDevs, err := devMan.NewContainerDevices(input, mappedDevs[idx])
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "NewContainerDevices with %#v", devs)
|
||||
}
|
||||
|
||||
@@ -1043,7 +1043,7 @@ func (t *SGuestIsolatedDeviceSyncTask) addDevice(dev *desc.SGuestIsolatedDevice)
|
||||
id := devObj.GetQemuId()
|
||||
dev.VfioDevs = make([]*desc.VFIODevice, 0)
|
||||
vfioDev := desc.NewVfioDevice(
|
||||
*cType, "vfio-pci", id, devObj.GetAddr(), dev.DevType == api.GPU_VGA_TYPE,
|
||||
*cType, "vfio-pci", id, devObj.GetAddr(), dev.GpuType == api.GPU_VGA,
|
||||
)
|
||||
dev.VfioDevs = append(dev.VfioDevs, vfioDev)
|
||||
|
||||
|
||||
@@ -22,11 +22,11 @@ import (
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/hostman/guestman/desc"
|
||||
"yunion.io/x/onecloud/pkg/hostman/guestman/qemu"
|
||||
"yunion.io/x/onecloud/pkg/hostman/monitor"
|
||||
"yunion.io/x/onecloud/pkg/hostman/options"
|
||||
"yunion.io/x/onecloud/pkg/scheduler/api"
|
||||
"yunion.io/x/onecloud/pkg/util/fileutils2"
|
||||
)
|
||||
|
||||
@@ -345,14 +345,14 @@ func (s *SKVMGuestInstance) initIsolatedDevices(pciRoot, pciBridge *desc.PCICont
|
||||
manager := s.manager.GetHost().GetIsolatedDeviceManager()
|
||||
for i := 0; i < len(s.Desc.IsolatedDevices); i++ {
|
||||
dev := manager.GetDeviceByAddr(s.Desc.IsolatedDevices[i].Addr)
|
||||
if s.Desc.IsolatedDevices[i].DevType == api.USB_TYPE {
|
||||
if s.Desc.IsolatedDevices[i].DevType == compute.USB_TYPE {
|
||||
s.Desc.IsolatedDevices[i].Usb = desc.NewUsbDevice("usb-host", dev.GetQemuId())
|
||||
s.Desc.IsolatedDevices[i].Usb.Options = dev.GetPassthroughOptions()
|
||||
} else {
|
||||
id := dev.GetQemuId()
|
||||
s.Desc.IsolatedDevices[i].VfioDevs = make([]*desc.VFIODevice, 0)
|
||||
vfioDev := desc.NewVfioDevice(
|
||||
*cType, "vfio-pci", id, dev.GetAddr(), s.Desc.IsolatedDevices[i].DevType == api.GPU_VGA_TYPE,
|
||||
*cType, "vfio-pci", id, dev.GetAddr(), s.Desc.IsolatedDevices[i].GpuType == compute.GPU_VGA,
|
||||
)
|
||||
s.Desc.IsolatedDevices[i].VfioDevs = append(s.Desc.IsolatedDevices[i].VfioDevs, vfioDev)
|
||||
|
||||
|
||||
@@ -37,7 +37,6 @@ import (
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/util/sets"
|
||||
"yunion.io/x/pkg/utils"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/apis"
|
||||
computeapi "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
@@ -838,7 +837,8 @@ func (s *sPodGuestInstance) GetPodContainerCriIds() []string {
|
||||
|
||||
func (s *sPodGuestInstance) HasContainerNvidiaGpu() bool {
|
||||
for i := range s.Desc.IsolatedDevices {
|
||||
if utils.IsInStringArray(s.Desc.IsolatedDevices[i].DevType, computeapi.NVIDIA_GPU_TYPES) {
|
||||
vendor := strings.Split(s.Desc.IsolatedDevices[i].VendorDeviceId, ":")[0]
|
||||
if vendor == computeapi.NVIDIA_VENDOR_ID {
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -2340,39 +2340,6 @@ func (s *sPodGuestInstance) getEtcFilesMount(ctrId string) ([]*runtimeapi.Mount,
|
||||
return []*runtimeapi.Mount{etcHostsMount, etcHostnameMount, etcResolvConfMount}, nil
|
||||
}
|
||||
|
||||
type FilteredContainerDevices struct {
|
||||
EnvDevs []*hostapi.ContainerDevice
|
||||
CDIDevs []*hostapi.ContainerDevice
|
||||
RestDevs []*hostapi.ContainerDevice
|
||||
}
|
||||
|
||||
func filterContainerIsolatedDevices(devs []*hostapi.ContainerDevice, devTypes sets.String) FilteredContainerDevices {
|
||||
envDevs := []*hostapi.ContainerDevice{}
|
||||
restDevs := []*hostapi.ContainerDevice{}
|
||||
cdiDevs := []*hostapi.ContainerDevice{}
|
||||
for i := range devs {
|
||||
dev := devs[i]
|
||||
if dev.IsolatedDevice != nil {
|
||||
devType := dev.IsolatedDevice.DeviceType
|
||||
if !devTypes.Has(devType) {
|
||||
continue
|
||||
}
|
||||
if dev.IsolatedDevice.IsCDIUsed() {
|
||||
cdiDevs = append(cdiDevs, dev)
|
||||
} else if len(dev.IsolatedDevice.OnlyEnv) > 0 {
|
||||
envDevs = append(envDevs, dev)
|
||||
} else {
|
||||
restDevs = append(restDevs, dev)
|
||||
}
|
||||
}
|
||||
}
|
||||
return FilteredContainerDevices{
|
||||
EnvDevs: envDevs,
|
||||
CDIDevs: cdiDevs,
|
||||
RestDevs: restDevs,
|
||||
}
|
||||
}
|
||||
|
||||
func getEnvsFromDevices(devs []*hostapi.ContainerDevice) []*runtimeapi.KeyValue {
|
||||
retEnvs := []*runtimeapi.KeyValue{}
|
||||
for _, dev := range devs {
|
||||
@@ -2411,32 +2378,48 @@ func getEnvsFromDevices(devs []*hostapi.ContainerDevice) []*runtimeapi.KeyValue
|
||||
}
|
||||
|
||||
func (s *sPodGuestInstance) getIsolatedDeviceExtraConfig(spec *hostapi.ContainerSpec, ctrCfg *runtimeapi.ContainerConfig) error {
|
||||
devTypes := sets.NewString(
|
||||
string(isolated_device.ContainerDeviceTypeNvidiaGpu),
|
||||
string(isolated_device.ContainerDeviceTypeNvidiaMps),
|
||||
string(isolated_device.ContainerDeviceTypeNvidiaGpuShare),
|
||||
string(isolated_device.ContainerDeviceTypeAscendNpu),
|
||||
)
|
||||
fDevs := filterContainerIsolatedDevices(spec.Devices, devTypes)
|
||||
if len(fDevs.EnvDevs) != 0 {
|
||||
ctrCfg.Envs = append(ctrCfg.Envs, getEnvsFromDevices(fDevs.EnvDevs)...)
|
||||
}
|
||||
restDevsByType := map[string][]*hostapi.ContainerDevice{}
|
||||
restDevTypeOrder := []string{}
|
||||
for i := range fDevs.RestDevs {
|
||||
dev := fDevs.RestDevs[i]
|
||||
envDevs := []*hostapi.ContainerDevice{}
|
||||
restDevs := []*hostapi.ContainerDevice{}
|
||||
cdiDevs := []*hostapi.ContainerDevice{}
|
||||
for i := range spec.Devices {
|
||||
dev := spec.Devices[i]
|
||||
if dev.IsolatedDevice == nil {
|
||||
continue
|
||||
}
|
||||
devType := dev.IsolatedDevice.DeviceType
|
||||
if _, ok := restDevsByType[devType]; !ok {
|
||||
restDevTypeOrder = append(restDevTypeOrder, devType)
|
||||
if devType != computeapi.GPU_TYPE && devType != computeapi.NPU_TYPE {
|
||||
continue
|
||||
}
|
||||
if dev.IsolatedDevice.IsCDIUsed() {
|
||||
cdiDevs = append(cdiDevs, dev)
|
||||
} else if len(dev.IsolatedDevice.OnlyEnv) > 0 {
|
||||
envDevs = append(envDevs, dev)
|
||||
} else {
|
||||
restDevs = append(restDevs, dev)
|
||||
}
|
||||
restDevsByType[devType] = append(restDevsByType[devType], dev)
|
||||
}
|
||||
for _, devType := range restDevTypeOrder {
|
||||
devs := restDevsByType[devType]
|
||||
devMan, err := isolated_device.GetContainerDeviceManager(isolated_device.ContainerDeviceType(devType))
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "GetContainerDeviceManager by type %q", devType)
|
||||
|
||||
if len(envDevs) != 0 {
|
||||
ctrCfg.Envs = append(ctrCfg.Envs, getEnvsFromDevices(envDevs)...)
|
||||
}
|
||||
restDevsByType := map[isolated_device.IContainerDeviceManager][]*hostapi.ContainerDevice{}
|
||||
restDevTypeOrder := []isolated_device.IContainerDeviceManager{}
|
||||
for i := range restDevs {
|
||||
dev := restDevs[i]
|
||||
|
||||
iDev := hostinfo.Instance().IsolatedDeviceMan.GetDeviceByCloudId(dev.IsolatedDevice.Id)
|
||||
if iDev == nil {
|
||||
return errors.Wrapf(errors.ErrNotFound, "device %s not exist", dev.IsolatedDevice.Id)
|
||||
}
|
||||
devMan := iDev.GetContainerDeviceManager()
|
||||
|
||||
if _, ok := restDevsByType[devMan]; !ok {
|
||||
restDevTypeOrder = append(restDevTypeOrder, devMan)
|
||||
}
|
||||
restDevsByType[devMan] = append(restDevsByType[devMan], dev)
|
||||
}
|
||||
for _, devMan := range restDevTypeOrder {
|
||||
devs := restDevsByType[devMan]
|
||||
envs, mounts := devMan.GetContainerExtraConfigures(devs)
|
||||
if len(envs) > 0 {
|
||||
ctrCfg.Envs = append(ctrCfg.Envs, envs...)
|
||||
@@ -2446,8 +2429,8 @@ func (s *sPodGuestInstance) getIsolatedDeviceExtraConfig(spec *hostapi.Container
|
||||
}
|
||||
}
|
||||
|
||||
if len(fDevs.CDIDevs) > 0 {
|
||||
cdiDevs, err := isolated_device.GetContainerCDIDevices(fDevs.CDIDevs)
|
||||
if len(cdiDevs) > 0 {
|
||||
cdiDevs, err := isolated_device.GetContainerCDIDevices(cdiDevs)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "GetContainerCDIDevices")
|
||||
}
|
||||
|
||||
@@ -1161,10 +1161,8 @@ func (s *SKVMGuestInstance) startMemCleaner() error {
|
||||
}
|
||||
|
||||
func (s *SKVMGuestInstance) gpusHasVga() bool {
|
||||
manager := s.manager.GetHost().GetIsolatedDeviceManager()
|
||||
for i := 0; i < len(s.Desc.IsolatedDevices); i++ {
|
||||
dev := manager.GetDeviceByAddr(s.Desc.IsolatedDevices[i].Addr)
|
||||
if dev.GetDeviceType() == api.GPU_VGA_TYPE {
|
||||
if s.Desc.IsolatedDevices[i].GpuType == api.GPU_VGA {
|
||||
return true
|
||||
}
|
||||
}
|
||||
@@ -1175,7 +1173,7 @@ func (s *SKVMGuestInstance) hasGPU() bool {
|
||||
manager := s.manager.GetHost().GetIsolatedDeviceManager()
|
||||
for i := 0; i < len(s.Desc.IsolatedDevices); i++ {
|
||||
dev := manager.GetDeviceByAddr(s.Desc.IsolatedDevices[i].Addr)
|
||||
if dev.GetDeviceType() == api.GPU_VGA_TYPE || dev.GetDeviceType() == api.GPU_HPC_TYPE {
|
||||
if dev.GetDeviceType() == api.GPU_TYPE {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@ import (
|
||||
"yunion.io/x/onecloud/pkg/hostman/hostinfo/hostpinger"
|
||||
"yunion.io/x/onecloud/pkg/hostman/hostmetrics"
|
||||
"yunion.io/x/onecloud/pkg/hostman/hostutils"
|
||||
_ "yunion.io/x/onecloud/pkg/hostman/isolated_device/container_device"
|
||||
"yunion.io/x/onecloud/pkg/hostman/options"
|
||||
"yunion.io/x/onecloud/pkg/hostman/storageman"
|
||||
"yunion.io/x/onecloud/pkg/hostman/storageman/diskhandlers"
|
||||
|
||||
@@ -17,6 +17,7 @@ package hostinfo
|
||||
import (
|
||||
"context"
|
||||
"path"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"yunion.io/x/log"
|
||||
@@ -106,7 +107,8 @@ func (h *SHostInfo) HasContainerVastaitechGpu() bool {
|
||||
hasVastaitechGpus := false
|
||||
devs := h.IsolatedDeviceMan.GetDevices()
|
||||
for i := range devs {
|
||||
if devs[i].GetDeviceType() == apis.CONTAINER_DEV_VASTAITECH_GPU {
|
||||
vendorId := strings.Split(devs[i].GetVendorDeviceId(), ":")[0]
|
||||
if utils.IsInStringArray(devs[i].GetSharingMode(), apis.VIRTUAL_SHARING_MODES) && vendorId == apis.VASTAITECH_VENDOR_ID {
|
||||
hasVastaitechGpus = true
|
||||
}
|
||||
}
|
||||
@@ -121,7 +123,8 @@ func (h *SHostInfo) HasContainerCphAmdGpu() bool {
|
||||
hasCphAmdGpus := false
|
||||
devs := h.IsolatedDeviceMan.GetDevices()
|
||||
for i := range devs {
|
||||
if devs[i].GetDeviceType() == apis.CONTAINER_DEV_CPH_AMD_GPU {
|
||||
vendorId := strings.Split(devs[i].GetVendorDeviceId(), ":")[0]
|
||||
if utils.IsInStringArray(devs[i].GetSharingMode(), apis.VIRTUAL_SHARING_MODES) && vendorId == apis.AMD_VENDOR_ID {
|
||||
hasCphAmdGpus = true
|
||||
}
|
||||
}
|
||||
@@ -137,10 +140,12 @@ func (h *SHostInfo) HasContainerNvidiaGpu() bool {
|
||||
nvDevs := make([]isolated_device.IDevice, 0)
|
||||
devs := h.IsolatedDeviceMan.GetDevices()
|
||||
for i := range devs {
|
||||
if utils.IsInStringArray(devs[i].GetDeviceType(), apis.NVIDIA_GPU_TYPES) {
|
||||
vendorId := strings.Split(devs[i].GetVendorDeviceId(), ":")[0]
|
||||
if utils.IsInStringArray(devs[i].GetSharingMode(), apis.VIRTUAL_SHARING_MODES) && vendorId == apis.NVIDIA_VENDOR_ID {
|
||||
hasNvidiaGpus = true
|
||||
nvDevs = append(nvDevs, devs[i])
|
||||
}
|
||||
|
||||
}
|
||||
h.hasNvidiaGpus = &hasNvidiaGpus
|
||||
h.containerNvidiaGpus = nvDevs
|
||||
|
||||
@@ -59,7 +59,6 @@ import (
|
||||
"yunion.io/x/onecloud/pkg/hostman/hostutils/hardware"
|
||||
"yunion.io/x/onecloud/pkg/hostman/hostutils/kubelet"
|
||||
"yunion.io/x/onecloud/pkg/hostman/isolated_device"
|
||||
_ "yunion.io/x/onecloud/pkg/hostman/isolated_device/container_device"
|
||||
"yunion.io/x/onecloud/pkg/hostman/monitor"
|
||||
"yunion.io/x/onecloud/pkg/hostman/options"
|
||||
"yunion.io/x/onecloud/pkg/hostman/storageman"
|
||||
@@ -2311,7 +2310,11 @@ func (h *SHostInfo) probeSyncIsolatedDevices() (*jsonutils.JSONArray, error) {
|
||||
}
|
||||
}
|
||||
|
||||
enableDevWhitelist := options.HostOptions.EnableIsolatedDeviceWhitelist
|
||||
_, err := modules.Hosts.GetSpecific(h.GetSession(), h.HostId, "guest-isolated-devices-initialized", nil)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "check GuestIsolatedDevicesInitialized")
|
||||
}
|
||||
|
||||
offloadNics, err := h.getNicsInterfaces(options.HostOptions.OvsOffloadNics)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -2320,18 +2323,21 @@ func (h *SHostInfo) probeSyncIsolatedDevices() (*jsonutils.JSONArray, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
h.IsolatedDeviceMan.ProbePCIDevices(
|
||||
options.HostOptions.DisableGPU,
|
||||
options.HostOptions.DisableUSB,
|
||||
options.HostOptions.DisableCustomDevice,
|
||||
sriovNics, offloadNics,
|
||||
options.HostOptions.PTNVMEConfigs,
|
||||
options.HostOptions.AMDVgpuPFs,
|
||||
options.HostOptions.NVIDIAVgpuPFs,
|
||||
options.HostOptions.EnableCudaMPS,
|
||||
options.HostOptions.EnableContainerAscendNPU,
|
||||
enableDevWhitelist,
|
||||
)
|
||||
probeOpts := &isolated_device.SIsolatedDeviceProbeOptions{
|
||||
SkipGPUs: options.HostOptions.DisableGPU,
|
||||
SkipUSBs: options.HostOptions.DisableUSB,
|
||||
SkipCustomDevs: options.HostOptions.DisableCustomDevice,
|
||||
EnableCudaHAMI: options.HostOptions.EnableCudaHAMI,
|
||||
EnableCudaMps: options.HostOptions.EnableCudaMPS,
|
||||
EnableContainerNPU: options.HostOptions.EnableContainerAscendNPU,
|
||||
EnableWhitelist: options.HostOptions.EnableIsolatedDeviceWhitelist,
|
||||
SriovNics: sriovNics,
|
||||
OvsOffloadNics: offloadNics,
|
||||
NvmePciDisks: options.HostOptions.PTNVMEConfigs,
|
||||
AmdVgpuPFs: options.HostOptions.AMDVgpuPFs,
|
||||
NvidiaVgpuPFs: options.HostOptions.NVIDIAVgpuPFs,
|
||||
}
|
||||
h.IsolatedDeviceMan.ProbePCIDevices(probeOpts)
|
||||
|
||||
objs, err := h.getRemoteIsolatedDevices()
|
||||
if err != nil {
|
||||
@@ -2353,7 +2359,6 @@ func (h *SHostInfo) probeSyncIsolatedDevices() (*jsonutils.JSONArray, error) {
|
||||
// detach device
|
||||
h.IsolatedDeviceMan.AppendDetachedDevice(&info)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
h.IsolatedDeviceMan.StartDetachTask()
|
||||
@@ -2382,6 +2387,11 @@ func (h *SHostInfo) probeSyncIsolatedDevices() (*jsonutils.JSONArray, error) {
|
||||
mtx.Lock()
|
||||
updateDevs.Add(obj)
|
||||
mtx.Unlock()
|
||||
info := isolated_device.CloudDeviceInfo{}
|
||||
if err := obj.Unmarshal(&info); err != nil {
|
||||
return errors.Wrapf(err, "unmarshal isolated device %s to cloud device info", obj)
|
||||
}
|
||||
dev.SetDeviceInfo(info)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -2649,9 +2659,17 @@ func (h *SHostInfo) injectTelegrafDeviceConfig(conf map[string]interface{}) {
|
||||
hasVasmi := false
|
||||
hasNvidiasmi := false
|
||||
for _, dev := range devs {
|
||||
devType := dev.GetDeviceType()
|
||||
switch devType {
|
||||
case string(isolated_device.ContainerDeviceTypeCphAMDGPU):
|
||||
if !utils.IsInStringArray(dev.GetSharingMode(), api.VIRTUAL_SHARING_MODES) {
|
||||
continue
|
||||
}
|
||||
if dev.GetDeviceType() == api.NETINT_TYPE {
|
||||
hasNetint = true
|
||||
continue
|
||||
}
|
||||
|
||||
vendorId := strings.Split(dev.GetVendorDeviceId(), ":")[0]
|
||||
switch vendorId {
|
||||
case api.AMD_VENDOR_ID:
|
||||
confMap, ok := conf[system_service.TELEGRAF_INPUT_RADEONTOP].(map[string]interface{})
|
||||
if !ok {
|
||||
conf[system_service.TELEGRAF_INPUT_RADEONTOP] = map[string]interface{}{
|
||||
@@ -2665,13 +2683,9 @@ func (h *SHostInfo) injectTelegrafDeviceConfig(conf map[string]interface{}) {
|
||||
confMap[system_service.TELEGRAF_INPUT_RADEONTOP_DEV_PATHS] = devPaths
|
||||
}
|
||||
}
|
||||
case string(isolated_device.ContainerNetintCAQuadra), string(isolated_device.ContainerNetintCAASIC):
|
||||
hasNetint = true
|
||||
continue
|
||||
case string(isolated_device.ContainerDeviceTypeVastaitechGpu):
|
||||
case api.VASTAITECH_VENDOR_ID:
|
||||
hasVasmi = true
|
||||
continue
|
||||
case string(isolated_device.ContainerDeviceTypeNvidiaGpu), string(isolated_device.ContainerDeviceTypeNvidiaMps), string(isolated_device.ContainerDeviceTypeNvidiaGpuShare):
|
||||
case api.NVIDIA_VENDOR_ID:
|
||||
hasNvidiasmi = true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -146,7 +146,7 @@ func (m PodCphAmdGpuMetrics) GetUniformName() string {
|
||||
func (m PodCphAmdGpuMetrics) GetTag() map[string]string {
|
||||
return map[string]string{
|
||||
"dev_id": m.DevId,
|
||||
"dev_type": apis.CONTAINER_DEV_CPH_AMD_GPU,
|
||||
"dev_type": apis.GPU_TYPE,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -183,7 +183,7 @@ func (m PodVastaitechGpuMetrics) GetUniformName() string {
|
||||
func (m PodVastaitechGpuMetrics) GetTag() map[string]string {
|
||||
return map[string]string{
|
||||
"dev_id": m.DevId,
|
||||
"dev_type": apis.CONTAINER_DEV_VASTAITECH_GPU,
|
||||
"dev_type": apis.NPU_TYPE,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -226,14 +226,18 @@ func (m PodNvidiaGpuMetrics) GetUniformName() string {
|
||||
}
|
||||
|
||||
func (m PodNvidiaGpuMetrics) GetTag() map[string]string {
|
||||
devType := apis.CONTAINER_DEV_NVIDIA_GPU
|
||||
devType := apis.GPU_TYPE
|
||||
sharingMode := apis.DEVICE_SHARING_MODE_UNLIMITED
|
||||
if options.HostOptions.EnableCudaMPS {
|
||||
devType = apis.CONTAINER_DEV_NVIDIA_MPS
|
||||
sharingMode = apis.DEVICE_SHARING_MODE_MPS
|
||||
} else if options.HostOptions.EnableCudaHAMI {
|
||||
sharingMode = apis.DEVICE_SHARING_MODE_HAMI
|
||||
}
|
||||
return map[string]string{
|
||||
"index": strconv.Itoa(m.Index),
|
||||
"physical_index": strconv.Itoa(m.PhysicalIndex),
|
||||
"dev_type": devType,
|
||||
"sharing_mode": sharingMode,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -76,7 +76,7 @@ func parseNvidiaGpuProcessMetrics(gpuMetricsStr string) []NvidiaGpuProcessMetric
|
||||
&processMetrics.Index, &processMetrics.Pid, &processMetrics.Type, &fb, &ccpm,
|
||||
&sm, &mem, &enc, &dec, &jpg, &ofa, &processMetrics.Command)
|
||||
if err != nil {
|
||||
log.Errorf("failed parse nvidia gpu metrics %s: %s", line, err)
|
||||
log.Debugf("failed parse nvidia gpu metrics %s: %s", line, err)
|
||||
continue
|
||||
}
|
||||
if processMetrics.Command == "nvidia-cuda-mps" || processMetrics.Command == "-" {
|
||||
@@ -159,10 +159,14 @@ func (s *SGuestMonitorCollector) collectGpuPodsProcesses() map[string]map[string
|
||||
podDesc := pod.GetDesc()
|
||||
hasGpu := false
|
||||
for i := range podDesc.IsolatedDevices {
|
||||
if utils.IsInStringArray(podDesc.IsolatedDevices[i].DevType, compute.CONTAINER_GPU_TYPES) {
|
||||
hasGpu = true
|
||||
break
|
||||
if podDesc.IsolatedDevices[i].DevType != compute.GPU_TYPE {
|
||||
continue
|
||||
}
|
||||
if !utils.IsInStringArray(podDesc.IsolatedDevices[i].SharingMode, compute.VIRTUAL_SHARING_MODES) {
|
||||
continue
|
||||
}
|
||||
hasGpu = true
|
||||
break
|
||||
}
|
||||
if !hasGpu {
|
||||
return true
|
||||
|
||||
@@ -661,12 +661,17 @@ func NewGuestPodMonitor(
|
||||
hasCphAmdGpu := false
|
||||
hasVastaitechGpu := false
|
||||
for i := range podDesc.IsolatedDevices {
|
||||
if utils.IsInStringArray(podDesc.IsolatedDevices[i].DevType, compute.NVIDIA_GPU_TYPES) {
|
||||
if !utils.IsInStringArray(podDesc.IsolatedDevices[i].SharingMode, compute.VIRTUAL_SHARING_MODES) {
|
||||
continue
|
||||
}
|
||||
vendorId := strings.Split(podDesc.IsolatedDevices[i].VendorDeviceId, ":")[0]
|
||||
switch vendorId {
|
||||
case compute.NVIDIA_VENDOR_ID:
|
||||
hasNvGpu = true
|
||||
} else if podDesc.IsolatedDevices[i].DevType == compute.CONTAINER_DEV_VASTAITECH_GPU {
|
||||
hasVastaitechGpu = true
|
||||
} else if podDesc.IsolatedDevices[i].DevType == compute.CONTAINER_DEV_CPH_AMD_GPU {
|
||||
case compute.AMD_VENDOR_ID:
|
||||
hasCphAmdGpu = true
|
||||
case compute.VASTAITECH_VENDOR_ID:
|
||||
hasVastaitechGpu = true
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -44,23 +44,24 @@ const (
|
||||
ContainerDeviceTypeNvidiaGpu ContainerDeviceType = api.CONTAINER_DEV_NVIDIA_GPU
|
||||
ContainerDeviceTypeNvidiaMps ContainerDeviceType = api.CONTAINER_DEV_NVIDIA_MPS
|
||||
ContainerDeviceTypeNvidiaGpuShare ContainerDeviceType = api.CONTAINER_DEV_NVIDIA_GPU_SHARE
|
||||
ContainerDeviceTypeNvidiaHAMI ContainerDeviceType = api.CONTAINER_DEV_NVIDIA_HAMI
|
||||
ContainerDeviceTypeAscendNpu ContainerDeviceType = api.CONTAINER_DEV_ASCEND_NPU
|
||||
ContainerDeviceTypeVastaitechGpu ContainerDeviceType = api.CONTAINER_DEV_VASTAITECH_GPU
|
||||
)
|
||||
|
||||
func GetContainerDeviceManager(t ContainerDeviceType) (IContainerDeviceManager, error) {
|
||||
man, ok := containerDeviceManagers[t]
|
||||
func GetContainerDeviceManager(devType ContainerDeviceType) (IContainerDeviceManager, error) {
|
||||
man, ok := containerDeviceManagers[devType]
|
||||
if !ok {
|
||||
return nil, errors.Wrapf(errors.ErrNotFound, "not found container device manager by %q", t)
|
||||
return nil, errors.Wrapf(errors.ErrNotFound, "not found container device manager by %q", devType)
|
||||
}
|
||||
return man, nil
|
||||
}
|
||||
|
||||
func RegisterContainerDeviceManager(man IContainerDeviceManager) {
|
||||
if _, ok := containerDeviceManagers[man.GetType()]; ok {
|
||||
panic(fmt.Sprintf("container device manager %s is already registered", man.GetType()))
|
||||
if _, ok := containerDeviceManagers[man.GetRegisterType()]; ok {
|
||||
panic(fmt.Sprintf("container device manager %s is already registered", man.GetRegisterType()))
|
||||
}
|
||||
containerDeviceManagers[man.GetType()] = man
|
||||
containerDeviceManagers[man.GetRegisterType()] = man
|
||||
}
|
||||
|
||||
func GetContainerCDIManager(t apis.ContainerCDIKind) (IContainerCDIManager, error) {
|
||||
@@ -89,7 +90,7 @@ type ContainerDeviceConfiguration struct {
|
||||
}
|
||||
|
||||
type IContainerDeviceManager interface {
|
||||
GetType() ContainerDeviceType
|
||||
GetRegisterType() ContainerDeviceType
|
||||
NewDevices(dev *ContainerDevice) ([]IDevice, error)
|
||||
NewContainerDevices(input *hostapi.ContainerCreateInput, dev *hostapi.ContainerDevice) ([]*runtimeapi.Device, []*runtimeapi.Device, error)
|
||||
ProbeDevices() ([]IDevice, error)
|
||||
|
||||
@@ -24,7 +24,9 @@ import (
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
computeapi "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
hostapi "yunion.io/x/onecloud/pkg/apis/host"
|
||||
"yunion.io/x/onecloud/pkg/hostman/hostinfo"
|
||||
"yunion.io/x/onecloud/pkg/hostman/isolated_device"
|
||||
"yunion.io/x/onecloud/pkg/util/procutils"
|
||||
)
|
||||
@@ -41,7 +43,9 @@ func (m *ascendNPUManager) GetContainerExtraConfigures(devs []*hostapi.Container
|
||||
if dev.IsolatedDevice == nil {
|
||||
continue
|
||||
}
|
||||
if isolated_device.ContainerDeviceType(dev.IsolatedDevice.DeviceType) != isolated_device.ContainerDeviceTypeAscendNpu {
|
||||
iDev := hostinfo.Instance().IsolatedDeviceMan.GetDeviceByCloudId(dev.IsolatedDevice.Id)
|
||||
devMan := iDev.GetContainerDeviceManager()
|
||||
if _, ok := devMan.(*ascendNPUManager); !ok {
|
||||
continue
|
||||
}
|
||||
npus = append(npus, dev.IsolatedDevice.Path)
|
||||
@@ -104,7 +108,7 @@ func newAscendNPUManager() *ascendNPUManager {
|
||||
}
|
||||
|
||||
func (m *ascendNPUManager) ProbeDevices() ([]isolated_device.IDevice, error) {
|
||||
return getAscendNpus()
|
||||
return m.getAscendNpus()
|
||||
}
|
||||
|
||||
func (m *ascendNPUManager) NewDevices(dev *isolated_device.ContainerDevice) ([]isolated_device.IDevice, error) {
|
||||
@@ -137,15 +141,29 @@ func (m *ascendNPUManager) NewContainerDevices(input *hostapi.ContainerCreateInp
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (m *ascendNPUManager) GetType() isolated_device.ContainerDeviceType {
|
||||
func (m *ascendNPUManager) GetRegisterType() isolated_device.ContainerDeviceType {
|
||||
return isolated_device.ContainerDeviceTypeAscendNpu
|
||||
}
|
||||
|
||||
func (m *ascendNPUManager) GetDevType() string {
|
||||
return computeapi.NPU_TYPE
|
||||
}
|
||||
|
||||
func (m *ascendNPUManager) GetSharingMode() string {
|
||||
return computeapi.DEVICE_SHARING_MODE_UNLIMITED
|
||||
}
|
||||
|
||||
type ascnedNPU struct {
|
||||
manager *ascendNPUManager
|
||||
|
||||
*BaseDevice
|
||||
}
|
||||
|
||||
func getAscendNpus() ([]isolated_device.IDevice, error) {
|
||||
func (dev *ascnedNPU) GetContainerDeviceManager() isolated_device.IContainerDeviceManager {
|
||||
return dev.manager
|
||||
}
|
||||
|
||||
func (m *ascendNPUManager) getAscendNpus() ([]isolated_device.IDevice, error) {
|
||||
devs := make([]isolated_device.IDevice, 0)
|
||||
// Show all device's topology information
|
||||
out, err := procutils.NewRemoteCommandAsFarAsPossible("npu-smi", "info").Output()
|
||||
@@ -188,7 +206,8 @@ func getAscendNpus() ([]isolated_device.IDevice, error) {
|
||||
}
|
||||
dev := isolated_device.NewPCIDevice2(pciOutput[0])
|
||||
npuDev := &ascnedNPU{
|
||||
BaseDevice: NewBaseDevice(dev, isolated_device.ContainerDeviceTypeAscendNpu, devPath),
|
||||
manager: m,
|
||||
BaseDevice: NewBaseDevice(dev, computeapi.NPU_TYPE, devPath, computeapi.DEVICE_SHARING_MODE_UNLIMITED, 1),
|
||||
}
|
||||
npuDev.SetModelName(npuName)
|
||||
|
||||
|
||||
@@ -29,13 +29,17 @@ import (
|
||||
|
||||
type BaseDevice struct {
|
||||
*isolated_device.SBaseDevice
|
||||
Path string
|
||||
Path string
|
||||
VirtualNum int
|
||||
}
|
||||
|
||||
func NewBaseDevice(dev *isolated_device.PCIDevice, devType isolated_device.ContainerDeviceType, devPath string) *BaseDevice {
|
||||
func NewBaseDevice(
|
||||
dev *isolated_device.PCIDevice, devType, devPath, sharingMode string, virtualNum int,
|
||||
) *BaseDevice {
|
||||
return &BaseDevice{
|
||||
SBaseDevice: isolated_device.NewBaseDevice(dev, string(devType)),
|
||||
SBaseDevice: isolated_device.NewBaseDevice(dev, string(devType), sharingMode),
|
||||
Path: devPath,
|
||||
VirtualNum: virtualNum,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,6 +63,14 @@ func (c BaseDevice) GetDevicePath() string {
|
||||
return c.Path
|
||||
}
|
||||
|
||||
func (c BaseDevice) GetVirtualNum() int {
|
||||
return c.VirtualNum
|
||||
}
|
||||
|
||||
func (c BaseDevice) HotPluggable() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (c *BaseDevice) SetDevicePath(devPath string) {
|
||||
c.Path = devPath
|
||||
}
|
||||
@@ -116,7 +128,7 @@ func getGPUPCIAddr(linkPartName string) (string, error) {
|
||||
return fullAddr, nil
|
||||
}
|
||||
|
||||
func NewPCIGPURenderBaseDevice(devPath string, index int, devType isolated_device.ContainerDeviceType) (*BaseDevice, error) {
|
||||
func NewPCIGPURenderBaseDevice(devPath string, virtualNum int, devType, sharingMode string) (*BaseDevice, error) {
|
||||
dir := "/dev/dri/by-path/"
|
||||
entries, err := os.ReadDir(dir)
|
||||
if err != nil {
|
||||
@@ -144,9 +156,9 @@ func NewPCIGPURenderBaseDevice(devPath string, index int, devType isolated_devic
|
||||
return nil, errors.Wrapf(err, "GetPCIStrByAddr %s", pciAddr)
|
||||
}
|
||||
dev := isolated_device.NewPCIDevice2(pciOutput[0])
|
||||
devAddr := dev.Addr
|
||||
baseDev := NewBaseDevice(dev, devType, devPath)
|
||||
baseDev.SetAddr(fmt.Sprintf("%s-%d", devAddr, index), devAddr)
|
||||
// devAddr := dev.Addr
|
||||
baseDev := NewBaseDevice(dev, devType, devPath, sharingMode, virtualNum)
|
||||
//baseDev.SetAddr(fmt.Sprintf("%s-%d", devAddr, index), devAddr)
|
||||
|
||||
return baseDev, nil
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ import (
|
||||
"strings"
|
||||
|
||||
runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1"
|
||||
"yunion.io/x/onecloud/pkg/apis/compute"
|
||||
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
@@ -39,10 +40,18 @@ func (m *cphAMDGPUManager) ProbeDevices() ([]isolated_device.IDevice, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (m *cphAMDGPUManager) GetType() isolated_device.ContainerDeviceType {
|
||||
func (m *cphAMDGPUManager) GetRegisterType() isolated_device.ContainerDeviceType {
|
||||
return isolated_device.ContainerDeviceTypeCphAMDGPU
|
||||
}
|
||||
|
||||
func (m *cphAMDGPUManager) GetDevType() string {
|
||||
return compute.GPU_TYPE
|
||||
}
|
||||
|
||||
func (m *cphAMDGPUManager) GetSharingMode() string {
|
||||
return compute.DEVICE_SHARING_MODE_UNLIMITED
|
||||
}
|
||||
|
||||
func (m *cphAMDGPUManager) NewDevices(dev *isolated_device.ContainerDevice) ([]isolated_device.IDevice, error) {
|
||||
if !strings.HasPrefix(dev.Path, "/dev/dri/renderD") {
|
||||
return nil, errors.Errorf("device path %q doesn't start with /dev/dri/renderD", dev.Path)
|
||||
@@ -50,15 +59,11 @@ func (m *cphAMDGPUManager) NewDevices(dev *isolated_device.ContainerDevice) ([]i
|
||||
if err := CheckVirtualNumber(dev); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
gpuDevs := make([]isolated_device.IDevice, 0)
|
||||
for i := 0; i < dev.VirtualNumber; i++ {
|
||||
gpuDev, err := newCphAMDGPU(dev.Path, i)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "new CPH AMD GPU with index %d", i)
|
||||
}
|
||||
gpuDevs = append(gpuDevs, gpuDev)
|
||||
gpuDev, err := m.newCphAMDGPU(dev.Path, compute.DEVICE_SHARING_MODE_UNLIMITED, dev.VirtualNumber)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "new CPH AMD GPU with virtual num %d", dev.VirtualNumber)
|
||||
}
|
||||
return gpuDevs, nil
|
||||
return []isolated_device.IDevice{gpuDev}, nil
|
||||
}
|
||||
|
||||
func (m *cphAMDGPUManager) getDeviceHostPathByAddr(dev *hostapi.ContainerDevice) (string, error) {
|
||||
@@ -83,15 +88,22 @@ func (m *cphAMDGPUManager) GetContainerExtraConfigures(devs []*hostapi.Container
|
||||
}
|
||||
|
||||
type cphAMDGPU struct {
|
||||
manager *cphAMDGPUManager
|
||||
|
||||
*BaseDevice
|
||||
}
|
||||
|
||||
func newCphAMDGPU(devPath string, index int) (*cphAMDGPU, error) {
|
||||
dev, err := NewPCIGPURenderBaseDevice(devPath, index, isolated_device.ContainerDeviceTypeCphAMDGPU)
|
||||
func (dev *cphAMDGPU) GetContainerDeviceManager() isolated_device.IContainerDeviceManager {
|
||||
return dev.manager
|
||||
}
|
||||
|
||||
func (m *cphAMDGPUManager) newCphAMDGPU(devPath, sharingMode string, virtualNum int) (*cphAMDGPU, error) {
|
||||
dev, err := NewPCIGPURenderBaseDevice(devPath, virtualNum, compute.GPU_TYPE, sharingMode)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "new PCIGPURenderBaseDevice")
|
||||
}
|
||||
return &cphAMDGPU{
|
||||
manager: m,
|
||||
BaseDevice: dev,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import (
|
||||
"path/filepath"
|
||||
|
||||
runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1"
|
||||
"yunion.io/x/onecloud/pkg/apis/compute"
|
||||
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
@@ -43,16 +44,25 @@ func init() {
|
||||
type cphAOSPBinderManager struct {
|
||||
controlDevicePath string
|
||||
controlName string
|
||||
initialized bool
|
||||
}
|
||||
|
||||
func newCphAOSPBinderManager() *cphAOSPBinderManager {
|
||||
return &cphAOSPBinderManager{}
|
||||
}
|
||||
|
||||
func (m *cphAOSPBinderManager) GetType() isolated_device.ContainerDeviceType {
|
||||
func (m *cphAOSPBinderManager) GetRegisterType() isolated_device.ContainerDeviceType {
|
||||
return isolated_device.ContainerDeviceTypeCphASOPBinder
|
||||
}
|
||||
|
||||
func (m *cphAOSPBinderManager) GetDevType() string {
|
||||
return compute.BINDER_TYPE
|
||||
}
|
||||
|
||||
func (m *cphAOSPBinderManager) GetSharingMode() string {
|
||||
return compute.DEVICE_SHARING_MODE_UNLIMITED
|
||||
}
|
||||
|
||||
func (m *cphAOSPBinderManager) ProbeDevices() ([]isolated_device.IDevice, error) {
|
||||
return nil, nil
|
||||
}
|
||||
@@ -64,26 +74,27 @@ func (m *cphAOSPBinderManager) NewDevices(dev *isolated_device.ContainerDevice)
|
||||
if err := m.initialize(dev); err != nil {
|
||||
return nil, errors.Wrap(err, "initialize")
|
||||
}
|
||||
devs := make([]isolated_device.IDevice, 0)
|
||||
for i := 0; i < dev.VirtualNumber; i++ {
|
||||
newDev, err := m.newDeviceByIndex(i)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "new device by index %d", i)
|
||||
}
|
||||
devs = append(devs, newDev)
|
||||
}
|
||||
return devs, nil
|
||||
}
|
||||
|
||||
func (m *cphAOSPBinderManager) newDeviceByIndex(index int) (isolated_device.IDevice, error) {
|
||||
dev, err := newCphAOSPBinder(index, m.controlDevicePath)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "newCphAOSPBinder")
|
||||
id := "aosp_binder"
|
||||
ndev := &isolated_device.PCIDevice{
|
||||
Addr: m.controlName,
|
||||
VendorId: CPH_AOSP_VENDOR_ID,
|
||||
DeviceId: CPH_AOSP_DEVICE_ID,
|
||||
ModelName: CPH_AOSP_BINDER_MODEL_NAME,
|
||||
}
|
||||
return dev, nil
|
||||
devPath := fmt.Sprintf("/dev/%s", id)
|
||||
binderDev := &cphAOSPBinder{
|
||||
manager: m,
|
||||
BaseDevice: NewBaseDevice(ndev, compute.BINDER_TYPE, devPath, compute.DEVICE_SHARING_MODE_UNLIMITED, dev.VirtualNumber),
|
||||
ControlPath: m.controlDevicePath,
|
||||
}
|
||||
return []isolated_device.IDevice{binderDev}, nil
|
||||
}
|
||||
|
||||
func (m *cphAOSPBinderManager) initialize(dev *isolated_device.ContainerDevice) error {
|
||||
if m.initialized {
|
||||
return errors.Errorf("cphAOSPBinderManager already initialized")
|
||||
}
|
||||
ctrlPath := CPH_AOSP_BINDER_CONTROL_DEV_PATH
|
||||
info, err := os.Stat(ctrlPath)
|
||||
if err != nil {
|
||||
@@ -91,6 +102,7 @@ func (m *cphAOSPBinderManager) initialize(dev *isolated_device.ContainerDevice)
|
||||
}
|
||||
m.controlDevicePath = ctrlPath
|
||||
m.controlName = info.Name()
|
||||
m.initialized = true
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -159,22 +171,11 @@ func (m *cphAOSPBinderManager) ensureBinderDevice(ctrName string, dev *hostapi.C
|
||||
}
|
||||
|
||||
type cphAOSPBinder struct {
|
||||
manager *cphAOSPBinderManager
|
||||
*BaseDevice
|
||||
ControlPath string
|
||||
}
|
||||
|
||||
func newCphAOSPBinder(idx int, ctrPath string) (*cphAOSPBinder, error) {
|
||||
id := fmt.Sprintf("aosp_binder_%d", idx)
|
||||
dev := &isolated_device.PCIDevice{
|
||||
Addr: fmt.Sprintf("%d", idx),
|
||||
VendorId: CPH_AOSP_VENDOR_ID,
|
||||
DeviceId: CPH_AOSP_DEVICE_ID,
|
||||
ModelName: CPH_AOSP_BINDER_MODEL_NAME,
|
||||
}
|
||||
devPath := fmt.Sprintf("/dev/%s", id)
|
||||
binderDev := &cphAOSPBinder{
|
||||
BaseDevice: NewBaseDevice(dev, isolated_device.ContainerDeviceTypeCphASOPBinder, devPath),
|
||||
ControlPath: ctrPath,
|
||||
}
|
||||
return binderDev, nil
|
||||
func (dev *cphAOSPBinder) GetContainerDeviceManager() isolated_device.IContainerDeviceManager {
|
||||
return dev.manager
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
"strings"
|
||||
|
||||
runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1"
|
||||
"yunion.io/x/onecloud/pkg/apis/compute"
|
||||
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/errors"
|
||||
@@ -93,7 +94,7 @@ func newNetintDeviceManager(devType isolated_device.ContainerDeviceType, reg *re
|
||||
}
|
||||
}
|
||||
|
||||
func (m *netintDeviceManager) GetType() isolated_device.ContainerDeviceType {
|
||||
func (m *netintDeviceManager) GetRegisterType() isolated_device.ContainerDeviceType {
|
||||
return m.devType
|
||||
}
|
||||
|
||||
@@ -159,35 +160,27 @@ func (m *netintDeviceManager) NewDevices(dev *isolated_device.ContainerDevice) (
|
||||
}
|
||||
result := make([]isolated_device.IDevice, 0)
|
||||
for _, nvmeDev := range nvmeDevs {
|
||||
for i := 0; i < dev.VirtualNumber; i++ {
|
||||
newDev, err := m.newDeviceByIndex(nvmeDev, i)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "newDeviceByIndex %#v %d", nvmeDev, i)
|
||||
}
|
||||
result = append(result, newDev)
|
||||
devIdx, err := nvmeDev.GetIndex()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
devInfo := &isolated_device.PCIDevice{
|
||||
Addr: strconv.Itoa(devIdx),
|
||||
VendorId: NETINT_VENDOR_ID,
|
||||
DeviceId: NETINT_DEVICE_ID,
|
||||
ModelName: nvmeDev.ModelNumber,
|
||||
}
|
||||
newDev := &netintDevice{
|
||||
manager: m,
|
||||
BaseDevice: NewBaseDevice(devInfo, compute.NETINT_TYPE, nvmeDev.DevicePath, compute.DEVICE_SHARING_MODE_UNLIMITED, dev.VirtualNumber),
|
||||
info: nvmeDev,
|
||||
}
|
||||
|
||||
result = append(result, newDev)
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (m *netintDeviceManager) newDeviceByIndex(dev *NetintDeviceInfo, idx int) (*netintDevice, error) {
|
||||
devIdx, err := dev.GetIndex()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "dev.GetIndex")
|
||||
}
|
||||
devInfo := &isolated_device.PCIDevice{
|
||||
Addr: fmt.Sprintf("%d-%d", devIdx, idx),
|
||||
VendorId: NETINT_VENDOR_ID,
|
||||
DeviceId: NETINT_DEVICE_ID,
|
||||
ModelName: dev.ModelNumber,
|
||||
}
|
||||
nvmeDev := &netintDevice{
|
||||
BaseDevice: NewBaseDevice(devInfo, m.devType, dev.DevicePath),
|
||||
info: dev,
|
||||
}
|
||||
return nvmeDev, nil
|
||||
}
|
||||
|
||||
func (m *netintDeviceManager) NewContainerDevices(_ *hostapi.ContainerCreateInput, input *hostapi.ContainerDevice) ([]*runtimeapi.Device, []*runtimeapi.Device, error) {
|
||||
dev := input.IsolatedDevice
|
||||
if !fileutils2.Exists(dev.Path) {
|
||||
@@ -217,6 +210,7 @@ func (m *netintDeviceManager) GetContainerExtraConfigures(devs []*hostapi.Contai
|
||||
}
|
||||
|
||||
type netintDevice struct {
|
||||
manager *netintDeviceManager
|
||||
*BaseDevice
|
||||
info *NetintDeviceInfo
|
||||
}
|
||||
@@ -224,3 +218,7 @@ type netintDevice struct {
|
||||
func (d netintDevice) GetNVMESizeMB() int {
|
||||
return d.info.PhysicalSize / 1024 / 1024
|
||||
}
|
||||
|
||||
func (dev *netintDevice) GetContainerDeviceManager() isolated_device.IContainerDeviceManager {
|
||||
return dev.manager
|
||||
}
|
||||
|
||||
@@ -23,9 +23,10 @@ import (
|
||||
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/util/sets"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
hostapi "yunion.io/x/onecloud/pkg/apis/host"
|
||||
"yunion.io/x/onecloud/pkg/hostman/hostinfo"
|
||||
"yunion.io/x/onecloud/pkg/hostman/isolated_device"
|
||||
"yunion.io/x/onecloud/pkg/util/procutils"
|
||||
)
|
||||
@@ -40,12 +41,12 @@ func newNvidiaGPUManager() *nvidiaGPUManager {
|
||||
return &nvidiaGPUManager{}
|
||||
}
|
||||
|
||||
func (m *nvidiaGPUManager) GetType() isolated_device.ContainerDeviceType {
|
||||
func (m *nvidiaGPUManager) GetRegisterType() isolated_device.ContainerDeviceType {
|
||||
return isolated_device.ContainerDeviceTypeNvidiaGpu
|
||||
}
|
||||
|
||||
func (m *nvidiaGPUManager) ProbeDevices() ([]isolated_device.IDevice, error) {
|
||||
return probeNvidiaGpus()
|
||||
return probeNvidiaGpus(api.DEVICE_SHARING_MODE_EXCLUSIVE, m)
|
||||
}
|
||||
|
||||
func (m *nvidiaGPUManager) NewDevices(dev *isolated_device.ContainerDevice) ([]isolated_device.IDevice, error) {
|
||||
@@ -62,13 +63,12 @@ func (m *nvidiaGPUManager) GetContainerExtraConfigures(devs []*hostapi.Container
|
||||
if dev.IsolatedDevice == nil {
|
||||
continue
|
||||
}
|
||||
types := sets.NewString(
|
||||
string(isolated_device.ContainerDeviceTypeNvidiaGpu),
|
||||
string(isolated_device.ContainerDeviceTypeNvidiaGpuShare),
|
||||
)
|
||||
if !types.Has(dev.IsolatedDevice.DeviceType) {
|
||||
iDev := hostinfo.Instance().IsolatedDeviceMan.GetDeviceByCloudId(dev.IsolatedDevice.Id)
|
||||
devMan := iDev.GetContainerDeviceManager()
|
||||
if _, ok := devMan.(*nvidiaGPUManager); !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
gpuIds = append(gpuIds, dev.IsolatedDevice.Path)
|
||||
}
|
||||
if len(gpuIds) == 0 {
|
||||
@@ -91,6 +91,7 @@ func (m *nvidiaGPUManager) GetContainerExtraConfigures(devs []*hostapi.Container
|
||||
}
|
||||
|
||||
type nvidiaGPU struct {
|
||||
manager isolated_device.IContainerDeviceManager
|
||||
*BaseDevice
|
||||
|
||||
memSize int
|
||||
@@ -114,20 +115,26 @@ func (dev *nvidiaGPU) GetDeviceMinor() int {
|
||||
return dev.deviceMinor
|
||||
}
|
||||
|
||||
func probeNvidiaGpus() ([]isolated_device.IDevice, error) {
|
||||
func (dev *nvidiaGPU) GetContainerDeviceManager() isolated_device.IContainerDeviceManager {
|
||||
return dev.manager
|
||||
}
|
||||
|
||||
func probeNvidiaGpus(sharingMode string, manager isolated_device.IContainerDeviceManager) ([]isolated_device.IDevice, error) {
|
||||
if nvidiaGpuUsages != nil {
|
||||
res := make([]isolated_device.IDevice, 0)
|
||||
for pciAddr, dev := range nvidiaGpuUsages {
|
||||
if dev.Used {
|
||||
continue
|
||||
}
|
||||
dev := nvidiaGpuUsages[pciAddr].nvidiaGPU
|
||||
dev.manager = manager
|
||||
res = append(res, nvidiaGpuUsages[pciAddr].nvidiaGPU)
|
||||
}
|
||||
nvidiaGpuUsages = nil
|
||||
return res, nil
|
||||
}
|
||||
|
||||
devs, err := getNvidiaGPUs()
|
||||
devs, err := getNvidiaGPUs(sharingMode, manager)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -138,7 +145,7 @@ func probeNvidiaGpus() ([]isolated_device.IDevice, error) {
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func getNvidiaGPUs() ([]*nvidiaGPU, error) {
|
||||
func getNvidiaGPUs(sharingMode string, manager isolated_device.IContainerDeviceManager) ([]*nvidiaGPU, error) {
|
||||
devs := make([]*nvidiaGPU, 0)
|
||||
// nvidia-smi --query-gpu=gpu_uuid,gpu_name,gpu_bus_id --format=csv
|
||||
// uuid, name, pci.bus_id
|
||||
@@ -190,7 +197,8 @@ func getNvidiaGPUs() ([]*nvidiaGPU, error) {
|
||||
}
|
||||
|
||||
gpuDev := &nvidiaGPU{
|
||||
BaseDevice: NewBaseDevice(dev, isolated_device.ContainerDeviceTypeNvidiaGpu, gpuId),
|
||||
manager: manager,
|
||||
BaseDevice: NewBaseDevice(dev, api.GPU_TYPE, gpuId, sharingMode, 1),
|
||||
memSize: memSize,
|
||||
gpuIndex: indexInt,
|
||||
deviceMinor: driverInfo.DeviceMinor,
|
||||
|
||||
@@ -20,6 +20,10 @@ import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1"
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
hostapi "yunion.io/x/onecloud/pkg/apis/host"
|
||||
"yunion.io/x/onecloud/pkg/hostman/hostinfo"
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/hostman/isolated_device"
|
||||
@@ -30,14 +34,50 @@ func init() {
|
||||
}
|
||||
|
||||
type nvidiaGPUShareManager struct {
|
||||
nvidiaGPUManager
|
||||
}
|
||||
|
||||
func (m *nvidiaGPUShareManager) NewContainerDevices(input *hostapi.ContainerCreateInput, dev *hostapi.ContainerDevice) ([]*runtimeapi.Device, []*runtimeapi.Device, error) {
|
||||
return nil, nil, nil
|
||||
}
|
||||
|
||||
func (m *nvidiaGPUShareManager) GetContainerExtraConfigures(devs []*hostapi.ContainerDevice) ([]*runtimeapi.KeyValue, []*runtimeapi.Mount) {
|
||||
gpuIds := []string{}
|
||||
for _, dev := range devs {
|
||||
if dev.IsolatedDevice == nil {
|
||||
continue
|
||||
}
|
||||
iDev := hostinfo.Instance().IsolatedDeviceMan.GetDeviceByCloudId(dev.IsolatedDevice.Id)
|
||||
devMan := iDev.GetContainerDeviceManager()
|
||||
if _, ok := devMan.(*nvidiaGPUShareManager); !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
gpuIds = append(gpuIds, dev.IsolatedDevice.Path)
|
||||
}
|
||||
if len(gpuIds) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
retEnvs := []*runtimeapi.KeyValue{}
|
||||
if len(gpuIds) > 0 {
|
||||
retEnvs = append(retEnvs, []*runtimeapi.KeyValue{
|
||||
{
|
||||
Key: "NVIDIA_VISIBLE_DEVICES",
|
||||
Value: strings.Join(gpuIds, ","),
|
||||
},
|
||||
{
|
||||
Key: "NVIDIA_DRIVER_CAPABILITIES",
|
||||
Value: "all",
|
||||
},
|
||||
}...)
|
||||
}
|
||||
return retEnvs, nil
|
||||
}
|
||||
|
||||
func newNvidiaGPUShareManager() *nvidiaGPUShareManager {
|
||||
return &nvidiaGPUShareManager{}
|
||||
}
|
||||
|
||||
func (m *nvidiaGPUShareManager) GetType() isolated_device.ContainerDeviceType {
|
||||
func (m *nvidiaGPUShareManager) GetRegisterType() isolated_device.ContainerDeviceType {
|
||||
return isolated_device.ContainerDeviceTypeNvidiaGpuShare
|
||||
}
|
||||
|
||||
@@ -53,19 +93,16 @@ func (m *nvidiaGPUShareManager) NewDevices(dev *isolated_device.ContainerDevice)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
gpuDevs := make([]isolated_device.IDevice, 0)
|
||||
for i := 0; i < dev.VirtualNumber; i++ {
|
||||
gpuDev, err := newNvidiaGpuShare(dev.Path, i)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "new CPH AMD GPU with index %d", i)
|
||||
}
|
||||
gpuDevs = append(gpuDevs, gpuDev)
|
||||
gpuDev, err := m.newNvidiaGpuShare(dev.Path, dev.VirtualNumber)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "new CPH AMD GPU")
|
||||
}
|
||||
return gpuDevs, nil
|
||||
return []isolated_device.IDevice{gpuDev}, nil
|
||||
}
|
||||
|
||||
type nvidiaGpuShareDev struct {
|
||||
nvidiaGPU
|
||||
manager *nvidiaGPUShareManager
|
||||
|
||||
CardPath string
|
||||
RenderPath string
|
||||
@@ -79,6 +116,10 @@ func (dev *nvidiaGpuShareDev) GetRenderPath() string {
|
||||
return dev.RenderPath
|
||||
}
|
||||
|
||||
func (dev *nvidiaGpuShareDev) GetContainerDeviceManager() isolated_device.IContainerDeviceManager {
|
||||
return dev.manager
|
||||
}
|
||||
|
||||
type nvidiaGpuUsage struct {
|
||||
*nvidiaGPU
|
||||
|
||||
@@ -91,7 +132,7 @@ func getNvidiaGpuUsage() (map[string]*nvidiaGpuUsage, error) {
|
||||
if nvidiaGpuUsages != nil {
|
||||
return nvidiaGpuUsages, nil
|
||||
}
|
||||
devs, err := getNvidiaGPUs()
|
||||
devs, err := getNvidiaGPUs(api.DEVICE_SHARING_MODE_UNLIMITED, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -109,15 +150,15 @@ func getNvidiaGpuUsage() (map[string]*nvidiaGpuUsage, error) {
|
||||
return nvidiaGpuUsages, nil
|
||||
}
|
||||
|
||||
func newNvidiaGpuShare(devPath string, index int) (*nvidiaGpuShareDev, error) {
|
||||
func (m *nvidiaGPUShareManager) newNvidiaGpuShare(devPath string, virtualNumber int) (*nvidiaGpuShareDev, error) {
|
||||
devUsages, err := getNvidiaGpuUsage()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "getNvidiaGpuUsage")
|
||||
}
|
||||
|
||||
dev, err := NewPCIGPURenderBaseDevice(devPath, index, isolated_device.ContainerDeviceTypeNvidiaGpuShare)
|
||||
dev, err := NewPCIGPURenderBaseDevice(devPath, virtualNumber, api.GPU_TYPE, api.DEVICE_SHARING_MODE_UNLIMITED)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "new PCIGPURenderBaseDevice")
|
||||
return nil, errors.Wrap(err, "NewPCIGPURenderBaseDevice")
|
||||
}
|
||||
devAddr := dev.GetOriginAddr()
|
||||
cardPath := path.Join("/dev/dri/by-path", fmt.Sprintf("pci-0000:%s-card", devAddr))
|
||||
@@ -133,6 +174,7 @@ func newNvidiaGpuShare(devPath string, index int) (*nvidiaGpuShareDev, error) {
|
||||
dev.SetDevicePath(nvidiaGPUDev.Path)
|
||||
|
||||
return &nvidiaGpuShareDev{
|
||||
manager: m,
|
||||
nvidiaGPU: nvidiaGPU{
|
||||
BaseDevice: dev,
|
||||
memSize: devUsages[devAddr].memSize,
|
||||
|
||||
116
pkg/hostman/isolated_device/container_device/nvidia_hami.go
Normal file
116
pkg/hostman/isolated_device/container_device/nvidia_hami.go
Normal file
@@ -0,0 +1,116 @@
|
||||
// Copyright 2019 Yunion
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package container_device
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1"
|
||||
|
||||
computeapi "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
hostapi "yunion.io/x/onecloud/pkg/apis/host"
|
||||
"yunion.io/x/onecloud/pkg/hostman/hostinfo"
|
||||
"yunion.io/x/onecloud/pkg/hostman/isolated_device"
|
||||
"yunion.io/x/onecloud/pkg/hostman/options"
|
||||
)
|
||||
|
||||
func init() {
|
||||
isolated_device.RegisterContainerDeviceManager(newNvidiaHAMIManager())
|
||||
}
|
||||
|
||||
type nvidiaHAMIManager struct {
|
||||
}
|
||||
|
||||
func (m *nvidiaHAMIManager) NewDevices(dev *isolated_device.ContainerDevice) ([]isolated_device.IDevice, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (m *nvidiaHAMIManager) NewContainerDevices(input *hostapi.ContainerCreateInput, dev *hostapi.ContainerDevice) ([]*runtimeapi.Device, []*runtimeapi.Device, error) {
|
||||
return nil, nil, nil
|
||||
}
|
||||
|
||||
func newNvidiaHAMIManager() *nvidiaHAMIManager {
|
||||
return &nvidiaHAMIManager{}
|
||||
}
|
||||
|
||||
func (m *nvidiaHAMIManager) GetRegisterType() isolated_device.ContainerDeviceType {
|
||||
return isolated_device.ContainerDeviceTypeNvidiaHAMI
|
||||
}
|
||||
|
||||
func (m *nvidiaHAMIManager) ProbeDevices() ([]isolated_device.IDevice, error) {
|
||||
return probeNvidiaGpus(computeapi.DEVICE_SHARING_MODE_HAMI, m)
|
||||
}
|
||||
|
||||
func (m *nvidiaHAMIManager) GetContainerExtraConfigures(devs []*hostapi.ContainerDevice) ([]*runtimeapi.KeyValue, []*runtimeapi.Mount) {
|
||||
gpuIds := []string{}
|
||||
memoryLimit := ""
|
||||
smLimit := ""
|
||||
for _, dev := range devs {
|
||||
if dev.IsolatedDevice == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
iDev := hostinfo.Instance().IsolatedDeviceMan.GetDeviceByCloudId(dev.IsolatedDevice.Id)
|
||||
devMan := iDev.GetContainerDeviceManager()
|
||||
if _, ok := devMan.(*nvidiaHAMIManager); !ok {
|
||||
continue
|
||||
}
|
||||
gpuIds = append(gpuIds, dev.IsolatedDevice.Path)
|
||||
if memoryLimit == "" {
|
||||
memoryLimit = fmt.Sprintf("%dM", dev.IsolatedDevice.MemoryLimit)
|
||||
}
|
||||
if smLimit == "" && dev.IsolatedDevice.SmUtilLimit > 0 {
|
||||
smLimit = fmt.Sprintf("%d", dev.IsolatedDevice.SmUtilLimit)
|
||||
}
|
||||
}
|
||||
if len(gpuIds) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
retEnvs := []*runtimeapi.KeyValue{}
|
||||
if len(gpuIds) > 0 {
|
||||
retEnvs = append(retEnvs, []*runtimeapi.KeyValue{
|
||||
{
|
||||
Key: "NVIDIA_VISIBLE_DEVICES",
|
||||
Value: strings.Join(gpuIds, ","),
|
||||
},
|
||||
{
|
||||
Key: "NVIDIA_DRIVER_CAPABILITIES",
|
||||
Value: "all",
|
||||
},
|
||||
{
|
||||
Key: "LD_PRELOAD",
|
||||
Value: options.HostOptions.HAMICoreLibvgpuPath,
|
||||
},
|
||||
{
|
||||
Key: "CUDA_DEVICE_MEMORY_LIMIT",
|
||||
Value: memoryLimit,
|
||||
},
|
||||
}...)
|
||||
if len(smLimit) > 0 {
|
||||
retEnvs = append(retEnvs, &runtimeapi.KeyValue{
|
||||
Key: "CUDA_DEVICE_SM_LIMIT",
|
||||
Value: smLimit,
|
||||
})
|
||||
}
|
||||
}
|
||||
return retEnvs, []*runtimeapi.Mount{
|
||||
{
|
||||
ContainerPath: options.HostOptions.HAMICoreLibvgpuPath,
|
||||
HostPath: options.HostOptions.HAMICoreLibvgpuPath,
|
||||
Readonly: true,
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,6 @@
|
||||
package container_device
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
@@ -24,7 +23,9 @@ import (
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
computeapi "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
hostapi "yunion.io/x/onecloud/pkg/apis/host"
|
||||
"yunion.io/x/onecloud/pkg/hostman/hostinfo"
|
||||
"yunion.io/x/onecloud/pkg/hostman/isolated_device"
|
||||
"yunion.io/x/onecloud/pkg/hostman/options"
|
||||
"yunion.io/x/onecloud/pkg/util/procutils"
|
||||
@@ -44,12 +45,12 @@ func newNvidiaMPSManager() *nvidiaMPSManager {
|
||||
return &nvidiaMPSManager{}
|
||||
}
|
||||
|
||||
func (m *nvidiaMPSManager) GetType() isolated_device.ContainerDeviceType {
|
||||
func (m *nvidiaMPSManager) GetRegisterType() isolated_device.ContainerDeviceType {
|
||||
return isolated_device.ContainerDeviceTypeNvidiaMps
|
||||
}
|
||||
|
||||
func (m *nvidiaMPSManager) ProbeDevices() ([]isolated_device.IDevice, error) {
|
||||
return getNvidiaMPSGpus(options.HostOptions.CudaMPSReplicas)
|
||||
return m.getNvidiaMPSGpus(options.HostOptions.CudaMPSReplicas)
|
||||
}
|
||||
|
||||
func (m *nvidiaMPSManager) NewDevices(dev *isolated_device.ContainerDevice) ([]isolated_device.IDevice, error) {
|
||||
@@ -60,7 +61,7 @@ func (m *nvidiaMPSManager) NewDevices(dev *isolated_device.ContainerDevice) ([]i
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return getNvidiaMPSGpusByDevPath(dev.VirtualNumber, dev.Path)
|
||||
return m.getNvidiaMPSGpusByDevPath(dev.VirtualNumber, dev.Path)
|
||||
}
|
||||
|
||||
func (m *nvidiaMPSManager) NewContainerDevices(input *hostapi.ContainerCreateInput, dev *hostapi.ContainerDevice) ([]*runtimeapi.Device, []*runtimeapi.Device, error) {
|
||||
@@ -81,9 +82,12 @@ func (m *nvidiaMPSManager) GetContainerExtraConfigures(devs []*hostapi.Container
|
||||
if dev.IsolatedDevice == nil {
|
||||
continue
|
||||
}
|
||||
if isolated_device.ContainerDeviceType(dev.IsolatedDevice.DeviceType) != isolated_device.ContainerDeviceTypeNvidiaMps {
|
||||
iDev := hostinfo.Instance().IsolatedDeviceMan.GetDeviceByCloudId(dev.IsolatedDevice.Id)
|
||||
devMan := iDev.GetContainerDeviceManager()
|
||||
if _, ok := devMan.(*nvidiaMPSManager); !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
gpuIds = append(gpuIds, dev.IsolatedDevice.Path)
|
||||
}
|
||||
if len(gpuIds) == 0 {
|
||||
@@ -116,6 +120,7 @@ func (m *nvidiaMPSManager) GetContainerExtraConfigures(devs []*hostapi.Container
|
||||
}
|
||||
|
||||
type nvidiaMPS struct {
|
||||
manager *nvidiaMPSManager
|
||||
*BaseDevice
|
||||
|
||||
MemSizeMB int
|
||||
@@ -145,6 +150,10 @@ func (c *nvidiaMPS) GetNvidiaMpsThreadPercentage() int {
|
||||
return c.ThreadPercentage
|
||||
}
|
||||
|
||||
func (dev *nvidiaMPS) GetContainerDeviceManager() isolated_device.IContainerDeviceManager {
|
||||
return dev.manager
|
||||
}
|
||||
|
||||
func parseMemSize(memTotalStr string) (int, error) {
|
||||
if !strings.HasSuffix(memTotalStr, " MiB") {
|
||||
return -1, errors.Errorf("unknown mem string suffix")
|
||||
@@ -153,9 +162,9 @@ func parseMemSize(memTotalStr string) (int, error) {
|
||||
return strconv.Atoi(memStr)
|
||||
}
|
||||
|
||||
func getNvidiaMPSGpusByDevPath(cudaMPSReplicas int, devPath string) ([]isolated_device.IDevice, error) {
|
||||
func (m *nvidiaMPSManager) getNvidiaMPSGpusByDevPath(cudaMPSReplicas int, devPath string) ([]isolated_device.IDevice, error) {
|
||||
configuredByDevPath = true
|
||||
pDev, err := NewPCIGPURenderBaseDevice(devPath, 0, isolated_device.ContainerDeviceTypeNvidiaMps)
|
||||
pDev, err := NewPCIGPURenderBaseDevice(devPath, 0, computeapi.GPU_TYPE, computeapi.DEVICE_SHARING_MODE_MPS)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "new PCIGPURenderBaseDevice")
|
||||
}
|
||||
@@ -200,21 +209,17 @@ func getNvidiaMPSGpusByDevPath(cudaMPSReplicas int, devPath string) ([]isolated_
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "GetPCIStrByAddr %s", gpuPciAddr)
|
||||
}
|
||||
|
||||
for i := 0; i < cudaMPSReplicas; i++ {
|
||||
dev := isolated_device.NewPCIDevice2(pciOutput[0])
|
||||
gpuDev := &nvidiaMPS{
|
||||
BaseDevice: NewBaseDevice(dev, isolated_device.ContainerDeviceTypeNvidiaMps, gpuId),
|
||||
MemSizeMB: memSize / cudaMPSReplicas,
|
||||
MemTotalMB: memSize,
|
||||
ThreadPercentage: 100 / cudaMPSReplicas,
|
||||
gpuIndex: index,
|
||||
}
|
||||
gpuDev.SetModelName(gpuName)
|
||||
devAddr := gpuDev.GetAddr()
|
||||
gpuDev.SetAddr(fmt.Sprintf("%s-%d", devAddr, i), devAddr)
|
||||
devs = append(devs, gpuDev)
|
||||
dev := isolated_device.NewPCIDevice2(pciOutput[0])
|
||||
gpuDev := &nvidiaMPS{
|
||||
manager: m,
|
||||
BaseDevice: NewBaseDevice(dev, computeapi.GPU_TYPE, gpuId, computeapi.DEVICE_SHARING_MODE_MPS, cudaMPSReplicas),
|
||||
MemSizeMB: memSize / cudaMPSReplicas,
|
||||
MemTotalMB: memSize,
|
||||
ThreadPercentage: 100 / cudaMPSReplicas,
|
||||
gpuIndex: index,
|
||||
}
|
||||
gpuDev.SetModelName(gpuName)
|
||||
devs = append(devs, gpuDev)
|
||||
}
|
||||
if len(devs) == 0 {
|
||||
return nil, nil
|
||||
@@ -222,7 +227,7 @@ func getNvidiaMPSGpusByDevPath(cudaMPSReplicas int, devPath string) ([]isolated_
|
||||
return devs, nil
|
||||
}
|
||||
|
||||
func getNvidiaMPSGpus(cudaMPSReplicas int) ([]isolated_device.IDevice, error) {
|
||||
func (m *nvidiaMPSManager) getNvidiaMPSGpus(cudaMPSReplicas int) ([]isolated_device.IDevice, error) {
|
||||
if configuredByDevPath {
|
||||
return nil, nil
|
||||
}
|
||||
@@ -257,20 +262,17 @@ func getNvidiaMPSGpus(cudaMPSReplicas int) ([]isolated_device.IDevice, error) {
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "GetPCIStrByAddr %s", gpuPciAddr)
|
||||
}
|
||||
for i := 0; i < cudaMPSReplicas; i++ {
|
||||
dev := isolated_device.NewPCIDevice2(pciOutput[0])
|
||||
gpuDev := &nvidiaMPS{
|
||||
BaseDevice: NewBaseDevice(dev, isolated_device.ContainerDeviceTypeNvidiaMps, gpuId),
|
||||
MemSizeMB: memSize / cudaMPSReplicas,
|
||||
MemTotalMB: memSize,
|
||||
ThreadPercentage: 100 / cudaMPSReplicas,
|
||||
gpuIndex: index,
|
||||
}
|
||||
gpuDev.SetModelName(gpuName)
|
||||
devAddr := gpuDev.GetAddr()
|
||||
gpuDev.SetAddr(fmt.Sprintf("%s-%d", devAddr, i), devAddr)
|
||||
devs = append(devs, gpuDev)
|
||||
dev := isolated_device.NewPCIDevice2(pciOutput[0])
|
||||
gpuDev := &nvidiaMPS{
|
||||
manager: m,
|
||||
BaseDevice: NewBaseDevice(dev, computeapi.GPU_TYPE, gpuId, computeapi.DEVICE_SHARING_MODE_MPS, cudaMPSReplicas),
|
||||
MemSizeMB: memSize / cudaMPSReplicas,
|
||||
MemTotalMB: memSize,
|
||||
ThreadPercentage: 100 / cudaMPSReplicas,
|
||||
gpuIndex: index,
|
||||
}
|
||||
gpuDev.SetModelName(gpuName)
|
||||
devs = append(devs, gpuDev)
|
||||
}
|
||||
if len(devs) == 0 {
|
||||
return nil, nil
|
||||
|
||||
@@ -22,6 +22,7 @@ import (
|
||||
"strings"
|
||||
|
||||
runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1"
|
||||
computeapi "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
@@ -40,7 +41,7 @@ func newVastaitechGPUManager() isolated_device.IContainerDeviceManager {
|
||||
return &vastaitechGPUManager{}
|
||||
}
|
||||
|
||||
func (v vastaitechGPUManager) GetType() isolated_device.ContainerDeviceType {
|
||||
func (v vastaitechGPUManager) GetRegisterType() isolated_device.ContainerDeviceType {
|
||||
return isolated_device.ContainerDeviceTypeVastaitechGpu
|
||||
}
|
||||
|
||||
@@ -56,7 +57,7 @@ var vastaitechRelatedDevices = map[string]string{
|
||||
VASTAITECH_VACC: "/dev/vacc%d",
|
||||
}
|
||||
|
||||
func (v vastaitechGPUManager) getRelatedDevices(index int) map[string]string {
|
||||
func (v *vastaitechGPUManager) getRelatedDevices(index int) map[string]string {
|
||||
devs := make(map[string]string)
|
||||
for key, devFmt := range vastaitechRelatedDevices {
|
||||
devs[key] = fmt.Sprintf(devFmt, index)
|
||||
@@ -64,12 +65,12 @@ func (v vastaitechGPUManager) getRelatedDevices(index int) map[string]string {
|
||||
return devs
|
||||
}
|
||||
|
||||
func (v vastaitechGPUManager) getDriRenderPrefix() string {
|
||||
func (v *vastaitechGPUManager) getDriRenderPrefix() string {
|
||||
return "/dev/dri/renderD"
|
||||
}
|
||||
|
||||
// getVastaitechDriStartIndexFromByPath 扫描 /dev/dri/by-path/,找到名称含 va_card 的 -render 链接对应的最小 renderD 编号
|
||||
func (v vastaitechGPUManager) getVastaitechDriStartIndexFromByPath() (int, error) {
|
||||
func (v *vastaitechGPUManager) getVastaitechDriStartIndexFromByPath() (int, error) {
|
||||
const byPathDir = "/dev/dri/by-path"
|
||||
entries, err := os.ReadDir(byPathDir)
|
||||
if err != nil {
|
||||
@@ -107,11 +108,11 @@ func (v vastaitechGPUManager) getVastaitechDriStartIndexFromByPath() (int, error
|
||||
return *minIdx, nil
|
||||
}
|
||||
|
||||
func (v vastaitechGPUManager) getDriStartIndex() (int, error) {
|
||||
func (v *vastaitechGPUManager) getDriStartIndex() (int, error) {
|
||||
return v.getVastaitechDriStartIndexFromByPath()
|
||||
}
|
||||
|
||||
func (v vastaitechGPUManager) getRelatedDeviceStartIndex(driPath string) (int, error) {
|
||||
func (v *vastaitechGPUManager) getRelatedDeviceStartIndex(driPath string) (int, error) {
|
||||
prefix := v.getDriRenderPrefix()
|
||||
if !strings.HasPrefix(driPath, prefix) {
|
||||
return -1, errors.Errorf("device path %q doesn't start with /dev/dri/renderD", driPath)
|
||||
@@ -132,7 +133,7 @@ func (v vastaitechGPUManager) getRelatedDeviceStartIndex(driPath string) (int, e
|
||||
return idx, nil
|
||||
}
|
||||
|
||||
func (v vastaitechGPUManager) NewDevices(dev *isolated_device.ContainerDevice) ([]isolated_device.IDevice, error) {
|
||||
func (v *vastaitechGPUManager) NewDevices(dev *isolated_device.ContainerDevice) ([]isolated_device.IDevice, error) {
|
||||
idx, err := v.getRelatedDeviceStartIndex(dev.Path)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "get related device start index")
|
||||
@@ -146,18 +147,15 @@ func (v vastaitechGPUManager) NewDevices(dev *isolated_device.ContainerDevice) (
|
||||
if err := CheckVirtualNumber(dev); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
gpuDevs := make([]isolated_device.IDevice, 0)
|
||||
for i := 0; i < dev.VirtualNumber; i++ {
|
||||
gpuDev, err := newVastaitechGPU(dev.Path, i)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "new CPH AMD GPU with index %d", i)
|
||||
}
|
||||
gpuDevs = append(gpuDevs, gpuDev)
|
||||
gpuDev, err := v.newVastaitechGPU(dev.Path, dev.VirtualNumber)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "new CPH AMD GPU")
|
||||
}
|
||||
return gpuDevs, nil
|
||||
|
||||
return []isolated_device.IDevice{gpuDev}, nil
|
||||
}
|
||||
|
||||
func (v vastaitechGPUManager) getCommonDevices() []*runtimeapi.Device {
|
||||
func (v *vastaitechGPUManager) getCommonDevices() []*runtimeapi.Device {
|
||||
vatools := "/dev/vatools"
|
||||
vaSync := "/dev/va_sync"
|
||||
devs := []*runtimeapi.Device{}
|
||||
@@ -171,7 +169,7 @@ func (v vastaitechGPUManager) getCommonDevices() []*runtimeapi.Device {
|
||||
return devs
|
||||
}
|
||||
|
||||
func (v vastaitechGPUManager) NewContainerDevices(input *hostapi.ContainerCreateInput, dev *hostapi.ContainerDevice) ([]*runtimeapi.Device, []*runtimeapi.Device, error) {
|
||||
func (v *vastaitechGPUManager) NewContainerDevices(input *hostapi.ContainerCreateInput, dev *hostapi.ContainerDevice) ([]*runtimeapi.Device, []*runtimeapi.Device, error) {
|
||||
driHostPath := dev.IsolatedDevice.Path
|
||||
idx, err := v.getRelatedDeviceStartIndex(driHostPath)
|
||||
if err != nil {
|
||||
@@ -195,22 +193,26 @@ func (v vastaitechGPUManager) NewContainerDevices(input *hostapi.ContainerCreate
|
||||
return devs, v.getCommonDevices(), nil
|
||||
}
|
||||
|
||||
func (v vastaitechGPUManager) ProbeDevices() ([]isolated_device.IDevice, error) {
|
||||
func (v *vastaitechGPUManager) ProbeDevices() ([]isolated_device.IDevice, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (v vastaitechGPUManager) GetContainerExtraConfigures(devs []*hostapi.ContainerDevice) ([]*runtimeapi.KeyValue, []*runtimeapi.Mount) {
|
||||
func (v *vastaitechGPUManager) GetContainerExtraConfigures(devs []*hostapi.ContainerDevice) ([]*runtimeapi.KeyValue, []*runtimeapi.Mount) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
type vastaitechGPU struct {
|
||||
*BaseDevice
|
||||
manager *vastaitechGPUManager
|
||||
}
|
||||
|
||||
func newVastaitechGPU(devPath string, index int) (*vastaitechGPU, error) {
|
||||
dev, err := NewPCIGPURenderBaseDevice(devPath, index, isolated_device.ContainerDeviceTypeVastaitechGpu)
|
||||
func (v *vastaitechGPUManager) newVastaitechGPU(devPath string, virtualNum int) (*vastaitechGPU, error) {
|
||||
dev, err := NewPCIGPURenderBaseDevice(devPath, virtualNum, computeapi.GPU_TYPE, computeapi.DEVICE_SHARING_MODE_UNLIMITED)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "new PCIGPURenderBaseDevice")
|
||||
}
|
||||
return &vastaitechGPU{BaseDevice: dev}, nil
|
||||
return &vastaitechGPU{
|
||||
BaseDevice: dev,
|
||||
manager: v,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -254,9 +254,9 @@ type sGPUBaseDevice struct {
|
||||
*SBaseDevice
|
||||
}
|
||||
|
||||
func newGPUBaseDevice(dev *PCIDevice, devType string) *sGPUBaseDevice {
|
||||
func newGPUBaseDevice(dev *PCIDevice, devType, sharingMode string) *sGPUBaseDevice {
|
||||
return &sGPUBaseDevice{
|
||||
SBaseDevice: NewBaseDevice(dev, devType),
|
||||
SBaseDevice: NewBaseDevice(dev, devType, sharingMode),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -332,9 +332,9 @@ type sGPUHPCDevice struct {
|
||||
*sGPUBaseDevice
|
||||
}
|
||||
|
||||
func NewGPUHPCDevice(dev *PCIDevice) *sGPUHPCDevice {
|
||||
func NewGPUHPCDevice(dev *PCIDevice, sharingMode string) *sGPUHPCDevice {
|
||||
gpuDev := &sGPUHPCDevice{
|
||||
sGPUBaseDevice: newGPUBaseDevice(dev, api.GPU_HPC_TYPE),
|
||||
sGPUBaseDevice: newGPUBaseDevice(dev, api.GPU_TYPE, api.DEVICE_SHARING_MODE_EXCLUSIVE),
|
||||
}
|
||||
return gpuDev
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import (
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/tristate"
|
||||
|
||||
api "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/hostman/guestman/desc"
|
||||
@@ -62,6 +63,9 @@ type CloudDeviceInfo struct {
|
||||
MpsThreadPercentage int `json:"mps_thread_percentage"`
|
||||
NumaNode int `json:"numa_node"`
|
||||
PcieInfo *api.IsolatedDevicePCIEInfo `json:"pcie_info"`
|
||||
VirtualNum int `json:"virtual_num"`
|
||||
HotPluggable bool `json:"hot_pluggable"`
|
||||
SharingMode string `json:"sharing_mode"`
|
||||
|
||||
// The frame rate limiter (FRL) configuration in frames per second
|
||||
FRL string `json:"frl"`
|
||||
@@ -110,10 +114,14 @@ type IDevice interface {
|
||||
GetVendorDeviceId() string
|
||||
GetAddr() string
|
||||
GetDeviceType() string
|
||||
GetSharingMode() string
|
||||
GetModelName() string
|
||||
CustomProbe(idx int) error
|
||||
SetDeviceInfo(info CloudDeviceInfo)
|
||||
DetectByAddr() error
|
||||
GetVirtualNum() int
|
||||
GetContainerDeviceManager() IContainerDeviceManager
|
||||
HotPluggable() bool
|
||||
|
||||
GetPassthroughOptions() map[string]string
|
||||
GetPassthroughCmd(index int) string
|
||||
@@ -161,11 +169,12 @@ type IsolatedDeviceManager interface {
|
||||
GetDevices() []IDevice
|
||||
GetDeviceByIdent(vendorDevId, addr, mdevId string) IDevice
|
||||
GetDeviceByAddr(addr string) IDevice
|
||||
ProbePCIDevices(skipGPUs, skipUSBs, skipCustomDevs bool, sriovNics, ovsOffloadNics []HostNic, nvmePciDisks, amdVgpuPFs, nvidiaVgpuPFs []string, enableCudaMps, enableContainerNPU, enableWhitelist bool)
|
||||
GetDeviceByCloudId(cloudId string) IDevice
|
||||
ProbePCIDevices(opts *SIsolatedDeviceProbeOptions)
|
||||
StartDetachTask()
|
||||
BatchCustomProbe()
|
||||
AppendDetachedDevice(dev *CloudDeviceInfo)
|
||||
GetQemuParams(devAddrs []string) *QemuParams
|
||||
//GetQemuParams(devAddrs []string) *QemuParams
|
||||
CheckDevIsNeedUpdate(dev IDevice, devInfo *CloudDeviceInfo) bool
|
||||
}
|
||||
|
||||
@@ -233,10 +242,12 @@ func (man *isolatedDeviceManager) probeContainerDevices() {
|
||||
}
|
||||
}
|
||||
|
||||
func (man *isolatedDeviceManager) probeContainerNvidiaGPUs(enableCudaMps bool) {
|
||||
func (man *isolatedDeviceManager) probeContainerNvidiaGPUs(enableCudaHAMI, enableCudaMps bool) {
|
||||
devType := ContainerDeviceTypeNvidiaGpu
|
||||
if enableCudaMps {
|
||||
devType = ContainerDeviceTypeNvidiaMps
|
||||
} else if enableCudaHAMI {
|
||||
devType = ContainerDeviceTypeNvidiaHAMI
|
||||
}
|
||||
|
||||
devman, err := GetContainerDeviceManager(devType)
|
||||
@@ -301,7 +312,7 @@ func (man *isolatedDeviceManager) probeGPUS(skipGPUs bool, amdVgpuPFs, nvidiaVgp
|
||||
}
|
||||
}
|
||||
for idx, gpu := range gpus {
|
||||
man.devices = append(man.devices, NewGPUHPCDevice(gpu))
|
||||
man.devices = append(man.devices, NewGPUHPCDevice(gpu, api.DEVICE_SHARING_MODE_EXCLUSIVE))
|
||||
log.Infof("Add GPU device: %d => %#v", idx, gpu)
|
||||
}
|
||||
}
|
||||
@@ -441,12 +452,27 @@ func (man *isolatedDeviceManager) probeNVIDIAVgpus(nvidiaVgpuPFs []string) {
|
||||
}
|
||||
}
|
||||
|
||||
func (man *isolatedDeviceManager) ProbePCIDevices(skipGPUs, skipUSBs, skipCustomDevs bool, sriovNics, ovsOffloadNics []HostNic, nvmePciDisks, amdVgpuPFs, nvidiaVgpuPFs []string, enableCudaMps, enableContainerNPU, enableWhitelist bool) {
|
||||
type SIsolatedDeviceProbeOptions struct {
|
||||
SkipGPUs bool
|
||||
SkipUSBs bool
|
||||
SkipCustomDevs bool
|
||||
|
||||
EnableCudaHAMI bool
|
||||
EnableCudaMps bool
|
||||
EnableContainerNPU bool
|
||||
EnableWhitelist bool
|
||||
|
||||
SriovNics, OvsOffloadNics []HostNic
|
||||
|
||||
NvmePciDisks, AmdVgpuPFs, NvidiaVgpuPFs []string
|
||||
}
|
||||
|
||||
func (man *isolatedDeviceManager) ProbePCIDevices(opts *SIsolatedDeviceProbeOptions) {
|
||||
man.devices = make([]IDevice, 0)
|
||||
if man.host.IsContainerHost() {
|
||||
man.probeContainerDevices()
|
||||
man.probeContainerNvidiaGPUs(enableCudaMps)
|
||||
man.probeContainerAscendNPUs(enableContainerNPU)
|
||||
man.probeContainerNvidiaGPUs(opts.EnableCudaHAMI, opts.EnableCudaMps)
|
||||
man.probeContainerAscendNPUs(opts.EnableContainerNPU)
|
||||
} else {
|
||||
devModels, err := man.getCustomIsolatedDeviceModels()
|
||||
if err != nil {
|
||||
@@ -454,21 +480,22 @@ func (man *isolatedDeviceManager) ProbePCIDevices(skipGPUs, skipUSBs, skipCustom
|
||||
man.host.AppendError(fmt.Sprintf("get custom isolated device devModels %s", err.Error()), "isolated_devices", "", "")
|
||||
return
|
||||
}
|
||||
man.probeUSBs(skipUSBs)
|
||||
man.probeCustomPCIDevs(skipCustomDevs, devModels, GpuClassCodes)
|
||||
man.probeSRIOVNics(sriovNics)
|
||||
man.probeOffloadNICS(ovsOffloadNics)
|
||||
man.probeAMDVgpus(amdVgpuPFs)
|
||||
man.probeNVIDIAVgpus(nvidiaVgpuPFs)
|
||||
man.probeGPUS(skipGPUs, amdVgpuPFs, nvidiaVgpuPFs, enableWhitelist, devModels)
|
||||
man.probeUSBs(opts.SkipUSBs)
|
||||
man.probeCustomPCIDevs(opts.SkipCustomDevs, devModels, GpuClassCodes)
|
||||
man.probeSRIOVNics(opts.SriovNics)
|
||||
man.probeOffloadNICS(opts.OvsOffloadNics)
|
||||
man.probeAMDVgpus(opts.AmdVgpuPFs)
|
||||
man.probeNVIDIAVgpus(opts.NvidiaVgpuPFs)
|
||||
man.probeGPUS(opts.SkipGPUs, opts.AmdVgpuPFs, opts.NvidiaVgpuPFs, opts.EnableWhitelist, devModels)
|
||||
}
|
||||
}
|
||||
|
||||
type IsolatedDeviceModel struct {
|
||||
DevType string `json:"dev_type"`
|
||||
VendorId string `json:"vendor_id"`
|
||||
DeviceId string `json:"device_id"`
|
||||
Model string `json:"model"`
|
||||
DevType string `json:"dev_type"`
|
||||
VendorId string `json:"vendor_id"`
|
||||
DeviceId string `json:"device_id"`
|
||||
Model string `json:"model"`
|
||||
HotPluggable tristate.TriState `json:"hot_pluggable"`
|
||||
}
|
||||
|
||||
func (man *isolatedDeviceManager) getCustomIsolatedDeviceModels() ([]IsolatedDeviceModel, error) {
|
||||
@@ -571,6 +598,15 @@ func (man *isolatedDeviceManager) CheckDevIsNeedUpdate(dev IDevice, devInfo *Clo
|
||||
return true
|
||||
}
|
||||
}
|
||||
if dev.GetVirtualNum() != devInfo.VirtualNum {
|
||||
return true
|
||||
}
|
||||
if dev.HotPluggable() != devInfo.HotPluggable {
|
||||
return true
|
||||
}
|
||||
if dev.GetSharingMode() != devInfo.SharingMode {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -616,6 +652,15 @@ func (man *isolatedDeviceManager) GetDeviceByAddr(addr string) IDevice {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (man *isolatedDeviceManager) GetDeviceByCloudId(cloudId string) IDevice {
|
||||
for _, dev := range man.devices {
|
||||
if dev.GetCloudId() == cloudId {
|
||||
return dev
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (man *isolatedDeviceManager) BatchCustomProbe() {
|
||||
for i, dev := range man.devices {
|
||||
if err := dev.CustomProbe(i); err != nil {
|
||||
@@ -661,10 +706,6 @@ func (man *isolatedDeviceManager) StartDetachTask() {
|
||||
}()
|
||||
}
|
||||
|
||||
func (man *isolatedDeviceManager) GetQemuParams(devAddrs []string) *QemuParams {
|
||||
return getQemuParams(man, devAddrs)
|
||||
}
|
||||
|
||||
type SBaseDevice struct {
|
||||
dev *PCIDevice
|
||||
originAddr string
|
||||
@@ -672,13 +713,15 @@ type SBaseDevice struct {
|
||||
hostId string
|
||||
guestId string
|
||||
devType string
|
||||
sharingMode string
|
||||
detectedOnHost bool
|
||||
}
|
||||
|
||||
func NewBaseDevice(dev *PCIDevice, devType string) *SBaseDevice {
|
||||
func NewBaseDevice(dev *PCIDevice, devType, sharingMode string) *SBaseDevice {
|
||||
return &SBaseDevice{
|
||||
dev: dev,
|
||||
devType: devType,
|
||||
dev: dev,
|
||||
devType: devType,
|
||||
sharingMode: sharingMode,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -763,6 +806,10 @@ func (dev *SBaseDevice) GetDeviceType() string {
|
||||
return dev.devType
|
||||
}
|
||||
|
||||
func (dev *SBaseDevice) GetSharingMode() string {
|
||||
return dev.sharingMode
|
||||
}
|
||||
|
||||
func (dev *SBaseDevice) GetPfName() string {
|
||||
return ""
|
||||
}
|
||||
@@ -822,6 +869,18 @@ func (dev *SBaseDevice) GetGuestId() string {
|
||||
return dev.guestId
|
||||
}
|
||||
|
||||
func (dev *SBaseDevice) GetVirtualNum() int {
|
||||
return 1
|
||||
}
|
||||
|
||||
func (dev *SBaseDevice) HotPluggable() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (dev *SBaseDevice) GetContainerDeviceManager() IContainerDeviceManager {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (dev *SBaseDevice) GetNvidiaMpsMemoryLimit() int {
|
||||
return -1
|
||||
}
|
||||
@@ -856,6 +915,9 @@ func GetApiResourceData(dev IDevice) *jsonutils.JSONDict {
|
||||
"addr": dev.GetAddr(),
|
||||
"model": dev.GetModelName(),
|
||||
"vendor_device_id": dev.GetVendorDeviceId(),
|
||||
"virtual_num": dev.GetVirtualNum(),
|
||||
"hot_pluggable": dev.HotPluggable(),
|
||||
"sharing_mode": dev.GetSharingMode(),
|
||||
}
|
||||
detected := false
|
||||
if err := dev.DetectByAddr(); err == nil {
|
||||
@@ -868,9 +930,9 @@ func GetApiResourceData(dev IDevice) *jsonutils.JSONDict {
|
||||
if len(dev.GetHostId()) != 0 {
|
||||
data["host_id"] = dev.GetHostId()
|
||||
}
|
||||
if len(dev.GetGuestId()) != 0 {
|
||||
data["guest_id"] = dev.GetGuestId()
|
||||
}
|
||||
//if len(dev.GetGuestId()) != 0 {
|
||||
// data["guest_id"] = dev.GetGuestId()
|
||||
//}
|
||||
if len(dev.GetWireId()) != 0 {
|
||||
data["wire_id"] = dev.GetWireId()
|
||||
}
|
||||
@@ -891,7 +953,6 @@ func GetApiResourceData(dev IDevice) *jsonutils.JSONDict {
|
||||
} else {
|
||||
log.Debugf("failed get dev %s numa node %s", dev.GetAddr(), err)
|
||||
}
|
||||
|
||||
if dev.GetMdevId() != "" {
|
||||
data["mdev_id"] = dev.GetMdevId()
|
||||
}
|
||||
@@ -1083,52 +1144,3 @@ func bashOutput(cmd string) ([]string, error) {
|
||||
func bashRawOutput(cmd string) ([]string, error) {
|
||||
return bashCmdOutput(cmd, false)
|
||||
}
|
||||
|
||||
type QemuParams struct {
|
||||
Cpu string
|
||||
Vga string
|
||||
Devices []string
|
||||
}
|
||||
|
||||
func getQemuParams(man *isolatedDeviceManager, devAddrs []string) *QemuParams {
|
||||
if len(devAddrs) == 0 {
|
||||
return nil
|
||||
}
|
||||
devCmds := []string{}
|
||||
cpuCmd := DEFAULT_CPU_CMD
|
||||
vgaCmd := DEFAULT_VGA_CMD
|
||||
// group by device type firstly
|
||||
devices := make(map[string][]IDevice, 0)
|
||||
for _, addr := range devAddrs {
|
||||
dev := man.GetDeviceByAddr(addr)
|
||||
if dev == nil {
|
||||
log.Warningf("IsolatedDeviceManager not found dev %#v, ignore it!", addr)
|
||||
continue
|
||||
}
|
||||
devType := dev.GetDeviceType()
|
||||
if _, ok := devices[devType]; !ok {
|
||||
devices[devType] = []IDevice{dev}
|
||||
} else {
|
||||
devices[devType] = append(devices[devType], dev)
|
||||
}
|
||||
}
|
||||
|
||||
for devType, devs := range devices {
|
||||
log.Debugf("get devices %s command", devType)
|
||||
for idx, dev := range devs {
|
||||
devCmds = append(devCmds, getDeviceCmd(dev, idx))
|
||||
if dev.GetVGACmd() != vgaCmd && dev.GetDeviceType() == api.GPU_VGA_TYPE {
|
||||
vgaCmd = dev.GetVGACmd()
|
||||
}
|
||||
if dev.GetCPUCmd() != cpuCmd {
|
||||
cpuCmd = dev.GetCPUCmd()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return &QemuParams{
|
||||
Cpu: cpuCmd,
|
||||
Vga: vgaCmd,
|
||||
Devices: devCmds,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,7 +100,7 @@ func getSRIOVNics(hostNics []HostNic) ([]*sSRIOVNicDevice, error) {
|
||||
|
||||
func NewSRIOVNicDevice(dev *PCIDevice, devType, wireId, pfName string, virtfn int, isInfinibandNic bool) *sSRIOVNicDevice {
|
||||
return &sSRIOVNicDevice{
|
||||
sSRIOVBaseDevice: newSRIOVBaseDevice(dev, devType),
|
||||
sSRIOVBaseDevice: newSRIOVBaseDevice(dev, devType, api.DEVICE_SHARING_MODE_SRIOV),
|
||||
WireId: wireId,
|
||||
pfName: pfName,
|
||||
virtfn: virtfn,
|
||||
|
||||
@@ -30,11 +30,12 @@ import (
|
||||
)
|
||||
|
||||
type sNVIDIAVgpuDevice struct {
|
||||
pfDev *PCIDevice
|
||||
cloudId string
|
||||
hostId string
|
||||
guestId string
|
||||
devType string
|
||||
pfDev *PCIDevice
|
||||
cloudId string
|
||||
hostId string
|
||||
guestId string
|
||||
devType string
|
||||
sharingMode string
|
||||
|
||||
mdevId string
|
||||
model string
|
||||
@@ -85,6 +86,10 @@ func (dev *sNVIDIAVgpuDevice) GetDeviceType() string {
|
||||
return dev.devType
|
||||
}
|
||||
|
||||
func (dev *sNVIDIAVgpuDevice) GetSharingMode() string {
|
||||
return dev.sharingMode
|
||||
}
|
||||
|
||||
func (dev *sNVIDIAVgpuDevice) GetModelName() string {
|
||||
modelName := dev.pfDev.ModelName
|
||||
if dev.pfDev.ModelName == "" {
|
||||
@@ -101,6 +106,18 @@ func (dev *sNVIDIAVgpuDevice) GetDevicePath() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (dev *sNVIDIAVgpuDevice) GetVirtualNum() int {
|
||||
return 1
|
||||
}
|
||||
|
||||
func (dev *sNVIDIAVgpuDevice) HotPluggable() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (dev *sNVIDIAVgpuDevice) GetContainerDeviceManager() IContainerDeviceManager {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (dev *sNVIDIAVgpuDevice) GetNvidiaMpsMemoryLimit() int {
|
||||
return -1
|
||||
}
|
||||
@@ -265,13 +282,14 @@ func (dev *sNVIDIAVgpuDevice) GetPCIEInfo() *compute.IsolatedDevicePCIEInfo {
|
||||
return dev.pfDev.PCIEInfo
|
||||
}
|
||||
|
||||
func NewNvidiaVgpuDevice(dev *PCIDevice, devType, mdevId, model string, profile map[string]string) *sNVIDIAVgpuDevice {
|
||||
func NewNvidiaVgpuDevice(dev *PCIDevice, devType, sharingMode, mdevId, model string, profile map[string]string) *sNVIDIAVgpuDevice {
|
||||
return &sNVIDIAVgpuDevice{
|
||||
pfDev: dev,
|
||||
devType: devType,
|
||||
mdevId: mdevId,
|
||||
model: model,
|
||||
profile: profile,
|
||||
pfDev: dev,
|
||||
devType: devType,
|
||||
sharingMode: sharingMode,
|
||||
mdevId: mdevId,
|
||||
model: model,
|
||||
profile: profile,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -318,7 +336,7 @@ func getNvidiaVGpus(gpuPF string) ([]*sNVIDIAVgpuDevice, error) {
|
||||
profile[key] = strings.TrimSpace(value)
|
||||
}
|
||||
}
|
||||
mdev := NewNvidiaVgpuDevice(pfDev, compute.LEGACY_VGPU_TYPE, files[i].Name(), model, profile)
|
||||
mdev := NewNvidiaVgpuDevice(pfDev, compute.GPU_TYPE, compute.DEVICE_SHARING_MODE_MDEV, files[i].Name(), model, profile)
|
||||
nvidiaVgpus = append(nvidiaVgpus, mdev)
|
||||
}
|
||||
return nvidiaVgpus, nil
|
||||
|
||||
@@ -48,7 +48,7 @@ func (dev *sNVMEDevice) GetNVMESizeMB() int {
|
||||
|
||||
func newNVMEDevice(dev *PCIDevice, devType string, sizeMB int) *sNVMEDevice {
|
||||
return &sNVMEDevice{
|
||||
SBaseDevice: NewBaseDevice(dev, devType),
|
||||
SBaseDevice: NewBaseDevice(dev, devType, api.DEVICE_SHARING_MODE_EXCLUSIVE),
|
||||
sizeMB: sizeMB,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,10 +21,14 @@ import (
|
||||
"yunion.io/x/jsonutils"
|
||||
"yunion.io/x/pkg/errors"
|
||||
"yunion.io/x/pkg/utils"
|
||||
|
||||
computeapi "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
)
|
||||
|
||||
type sGeneralPCIDevice struct {
|
||||
*SBaseDevice
|
||||
|
||||
hotPluggable bool
|
||||
}
|
||||
|
||||
func (dev *sGeneralPCIDevice) GetVGACmd() string {
|
||||
@@ -39,9 +43,14 @@ func (dev *sGeneralPCIDevice) GetQemuId() string {
|
||||
return fmt.Sprintf("dev_%s", strings.ReplaceAll(dev.GetAddr(), ":", "_"))
|
||||
}
|
||||
|
||||
func newGeneralPCIDevice(dev *PCIDevice, devType string) *sGeneralPCIDevice {
|
||||
func (dev *sGeneralPCIDevice) HotPluggable() bool {
|
||||
return dev.hotPluggable
|
||||
}
|
||||
|
||||
func newGeneralPCIDevice(dev *PCIDevice, devType string, hotPluggable bool) *sGeneralPCIDevice {
|
||||
return &sGeneralPCIDevice{
|
||||
SBaseDevice: NewBaseDevice(dev, devType),
|
||||
SBaseDevice: NewBaseDevice(dev, devType, computeapi.DEVICE_SHARING_MODE_EXCLUSIVE),
|
||||
hotPluggable: hotPluggable,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,7 +80,7 @@ func getPassthroughPCIDevs(devModel IsolatedDeviceModel, filteredCodes []string)
|
||||
errs = append(errs, errors.Wrapf(err, "get dev %s iommu group devices by model: %s", dev.Addr, jsonutils.Marshal(devModel)))
|
||||
continue
|
||||
}
|
||||
devs = append(devs, newGeneralPCIDevice(dev, devModel.DevType))
|
||||
devs = append(devs, newGeneralPCIDevice(dev, devModel.DevType, devModel.HotPluggable.Bool()))
|
||||
}
|
||||
return devs, errors.NewAggregate(errs)
|
||||
}
|
||||
|
||||
@@ -70,9 +70,9 @@ func detectSRIOVDevice(vfBDF string) (*PCIDevice, error) {
|
||||
return dev, nil
|
||||
}
|
||||
|
||||
func newSRIOVBaseDevice(dev *PCIDevice, devType string) *sSRIOVBaseDevice {
|
||||
func newSRIOVBaseDevice(dev *PCIDevice, devType, sharingMode string) *sSRIOVBaseDevice {
|
||||
return &sSRIOVBaseDevice{
|
||||
SBaseDevice: NewBaseDevice(dev, devType),
|
||||
SBaseDevice: NewBaseDevice(dev, devType, sharingMode),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -32,9 +32,9 @@ type sSRIOVGpuDevice struct {
|
||||
*sSRIOVBaseDevice
|
||||
}
|
||||
|
||||
func NewSRIOVGpuDevice(dev *PCIDevice, devType string) *sSRIOVGpuDevice {
|
||||
func NewSRIOVGpuDevice(dev *PCIDevice, devType, sharingMode string) *sSRIOVGpuDevice {
|
||||
return &sSRIOVGpuDevice{
|
||||
sSRIOVBaseDevice: newSRIOVBaseDevice(dev, devType),
|
||||
sSRIOVBaseDevice: newSRIOVBaseDevice(dev, devType, sharingMode),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ func getSRIOVGpus(gpuPF string) ([]*sSRIOVGpuDevice, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
sriovGPUs = append(sriovGPUs, NewSRIOVGpuDevice(vfDev, compute.SRIOV_VGPU_TYPE))
|
||||
sriovGPUs = append(sriovGPUs, NewSRIOVGpuDevice(vfDev, compute.GPU_TYPE, compute.DEVICE_SHARING_MODE_SRIOV))
|
||||
}
|
||||
}
|
||||
return sriovGPUs, err
|
||||
|
||||
@@ -39,7 +39,7 @@ type sUSBDevice struct {
|
||||
// TODO: rename PCIDevice
|
||||
func newUSBDevice(dev *PCIDevice, lsusbLine *sLsusbLine) *sUSBDevice {
|
||||
return &sUSBDevice{
|
||||
SBaseDevice: NewBaseDevice(dev, api.USB_TYPE),
|
||||
SBaseDevice: NewBaseDevice(dev, api.USB_TYPE, api.DEVICE_SHARING_MODE_EXCLUSIVE),
|
||||
lsusbLine: lsusbLine,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -269,9 +269,12 @@ type SHostOptions struct {
|
||||
CudaMPSLogDirectory string `help:"cuda mps log dir" default:"/tmp/nvidia-mps/log"`
|
||||
CudaMPSReplicas int `help:"cuda mps replicas" default:"10"`
|
||||
|
||||
EnableCudaHAMI bool `help:"enable cuda hami" default:"true"`
|
||||
HAMICoreLibvgpuPath string `help:"hami core libvgpu.so path" default:"/opt/cloud/hami/libvgpu.so"`
|
||||
|
||||
SkipCheckKernelMods []string `help:"skip check kernel modules"`
|
||||
|
||||
EnableContainerAscendNPU bool `help:"enable container npu" default:"false"`
|
||||
EnableContainerAscendNPU bool `help:"enable container npu" default:"true"`
|
||||
|
||||
EnableDirtyRecoverySeconds int `help:"Seconds to delay enable dirty guests recovery feature, default 15 minutes" default:"900"`
|
||||
EnableContainerCniPortmap bool `help:"Use container cni portmap plugin" default:"false"`
|
||||
|
||||
@@ -33,12 +33,20 @@ func init() {
|
||||
type localLoopDiskManager struct {
|
||||
}
|
||||
|
||||
func (l localLoopDiskManager) GetType() isolated_device.ContainerDeviceType {
|
||||
func (l localLoopDiskManager) GetRegisterType() isolated_device.ContainerDeviceType {
|
||||
return api.CONTAINER_STORAGE_LOCAL_RAW
|
||||
}
|
||||
|
||||
func (m *localLoopDiskManager) GetDevType() string {
|
||||
return api.GPU_TYPE
|
||||
}
|
||||
|
||||
func (m *localLoopDiskManager) GetSharingMode() string {
|
||||
return api.DEVICE_SHARING_MODE_UNLIMITED
|
||||
}
|
||||
|
||||
func (l localLoopDiskManager) NewDevices(dev *isolated_device.ContainerDevice) ([]isolated_device.IDevice, error) {
|
||||
return nil, errors.Errorf("%s storage doesn't support NewDevices", l.GetType())
|
||||
return nil, errors.Errorf("%s storage doesn't support NewDevices", l.GetRegisterType())
|
||||
}
|
||||
|
||||
func (l localLoopDiskManager) NewContainerDevices(_ *hostapi.ContainerCreateInput, input *hostapi.ContainerDevice) ([]*runtimeapi.Device, []*runtimeapi.Device, error) {
|
||||
|
||||
@@ -87,7 +87,7 @@ func (man *SLLMSkuBaseManager) ValidateCreateData(ctx context.Context, userCred
|
||||
if input.Devices != nil {
|
||||
for i := range *input.Devices {
|
||||
if (*input.Devices)[i].DevType == "" {
|
||||
(*input.Devices)[i].DevType = computeapi.CONTAINER_DEV_NVIDIA_GPU_SHARE
|
||||
(*input.Devices)[i].DevType = computeapi.GPU_TYPE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,15 +20,27 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
IsolatedDevices modulebase.ResourceManager
|
||||
IsolatedDevices modulebase.ResourceManager
|
||||
ServerIsolatedDevices modulebase.JointResourceManager
|
||||
)
|
||||
|
||||
func init() {
|
||||
IsolatedDevices = modules.NewComputeManager("isolated_device", "isolated_devices",
|
||||
[]string{"ID", "Dev_type",
|
||||
[]string{"ID", "Dev_type", "Sharing_mode",
|
||||
"Model", "Addr", "Vendor_device_id", "Mdev_id",
|
||||
"Host_id", "Host", "numa_node",
|
||||
"Guest_id", "Guest", "Guest_status", "Device_path", "Render_path", "PCIE_Info", "Index", "Device_minor"},
|
||||
[]string{})
|
||||
modules.RegisterCompute(&IsolatedDevices)
|
||||
|
||||
ServerIsolatedDevices = modules.NewJointComputeManager(
|
||||
"guestisolateddevice",
|
||||
"guestisolateddevices",
|
||||
[]string{"Guest_ID", "Guest", "Isolated_device_ID", "Index", "Dev_type", "Sharing_mode",
|
||||
"Device_memory_size", "Sm_util_limit", "Network_index", "Disk_index"},
|
||||
[]string{},
|
||||
&Servers,
|
||||
&IsolatedDevices,
|
||||
)
|
||||
modules.RegisterCompute(&ServerIsolatedDevices)
|
||||
}
|
||||
|
||||
@@ -43,6 +43,35 @@ func (o *DeviceListOptions) Params() (jsonutils.JSONObject, error) {
|
||||
return options.ListStructToParams(o)
|
||||
}
|
||||
|
||||
type ServerDeviceListOptions struct {
|
||||
DeviceListOptions
|
||||
IsolateDeviceIds []string `json:"isolate_device_ids"`
|
||||
}
|
||||
|
||||
func (o *ServerDeviceListOptions) Params() (jsonutils.JSONObject, error) {
|
||||
return options.ListStructToParams(o)
|
||||
}
|
||||
|
||||
type DeviceCreateOptions struct {
|
||||
options.BaseCreateOptions
|
||||
|
||||
HostId string
|
||||
DevType string
|
||||
SharingMode string
|
||||
Model string
|
||||
HotPluggable bool
|
||||
Addr string
|
||||
DevicePath string
|
||||
VendorDeviceId string
|
||||
MemorySize int
|
||||
VirtualNum int
|
||||
NumaNode int
|
||||
}
|
||||
|
||||
func (o *DeviceCreateOptions) Params() (jsonutils.JSONObject, error) {
|
||||
return jsonutils.Marshal(o), nil
|
||||
}
|
||||
|
||||
type DeviceShowOptions struct {
|
||||
options.BaseIdOptions
|
||||
}
|
||||
|
||||
@@ -80,6 +80,7 @@ type ServerListOptions struct {
|
||||
|
||||
WithUserMeta *bool `help:"filter by user metadata" negative:"without_user_meta"`
|
||||
|
||||
IsolateDeviceId string `help:"filter guest with isolated device id" json:"isolate_device_id"`
|
||||
WithHost *bool `help:"filter guest with host or not" negative:"without_host"`
|
||||
SnapshotpolicyId string `help:"filter guest with snapshotpolicy or not" json:"snapshotpolicy_id"`
|
||||
BindingDisksSnapshotpolicy *bool `help:"filter guest with disks binding snapshotpolicy or not" negative:"no-binding-disks-snapshotpolicy" json:"binding_disks_snapshotpolicy"`
|
||||
|
||||
@@ -17,6 +17,7 @@ package predicates
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"path"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/scheduler/core"
|
||||
@@ -61,36 +62,35 @@ func (f *IsolatedDevicePredicate) PreExecute(ctx context.Context, u *core.Unit,
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (f *IsolatedDevicePredicate) getIsolatedDeviceCountByType(getter core.CandidatePropertyGetter, devType string) int {
|
||||
devs := getter.UnusedIsolatedDevicesByType(devType)
|
||||
if devType != compute.CONTAINER_DEV_NVIDIA_MPS && devType != compute.CONTAINER_DEV_NVIDIA_GPU_SHARE {
|
||||
return len(devs)
|
||||
} else {
|
||||
devMap := map[string]struct{}{}
|
||||
for _, dev := range devs {
|
||||
devMap[dev.DevicePath] = struct{}{}
|
||||
func (f *IsolatedDevicePredicate) getIsolatedDeviceCountBySharingMode(sharingMode string, devs []*core.IsolatedDeviceDesc) int {
|
||||
if sharingMode == compute.DEVICE_SHARING_MODE_HAMI {
|
||||
ret := 0
|
||||
for i := range devs {
|
||||
ret += devs[i].AvailableMemorySize()
|
||||
}
|
||||
return len(devMap)
|
||||
return ret
|
||||
}
|
||||
ret := 0
|
||||
for i := range devs {
|
||||
ret += devs[i].AvailableNum()
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// countDevicesWithMinMemory counts free devices of the given dev_type whose
|
||||
// MemorySize satisfies the minimum requirement. Devices with MemorySize == 0
|
||||
// are treated as "unknown" and pass through (so newly-introduced rows that
|
||||
// haven't been backfilled yet don't accidentally exclude every host).
|
||||
// For NVIDIA_MPS / NVIDIA_GPU_SHARE the count is deduplicated by DevicePath,
|
||||
// matching getIsolatedDeviceCountByType.
|
||||
func (f *IsolatedDevicePredicate) countDevicesWithMinMemory(getter core.CandidatePropertyGetter, devType string, minMemoryMb int) int {
|
||||
devs := getter.UnusedIsolatedDevicesByType(devType)
|
||||
isShared := devType == compute.CONTAINER_DEV_NVIDIA_MPS || devType == compute.CONTAINER_DEV_NVIDIA_GPU_SHARE
|
||||
return countDevicesWithMinMemoryFromList(devs, isShared, minMemoryMb)
|
||||
// countDevicesWithMinMemory counts available capacity for devices of the given
|
||||
// dev_type whose MemorySize satisfies the minimum requirement. Devices with
|
||||
// MemorySize == 0 are treated as "unknown" and pass through for non-HAMI modes
|
||||
// so rows that have not been backfilled yet do not exclude every host.
|
||||
func (f *IsolatedDevicePredicate) countDevicesWithMinMemory(getter core.CandidatePropertyGetter, devType, sharingMode string, minMemoryMb int) int {
|
||||
devs := getter.AvailableIsolatedDevicesByTypeSharingMode(devType, sharingMode)
|
||||
return countDevicesWithMinMemoryFromList(devs, sharingMode, minMemoryMb)
|
||||
}
|
||||
|
||||
// countDevicesWithMinMemoryFromList is the pure-function core of the memory
|
||||
// fit count, factored out for unit testing. Callers pass an already-filtered
|
||||
// list (typically by dev_type).
|
||||
func countDevicesWithMinMemoryFromList(devs []*core.IsolatedDeviceDesc, isShared bool, minMemoryMb int) int {
|
||||
if !isShared {
|
||||
func countDevicesWithMinMemoryFromList(devs []*core.IsolatedDeviceDesc, sharingMode string, minMemoryMb int) int {
|
||||
if sharingMode != compute.DEVICE_SHARING_MODE_HAMI {
|
||||
n := 0
|
||||
for _, d := range devs {
|
||||
if d.MemorySize > 0 && d.MemorySize < minMemoryMb {
|
||||
@@ -100,14 +100,43 @@ func countDevicesWithMinMemoryFromList(devs []*core.IsolatedDeviceDesc, isShared
|
||||
}
|
||||
return n
|
||||
}
|
||||
seen := map[string]struct{}{}
|
||||
n := 0
|
||||
for _, d := range devs {
|
||||
if d.MemorySize > 0 && d.MemorySize < minMemoryMb {
|
||||
if d.AvailableMemorySize() < minMemoryMb {
|
||||
continue
|
||||
}
|
||||
seen[d.DevicePath] = struct{}{}
|
||||
n++
|
||||
}
|
||||
return len(seen)
|
||||
return n
|
||||
}
|
||||
|
||||
func filterDevicesByTypeSharingMode(devs []*core.IsolatedDeviceDesc, devType, sharingMode string) []*core.IsolatedDeviceDesc {
|
||||
ret := make([]*core.IsolatedDeviceDesc, 0)
|
||||
for _, dev := range devs {
|
||||
if devType != "" && devType != dev.DevType {
|
||||
continue
|
||||
}
|
||||
if sharingMode != "" && dev.SharingMode != sharingMode {
|
||||
continue
|
||||
}
|
||||
ret = append(ret, dev)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func isolatedDeviceRequestAmount(dev *compute.IsolatedDeviceConfig) int {
|
||||
if dev.SharingMode == compute.DEVICE_SHARING_MODE_HAMI {
|
||||
return dev.MemoryRequest
|
||||
}
|
||||
return 1
|
||||
}
|
||||
|
||||
func isolatedDeviceMinMemory(dev *compute.IsolatedDeviceConfig) int {
|
||||
minMemMb := dev.MemoryMb
|
||||
if dev.SharingMode == compute.DEVICE_SHARING_MODE_HAMI && dev.MemoryRequest > minMemMb {
|
||||
minMemMb = dev.MemoryRequest
|
||||
}
|
||||
return minMemMb
|
||||
}
|
||||
|
||||
func (f *IsolatedDevicePredicate) Execute(ctx context.Context, u *core.Unit, c core.Candidater) (bool, []core.PredicateFailureReason, error) {
|
||||
@@ -131,6 +160,7 @@ func (f *IsolatedDevicePredicate) Execute(ctx context.Context, u *core.Unit, c c
|
||||
|
||||
getter := c.Getter()
|
||||
minCapacity := int64(0xFFFFFFFF)
|
||||
pendingUsage := getter.GetPendingUsage().IsolatedDevice
|
||||
|
||||
// check by specify device id
|
||||
for _, dev := range reqIsoDevs {
|
||||
@@ -138,8 +168,8 @@ func (f *IsolatedDevicePredicate) Execute(ctx context.Context, u *core.Unit, c c
|
||||
continue
|
||||
}
|
||||
if fDev := getter.GetIsolatedDevice(dev.Id); fDev != nil {
|
||||
if len(fDev.GuestID) != 0 {
|
||||
h.Exclude(fmt.Sprintf("IsolatedDevice %q already used by guest %q", dev.Id, fDev.GuestID))
|
||||
if fDev.IsUsedUp() {
|
||||
h.Exclude(fmt.Sprintf("IsolatedDevice %q already used up", dev.Id))
|
||||
return h.GetResult()
|
||||
}
|
||||
} else {
|
||||
@@ -148,30 +178,29 @@ func (f *IsolatedDevicePredicate) Execute(ctx context.Context, u *core.Unit, c c
|
||||
}
|
||||
minCapacity = 1
|
||||
}
|
||||
|
||||
reqCount := len(reqIsoDevs)
|
||||
freeCount := len(getter.UnusedIsolatedDevices()) - getter.GetPendingUsage().IsolatedDevice
|
||||
totalCount := len(getter.GetIsolatedDevices())
|
||||
|
||||
// check host isolated device count
|
||||
if freeCount < reqCount {
|
||||
h.AppendInsufficientResourceError(int64(reqCount), int64(totalCount), int64(freeCount))
|
||||
h.Exclude(fmt.Sprintf(
|
||||
"IsolatedDevice count not enough, request: %d, hostTotal: %d, hostFree: %d",
|
||||
reqCount, totalCount, freeCount))
|
||||
return h.GetResult()
|
||||
type reqKey struct {
|
||||
devType string
|
||||
sharingMode string
|
||||
}
|
||||
|
||||
// check host device by type
|
||||
devTypeRequest := make(map[string]int, 0)
|
||||
devTypeRequest := make(map[reqKey]int, 0)
|
||||
for _, dev := range reqIsoDevs {
|
||||
if len(dev.DevType) != 0 {
|
||||
devTypeRequest[dev.DevType] += 1
|
||||
key := reqKey{devType: dev.DevType, sharingMode: dev.SharingMode}
|
||||
reqAmount := isolatedDeviceRequestAmount(dev)
|
||||
if reqAmount <= 0 {
|
||||
h.Exclude(fmt.Sprintf("IsolatedDevice type %q sharing_mode %q request amount must be positive", dev.DevType, dev.SharingMode))
|
||||
return h.GetResult()
|
||||
}
|
||||
devTypeRequest[key] += reqAmount
|
||||
}
|
||||
}
|
||||
for devType, reqCount := range devTypeRequest {
|
||||
freeCount := f.getIsolatedDeviceCountByType(getter, devType)
|
||||
if freeCount < reqCount {
|
||||
for key, reqCount := range devTypeRequest {
|
||||
devType, sharingMode := key.devType, key.sharingMode
|
||||
devs := getter.AvailableIsolatedDevicesByTypeSharingMode(devType, sharingMode)
|
||||
pendingCnt := pendingUsage.Get(path.Join(devType, sharingMode))
|
||||
freeCount := f.getIsolatedDeviceCountBySharingMode(sharingMode, devs)
|
||||
if freeCount < (reqCount + pendingCnt) {
|
||||
h.Exclude(fmt.Sprintf("IsolatedDevice type %q not enough, request: %d, hostFree: %d", devType, reqCount, freeCount))
|
||||
return h.GetResult()
|
||||
}
|
||||
@@ -182,16 +211,37 @@ func (f *IsolatedDevicePredicate) Execute(ctx context.Context, u *core.Unit, c c
|
||||
}
|
||||
|
||||
// check host device by model
|
||||
devVendorModelRequest := make(map[string]int, 0)
|
||||
type modelReqKey struct {
|
||||
vendorModel string
|
||||
devType string
|
||||
sharingMode string
|
||||
}
|
||||
devVendorModelRequest := make(map[modelReqKey]int, 0)
|
||||
for _, dev := range reqIsoDevs {
|
||||
if len(dev.Model) != 0 {
|
||||
devVendorModelRequest[fmt.Sprintf("%s:%s", dev.Vendor, dev.Model)] += 1
|
||||
key := modelReqKey{
|
||||
vendorModel: fmt.Sprintf("%s:%s", dev.Vendor, dev.Model),
|
||||
devType: dev.DevType,
|
||||
sharingMode: dev.SharingMode,
|
||||
}
|
||||
reqAmount := isolatedDeviceRequestAmount(dev)
|
||||
if reqAmount <= 0 {
|
||||
h.Exclude(fmt.Sprintf("IsolatedDevice vendor:model %q request amount must be positive", key.vendorModel))
|
||||
return h.GetResult()
|
||||
}
|
||||
devVendorModelRequest[key] += reqAmount
|
||||
}
|
||||
}
|
||||
for vendorModel, reqCount := range devVendorModelRequest {
|
||||
freeCount := len(getter.UnusedIsolatedDevicesByVendorModel(vendorModel))
|
||||
if freeCount < reqCount {
|
||||
h.Exclude(fmt.Sprintf("IsolatedDevice vendor:model %q not enough, request: %d, hostFree: %d", vendorModel, reqCount, freeCount))
|
||||
for key, reqCount := range devVendorModelRequest {
|
||||
devs := filterDevicesByTypeSharingMode(getter.AvailableIsolatedDevicesByVendorModel(key.vendorModel), key.devType, key.sharingMode)
|
||||
if len(devs) == 0 {
|
||||
h.Exclude(fmt.Sprintf("IsolatedDevice vendor:model %q not enough, request: %d, hostFree: 0", key.vendorModel, reqCount))
|
||||
return h.GetResult()
|
||||
}
|
||||
pendingCnt := pendingUsage.Get(path.Join(key.devType, key.sharingMode))
|
||||
freeCount := f.getIsolatedDeviceCountBySharingMode(key.sharingMode, devs)
|
||||
if freeCount < (reqCount + pendingCnt) {
|
||||
h.Exclude(fmt.Sprintf("IsolatedDevice vendor:model %q not enough, request: %d, hostFree: %d", key.vendorModel, reqCount, freeCount))
|
||||
return h.GetResult()
|
||||
}
|
||||
cap := freeCount / reqCount
|
||||
@@ -205,18 +255,20 @@ func (f *IsolatedDevicePredicate) Execute(ctx context.Context, u *core.Unit, c c
|
||||
// vram_claim_mb is honoured. Devices with memory_size == 0 are passed
|
||||
// through as unknown (see countDevicesWithMinMemory).
|
||||
type vramReqKey struct {
|
||||
devType string
|
||||
minMemMb int
|
||||
devType string
|
||||
sharingMode string
|
||||
minMemMb int
|
||||
}
|
||||
vramReq := make(map[vramReqKey]int)
|
||||
for _, dev := range reqIsoDevs {
|
||||
if dev.MemoryMb <= 0 {
|
||||
minMemMb := isolatedDeviceMinMemory(dev)
|
||||
if minMemMb <= 0 {
|
||||
continue
|
||||
}
|
||||
vramReq[vramReqKey{dev.DevType, dev.MemoryMb}]++
|
||||
vramReq[vramReqKey{dev.DevType, dev.SharingMode, minMemMb}]++
|
||||
}
|
||||
for k, reqCnt := range vramReq {
|
||||
fit := f.countDevicesWithMinMemory(getter, k.devType, k.minMemMb)
|
||||
fit := f.countDevicesWithMinMemory(getter, k.devType, k.sharingMode, k.minMemMb)
|
||||
if fit < reqCnt {
|
||||
h.Exclude(fmt.Sprintf(
|
||||
"IsolatedDevice type %q with memory >= %d MiB not enough, request: %d, hostFree: %d",
|
||||
@@ -230,16 +282,37 @@ func (f *IsolatedDevicePredicate) Execute(ctx context.Context, u *core.Unit, c c
|
||||
}
|
||||
|
||||
// check host device by device_path
|
||||
devicePathReq := make(map[string]int, 0)
|
||||
type devicePathReqKey struct {
|
||||
devicePath string
|
||||
devType string
|
||||
sharingMode string
|
||||
}
|
||||
devicePathReq := make(map[devicePathReqKey]int, 0)
|
||||
for _, dev := range reqIsoDevs {
|
||||
if len(dev.DevicePath) != 0 {
|
||||
devicePathReq[dev.DevicePath] += 1
|
||||
key := devicePathReqKey{
|
||||
devicePath: dev.DevicePath,
|
||||
devType: dev.DevType,
|
||||
sharingMode: dev.SharingMode,
|
||||
}
|
||||
reqAmount := isolatedDeviceRequestAmount(dev)
|
||||
if reqAmount <= 0 {
|
||||
h.Exclude(fmt.Sprintf("IsolatedDevice device_path %q request amount must be positive", dev.DevicePath))
|
||||
return h.GetResult()
|
||||
}
|
||||
devicePathReq[key] += reqAmount
|
||||
}
|
||||
}
|
||||
for devPath, reqCnt := range devicePathReq {
|
||||
freeCount := len(getter.UnusedIsolatedDevicesByDevicePath(devPath))
|
||||
if freeCount < reqCount {
|
||||
h.Exclude(fmt.Sprintf("IsolatedDevice device_path %q not enough, request: %d, hostFree: %d", devPath, reqCount, freeCount))
|
||||
for key, reqCnt := range devicePathReq {
|
||||
devs := filterDevicesByTypeSharingMode(getter.AvailableIsolatedDevicesByDevicePath(key.devicePath), key.devType, key.sharingMode)
|
||||
if len(devs) == 0 {
|
||||
h.Exclude(fmt.Sprintf("IsolatedDevice device_path %q not enough, request: %d, hostFree: 0", key.devicePath, reqCnt))
|
||||
return h.GetResult()
|
||||
}
|
||||
pendingCnt := pendingUsage.Get(path.Join(key.devType, key.sharingMode))
|
||||
freeCount := f.getIsolatedDeviceCountBySharingMode(key.sharingMode, devs)
|
||||
if freeCount < (reqCnt + pendingCnt) {
|
||||
h.Exclude(fmt.Sprintf("IsolatedDevice device_path %q not enough, request: %d, hostFree: %d", key.devicePath, reqCnt, freeCount))
|
||||
return h.GetResult()
|
||||
}
|
||||
cap := freeCount / reqCnt
|
||||
|
||||
@@ -17,20 +17,36 @@ package predicates
|
||||
import (
|
||||
"testing"
|
||||
|
||||
computeapi "yunion.io/x/onecloud/pkg/apis/compute"
|
||||
"yunion.io/x/onecloud/pkg/scheduler/core"
|
||||
)
|
||||
|
||||
func TestCountDevicesWithMinMemoryFromList(t *testing.T) {
|
||||
mk := func(path string, memMb int) *core.IsolatedDeviceDesc {
|
||||
return &core.IsolatedDeviceDesc{DevicePath: path, MemorySize: memMb}
|
||||
return &core.IsolatedDeviceDesc{DevicePath: path, MemorySize: memMb, VirtualNum: 1}
|
||||
}
|
||||
mkVirtual := func(path string, memMb, virtualNum, allocated int) *core.IsolatedDeviceDesc {
|
||||
return &core.IsolatedDeviceDesc{
|
||||
DevicePath: path,
|
||||
MemorySize: memMb,
|
||||
VirtualNum: virtualNum,
|
||||
VirtualNumAllocated: allocated,
|
||||
}
|
||||
}
|
||||
mkHAMI := func(path string, memMb, allocatedMb int) *core.IsolatedDeviceDesc {
|
||||
return &core.IsolatedDeviceDesc{
|
||||
DevicePath: path,
|
||||
MemorySize: memMb,
|
||||
MemorySizeAllocated: allocatedMb,
|
||||
}
|
||||
}
|
||||
|
||||
cases := []struct {
|
||||
name string
|
||||
devs []*core.IsolatedDeviceDesc
|
||||
shared bool
|
||||
minMemMb int
|
||||
want int
|
||||
name string
|
||||
devs []*core.IsolatedDeviceDesc
|
||||
sharingMode string
|
||||
minMemMb int
|
||||
want int
|
||||
}{
|
||||
{
|
||||
name: "plain GPU: 3 cards 24/40/80 GiB, request 30 GiB → 2 fit",
|
||||
@@ -39,7 +55,7 @@ func TestCountDevicesWithMinMemoryFromList(t *testing.T) {
|
||||
mk("/dev/nvidia1", 40960),
|
||||
mk("/dev/nvidia2", 81920),
|
||||
},
|
||||
shared: false, minMemMb: 30000, want: 2,
|
||||
sharingMode: computeapi.DEVICE_SHARING_MODE_EXCLUSIVE, minMemMb: 30000, want: 2,
|
||||
},
|
||||
{
|
||||
name: "plain GPU: request 0 (unconstrained) → all pass through",
|
||||
@@ -47,7 +63,7 @@ func TestCountDevicesWithMinMemoryFromList(t *testing.T) {
|
||||
mk("/dev/nvidia0", 24576),
|
||||
mk("/dev/nvidia1", 40960),
|
||||
},
|
||||
shared: false, minMemMb: 0, want: 2,
|
||||
sharingMode: computeapi.DEVICE_SHARING_MODE_EXCLUSIVE, minMemMb: 0, want: 2,
|
||||
},
|
||||
{
|
||||
name: "unknown MemorySize=0 → passes as unknown (avoid mass exclusion)",
|
||||
@@ -55,40 +71,44 @@ func TestCountDevicesWithMinMemoryFromList(t *testing.T) {
|
||||
mk("/dev/nvidia0", 0),
|
||||
mk("/dev/nvidia1", 24576),
|
||||
},
|
||||
shared: false, minMemMb: 40000, want: 1, // unknown stays in, 24GiB excluded
|
||||
sharingMode: computeapi.DEVICE_SHARING_MODE_EXCLUSIVE, minMemMb: 40000, want: 1, // unknown stays in, 24GiB excluded
|
||||
},
|
||||
{
|
||||
name: "MPS share: 2 physical cards, 4 slices each, only 1 card meets req",
|
||||
name: "UNLIMITED share: 2 physical cards, only one card's slots meet req",
|
||||
devs: []*core.IsolatedDeviceDesc{
|
||||
// card 0: 6 GiB per slice (4 slices × same path)
|
||||
mk("/dev/nvidia0", 6144), mk("/dev/nvidia0", 6144),
|
||||
mk("/dev/nvidia0", 6144), mk("/dev/nvidia0", 6144),
|
||||
// card 1: 20 GiB per slice
|
||||
mk("/dev/nvidia1", 20480), mk("/dev/nvidia1", 20480),
|
||||
mk("/dev/nvidia1", 20480), mk("/dev/nvidia1", 20480),
|
||||
mkVirtual("/dev/nvidia0", 6144, 4, 0),
|
||||
mkVirtual("/dev/nvidia1", 20480, 4, 0),
|
||||
},
|
||||
shared: true, minMemMb: 10000, want: 1, // only card 1 satisfies
|
||||
sharingMode: computeapi.DEVICE_SHARING_MODE_UNLIMITED, minMemMb: 10000, want: 1,
|
||||
},
|
||||
{
|
||||
name: "MPS share: all slices pass through dedup → count by DevicePath",
|
||||
name: "UNLIMITED share: all matching virtual slots are counted",
|
||||
devs: []*core.IsolatedDeviceDesc{
|
||||
mk("/dev/nvidia0", 24576), mk("/dev/nvidia0", 24576),
|
||||
mk("/dev/nvidia1", 24576),
|
||||
mkVirtual("/dev/nvidia0", 24576, 2, 0),
|
||||
mkVirtual("/dev/nvidia1", 24576, 2, 1),
|
||||
},
|
||||
shared: true, minMemMb: 10000, want: 2, // 2 distinct paths
|
||||
sharingMode: computeapi.DEVICE_SHARING_MODE_UNLIMITED, minMemMb: 10000, want: 2,
|
||||
},
|
||||
{
|
||||
name: "empty pool → 0",
|
||||
devs: []*core.IsolatedDeviceDesc{},
|
||||
shared: false,
|
||||
minMemMb: 1000,
|
||||
want: 0,
|
||||
name: "HAMI share: count cards with enough remaining memory",
|
||||
devs: []*core.IsolatedDeviceDesc{
|
||||
mkHAMI("/dev/nvidia0", 24576, 8192),
|
||||
mkHAMI("/dev/nvidia1", 24576, 20480),
|
||||
},
|
||||
sharingMode: computeapi.DEVICE_SHARING_MODE_HAMI, minMemMb: 10000, want: 1,
|
||||
},
|
||||
{
|
||||
name: "empty pool → 0",
|
||||
devs: []*core.IsolatedDeviceDesc{},
|
||||
sharingMode: computeapi.DEVICE_SHARING_MODE_EXCLUSIVE,
|
||||
minMemMb: 1000,
|
||||
want: 0,
|
||||
},
|
||||
}
|
||||
|
||||
for _, c := range cases {
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
got := countDevicesWithMinMemoryFromList(c.devs, c.shared, c.minMemMb)
|
||||
got := countDevicesWithMinMemoryFromList(c.devs, c.sharingMode, c.minMemMb)
|
||||
if got != c.want {
|
||||
t.Errorf("got %d, want %d", got, c.want)
|
||||
}
|
||||
|
||||
@@ -177,7 +177,7 @@ func checkSriovNic(
|
||||
}
|
||||
}
|
||||
getter := c.Getter()
|
||||
devs := getter.UnusedIsolatedDevicesByModelAndWire(dev.Model, netWireId)
|
||||
devs := getter.AvailableIsolatedDevicesByModelAndWire(dev.Model, netWireId)
|
||||
if len(devs) == 0 {
|
||||
return fmt.Errorf("Network wire no sriov nic available")
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ func (p *GPUVramBinpackPriority) Map(u *core.Unit, c core.Candidater) (core.Host
|
||||
return h.GetResult()
|
||||
}
|
||||
|
||||
score := scoreVramBinpack(c.Getter().UnusedIsolatedDevices(), perDevMin)
|
||||
score := scoreVramBinpack(c.Getter().AvailableIsolatedDevices(), perDevMin)
|
||||
h.SetScore(score)
|
||||
return h.GetResult()
|
||||
}
|
||||
|
||||
@@ -55,32 +55,8 @@ var (
|
||||
AggregateStrategyPrefer,
|
||||
AggregateStrategyAvoid,
|
||||
)
|
||||
|
||||
ValidGpuTypes = sets.NewString(
|
||||
GPU_HPC_TYPE,
|
||||
GPU_VGA_TYPE,
|
||||
)
|
||||
|
||||
ValidPassthroughTypes = sets.NewString(
|
||||
DIRECT_PCI_TYPE,
|
||||
USB_TYPE,
|
||||
NIC_TYPE,
|
||||
).Union(ValidGpuTypes)
|
||||
|
||||
IsolatedVendorIDMap = map[string]string{
|
||||
NVIDIA: NVIDIA_VENDOR_ID,
|
||||
AMD: AMD_VENDOR_ID,
|
||||
}
|
||||
|
||||
IsolatedIDVendorMap = map[string]string{}
|
||||
)
|
||||
|
||||
func init() {
|
||||
for k, v := range IsolatedVendorIDMap {
|
||||
IsolatedIDVendorMap[v] = k
|
||||
}
|
||||
}
|
||||
|
||||
func SchedtagStrategyCheck(strategy string) (err error) {
|
||||
if !AggregateStrategySets.Has(strategy) {
|
||||
err = fmt.Errorf("Strategy %q must in set %v", strategy, AggregateStrategySets.List())
|
||||
|
||||
93
pkg/scheduler/cache/candidate/base.go
vendored
93
pkg/scheduler/cache/candidate/base.go
vendored
@@ -296,38 +296,34 @@ func (b baseHostGetter) GetPendingUsage() *schedmodels.SPendingUsage {
|
||||
return b.h.GetPendingUsage()
|
||||
}
|
||||
|
||||
func (b baseHostGetter) UnusedIsolatedDevices() []*core.IsolatedDeviceDesc {
|
||||
return b.h.UnusedIsolatedDevices()
|
||||
func (b baseHostGetter) AvailableIsolatedDevices() []*core.IsolatedDeviceDesc {
|
||||
return b.h.AvailableIsolatedDevices()
|
||||
}
|
||||
|
||||
func (b baseHostGetter) UnusedIsolatedDevicesByType(devType string) []*core.IsolatedDeviceDesc {
|
||||
return b.h.UnusedIsolatedDevicesByType(devType)
|
||||
func (b baseHostGetter) AvailableIsolatedDevicesByTypeSharingMode(devType string, sharingMode string) []*core.IsolatedDeviceDesc {
|
||||
return b.h.AvailableIsolatedDevicesByTypeSharingMode(devType, sharingMode)
|
||||
}
|
||||
|
||||
func (b baseHostGetter) UnusedIsolatedDevicesByVendorModel(vendorModel string) []*core.IsolatedDeviceDesc {
|
||||
return b.h.UnusedIsolatedDevicesByVendorModel(vendorModel)
|
||||
func (b baseHostGetter) AvailableIsolatedDevicesByVendorModel(vendorModel string) []*core.IsolatedDeviceDesc {
|
||||
return b.h.AvailableIsolatedDevicesByVendorModel(vendorModel)
|
||||
}
|
||||
|
||||
func (b baseHostGetter) UnusedIsolatedDevicesByDevicePath(devPath string) []*core.IsolatedDeviceDesc {
|
||||
return b.h.UnusedIsolatedDevicesByDevicePath(devPath)
|
||||
func (b baseHostGetter) AvailableIsolatedDevicesByDevicePath(devPath string) []*core.IsolatedDeviceDesc {
|
||||
return b.h.AvailableIsolatedDevicesByDevicePath(devPath)
|
||||
}
|
||||
|
||||
func (b baseHostGetter) UnusedIsolatedDevicesByModel(model string) []*core.IsolatedDeviceDesc {
|
||||
return b.h.UnusedIsolatedDevicesByModel(model)
|
||||
func (b baseHostGetter) AvailableIsolatedDevicesByModel(model string) []*core.IsolatedDeviceDesc {
|
||||
return b.h.AvailableIsolatedDevicesByModel(model)
|
||||
}
|
||||
|
||||
func (b baseHostGetter) UnusedIsolatedDevicesByModelAndWire(model, wire string) []*core.IsolatedDeviceDesc {
|
||||
return b.h.UnusedIsolatedDevicesByModelAndWire(model, wire)
|
||||
func (b baseHostGetter) AvailableIsolatedDevicesByModelAndWire(model, wire string) []*core.IsolatedDeviceDesc {
|
||||
return b.h.AvailableIsolatedDevicesByModelAndWire(model, wire)
|
||||
}
|
||||
|
||||
func (b baseHostGetter) GetIsolatedDevice(devID string) *core.IsolatedDeviceDesc {
|
||||
return b.h.GetIsolatedDevice(devID)
|
||||
}
|
||||
|
||||
func (b baseHostGetter) UnusedGpuDevices() []*core.IsolatedDeviceDesc {
|
||||
return b.h.UnusedGpuDevices()
|
||||
}
|
||||
|
||||
func (b baseHostGetter) GetIsolatedDevices() []*core.IsolatedDeviceDesc {
|
||||
return b.h.GetIsolatedDevices()
|
||||
}
|
||||
@@ -485,30 +481,34 @@ func (b BaseHostDesc) GetResourceType() string {
|
||||
return b.ResourceType
|
||||
}
|
||||
|
||||
func (h *BaseHostDesc) UnusedIsolatedDevices() []*core.IsolatedDeviceDesc {
|
||||
func (h *BaseHostDesc) AvailableIsolatedDevices() []*core.IsolatedDeviceDesc {
|
||||
ret := make([]*core.IsolatedDeviceDesc, 0)
|
||||
for _, dev := range h.IsolatedDevices {
|
||||
if len(dev.GuestID) == 0 {
|
||||
if !dev.IsUsedUp() {
|
||||
ret = append(ret, dev)
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func (h *BaseHostDesc) UnusedIsolatedDevicesByType(devType string) []*core.IsolatedDeviceDesc {
|
||||
func (h *BaseHostDesc) AvailableIsolatedDevicesByTypeSharingMode(devType, sharingMode string) []*core.IsolatedDeviceDesc {
|
||||
ret := make([]*core.IsolatedDeviceDesc, 0)
|
||||
for _, dev := range h.UnusedIsolatedDevices() {
|
||||
if dev.DevType == devType {
|
||||
ret = append(ret, dev)
|
||||
for _, dev := range h.AvailableIsolatedDevices() {
|
||||
if devType != "" && dev.DevType != devType {
|
||||
continue
|
||||
}
|
||||
if sharingMode != "" && dev.SharingMode != sharingMode {
|
||||
continue
|
||||
}
|
||||
ret = append(ret, dev)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func (h *BaseHostDesc) UnusedIsolatedDevicesByVendorModel(vendorModel string) []*core.IsolatedDeviceDesc {
|
||||
func (h *BaseHostDesc) AvailableIsolatedDevicesByVendorModel(vendorModel string) []*core.IsolatedDeviceDesc {
|
||||
ret := make([]*core.IsolatedDeviceDesc, 0)
|
||||
vm := core.NewVendorModelByStr(vendorModel)
|
||||
for _, dev := range h.UnusedIsolatedDevices() {
|
||||
for _, dev := range h.AvailableIsolatedDevices() {
|
||||
if dev.GetVendorModel().IsMatch(vm) {
|
||||
ret = append(ret, dev)
|
||||
}
|
||||
@@ -516,9 +516,9 @@ func (h *BaseHostDesc) UnusedIsolatedDevicesByVendorModel(vendorModel string) []
|
||||
return ret
|
||||
}
|
||||
|
||||
func (h *BaseHostDesc) UnusedIsolatedDevicesByModel(model string) []*core.IsolatedDeviceDesc {
|
||||
func (h *BaseHostDesc) AvailableIsolatedDevicesByModel(model string) []*core.IsolatedDeviceDesc {
|
||||
ret := make([]*core.IsolatedDeviceDesc, 0)
|
||||
for _, dev := range h.UnusedIsolatedDevices() {
|
||||
for _, dev := range h.AvailableIsolatedDevices() {
|
||||
if strings.Contains(dev.Model, model) {
|
||||
ret = append(ret, dev)
|
||||
}
|
||||
@@ -526,9 +526,9 @@ func (h *BaseHostDesc) UnusedIsolatedDevicesByModel(model string) []*core.Isolat
|
||||
return ret
|
||||
}
|
||||
|
||||
func (h *BaseHostDesc) UnusedIsolatedDevicesByDevicePath(devPath string) []*core.IsolatedDeviceDesc {
|
||||
func (h *BaseHostDesc) AvailableIsolatedDevicesByDevicePath(devPath string) []*core.IsolatedDeviceDesc {
|
||||
ret := make([]*core.IsolatedDeviceDesc, 0)
|
||||
for _, dev := range h.UnusedIsolatedDevices() {
|
||||
for _, dev := range h.AvailableIsolatedDevices() {
|
||||
if devPath == dev.DevicePath {
|
||||
ret = append(ret, dev)
|
||||
}
|
||||
@@ -536,9 +536,9 @@ func (h *BaseHostDesc) UnusedIsolatedDevicesByDevicePath(devPath string) []*core
|
||||
return ret
|
||||
}
|
||||
|
||||
func (h *BaseHostDesc) UnusedIsolatedDevicesByModelAndWire(model, wire string) []*core.IsolatedDeviceDesc {
|
||||
func (h *BaseHostDesc) AvailableIsolatedDevicesByModelAndWire(model, wire string) []*core.IsolatedDeviceDesc {
|
||||
ret := make([]*core.IsolatedDeviceDesc, 0)
|
||||
for _, dev := range h.UnusedIsolatedDevices() {
|
||||
for _, dev := range h.AvailableIsolatedDevices() {
|
||||
log.Errorf("dev wire is %s, dev model is %s, request model is %s, request wire is %s", dev.Model, dev.WireId, model, wire)
|
||||
if strings.Contains(dev.Model, model) && dev.WireId == wire {
|
||||
ret = append(ret, dev)
|
||||
@@ -560,16 +560,6 @@ func (h *BaseHostDesc) GetIsolatedDevices() []*core.IsolatedDeviceDesc {
|
||||
return h.IsolatedDevices
|
||||
}
|
||||
|
||||
func (h *BaseHostDesc) UnusedGpuDevices() []*core.IsolatedDeviceDesc {
|
||||
ret := make([]*core.IsolatedDeviceDesc, 0)
|
||||
for _, dev := range h.UnusedIsolatedDevices() {
|
||||
if strings.HasPrefix(dev.DevType, "GPU") {
|
||||
ret = append(ret, dev)
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
func (h *BaseHostDesc) fillIsolatedDevices(b *baseBuilder, host *computemodels.SHost) error {
|
||||
allDevs := b.getIsolatedDevices(host.Id)
|
||||
if len(allDevs) == 0 {
|
||||
@@ -579,16 +569,19 @@ func (h *BaseHostDesc) fillIsolatedDevices(b *baseBuilder, host *computemodels.S
|
||||
devs := make([]*core.IsolatedDeviceDesc, len(allDevs))
|
||||
for index, devModel := range allDevs {
|
||||
dev := &core.IsolatedDeviceDesc{
|
||||
ID: devModel.Id,
|
||||
GuestID: devModel.GuestId,
|
||||
HostID: devModel.HostId,
|
||||
DevType: devModel.DevType,
|
||||
Model: devModel.Model,
|
||||
Addr: devModel.Addr,
|
||||
VendorDeviceID: devModel.VendorDeviceId,
|
||||
WireId: devModel.WireId,
|
||||
DevicePath: devModel.DevicePath,
|
||||
MemorySize: devModel.MemorySize,
|
||||
ID: devModel.Id,
|
||||
HostID: devModel.HostId,
|
||||
DevType: devModel.DevType,
|
||||
SharingMode: devModel.SharingMode,
|
||||
Model: devModel.Model,
|
||||
Addr: devModel.Addr,
|
||||
VendorDeviceID: devModel.VendorDeviceId,
|
||||
WireId: devModel.WireId,
|
||||
DevicePath: devModel.DevicePath,
|
||||
MemorySize: devModel.MemorySize,
|
||||
MemorySizeAllocated: devModel.MemoryAllocated,
|
||||
VirtualNum: devModel.VirtualNum,
|
||||
VirtualNumAllocated: devModel.GuestCount,
|
||||
}
|
||||
devs[index] = dev
|
||||
}
|
||||
|
||||
15
pkg/scheduler/cache/candidate/builder.go
vendored
15
pkg/scheduler/cache/candidate/builder.go
vendored
@@ -43,7 +43,8 @@ type baseBuilder struct {
|
||||
hosts []computemodels.SHost
|
||||
hostDict map[string]*computemodels.SHost
|
||||
|
||||
isolatedDevicesDict map[string][]interface{}
|
||||
isolatedDevicesDict map[string][]interface{}
|
||||
isolatedDeviceGuestsDict map[string][]string
|
||||
|
||||
hostCloudproviers map[string]*computemodels.SCloudprovider
|
||||
hostCloudaccounts map[string]*computemodels.SCloudaccount
|
||||
@@ -181,23 +182,23 @@ func (b *baseBuilder) setHosts(ids []string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *baseBuilder) getIsolatedDevices(hostID string) (devs []computemodels.SIsolatedDevice) {
|
||||
func (b *baseBuilder) getIsolatedDevices(hostID string) (devs []computemodels.IsolatedDeviceAllocateStat) {
|
||||
devObjs, ok := b.isolatedDevicesDict[hostID]
|
||||
devs = make([]computemodels.SIsolatedDevice, 0)
|
||||
devs = make([]computemodels.IsolatedDeviceAllocateStat, 0)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
for _, obj := range devObjs {
|
||||
dev := obj.(computemodels.SIsolatedDevice)
|
||||
dev := obj.(computemodels.IsolatedDeviceAllocateStat)
|
||||
devs = append(devs, dev)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (b *baseBuilder) setIsolatedDevs(ids []string, errMessageChannel chan error) {
|
||||
devs := computemodels.IsolatedDeviceManager.FindByHosts(ids)
|
||||
devs := computemodels.IsolatedDeviceManager.GetHostsIsolatedDeviceStats(ids)
|
||||
dict, err := utils.GroupBy(devs, func(obj interface{}) (string, error) {
|
||||
dev, ok := obj.(computemodels.SIsolatedDevice)
|
||||
dev, ok := obj.(computemodels.IsolatedDeviceAllocateStat)
|
||||
if !ok {
|
||||
return "", utils.ConvertError(obj, "computemodels.SIsolatedDevice")
|
||||
}
|
||||
@@ -208,6 +209,8 @@ func (b *baseBuilder) setIsolatedDevs(ids []string, errMessageChannel chan error
|
||||
return
|
||||
}
|
||||
b.isolatedDevicesDict = dict
|
||||
devGuests := computemodels.IsolatedDeviceManager.GetHostsGuestIsolatedDevices(ids)
|
||||
b.isolatedDeviceGuestsDict = devGuests
|
||||
}
|
||||
|
||||
func (b *baseBuilder) setCloudproviderAccounts(hosts []computemodels.SHost, errCh chan error) {
|
||||
|
||||
39
pkg/scheduler/cache/candidate/hosts.go
vendored
39
pkg/scheduler/cache/candidate/hosts.go
vendored
@@ -814,7 +814,8 @@ func NewGuestReservedResourceByBuilder(b *HostBuilder, host *computemodels.SHost
|
||||
if len(isoDevs) == 0 {
|
||||
return
|
||||
}
|
||||
reservedResource := host.GetDevsReservedResource(isoDevs)
|
||||
|
||||
reservedResource := host.GetDevsReservedResourceByDevStats(isoDevs)
|
||||
if reservedResource != nil {
|
||||
ret.CPUCount = int64(*reservedResource.ReservedCpu)
|
||||
ret.MemorySize = int64(*reservedResource.ReservedMemory)
|
||||
@@ -1741,25 +1742,25 @@ func (b *HostBuilder) fillMetadata(desc *HostDesc, host *computemodels.SHost) er
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *HostBuilder) getUsedIsolatedDevices(hostID string) (devs []computemodels.SIsolatedDevice) {
|
||||
devs = make([]computemodels.SIsolatedDevice, 0)
|
||||
func (b *HostBuilder) getUsedIsolatedDevicesGuests(hostID string) []string {
|
||||
guests := make([]string, 0)
|
||||
for _, dev := range b.getIsolatedDevices(hostID) {
|
||||
if len(dev.GuestId) != 0 {
|
||||
devs = append(devs, dev)
|
||||
if gss, ok := b.isolatedDeviceGuestsDict[dev.Id]; ok {
|
||||
guests = append(guests, gss...)
|
||||
}
|
||||
}
|
||||
return
|
||||
return guests
|
||||
}
|
||||
|
||||
func (b *HostBuilder) getIsolatedDeviceGuests(hostID string) (guests []computemodels.SGuest) {
|
||||
guests = make([]computemodels.SGuest, 0)
|
||||
usedDevs := b.getUsedIsolatedDevices(hostID)
|
||||
if len(usedDevs) == 0 {
|
||||
usedGuests := b.getUsedIsolatedDevicesGuests(hostID)
|
||||
if len(usedGuests) == 0 {
|
||||
return
|
||||
}
|
||||
ids := sets.NewString()
|
||||
for _, dev := range usedDevs {
|
||||
g, ok := b.guestDict[dev.GuestId]
|
||||
for _, guestId := range usedGuests {
|
||||
g, ok := b.guestDict[guestId]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
@@ -1772,15 +1773,15 @@ func (b *HostBuilder) getIsolatedDeviceGuests(hostID string) (guests []computemo
|
||||
return
|
||||
}
|
||||
|
||||
func (b *HostBuilder) getUnusedIsolatedDevices(hostID string) (devs []computemodels.SIsolatedDevice) {
|
||||
devs = make([]computemodels.SIsolatedDevice, 0)
|
||||
for _, dev := range b.getIsolatedDevices(hostID) {
|
||||
if len(dev.GuestId) == 0 {
|
||||
devs = append(devs, dev)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
//func (b *HostBuilder) getUnusedIsolatedDevices(hostID string) (devs []computemodels.IsolatedDeviceAllocateStat) {
|
||||
// devs = make([]computemodels.IsolatedDeviceAllocateStat, 0)
|
||||
// for _, dev := range b.getIsolatedDevices(hostID) {
|
||||
// if len(dev.GuestId) == 0 {
|
||||
// devs = append(devs, dev)
|
||||
// }
|
||||
// }
|
||||
// return
|
||||
//}
|
||||
|
||||
func (b *HostBuilder) fillCPUIOLoads(desc *HostDesc, host *computemodels.SHost) error {
|
||||
desc.CPULoad = b.loadByName(host.Id, "cpu_load")
|
||||
|
||||
@@ -121,14 +121,13 @@ type CandidatePropertyGetter interface {
|
||||
GetPendingUsage() *schedmodels.SPendingUsage
|
||||
|
||||
// isloatedDevices
|
||||
UnusedIsolatedDevices() []*IsolatedDeviceDesc
|
||||
UnusedIsolatedDevicesByType(devType string) []*IsolatedDeviceDesc
|
||||
UnusedIsolatedDevicesByVendorModel(vendorModel string) []*IsolatedDeviceDesc
|
||||
UnusedIsolatedDevicesByModel(model string) []*IsolatedDeviceDesc
|
||||
UnusedIsolatedDevicesByModelAndWire(model, wire string) []*IsolatedDeviceDesc
|
||||
UnusedIsolatedDevicesByDevicePath(devPath string) []*IsolatedDeviceDesc
|
||||
AvailableIsolatedDevices() []*IsolatedDeviceDesc
|
||||
AvailableIsolatedDevicesByTypeSharingMode(devType string, sharingMode string) []*IsolatedDeviceDesc
|
||||
AvailableIsolatedDevicesByVendorModel(vendorModel string) []*IsolatedDeviceDesc
|
||||
AvailableIsolatedDevicesByModel(model string) []*IsolatedDeviceDesc
|
||||
AvailableIsolatedDevicesByModelAndWire(model, wire string) []*IsolatedDeviceDesc
|
||||
AvailableIsolatedDevicesByDevicePath(devPath string) []*IsolatedDeviceDesc
|
||||
GetIsolatedDevice(devID string) *IsolatedDeviceDesc
|
||||
UnusedGpuDevices() []*IsolatedDeviceDesc
|
||||
GetIsolatedDevices() []*IsolatedDeviceDesc
|
||||
|
||||
db.IResource
|
||||
@@ -273,6 +272,7 @@ type IsolatedDeviceDesc struct {
|
||||
GuestID string
|
||||
HostID string
|
||||
DevType string
|
||||
SharingMode string
|
||||
Model string
|
||||
Addr string
|
||||
VendorDeviceID string
|
||||
@@ -280,7 +280,26 @@ type IsolatedDeviceDesc struct {
|
||||
DevicePath string
|
||||
// MemorySize is the on-device memory in MiB (NVIDIA GPU VRAM via
|
||||
// `nvidia-smi memory.total`). 0 means unknown / not yet reported by host.
|
||||
MemorySize int
|
||||
MemorySize int
|
||||
MemorySizeAllocated int
|
||||
VirtualNum int
|
||||
VirtualNumAllocated int
|
||||
}
|
||||
|
||||
func (i *IsolatedDeviceDesc) IsUsedUp() bool {
|
||||
if i.SharingMode == computeapi.DEVICE_SHARING_MODE_HAMI {
|
||||
return i.MemorySizeAllocated >= i.MemorySize
|
||||
} else {
|
||||
return i.VirtualNumAllocated >= i.VirtualNum
|
||||
}
|
||||
}
|
||||
|
||||
func (i *IsolatedDeviceDesc) AvailableNum() int {
|
||||
return i.VirtualNum - i.VirtualNumAllocated
|
||||
}
|
||||
|
||||
func (i *IsolatedDeviceDesc) AvailableMemorySize() int {
|
||||
return i.MemorySize - i.MemorySizeAllocated
|
||||
}
|
||||
|
||||
func (i *IsolatedDeviceDesc) VendorID() string {
|
||||
|
||||
@@ -17,6 +17,7 @@ package models
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"path"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@@ -24,6 +25,7 @@ import (
|
||||
"yunion.io/x/log"
|
||||
"yunion.io/x/pkg/errors"
|
||||
|
||||
"yunion.io/x/onecloud/pkg/apis/compute"
|
||||
schedapi "yunion.io/x/onecloud/pkg/apis/scheduler"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/lockman"
|
||||
"yunion.io/x/onecloud/pkg/cloudcommon/db/quotas"
|
||||
@@ -512,7 +514,7 @@ type SPendingUsage struct {
|
||||
|
||||
// nodeId: memSizeMB
|
||||
NumaMemPin map[int]int
|
||||
IsolatedDevice int
|
||||
IsolatedDevice *SResourcePendingUsage
|
||||
DiskUsage *SResourcePendingUsage
|
||||
NetUsage *SResourcePendingUsage
|
||||
// Lock is not need here
|
||||
@@ -524,6 +526,7 @@ func NewPendingUsageBySchedInfo(hostId string, req *api.SchedInfo, candidate *sc
|
||||
HostId: hostId,
|
||||
DiskUsage: NewResourcePendingUsage(nil),
|
||||
NetUsage: NewResourcePendingUsage(nil),
|
||||
IsolatedDevice: NewResourcePendingUsage(nil),
|
||||
PendingGuestIds: make(map[string]struct{}),
|
||||
}
|
||||
|
||||
@@ -537,7 +540,6 @@ func NewPendingUsageBySchedInfo(hostId string, req *api.SchedInfo, candidate *sc
|
||||
}
|
||||
u.Cpu = req.Ncpu
|
||||
u.Memory = req.Memory
|
||||
u.IsolatedDevice = len(req.IsolatedDevices)
|
||||
|
||||
if candidate != nil && len(candidate.CpuNumaPin) > 0 {
|
||||
for _, cpuNumaPin := range candidate.CpuNumaPin {
|
||||
@@ -559,6 +561,20 @@ func NewPendingUsageBySchedInfo(hostId string, req *api.SchedInfo, candidate *sc
|
||||
}
|
||||
}
|
||||
|
||||
for _, dev := range req.IsolatedDevices {
|
||||
devType := dev.DevType
|
||||
sharingMode := dev.SharingMode
|
||||
pendingKey := path.Join(devType, sharingMode)
|
||||
if sharingMode == compute.DEVICE_SHARING_MODE_HAMI {
|
||||
oSize := u.IsolatedDevice.Get(pendingKey)
|
||||
size := dev.MemoryRequest
|
||||
u.IsolatedDevice.Set(pendingKey, oSize+size)
|
||||
} else {
|
||||
oCnt := u.IsolatedDevice.Get(pendingKey)
|
||||
u.IsolatedDevice.Set(pendingKey, oCnt+1)
|
||||
}
|
||||
}
|
||||
|
||||
for _, disk := range req.Disks {
|
||||
backend := disk.Backend
|
||||
size := disk.SizeMb
|
||||
@@ -608,7 +624,7 @@ func (self *SPendingUsage) ToMap() map[string]interface{} {
|
||||
return map[string]interface{}{
|
||||
"cpu": self.Cpu,
|
||||
"memory": self.Memory,
|
||||
"isolated_device": self.IsolatedDevice,
|
||||
"isolated_device": self.IsolatedDevice.ToMap(),
|
||||
"disk": self.DiskUsage.ToMap(),
|
||||
"net": self.NetUsage.ToMap(),
|
||||
"instance_groups": self.InstanceGroupUsage,
|
||||
@@ -644,7 +660,7 @@ func (self *SPendingUsage) Add(sUsage *SPendingUsage, addGuestId string) {
|
||||
self.NumaMemPin[k] = v1
|
||||
}
|
||||
}
|
||||
self.IsolatedDevice = self.IsolatedDevice + sUsage.IsolatedDevice
|
||||
self.IsolatedDevice.Add(sUsage.IsolatedDevice)
|
||||
self.DiskUsage.Add(sUsage.DiskUsage)
|
||||
self.NetUsage.Add(sUsage.NetUsage)
|
||||
for id, cg := range sUsage.InstanceGroupUsage {
|
||||
@@ -676,7 +692,7 @@ func (self *SPendingUsage) Sub(sUsage *SPendingUsage) {
|
||||
}
|
||||
}
|
||||
|
||||
self.IsolatedDevice = quotas.NonNegative(self.IsolatedDevice - sUsage.IsolatedDevice)
|
||||
self.IsolatedDevice.Sub(sUsage.IsolatedDevice)
|
||||
self.DiskUsage.Sub(sUsage.DiskUsage)
|
||||
self.NetUsage.Sub(sUsage.NetUsage)
|
||||
for id, cg := range sUsage.InstanceGroupUsage {
|
||||
@@ -698,7 +714,7 @@ func (self *SPendingUsage) IsEmpty() bool {
|
||||
if self.Memory > 0 {
|
||||
return false
|
||||
}
|
||||
if self.IsolatedDevice > 0 {
|
||||
if !self.IsolatedDevice.IsEmpty() {
|
||||
return false
|
||||
}
|
||||
if !self.DiskUsage.IsEmpty() {
|
||||
|
||||
@@ -697,96 +697,82 @@ func (mr *MockCandidatePropertyGetterMockRecorder) TotalMemorySize(arg0 interfac
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "TotalMemorySize", reflect.TypeOf((*MockCandidatePropertyGetter)(nil).TotalMemorySize), arg0)
|
||||
}
|
||||
|
||||
// UnusedGpuDevices mocks base method
|
||||
func (m *MockCandidatePropertyGetter) UnusedGpuDevices() []*core.IsolatedDeviceDesc {
|
||||
// AvailableIsolatedDevices mocks base method
|
||||
func (m *MockCandidatePropertyGetter) AvailableIsolatedDevices() []*core.IsolatedDeviceDesc {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "UnusedGpuDevices")
|
||||
ret := m.ctrl.Call(m, "AvailableIsolatedDevices")
|
||||
ret0, _ := ret[0].([]*core.IsolatedDeviceDesc)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// UnusedGpuDevices indicates an expected call of UnusedGpuDevices
|
||||
func (mr *MockCandidatePropertyGetterMockRecorder) UnusedGpuDevices() *gomock.Call {
|
||||
// AvailableIsolatedDevices indicates an expected call of AvailableIsolatedDevices
|
||||
func (mr *MockCandidatePropertyGetterMockRecorder) AvailableIsolatedDevices() *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UnusedGpuDevices", reflect.TypeOf((*MockCandidatePropertyGetter)(nil).UnusedGpuDevices))
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AvailableIsolatedDevices", reflect.TypeOf((*MockCandidatePropertyGetter)(nil).AvailableIsolatedDevices))
|
||||
}
|
||||
|
||||
// UnusedIsolatedDevices mocks base method
|
||||
func (m *MockCandidatePropertyGetter) UnusedIsolatedDevices() []*core.IsolatedDeviceDesc {
|
||||
// AvailableIsolatedDevicesByModel mocks base method
|
||||
func (m *MockCandidatePropertyGetter) AvailableIsolatedDevicesByModel(arg0 string) []*core.IsolatedDeviceDesc {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "UnusedIsolatedDevices")
|
||||
ret := m.ctrl.Call(m, "AvailableIsolatedDevicesByModel", arg0)
|
||||
ret0, _ := ret[0].([]*core.IsolatedDeviceDesc)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// UnusedIsolatedDevices indicates an expected call of UnusedIsolatedDevices
|
||||
func (mr *MockCandidatePropertyGetterMockRecorder) UnusedIsolatedDevices() *gomock.Call {
|
||||
// AvailableIsolatedDevicesByDevicePath mocks base method
|
||||
func (m *MockCandidatePropertyGetter) AvailableIsolatedDevicesByDevicePath(arg0 string) []*core.IsolatedDeviceDesc {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "AvailableIsolatedDevicesByDevicePath", arg0)
|
||||
ret0, _ := ret[0].([]*core.IsolatedDeviceDesc)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// AvailableIsolatedDevicesByModel indicates an expected call of AvailableIsolatedDevicesByModel
|
||||
func (mr *MockCandidatePropertyGetterMockRecorder) AvailableIsolatedDevicesByModel(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UnusedIsolatedDevices", reflect.TypeOf((*MockCandidatePropertyGetter)(nil).UnusedIsolatedDevices))
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AvailableIsolatedDevicesByModel", reflect.TypeOf((*MockCandidatePropertyGetter)(nil).AvailableIsolatedDevicesByModel), arg0)
|
||||
}
|
||||
|
||||
// UnusedIsolatedDevicesByModel mocks base method
|
||||
func (m *MockCandidatePropertyGetter) UnusedIsolatedDevicesByModel(arg0 string) []*core.IsolatedDeviceDesc {
|
||||
// AvailableIsolatedDevicesByModelAndWire mocks base method
|
||||
func (m *MockCandidatePropertyGetter) AvailableIsolatedDevicesByModelAndWire(arg0, arg1 string) []*core.IsolatedDeviceDesc {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "UnusedIsolatedDevicesByModel", arg0)
|
||||
ret := m.ctrl.Call(m, "AvailableIsolatedDevicesByModelAndWire", arg0, arg1)
|
||||
ret0, _ := ret[0].([]*core.IsolatedDeviceDesc)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// UnusedIsolatedDevicesByDevicePath mocks base method
|
||||
func (m *MockCandidatePropertyGetter) UnusedIsolatedDevicesByDevicePath(arg0 string) []*core.IsolatedDeviceDesc {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "UnusedIsolatedDevicesByDevicePath", arg0)
|
||||
ret0, _ := ret[0].([]*core.IsolatedDeviceDesc)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// UnusedIsolatedDevicesByModel indicates an expected call of UnusedIsolatedDevicesByModel
|
||||
func (mr *MockCandidatePropertyGetterMockRecorder) UnusedIsolatedDevicesByModel(arg0 interface{}) *gomock.Call {
|
||||
// AvailableIsolatedDevicesByModelAndWire indicates an expected call of AvailableIsolatedDevicesByModelAndWire
|
||||
func (mr *MockCandidatePropertyGetterMockRecorder) AvailableIsolatedDevicesByModelAndWire(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UnusedIsolatedDevicesByModel", reflect.TypeOf((*MockCandidatePropertyGetter)(nil).UnusedIsolatedDevicesByModel), arg0)
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AvailableIsolatedDevicesByModelAndWire", reflect.TypeOf((*MockCandidatePropertyGetter)(nil).AvailableIsolatedDevicesByModelAndWire), arg0, arg1)
|
||||
}
|
||||
|
||||
// UnusedIsolatedDevicesByModelAndWire mocks base method
|
||||
func (m *MockCandidatePropertyGetter) UnusedIsolatedDevicesByModelAndWire(arg0, arg1 string) []*core.IsolatedDeviceDesc {
|
||||
// AvailableIsolatedDevicesByTypeSharingMode mocks base method
|
||||
func (m *MockCandidatePropertyGetter) AvailableIsolatedDevicesByTypeSharingMode(arg0 string, arg1 string) []*core.IsolatedDeviceDesc {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "UnusedIsolatedDevicesByModelAndWire", arg0, arg1)
|
||||
ret := m.ctrl.Call(m, "AvailableIsolatedDevicesByType", arg0, arg1)
|
||||
ret0, _ := ret[0].([]*core.IsolatedDeviceDesc)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// UnusedIsolatedDevicesByModelAndWire indicates an expected call of UnusedIsolatedDevicesByModelAndWire
|
||||
func (mr *MockCandidatePropertyGetterMockRecorder) UnusedIsolatedDevicesByModelAndWire(arg0, arg1 interface{}) *gomock.Call {
|
||||
// AvailableIsolatedDevicesByTypeSharingMode indicates an expected call of AvailableIsolatedDevicesByTypeSharingMode
|
||||
func (mr *MockCandidatePropertyGetterMockRecorder) AvailableIsolatedDevicesByTypeSharingMode(arg0, arg1 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UnusedIsolatedDevicesByModelAndWire", reflect.TypeOf((*MockCandidatePropertyGetter)(nil).UnusedIsolatedDevicesByModel), arg0, arg1)
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AvailableIsolatedDevicesByType", reflect.TypeOf((*MockCandidatePropertyGetter)(nil).AvailableIsolatedDevicesByTypeSharingMode), arg0, arg1)
|
||||
}
|
||||
|
||||
// UnusedIsolatedDevicesByType mocks base method
|
||||
func (m *MockCandidatePropertyGetter) UnusedIsolatedDevicesByType(arg0 string) []*core.IsolatedDeviceDesc {
|
||||
// AvailableIsolatedDevicesByVendorModel mocks base method
|
||||
func (m *MockCandidatePropertyGetter) AvailableIsolatedDevicesByVendorModel(arg0 string) []*core.IsolatedDeviceDesc {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "UnusedIsolatedDevicesByType", arg0)
|
||||
ret := m.ctrl.Call(m, "AvailableIsolatedDevicesByVendorModel", arg0)
|
||||
ret0, _ := ret[0].([]*core.IsolatedDeviceDesc)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// UnusedIsolatedDevicesByType indicates an expected call of UnusedIsolatedDevicesByType
|
||||
func (mr *MockCandidatePropertyGetterMockRecorder) UnusedIsolatedDevicesByType(arg0 interface{}) *gomock.Call {
|
||||
// AvailableIsolatedDevicesByVendorModel indicates an expected call of AvailableIsolatedDevicesByVendorModel
|
||||
func (mr *MockCandidatePropertyGetterMockRecorder) AvailableIsolatedDevicesByVendorModel(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UnusedIsolatedDevicesByType", reflect.TypeOf((*MockCandidatePropertyGetter)(nil).UnusedIsolatedDevicesByType), arg0)
|
||||
}
|
||||
|
||||
// UnusedIsolatedDevicesByVendorModel mocks base method
|
||||
func (m *MockCandidatePropertyGetter) UnusedIsolatedDevicesByVendorModel(arg0 string) []*core.IsolatedDeviceDesc {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "UnusedIsolatedDevicesByVendorModel", arg0)
|
||||
ret0, _ := ret[0].([]*core.IsolatedDeviceDesc)
|
||||
return ret0
|
||||
}
|
||||
|
||||
// UnusedIsolatedDevicesByVendorModel indicates an expected call of UnusedIsolatedDevicesByVendorModel
|
||||
func (mr *MockCandidatePropertyGetterMockRecorder) UnusedIsolatedDevicesByVendorModel(arg0 interface{}) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UnusedIsolatedDevicesByVendorModel", reflect.TypeOf((*MockCandidatePropertyGetter)(nil).UnusedIsolatedDevicesByVendorModel), arg0)
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "AvailableIsolatedDevicesByVendorModel", reflect.TypeOf((*MockCandidatePropertyGetter)(nil).AvailableIsolatedDevicesByVendorModel), arg0)
|
||||
}
|
||||
|
||||
// Zone mocks base method
|
||||
|
||||
Reference in New Issue
Block a user