mirror of
https://github.com/intel/intel-device-plugins-for-kubernetes.git
synced 2025-06-03 03:59:37 +00:00
fpga_crihook: check if bitstream is already programmed
FPGA device can be already programmed with requested bitstream. In this case hook should not programm the device again.
This commit is contained in:
parent
8f977b7782
commit
2f9debe35b
@ -20,8 +20,10 @@ import (
|
|||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
@ -34,6 +36,8 @@ const (
|
|||||||
fpgaRegionEnv = "FPGA_REGION"
|
fpgaRegionEnv = "FPGA_REGION"
|
||||||
fpgaAfuEnv = "FPGA_AFU"
|
fpgaAfuEnv = "FPGA_AFU"
|
||||||
fpgaBitStreamExt = ".gbs"
|
fpgaBitStreamExt = ".gbs"
|
||||||
|
fpgaDevRegexp = `\/dev\/intel-fpga-port.(\d)$`
|
||||||
|
afuIDTemplate = "/sys/class/fpga/intel-fpga-dev.%s/intel-fpga-port.%s/afu_id"
|
||||||
)
|
)
|
||||||
|
|
||||||
func decodeJSONStream(reader io.Reader) (map[string]interface{}, error) {
|
func decodeJSONStream(reader io.Reader) (map[string]interface{}, error) {
|
||||||
@ -47,13 +51,21 @@ type hookEnv struct {
|
|||||||
bitStreamDir string
|
bitStreamDir string
|
||||||
config string
|
config string
|
||||||
execer utilsexec.Interface
|
execer utilsexec.Interface
|
||||||
|
afuIDTemplate string
|
||||||
}
|
}
|
||||||
|
|
||||||
func newHookEnv(bitStreamDir string, config string, execer utilsexec.Interface) *hookEnv {
|
type fpgaParams struct {
|
||||||
|
region string
|
||||||
|
afu string
|
||||||
|
devNum string
|
||||||
|
}
|
||||||
|
|
||||||
|
func newHookEnv(bitStreamDir string, config string, execer utilsexec.Interface, afuIDTemplate string) *hookEnv {
|
||||||
return &hookEnv{
|
return &hookEnv{
|
||||||
bitStreamDir,
|
bitStreamDir,
|
||||||
config,
|
config,
|
||||||
execer,
|
execer,
|
||||||
|
afuIDTemplate,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,37 +73,37 @@ func canonize(uuid string) string {
|
|||||||
return strings.ToLower(strings.Replace(uuid, "-", "", -1))
|
return strings.ToLower(strings.Replace(uuid, "-", "", -1))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (he *hookEnv) getFPGAParams(reader io.Reader) (string, string, error) {
|
func (he *hookEnv) getFPGAParams(reader io.Reader) (*fpgaParams, error) {
|
||||||
content, err := decodeJSONStream(reader)
|
content, err := decodeJSONStream(reader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", "", err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
bundle, ok := content["bundle"]
|
bundle, ok := content["bundle"]
|
||||||
if !ok {
|
if !ok {
|
||||||
return "", "", fmt.Errorf("no 'bundle' field in the configuration")
|
return nil, fmt.Errorf("no 'bundle' field in the configuration")
|
||||||
}
|
}
|
||||||
|
|
||||||
configPath := path.Join(fmt.Sprint(bundle), he.config)
|
configPath := path.Join(fmt.Sprint(bundle), he.config)
|
||||||
configFile, err := os.Open(configPath)
|
configFile, err := os.Open(configPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", "", err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer configFile.Close()
|
defer configFile.Close()
|
||||||
|
|
||||||
content, err = decodeJSONStream(configFile)
|
content, err = decodeJSONStream(configFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", "", fmt.Errorf("can't decode %s", configPath)
|
return nil, fmt.Errorf("can't decode %s", configPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
process, ok := content["process"]
|
process, ok := content["process"]
|
||||||
if !ok {
|
if !ok {
|
||||||
return "", "", fmt.Errorf("no 'process' field found in %s", configPath)
|
return nil, fmt.Errorf("no 'process' field found in %s", configPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
rawEnv, ok := process.(map[string]interface{})["env"]
|
rawEnv, ok := process.(map[string]interface{})["env"]
|
||||||
if !ok {
|
if !ok {
|
||||||
return "", "", fmt.Errorf("no 'env' field found in the 'process' struct in %s", configPath)
|
return nil, fmt.Errorf("no 'env' field found in the 'process' struct in %s", configPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
dEnv := make(map[string]string)
|
dEnv := make(map[string]string)
|
||||||
@ -102,85 +114,125 @@ func (he *hookEnv) getFPGAParams(reader io.Reader) (string, string, error) {
|
|||||||
|
|
||||||
fpgaRegion, ok := dEnv[fpgaRegionEnv]
|
fpgaRegion, ok := dEnv[fpgaRegionEnv]
|
||||||
if !ok {
|
if !ok {
|
||||||
return "", "", fmt.Errorf("%s environment is not set in the 'process/env' list in %s", fpgaRegionEnv, configPath)
|
return nil, fmt.Errorf("%s environment is not set in the 'process/env' list in %s", fpgaRegionEnv, configPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
fpgaAfu, ok := dEnv[fpgaAfuEnv]
|
fpgaAfu, ok := dEnv[fpgaAfuEnv]
|
||||||
if !ok {
|
if !ok {
|
||||||
return fpgaRegion, "", fmt.Errorf("%s environment is not set in the 'process/env' list in %s", fpgaAfuEnv, configPath)
|
return nil, fmt.Errorf("%s environment is not set in the 'process/env' list in %s", fpgaAfuEnv, configPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
return canonize(fpgaRegion), canonize(fpgaAfu), nil
|
linux, ok := content["linux"]
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("no 'linux' field found in %s", configPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
rawDevices, ok := linux.(map[string]interface{})["devices"]
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("no 'devices' field found in the 'linux' struct in %s", configPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
pattern := regexp.MustCompile(fpgaDevRegexp)
|
||||||
|
for _, device := range rawDevices.([]interface{}) {
|
||||||
|
deviceNum := pattern.FindStringSubmatch(device.(map[string]interface{})["path"].(string))
|
||||||
|
if deviceNum != nil {
|
||||||
|
return &fpgaParams{region: canonize(fpgaRegion), afu: canonize(fpgaAfu), devNum: deviceNum[1]}, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, fmt.Errorf("no FPGA devices found in linux/devices list in %s", configPath)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (he *hookEnv) validateBitStream(fpgaRegion string, fpgaAfu string, fpgaBitStreamPath string) error {
|
func (he *hookEnv) validateBitStream(params *fpgaParams, fpgaBitStreamPath string) error {
|
||||||
output, err := he.execer.Command("packager", "gbs-info", "--gbs", fpgaBitStreamPath).CombinedOutput()
|
output, err := he.execer.Command("packager", "gbs-info", "--gbs", fpgaBitStreamPath).CombinedOutput()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("%s/%s: can't get bitstream info: %v", fpgaRegion, fpgaAfu, err)
|
return fmt.Errorf("%s/%s: can't get bitstream info: %v", params.region, params.afu, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
reader := bytes.NewBuffer(output)
|
reader := bytes.NewBuffer(output)
|
||||||
content, err := decodeJSONStream(reader)
|
content, err := decodeJSONStream(reader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("%s/%s: can't decode 'packager gbs-info' output: %v", fpgaRegion, fpgaAfu, err)
|
return fmt.Errorf("%s/%s: can't decode 'packager gbs-info' output: %v", params.region, params.afu, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
afuImage, ok := content["afu-image"]
|
afuImage, ok := content["afu-image"]
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("%s/%s: 'afu-image' field not found in the 'packager gbs-info' output", fpgaRegion, fpgaAfu)
|
return fmt.Errorf("%s/%s: 'afu-image' field not found in the 'packager gbs-info' output", params.region, params.afu)
|
||||||
}
|
}
|
||||||
|
|
||||||
interfaceUUID, ok := afuImage.(map[string]interface{})["interface-uuid"]
|
interfaceUUID, ok := afuImage.(map[string]interface{})["interface-uuid"]
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("%s/%s: 'interface-uuid' field not found in the 'packager gbs-info' output", fpgaRegion, fpgaAfu)
|
return fmt.Errorf("%s/%s: 'interface-uuid' field not found in the 'packager gbs-info' output", params.region, params.afu)
|
||||||
}
|
}
|
||||||
|
|
||||||
acceleratorClusters, ok := afuImage.(map[string]interface{})["accelerator-clusters"]
|
acceleratorClusters, ok := afuImage.(map[string]interface{})["accelerator-clusters"]
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("%s/%s: 'accelerator-clusters' field not found in the 'packager gbs-info' output", fpgaRegion, fpgaAfu)
|
return fmt.Errorf("%s/%s: 'accelerator-clusters' field not found in the 'packager gbs-info' output", params.region, params.afu)
|
||||||
}
|
}
|
||||||
|
|
||||||
if canonize(interfaceUUID.(string)) != canonize(fpgaRegion) {
|
if canonize(interfaceUUID.(string)) != params.region {
|
||||||
return fmt.Errorf("bitstream is not for this device: region(%s) and interface-uuid(%s) don't match", fpgaRegion, interfaceUUID)
|
return fmt.Errorf("bitstream is not for this device: region(%s) and interface-uuid(%s) don't match", params.region, interfaceUUID)
|
||||||
}
|
}
|
||||||
|
|
||||||
acceleratorTypeUUID, ok := acceleratorClusters.([]interface{})[0].(map[string]interface{})["accelerator-type-uuid"]
|
acceleratorTypeUUID, ok := acceleratorClusters.([]interface{})[0].(map[string]interface{})["accelerator-type-uuid"]
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("%s/%s: 'accelerator-type-uuid' field not found in the 'packager gbs-info' output", fpgaRegion, fpgaAfu)
|
return fmt.Errorf("%s/%s: 'accelerator-type-uuid' field not found in the 'packager gbs-info' output", params.region, params.afu)
|
||||||
}
|
}
|
||||||
|
|
||||||
if canonize(acceleratorTypeUUID.(string)) != canonize(fpgaAfu) {
|
if canonize(acceleratorTypeUUID.(string)) != params.afu {
|
||||||
return fmt.Errorf("incorrect bitstream: AFU(%s) and accelerator-type-uuid(%s) don't match", fpgaAfu, acceleratorTypeUUID)
|
return fmt.Errorf("incorrect bitstream: AFU(%s) and accelerator-type-uuid(%s) don't match", params.afu, acceleratorTypeUUID)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (he *hookEnv) programBitStream(fpgaRegion string, fpgaAfu string, fpgaBitStreamPath string) error {
|
func (he *hookEnv) programBitStream(params *fpgaParams, fpgaBitStreamPath string) error {
|
||||||
output, err := he.execer.Command("fpgaconf", fpgaBitStreamPath).CombinedOutput()
|
output, err := he.execer.Command("fpgaconf", fpgaBitStreamPath).CombinedOutput()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to program AFU %s to region %s: error: %v, output: %s", fpgaAfu, fpgaRegion, err, string(output))
|
return fmt.Errorf("failed to program AFU %s to region %s: error: %v, output: %s", params.afu, params.region, err, string(output))
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (he *hookEnv) getProgrammedAfu(deviceNum string) (string, error) {
|
||||||
|
// NOTE: only one region per device is supported, hence
|
||||||
|
// deviceNum is used twice (device and port numbers are the same)
|
||||||
|
afuIDPath := fmt.Sprintf(he.afuIDTemplate, deviceNum, deviceNum)
|
||||||
|
data, err := ioutil.ReadFile(afuIDPath)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return strings.TrimSpace(string(data)), nil
|
||||||
|
}
|
||||||
|
|
||||||
func (he *hookEnv) process(reader io.Reader) error {
|
func (he *hookEnv) process(reader io.Reader) error {
|
||||||
fpgaRegion, fpgaAfu, err := he.getFPGAParams(reader)
|
params, err := he.getFPGAParams(reader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("couldn't get FPGA region and AFU: %v, skipping", err)
|
return fmt.Errorf("couldn't get FPGA region, AFU and device number: %v, skipping", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
fpgaBitStreamPath := path.Join(he.bitStreamDir, fpgaRegion, fpgaAfu+fpgaBitStreamExt)
|
programmedAfu, err := he.getProgrammedAfu(params.devNum)
|
||||||
if _, err = os.Stat(fpgaBitStreamPath); os.IsNotExist(err) {
|
|
||||||
return fmt.Errorf("%s/%s: bitstream is not found", fpgaRegion, fpgaAfu)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = he.validateBitStream(fpgaRegion, fpgaAfu, fpgaBitStreamPath)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = he.programBitStream(fpgaRegion, fpgaAfu, fpgaBitStreamPath)
|
if canonize(programmedAfu) == params.afu {
|
||||||
|
// Afu is already programmed
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
fpgaBitStreamPath := path.Join(he.bitStreamDir, params.region, params.afu+fpgaBitStreamExt)
|
||||||
|
if _, err = os.Stat(fpgaBitStreamPath); os.IsNotExist(err) {
|
||||||
|
return fmt.Errorf("%s/%s: bitstream is not found", params.region, params.afu)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = he.validateBitStream(params, fpgaBitStreamPath)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = he.programBitStream(params, fpgaBitStreamPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -196,7 +248,7 @@ func main() {
|
|||||||
os.Setenv("PATH", "/sbin:/usr/sbin:/usr/local/sbin:/usr/local/bin:/usr/bin:/bin")
|
os.Setenv("PATH", "/sbin:/usr/sbin:/usr/local/sbin:/usr/local/bin:/usr/bin:/bin")
|
||||||
}
|
}
|
||||||
|
|
||||||
he := newHookEnv(fpgaBitStreamDirectory, configJSON, utilsexec.New())
|
he := newHookEnv(fpgaBitStreamDirectory, configJSON, utilsexec.New(), afuIDTemplate)
|
||||||
|
|
||||||
err := he.process(os.Stdin)
|
err := he.process(os.Stdin)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -28,9 +28,11 @@ func TestGetFPGAParams(t *testing.T) {
|
|||||||
tcases := []struct {
|
tcases := []struct {
|
||||||
stdinJSON string
|
stdinJSON string
|
||||||
configJSON string
|
configJSON string
|
||||||
|
afuIDPath string
|
||||||
expectedErr bool
|
expectedErr bool
|
||||||
expectedRegion string
|
expectedRegion string
|
||||||
expectedAFU string
|
expectedAFU string
|
||||||
|
expectedDeviceNum string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
stdinJSON: "stdin-correct.json",
|
stdinJSON: "stdin-correct.json",
|
||||||
@ -38,6 +40,7 @@ func TestGetFPGAParams(t *testing.T) {
|
|||||||
expectedErr: false,
|
expectedErr: false,
|
||||||
expectedRegion: "ce48969398f05f33946d560708be108a",
|
expectedRegion: "ce48969398f05f33946d560708be108a",
|
||||||
expectedAFU: "f7df405cbd7acf7222f144b0b93acd18",
|
expectedAFU: "f7df405cbd7acf7222f144b0b93acd18",
|
||||||
|
expectedDeviceNum: "0",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
stdinJSON: "stdin-broken-json.json",
|
stdinJSON: "stdin-broken-json.json",
|
||||||
@ -80,6 +83,27 @@ func TestGetFPGAParams(t *testing.T) {
|
|||||||
expectedErr: true,
|
expectedErr: true,
|
||||||
expectedRegion: "ce48969398f05f33946d560708be108a",
|
expectedRegion: "ce48969398f05f33946d560708be108a",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
stdinJSON: "stdin-correct.json",
|
||||||
|
configJSON: "config-no-linux.json",
|
||||||
|
expectedErr: true,
|
||||||
|
expectedRegion: "ce48969398f05f33946d560708be108a",
|
||||||
|
expectedAFU: "f7df405cbd7acf7222f144b0b93acd18",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
stdinJSON: "stdin-correct.json",
|
||||||
|
configJSON: "config-no-devices.json",
|
||||||
|
expectedErr: true,
|
||||||
|
expectedRegion: "ce48969398f05f33946d560708be108a",
|
||||||
|
expectedAFU: "f7df405cbd7acf7222f144b0b93acd18",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
stdinJSON: "stdin-correct.json",
|
||||||
|
configJSON: "config-no-FPGA-devices.json",
|
||||||
|
expectedErr: true,
|
||||||
|
expectedRegion: "ce48969398f05f33946d560708be108a",
|
||||||
|
expectedAFU: "f7df405cbd7acf7222f144b0b93acd18",
|
||||||
|
},
|
||||||
}
|
}
|
||||||
for _, tc := range tcases {
|
for _, tc := range tcases {
|
||||||
stdin, err := os.Open(path.Join("testdata", tc.stdinJSON))
|
stdin, err := os.Open(path.Join("testdata", tc.stdinJSON))
|
||||||
@ -87,16 +111,22 @@ func TestGetFPGAParams(t *testing.T) {
|
|||||||
t.Fatalf("can't open file %s: %v", tc.stdinJSON, err)
|
t.Fatalf("can't open file %s: %v", tc.stdinJSON, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
he := newHookEnv("", tc.configJSON, nil)
|
he := newHookEnv("", tc.configJSON, nil, "")
|
||||||
|
|
||||||
region, afu, err := he.getFPGAParams(stdin)
|
params, err := he.getFPGAParams(stdin)
|
||||||
|
|
||||||
if err != nil && !tc.expectedErr {
|
if err != nil {
|
||||||
|
if !tc.expectedErr {
|
||||||
t.Errorf("unexpected error: %v", err)
|
t.Errorf("unexpected error: %v", err)
|
||||||
} else if region != tc.expectedRegion {
|
}
|
||||||
t.Errorf("expected region: %s, actual: %s", tc.expectedRegion, region)
|
} else {
|
||||||
} else if afu != tc.expectedAFU {
|
if params.region != tc.expectedRegion {
|
||||||
t.Errorf("expected AFU: %s, actual: %s", tc.expectedAFU, afu)
|
t.Errorf("expected region: %s, actual: %s", tc.expectedRegion, params.region)
|
||||||
|
} else if params.afu != tc.expectedAFU {
|
||||||
|
t.Errorf("expected AFU: %s, actual: %s", tc.expectedAFU, params.afu)
|
||||||
|
} else if params.devNum != tc.expectedDeviceNum {
|
||||||
|
t.Errorf("expected device number: %s, actual: %s", tc.expectedDeviceNum, params.devNum)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -113,14 +143,14 @@ func genFakeActions(fcmd *fakeexec.FakeCmd, num int) []fakeexec.FakeCommandActio
|
|||||||
|
|
||||||
func TestValidateBitstream(t *testing.T) {
|
func TestValidateBitstream(t *testing.T) {
|
||||||
tcases := []struct {
|
tcases := []struct {
|
||||||
fpgaRegion string
|
params *fpgaParams
|
||||||
fpgaAfu string
|
|
||||||
expectedErr bool
|
expectedErr bool
|
||||||
fakeAction []fakeexec.FakeCombinedOutputAction
|
fakeAction []fakeexec.FakeCombinedOutputAction
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
fpgaRegion: "ce48969398f05f33946d560708be108a",
|
params: &fpgaParams{
|
||||||
fpgaAfu: "f7df405cbd7acf7222f144b0b93acd18",
|
region: "ce48969398f05f33946d560708be108a",
|
||||||
|
afu: "f7df405cbd7acf7222f144b0b93acd18"},
|
||||||
expectedErr: false,
|
expectedErr: false,
|
||||||
fakeAction: []fakeexec.FakeCombinedOutputAction{
|
fakeAction: []fakeexec.FakeCombinedOutputAction{
|
||||||
func() ([]byte, error) {
|
func() ([]byte, error) {
|
||||||
@ -129,12 +159,14 @@ func TestValidateBitstream(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
params: &fpgaParams{region: "", afu: ""},
|
||||||
expectedErr: true,
|
expectedErr: true,
|
||||||
fakeAction: []fakeexec.FakeCombinedOutputAction{
|
fakeAction: []fakeexec.FakeCombinedOutputAction{
|
||||||
func() ([]byte, error) { return nil, &fakeexec.FakeExitError{Status: 1} },
|
func() ([]byte, error) { return nil, &fakeexec.FakeExitError{Status: 1} },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
params: &fpgaParams{region: "", afu: ""},
|
||||||
expectedErr: true,
|
expectedErr: true,
|
||||||
fakeAction: []fakeexec.FakeCombinedOutputAction{
|
fakeAction: []fakeexec.FakeCombinedOutputAction{
|
||||||
func() ([]byte, error) {
|
func() ([]byte, error) {
|
||||||
@ -143,6 +175,7 @@ func TestValidateBitstream(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
params: &fpgaParams{region: "", afu: ""},
|
||||||
expectedErr: true,
|
expectedErr: true,
|
||||||
fakeAction: []fakeexec.FakeCombinedOutputAction{
|
fakeAction: []fakeexec.FakeCombinedOutputAction{
|
||||||
func() ([]byte, error) {
|
func() ([]byte, error) {
|
||||||
@ -151,6 +184,7 @@ func TestValidateBitstream(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
params: &fpgaParams{region: "", afu: ""},
|
||||||
expectedErr: true,
|
expectedErr: true,
|
||||||
fakeAction: []fakeexec.FakeCombinedOutputAction{
|
fakeAction: []fakeexec.FakeCombinedOutputAction{
|
||||||
func() ([]byte, error) {
|
func() ([]byte, error) {
|
||||||
@ -159,6 +193,7 @@ func TestValidateBitstream(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
params: &fpgaParams{region: "", afu: ""},
|
||||||
expectedErr: true,
|
expectedErr: true,
|
||||||
fakeAction: []fakeexec.FakeCombinedOutputAction{
|
fakeAction: []fakeexec.FakeCombinedOutputAction{
|
||||||
func() ([]byte, error) {
|
func() ([]byte, error) {
|
||||||
@ -167,7 +202,7 @@ func TestValidateBitstream(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
fpgaRegion: "this should not match",
|
params: &fpgaParams{region: "this should not match", afu: ""},
|
||||||
expectedErr: true,
|
expectedErr: true,
|
||||||
fakeAction: []fakeexec.FakeCombinedOutputAction{
|
fakeAction: []fakeexec.FakeCombinedOutputAction{
|
||||||
func() ([]byte, error) {
|
func() ([]byte, error) {
|
||||||
@ -176,7 +211,7 @@ func TestValidateBitstream(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
fpgaRegion: "ce48969398f05f33946d560708be108a",
|
params: &fpgaParams{region: "ce48969398f05f33946d560708be108a", afu: ""},
|
||||||
expectedErr: true,
|
expectedErr: true,
|
||||||
fakeAction: []fakeexec.FakeCombinedOutputAction{
|
fakeAction: []fakeexec.FakeCombinedOutputAction{
|
||||||
func() ([]byte, error) {
|
func() ([]byte, error) {
|
||||||
@ -185,8 +220,9 @@ func TestValidateBitstream(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
fpgaRegion: "ce48969398f05f33946d560708be108a",
|
params: &fpgaParams{
|
||||||
fpgaAfu: "this should not match",
|
region: "ce48969398f05f33946d560708be108a",
|
||||||
|
afu: "this should not match"},
|
||||||
expectedErr: true,
|
expectedErr: true,
|
||||||
fakeAction: []fakeexec.FakeCombinedOutputAction{
|
fakeAction: []fakeexec.FakeCombinedOutputAction{
|
||||||
func() ([]byte, error) {
|
func() ([]byte, error) {
|
||||||
@ -199,8 +235,8 @@ func TestValidateBitstream(t *testing.T) {
|
|||||||
for _, tc := range tcases {
|
for _, tc := range tcases {
|
||||||
fcmd := fakeexec.FakeCmd{CombinedOutputScript: tc.fakeAction}
|
fcmd := fakeexec.FakeCmd{CombinedOutputScript: tc.fakeAction}
|
||||||
execer := fakeexec.FakeExec{CommandScript: genFakeActions(&fcmd, len(fcmd.CombinedOutputScript))}
|
execer := fakeexec.FakeExec{CommandScript: genFakeActions(&fcmd, len(fcmd.CombinedOutputScript))}
|
||||||
he := newHookEnv("", "", &execer)
|
he := newHookEnv("", "", &execer, "")
|
||||||
err := he.validateBitStream(tc.fpgaRegion, tc.fpgaAfu, "")
|
err := he.validateBitStream(tc.params, "")
|
||||||
if err != nil && !tc.expectedErr {
|
if err != nil && !tc.expectedErr {
|
||||||
t.Errorf("unexpected error: %v", err)
|
t.Errorf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
@ -209,22 +245,23 @@ func TestValidateBitstream(t *testing.T) {
|
|||||||
|
|
||||||
func TestProgramBitStream(t *testing.T) {
|
func TestProgramBitStream(t *testing.T) {
|
||||||
tcases := []struct {
|
tcases := []struct {
|
||||||
fpgaRegion string
|
params *fpgaParams
|
||||||
fpgaAfu string
|
|
||||||
expectedErr bool
|
expectedErr bool
|
||||||
fakeAction []fakeexec.FakeCombinedOutputAction
|
fakeAction []fakeexec.FakeCombinedOutputAction
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
fpgaRegion: "ce48969398f05f33946d560708be108a",
|
params: &fpgaParams{
|
||||||
fpgaAfu: "f7df405cbd7acf7222f144b0b93acd18",
|
region: "ce48969398f05f33946d560708be108a",
|
||||||
|
afu: "f7df405cbd7acf7222f144b0b93acd18"},
|
||||||
expectedErr: false,
|
expectedErr: false,
|
||||||
fakeAction: []fakeexec.FakeCombinedOutputAction{
|
fakeAction: []fakeexec.FakeCombinedOutputAction{
|
||||||
func() ([]byte, error) { return []byte(""), nil },
|
func() ([]byte, error) { return []byte(""), nil },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
fpgaRegion: "ce48969398f05f33946d560708be108a",
|
params: &fpgaParams{
|
||||||
fpgaAfu: "f7df405cbd7acf7222f144b0b93acd18",
|
region: "ce48969398f05f33946d560708be108a",
|
||||||
|
afu: "f7df405cbd7acf7222f144b0b93acd18"},
|
||||||
expectedErr: true,
|
expectedErr: true,
|
||||||
fakeAction: []fakeexec.FakeCombinedOutputAction{
|
fakeAction: []fakeexec.FakeCombinedOutputAction{
|
||||||
func() ([]byte, error) { return []byte("error"), &fakeexec.FakeExitError{Status: 1} },
|
func() ([]byte, error) { return []byte("error"), &fakeexec.FakeExitError{Status: 1} },
|
||||||
@ -235,8 +272,8 @@ func TestProgramBitStream(t *testing.T) {
|
|||||||
for _, tc := range tcases {
|
for _, tc := range tcases {
|
||||||
fcmd := fakeexec.FakeCmd{CombinedOutputScript: tc.fakeAction}
|
fcmd := fakeexec.FakeCmd{CombinedOutputScript: tc.fakeAction}
|
||||||
execer := fakeexec.FakeExec{CommandScript: genFakeActions(&fcmd, len(fcmd.CombinedOutputScript))}
|
execer := fakeexec.FakeExec{CommandScript: genFakeActions(&fcmd, len(fcmd.CombinedOutputScript))}
|
||||||
he := newHookEnv("", "", &execer)
|
he := newHookEnv("", "", &execer, "")
|
||||||
err := he.programBitStream(tc.fpgaRegion, tc.fpgaAfu, "")
|
err := he.programBitStream(tc.params, "")
|
||||||
if err != nil && !tc.expectedErr {
|
if err != nil && !tc.expectedErr {
|
||||||
t.Errorf("unexpected error: %v", err)
|
t.Errorf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
@ -247,12 +284,26 @@ func TestProcess(t *testing.T) {
|
|||||||
tcases := []struct {
|
tcases := []struct {
|
||||||
stdinJSON string
|
stdinJSON string
|
||||||
configJSON string
|
configJSON string
|
||||||
|
afuIDTemplate string
|
||||||
expectedErr bool
|
expectedErr bool
|
||||||
fakeCombinedOutputAction []fakeexec.FakeCombinedOutputAction
|
fakeCombinedOutputAction []fakeexec.FakeCombinedOutputAction
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
stdinJSON: "stdin-correct.json",
|
stdinJSON: "stdin-correct.json",
|
||||||
configJSON: "config-correct.json",
|
configJSON: "config-correct.json",
|
||||||
|
afuIDTemplate: "testdata/sys/class/fpga/intel-fpga-dev.%s/intel-fpga-port.%s/afu_id_already_programmed",
|
||||||
|
expectedErr: false,
|
||||||
|
fakeCombinedOutputAction: []fakeexec.FakeCombinedOutputAction{
|
||||||
|
func() ([]byte, error) {
|
||||||
|
return ioutil.ReadFile("testdata/gbs-info-correct.json")
|
||||||
|
},
|
||||||
|
func() ([]byte, error) { return []byte(""), nil },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
stdinJSON: "stdin-correct.json",
|
||||||
|
configJSON: "config-correct.json",
|
||||||
|
afuIDTemplate: "testdata/sys/class/fpga/intel-fpga-dev.%s/intel-fpga-port.%s/afu_id_not_programmed_yet",
|
||||||
expectedErr: false,
|
expectedErr: false,
|
||||||
fakeCombinedOutputAction: []fakeexec.FakeCombinedOutputAction{
|
fakeCombinedOutputAction: []fakeexec.FakeCombinedOutputAction{
|
||||||
func() ([]byte, error) {
|
func() ([]byte, error) {
|
||||||
@ -264,17 +315,25 @@ func TestProcess(t *testing.T) {
|
|||||||
{
|
{
|
||||||
stdinJSON: "stdin-correct.json",
|
stdinJSON: "stdin-correct.json",
|
||||||
configJSON: "config-no-afu.json",
|
configJSON: "config-no-afu.json",
|
||||||
expectedErr: true,
|
afuIDTemplate: "testdata/sys/class/fpga/intel-fpga-dev.%s/intel-fpga-port.%s/afu_id_not_programmed_yet",
|
||||||
},
|
|
||||||
{
|
|
||||||
stdinJSON: "stdin-correct.json",
|
|
||||||
configJSON: "config-non-existing-bitstream.json",
|
|
||||||
expectedErr: true,
|
expectedErr: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
stdinJSON: "stdin-correct.json",
|
stdinJSON: "stdin-correct.json",
|
||||||
configJSON: "config-correct.json",
|
configJSON: "config-correct.json",
|
||||||
expectedErr: true,
|
expectedErr: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
stdinJSON: "stdin-correct.json",
|
||||||
|
configJSON: "config-non-existing-bitstream.json",
|
||||||
|
afuIDTemplate: "testdata/sys/class/fpga/intel-fpga-dev.%s/intel-fpga-port.%s/afu_id_not_programmed_yet",
|
||||||
|
expectedErr: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
stdinJSON: "stdin-correct.json",
|
||||||
|
configJSON: "config-correct.json",
|
||||||
|
afuIDTemplate: "testdata/sys/class/fpga/intel-fpga-dev.%s/intel-fpga-port.%s/afu_id_not_programmed_yet",
|
||||||
|
expectedErr: true,
|
||||||
fakeCombinedOutputAction: []fakeexec.FakeCombinedOutputAction{
|
fakeCombinedOutputAction: []fakeexec.FakeCombinedOutputAction{
|
||||||
func() ([]byte, error) {
|
func() ([]byte, error) {
|
||||||
return ioutil.ReadFile("testdata/gbs-info-no-accelerator-type-uuid.json")
|
return ioutil.ReadFile("testdata/gbs-info-no-accelerator-type-uuid.json")
|
||||||
@ -284,6 +343,7 @@ func TestProcess(t *testing.T) {
|
|||||||
{
|
{
|
||||||
stdinJSON: "stdin-correct.json",
|
stdinJSON: "stdin-correct.json",
|
||||||
configJSON: "config-correct.json",
|
configJSON: "config-correct.json",
|
||||||
|
afuIDTemplate: "testdata/sys/class/fpga/intel-fpga-dev.%s/intel-fpga-port.%s/afu_id_not_programmed_yet",
|
||||||
expectedErr: true,
|
expectedErr: true,
|
||||||
fakeCombinedOutputAction: []fakeexec.FakeCombinedOutputAction{
|
fakeCombinedOutputAction: []fakeexec.FakeCombinedOutputAction{
|
||||||
func() ([]byte, error) {
|
func() ([]byte, error) {
|
||||||
@ -303,7 +363,7 @@ func TestProcess(t *testing.T) {
|
|||||||
fcmd := fakeexec.FakeCmd{CombinedOutputScript: tc.fakeCombinedOutputAction}
|
fcmd := fakeexec.FakeCmd{CombinedOutputScript: tc.fakeCombinedOutputAction}
|
||||||
execer := fakeexec.FakeExec{CommandScript: genFakeActions(&fcmd, len(fcmd.CombinedOutputScript))}
|
execer := fakeexec.FakeExec{CommandScript: genFakeActions(&fcmd, len(fcmd.CombinedOutputScript))}
|
||||||
|
|
||||||
he := newHookEnv("testdata/intel.com/fpga", tc.configJSON, &execer)
|
he := newHookEnv("testdata/intel.com/fpga", tc.configJSON, &execer, tc.afuIDTemplate)
|
||||||
err = he.process(stdin)
|
err = he.process(stdin)
|
||||||
|
|
||||||
if err != nil && !tc.expectedErr {
|
if err != nil && !tc.expectedErr {
|
||||||
|
136
cmd/fpga_crihook/testdata/config-no-FPGA-devices.json
vendored
Normal file
136
cmd/fpga_crihook/testdata/config-no-FPGA-devices.json
vendored
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
{
|
||||||
|
"ociVersion": "1.0.0",
|
||||||
|
"process": {
|
||||||
|
"user": {
|
||||||
|
"uid": 0,
|
||||||
|
"gid": 0
|
||||||
|
},
|
||||||
|
"args": [
|
||||||
|
"sh",
|
||||||
|
"/usr/bin/test_fpga.sh"
|
||||||
|
],
|
||||||
|
"env": [
|
||||||
|
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
|
||||||
|
"TERM=xterm",
|
||||||
|
"HOSTNAME=test-fpga-region",
|
||||||
|
"FPGA_REGION=ce48969398f05f33946d560708be108a",
|
||||||
|
"FPGA_AFU=f7df405cbd7acf7222f144b0b93acd18",
|
||||||
|
"KUBERNETES_SERVICE_PORT=443",
|
||||||
|
"KUBERNETES_PORT_443_TCP_PROTO=tcp",
|
||||||
|
"OPAE_URL=https://github.com/OPAE/opae-sdk/releases/download/1.0.0-5"
|
||||||
|
],
|
||||||
|
"oomScoreAdj": 999
|
||||||
|
},
|
||||||
|
"hostname": "test-fpga-region",
|
||||||
|
"mounts": [
|
||||||
|
{
|
||||||
|
"destination": "/proc",
|
||||||
|
"type": "proc",
|
||||||
|
"source": "proc"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"destination": "/dev",
|
||||||
|
"type": "tmpfs",
|
||||||
|
"source": "tmpfs",
|
||||||
|
"options": [
|
||||||
|
"nosuid",
|
||||||
|
"strictatime",
|
||||||
|
"mode=755",
|
||||||
|
"size=65536k"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"destination": "/sys",
|
||||||
|
"type": "sysfs",
|
||||||
|
"source": "sysfs",
|
||||||
|
"options": [
|
||||||
|
"nosuid",
|
||||||
|
"noexec",
|
||||||
|
"nodev",
|
||||||
|
"ro"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"hooks": {
|
||||||
|
"prestart": [
|
||||||
|
{
|
||||||
|
"path": "/usr/local/bin/fpga_crihook",
|
||||||
|
"args": [
|
||||||
|
"/usr/local/bin/fpga_crihook"
|
||||||
|
],
|
||||||
|
"env": [
|
||||||
|
"stage=prestart"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"annotations": {
|
||||||
|
"io.kubernetes.container.hash": "22e3c9bc",
|
||||||
|
"io.kubernetes.container.name": "test-container",
|
||||||
|
"io.kubernetes.container.restartCount": "0",
|
||||||
|
"io.kubernetes.container.terminationMessagePolicy": "File",
|
||||||
|
"io.kubernetes.cri-o.ContainerID": "a15ee43034ade4083279bdbb7cf656a971809cfb00eb97a7751bb46dd74c9150",
|
||||||
|
"io.kubernetes.cri-o.ContainerType": "container",
|
||||||
|
"io.kubernetes.cri-o.Created": "2018-06-20T15:08:41.361981842+03:00",
|
||||||
|
"io.kubernetes.cri-o.LogPath": "/var/log/pods/a869ac70-7482-11e8-a041-c81f66f62fcc/test-container/0.log",
|
||||||
|
"io.kubernetes.cri-o.Metadata": "{\"name\":\"test-container\"}",
|
||||||
|
"io.kubernetes.cri-o.SandboxID": "a30829b039e1c631432fe7ab5c748a393c105ed90ec42a6cc95bd7d33356b94e",
|
||||||
|
"io.kubernetes.cri-o.SandboxName": "k8s_POD_test-fpga-region_default_a869ac70-7482-11e8-a041-c81f66f62fcc_0",
|
||||||
|
"io.kubernetes.cri-o.SeccompProfilePath": "",
|
||||||
|
"io.kubernetes.cri-o.Stdin": "false",
|
||||||
|
"io.kubernetes.cri-o.StdinOnce": "false",
|
||||||
|
"io.kubernetes.cri-o.TTY": "false",
|
||||||
|
"io.kubernetes.pod.name": "test-fpga-region",
|
||||||
|
"io.kubernetes.pod.namespace": "default",
|
||||||
|
"io.kubernetes.pod.terminationGracePeriod": "30",
|
||||||
|
"io.kubernetes.pod.uid": "a869ac70-7482-11e8-a041-c81f66f62fcc"
|
||||||
|
},
|
||||||
|
"linux": {
|
||||||
|
"resources": {
|
||||||
|
"devices": [
|
||||||
|
{
|
||||||
|
"allow": false,
|
||||||
|
"access": "rwm"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow": true,
|
||||||
|
"type": "c",
|
||||||
|
"major": 243,
|
||||||
|
"minor": 0,
|
||||||
|
"access": "mrw"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"memory": {
|
||||||
|
"limit": 0
|
||||||
|
},
|
||||||
|
"cpu": {
|
||||||
|
"shares": 1024,
|
||||||
|
"quota": 100000,
|
||||||
|
"period": 100000
|
||||||
|
},
|
||||||
|
"pids": {
|
||||||
|
"limit": 1024
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"cgroupsPath": "/kubepods/burstable/poda869ac70-7482-11e8-a041-c81f66f62fcc/crio-a15ee43034ade4083279bdbb7cf656a971809cfb00eb97a7751bb46dd74c9150",
|
||||||
|
"namespaces": [
|
||||||
|
{
|
||||||
|
"type": "pid"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "mount"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"devices": [
|
||||||
|
{
|
||||||
|
"path": "/dev/not-FPGA-device",
|
||||||
|
"type": "c",
|
||||||
|
"major": 243,
|
||||||
|
"minor": 0,
|
||||||
|
"uid": 0,
|
||||||
|
"gid": 0
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"rootfsPropagation": "rslave"
|
||||||
|
}
|
||||||
|
}
|
126
cmd/fpga_crihook/testdata/config-no-devices.json
vendored
Normal file
126
cmd/fpga_crihook/testdata/config-no-devices.json
vendored
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
{
|
||||||
|
"ociVersion": "1.0.0",
|
||||||
|
"process": {
|
||||||
|
"user": {
|
||||||
|
"uid": 0,
|
||||||
|
"gid": 0
|
||||||
|
},
|
||||||
|
"args": [
|
||||||
|
"sh",
|
||||||
|
"/usr/bin/test_fpga.sh"
|
||||||
|
],
|
||||||
|
"env": [
|
||||||
|
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
|
||||||
|
"TERM=xterm",
|
||||||
|
"HOSTNAME=test-fpga-region",
|
||||||
|
"FPGA_REGION=ce48969398f05f33946d560708be108a",
|
||||||
|
"FPGA_AFU=f7df405cbd7acf7222f144b0b93acd18",
|
||||||
|
"KUBERNETES_SERVICE_PORT=443",
|
||||||
|
"KUBERNETES_PORT_443_TCP_PROTO=tcp",
|
||||||
|
"OPAE_URL=https://github.com/OPAE/opae-sdk/releases/download/1.0.0-5"
|
||||||
|
],
|
||||||
|
"oomScoreAdj": 999
|
||||||
|
},
|
||||||
|
"hostname": "test-fpga-region",
|
||||||
|
"mounts": [
|
||||||
|
{
|
||||||
|
"destination": "/proc",
|
||||||
|
"type": "proc",
|
||||||
|
"source": "proc"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"destination": "/dev",
|
||||||
|
"type": "tmpfs",
|
||||||
|
"source": "tmpfs",
|
||||||
|
"options": [
|
||||||
|
"nosuid",
|
||||||
|
"strictatime",
|
||||||
|
"mode=755",
|
||||||
|
"size=65536k"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"destination": "/sys",
|
||||||
|
"type": "sysfs",
|
||||||
|
"source": "sysfs",
|
||||||
|
"options": [
|
||||||
|
"nosuid",
|
||||||
|
"noexec",
|
||||||
|
"nodev",
|
||||||
|
"ro"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"hooks": {
|
||||||
|
"prestart": [
|
||||||
|
{
|
||||||
|
"path": "/usr/local/bin/fpga_crihook",
|
||||||
|
"args": [
|
||||||
|
"/usr/local/bin/fpga_crihook"
|
||||||
|
],
|
||||||
|
"env": [
|
||||||
|
"stage=prestart"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"annotations": {
|
||||||
|
"io.kubernetes.container.hash": "22e3c9bc",
|
||||||
|
"io.kubernetes.container.name": "test-container",
|
||||||
|
"io.kubernetes.container.restartCount": "0",
|
||||||
|
"io.kubernetes.container.terminationMessagePolicy": "File",
|
||||||
|
"io.kubernetes.cri-o.ContainerID": "a15ee43034ade4083279bdbb7cf656a971809cfb00eb97a7751bb46dd74c9150",
|
||||||
|
"io.kubernetes.cri-o.ContainerType": "container",
|
||||||
|
"io.kubernetes.cri-o.Created": "2018-06-20T15:08:41.361981842+03:00",
|
||||||
|
"io.kubernetes.cri-o.LogPath": "/var/log/pods/a869ac70-7482-11e8-a041-c81f66f62fcc/test-container/0.log",
|
||||||
|
"io.kubernetes.cri-o.Metadata": "{\"name\":\"test-container\"}",
|
||||||
|
"io.kubernetes.cri-o.SandboxID": "a30829b039e1c631432fe7ab5c748a393c105ed90ec42a6cc95bd7d33356b94e",
|
||||||
|
"io.kubernetes.cri-o.SandboxName": "k8s_POD_test-fpga-region_default_a869ac70-7482-11e8-a041-c81f66f62fcc_0",
|
||||||
|
"io.kubernetes.cri-o.SeccompProfilePath": "",
|
||||||
|
"io.kubernetes.cri-o.Stdin": "false",
|
||||||
|
"io.kubernetes.cri-o.StdinOnce": "false",
|
||||||
|
"io.kubernetes.cri-o.TTY": "false",
|
||||||
|
"io.kubernetes.pod.name": "test-fpga-region",
|
||||||
|
"io.kubernetes.pod.namespace": "default",
|
||||||
|
"io.kubernetes.pod.terminationGracePeriod": "30",
|
||||||
|
"io.kubernetes.pod.uid": "a869ac70-7482-11e8-a041-c81f66f62fcc"
|
||||||
|
},
|
||||||
|
"linux": {
|
||||||
|
"resources": {
|
||||||
|
"devices": [
|
||||||
|
{
|
||||||
|
"allow": false,
|
||||||
|
"access": "rwm"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"allow": true,
|
||||||
|
"type": "c",
|
||||||
|
"major": 243,
|
||||||
|
"minor": 0,
|
||||||
|
"access": "mrw"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"memory": {
|
||||||
|
"limit": 0
|
||||||
|
},
|
||||||
|
"cpu": {
|
||||||
|
"shares": 1024,
|
||||||
|
"quota": 100000,
|
||||||
|
"period": 100000
|
||||||
|
},
|
||||||
|
"pids": {
|
||||||
|
"limit": 1024
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"cgroupsPath": "/kubepods/burstable/poda869ac70-7482-11e8-a041-c81f66f62fcc/crio-a15ee43034ade4083279bdbb7cf656a971809cfb00eb97a7751bb46dd74c9150",
|
||||||
|
"namespaces": [
|
||||||
|
{
|
||||||
|
"type": "pid"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "mount"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"rootfsPropagation": "rslave"
|
||||||
|
}
|
||||||
|
}
|
88
cmd/fpga_crihook/testdata/config-no-linux.json
vendored
Normal file
88
cmd/fpga_crihook/testdata/config-no-linux.json
vendored
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
{
|
||||||
|
"ociVersion": "1.0.0",
|
||||||
|
"process": {
|
||||||
|
"user": {
|
||||||
|
"uid": 0,
|
||||||
|
"gid": 0
|
||||||
|
},
|
||||||
|
"args": [
|
||||||
|
"sh",
|
||||||
|
"/usr/bin/test_fpga.sh"
|
||||||
|
],
|
||||||
|
"env": [
|
||||||
|
"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
|
||||||
|
"TERM=xterm",
|
||||||
|
"HOSTNAME=test-fpga-region",
|
||||||
|
"FPGA_REGION=ce48969398f05f33946d560708be108a",
|
||||||
|
"FPGA_AFU=f7df405cbd7acf7222f144b0b93acd18",
|
||||||
|
"KUBERNETES_SERVICE_PORT=443",
|
||||||
|
"KUBERNETES_PORT_443_TCP_PROTO=tcp",
|
||||||
|
"OPAE_URL=https://github.com/OPAE/opae-sdk/releases/download/1.0.0-5"
|
||||||
|
],
|
||||||
|
"oomScoreAdj": 999
|
||||||
|
},
|
||||||
|
"hostname": "test-fpga-region",
|
||||||
|
"mounts": [
|
||||||
|
{
|
||||||
|
"destination": "/proc",
|
||||||
|
"type": "proc",
|
||||||
|
"source": "proc"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"destination": "/dev",
|
||||||
|
"type": "tmpfs",
|
||||||
|
"source": "tmpfs",
|
||||||
|
"options": [
|
||||||
|
"nosuid",
|
||||||
|
"strictatime",
|
||||||
|
"mode=755",
|
||||||
|
"size=65536k"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"destination": "/sys",
|
||||||
|
"type": "sysfs",
|
||||||
|
"source": "sysfs",
|
||||||
|
"options": [
|
||||||
|
"nosuid",
|
||||||
|
"noexec",
|
||||||
|
"nodev",
|
||||||
|
"ro"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"hooks": {
|
||||||
|
"prestart": [
|
||||||
|
{
|
||||||
|
"path": "/usr/local/bin/fpga_crihook",
|
||||||
|
"args": [
|
||||||
|
"/usr/local/bin/fpga_crihook"
|
||||||
|
],
|
||||||
|
"env": [
|
||||||
|
"stage=prestart"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"annotations": {
|
||||||
|
"io.kubernetes.container.hash": "22e3c9bc",
|
||||||
|
"io.kubernetes.container.name": "test-container",
|
||||||
|
"io.kubernetes.container.restartCount": "0",
|
||||||
|
"io.kubernetes.container.terminationMessagePolicy": "File",
|
||||||
|
"io.kubernetes.cri-o.ContainerID": "a15ee43034ade4083279bdbb7cf656a971809cfb00eb97a7751bb46dd74c9150",
|
||||||
|
"io.kubernetes.cri-o.ContainerType": "container",
|
||||||
|
"io.kubernetes.cri-o.Created": "2018-06-20T15:08:41.361981842+03:00",
|
||||||
|
"io.kubernetes.cri-o.LogPath": "/var/log/pods/a869ac70-7482-11e8-a041-c81f66f62fcc/test-container/0.log",
|
||||||
|
"io.kubernetes.cri-o.Metadata": "{\"name\":\"test-container\"}",
|
||||||
|
"io.kubernetes.cri-o.SandboxID": "a30829b039e1c631432fe7ab5c748a393c105ed90ec42a6cc95bd7d33356b94e",
|
||||||
|
"io.kubernetes.cri-o.SandboxName": "k8s_POD_test-fpga-region_default_a869ac70-7482-11e8-a041-c81f66f62fcc_0",
|
||||||
|
"io.kubernetes.cri-o.SeccompProfilePath": "",
|
||||||
|
"io.kubernetes.cri-o.Stdin": "false",
|
||||||
|
"io.kubernetes.cri-o.StdinOnce": "false",
|
||||||
|
"io.kubernetes.cri-o.TTY": "false",
|
||||||
|
"io.kubernetes.pod.name": "test-fpga-region",
|
||||||
|
"io.kubernetes.pod.namespace": "default",
|
||||||
|
"io.kubernetes.pod.terminationGracePeriod": "30",
|
||||||
|
"io.kubernetes.pod.uid": "a869ac70-7482-11e8-a041-c81f66f62fcc"
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1 @@
|
|||||||
|
f7df405cbd7acf7222f144b0b93acd18
|
@ -0,0 +1 @@
|
|||||||
|
d8424dc4a4a3c413f89e433683f9040b
|
Loading…
Reference in New Issue
Block a user