Merge pull request #4780 from hashicorp/f-device-attributes

Device fingerprinting uses Attribute object
This commit is contained in:
Alex Dadgar 2018-10-15 13:37:49 -07:00 committed by GitHub
commit b94505b256
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 695 additions and 479 deletions

View file

@ -2,24 +2,25 @@ package nvidia
import (
"context"
"fmt"
"time"
"github.com/hashicorp/nomad/devices/gpu/nvidia/nvml"
"github.com/hashicorp/nomad/helper"
"github.com/hashicorp/nomad/plugins/device"
"github.com/hashicorp/nomad/plugins/shared/structs"
)
const (
// Attribute names for reporting Fingerprint output
MemoryMiBAttr = "memory_mib"
PowerWAttr = "power_w"
BAR1MiBAttr = "bar1_mib"
DriverVersionAttr = "driver_version"
CoresClockMHzAttr = "cores_clock_mhz"
MemoryClockMHzAttr = "memory_clock_mhz"
PCIBandwidthMBPerSAttr = "pci_bandwidth_mb/s"
DisplayStateAttr = "display_state"
PersistenceModeAttr = "persistence_mode"
// Attribute names and units for reporting Fingerprint output
MemoryAttr = "memory"
PowerAttr = "power"
BAR1Attr = "bar1"
DriverVersionAttr = "driver_version"
CoresClockAttr = "cores_clock"
MemoryClockAttr = "memory_clock"
PCIBandwidthAttr = "pci_bandwidth"
DisplayStateAttr = "display_state"
PersistenceModeAttr = "persistence_mode"
)
// fingerprint is the long running goroutine that detects hardware
@ -69,8 +70,10 @@ func (d *NvidiaDevice) writeFingerprintToChannel(devices chan<- *device.Fingerpr
return
}
commonAttributes := map[string]string{
DriverVersionAttr: fingerprintData.DriverVersion,
commonAttributes := map[string]*structs.Attribute{
DriverVersionAttr: {
String: helper.StringToPtr(fingerprintData.DriverVersion),
},
}
// Group all FingerprintDevices by DeviceName attribute
@ -137,7 +140,7 @@ func (d *NvidiaDevice) fingerprintChanged(allDevices []*nvml.FingerprintDeviceDa
}
// deviceGroupFromFingerprintData composes deviceGroup from FingerprintDeviceData slice
func deviceGroupFromFingerprintData(groupName string, deviceList []*nvml.FingerprintDeviceData, commonAttributes map[string]string) *device.DeviceGroup {
func deviceGroupFromFingerprintData(groupName string, deviceList []*nvml.FingerprintDeviceData, commonAttributes map[string]*structs.Attribute) *device.DeviceGroup {
// deviceGroup without devices makes no sense -> return nil when no devices are provided
if len(deviceList) == 0 {
return nil
@ -177,63 +180,52 @@ func deviceGroupFromFingerprintData(groupName string, deviceList []*nvml.Fingerp
// attributesFromFingerprintDeviceData converts nvml.FingerprintDeviceData
// struct to device.DeviceGroup.Attributes format (map[string]string)
// this function performs all nil checks for FingerprintDeviceData pointers
func attributesFromFingerprintDeviceData(fingerprintDeviceData *nvml.FingerprintDeviceData) map[string]string {
// The following fields in FingerprintDeviceData are pointers, so they can be nil
// In case they are nil -> return 'notAvailable' constant instead
var (
MemoryMiB string
PowerW string
BAR1MiB string
CoresClockMHz string
MemoryClockMHz string
PCIBandwidthMBPerS string
)
if fingerprintDeviceData.MemoryMiB == nil {
MemoryMiB = notAvailable
} else {
MemoryMiB = fmt.Sprint(*fingerprintDeviceData.MemoryMiB)
func attributesFromFingerprintDeviceData(d *nvml.FingerprintDeviceData) map[string]*structs.Attribute {
attrs := map[string]*structs.Attribute{
DisplayStateAttr: {
String: helper.StringToPtr(d.DisplayState),
},
PersistenceModeAttr: {
String: helper.StringToPtr(d.PersistenceMode),
},
}
if fingerprintDeviceData.PowerW == nil {
PowerW = notAvailable
} else {
PowerW = fmt.Sprint(*fingerprintDeviceData.PowerW)
}
if fingerprintDeviceData.BAR1MiB == nil {
BAR1MiB = notAvailable
} else {
BAR1MiB = fmt.Sprint(*fingerprintDeviceData.BAR1MiB)
}
if fingerprintDeviceData.CoresClockMHz == nil {
CoresClockMHz = notAvailable
} else {
CoresClockMHz = fmt.Sprint(*fingerprintDeviceData.CoresClockMHz)
}
if fingerprintDeviceData.MemoryClockMHz == nil {
MemoryClockMHz = notAvailable
} else {
MemoryClockMHz = fmt.Sprint(*fingerprintDeviceData.MemoryClockMHz)
}
if fingerprintDeviceData.PCIBandwidthMBPerS == nil {
PCIBandwidthMBPerS = notAvailable
} else {
PCIBandwidthMBPerS = fmt.Sprint(*fingerprintDeviceData.PCIBandwidthMBPerS)
}
return map[string]string{
DisplayStateAttr: fingerprintDeviceData.DisplayState,
PersistenceModeAttr: fingerprintDeviceData.PersistenceMode,
MemoryMiBAttr: MemoryMiB,
PowerWAttr: PowerW,
BAR1MiBAttr: BAR1MiB,
CoresClockMHzAttr: CoresClockMHz,
MemoryClockMHzAttr: MemoryClockMHz,
PCIBandwidthMBPerSAttr: PCIBandwidthMBPerS,
if d.MemoryMiB != nil {
attrs[MemoryAttr] = &structs.Attribute{
Int: helper.Int64ToPtr(int64(*d.MemoryMiB)),
Unit: structs.UnitMiB,
}
}
if d.PowerW != nil {
attrs[PowerAttr] = &structs.Attribute{
Int: helper.Int64ToPtr(int64(*d.PowerW)),
Unit: structs.UnitW,
}
}
if d.BAR1MiB != nil {
attrs[BAR1Attr] = &structs.Attribute{
Int: helper.Int64ToPtr(int64(*d.BAR1MiB)),
Unit: structs.UnitMiB,
}
}
if d.CoresClockMHz != nil {
attrs[CoresClockAttr] = &structs.Attribute{
Int: helper.Int64ToPtr(int64(*d.CoresClockMHz)),
Unit: structs.UnitMHz,
}
}
if d.MemoryClockMHz != nil {
attrs[MemoryClockAttr] = &structs.Attribute{
Int: helper.Int64ToPtr(int64(*d.MemoryClockMHz)),
Unit: structs.UnitMHz,
}
}
if d.PCIBandwidthMBPerS != nil {
attrs[PCIBandwidthAttr] = &structs.Attribute{
Int: helper.Int64ToPtr(int64(*d.PCIBandwidthMBPerS)),
Unit: structs.UnitMBPerS,
}
}
return attrs
}

View file

@ -10,6 +10,7 @@ import (
"github.com/hashicorp/nomad/devices/gpu/nvidia/nvml"
"github.com/hashicorp/nomad/helper"
"github.com/hashicorp/nomad/plugins/device"
"github.com/hashicorp/nomad/plugins/shared/structs"
"github.com/stretchr/testify/require"
)
@ -359,7 +360,7 @@ func TestAttributesFromFingerprintDeviceData(t *testing.T) {
for _, testCase := range []struct {
Name string
FingerprintDeviceData *nvml.FingerprintDeviceData
ExpectedResult map[string]string
ExpectedResult map[string]*structs.Attribute
}{
{
Name: "All attributes are not nil",
@ -378,19 +379,41 @@ func TestAttributesFromFingerprintDeviceData(t *testing.T) {
DisplayState: "Enabled",
PersistenceMode: "Enabled",
},
ExpectedResult: map[string]string{
MemoryMiBAttr: "256",
PowerWAttr: "2",
BAR1MiBAttr: "256",
PCIBandwidthMBPerSAttr: "1",
CoresClockMHzAttr: "1",
MemoryClockMHzAttr: "1",
DisplayStateAttr: "Enabled",
PersistenceModeAttr: "Enabled",
ExpectedResult: map[string]*structs.Attribute{
MemoryAttr: {
Int: helper.Int64ToPtr(256),
Unit: structs.UnitMiB,
},
PowerAttr: {
Int: helper.Int64ToPtr(2),
Unit: structs.UnitW,
},
BAR1Attr: {
Int: helper.Int64ToPtr(256),
Unit: structs.UnitMiB,
},
PCIBandwidthAttr: {
Int: helper.Int64ToPtr(1),
Unit: structs.UnitMBPerS,
},
CoresClockAttr: {
Int: helper.Int64ToPtr(1),
Unit: structs.UnitMHz,
},
MemoryClockAttr: {
Int: helper.Int64ToPtr(1),
Unit: structs.UnitMHz,
},
DisplayStateAttr: {
String: helper.StringToPtr("Enabled"),
},
PersistenceModeAttr: {
String: helper.StringToPtr("Enabled"),
},
},
},
{
Name: "MemoryMiB is nil and has to be replaced to N/A",
Name: "nil values are omitted",
FingerprintDeviceData: &nvml.FingerprintDeviceData{
DeviceData: &nvml.DeviceData{
UUID: "1",
@ -399,168 +422,31 @@ func TestAttributesFromFingerprintDeviceData(t *testing.T) {
PowerW: helper.UintToPtr(2),
BAR1MiB: helper.Uint64ToPtr(256),
},
PCIBusID: "pciBusID1",
PCIBandwidthMBPerS: helper.UintToPtr(1),
CoresClockMHz: helper.UintToPtr(1),
MemoryClockMHz: helper.UintToPtr(1),
DisplayState: "Enabled",
PersistenceMode: "Enabled",
PCIBusID: "pciBusID1",
DisplayState: "Enabled",
PersistenceMode: "Enabled",
},
ExpectedResult: map[string]string{
MemoryMiBAttr: notAvailable,
PowerWAttr: "2",
BAR1MiBAttr: "256",
PCIBandwidthMBPerSAttr: "1",
CoresClockMHzAttr: "1",
MemoryClockMHzAttr: "1",
DisplayStateAttr: "Enabled",
PersistenceModeAttr: "Enabled",
},
},
{
Name: "PowerW is nil and has to be replaced to N/A",
FingerprintDeviceData: &nvml.FingerprintDeviceData{
DeviceData: &nvml.DeviceData{
UUID: "1",
DeviceName: helper.StringToPtr("Type1"),
MemoryMiB: helper.Uint64ToPtr(256),
PowerW: nil,
BAR1MiB: helper.Uint64ToPtr(256),
ExpectedResult: map[string]*structs.Attribute{
PowerAttr: {
Int: helper.Int64ToPtr(2),
Unit: structs.UnitW,
},
PCIBusID: "pciBusID1",
PCIBandwidthMBPerS: helper.UintToPtr(1),
CoresClockMHz: helper.UintToPtr(1),
MemoryClockMHz: helper.UintToPtr(1),
DisplayState: "Enabled",
PersistenceMode: "Enabled",
},
ExpectedResult: map[string]string{
MemoryMiBAttr: "256",
PowerWAttr: notAvailable,
BAR1MiBAttr: "256",
PCIBandwidthMBPerSAttr: "1",
CoresClockMHzAttr: "1",
MemoryClockMHzAttr: "1",
DisplayStateAttr: "Enabled",
PersistenceModeAttr: "Enabled",
},
},
{
Name: "BAR1MiB is nil and has to be replaced to N/A",
FingerprintDeviceData: &nvml.FingerprintDeviceData{
DeviceData: &nvml.DeviceData{
UUID: "1",
DeviceName: helper.StringToPtr("Type1"),
MemoryMiB: helper.Uint64ToPtr(256),
PowerW: helper.UintToPtr(2),
BAR1MiB: nil,
BAR1Attr: {
Int: helper.Int64ToPtr(256),
Unit: structs.UnitMiB,
},
PCIBusID: "pciBusID1",
PCIBandwidthMBPerS: helper.UintToPtr(1),
CoresClockMHz: helper.UintToPtr(1),
MemoryClockMHz: helper.UintToPtr(1),
DisplayState: "Enabled",
PersistenceMode: "Enabled",
},
ExpectedResult: map[string]string{
MemoryMiBAttr: "256",
PowerWAttr: "2",
BAR1MiBAttr: notAvailable,
PCIBandwidthMBPerSAttr: "1",
CoresClockMHzAttr: "1",
MemoryClockMHzAttr: "1",
DisplayStateAttr: "Enabled",
PersistenceModeAttr: "Enabled",
},
},
{
Name: "PCIBandwidthMBPerS is nil and has to be replaced to N/A",
FingerprintDeviceData: &nvml.FingerprintDeviceData{
DeviceData: &nvml.DeviceData{
UUID: "1",
DeviceName: helper.StringToPtr("Type1"),
MemoryMiB: helper.Uint64ToPtr(256),
PowerW: helper.UintToPtr(2),
BAR1MiB: helper.Uint64ToPtr(256),
DisplayStateAttr: {
String: helper.StringToPtr("Enabled"),
},
PCIBusID: "pciBusID1",
PCIBandwidthMBPerS: nil,
CoresClockMHz: helper.UintToPtr(1),
MemoryClockMHz: helper.UintToPtr(1),
DisplayState: "Enabled",
PersistenceMode: "Enabled",
},
ExpectedResult: map[string]string{
MemoryMiBAttr: "256",
PowerWAttr: "2",
BAR1MiBAttr: "256",
PCIBandwidthMBPerSAttr: notAvailable,
CoresClockMHzAttr: "1",
MemoryClockMHzAttr: "1",
DisplayStateAttr: "Enabled",
PersistenceModeAttr: "Enabled",
},
},
{
Name: "CoresClockMHz is nil and has to be replaced to N/A",
FingerprintDeviceData: &nvml.FingerprintDeviceData{
DeviceData: &nvml.DeviceData{
UUID: "1",
DeviceName: helper.StringToPtr("Type1"),
MemoryMiB: helper.Uint64ToPtr(256),
PowerW: helper.UintToPtr(2),
BAR1MiB: helper.Uint64ToPtr(256),
PersistenceModeAttr: {
String: helper.StringToPtr("Enabled"),
},
PCIBusID: "pciBusID1",
PCIBandwidthMBPerS: helper.UintToPtr(1),
CoresClockMHz: nil,
MemoryClockMHz: helper.UintToPtr(1),
DisplayState: "Enabled",
PersistenceMode: "Enabled",
},
ExpectedResult: map[string]string{
MemoryMiBAttr: "256",
PowerWAttr: "2",
BAR1MiBAttr: "256",
PCIBandwidthMBPerSAttr: "1",
CoresClockMHzAttr: notAvailable,
MemoryClockMHzAttr: "1",
DisplayStateAttr: "Enabled",
PersistenceModeAttr: "Enabled",
},
},
{
Name: "MemoryClockMHz is nil and has to be replaced to N/A",
FingerprintDeviceData: &nvml.FingerprintDeviceData{
DeviceData: &nvml.DeviceData{
UUID: "1",
DeviceName: helper.StringToPtr("Type1"),
MemoryMiB: helper.Uint64ToPtr(256),
PowerW: helper.UintToPtr(2),
BAR1MiB: helper.Uint64ToPtr(256),
},
PCIBusID: "pciBusID1",
PCIBandwidthMBPerS: helper.UintToPtr(1),
CoresClockMHz: helper.UintToPtr(1),
MemoryClockMHz: nil,
DisplayState: "Enabled",
PersistenceMode: "Enabled",
},
ExpectedResult: map[string]string{
MemoryMiBAttr: "256",
PowerWAttr: "2",
BAR1MiBAttr: "256",
PCIBandwidthMBPerSAttr: "1",
CoresClockMHzAttr: "1",
MemoryClockMHzAttr: notAvailable,
DisplayStateAttr: "Enabled",
PersistenceModeAttr: "Enabled",
},
},
} {
t.Run(testCase.Name, func(t *testing.T) {
actualResult := attributesFromFingerprintDeviceData(testCase.FingerprintDeviceData)
require.New(t).Equal(testCase.ExpectedResult, actualResult)
require.Equal(t, testCase.ExpectedResult, actualResult)
})
}
}
@ -570,7 +456,7 @@ func TestDeviceGroupFromFingerprintData(t *testing.T) {
Name string
GroupName string
Devices []*nvml.FingerprintDeviceData
CommonAttributes map[string]string
CommonAttributes map[string]*structs.Attribute
ExpectedResult *device.DeviceGroup
}{
{
@ -628,15 +514,37 @@ func TestDeviceGroupFromFingerprintData(t *testing.T) {
},
},
},
Attributes: map[string]string{
MemoryMiBAttr: "100",
PowerWAttr: "2",
BAR1MiBAttr: "256",
PCIBandwidthMBPerSAttr: "1",
CoresClockMHzAttr: "1",
MemoryClockMHzAttr: "1",
DisplayStateAttr: "Enabled",
PersistenceModeAttr: "Enabled",
Attributes: map[string]*structs.Attribute{
MemoryAttr: {
Int: helper.Int64ToPtr(100),
Unit: structs.UnitMiB,
},
PowerAttr: {
Int: helper.Int64ToPtr(2),
Unit: structs.UnitW,
},
BAR1Attr: {
Int: helper.Int64ToPtr(256),
Unit: structs.UnitMiB,
},
PCIBandwidthAttr: {
Int: helper.Int64ToPtr(1),
Unit: structs.UnitMBPerS,
},
CoresClockAttr: {
Int: helper.Int64ToPtr(1),
Unit: structs.UnitMHz,
},
MemoryClockAttr: {
Int: helper.Int64ToPtr(1),
Unit: structs.UnitMHz,
},
DisplayStateAttr: {
String: helper.StringToPtr("Enabled"),
},
PersistenceModeAttr: {
String: helper.StringToPtr("Enabled"),
},
},
},
},
@ -675,8 +583,10 @@ func TestDeviceGroupFromFingerprintData(t *testing.T) {
PersistenceMode: "Enabled",
},
},
CommonAttributes: map[string]string{
DriverVersionAttr: "1",
CommonAttributes: map[string]*structs.Attribute{
DriverVersionAttr: {
String: helper.StringToPtr("1"),
},
},
ExpectedResult: &device.DeviceGroup{
Vendor: vendor,
@ -698,24 +608,50 @@ func TestDeviceGroupFromFingerprintData(t *testing.T) {
},
},
},
Attributes: map[string]string{
MemoryMiBAttr: "100",
PowerWAttr: "2",
BAR1MiBAttr: "256",
DriverVersionAttr: "1",
PCIBandwidthMBPerSAttr: "1",
CoresClockMHzAttr: "1",
MemoryClockMHzAttr: "1",
DisplayStateAttr: "Enabled",
PersistenceModeAttr: "Enabled",
Attributes: map[string]*structs.Attribute{
MemoryAttr: {
Int: helper.Int64ToPtr(100),
Unit: structs.UnitMiB,
},
PowerAttr: {
Int: helper.Int64ToPtr(2),
Unit: structs.UnitW,
},
BAR1Attr: {
Int: helper.Int64ToPtr(256),
Unit: structs.UnitMiB,
},
PCIBandwidthAttr: {
Int: helper.Int64ToPtr(1),
Unit: structs.UnitMBPerS,
},
CoresClockAttr: {
Int: helper.Int64ToPtr(1),
Unit: structs.UnitMHz,
},
MemoryClockAttr: {
Int: helper.Int64ToPtr(1),
Unit: structs.UnitMHz,
},
DisplayStateAttr: {
String: helper.StringToPtr("Enabled"),
},
PersistenceModeAttr: {
String: helper.StringToPtr("Enabled"),
},
DriverVersionAttr: {
String: helper.StringToPtr("1"),
},
},
},
},
{
Name: "Devices are not provided",
GroupName: "Type1",
CommonAttributes: map[string]string{
DriverVersionAttr: "1",
CommonAttributes: map[string]*structs.Attribute{
DriverVersionAttr: {
String: helper.StringToPtr("1"),
},
},
Devices: nil,
ExpectedResult: nil,
@ -806,16 +742,40 @@ func TestWriteFingerprintToChannel(t *testing.T) {
},
},
},
Attributes: map[string]string{
MemoryMiBAttr: "10",
PowerWAttr: "100",
BAR1MiBAttr: "256",
DriverVersionAttr: "1",
PCIBandwidthMBPerSAttr: "1",
CoresClockMHzAttr: "1",
MemoryClockMHzAttr: "1",
DisplayStateAttr: "Enabled",
PersistenceModeAttr: "Enabled",
Attributes: map[string]*structs.Attribute{
MemoryAttr: {
Int: helper.Int64ToPtr(10),
Unit: structs.UnitMiB,
},
PowerAttr: {
Int: helper.Int64ToPtr(100),
Unit: structs.UnitW,
},
BAR1Attr: {
Int: helper.Int64ToPtr(256),
Unit: structs.UnitMiB,
},
PCIBandwidthAttr: {
Int: helper.Int64ToPtr(1),
Unit: structs.UnitMBPerS,
},
CoresClockAttr: {
Int: helper.Int64ToPtr(1),
Unit: structs.UnitMHz,
},
MemoryClockAttr: {
Int: helper.Int64ToPtr(1),
Unit: structs.UnitMHz,
},
DisplayStateAttr: {
String: helper.StringToPtr("Enabled"),
},
PersistenceModeAttr: {
String: helper.StringToPtr("Enabled"),
},
DriverVersionAttr: {
String: helper.StringToPtr("1"),
},
},
},
},
@ -893,16 +853,40 @@ func TestWriteFingerprintToChannel(t *testing.T) {
},
},
},
Attributes: map[string]string{
MemoryMiBAttr: "10",
DriverVersionAttr: "1",
PowerWAttr: "100",
BAR1MiBAttr: "256",
PCIBandwidthMBPerSAttr: "1",
CoresClockMHzAttr: "1",
MemoryClockMHzAttr: "1",
DisplayStateAttr: "Enabled",
PersistenceModeAttr: "Enabled",
Attributes: map[string]*structs.Attribute{
MemoryAttr: {
Int: helper.Int64ToPtr(10),
Unit: structs.UnitMiB,
},
PowerAttr: {
Int: helper.Int64ToPtr(100),
Unit: structs.UnitW,
},
BAR1Attr: {
Int: helper.Int64ToPtr(256),
Unit: structs.UnitMiB,
},
PCIBandwidthAttr: {
Int: helper.Int64ToPtr(1),
Unit: structs.UnitMBPerS,
},
CoresClockAttr: {
Int: helper.Int64ToPtr(1),
Unit: structs.UnitMHz,
},
MemoryClockAttr: {
Int: helper.Int64ToPtr(1),
Unit: structs.UnitMHz,
},
DisplayStateAttr: {
String: helper.StringToPtr("Enabled"),
},
PersistenceModeAttr: {
String: helper.StringToPtr("Enabled"),
},
DriverVersionAttr: {
String: helper.StringToPtr("1"),
},
},
},
{
@ -918,16 +902,40 @@ func TestWriteFingerprintToChannel(t *testing.T) {
},
},
},
Attributes: map[string]string{
MemoryMiBAttr: "11",
DriverVersionAttr: "1",
PowerWAttr: "100",
BAR1MiBAttr: "256",
PCIBandwidthMBPerSAttr: "1",
CoresClockMHzAttr: "1",
MemoryClockMHzAttr: "1",
DisplayStateAttr: "Enabled",
PersistenceModeAttr: "Enabled",
Attributes: map[string]*structs.Attribute{
MemoryAttr: {
Int: helper.Int64ToPtr(11),
Unit: structs.UnitMiB,
},
PowerAttr: {
Int: helper.Int64ToPtr(100),
Unit: structs.UnitW,
},
BAR1Attr: {
Int: helper.Int64ToPtr(256),
Unit: structs.UnitMiB,
},
PCIBandwidthAttr: {
Int: helper.Int64ToPtr(1),
Unit: structs.UnitMBPerS,
},
CoresClockAttr: {
Int: helper.Int64ToPtr(1),
Unit: structs.UnitMHz,
},
MemoryClockAttr: {
Int: helper.Int64ToPtr(1),
Unit: structs.UnitMHz,
},
DisplayStateAttr: {
String: helper.StringToPtr("Enabled"),
},
PersistenceModeAttr: {
String: helper.StringToPtr("Enabled"),
},
DriverVersionAttr: {
String: helper.StringToPtr("1"),
},
},
},
{
@ -943,16 +951,40 @@ func TestWriteFingerprintToChannel(t *testing.T) {
},
},
},
Attributes: map[string]string{
MemoryMiBAttr: "12",
DriverVersionAttr: "1",
PowerWAttr: "100",
BAR1MiBAttr: "256",
PCIBandwidthMBPerSAttr: "1",
CoresClockMHzAttr: "1",
MemoryClockMHzAttr: "1",
DisplayStateAttr: "Enabled",
PersistenceModeAttr: "Enabled",
Attributes: map[string]*structs.Attribute{
MemoryAttr: {
Int: helper.Int64ToPtr(12),
Unit: structs.UnitMiB,
},
PowerAttr: {
Int: helper.Int64ToPtr(100),
Unit: structs.UnitW,
},
BAR1Attr: {
Int: helper.Int64ToPtr(256),
Unit: structs.UnitMiB,
},
PCIBandwidthAttr: {
Int: helper.Int64ToPtr(1),
Unit: structs.UnitMBPerS,
},
CoresClockAttr: {
Int: helper.Int64ToPtr(1),
Unit: structs.UnitMHz,
},
MemoryClockAttr: {
Int: helper.Int64ToPtr(1),
Unit: structs.UnitMHz,
},
DisplayStateAttr: {
String: helper.StringToPtr("Enabled"),
},
PersistenceModeAttr: {
String: helper.StringToPtr("Enabled"),
},
DriverVersionAttr: {
String: helper.StringToPtr("1"),
},
},
},
},
@ -1030,16 +1062,40 @@ func TestWriteFingerprintToChannel(t *testing.T) {
},
},
},
Attributes: map[string]string{
MemoryMiBAttr: "10",
DriverVersionAttr: "1",
PowerWAttr: "100",
BAR1MiBAttr: "256",
PCIBandwidthMBPerSAttr: "1",
CoresClockMHzAttr: "1",
MemoryClockMHzAttr: "1",
DisplayStateAttr: "Enabled",
PersistenceModeAttr: "Enabled",
Attributes: map[string]*structs.Attribute{
MemoryAttr: {
Int: helper.Int64ToPtr(10),
Unit: structs.UnitMiB,
},
PowerAttr: {
Int: helper.Int64ToPtr(100),
Unit: structs.UnitW,
},
BAR1Attr: {
Int: helper.Int64ToPtr(256),
Unit: structs.UnitMiB,
},
PCIBandwidthAttr: {
Int: helper.Int64ToPtr(1),
Unit: structs.UnitMBPerS,
},
CoresClockAttr: {
Int: helper.Int64ToPtr(1),
Unit: structs.UnitMHz,
},
MemoryClockAttr: {
Int: helper.Int64ToPtr(1),
Unit: structs.UnitMHz,
},
DisplayStateAttr: {
String: helper.StringToPtr("Enabled"),
},
PersistenceModeAttr: {
String: helper.StringToPtr("Enabled"),
},
DriverVersionAttr: {
String: helper.StringToPtr("1"),
},
},
},
{
@ -1062,16 +1118,40 @@ func TestWriteFingerprintToChannel(t *testing.T) {
},
},
},
Attributes: map[string]string{
MemoryMiBAttr: "11",
DriverVersionAttr: "1",
PowerWAttr: "100",
BAR1MiBAttr: "256",
PCIBandwidthMBPerSAttr: "1",
CoresClockMHzAttr: "1",
MemoryClockMHzAttr: "1",
DisplayStateAttr: "Enabled",
PersistenceModeAttr: "Enabled",
Attributes: map[string]*structs.Attribute{
MemoryAttr: {
Int: helper.Int64ToPtr(11),
Unit: structs.UnitMiB,
},
PowerAttr: {
Int: helper.Int64ToPtr(100),
Unit: structs.UnitW,
},
BAR1Attr: {
Int: helper.Int64ToPtr(256),
Unit: structs.UnitMiB,
},
PCIBandwidthAttr: {
Int: helper.Int64ToPtr(1),
Unit: structs.UnitMBPerS,
},
CoresClockAttr: {
Int: helper.Int64ToPtr(1),
Unit: structs.UnitMHz,
},
MemoryClockAttr: {
Int: helper.Int64ToPtr(1),
Unit: structs.UnitMHz,
},
DisplayStateAttr: {
String: helper.StringToPtr("Enabled"),
},
PersistenceModeAttr: {
String: helper.StringToPtr("Enabled"),
},
DriverVersionAttr: {
String: helper.StringToPtr("1"),
},
},
},
},
@ -1092,7 +1172,7 @@ func TestWriteFingerprintToChannel(t *testing.T) {
sort.Slice(testCase.ExpectedWriteToChannel.Devices, func(i, j int) bool {
return testCase.ExpectedWriteToChannel.Devices[i].Name < testCase.ExpectedWriteToChannel.Devices[j].Name
})
require.New(t).Equal(testCase.ExpectedWriteToChannel, actualResult)
require.Equal(t, testCase.ExpectedWriteToChannel, actualResult)
})
}
}
@ -1191,16 +1271,40 @@ func TestFingerprint(t *testing.T) {
},
},
},
Attributes: map[string]string{
MemoryMiBAttr: "10",
DriverVersionAttr: "1",
PowerWAttr: "100",
BAR1MiBAttr: "256",
PCIBandwidthMBPerSAttr: "1",
CoresClockMHzAttr: "1",
MemoryClockMHzAttr: "1",
DisplayStateAttr: "Enabled",
PersistenceModeAttr: "Enabled",
Attributes: map[string]*structs.Attribute{
MemoryAttr: {
Int: helper.Int64ToPtr(10),
Unit: structs.UnitMiB,
},
PowerAttr: {
Int: helper.Int64ToPtr(100),
Unit: structs.UnitW,
},
BAR1Attr: {
Int: helper.Int64ToPtr(256),
Unit: structs.UnitMiB,
},
PCIBandwidthAttr: {
Int: helper.Int64ToPtr(1),
Unit: structs.UnitMBPerS,
},
CoresClockAttr: {
Int: helper.Int64ToPtr(1),
Unit: structs.UnitMHz,
},
MemoryClockAttr: {
Int: helper.Int64ToPtr(1),
Unit: structs.UnitMHz,
},
DisplayStateAttr: {
String: helper.StringToPtr("Enabled"),
},
PersistenceModeAttr: {
String: helper.StringToPtr("Enabled"),
},
DriverVersionAttr: {
String: helper.StringToPtr("1"),
},
},
},
},

View file

@ -5,6 +5,7 @@ import (
"time"
"github.com/hashicorp/nomad/plugins/base"
"github.com/hashicorp/nomad/plugins/shared/structs"
)
const (
@ -69,7 +70,7 @@ type DeviceGroup struct {
Devices []*Device
// Attributes are a set of attributes shared for all the devices.
Attributes map[string]string
Attributes map[string]*structs.Attribute
}
// Device is an instance of a particular device.

View file

@ -8,6 +8,9 @@ import (
pb "github.com/golang/protobuf/proto"
plugin "github.com/hashicorp/go-plugin"
"github.com/hashicorp/nomad/helper"
psstructs "github.com/hashicorp/nomad/plugins/shared/structs"
"github.com/hashicorp/nomad/nomad/structs"
"github.com/hashicorp/nomad/plugins/base"
"github.com/hashicorp/nomad/plugins/shared/hclspec"
@ -179,6 +182,12 @@ func TestDevicePlugin_Fingerprint(t *testing.T) {
Vendor: "nvidia",
Type: DeviceTypeGPU,
Name: "foo",
Attributes: map[string]*psstructs.Attribute{
"memory": {
Int: helper.Int64ToPtr(4),
Unit: "GiB",
},
},
},
}
devices2 := []*DeviceGroup{

View file

@ -7,6 +7,7 @@ import proto "github.com/golang/protobuf/proto"
import fmt "fmt"
import math "math"
import timestamp "github.com/golang/protobuf/ptypes/timestamp"
import proto1 "github.com/hashicorp/nomad/plugins/shared/structs/proto"
import (
context "golang.org/x/net/context"
@ -35,7 +36,7 @@ func (m *FingerprintRequest) Reset() { *m = FingerprintRequest{} }
func (m *FingerprintRequest) String() string { return proto.CompactTextString(m) }
func (*FingerprintRequest) ProtoMessage() {}
func (*FingerprintRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_device_ebefe60214c28313, []int{0}
return fileDescriptor_device_c5ad1463d0f8d225, []int{0}
}
func (m *FingerprintRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_FingerprintRequest.Unmarshal(m, b)
@ -70,7 +71,7 @@ func (m *FingerprintResponse) Reset() { *m = FingerprintResponse{} }
func (m *FingerprintResponse) String() string { return proto.CompactTextString(m) }
func (*FingerprintResponse) ProtoMessage() {}
func (*FingerprintResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_device_ebefe60214c28313, []int{1}
return fileDescriptor_device_c5ad1463d0f8d225, []int{1}
}
func (m *FingerprintResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_FingerprintResponse.Unmarshal(m, b)
@ -109,17 +110,17 @@ type DeviceGroup struct {
Devices []*DetectedDevice `protobuf:"bytes,4,rep,name=devices,proto3" json:"devices,omitempty"`
// attributes allows adding attributes to be used for constraints or
// affinities.
Attributes map[string]string `protobuf:"bytes,5,rep,name=attributes,proto3" json:"attributes,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
Attributes map[string]*proto1.Attribute `protobuf:"bytes,5,rep,name=attributes,proto3" json:"attributes,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *DeviceGroup) Reset() { *m = DeviceGroup{} }
func (m *DeviceGroup) String() string { return proto.CompactTextString(m) }
func (*DeviceGroup) ProtoMessage() {}
func (*DeviceGroup) Descriptor() ([]byte, []int) {
return fileDescriptor_device_ebefe60214c28313, []int{2}
return fileDescriptor_device_c5ad1463d0f8d225, []int{2}
}
func (m *DeviceGroup) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_DeviceGroup.Unmarshal(m, b)
@ -167,7 +168,7 @@ func (m *DeviceGroup) GetDevices() []*DetectedDevice {
return nil
}
func (m *DeviceGroup) GetAttributes() map[string]string {
func (m *DeviceGroup) GetAttributes() map[string]*proto1.Attribute {
if m != nil {
return m.Attributes
}
@ -196,7 +197,7 @@ func (m *DetectedDevice) Reset() { *m = DetectedDevice{} }
func (m *DetectedDevice) String() string { return proto.CompactTextString(m) }
func (*DetectedDevice) ProtoMessage() {}
func (*DetectedDevice) Descriptor() ([]byte, []int) {
return fileDescriptor_device_ebefe60214c28313, []int{3}
return fileDescriptor_device_c5ad1463d0f8d225, []int{3}
}
func (m *DetectedDevice) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_DetectedDevice.Unmarshal(m, b)
@ -258,7 +259,7 @@ func (m *DeviceLocality) Reset() { *m = DeviceLocality{} }
func (m *DeviceLocality) String() string { return proto.CompactTextString(m) }
func (*DeviceLocality) ProtoMessage() {}
func (*DeviceLocality) Descriptor() ([]byte, []int) {
return fileDescriptor_device_ebefe60214c28313, []int{4}
return fileDescriptor_device_c5ad1463d0f8d225, []int{4}
}
func (m *DeviceLocality) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_DeviceLocality.Unmarshal(m, b)
@ -299,7 +300,7 @@ func (m *ReserveRequest) Reset() { *m = ReserveRequest{} }
func (m *ReserveRequest) String() string { return proto.CompactTextString(m) }
func (*ReserveRequest) ProtoMessage() {}
func (*ReserveRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_device_ebefe60214c28313, []int{5}
return fileDescriptor_device_c5ad1463d0f8d225, []int{5}
}
func (m *ReserveRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ReserveRequest.Unmarshal(m, b)
@ -342,7 +343,7 @@ func (m *ReserveResponse) Reset() { *m = ReserveResponse{} }
func (m *ReserveResponse) String() string { return proto.CompactTextString(m) }
func (*ReserveResponse) ProtoMessage() {}
func (*ReserveResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_device_ebefe60214c28313, []int{6}
return fileDescriptor_device_c5ad1463d0f8d225, []int{6}
}
func (m *ReserveResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ReserveResponse.Unmarshal(m, b)
@ -387,7 +388,7 @@ func (m *ContainerReservation) Reset() { *m = ContainerReservation{} }
func (m *ContainerReservation) String() string { return proto.CompactTextString(m) }
func (*ContainerReservation) ProtoMessage() {}
func (*ContainerReservation) Descriptor() ([]byte, []int) {
return fileDescriptor_device_ebefe60214c28313, []int{7}
return fileDescriptor_device_c5ad1463d0f8d225, []int{7}
}
func (m *ContainerReservation) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_ContainerReservation.Unmarshal(m, b)
@ -446,7 +447,7 @@ func (m *Mount) Reset() { *m = Mount{} }
func (m *Mount) String() string { return proto.CompactTextString(m) }
func (*Mount) ProtoMessage() {}
func (*Mount) Descriptor() ([]byte, []int) {
return fileDescriptor_device_ebefe60214c28313, []int{8}
return fileDescriptor_device_c5ad1463d0f8d225, []int{8}
}
func (m *Mount) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Mount.Unmarshal(m, b)
@ -507,7 +508,7 @@ func (m *DeviceSpec) Reset() { *m = DeviceSpec{} }
func (m *DeviceSpec) String() string { return proto.CompactTextString(m) }
func (*DeviceSpec) ProtoMessage() {}
func (*DeviceSpec) Descriptor() ([]byte, []int) {
return fileDescriptor_device_ebefe60214c28313, []int{9}
return fileDescriptor_device_c5ad1463d0f8d225, []int{9}
}
func (m *DeviceSpec) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_DeviceSpec.Unmarshal(m, b)
@ -559,7 +560,7 @@ func (m *StatsRequest) Reset() { *m = StatsRequest{} }
func (m *StatsRequest) String() string { return proto.CompactTextString(m) }
func (*StatsRequest) ProtoMessage() {}
func (*StatsRequest) Descriptor() ([]byte, []int) {
return fileDescriptor_device_ebefe60214c28313, []int{10}
return fileDescriptor_device_c5ad1463d0f8d225, []int{10}
}
func (m *StatsRequest) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_StatsRequest.Unmarshal(m, b)
@ -592,7 +593,7 @@ func (m *StatsResponse) Reset() { *m = StatsResponse{} }
func (m *StatsResponse) String() string { return proto.CompactTextString(m) }
func (*StatsResponse) ProtoMessage() {}
func (*StatsResponse) Descriptor() ([]byte, []int) {
return fileDescriptor_device_ebefe60214c28313, []int{11}
return fileDescriptor_device_c5ad1463d0f8d225, []int{11}
}
func (m *StatsResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_StatsResponse.Unmarshal(m, b)
@ -636,7 +637,7 @@ func (m *DeviceGroupStats) Reset() { *m = DeviceGroupStats{} }
func (m *DeviceGroupStats) String() string { return proto.CompactTextString(m) }
func (*DeviceGroupStats) ProtoMessage() {}
func (*DeviceGroupStats) Descriptor() ([]byte, []int) {
return fileDescriptor_device_ebefe60214c28313, []int{12}
return fileDescriptor_device_c5ad1463d0f8d225, []int{12}
}
func (m *DeviceGroupStats) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_DeviceGroupStats.Unmarshal(m, b)
@ -702,7 +703,7 @@ func (m *DeviceStats) Reset() { *m = DeviceStats{} }
func (m *DeviceStats) String() string { return proto.CompactTextString(m) }
func (*DeviceStats) ProtoMessage() {}
func (*DeviceStats) Descriptor() ([]byte, []int) {
return fileDescriptor_device_ebefe60214c28313, []int{13}
return fileDescriptor_device_c5ad1463d0f8d225, []int{13}
}
func (m *DeviceStats) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_DeviceStats.Unmarshal(m, b)
@ -759,7 +760,7 @@ func (m *StatObject) Reset() { *m = StatObject{} }
func (m *StatObject) String() string { return proto.CompactTextString(m) }
func (*StatObject) ProtoMessage() {}
func (*StatObject) Descriptor() ([]byte, []int) {
return fileDescriptor_device_ebefe60214c28313, []int{14}
return fileDescriptor_device_c5ad1463d0f8d225, []int{14}
}
func (m *StatObject) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_StatObject.Unmarshal(m, b)
@ -824,7 +825,7 @@ func (m *StatValue) Reset() { *m = StatValue{} }
func (m *StatValue) String() string { return proto.CompactTextString(m) }
func (*StatValue) ProtoMessage() {}
func (*StatValue) Descriptor() ([]byte, []int) {
return fileDescriptor_device_ebefe60214c28313, []int{15}
return fileDescriptor_device_c5ad1463d0f8d225, []int{15}
}
func (m *StatValue) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_StatValue.Unmarshal(m, b)
@ -904,7 +905,7 @@ func init() {
proto.RegisterType((*FingerprintRequest)(nil), "hashicorp.nomad.plugins.device.FingerprintRequest")
proto.RegisterType((*FingerprintResponse)(nil), "hashicorp.nomad.plugins.device.FingerprintResponse")
proto.RegisterType((*DeviceGroup)(nil), "hashicorp.nomad.plugins.device.DeviceGroup")
proto.RegisterMapType((map[string]string)(nil), "hashicorp.nomad.plugins.device.DeviceGroup.AttributesEntry")
proto.RegisterMapType((map[string]*proto1.Attribute)(nil), "hashicorp.nomad.plugins.device.DeviceGroup.AttributesEntry")
proto.RegisterType((*DetectedDevice)(nil), "hashicorp.nomad.plugins.device.DetectedDevice")
proto.RegisterType((*DeviceLocality)(nil), "hashicorp.nomad.plugins.device.DeviceLocality")
proto.RegisterType((*ReserveRequest)(nil), "hashicorp.nomad.plugins.device.ReserveRequest")
@ -1134,77 +1135,80 @@ var _DevicePlugin_serviceDesc = grpc.ServiceDesc{
}
func init() {
proto.RegisterFile("github.com/hashicorp/nomad/plugins/device/proto/device.proto", fileDescriptor_device_ebefe60214c28313)
proto.RegisterFile("github.com/hashicorp/nomad/plugins/device/proto/device.proto", fileDescriptor_device_c5ad1463d0f8d225)
}
var fileDescriptor_device_ebefe60214c28313 = []byte{
// 1086 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x56, 0xeb, 0x8e, 0xdb, 0x44,
0x14, 0x26, 0xf7, 0xe4, 0x64, 0x2f, 0xdd, 0xd9, 0x05, 0x85, 0x40, 0xe9, 0xca, 0x12, 0x52, 0x59,
0xa8, 0x53, 0xa5, 0x08, 0xaa, 0x42, 0xa1, 0xed, 0xa6, 0xd0, 0x95, 0x60, 0xb7, 0x72, 0xab, 0x4a,
0x2d, 0x12, 0xd6, 0xc4, 0x9e, 0xc6, 0xd3, 0xda, 0x33, 0xc6, 0x33, 0x4e, 0x15, 0xde, 0x80, 0x37,
0xe1, 0x4f, 0x5f, 0x80, 0x77, 0x80, 0x87, 0xe0, 0x49, 0xd0, 0x5c, 0x9c, 0x38, 0xdb, 0xa5, 0x49,
0xe0, 0x97, 0xe7, 0x5c, 0xbe, 0x6f, 0x8e, 0xcf, 0x39, 0x73, 0x66, 0xe0, 0xeb, 0x09, 0x95, 0x51,
0x3e, 0x76, 0x03, 0x9e, 0x0c, 0x22, 0x2c, 0x22, 0x1a, 0xf0, 0x2c, 0x1d, 0x30, 0x9e, 0xe0, 0x70,
0x90, 0xc6, 0xf9, 0x84, 0x32, 0x31, 0x08, 0xc9, 0x94, 0x06, 0x64, 0x90, 0x66, 0x5c, 0x72, 0x2b,
0xb8, 0x5a, 0x40, 0x1f, 0xcd, 0x21, 0xae, 0x86, 0xb8, 0x16, 0xe2, 0x1a, 0xaf, 0xfe, 0x95, 0x09,
0xe7, 0x93, 0xd8, 0x42, 0xc7, 0xf9, 0xf3, 0x81, 0xa4, 0x09, 0x11, 0x12, 0x27, 0xa9, 0x21, 0x70,
0x0e, 0x00, 0x7d, 0x47, 0xd9, 0x84, 0x64, 0x69, 0x46, 0x99, 0xf4, 0xc8, 0x2f, 0x39, 0x11, 0xd2,
0x21, 0xb0, 0xbf, 0xa4, 0x15, 0x29, 0x67, 0x82, 0xa0, 0x53, 0xd8, 0x32, 0xbc, 0xfe, 0x24, 0xe3,
0x79, 0xda, 0xab, 0x1c, 0xd6, 0xae, 0x76, 0x87, 0x9f, 0xba, 0x6f, 0x0f, 0xc2, 0x1d, 0xe9, 0xcf,
0xf7, 0x0a, 0xe2, 0x75, 0xc3, 0x85, 0xe0, 0xfc, 0x59, 0x85, 0x6e, 0xc9, 0x88, 0xde, 0x83, 0xe6,
0x94, 0xb0, 0x90, 0x67, 0xbd, 0xca, 0x61, 0xe5, 0x6a, 0xc7, 0xb3, 0x12, 0xba, 0x02, 0x16, 0xe6,
0xcb, 0x59, 0x4a, 0x7a, 0x55, 0x6d, 0x04, 0xa3, 0x7a, 0x3c, 0x4b, 0x49, 0xc9, 0x81, 0xe1, 0x84,
0xf4, 0x6a, 0x65, 0x87, 0x53, 0x9c, 0x10, 0xf4, 0x00, 0x5a, 0x46, 0x12, 0xbd, 0xba, 0x0e, 0xda,
0x5d, 0x1d, 0xb4, 0x24, 0x81, 0x24, 0xa1, 0x89, 0xcf, 0x2b, 0xe0, 0xe8, 0x27, 0x00, 0x2c, 0x65,
0x46, 0xc7, 0xb9, 0x24, 0xa2, 0xd7, 0xd0, 0x64, 0x5f, 0x6d, 0x90, 0x01, 0xf7, 0xee, 0x1c, 0x7d,
0x9f, 0xc9, 0x6c, 0xe6, 0x95, 0xe8, 0xfa, 0xb7, 0x61, 0xf7, 0x9c, 0x19, 0x5d, 0x82, 0xda, 0x4b,
0x32, 0xb3, 0x09, 0x51, 0x4b, 0x74, 0x00, 0x8d, 0x29, 0x8e, 0xf3, 0x22, 0x0f, 0x46, 0xb8, 0x55,
0xbd, 0x59, 0x71, 0xfe, 0xa8, 0xc0, 0xce, 0x72, 0xdc, 0x68, 0x07, 0xaa, 0x27, 0x23, 0x8b, 0xae,
0x9e, 0x8c, 0x50, 0x0f, 0x5a, 0x11, 0xc1, 0xb1, 0x8c, 0x66, 0x1a, 0xde, 0xf6, 0x0a, 0x11, 0x5d,
0x03, 0x64, 0x96, 0x7e, 0x48, 0x44, 0x90, 0xd1, 0x54, 0x52, 0xce, 0x6c, 0x2a, 0xf7, 0x8c, 0x65,
0xb4, 0x30, 0xa0, 0x33, 0xe8, 0x46, 0xaf, 0xfc, 0x98, 0x07, 0x38, 0xa6, 0x72, 0xd6, 0xab, 0x1f,
0x56, 0xd6, 0xcb, 0xaa, 0xfa, 0xfc, 0x60, 0x51, 0x1e, 0x44, 0xaf, 0x8a, 0xb5, 0xe3, 0xaa, 0xd8,
0xcb, 0x56, 0xf4, 0x21, 0x40, 0x1a, 0x50, 0x7f, 0x9c, 0x0b, 0x9f, 0x86, 0xf6, 0x1f, 0xda, 0x69,
0x40, 0xef, 0xe5, 0xe2, 0x24, 0x74, 0x06, 0xb0, 0xe3, 0x11, 0x41, 0xb2, 0x29, 0xb1, 0x5d, 0x8b,
0x2e, 0x83, 0x2d, 0xb9, 0x4f, 0x43, 0xa1, 0x9b, 0xb3, 0xe3, 0x75, 0x8c, 0xe6, 0x24, 0x14, 0x4e,
0x0c, 0xbb, 0x73, 0x80, 0x6d, 0xe8, 0xa7, 0xb0, 0x1d, 0x70, 0x26, 0x31, 0x65, 0x24, 0xf3, 0x33,
0x22, 0xf4, 0x26, 0xdd, 0xe1, 0xe7, 0xab, 0x7e, 0xe3, 0xb8, 0x00, 0x19, 0x42, 0xac, 0x32, 0xe2,
0x6d, 0x05, 0x25, 0xad, 0xf3, 0x7b, 0x15, 0x0e, 0x2e, 0x72, 0x43, 0x1e, 0xd4, 0x09, 0x9b, 0x0a,
0x7b, 0x78, 0xbe, 0xf9, 0x2f, 0x5b, 0xb9, 0xf7, 0xd9, 0xd4, 0x76, 0x8f, 0xe6, 0x42, 0xb7, 0xa1,
0x99, 0xf0, 0x9c, 0x49, 0xd1, 0xab, 0x6a, 0xd6, 0x8f, 0x57, 0xb1, 0xfe, 0xa8, 0xbc, 0x3d, 0x0b,
0x42, 0xa3, 0xc5, 0xe9, 0xa8, 0x69, 0xfc, 0xd1, 0x7a, 0x75, 0x7c, 0x94, 0x92, 0x60, 0x7e, 0x32,
0xfa, 0x5f, 0x42, 0x67, 0x1e, 0xd7, 0x46, 0x6d, 0xfb, 0x33, 0x34, 0x74, 0x3c, 0xe8, 0x03, 0xe8,
0x48, 0x2c, 0x5e, 0xfa, 0x29, 0x96, 0x51, 0x51, 0x6f, 0xa5, 0x78, 0x88, 0x65, 0xa4, 0x8c, 0x11,
0x17, 0xd2, 0x18, 0x0d, 0x47, 0x5b, 0x29, 0x0a, 0x63, 0x46, 0x70, 0xe8, 0x73, 0x16, 0xcf, 0x74,
0xcf, 0xb6, 0xbd, 0xb6, 0x52, 0x9c, 0xb1, 0x78, 0xe6, 0x44, 0x00, 0x8b, 0x78, 0xff, 0xc7, 0x26,
0x87, 0xd0, 0x4d, 0x49, 0x96, 0x50, 0x21, 0x28, 0x67, 0xc2, 0x1e, 0x8d, 0xb2, 0xca, 0xd9, 0x81,
0xad, 0x47, 0x12, 0x4b, 0x51, 0xcc, 0xd1, 0xa7, 0xb0, 0x6d, 0x65, 0xdb, 0x70, 0x0f, 0xa0, 0xa9,
0x47, 0x67, 0x51, 0xfe, 0xeb, 0x1b, 0x4c, 0x0e, 0xc3, 0x64, 0xf1, 0xce, 0xeb, 0x2a, 0x5c, 0x3a,
0x6f, 0xfc, 0xd7, 0x01, 0x8a, 0xa0, 0x5e, 0x9a, 0x9c, 0x7a, 0xad, 0x74, 0xa5, 0x61, 0xa9, 0xd7,
0xe8, 0x05, 0xec, 0x50, 0x26, 0x24, 0x66, 0x01, 0xf1, 0x85, 0x62, 0xb4, 0xd3, 0xf2, 0x78, 0xd3,
0x30, 0xdd, 0x13, 0x4b, 0xa3, 0x25, 0xd3, 0xaa, 0xdb, 0xb4, 0xac, 0xeb, 0x27, 0x80, 0xde, 0x74,
0xba, 0xa0, 0x6f, 0xee, 0x96, 0xfb, 0x66, 0xed, 0xdb, 0xc6, 0x24, 0xab, 0xd4, 0x64, 0x7f, 0x55,
0x8a, 0xbb, 0xc6, 0xa4, 0xea, 0x18, 0x5a, 0x22, 0x4f, 0x12, 0x9c, 0xcd, 0xec, 0xa1, 0xff, 0x64,
0x15, 0xb1, 0xc2, 0x3d, 0x51, 0x7c, 0x5e, 0x81, 0x44, 0x77, 0xa0, 0x61, 0xd2, 0x64, 0x62, 0x3b,
0x5a, 0x87, 0xe2, 0x6c, 0xfc, 0x82, 0x04, 0xd2, 0x33, 0x40, 0x74, 0x13, 0x3a, 0xf3, 0x2b, 0x59,
0x97, 0xa2, 0x3b, 0xec, 0xbb, 0xe6, 0xd2, 0x76, 0x8b, 0x4b, 0xdb, 0x7d, 0x5c, 0x78, 0x78, 0x0b,
0x67, 0xe7, 0xb7, 0x1a, 0xc0, 0x82, 0x0f, 0x9d, 0x42, 0x93, 0x11, 0x21, 0x49, 0x68, 0x3b, 0xeb,
0x8b, 0xf5, 0x63, 0x71, 0x4f, 0x35, 0xd0, 0x54, 0xc9, 0xb2, 0xa0, 0x67, 0x4b, 0xf7, 0x9c, 0x19,
0x2b, 0xb7, 0x36, 0xe0, 0x7c, 0xdb, 0x35, 0x47, 0xa0, 0x5b, 0xda, 0xf2, 0x82, 0x9a, 0xdf, 0x59,
0xae, 0xf9, 0x46, 0x79, 0x9d, 0x97, 0xbc, 0x1f, 0xad, 0x73, 0x9b, 0x7e, 0xbb, 0xbc, 0xd5, 0x06,
0x5d, 0x50, 0x6a, 0xae, 0xd7, 0x55, 0xe8, 0xcc, 0x0d, 0xc8, 0x85, 0xfd, 0xe7, 0x31, 0xc7, 0xd2,
0x67, 0x79, 0x42, 0x32, 0x2c, 0x79, 0xe6, 0x4f, 0x71, 0xac, 0x37, 0xad, 0x78, 0x7b, 0xda, 0x74,
0x5a, 0x58, 0x9e, 0xe0, 0x18, 0x0d, 0xe1, 0x5d, 0xe3, 0x1f, 0x12, 0xc6, 0x13, 0xca, 0xe6, 0x88,
0xaa, 0x46, 0x18, 0xb2, 0xd1, 0xc2, 0xa6, 0x30, 0x47, 0xb0, 0x47, 0xd9, 0xf9, 0x1d, 0x54, 0xff,
0xd4, 0xbc, 0x5d, 0xca, 0x96, 0xf9, 0x5d, 0xd8, 0x57, 0xbe, 0xe7, 0xd9, 0xeb, 0xda, 0x5b, 0xd1,
0x9c, 0xe3, 0xbe, 0x0c, 0x20, 0x64, 0x46, 0xd9, 0x44, 0xbb, 0x35, 0x74, 0xae, 0x3a, 0x46, 0xa3,
0xcc, 0xef, 0x43, 0x7b, 0xcc, 0x79, 0xac, 0x8d, 0x4d, 0xf3, 0x86, 0x50, 0xb2, 0x32, 0x21, 0xa8,
0xe7, 0x8c, 0xca, 0x5e, 0xcb, 0xcc, 0x14, 0xb5, 0x56, 0x3a, 0xf5, 0xa0, 0xe8, 0xb5, 0x8d, 0x4e,
0xad, 0x87, 0x7f, 0x57, 0x61, 0xcb, 0x1c, 0xc6, 0x87, 0x3a, 0xbb, 0xe8, 0x57, 0xe8, 0x96, 0x1e,
0x9c, 0x68, 0xb8, 0xaa, 0x0a, 0x6f, 0xbe, 0x59, 0xfb, 0x37, 0x36, 0xc2, 0x98, 0x79, 0xec, 0xbc,
0x73, 0xbd, 0x82, 0x62, 0x68, 0xd9, 0x77, 0x01, 0x5a, 0xf9, 0x7e, 0x59, 0x7e, 0x71, 0xf4, 0x07,
0x6b, 0xfb, 0x17, 0xfb, 0xa1, 0x08, 0x1a, 0x66, 0x00, 0x7d, 0xb6, 0x4e, 0xa7, 0x15, 0x37, 0x49,
0xff, 0xda, 0x9a, 0xde, 0x8b, 0xff, 0xba, 0xd7, 0x7a, 0xd6, 0x30, 0x13, 0xa4, 0xa9, 0x3f, 0x37,
0xfe, 0x09, 0x00, 0x00, 0xff, 0xff, 0xe4, 0x5c, 0x8f, 0xd7, 0x6b, 0x0c, 0x00, 0x00,
var fileDescriptor_device_c5ad1463d0f8d225 = []byte{
// 1129 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x56, 0xef, 0x8e, 0xdb, 0x44,
0x10, 0x27, 0xff, 0x93, 0xc9, 0xf5, 0xda, 0xdb, 0x3b, 0x50, 0x08, 0x94, 0x9e, 0x2c, 0x21, 0x95,
0x83, 0x3a, 0x25, 0x45, 0x50, 0x95, 0x7f, 0x6d, 0x2f, 0xe5, 0x7a, 0x12, 0xdc, 0x55, 0x6e, 0x55,
0xa9, 0x45, 0xc2, 0xda, 0xd8, 0xdb, 0x78, 0x5b, 0x7b, 0xd7, 0x78, 0xd7, 0xa9, 0xc2, 0x27, 0xbe,
0xf2, 0x26, 0x7c, 0xe9, 0x0b, 0xf0, 0x10, 0x3c, 0x04, 0x4f, 0x82, 0xf6, 0x8f, 0x13, 0xe7, 0x7a,
0x6d, 0x12, 0xf8, 0xe4, 0xdd, 0x99, 0xf9, 0xfd, 0x66, 0x3c, 0x3b, 0x3b, 0x3b, 0xf0, 0xcd, 0x84,
0xca, 0x28, 0x1f, 0xbb, 0x01, 0x4f, 0x06, 0x11, 0x16, 0x11, 0x0d, 0x78, 0x96, 0x0e, 0x18, 0x4f,
0x70, 0x38, 0x48, 0xe3, 0x7c, 0x42, 0x99, 0x18, 0x84, 0x64, 0x4a, 0x03, 0x32, 0x48, 0x33, 0x2e,
0xb9, 0xdd, 0xb8, 0x7a, 0x83, 0x3e, 0x9a, 0x43, 0x5c, 0x0d, 0x71, 0x2d, 0xc4, 0x35, 0x56, 0xfd,
0x2b, 0x13, 0xce, 0x27, 0xb1, 0x85, 0x8e, 0xf3, 0x67, 0x03, 0x49, 0x13, 0x22, 0x24, 0x4e, 0x52,
0x43, 0xd0, 0x3f, 0x5a, 0xc3, 0xbd, 0x88, 0x70, 0x46, 0xc2, 0x81, 0x90, 0x59, 0x1e, 0x48, 0x61,
0xc3, 0xc0, 0x52, 0x66, 0x74, 0x9c, 0x4b, 0x1b, 0x89, 0xb3, 0x07, 0xe8, 0x07, 0xca, 0x26, 0x24,
0x4b, 0x33, 0xca, 0xa4, 0x47, 0x7e, 0xcd, 0x89, 0x90, 0x0e, 0x81, 0xdd, 0x25, 0xa9, 0x48, 0x39,
0x13, 0x04, 0x9d, 0xc0, 0x96, 0x09, 0xd0, 0x9f, 0x64, 0x3c, 0x4f, 0x7b, 0x95, 0xfd, 0xda, 0xd5,
0xee, 0xf0, 0x53, 0xf7, 0xed, 0x7f, 0xe3, 0x8e, 0xf4, 0xe7, 0x48, 0x41, 0xbc, 0x6e, 0xb8, 0xd8,
0x38, 0xbf, 0xd7, 0xa0, 0x5b, 0x52, 0xa2, 0xf7, 0xa0, 0x39, 0x25, 0x2c, 0xe4, 0x59, 0xaf, 0xb2,
0x5f, 0xb9, 0xda, 0xf1, 0xec, 0x0e, 0x5d, 0x01, 0x0b, 0xf3, 0xe5, 0x2c, 0x25, 0xbd, 0xaa, 0x56,
0x82, 0x11, 0x3d, 0x9a, 0xa5, 0xa4, 0x64, 0xc0, 0x70, 0x42, 0x7a, 0xb5, 0xb2, 0xc1, 0x09, 0x4e,
0x08, 0xba, 0x0f, 0x2d, 0xb3, 0x13, 0xbd, 0xba, 0x0e, 0xda, 0x5d, 0x1d, 0xb4, 0x24, 0x81, 0x24,
0xa1, 0x89, 0xcf, 0x2b, 0xe0, 0xe8, 0x67, 0x80, 0x79, 0x0e, 0x45, 0xaf, 0xa1, 0xc9, 0xbe, 0xde,
0x20, 0x03, 0xee, 0x9d, 0x39, 0xfa, 0x1e, 0x93, 0xd9, 0xcc, 0x2b, 0xd1, 0xf5, 0x53, 0xb8, 0x78,
0x46, 0x8d, 0x2e, 0x41, 0xed, 0x05, 0x99, 0xd9, 0x84, 0xa8, 0x25, 0x3a, 0x82, 0xc6, 0x14, 0xc7,
0xb9, 0xc9, 0x43, 0x77, 0xf8, 0xf9, 0x1b, 0x9d, 0x9b, 0x02, 0x70, 0x6d, 0x01, 0x2c, 0x1c, 0x7b,
0x06, 0x7f, 0xab, 0x7a, 0xb3, 0xe2, 0xfc, 0x55, 0x81, 0xed, 0xe5, 0x5f, 0x45, 0xdb, 0x50, 0x3d,
0x1e, 0x59, 0x87, 0xd5, 0xe3, 0x11, 0xea, 0x41, 0x2b, 0x22, 0x38, 0x96, 0xd1, 0x4c, 0x7b, 0x6c,
0x7b, 0xc5, 0x16, 0x5d, 0x03, 0x64, 0x96, 0x7e, 0x48, 0x44, 0x90, 0xd1, 0x54, 0x52, 0xce, 0x6c,
0xf6, 0x77, 0x8c, 0x66, 0xb4, 0x50, 0xa0, 0x53, 0xe8, 0x46, 0x2f, 0xfd, 0x98, 0x07, 0x38, 0xa6,
0x72, 0xd6, 0xab, 0xeb, 0xf0, 0xdd, 0xf5, 0x72, 0xf7, 0xa3, 0x45, 0x79, 0x10, 0xbd, 0x2c, 0xd6,
0x8e, 0xab, 0x62, 0x2f, 0x6b, 0xd1, 0x87, 0x00, 0x69, 0x40, 0xfd, 0x71, 0x2e, 0x7c, 0x1a, 0xda,
0x7f, 0x68, 0xa7, 0x01, 0xbd, 0x9b, 0x8b, 0xe3, 0xd0, 0x19, 0xc0, 0xb6, 0x47, 0x04, 0xc9, 0xa6,
0xc4, 0x16, 0x3a, 0xba, 0x0c, 0xb6, 0x4a, 0x7c, 0x1a, 0x0a, 0x5d, 0xcf, 0x1d, 0xaf, 0x63, 0x24,
0xc7, 0xa1, 0x70, 0x62, 0xb8, 0x38, 0x07, 0xd8, 0x3b, 0xf0, 0x04, 0x2e, 0x04, 0x9c, 0x49, 0x4c,
0x19, 0xc9, 0xfc, 0x8c, 0x08, 0xed, 0xa4, 0x3b, 0xfc, 0x62, 0xd5, 0x6f, 0x1c, 0x16, 0x20, 0x43,
0x88, 0x55, 0x46, 0xbc, 0xad, 0xa0, 0x24, 0x75, 0xfe, 0xac, 0xc2, 0xde, 0x79, 0x66, 0xc8, 0x83,
0x3a, 0x61, 0x53, 0x61, 0xef, 0xdb, 0x77, 0xff, 0xc5, 0x95, 0x7b, 0x8f, 0x4d, 0x6d, 0xc1, 0x69,
0x2e, 0xf4, 0x2d, 0x34, 0x13, 0x9e, 0x33, 0x29, 0x7a, 0x55, 0xcd, 0xfa, 0xf1, 0x2a, 0xd6, 0x9f,
0x94, 0xb5, 0x67, 0x41, 0x68, 0xb4, 0xb8, 0x50, 0x35, 0x8d, 0x3f, 0x58, 0xef, 0x1c, 0x1f, 0xa6,
0x24, 0x98, 0x5f, 0xa6, 0xfe, 0x57, 0xd0, 0x99, 0xc7, 0x75, 0x4e, 0xa5, 0xef, 0x95, 0x2b, 0xbd,
0x53, 0x2e, 0xdb, 0x5f, 0xa0, 0xa1, 0xe3, 0x41, 0x1f, 0x40, 0x47, 0x62, 0xf1, 0xc2, 0x4f, 0xb1,
0x8c, 0x8a, 0xf3, 0x56, 0x82, 0x07, 0x58, 0x46, 0x4a, 0x19, 0x71, 0x21, 0x8d, 0xd2, 0x70, 0xb4,
0x95, 0xa0, 0x50, 0x66, 0x04, 0x87, 0x3e, 0x67, 0xf1, 0x4c, 0xd7, 0x6c, 0xdb, 0x6b, 0x2b, 0xc1,
0x29, 0x8b, 0x67, 0x4e, 0x04, 0xb0, 0x88, 0xf7, 0x7f, 0x38, 0xd9, 0x87, 0x6e, 0x4a, 0xb2, 0x84,
0x0a, 0x41, 0x39, 0x13, 0xf6, 0x6a, 0x94, 0x45, 0xce, 0x36, 0x6c, 0x3d, 0x94, 0x58, 0x8a, 0xa2,
0xf5, 0x3e, 0x81, 0x0b, 0x76, 0x6f, 0x0b, 0xee, 0x3e, 0x34, 0x75, 0xb7, 0x2d, 0x8e, 0xff, 0xfa,
0x06, 0xcd, 0xc6, 0x30, 0x59, 0xbc, 0xf3, 0xaa, 0x0a, 0x97, 0xce, 0x2a, 0xdf, 0xd8, 0x73, 0x11,
0xd4, 0x4b, 0xcd, 0x56, 0xaf, 0x95, 0xac, 0xd4, 0x5f, 0xf5, 0x1a, 0x3d, 0x87, 0x6d, 0xca, 0x84,
0xc4, 0x2c, 0x20, 0xbe, 0x50, 0x8c, 0xb6, 0xc1, 0x1e, 0x6e, 0x1a, 0xa6, 0x7b, 0x6c, 0x69, 0xf4,
0xce, 0x94, 0xea, 0x05, 0x5a, 0x96, 0xf5, 0x13, 0x40, 0xaf, 0x1b, 0x9d, 0x53, 0x37, 0x77, 0x96,
0x3b, 0xe4, 0x9a, 0x0f, 0x94, 0x49, 0x56, 0xa9, 0xc8, 0xfe, 0xae, 0x14, 0xcf, 0x93, 0x49, 0xd5,
0x21, 0xb4, 0x44, 0x9e, 0x24, 0x38, 0x9b, 0xd9, 0x4b, 0xff, 0xc9, 0x2a, 0x62, 0x85, 0x7b, 0xac,
0xf8, 0xbc, 0x02, 0x89, 0x6e, 0x43, 0xc3, 0xa4, 0xc9, 0xc4, 0x76, 0xb0, 0x0e, 0xc5, 0xe9, 0xf8,
0x39, 0x09, 0xa4, 0x67, 0x80, 0xe8, 0x26, 0x74, 0xe6, 0xe3, 0x80, 0x3e, 0x8a, 0xee, 0xb0, 0xef,
0x9a, 0x81, 0xc1, 0x2d, 0x06, 0x06, 0xf7, 0x51, 0x61, 0xe1, 0x2d, 0x8c, 0x9d, 0x3f, 0x6a, 0x00,
0x0b, 0x3e, 0x74, 0x02, 0x4d, 0x46, 0x84, 0x24, 0xa1, 0xad, 0xac, 0x2f, 0xd7, 0x8f, 0xc5, 0x3d,
0xd1, 0x40, 0x73, 0x4a, 0x96, 0x05, 0x3d, 0x5d, 0x7a, 0x1a, 0x4d, 0x5b, 0xb9, 0xb5, 0x01, 0xe7,
0xdb, 0x5e, 0x46, 0x02, 0xdd, 0x92, 0xcb, 0x73, 0xce, 0xfc, 0xf6, 0xf2, 0x99, 0x6f, 0x94, 0xd7,
0xf9, 0x91, 0xf7, 0xa3, 0x75, 0x1e, 0xe0, 0xef, 0x97, 0x5d, 0x6d, 0x50, 0x05, 0xa5, 0xe2, 0x7a,
0x55, 0x85, 0xce, 0x5c, 0x81, 0x5c, 0xd8, 0x7d, 0x16, 0x73, 0x2c, 0x7d, 0x96, 0x27, 0x24, 0xc3,
0x92, 0x67, 0xfe, 0x14, 0xc7, 0xda, 0x69, 0xc5, 0xdb, 0xd1, 0xaa, 0x93, 0x42, 0xf3, 0x18, 0xc7,
0x68, 0x08, 0xef, 0x1a, 0xfb, 0x90, 0x30, 0x9e, 0x50, 0x36, 0x47, 0x54, 0x35, 0xc2, 0x90, 0x8d,
0x16, 0x3a, 0x85, 0x39, 0x80, 0x1d, 0xca, 0xce, 0x7a, 0x50, 0xf5, 0x53, 0xf3, 0x2e, 0x52, 0xb6,
0xcc, 0xef, 0xc2, 0xae, 0xb2, 0x3d, 0xcb, 0x5e, 0xd7, 0xd6, 0x8a, 0xe6, 0x0c, 0xf7, 0x65, 0x00,
0x21, 0x33, 0xca, 0x26, 0xda, 0xac, 0xa1, 0x73, 0xd5, 0x31, 0x12, 0xa5, 0x7e, 0x1f, 0xda, 0x63,
0xce, 0x63, 0xad, 0x6c, 0x9a, 0x19, 0x42, 0xed, 0x95, 0x0a, 0x41, 0x3d, 0x67, 0x54, 0xf6, 0x5a,
0xa6, 0xa7, 0xa8, 0xb5, 0x92, 0xa9, 0x81, 0xa2, 0xd7, 0x36, 0x32, 0xb5, 0x1e, 0xfe, 0x53, 0x85,
0x2d, 0x73, 0x19, 0x1f, 0xe8, 0xec, 0xa2, 0xdf, 0xa0, 0x5b, 0x9a, 0x51, 0xd1, 0x70, 0xd5, 0x29,
0xbc, 0x3e, 0xe6, 0xf6, 0x6f, 0x6c, 0x84, 0x31, 0xfd, 0xd8, 0x79, 0xe7, 0x7a, 0x05, 0xc5, 0xd0,
0xb2, 0x73, 0x01, 0x5a, 0x39, 0xbf, 0x2c, 0x4f, 0x1c, 0xfd, 0xc1, 0xda, 0xf6, 0x85, 0x3f, 0x14,
0x41, 0xc3, 0x34, 0xa0, 0xcf, 0xd6, 0xa9, 0xb4, 0xe2, 0x25, 0xe9, 0x5f, 0x5b, 0xd3, 0x7a, 0xf1,
0x5f, 0x77, 0x5b, 0x4f, 0x1b, 0xa6, 0x83, 0x34, 0xf5, 0xe7, 0xc6, 0xbf, 0x01, 0x00, 0x00, 0xff,
0xff, 0xe1, 0x29, 0x35, 0x33, 0xe7, 0x0c, 0x00, 0x00,
}

View file

@ -3,6 +3,7 @@ package hashicorp.nomad.plugins.device;
option go_package = "proto";
import "google/protobuf/timestamp.proto";
import "github.com/hashicorp/nomad/plugins/shared/structs/proto/attribute.proto";
// DevicePlugin is the API exposed by device plugins
service DevicePlugin {
@ -48,7 +49,7 @@ message DeviceGroup {
// attributes allows adding attributes to be used for constraints or
// affinities.
map<string, string> attributes = 5;
map<string, hashicorp.nomad.plugins.shared.structs.Attribute> attributes = 5;
}
// DetectedDevice is a single detected device.

View file

@ -1,7 +1,10 @@
package device
import "github.com/hashicorp/nomad/plugins/device/proto"
import "github.com/golang/protobuf/ptypes"
import (
"github.com/golang/protobuf/ptypes"
"github.com/hashicorp/nomad/plugins/device/proto"
"github.com/hashicorp/nomad/plugins/shared/structs"
)
// convertProtoDeviceGroups converts between a list of proto and structs DeviceGroup
func convertProtoDeviceGroups(in []*proto.DeviceGroup) []*DeviceGroup {
@ -28,7 +31,7 @@ func convertProtoDeviceGroup(in *proto.DeviceGroup) *DeviceGroup {
Type: in.DeviceType,
Name: in.DeviceName,
Devices: convertProtoDevices(in.Devices),
Attributes: in.Attributes,
Attributes: structs.ConvertProtoAttributeMap(in.Attributes),
}
}
@ -164,7 +167,7 @@ func convertStructDeviceGroup(in *DeviceGroup) *proto.DeviceGroup {
DeviceType: in.Type,
DeviceName: in.Name,
Devices: convertStructDevices(in.Devices),
Attributes: in.Attributes,
Attributes: structs.ConvertStructAttributeMap(in.Attributes),
}
}

View file

@ -1,5 +1,5 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// source: attribute.proto
// source: github.com/hashicorp/nomad/plugins/shared/structs/proto/attribute.proto
package proto
@ -38,7 +38,7 @@ func (m *Attribute) Reset() { *m = Attribute{} }
func (m *Attribute) String() string { return proto.CompactTextString(m) }
func (*Attribute) ProtoMessage() {}
func (*Attribute) Descriptor() ([]byte, []int) {
return fileDescriptor_attribute_bfac9d16cf08e8f5, []int{0}
return fileDescriptor_attribute_5e512eadce7864ec, []int{0}
}
func (m *Attribute) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_Attribute.Unmarshal(m, b)
@ -229,22 +229,25 @@ func init() {
proto.RegisterType((*Attribute)(nil), "hashicorp.nomad.plugins.shared.structs.Attribute")
}
func init() { proto.RegisterFile("attribute.proto", fileDescriptor_attribute_bfac9d16cf08e8f5) }
var fileDescriptor_attribute_bfac9d16cf08e8f5 = []byte{
// 209 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x34, 0xcf, 0xb1, 0x4e, 0xc3, 0x30,
0x10, 0x06, 0xe0, 0x98, 0x36, 0x4d, 0x7c, 0x0b, 0x92, 0xa7, 0x22, 0x84, 0xb0, 0x18, 0x90, 0x27,
0x2f, 0x3c, 0x01, 0x9d, 0x3c, 0x7b, 0x60, 0x60, 0x41, 0x97, 0x36, 0x34, 0x96, 0x8c, 0x1d, 0xd9,
0xe7, 0x3e, 0x0f, 0x8f, 0x8a, 0xec, 0x88, 0xe9, 0x4e, 0xff, 0x77, 0xff, 0x70, 0x70, 0x8f, 0x44,
0xc9, 0x4d, 0x85, 0x66, 0xbd, 0xa6, 0x48, 0x51, 0xbc, 0x2e, 0x98, 0x17, 0x77, 0x8e, 0x69, 0xd5,
0x21, 0xfe, 0xe0, 0x45, 0xaf, 0xbe, 0x5c, 0x5d, 0xc8, 0x3a, 0x2f, 0x98, 0xe6, 0x8b, 0xce, 0x94,
0xca, 0x99, 0xf2, 0xcb, 0x2f, 0x03, 0xfe, 0xfe, 0xdf, 0x15, 0x4f, 0xc0, 0xbf, 0x7d, 0x44, 0xfa,
0xba, 0xa1, 0x3f, 0x32, 0xc9, 0x14, 0x33, 0x9d, 0x1d, 0x5b, 0xf4, 0x81, 0x5e, 0x3c, 0xc0, 0xe0,
0xc2, 0x86, 0x77, 0x92, 0xa9, 0x9d, 0xe9, 0xec, 0xc1, 0x85, 0x46, 0xcf, 0x00, 0x99, 0x92, 0x0b,
0xd7, 0xa6, 0x3b, 0xc9, 0x14, 0x37, 0x9d, 0xe5, 0x5b, 0x56, 0x0f, 0x1e, 0x61, 0x9c, 0x62, 0xf4,
0x8d, 0xf7, 0x92, 0xa9, 0xd1, 0x74, 0x76, 0xa8, 0x49, 0x45, 0x01, 0xfb, 0x12, 0x1c, 0x1d, 0xfb,
0xda, 0xb3, 0x6d, 0x3f, 0x0d, 0xd0, 0xdf, 0xd0, 0x97, 0xf9, 0x34, 0x7c, 0xf6, 0xed, 0xa7, 0xe9,
0xd0, 0xc6, 0xdb, 0x5f, 0x00, 0x00, 0x00, 0xff, 0xff, 0x79, 0x18, 0x15, 0x15, 0xed, 0x00, 0x00,
0x00,
func init() {
proto.RegisterFile("github.com/hashicorp/nomad/plugins/shared/structs/proto/attribute.proto", fileDescriptor_attribute_5e512eadce7864ec)
}
var fileDescriptor_attribute_5e512eadce7864ec = []byte{
// 229 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x3c, 0x8f, 0xb1, 0x4e, 0xc3, 0x30,
0x10, 0x40, 0x63, 0xda, 0x34, 0xc9, 0x8d, 0x99, 0x8a, 0x10, 0x22, 0x62, 0x40, 0x99, 0xec, 0x81,
0x2f, 0xa0, 0x0b, 0x99, 0x3d, 0x30, 0xb0, 0x20, 0x27, 0x0d, 0x89, 0x25, 0xd7, 0x17, 0xd9, 0xe7,
0x7e, 0x0f, 0x9f, 0x8a, 0x72, 0x29, 0x4c, 0xf6, 0xbd, 0x77, 0x6f, 0x38, 0x78, 0x9f, 0x2c, 0xcd,
0xa9, 0x97, 0x03, 0x5e, 0xd4, 0x6c, 0xe2, 0x6c, 0x07, 0x0c, 0x8b, 0xf2, 0x78, 0x31, 0x67, 0xb5,
0xb8, 0x34, 0x59, 0x1f, 0x55, 0x9c, 0x4d, 0x18, 0xcf, 0x2a, 0x52, 0x48, 0x03, 0x45, 0xb5, 0x04,
0x24, 0x54, 0x86, 0x28, 0xd8, 0x3e, 0xd1, 0x28, 0x79, 0xae, 0x5f, 0xfe, 0x6b, 0xc9, 0xb5, 0xbc,
0xd5, 0x72, 0xab, 0xe5, 0xad, 0x7e, 0xfe, 0x11, 0x50, 0xbd, 0xfd, 0xb5, 0xf5, 0x23, 0x54, 0xdf,
0x0e, 0x0d, 0x7d, 0x5d, 0x8d, 0x3b, 0x8a, 0x46, 0xb4, 0xa2, 0xcb, 0x74, 0xc9, 0xe8, 0xc3, 0xb8,
0xfa, 0x1e, 0x0a, 0xeb, 0x37, 0x79, 0xd7, 0x88, 0x76, 0xd7, 0x65, 0xfa, 0x60, 0x3d, 0xab, 0x27,
0x80, 0x48, 0xc1, 0xfa, 0x89, 0xed, 0xae, 0x11, 0x6d, 0xd5, 0x65, 0xba, 0xda, 0xd8, 0xba, 0xf0,
0x00, 0x65, 0x8f, 0xe8, 0x58, 0xef, 0x1b, 0xd1, 0x96, 0x5d, 0xa6, 0x8b, 0x95, 0xac, 0xb2, 0x86,
0x7d, 0xf2, 0x96, 0x8e, 0xf9, 0xda, 0x69, 0xfe, 0x9f, 0x0a, 0xc8, 0xaf, 0xc6, 0xa5, 0xf1, 0x54,
0x7c, 0xe6, 0x7c, 0x53, 0x7f, 0xe0, 0xe7, 0xf5, 0x37, 0x00, 0x00, 0xff, 0xff, 0xb8, 0x2e, 0x1a,
0x5b, 0x25, 0x01, 0x00, 0x00,
}

View file

@ -2,6 +2,53 @@ package structs
import "sort"
const (
// Binary SI Byte Units
UnitKiB = "KiB"
UnitMiB = "MiB"
UnitGiB = "GiB"
UnitTiB = "TiB"
UnitPiB = "PiB"
UnitEiB = "EiB"
// Decimal SI Byte Units
UnitkB = "kB"
UnitKB = "KB"
UnitMB = "MB"
UnitGB = "GB"
UnitTB = "TB"
UnitPB = "PB"
UnitEB = "EB"
// Binary SI Byte Rates
UnitKiBPerS = "KiB/s"
UnitMiBPerS = "MiB/s"
UnitGiBPerS = "GiB/s"
UnitTiBPerS = "TiB/s"
UnitPiBPerS = "PiB/s"
UnitEiBPerS = "EiB/s"
// Decimal SI Byte Rates
UnitkBPerS = "kB/s"
UnitKBPerS = "KB/s"
UnitMBPerS = "MB/s"
UnitGBPerS = "GB/s"
UnitTBPerS = "TB/s"
UnitPBPerS = "PB/s"
UnitEBPerS = "EB/s"
// Hertz units
UnitMHz = "MHz"
UnitGHz = "GHz"
// Watts units
UnitmW = "mW"
UnitW = "W"
UnitkW = "kW"
UnitMW = "MW"
UnitGW = "GW"
)
var (
// numUnits is the number of known units
numUnits = len(binarySIBytes) + len(decimalSIBytes) + len(binarySIByteRates) + len(decimalSIByteRates) + len(watts) + len(hertz)
@ -15,32 +62,32 @@ var (
binarySIBytes = []*Unit{
{
Name: "KiB",
Name: UnitKiB,
Base: UnitByte,
Multiplier: 1 << 10,
},
{
Name: "MiB",
Name: UnitMiB,
Base: UnitByte,
Multiplier: 1 << 20,
},
{
Name: "GiB",
Name: UnitGiB,
Base: UnitByte,
Multiplier: 1 << 30,
},
{
Name: "TiB",
Name: UnitTiB,
Base: UnitByte,
Multiplier: 1 << 40,
},
{
Name: "PiB",
Name: UnitPiB,
Base: UnitByte,
Multiplier: 1 << 50,
},
{
Name: "EiB",
Name: UnitEiB,
Base: UnitByte,
Multiplier: 1 << 60,
},
@ -48,37 +95,37 @@ var (
decimalSIBytes = []*Unit{
{
Name: "kB",
Name: UnitkB,
Base: UnitByte,
Multiplier: Pow(1000, 1),
},
{
Name: "KB", // Alternative name for kB
Name: UnitKB, // Alternative name for kB
Base: UnitByte,
Multiplier: Pow(1000, 1),
},
{
Name: "MB",
Name: UnitMB,
Base: UnitByte,
Multiplier: Pow(1000, 2),
},
{
Name: "GB",
Name: UnitGB,
Base: UnitByte,
Multiplier: Pow(1000, 3),
},
{
Name: "TB",
Name: UnitTB,
Base: UnitByte,
Multiplier: Pow(1000, 4),
},
{
Name: "PB",
Name: UnitPB,
Base: UnitByte,
Multiplier: Pow(1000, 5),
},
{
Name: "EB",
Name: UnitEB,
Base: UnitByte,
Multiplier: Pow(1000, 6),
},
@ -86,32 +133,32 @@ var (
binarySIByteRates = []*Unit{
{
Name: "KiB/s",
Name: UnitKiBPerS,
Base: UnitByteRate,
Multiplier: 1 << 10,
},
{
Name: "MiB/s",
Name: UnitMiBPerS,
Base: UnitByteRate,
Multiplier: 1 << 20,
},
{
Name: "GiB/s",
Name: UnitGiBPerS,
Base: UnitByteRate,
Multiplier: 1 << 30,
},
{
Name: "TiB/s",
Name: UnitTiBPerS,
Base: UnitByteRate,
Multiplier: 1 << 40,
},
{
Name: "PiB/s",
Name: UnitPiBPerS,
Base: UnitByteRate,
Multiplier: 1 << 50,
},
{
Name: "EiB/s",
Name: UnitEiBPerS,
Base: UnitByteRate,
Multiplier: 1 << 60,
},
@ -119,37 +166,37 @@ var (
decimalSIByteRates = []*Unit{
{
Name: "kB/s",
Name: UnitkBPerS,
Base: UnitByteRate,
Multiplier: Pow(1000, 1),
},
{
Name: "KB/s", // Alternative name for kB/s
Name: UnitKBPerS,
Base: UnitByteRate,
Multiplier: Pow(1000, 1),
},
{
Name: "MB/s",
Name: UnitMBPerS,
Base: UnitByteRate,
Multiplier: Pow(1000, 2),
},
{
Name: "GB/s",
Name: UnitGBPerS,
Base: UnitByteRate,
Multiplier: Pow(1000, 3),
},
{
Name: "TB/s",
Name: UnitTBPerS,
Base: UnitByteRate,
Multiplier: Pow(1000, 4),
},
{
Name: "PB/s",
Name: UnitPBPerS,
Base: UnitByteRate,
Multiplier: Pow(1000, 5),
},
{
Name: "EB/s",
Name: UnitEBPerS,
Base: UnitByteRate,
Multiplier: Pow(1000, 6),
},
@ -157,12 +204,12 @@ var (
hertz = []*Unit{
{
Name: "MHz",
Name: UnitMHz,
Base: UnitHertz,
Multiplier: Pow(1000, 1),
},
{
Name: "GHz",
Name: UnitGHz,
Base: UnitHertz,
Multiplier: Pow(1000, 3),
},
@ -170,28 +217,28 @@ var (
watts = []*Unit{
{
Name: "mW",
Name: UnitmW,
Base: UnitWatt,
Multiplier: Pow(10, 3),
InverseMultiplier: true,
},
{
Name: "W",
Name: UnitW,
Base: UnitWatt,
Multiplier: 1,
},
{
Name: "kW",
Name: UnitkW,
Base: UnitWatt,
Multiplier: Pow(10, 3),
},
{
Name: "MW",
Name: UnitMW,
Base: UnitWatt,
Multiplier: Pow(10, 6),
},
{
Name: "GW",
Name: UnitGW,
Base: UnitWatt,
Multiplier: Pow(10, 9),
},

View file

@ -25,6 +25,58 @@ func ConvertProtoAttribute(in *proto.Attribute) *Attribute {
return out
}
func ConvertProtoAttributeMap(in map[string]*proto.Attribute) map[string]*Attribute {
if in == nil {
return nil
}
out := make(map[string]*Attribute, len(in))
for k, a := range in {
out[k] = ConvertProtoAttribute(a)
}
return out
}
func ConvertStructsAttribute(in *Attribute) *proto.Attribute {
out := &proto.Attribute{
Unit: in.Unit,
}
if in.Int != nil {
out.Value = &proto.Attribute_IntVal{
IntVal: *in.Int,
}
} else if in.Float != nil {
out.Value = &proto.Attribute_FloatVal{
FloatVal: *in.Float,
}
} else if in.String != nil {
out.Value = &proto.Attribute_StringVal{
StringVal: *in.String,
}
} else if in.Bool != nil {
out.Value = &proto.Attribute_BoolVal{
BoolVal: *in.Bool,
}
}
return out
}
func ConvertStructAttributeMap(in map[string]*Attribute) map[string]*proto.Attribute {
if in == nil {
return nil
}
out := make(map[string]*proto.Attribute, len(in))
for k, a := range in {
out[k] = ConvertStructsAttribute(a)
}
return out
}
func Pow(a, b int64) int64 {
var p int64 = 1
for b > 0 {