#695 master

Merged
yangxzh1 merged 28 commits from openioctopus/octopus:master into master 1 year ago
  1. +1
    -1
      admin-portal/src/layout/components/Navbar.vue
  2. +2
    -2
      admin-portal/vue.config.js
  3. +1
    -1
      deploy/charts/octopus/templates/api-doc.yaml
  4. +74
    -0
      deploy/charts/octopus/templates/ascend.yaml
  5. +1352
    -788
      deploy/charts/octopus/templates/grafana.yaml
  6. +3
    -3
      deploy/charts/octopus/templates/prometheus.yaml
  7. +5
    -1
      deploy/charts/octopus/values.yaml
  8. +1
    -1
      deploy/single_master_k8s_install/comm.sh
  9. +1
    -1
      openai-portal/src/layout/components/Navbar.vue
  10. +12
    -12
      openai-portal/src/router/index.js
  11. +21
    -0
      openai-portal/src/utils/index.js
  12. +12
    -2
      openai-portal/src/views/modelDev/components/notebook/notebookCreation.vue
  13. +17
    -5
      openai-portal/src/views/trainingManager/components/createDialog/index.vue
  14. +16
    -16
      openai-portal/src/views/trainingManager/components/editDialog/index.vue
  15. +2
    -2
      openai-portal/src/views/trainingManager/index.vue
  16. +39
    -32
      openai-portal/src/views/trainingManager/traningTask.vue
  17. +1
    -3
      server/admin-server/internal/service/billing.go
  18. +3
    -3
      server/base-server/configs/config.yaml
  19. +5
    -3
      server/base-server/internal/data/dao/billing.go
  20. +0
    -1
      server/base-server/internal/service/billing/billing.go
  21. +5
    -2
      server/go.mod
  22. +77
    -6
      server/go.sum
  23. +41
    -39
      server/openai-server/api/v1/trainJob.proto
  24. +0
    -35
      third-party/cambricon-k8s-device-plugin/.drone.yml
  25. +0
    -7
      third-party/cambricon-k8s-device-plugin/.github/issue_template.md
  26. +0
    -50
      third-party/cambricon-k8s-device-plugin/.github/workflows/ci.yaml
  27. +0
    -41
      third-party/cambricon-k8s-device-plugin/.gitlab-ci.yml
  28. +0
    -25
      third-party/cambricon-k8s-device-plugin/.golangci.yml
  29. +0
    -201
      third-party/cambricon-k8s-device-plugin/LICENSE
  30. +0
    -7
      third-party/cambricon-k8s-device-plugin/README.md
  31. +0
    -5
      third-party/cambricon-k8s-device-plugin/device-plugin/.gitignore
  32. +0
    -50
      third-party/cambricon-k8s-device-plugin/device-plugin/.gitlab-ci.yml
  33. +0
    -14
      third-party/cambricon-k8s-device-plugin/device-plugin/CHANGELOG.md
  34. +0
    -31
      third-party/cambricon-k8s-device-plugin/device-plugin/Dockerfile
  35. +0
    -58
      third-party/cambricon-k8s-device-plugin/device-plugin/Makefile
  36. +0
    -120
      third-party/cambricon-k8s-device-plugin/device-plugin/README.md
  37. +0
    -93
      third-party/cambricon-k8s-device-plugin/device-plugin/build_image.sh
  38. +0
    -198
      third-party/cambricon-k8s-device-plugin/device-plugin/cambricon.go
  39. +0
    -98
      third-party/cambricon-k8s-device-plugin/device-plugin/cambricon_test.go
  40. +0
    -34
      third-party/cambricon-k8s-device-plugin/device-plugin/create_release_package.sh
  41. +0
    -69
      third-party/cambricon-k8s-device-plugin/device-plugin/examples/cambricon-device-plugin-daemonset.yaml
  42. +0
    -48
      third-party/cambricon-k8s-device-plugin/device-plugin/examples/cambricon-device-plugin-static-pod.yaml
  43. +0
    -38
      third-party/cambricon-k8s-device-plugin/device-plugin/examples/deployment.yaml
  44. +0
    -11
      third-party/cambricon-k8s-device-plugin/device-plugin/go.mod
  45. +0
    -373
      third-party/cambricon-k8s-device-plugin/device-plugin/go.sum
  46. +0
    -135
      third-party/cambricon-k8s-device-plugin/device-plugin/main.go
  47. +0
    -112
      third-party/cambricon-k8s-device-plugin/device-plugin/pkg/cndev/bindings.go
  48. +0
    -72
      third-party/cambricon-k8s-device-plugin/device-plugin/pkg/cndev/bindings_test.go
  49. +0
    -155
      third-party/cambricon-k8s-device-plugin/device-plugin/pkg/cndev/cndev.go
  50. +0
    -158
      third-party/cambricon-k8s-device-plugin/device-plugin/pkg/cndev/cndev_dl.c
  51. +0
    -26
      third-party/cambricon-k8s-device-plugin/device-plugin/pkg/cndev/cndev_dl.h
  52. +0
    -54
      third-party/cambricon-k8s-device-plugin/device-plugin/pkg/cndev/cndev_test.go
  53. +0
    -1471
      third-party/cambricon-k8s-device-plugin/device-plugin/pkg/cndev/include/cndev.h
  54. +0
    -750
      third-party/cambricon-k8s-device-plugin/device-plugin/pkg/cndev/mock/cJSON.c
  55. +0
    -149
      third-party/cambricon-k8s-device-plugin/device-plugin/pkg/cndev/mock/cJSON.h
  56. +0
    -173
      third-party/cambricon-k8s-device-plugin/device-plugin/pkg/cndev/mock/cndev.c
  57. +0
    -76
      third-party/cambricon-k8s-device-plugin/device-plugin/pkg/cndev/mock/main.c
  58. +0
    -336
      third-party/cambricon-k8s-device-plugin/device-plugin/server.go
  59. +0
    -423
      third-party/cambricon-k8s-device-plugin/device-plugin/server_test.go
  60. +0
    -18
      third-party/cambricon-k8s-device-plugin/device-plugin/test/Dockerfile
  61. +0
    -137
      third-party/cambricon-k8s-device-plugin/device-plugin/test/device-plugin-integration-test.sh
  62. +0
    -107
      third-party/cambricon-k8s-device-plugin/device-plugin/test/do-test-device-plugin.sh
  63. +0
    -9
      third-party/cambricon-k8s-device-plugin/device-plugin/test/mockmlu100.json
  64. +0
    -28
      third-party/cambricon-k8s-device-plugin/device-plugin/test/mockmlu270.json
  65. +0
    -34
      third-party/k8s-fpga-device-plugin/.drone.yml
  66. +0
    -30
      third-party/k8s-fpga-device-plugin/Dockerfile
  67. +0
    -17
      third-party/k8s-fpga-device-plugin/FAQ.md
  68. +0
    -202
      third-party/k8s-fpga-device-plugin/LICENSE
  69. +0
    -38
      third-party/k8s-fpga-device-plugin/README.md
  70. +0
    -56
      third-party/k8s-fpga-device-plugin/aws-accelator-pod.yaml
  71. +0
    -194
      third-party/k8s-fpga-device-plugin/aws-readme.md
  72. +0
    -26
      third-party/k8s-fpga-device-plugin/aws-test-client-pod.yaml
  73. +0
    -19
      third-party/k8s-fpga-device-plugin/aws/Dockerfile
  74. +0
    -84
      third-party/k8s-fpga-device-plugin/aws/README.md
  75. +0
    -44
      third-party/k8s-fpga-device-plugin/aws/aws-fpga-device-plugin.yaml
  76. +0
    -14
      third-party/k8s-fpga-device-plugin/aws/build
  77. +0
    -157
      third-party/k8s-fpga-device-plugin/aws/fpga_aws.go
  78. +0
    -1
      third-party/k8s-fpga-device-plugin/aws/main.go
  79. +0
    -36
      third-party/k8s-fpga-device-plugin/aws/mypod.yaml
  80. +0
    -1
      third-party/k8s-fpga-device-plugin/aws/server.go
  81. +0
    -1
      third-party/k8s-fpga-device-plugin/aws/watcher.go
  82. BIN
      third-party/k8s-fpga-device-plugin/bin/k8s-fpga-device-plugin
  83. +0
    -18
      third-party/k8s-fpga-device-plugin/build
  84. +0
    -106
      third-party/k8s-fpga-device-plugin/docker/README.md
  85. +0
    -2
      third-party/k8s-fpga-device-plugin/docker/build_fpga_server_docker/Dockerfile
  86. BIN
      third-party/k8s-fpga-device-plugin/docker/build_fpga_server_docker/server/fpga_algo.awsxclbin
  87. BIN
      third-party/k8s-fpga-device-plugin/docker/build_fpga_server_docker/server/fpga_host_exe
  88. +0
    -60
      third-party/k8s-fpga-device-plugin/docker/build_fpga_server_docker/server/fpga_server.py
  89. +0
    -4
      third-party/k8s-fpga-device-plugin/docker/build_fpga_server_docker/server/run.sh
  90. +0
    -2
      third-party/k8s-fpga-device-plugin/docker/build_test_client_docker/Dockerfile
  91. +0
    -34
      third-party/k8s-fpga-device-plugin/docker/build_test_client_docker/client/client.py
  92. +0
    -28
      third-party/k8s-fpga-device-plugin/dp-pod.yaml
  93. +0
    -50
      third-party/k8s-fpga-device-plugin/fpga-device-plugin.yml
  94. +0
    -274
      third-party/k8s-fpga-device-plugin/fpga.go
  95. +0
    -469
      third-party/k8s-fpga-device-plugin/full-tutorial.md
  96. +0
    -84
      third-party/k8s-fpga-device-plugin/main.go
  97. +0
    -171
      third-party/k8s-fpga-device-plugin/quickstart.md
  98. +0
    -383
      third-party/k8s-fpga-device-plugin/server.go
  99. +0
    -1
      third-party/k8s-fpga-device-plugin/src
  100. +0
    -31
      third-party/k8s-fpga-device-plugin/watcher.go

+ 1
- 1
admin-portal/src/layout/components/Navbar.vue View File

@@ -6,7 +6,7 @@
<el-row class="demo-avatar demo-basic">
<el-dropdown>
<i class="el-icon-document" style="color:#666699;"></i>
<a href="https://octopus.openi.org.cn/docs/management/intro" target="_blank" class="manual">管理手册</a>
<a href="https://octopus.pcl.ac.cn/" target="_blank" class="manual">管理手册</a>
<i class="el-icon-service" style="color:#666699 ;"></i>
<a href="https://git.openi.org.cn/OpenI/octopus/issues" target="_blank" class="manual">问题意见</a>
<el-dropdown-menu slot="dropdown" />


+ 2
- 2
admin-portal/vue.config.js View File

@@ -38,14 +38,14 @@ module.exports = {
},
proxy: {
[process.env.VUE_APP_BASE_API]: {
target: 'http://192.168.202.73',
target: 'http://192.168.202.71/',
changeOrigin: true,
pathRewrite: {
['^' + process.env.VUE_APP_BASE_API]: '/adminserver'
}
},
[process.env.VUE_APP_BASE_API2]: {
target: 'http://192.168.202.73',
target: 'http://192.168.202.71/',
changeOrigin: true,
pathRewrite: {
['^' + process.env.VUE_APP_BASE_API]: ''


+ 1
- 1
deploy/charts/octopus/templates/api-doc.yaml View File

@@ -51,7 +51,7 @@ spec:
mountPath: /etc/localtime
env:
- name: URLS
value: "[{url:\"{{ .Values.ingress.apidocPath }}/admin.swagger.json\",name:\"admin\"},{url:\"{{ .Values.ingress.apidocPath }}/openai.swagger.json\",name:\"openai\"}]"
value: "[{url:\"{{ .Values.ingress.apidocPath }}/openai.swagger.json\",name:\"计算平台API\"},{url:\"{{ .Values.ingress.apidocPath }}/admin.swagger.json\",name:\"管理后台API\"}]"
ports:
- name: http
containerPort: {{ template "apidoc.targetPort" . }}


+ 74
- 0
deploy/charts/octopus/templates/ascend.yaml View File

@@ -0,0 +1,74 @@
{{- if .Values.ascend.enabled }}
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: ascend-device-plugin-daemonset
namespace: kube-system
spec:
selector:
matchLabels:
name: ascend-device-plugin-ds
updateStrategy:
type: RollingUpdate
template:
metadata:
annotations:
scheduler.alpha.kubernetes.io/critical-pod: ""
seccomp.security.alpha.kubernetes.io/pod: runtime/default
labels:
name: ascend-device-plugin-ds
spec:
tolerations:
- key: CriticalAddonsOnly
operator: Exists
- key: huawei.com/Ascend910
operator: Exists
effect: NoSchedule
- key: "device-plugin"
operator: "Equal"
value: "v2"
effect: NoSchedule
priorityClassName: "system-node-critical"
nodeSelector:
hardware-type: ASCENDNPU
containers:
- image: swr.cn-south-1.myhuaweicloud.com/openioctopus/ascend-k8sdeviceplugin:v3.0.RC1
name: device-plugin-01
resources:
requests:
memory: 500Mi
cpu: 500m
limits:
memory: 500Mi
cpu: 500m
command: [ "/bin/bash", "-c", "--"]
args: [ "device-plugin -useAscendDocker=true
-logFile=/var/log/mindx-dl/devicePlugin/devicePlugin.log -logLevel=0" ]
securityContext:
privileged: true
readOnlyRootFilesystem: true
imagePullPolicy: IfNotPresent
volumeMounts:
- name: device-plugin
mountPath: /var/lib/kubelet/device-plugins
- name: hiai-driver
mountPath: /usr/local/Ascend/driver
- name: log-path
mountPath: /var/log/mindx-dl/devicePlugin
- name: tmp
mountPath: /tmp
volumes:
- name: device-plugin
hostPath:
path: /var/lib/kubelet/device-plugins
- name: hiai-driver
hostPath:
path: /usr/local/Ascend/driver
- name: log-path
hostPath:
path: /var/log/mindx-dl/devicePlugin
type: Directory
- name: tmp
hostPath:
path: /tmp
{{- end }}

+ 1352
- 788
deploy/charts/octopus/templates/grafana.yaml
File diff suppressed because it is too large
View File


+ 3
- 3
deploy/charts/octopus/templates/prometheus.yaml View File

@@ -446,10 +446,10 @@ spec:
app.kubernetes.io/part-of: {{ template "prometheus.name" . }}
spec:
nodeSelector:
workerselector: dls-worker-node
hardware-type: ASCENDNPU
containers:
- name: huawei-npu-exporter
image: 192.168.202.110:5000/octopus/npu-exporter:v3.0.RC1
image: swr.cn-south-1.myhuaweicloud.com/openioctopus/npu-exporter:v3.0.RC1
resources:
requests:
memory: 1000Mi
@@ -457,7 +457,7 @@ spec:
limits:
memory: 1000Mi
cpu: 1000m
imagePullPolicy: Never
imagePullPolicy: IfNotPresent
command: [ "/bin/bash", "-c", "--"]
# NOTE: enable HTTPS needs to use
# ./cert-importer -certFile=../cert/rsa_aes.crt -keyFile=../cert/rsa_aes_private.key to import certificate


+ 5
- 1
deploy/charts/octopus/values.yaml View File

@@ -511,4 +511,8 @@ cambricon:

nvidia:
# nvidia节点需要打标签hardware-type=NVIDIAGPU
enabled: true
enabled: true

ascend:
# ascend节点需要打标签hardware-type=ASCENDNPU
enabled: false

+ 1
- 1
deploy/single_master_k8s_install/comm.sh View File

@@ -250,5 +250,5 @@ cambricon_mlu_label() {

# huawei a910节点打标签
huawei_a910_label() {
kubectl label nodes `hostname` a910-device-plugin=active
kubectl label nodes `hostname` hardware-type=ASCENDNPU
}

+ 1
- 1
openai-portal/src/layout/components/Navbar.vue View File

@@ -13,7 +13,7 @@
<el-dropdown>
<div v-show="!this.GLOBAL.THEME_MANUAL_INVISIBLE">
<i class="el-icon-document" :style="{'color':fontColor?fontColor:'#666699'}" />
<a href="https://octopus.openi.org.cn/docs/manual/intro" target="_blank" class="manual"
<a href="https://octopus.pcl.ac.cn/" target="_blank" class="manual"
:style="{'color':fontColor}">使用手册</a>
<i class="el-icon-service" :style="{'color':fontColor?fontColor:'#666699'}" />
<a href="https://git.openi.org.cn/OpenI/octopus/issues" target="_blank" class="manual"


+ 12
- 12
openai-portal/src/router/index.js View File

@@ -138,18 +138,18 @@ export const constantRoutes = [
}
]
},
{
path: '/cloudInterconnection',
component: Layout,
children: [
{
path: 'index',
name: 'cloudInterconnection',
component: () => import('@/views/cloudInterconnection/index'),
meta: { title: '云际互联', icon: 'cloudConnection' }
}
]
},
// {
// path: '/cloudInterconnection',
// component: Layout,
// children: [
// {
// path: 'index',
// name: 'cloudInterconnection',
// component: () => import('@/views/cloudInterconnection/index'),
// meta: { title: '云际互联', icon: 'cloudConnection' }
// }
// ]
// },
{
path: '/setting',
component: Layout,


+ 21
- 0
openai-portal/src/utils/index.js View File

@@ -152,3 +152,24 @@ export function clearProgress(paraName) {
}
}

// 生成随机名字
export function randomName(val) {
var myDate = new Date();
const year = myDate.getFullYear().toString()
let month = (myDate.getMonth() + 1).toString()
if (month < 10) {
month = '0' + (myDate.getMonth() + 1).toString()
}
let date = myDate.getDate().toString()
if (date < 10) {
date = '0' + myDate.getDate().toString()
}
var charactors = "ab1cd2ef3gh4ij5kl6mn7opq8rst9uvw0xyz";
var value = ''; var i;
for (let j = 1; j <= 4; j++) {
i = parseInt(35 * Math.random());
value = value + charactors.charAt(i);
}
const name = val + '-' + year + month + date + '-' + value
return name
}

+ 12
- 2
openai-portal/src/views/modelDev/components/notebook/notebookCreation.vue View File

@@ -123,6 +123,7 @@
import { getMyImage, getPublicImage, getPreImage } from "@/api/imageManager";
import { getResourceList } from "@/api/trainingManager";
import { mapGetters } from 'vuex'
import { randomName } from '@/utils/index'
export default {
name: "NotebookCreation",
directives: {
@@ -264,6 +265,7 @@
created() {
// this.getResource();
this.getSpacePools();
this.ruleForm.name = this.randomName('notebook')
},
computed: {
...mapGetters([
@@ -271,6 +273,9 @@
])
},
methods: {
randomName(val) {
return randomName(val)
},
clearDataSetVersionOption() {
this.dataSetVersionOption = []
},
@@ -762,9 +767,14 @@

.tip {
margin: 16px 0 16px 120px;
color:#B3B3B3
color: #B3B3B3
}

.tip span {
color: #000;
font-weight: 600;
}
.tip span{color:#000;font-weight: 600;}
.el-alert__icon {
color: orange
}

+ 17
- 5
openai-portal/src/views/trainingManager/components/createDialog/index.vue View File

@@ -4,7 +4,8 @@
:close-on-click-modal="false">
<el-form ref="ruleForm" :model="ruleForm" :rules="rules" :label-width="formLabelWidth"
class="demo-ruleForm">
<el-form-item :label="name" :label-width="formLabelWidth" placeholder="请输入任务名称" prop="name" class="[flag ==2 : 'name'? '']">
<el-form-item :label="name" :label-width="formLabelWidth" placeholder="请输入任务名称" prop="name"
class="[flag ==2 : 'name'? '']">
<el-input v-model="ruleForm.name" maxlength="30" show-word-limit />
</el-form-item>
<div class="tip" v-if="flag!=2"><i
@@ -139,8 +140,8 @@
<div slot="footer" class="dialog-footer">
<el-button v-if="showTraning" type="success" @click="traningAndSave('traning')" v-preventReClick>开始训练
</el-button>
<el-button v-if="showTemplate" type="primary" @click="traningAndSave('save')" v-preventReClick>保存模板
</el-button>
<!-- <el-button v-if="showTemplate" type="primary" @click="traningAndSave('save')" v-preventReClick>保存模板
</el-button> -->
<el-button type="warning" @click="cancel">取消</el-button>
</div>
</el-dialog>
@@ -154,6 +155,7 @@
import { getPresetAlgorithmList, getPublicAlgorithmList, getMyAlgorithmList, getAlgorithmVersionList } from '@/api/modelDev'
import { getMyImage, getPublicImage, getPreImage } from '@/api/imageManager'
import { getMyDatasetList, getPublicDatasetList, getPresetDatasetList, getVersionList } from '@/api/datasetManager'
import { randomName } from '@/utils/index'
export default {
name: "DialogCreateForm",
components: {
@@ -360,8 +362,12 @@
this.algorithmName = true
this.algorithmVersion = true
}
this.ruleForm.name = this.randomName('trainjob')
},
methods: {
randomName(val) {
return randomName(val)
},
clearDataSetVersionOption() {
this.dataSetVersionOption = []
},
@@ -886,15 +892,21 @@
.block {
display: block !important;
}

.name {
margin-bottom: 0px
}

.tip {
margin: 16px 0 16px 120px;
color:#B3B3B3
color: #B3B3B3
}
.tip span{color:#000;font-weight: 600;}

.tip span {
color: #000;
font-weight: 600;
}

.el-alert__icon {
color: orange
}

+ 16
- 16
openai-portal/src/views/trainingManager/components/editDialog/index.vue View File

@@ -4,14 +4,13 @@
:close-on-click-modal="false">
<el-form ref="ruleForm" :model="ruleForm" :rules="rules" :label-width="formLabelWidth"
class="demo-ruleForm">
<el-form-item :label="name" :label-width="formLabelWidth" placeholder="请输入镜像名称" prop="name"
class="[flag ==2 : 'name'? '']">
<el-form-item label="任务名称" :label-width="formLabelWidth" placeholder="请输入任务名称" prop="name">
<el-input v-model="ruleForm.name" maxlength="30" show-word-limit />
</el-form-item>
<div class="tip" v-if="flag==2"><i
<div class="tip"><i
class="el-alert__icon el-icon-warning"></i>算法存储在<span>/code</span>中,数据集存储在<span>/dataset</span>中,用户目录在<span>/userhome</span>中,训练输出请存储在<span>/model</span>中以供后续下载
</div>
<el-form-item :label="desc" :label-width="formLabelWidth">
<el-form-item label="任务描述" :label-width="formLabelWidth">
<el-input v-model="ruleForm.desc" type="textarea" maxlength="300" show-word-limit />
</el-form-item>
<!-- 算法三级框 -->
@@ -137,10 +136,10 @@
</div>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button v-if="showTraning" type="success" @click="traningAndSave('traning')" v-preventReClick>开始训练
</el-button>
<el-button v-if="!showTemplate" type="primary" @click="traningAndSave('save')" v-preventReClick>保存模板
<el-button type="success" @click="traningAndSave('traning')" v-preventReClick>开始训练
</el-button>
<!-- <el-button v-if="!showTemplate" type="primary" @click="traningAndSave('save')" v-preventReClick>保存模板
</el-button> -->
<el-button type="warning" @click="cancel">取消</el-button>
</div>
</el-dialog>
@@ -154,6 +153,7 @@
import { getPresetAlgorithmList, getPublicAlgorithmList, getMyAlgorithmList, getAlgorithmVersionList } from '@/api/modelDev'
import { getMyImage, getPublicImage, getPreImage } from '@/api/imageManager'
import { getMyDatasetList, getPublicDatasetList, getPresetDatasetList, getVersionList } from '@/api/datasetManager'
import { randomName } from '@/utils/index'
export default {
name: "DialogEditForm",
components: {
@@ -283,8 +283,6 @@
algorithmNameTemp: '',
imageTemp: '',
dataSetTemp: '',
name: '',
desc: ''

}
},
@@ -293,15 +291,13 @@
switch (this.flag) {
case 1:
this.showTraning = false
this.name = '模版名称'
this.desc = '模版描述'
return '编辑任务模板'
delete this.rules.resourcePool
return '编辑训练任务'
break
case 2:
this.showTraning = true
this.showTemplate = true
this.name = '任务名称'
this.desc = '任务描述'

return '创建训练任务'
break
}
@@ -344,8 +340,12 @@
this.dataSetVersion = true
// 获取模板信息
this.getSpacePools()
this.ruleForm.name = this.randomName('trainjob')
},
methods: {
randomName(val) {
return randomName(val)
},
clearDataSetVersionOption() {
this.dataSetVersionOption = []
},
@@ -387,7 +387,7 @@
if (this.flag === 2) {
this.ruleForm.name = ''
}
this.getResourceList()
// this.getResourceList()
},
changeDisResourceList() {
this.resourceOptions = []
@@ -437,7 +437,7 @@
},
cancel() {
let message = ''
if (this.flag === 1) { message = '此操作将放弃编辑任务模板, 是否继续?' } else { message = '此操作将放弃创建训练任务,是否继续' }
if (this.flag === 1) { message = '此操作将放弃编辑训练任务, 是否继续?' } else { message = '此操作将放弃创建训练任务,是否继续' }
this.$confirm(message, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',


+ 2
- 2
openai-portal/src/views/trainingManager/index.vue View File

@@ -3,9 +3,9 @@
<el-tab-pane label="训练任务" name="menu1">
<traningTask v-if="tabRefresh.menu1" :training-task="trainingTask" />
</el-tab-pane>
<el-tab-pane label="任务模板" name="menu2">
<!-- <el-tab-pane label="任务模板" name="menu2">
<taskTemplate v-if="tabRefresh.menu2" :training-template="trainingTemplate" @createTraning="createTraning" />
</el-tab-pane>
</el-tab-pane> -->
</el-tabs>
</template>
<script>


+ 39
- 32
openai-portal/src/views/trainingManager/traningTask.vue View File

@@ -5,14 +5,9 @@
</div>
<el-button type="primary" class="create" @click="open()">批量删除</el-button>
<el-button type="primary" class="create" @click="create">创建任务</el-button>
<el-table
ref="multipleTable"
:data="tableData"
style="width: 100%;font-size: 15px;"
:header-cell-style="{'text-align':'left','color':'black'}"
:cell-style="{'text-align':'left'}"
@selection-change="handleSelectionChange"
>
<el-table ref="multipleTable" :data="tableData" style="width: 100%;font-size: 15px;"
:header-cell-style="{'text-align':'left','color':'black'}" :cell-style="{'text-align':'left'}"
@selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" :selectable="checkSelectable" />
<el-table-column label="任务名称" align="center">
<template slot-scope="scope">
@@ -59,42 +54,35 @@
<template slot-scope="scope">
<el-button
v-if="scope.row.status==='pending'||scope.row.status==='running'||scope.row.status==='preparing'"
type="text"
@click="open2(scope.row)"
>
type="text" @click="open2(scope.row)">
停止
</el-button>
<el-button type="text" @click="handleDetail(scope.row)">详情</el-button>
<el-button
v-if="scope.row.status==='failed'||scope.row.status==='succeeded'||scope.row.status==='stopped'"
type="text"
@click="open(scope.row)"
>删除
type="text" @click="open(scope.row)">删除
</el-button>
<el-button type="text" @click="handleEdit(scope.row,'editTemplate')">重新训练</el-button>
</template>
</el-table-column>
</el-table>
<div class="block">
<el-pagination
:current-page="searchData.pageIndex"
:page-sizes="[10, 20, 50, 80]"
:page-size="searchData.pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="total"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
/>
<el-pagination :current-page="searchData.pageIndex" :page-sizes="[10, 20, 50, 80]"
:page-size="searchData.pageSize" layout="total, sizes, prev, pager, next, jumper" :total="total"
@size-change="handleSizeChange" @current-change="handleCurrentChange" />
</div>
<!-- 创建对话框 -->
<createDialog v-if="createDialog" :row="row" :flag="flag" @cancel="cancel" @confirm="confirm" @close="close" />
<!-- 详情对话框 -->
<detailDialog v-if="detailDialog" :data="data" @cancel="cancel" @confirm="confirm" @close="close" />
<editDialog v-if="editDialog" :flag="flag" :row="row" @cancel="cancel" @confirm="confirm" @close="close" />

</div>
</template>
<script>
import createDialog from "./components/createDialog/index.vue";
import detailDialog from "./components/detailDialog/index.vue";
import editDialog from "./components/editDialog/index.vue";
import { getList, stop, Delete, getTraningDetail } from '@/api/trainingManager'
import searchForm from '@/components/search/index.vue'
import { formatDuring } from '@/utils/index'
@@ -103,13 +91,14 @@
components: {
createDialog,
detailDialog,
searchForm
searchForm,
editDialog,
},
props: {
trainingTask: {
type: Boolean,
default: false
}
trainingTask: {
type: Boolean,
default: false
}
},
data() {
return {
@@ -119,6 +108,7 @@
data: {},
createDialog: false,
detailDialog: false,
editDialog: false,
total: undefined,
statusText: { 'preparing': ['status-ready', '初始中'], 'pending': ['status-agent', '等待中'], 'running': ['status-running', '运行中'], 'failed': ['status-danger', '失败'], 'succeeded': ['status-success', '成功'], 'stopped': ['status-stopping', '已停止'] },
flag: undefined,
@@ -266,17 +256,20 @@
cancel(val) {
this.getList(this.searchData)
this.createDialog = val;
this.detailDialog = val
this.detailDialog = val;
this.editDialog = val
},
confirm(val) {
this.getList(this.searchData)
this.createDialog = val;
this.detailDialog = val
this.detailDialog = val;
this.editDialog = val
},
close(val) {
this.getList(this.searchData)
this.createDialog = val;
this.detailDialog = val
this.detailDialog = val;
this.editDialog = val
},
create() {
this.createDialog = true; this.row = {}
@@ -327,7 +320,21 @@
message: '已取消操作'
});
});
}
},
handleEdit(val, name) {
getTraningDetail(val.id).then(response => {
if (response.success) {
this.editDialog = true
this.row = response.data.trainJob
if (name === 'editTemplate') { this.flag = 1 } else { this.flag = 2 }
} else {
this.$message({
message: this.getErrorMsg(response.error.subcode),
type: 'warning'
});
}
})
},

}
}


+ 1
- 3
server/admin-server/internal/service/billing.go View File

@@ -2,6 +2,7 @@ package service

import (
"context"
"github.com/jinzhu/copier"
api "server/admin-server/api/v1"
"server/admin-server/internal/conf"
"server/admin-server/internal/data"
@@ -9,8 +10,6 @@ import (
"server/common/errors"
"server/common/log"
"server/common/utils/collections/set"

"github.com/jinzhu/copier"
)

type billingService struct {
@@ -111,7 +110,6 @@ func (s *billingService) RechargeUser(ctx context.Context, req *api.RechargeUser
Amount: req.Amount,
Title: req.Title,
})

if err != nil {
return nil, err
}


+ 3
- 3
server/base-server/configs/config.yaml View File

@@ -15,8 +15,8 @@ data:
driver: mysql
source: root:root@tcp(192.168.203.154:30336)/octopus?charset=utf8&parseTime=True&loc=Local
kubernetes:
masterUrl: https://192.168.202.73:6443/
configPath: C:/Users/dell/Desktop/154kubeconfig
masterUrl: https://192.168.203.154:6443/
configPath: C:/Users/dell/Desktop/kubeconfig
minio:
base:
endPoint: 192.168.203.154:31311
@@ -36,7 +36,7 @@ data:
apiVersion: v1.0
useSSL: false
redis:
addr: 192.168.203.154:32112
addr: 192.168.203.154:32260
username:
password: abcde
influxdb:


+ 5
- 3
server/base-server/internal/data/dao/billing.go View File

@@ -4,14 +4,13 @@ import (
"context"
stderrors "errors"
"fmt"
"gorm.io/gorm"
"server/base-server/internal/data/dao/model"
"server/common/errors"
"server/common/log"
"server/common/transaction"
"server/common/utils"
"time"

"gorm.io/gorm"
)

type BillingDao interface {
@@ -74,7 +73,10 @@ func (d *billingDao) CreateBillingOwner(ctx context.Context, owner *model.Billin

func (d *billingDao) UpdateBillingOwnerSelective(ctx context.Context, key *model.BillingOwnerKey, owner *model.BillingOwner) error {
db := d.db(ctx)
res := db.Where("owner_id = ? and owner_type = ? ", key.OwnerId, key.OwnerType).Updates(owner)
ownerMap := map[string]interface{}{
"amount":owner.Amount,
}
res := db.Model(model.BillingOwner{}).Where("owner_id = ? and owner_type = ? ", key.OwnerId, key.OwnerType).Updates(ownerMap)

if res.Error != nil {
return errors.Errorf(res.Error, errors.ErrorDBUpdateFailed)


+ 0
- 1
server/base-server/internal/service/billing/billing.go View File

@@ -210,7 +210,6 @@ func (s *billingService) Recharge(ctx context.Context, req *api.RechargeRequest)
if err != nil {
return err
}

err = s.data.BillingDao.UpdateBillingOwnerSelective(ctx, ownerKey, &model.BillingOwner{Amount: owner.Amount + req.Amount})
if err != nil {
return err


+ 5
- 2
server/go.mod View File

@@ -26,7 +26,7 @@ require (
golang.org/x/oauth2 v0.0.0-20210413134643-5e61552d6c78
golang.org/x/text v0.3.6
gonum.org/v1/gonum v0.8.2
google.golang.org/genproto v0.0.0-20210416161957-9910b6c460de
google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c
google.golang.org/grpc v1.40.0
google.golang.org/protobuf v1.27.1
gopkg.in/errgo.v2 v2.1.0
@@ -44,6 +44,7 @@ require (
)

require (
cloud.google.com/go v0.81.0 // indirect
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 // indirect
github.com/Microsoft/go-winio v0.5.1 // indirect
github.com/Microsoft/hcsshim v0.9.1 // indirect
@@ -127,12 +128,14 @@ require (
golang.org/x/sys v0.0.0-20211213223007-03aa0b5f6827 // indirect
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 // indirect
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect
golang.org/x/tools v0.1.5 // indirect
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect
google.golang.org/api v0.44.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
gopkg.in/evanphx/json-patch.v4 v4.9.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/ini.v1 v1.57.0 // indirect
gopkg.in/ini.v1 v1.62.0 // indirect
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
k8s.io/apiextensions-apiserver v0.22.1 // indirect
k8s.io/component-base v0.22.1 // indirect


+ 77
- 6
server/go.sum View File

@@ -26,8 +26,12 @@ cloud.google.com/go v0.60.0/go.mod h1:yw2G51M9IfRboUH61Us8GqCeF1PzPblB823Mn2q2eA
cloud.google.com/go v0.61.0/go.mod h1:XukKJg4Y7QsUu0Hxg3qQKUWR4VuWivmyMK2+rUyxAqw=
cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
cloud.google.com/go v0.72.0 h1:eWRCuwubtDrCJG0oSUMgnsbD4CmPFQF2ei4OFbXvwww=
cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI=
cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk=
cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg=
cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8=
cloud.google.com/go v0.81.0 h1:at8Tk2zUz63cLPR0JPWm5vp77pEZmzxEQBEfRKn1VV8=
cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0=
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
@@ -355,6 +359,7 @@ github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kB
github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA=
github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA=
github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM=
github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb/go.mod h1:PkYb9DJNAwrSvRx5DYA+gUcOIgTGVMNkfSCbZM8cWpI=
github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
github.com/blang/semver v3.5.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
@@ -423,6 +428,7 @@ github.com/cloudevents/sdk-go v0.0.0-20190509003705-56931988abe3/go.mod h1:j1nZW
github.com/cloudevents/sdk-go v1.0.0/go.mod h1:3TkmM0cFqkhCHOq5JzzRU/RxRkwzoS8TZ+G448qVTog=
github.com/cloudevents/sdk-go/v2 v2.0.0/go.mod h1:3CTrpB4+u7Iaj6fd7E2Xvm5IxMdRoaAhqaRVnOr2rCU=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
@@ -633,6 +639,7 @@ github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4s
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po=
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
@@ -773,6 +780,7 @@ github.com/go-openapi/validate v0.19.2/go.mod h1:1tRCw7m3jtI8eNWEEliiAqUIcBztB2K
github.com/go-openapi/validate v0.19.3/go.mod h1:90Vh6jjkTn+OT1Eefm0ZixWNFjhtOH7vS9k0lo6zwJo=
github.com/go-openapi/validate v0.19.5/go.mod h1:8DJv2CVJQ6kGNpFW6eV9N3JviE1C85nY1c2z52x1Gk4=
github.com/go-openapi/validate v0.19.8/go.mod h1:8DJv2CVJQ6kGNpFW6eV9N3JviE1C85nY1c2z52x1Gk4=
github.com/go-redis/redis v6.15.9+incompatible h1:K0pv1D7EQUjfyoMql+r/jZqCLizCGKFlFgcHWWmHQjg=
github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
github.com/go-redis/redis/v8 v8.1.0/go.mod h1:isLoQT/NFSP7V67lyvM9GmdvLdyZ7pEhsXvvyQtnQTo=
github.com/go-redis/redis/v8 v8.10.0 h1:OZwrQKuZqdJ4QIM8wn8rnuz868Li91xA3J2DEq+TPGA=
@@ -875,6 +883,7 @@ github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8=
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
@@ -892,6 +901,7 @@ github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QD
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
@@ -988,6 +998,9 @@ github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hf
github.com/google/pprof v0.0.0-20200507031123-427632fa3b1c/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/rpmpack v0.0.0-20191226140753-aa36bfddb3a0/go.mod h1:RaTPr0KUf2K7fnZYLNDrr8rxAamWs3iNywJLtQ2AzBg=
github.com/google/subcommands v1.0.1/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk=
@@ -1019,6 +1032,7 @@ github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEo
github.com/gophercloud/gophercloud v0.10.0/go.mod h1:gmC5oQqMDOMO1t1gq5DquX/yAU808e/4mzjjDA76+Ss=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gopherjs/gopherjs v0.0.0-20220104163920-15ed2e8cf2bd h1:D/H64OK+VY7O0guGbCQaFKwAZlU5t764R++kgIdAGog=
github.com/gopherjs/gopherjs v0.0.0-20220104163920-15ed2e8cf2bd/go.mod h1:cz9oNYuRUWGdHmLF2IodMLkAhcPtXeULvcBNagUrxTI=
github.com/goreleaser/goreleaser v0.136.0/go.mod h1:wiKrPUeSNh6Wu8nUHxZydSOVQ/OZvOaO7DTtFqie904=
github.com/goreleaser/nfpm v1.2.1/go.mod h1:TtWrABZozuLOttX2uDlYyECfQX7x5XYkVxhjYcR6G9w=
github.com/goreleaser/nfpm v1.3.0/go.mod h1:w0p7Kc9TAUgWMyrub63ex3M2Mgw88M4GZXoTq5UCb40=
@@ -1256,6 +1270,7 @@ github.com/konsorten/go-windows-terminal-sequences v0.0.0-20180402223658-b729f26
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
@@ -1286,6 +1301,7 @@ github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e/go.mod h1:7rIyQ
github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
@@ -1365,6 +1381,7 @@ github.com/minio/md5-simd v1.1.0 h1:QPfiOqlZH+Cj9teu0t9b1nTBfPbyTl16Of5MeuShdK4=
github.com/minio/md5-simd v1.1.0/go.mod h1:XpBqgZULrMYD3R+M28PcmP0CkI7PEMzB3U77ZrKZ0Gw=
github.com/minio/minio-go/v7 v7.0.23 h1:NleyGQvAn9VQMU+YHVrgV4CX+EPtxPt/78lHOOTncy4=
github.com/minio/minio-go/v7 v7.0.23/go.mod h1:ei5JjmxwHaMrgsMrn4U/+Nmg+d8MKS1U2DAn1ou4+Do=
github.com/minio/sha256-simd v0.1.1/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM=
github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g=
github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM=
github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4=
@@ -1386,6 +1403,7 @@ github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh
github.com/mitchellh/mapstructure v1.2.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/mapstructure v1.3.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A=
github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc=
@@ -1435,6 +1453,8 @@ github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OS
github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms=
github.com/nbutton23/zxcvbn-go v0.0.0-20180912185939-ae427f1e4c1d/go.mod h1:o96djdrsSGy3AWPyBgZMAGfxZNfgntdJG+11KU4QvbU=
github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM=
github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo=
github.com/neelance/sourcemap v0.0.0-20200213170602-2833bce08e4c/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/nwaples/rardecode v1.0.0/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0=
@@ -1536,6 +1556,7 @@ github.com/pelletier/go-toml v1.4.0/go.mod h1:PN7xzY2wHTK0K9p34ErDQMlFxa51Fk0OUr
github.com/pelletier/go-toml v1.6.0/go.mod h1:5N711Q9dKgbdkxHL+MEfF31hpT7l0S0s/t2kKREewys=
github.com/pelletier/go-toml v1.8.0/go.mod h1:D6yutnOGMveHEPV7VQOuvI/gXY61bv+9bAOTRnLElKs=
github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc=
github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac=
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
github.com/peterh/liner v1.0.1-0.20180619022028-8c1271fcf47f/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc=
@@ -1557,6 +1578,7 @@ github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA=
github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI=
github.com/pkg/term v0.0.0-20180730021639-bffc007b7fd5 h1:tFwafIEMf0B7NlcxV/zJ6leBIa81D3hgGSgsE5hCkOQ=
github.com/pkg/term v0.0.0-20180730021639-bffc007b7fd5/go.mod h1:eCbImbZ95eXtAUIbLAuAVnBnwf83mjf6QIVH8SHYwqQ=
github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
@@ -1685,6 +1707,7 @@ github.com/seldonio/seldon-core/operator v1.11.2/go.mod h1:t55mI0E9CucN2qW3NBTsL
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
github.com/shirou/gopsutil v0.0.0-20190901111213-e4ec7b275ada h1:WokF3GuxBeL+n4Lk4Fa8v9mbdjlrl7bHuneF4N1bk2I=
github.com/shirou/gopsutil v0.0.0-20190901111213-e4ec7b275ada/go.mod h1:WWnYX4lzhCH5h/3YBfyVA3VbLYjlMZZAQcW9ojMexNc=
github.com/shirou/gopsutil/v3 v3.21.6 h1:vU7jrp1Ic/2sHB7w6UNs7MIkn7ebVtTb5D9j45o9VYE=
github.com/shirou/gopsutil/v3 v3.21.6/go.mod h1:JfVbDpIBLVzT8oKbvMg9P3wEIMDDpVn+LwHTKj0ST88=
@@ -1693,12 +1716,14 @@ github.com/shurcooL/githubv4 v0.0.0-20180925043049-51d7b505e2e9/go.mod h1:hAF0iL
github.com/shurcooL/githubv4 v0.0.0-20190718010115-4ba037080260/go.mod h1:hAF0iLZy4td2EX+/8Tw+4nodhlMrwN3HupfaXj3zkGo=
github.com/shurcooL/githubv4 v0.0.0-20191102174205-af46314aec7b/go.mod h1:hAF0iLZy4td2EX+/8Tw+4nodhlMrwN3HupfaXj3zkGo=
github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk=
github.com/shurcooL/go v0.0.0-20200502201357-93f07166e636/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk=
github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ=
github.com/shurcooL/graphql v0.0.0-20180924043259-e4a3a37e6d42/go.mod h1:AuYgA5Kyo4c7HfUmvRGs/6rGlMMV/6B1bVnB9JxJEEg=
github.com/shurcooL/graphql v0.0.0-20181231061246-d48a9a75455f/go.mod h1:AuYgA5Kyo4c7HfUmvRGs/6rGlMMV/6B1bVnB9JxJEEg=
github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/shurcooL/vfsgen v0.0.0-20181202132449-6a9ea43bcacd/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw=
github.com/shurcooL/vfsgen v0.0.0-20200824052919-0d455de96546/go.mod h1:TrYk7fJVaAttu97ZZKrO9UbRa8izdowaMIZcxYMbVaw=
github.com/sirupsen/logrus v1.0.4-0.20170822132746-89742aefa4b2/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
github.com/sirupsen/logrus v1.0.5/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
github.com/sirupsen/logrus v1.0.6/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
@@ -1714,6 +1739,7 @@ github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/assertions v1.0.0/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM=
github.com/smartystreets/assertions v1.1.1 h1:T/YLemO5Yp7KPzS+lVtu+WsHn8yoSwTfItdAd1r3cck=
github.com/smartystreets/assertions v1.1.1/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo=
github.com/smartystreets/go-aws-auth v0.0.0-20180515143844-0c1422d1fdb9/go.mod h1:SnhjPscd9TpLiy1LpzGSKh3bXCfxxXuqd9xmQJy3slM=
github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
@@ -1732,6 +1758,7 @@ github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72 h1:qLC7fQah7D6K1
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
@@ -1739,6 +1766,7 @@ github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
github.com/spf13/cobra v0.0.6/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk=
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
@@ -1752,6 +1780,7 @@ github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/y
github.com/spf13/viper v1.6.1/go.mod h1:t3iDnF5Jlj76alVNuyFBk5oUMCvsrkbvZK0WQdfDi5k=
github.com/spf13/viper v1.6.2/go.mod h1:t3iDnF5Jlj76alVNuyFBk5oUMCvsrkbvZK0WQdfDi5k=
github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns=
github.com/src-d/gcfg v1.4.0/go.mod h1:p/UMsR43ujA89BJY9duynAwIpvqEujIH/jFlfL7jWoI=
github.com/stefanberger/go-pkcs11uri v0.0.0-20201008174630-78d3cae3a980/go.mod h1:AO3tvPzVZ/ayst6UlUKUv6rcPQInYe3IknH3jYhAKu8=
github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8=
@@ -1896,6 +1925,9 @@ go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4=
go.etcd.io/etcd v0.0.0-20181031231232-83304cfc808c/go.mod h1:weASp41xM3dk0YHg1s/W8ecdGP5G4teSTMBPpYAaUgA=
go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg=
go.etcd.io/etcd v0.5.0-alpha.5.0.20200819165624-17cef6e3e9d5/go.mod h1:skWido08r9w6Lq/w70DO5XYIKMu4QFu1+4VsqLQuJy8=
go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=
go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ=
go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
go.mongodb.org/mongo-driver v1.1.1/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
go.mongodb.org/mongo-driver v1.1.2/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
@@ -1958,6 +1990,7 @@ go.uber.org/zap v1.14.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=
go.uber.org/zap v1.14.1/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc=
go.uber.org/zap v1.15.0/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc=
go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ=
go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
go.uber.org/zap v1.19.0 h1:mZQZefskPPCMIBCSEH0v2/iUqqLrYtaeqwD6FUGUnFE=
go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI=
gocloud.dev v0.19.0/go.mod h1:SmKwiR8YwIMMJvQBKLsC3fHNyMwXLw3PMDO+VVteJMI=
@@ -1984,6 +2017,7 @@ golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190617133340-57b3e21c3d56/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=
@@ -2002,6 +2036,7 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201216223049-8b5274cf687f/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
golang.org/x/crypto v0.0.0-20210415154028-4f45737414dc/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
@@ -2038,8 +2073,9 @@ golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHl
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5 h1:2M3HP5CCK1Si9FQhwnzYhXdG6DXeebvUHFpre8QvbyI=
golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug=
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
golang.org/x/mobile v0.0.0-20190806162312-597adff16ade/go.mod h1:AlhUtkH4DA4asiFC5RgK7ZKmauvtkAVcy9L0epCzlWo=
@@ -2050,6 +2086,8 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.1-0.20200828183125-ce943fd02449/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -2110,6 +2148,7 @@ golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwY
golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
@@ -2131,6 +2170,11 @@ golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4Iltr
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210413134643-5e61552d6c78 h1:rPRtHfUb0UKZeZ6GH4K4Nt4YRbE9V1u+QZX5upZXqJQ=
golang.org/x/oauth2 v0.0.0-20210413134643-5e61552d6c78/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -2253,21 +2297,27 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201202213521-69691e467435/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201214210602-f9fddec55a1e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210216224549-f992740a1bac/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210309074719-68d13333faf2/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210316164454-77fc1eacc6aa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -2414,11 +2464,15 @@ golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82u
golang.org/x/tools v0.0.0-20200916195026-c9a70fc28ce3/go.mod h1:z6u4i615ZeAfBE4XtMziQW1fSVJXACjjbWkB/mvPzlU=
golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/tools v0.1.1 h1:wGiQel/hW0NnEkJUk8lbzkX2gFJU6PFxf1v5OlCfuOs=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.5 h1:ouewzE6p+/VEB31YYnTbEJdi8pFqKp4P4n85vwo3DHA=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -2464,8 +2518,12 @@ google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0M
google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg=
google.golang.org/api v0.36.0 h1:l2Nfbl2GPXdWorv+dT2XfinX2jOOw4zv1VhLstx+6rE=
google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE=
google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8=
google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU=
google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94=
google.golang.org/api v0.44.0 h1:URs6qR1lAxDsqWITsQXI4ZkGiYJ5dHtRNiCpfs2OeKA=
google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
@@ -2539,9 +2597,17 @@ google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6D
google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210114201628-6edceaf6022f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210416161957-9910b6c460de h1:+nG/xknR+Gc5ByHOtK1dT0Pl3LYo8NLR+Jz3XeBeGEg=
google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A=
google.golang.org/genproto v0.0.0-20210416161957-9910b6c460de/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A=
google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c h1:wtujag7C+4D6KMoulW9YauvK2lgdvCMS260jsqqBXr0=
google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
google.golang.org/grpc v1.15.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=
@@ -2569,10 +2635,12 @@ google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM
google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
google.golang.org/grpc v1.40.0 h1:AGJ0Ih4mHjSeibYkFGh1dD9KJ/eOtZ93I6hoHhukQ5Q=
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
@@ -2615,8 +2683,9 @@ gopkg.in/ini.v1 v1.46.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ini.v1 v1.52.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ini.v1 v1.56.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ini.v1 v1.57.0 h1:9unxIsFcTt4I55uWluz+UmL95q4kdJ0buvQ1ZIqVQww=
gopkg.in/ini.v1 v1.57.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU=
gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/jcmturner/aescts.v1 v1.0.1/go.mod h1:nsR8qBOg+OucoIW+WMhB3GspUQXq9XorLnQb9XtvcOo=
gopkg.in/jcmturner/dnsutils.v1 v1.0.1/go.mod h1:m3v+5svpVOhtFAP/wSz+yzh4Mc0Fg7eRhxkJMWSIz9Q=
gopkg.in/jcmturner/goidentity.v3 v3.0.0/go.mod h1:oG2kH0IvSYNIu80dVAyu/yoefjq1mNfM5bm88whjWx4=
@@ -2706,6 +2775,7 @@ k8s.io/gengo v0.0.0-20200205140755-e0e292d8aa12/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8
k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
k8s.io/gengo v0.0.0-20200428234225-8167cfdcfc14/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
k8s.io/gengo v0.0.0-20201113003025-83324d819ded/go.mod h1:FiNAH4ZV3gBg2Kwh89tzAEV2be7d5xI0vBa/VySYy3E=
k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8=
k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
@@ -2786,6 +2856,7 @@ sigs.k8s.io/boskos v0.0.0-20200729174948-794df80db9c9/go.mod h1:ZO5RV+VxJS9mb6Dv
sigs.k8s.io/controller-runtime v0.7.0 h1:bU20IBBEPccWz5+zXpLnpVsgBYxqclaHu1pVDl/gEt8=
sigs.k8s.io/controller-runtime v0.7.0/go.mod h1:pJ3YBrJiAqMAZKi6UVGuE98ZrroV1p+pIhoHsMm9wdU=
sigs.k8s.io/kustomize v2.0.3+incompatible/go.mod h1:MkjgH3RdOWrievjo6c9T245dYlB5QeXV4WCbnt/PEpU=
sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e h1:4Z09Hglb792X0kfOBBJUPFEyvVfQWrYT/l8h5EKA6JQ=
sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI=
sigs.k8s.io/structured-merge-diff/v2 v2.0.1/go.mod h1:Wb7vfKAodbKgf6tn1Kl0VvGj7mRH6DGaRcixXEJXTsE=
sigs.k8s.io/structured-merge-diff/v3 v3.0.1-0.20200706213357-43c19bbb7fba/go.mod h1:V06abazjHneE37ZdSY/UUwPVgcJMKI/jU5XGUjgIKoc=


+ 41
- 39
server/openai-server/api/v1/trainJob.proto View File

@@ -43,44 +43,44 @@ service TrainJobService {
get: "/v1/trainmanage/trainjob"
};
};
// 创建训练任务模板
rpc CreateJobTemplate (TrainJobTemplateRequest) returns (TrainJobTemplateReply) {
option (google.api.http) = {
post: "/v1/trainmanage/trainjobtemplate"
body: "*"
};
};
// 编辑训练任务模板
rpc UpdateJobTemplate (TrainJobTemplate) returns (TrainJobTemplateReply) {
option (google.api.http) = {
put: "/v1/trainmanage/trainjobtemplate/{id}"
body: "*"
};
};
// 删除训练任务模板
rpc DeleteTemplate (DeleteJobTemplateRequest) returns (DeleteJobTemplateReply) {
option (google.api.http) = {
delete: "/v1/trainmanage/trainjobtemplate"
};
};
// 获取训练任务模板详情
rpc GetJobTemplate (GetJobTemplateRequest) returns (GetJobTemplateReply) {
option (google.api.http) = {
get: "/v1/trainmanage/trainjobtemplate/{id}"
};
};
// 获取训练任务列表
rpc TrainJobTemplateList (TrainJobTemplateListRequest) returns (TrainJobTemplateListReply) {
option (google.api.http) = {
get: "/v1/trainmanage/trainjobtemplate"
};
};
// 复制训练任务模板
rpc CopyJobTemplate (CopyJobTemplateRequest) returns (CopyJobTemplateReply) {
option (google.api.http) = {
post: "/v1/trainmanage/trainjobtemplate/{id}/copy"
};
};
// // 创建训练任务模板
// rpc CreateJobTemplate (TrainJobTemplateRequest) returns (TrainJobTemplateReply) {
// option (google.api.http) = {
// post: "/v1/trainmanage/trainjobtemplate"
// body: "*"
// };
// };
// // 编辑训练任务模板
// rpc UpdateJobTemplate (TrainJobTemplate) returns (TrainJobTemplateReply) {
// option (google.api.http) = {
// put: "/v1/trainmanage/trainjobtemplate/{id}"
// body: "*"
// };
// };
// // 删除训练任务模板
// rpc DeleteTemplate (DeleteJobTemplateRequest) returns (DeleteJobTemplateReply) {
// option (google.api.http) = {
// delete: "/v1/trainmanage/trainjobtemplate"
// };
// };
// // 获取训练任务模板详情
// rpc GetJobTemplate (GetJobTemplateRequest) returns (GetJobTemplateReply) {
// option (google.api.http) = {
// get: "/v1/trainmanage/trainjobtemplate/{id}"
// };
// };
// // 获取训练任务列表
// rpc TrainJobTemplateList (TrainJobTemplateListRequest) returns (TrainJobTemplateListReply) {
// option (google.api.http) = {
// get: "/v1/trainmanage/trainjobtemplate"
// };
// };
// // 复制训练任务模板
// rpc CopyJobTemplate (CopyJobTemplateRequest) returns (CopyJobTemplateReply) {
// option (google.api.http) = {
// post: "/v1/trainmanage/trainjobtemplate/{id}/copy"
// };
// };
// 获取训练任务事件列表
rpc GetJobEventList (JobEventListRequest) returns (JobEventListReply) {
option (google.api.http) = {
@@ -179,7 +179,7 @@ message TrainJobTemplateRequest {
bool isDistributed = 9;
//job子任务及其配置信息,必填
repeated Config config = 10[(validate.rules).repeated.min_items = 1];
string resourcePool = 11[(validate.rules).string = {min_len: 1}];
string resourcePool = 11[(validate.rules).string = {min_len:1}];
}

message TrainJobTemplateReply {
@@ -335,6 +335,8 @@ message TrainJob{
//启动时间
int64 startedAt = 22;
string imageUrl = 23;
//资源池
string resourcePool=24;
}

message TrainJobTemplate{


+ 0
- 35
third-party/cambricon-k8s-device-plugin/.drone.yml View File

@@ -1,35 +0,0 @@
kind: pipeline
name: pipeline-octopus-cambricon-k8s-device-plugin
platform:
os: linux
arch: amd64
steps:

- name: containerize
image: docker:18.09.7
volumes:
# - name: dockerlib
# path: /var/lib/docker
- name: dockersock
path: /var/run/docker.sock
- name: drone
path: /etc/drone
commands:
- export DRONE_DOCKER_LOCAL_FILE="./device-plugin/Dockerfile"
- . /etc/drone/env.sh
- . /etc/drone/docker_build.sh

trigger:
event:
- tag

volumes:
- name: dockerlib
host:
path: /var/lib/docker
- name: dockersock
host:
path: /var/run/docker.sock
- name: drone
host:
path: /etc/drone

+ 0
- 7
third-party/cambricon-k8s-device-plugin/.github/issue_template.md View File

@@ -1,7 +0,0 @@
_The template below is mostly useful for bug reports and support questions. Feel free to remove anything which doesn't apply to you and add more information where it makes sense._

### 1. Issue or feature description

### 2. Steps to reproduce the issue

### 3. Information to [attach](https://help.github.com/articles/file-attachments-on-issues-and-pull-requests/) (optional if deemed irrelevant)

+ 0
- 50
third-party/cambricon-k8s-device-plugin/.github/workflows/ci.yaml View File

@@ -1,50 +0,0 @@
# Copyright 2020 Cambricon, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

name: Cambricon Device Plugin CI
on:
pull_request:
branches:
- master
jobs:
lint:
name: Lint
runs-on: ubuntu-18.04
steps:
- uses: actions/checkout@v2
- uses: golangci/golangci-lint-action@v2
with:
version: v1.29
working-directory: device-plugin
args: -v

build:
name: Build
runs-on: ubuntu-18.04
steps:
- uses: actions/checkout@v2
- uses: actions/setup-go@v1
with:
go-version: "1.13.1"
- run: make -C device-plugin build

test:
name: Test
runs-on: ubuntu-18.04
steps:
- uses: actions/checkout@v2
- uses: actions/setup-go@v1
with:
go-version: "1.13.1"
- run: make -C device-plugin test

+ 0
- 41
third-party/cambricon-k8s-device-plugin/.gitlab-ci.yml View File

@@ -1,41 +0,0 @@
# Copyright 2020 Cambricon, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

image: 10.110.210.252:5001/cambricon/buildpack:20200424
variables:
GOPROXY: http://10.110.210.252:8080

.only-mr-refs: &only-mr-refs
refs:
- merge_requests
- master

stages:
- lint
- build
- test

include:
- local: device-plugin/.gitlab-ci.yml

run-shellcheck-lint:
stage: lint
image: 10.110.210.252:5001/cambricon/shellcheck-alpine:v0.7.0
script:
- find . -name '*.sh' -exec shellcheck {} +
only:
changes:
- .gitlab-ci.yml
- "**/*.sh"
<<: *only-mr-refs

+ 0
- 25
third-party/cambricon-k8s-device-plugin/.golangci.yml View File

@@ -1,25 +0,0 @@
# Copyright 2020 Cambricon, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

linters:
enable:
- govet
- gofmt
- goimports
- golint
disable-all: true
issues:
exclude-use-default: false
exclude:
- (comment on exported (method|function|type|const)|should have( a package)? comment|comment should be of the form)

+ 0
- 201
third-party/cambricon-k8s-device-plugin/LICENSE View File

@@ -1,201 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/

TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

1. Definitions.

"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.

"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.

"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.

"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.

"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.

"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.

"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).

"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.

"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."

"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.

2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.

3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.

4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:

(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and

(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and

(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and

(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.

You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.

5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.

6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.

7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.

8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.

9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.

END OF TERMS AND CONDITIONS

APPENDIX: How to apply the Apache License to your work.

To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.

Copyright [yyyy] [name of copyright owner]

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

+ 0
- 7
third-party/cambricon-k8s-device-plugin/README.md View File

@@ -1,7 +0,0 @@
# Cambricon K8s Device Plugin

See [device-plugin](device-plugin) directory.

## License

[Apache-2.0](LICENSE)

+ 0
- 5
third-party/cambricon-k8s-device-plugin/device-plugin/.gitignore View File

@@ -1,5 +0,0 @@
libcndev.so
k8s-device-plugin
mock_test
image
*.tar*

+ 0
- 50
third-party/cambricon-k8s-device-plugin/device-plugin/.gitlab-ci.yml View File

@@ -1,50 +0,0 @@
# Copyright 2020 Cambricon, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

.run-device-plugin-mr:
only:
changes:
- .gitlab-ci.yml
- .golangci.yml
- device-plugin/**/*
refs:
- merge_requests

run-device-plugin-lint:
extends: .run-device-plugin-mr
stage: lint
script:
- make -C device-plugin lint

run-device-plugin-build:
extends: .run-device-plugin-mr
stage: build
script:
- make -C device-plugin build

run-device-plugin-test:
extends: .run-device-plugin-mr
stage: test
script:
- make -C device-plugin test

run-device-plugin-integration:
extends: .run-device-plugin-mr
variables:
APT_PROXY: http://10.110.210.252:3142
stage: test
tags:
- shell47
script:
- make -C device-plugin integration-test

+ 0
- 14
third-party/cambricon-k8s-device-plugin/device-plugin/CHANGELOG.md View File

@@ -1,14 +0,0 @@
# Changelog

## v1.0.0

+ Implement basic function.

## v1.1.0

+ Implement SR-IOV and env-share features.

## v1.1.1

+ Fix SR-IOV vf device name same as env-share fake device name.
+ Support building image on arm64 machines.

+ 0
- 31
third-party/cambricon-k8s-device-plugin/device-plugin/Dockerfile View File

@@ -1,31 +0,0 @@
# Copyright 2020 Cambricon, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

ARG BUILDPLATFORM=linux/amd64
FROM --platform=$BUILDPLATFORM golang:1.13 as build
ARG APT_PROXY
ARG GOPROXY=https://goproxy.cn
ARG TARGETPLATFORM
RUN set -ex && export http_proxy=$APT_PROXY && \
apt-get update && \
apt-get install -y build-essential gcc-aarch64-linux-gnu ca-certificates make
WORKDIR /work/
COPY ./device-plugin .
RUN make build

FROM ubuntu:18.04
ARG TARGETPLATFORM=linux/amd64
COPY --from=build /work/k8s-device-plugin /usr/bin/
COPY ./device-plugin/libs/$TARGETPLATFORM/libcndev.so /usr/lib
CMD ["/usr/bin/k8s-device-plugin"]

+ 0
- 58
third-party/cambricon-k8s-device-plugin/device-plugin/Makefile View File

@@ -1,58 +0,0 @@
# Copyright 2020 Cambricon, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

TARGETPLATFORM ?= linux/amd64
export GOOS := $(word 1, $(subst /, ,$(TARGETPLATFORM)))
export GOARCH := $(word 2, $(subst /, ,$(TARGETPLATFORM)))
export CGO_ENABLED := 1
ifeq ($(GOARCH), arm64)
export CC=aarch64-linux-gnu-gcc
endif

lint:
golangci-lint run -v

build:
go build -trimpath -ldflags="-s -w" -o k8s-device-plugin .

test: go-test mock-test

go-test: pkg/cndev/mock/libcndev.so
LD_LIBRARY_PATH=$(CURDIR)/pkg/cndev/mock \
MOCK_JSON=$(CURDIR)/test/mockmlu270.json \
go test -v ./...

integration-test: pkg/cndev/mock/libcndev.so
./test/device-plugin-integration-test.sh

LIBCNDEV_MOCK_DEPS := $(wildcard pkg/cndev/mock/*.h pkg/cndev/mock/*.c pkg/cndev/include/*)
pkg/cndev/mock/libcndev.so: $(LIBCNDEV_MOCK_DEPS)
$(CC) -fPIC -shared pkg/cndev/mock/cJSON.c pkg/cndev/mock/cndev.c -lm -o $@

pkg/cndev/mock/mock_test: pkg/cndev/mock/main.c pkg/cndev/mock/libcndev.so
$(CC) pkg/cndev/mock/main.c \
-Wl,-rpath='$$ORIGIN' -Lpkg/cndev/mock -lcndev \
-o pkg/cndev/mock/mock_test

mock-test: pkg/cndev/mock/mock_test
MOCK_JSON=$(CURDIR)/test/mockmlu270.json ./pkg/cndev/mock/mock_test

addlicense:
# install with `go get github.com/google/addlicense`
addlicense -c 'Cambricon, Inc.' -l apache -v .

clean:
rm -f pkg/cndev/mock/libcndev.so
rm -f pkg/cndev/mock/mock_test
rm -f k8s-device-plugin

+ 0
- 120
third-party/cambricon-k8s-device-plugin/device-plugin/README.md View File

@@ -1,120 +0,0 @@
# Cambricon Device Plugin for Kubernetes

## 说明
无官方docker镜像,原项目地址https://github.com/Cambricon/cambricon-k8s-device-plugin,修改了编译脚本

## About Cambricon Device Plugin

The Cambricon device plugin for Kubernetes is a Daemonset which allows you to automatically:

- Report the quantity of MLU on each nodes of your cluster.
- Monitor the health status of MLUs.
- Be capable to run containers with MLU enabled.

This repository contains Cambricon's official implementation of the Kubernetes device plugin.

## Prerequisites

The prerequisites for running the Cambricon device plugin:

- MLU100, MLU270, x5k, MLU220 devices
- MLU100 driver > 3.5; MLU270 driver >2.2.0; MLU220 driver > 4.1.1
- libcndev.so >= V1.8.0
- Kubernetes >= v1.11.2

## Quick Start

### Preparing your MLU Nodes

It assumes that the Cambricon drivers and neuware are installed on your MLU Nodes.

### Download and build

```shell
git clone https://github.com/Cambricon/cambricon-k8s-device-plugin.git
cd cambricon-k8s-device-plugin/device-plugin
```

Set the following environment variables if you need.

| env | description |
| --------- | ----------------------------------------------------------------------------- |
| APT_PROXY | apt proxy server |
| GOPROXY | golang proxy server |
| ARCH | target platform architecture, amd64 or arm64, amd64 by default |
| LIBCNDEV | absolute path of the libcndev.so binary, neuware installation path by default |

If you want to cross build, make sure docker version >= 19.03.

For amd64:

```shell
./build_image.sh
```

For arm64:

```shell
export ARCH=arm64
./build_image.sh
```

Please make sure Cambricon neuware is installed in your compiling environment.
It uses **libcndev.so** binary on your compiling machine and generates docker image in folder `./image`.

### Enabling MLU Support in Kubernetes

1. Push the docker image to the docker repo of your cluster or load the docker image on all your MLU nodes by:

```shell
docker load -i image/cambricon-k8s-device-plugin-amd64.tar
```

2. Enable MLU support in your cluster by deploying the daemonset in [examples](examples) folder:

Set the mode arg in the yaml file to change mode

```yaml
args:
- -mode
- default # switch mode here
env:
# change this if env-share mode or sriov mode is enabled.
- name: VIRTUALIZATION_NUM
value: "0"
```

supported features:

- default: default mode
- sriov: supports SR-IOV. Set `VIRTUALIZATION_NUM` as number of VFs on host.
- env-share: a whole card can be allocated into multiple containers. A container should use only one card in this mode.
Set `VIRTUALIZATION_NUM` as maximum number of containers one MLU can be allocated into.

```shell
kubectl create -f cambricon-device-plugin-daemonset.yml
```

(Optional) If you do not want the daemonset way of deployment, edit the static pod template in examples folder and
put the file into your configured static pod folder (`/etc/kubernetes/manifests` by default).

### Running MLU Jobs

Cambricon MLUs can now be consumed via container level resource requirements using the resource name `cambricon.com/mlu`:

```yaml
apiVersion: v1
kind: Pod
metadata:
name: pod1
spec:
restartPolicy: OnFailure
containers:
- image: ubuntu:16.04
name: pod1-ctr
command: ["sleep"]
args: ["100000"]
resources:
limits:
cambricon.com/mlu: 1
```

+ 0
- 93
third-party/cambricon-k8s-device-plugin/device-plugin/build_image.sh View File

@@ -1,93 +0,0 @@
#!/bin/bash
# Copyright 2020 Cambricon, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

curpath=$(dirname "$0")
cd "$curpath" || exit 1

: "${TAG:=v1.1.1}"
: "${ARCH:=amd64}"
: "${LIBCNDEV:=/usr/local/neuware/lib64/libcndev.so}"

echo "Build environ (Can be overridden):"
echo "TAG = $TAG"
echo "ARCH = $ARCH"
echo "LIBCNDEV = $LIBCNDEV"
echo "APT_PROXY = $APT_PROXY"
echo "GOPROXY = $GOPROXY"

case $(uname -m) in
x86_64)
build_arch=amd64
;;
aarch64*)
build_arch=arm64
;;
armv8*)
build_arch=arm64
esac

rm -rf "$curpath/image"
mkdir -p "$curpath/image"

# Cambricon neuware installation path
if [[ ! -f "$LIBCNDEV" ]]; then
echo "Can't find libcndev.so at $LIBCNDEV."
echo "Please install Cambricon neuware, or set LIBCNDEV environ to path of libcndev.so"
exit 1
fi

case $ARCH in
amd64)
file_arch=x86-64
;;
arm64)
file_arch=aarch64
;;
*)
echo "Unknown arch $ARCH"
exit 1
esac

if ! file "$LIBCNDEV" --dereference | grep -q "$file_arch"; then
echo "$LIBCNDEV is not for $ARCH"
exit 1
fi

cp "$LIBCNDEV" "$curpath/libs/linux/$ARCH/"

echo "Building Cambricon device plugin docker image."

# Legacy build for docker 18.06.
# Remove this when docker is upgraded to 19.03 in all environ.
[[ "$ARCH" == "$build_arch" ]] && docker build -t "cambricon-k8s-device-plugin:$TAG" \
--build-arg "GOPROXY=$GOPROXY" --build-arg "APT_PROXY=$APT_PROXY" \
--build-arg "BUILDPLATFORM=linux/$ARCH" \
--build-arg "TARGETPLATFORM=linux/$ARCH" .

[[ "$ARCH" == "$build_arch" ]] && docker save -o "image/cambricon-k8s-device-plugin-$ARCH.tar" \
"cambricon-k8s-device-plugin:$TAG"

if [[ "$ARCH" != "$build_arch" && "$(docker version -f '{{ge .Client.Version "19.03"}}')" != "true" ]]; then
echo "Needs docker 19.03 and above"
exit 1
fi

[[ "$ARCH" != "$build_arch" ]] && DOCKER_CLI_EXPERIMENTAL=enabled docker buildx build \
--platform="linux/$ARCH" -t "cambricon-k8s-device-plugin:$TAG" \
--build-arg "GOPROXY=$GOPROXY" --build-arg "APT_PROXY=$APT_PROXY" \
--output type=docker,dest="./image/cambricon-k8s-device-plugin-$ARCH.tar" .

echo "Image is saved at ./image/cambricon-k8s-device-plugin-$ARCH.tar"
rm -f "$curpath/libs/linux/$ARCH/libcndev.so"

+ 0
- 198
third-party/cambricon-k8s-device-plugin/device-plugin/cambricon.go View File

@@ -1,198 +0,0 @@
// Copyright 2020 Cambricon, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package main

import (
"fmt"
"log"
"os"
"path/filepath"
"strconv"
"time"

"github.com/cambricon/cambricon-k8s-device-plugin/device-plugin/pkg/cndev"
"golang.org/x/net/context"
pluginapi "k8s.io/kubelet/pkg/apis/deviceplugin/v1beta1"
)

const (
mlu100MonitorDeviceName = "/dev/cnmon_dev"
mlu100CodecDeviceName = "/dev/cncodec_dev"
mlu100DeviceName = "/dev/cambricon_c10Dev"

mluMonitorDeviceName = "/dev/cambricon_ctl"
mluMsgqDeviceName = "/dev/cambr-msgq"
mluRPCDeviceName = "/dev/cambr-rpc"
mluCmsgDeviceName = "/dev/cmsg_ctrl"
mluDeviceName = "/dev/cambricon_dev"
mluCommuDeviceName = "/dev/commu"

VirtualizationNum = "VIRTUALIZATION_NUM"
)

type deviceList struct {
hasCnmonDev bool
hasCodecDev bool
hasC10Dev bool

hasCtrlDev bool
hasMsgqDev bool
hasRPCDev bool
hasCmsgDev bool
hasCommuDev bool
}

func newDeviceList() *deviceList {
return &deviceList{
hasCnmonDev: hostDeviceExistsWithPrefix(mlu100MonitorDeviceName),
hasCodecDev: hostDeviceExistsWithPrefix(mlu100CodecDeviceName),
hasC10Dev: hostDeviceExistsWithPrefix(mlu100DeviceName),
hasCtrlDev: hostDeviceExistsWithPrefix(mluMonitorDeviceName),
hasMsgqDev: hostDeviceExistsWithPrefix(mluMsgqDeviceName),
hasRPCDev: hostDeviceExistsWithPrefix(mluRPCDeviceName),
hasCmsgDev: hostDeviceExistsWithPrefix(mluCmsgDeviceName),
hasCommuDev: hostDeviceExistsWithPrefix(mluCommuDeviceName),
}
}

func hostDeviceExistsWithPrefix(prefix string) bool {
matches, err := filepath.Glob(prefix + "*")
if err != nil {
log.Printf("failed to know if host device with prefix exists, err: %v \n", err)
return false
}
return len(matches) > 0
}

func check(err error) {
if err != nil {
log.Panicln("Fatal:", err)
}
}

func generateFakeDevs(origin *cndev.Device, num int, sriovEnabled bool) ([]*pluginapi.Device, []*cndev.Device) {
var devs []*pluginapi.Device
var devsInfo []*cndev.Device
var uuid string
path := origin.Path
for i := 0; i < num; i++ {
if sriovEnabled {
path = fmt.Sprintf("%svf%d", origin.Path, i+1)
uuid = fmt.Sprintf("%s--fake--%d", origin.UUID, i+1)
} else {
uuid = fmt.Sprintf("%s-_-%d", origin.UUID, i+1)
}
devsInfo = append(devsInfo, &cndev.Device{
Slot: origin.Slot,
UUID: uuid,
Path: path,
})
devs = append(devs, &pluginapi.Device{
ID: uuid,
Health: pluginapi.Healthy,
})
}
return devs, devsInfo
}

func getDevices(feature int) ([]*pluginapi.Device, []*cndev.Device) {
var devs []*pluginapi.Device
var devsInfo []*cndev.Device

num, err := cndev.GetDeviceCount()
check(err)

fakeNum := 0
if feature == sriovShare || feature == envShare {
fakeNum, err = getVirtualizationNum()
check(err)
}

for i := uint(0); i < num; i++ {
d, err := cndev.NewDeviceLite(i, feature == sriovShare)
check(err)
switch feature {
case envShare:
devices, infos := generateFakeDevs(d, fakeNum, false)
devs = append(devs, devices...)
devsInfo = append(devsInfo, infos...)
case sriovShare:
err = d.EnableSriov(fakeNum)
check(err)
devices, infos := generateFakeDevs(d, fakeNum, true)
devs = append(devs, devices...)
devsInfo = append(devsInfo, infos...)
default:
devsInfo = append(devsInfo, d)
devs = append(devs, &pluginapi.Device{
ID: d.UUID,
Health: pluginapi.Healthy,
})
}
}
return devs, devsInfo
}

func deviceExists(devs []*pluginapi.Device, id string) bool {
for _, d := range devs {
if d.ID == id {
return true
}
}
return false
}

func watchUnhealthy(ctx context.Context, devs []*pluginapi.Device, devsInfo []*cndev.Device, unhealthy chan<- *pluginapi.Device) {
healthCheck := true
for {
select {
case <-ctx.Done():
return
default:
}
if healthCheck {
for _, dm := range devsInfo {
ret, err := dm.GetGeviceHealthState(1)
if err != nil {
healthCheck = false
log.Printf("Failed to get Device %s healthy status, stop the healthy check", dm.UUID)
}
if ret == 0 {
for _, d := range devs {
if d.ID == dm.UUID {
log.Printf("Unhealthy device :%s\n", d.ID)
unhealthy <- d
break
}
}
}
}
}
//Sleep 1 second between two health checks
time.Sleep(time.Second)
}
}

func getVirtualizationNum() (int, error) {
s := os.Getenv(VirtualizationNum)
num, err := strconv.Atoi(s)
if err != nil {
return 0, err
}
if num < 1 {
return 0, fmt.Errorf("num %d should be larger than 0", num)
}
return num, nil
}

+ 0
- 98
third-party/cambricon-k8s-device-plugin/device-plugin/cambricon_test.go View File

@@ -1,98 +0,0 @@
// Copyright 2020 Cambricon, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package main

import (
"fmt"
"log"
"os"
"testing"

"github.com/cambricon/cambricon-k8s-device-plugin/device-plugin/pkg/cndev"
"github.com/stretchr/testify/assert"
)

func TestMain(m *testing.M) {
err := cndev.Init()
if err != nil {
log.Fatal(err)
}
ret := m.Run()
if ret != 0 {
os.Exit(ret)
}
err = cndev.Release()
if err != nil {
log.Fatal(err)
}
}

func TestGetDevices(t *testing.T) {

devs, devsInfo := getDevices(0)
assert.Equal(t, 8, len(devs))
assert.Equal(t, fmt.Sprintf("MLU-%x", 2701114), devs[3].ID)
assert.Equal(t, 8, len(devsInfo))
assert.Equal(t, fmt.Sprintf("MLU-%x", 2701114), devsInfo[3].UUID)
assert.Equal(t, uint(3), devsInfo[3].Slot)
assert.Equal(t, "/dev/cambricon_dev3", devsInfo[3].Path)

err := os.Setenv(VirtualizationNum, "2")
assert.NoError(t, err)
devs, devsInfo = getDevices(envShare)
assert.Equal(t, 16, len(devs))
assert.Equal(t, fmt.Sprintf("MLU-%x-_-2", 2701112), devs[3].ID)
assert.Equal(t, 16, len(devsInfo))
assert.Equal(t, fmt.Sprintf("MLU-%x-_-2", 2701112), devsInfo[3].UUID)
assert.Equal(t, uint(1), devsInfo[3].Slot)
assert.Equal(t, "/dev/cambricon_dev1", devsInfo[3].Path)
err = os.Unsetenv(VirtualizationNum)
assert.NoError(t, err)
}

func TestGenerateFakeDevs(t *testing.T) {
d := &cndev.Device{
Slot: 1,
UUID: fmt.Sprintf("MLU-%x", 2701112),
Path: "/dev/cambricon_dev1",
}
devs, devsInfo := generateFakeDevs(d, 4, true)
assert.Equal(t, 4, len(devs))
assert.Equal(t, fmt.Sprintf("MLU-%x--fake--4", 2701112), devs[3].ID)
assert.Equal(t, 4, len(devsInfo))
assert.Equal(t, fmt.Sprintf("MLU-%x--fake--4", 2701112), devsInfo[3].UUID)
assert.Equal(t, "/dev/cambricon_dev1vf4", devsInfo[3].Path)
assert.Equal(t, uint(1), devsInfo[3].Slot)
devs, devsInfo = generateFakeDevs(d, 2, false)
assert.Equal(t, 2, len(devs))
assert.Equal(t, fmt.Sprintf("MLU-%x-_-2", 2701112), devs[1].ID)
assert.Equal(t, 2, len(devsInfo))
assert.Equal(t, fmt.Sprintf("MLU-%x-_-2", 2701112), devsInfo[1].UUID)
assert.Equal(t, "/dev/cambricon_dev1", devsInfo[1].Path)
assert.Equal(t, uint(1), devsInfo[1].Slot)
}

func TestHostDeviceExistsWithPrefix(t *testing.T) {
filename := "/tmp/cambricon_dev0"
prefix := "/tmp/cambricon_dev"
_, err := os.Create(filename)
assert.NoError(t, err)
res := hostDeviceExistsWithPrefix(prefix)
assert.Equal(t, res, true)
err = os.Remove(filename)
assert.NoError(t, err)
res = hostDeviceExistsWithPrefix(prefix)
assert.Equal(t, res, false)
}

+ 0
- 34
third-party/cambricon-k8s-device-plugin/device-plugin/create_release_package.sh View File

@@ -1,34 +0,0 @@
#!/bin/bash
# Copyright 2020 Cambricon, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

set -e

usage() {
echo "Usage:"
echo "$0 TAG"
exit 0
}

tag=$1
[[ $tag == "" ]] && usage

rm -rf image
mkdir -p image
TAG=$tag ./build_image.sh
sed "s|v[0-9]\.[0-9].[0-9]|$tag|g" examples/cambricon-device-plugin-daemonset.yaml > image/cambricon-device-plugin-daemonset.yaml
sed "s|v[0-9]\.[0-9].[0-9]|$tag|g" examples/cambricon-device-plugin-static-pod.yaml > image/cambricon-device-plugin-static-pod.yaml
cp examples/pod.yaml image/

tar -zcvf cambricon_k8s_device_plugin_packages_"$tag".tar.gz image

+ 0
- 69
third-party/cambricon-k8s-device-plugin/device-plugin/examples/cambricon-device-plugin-daemonset.yaml View File

@@ -1,69 +0,0 @@
# Copyright 2020 Cambricon, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

apiVersion: apps/v1
kind: DaemonSet
metadata:
name: cambricon-device-plugin-daemonset
namespace: kube-system
spec:
selector:
matchLabels:
name: cambricon-device-plugin-ds
template:
metadata:
# Mark this pod as a critical add-on; when enabled, the critical add-on scheduler
# reserves resources for critical add-on pods so that they can be rescheduled after
# a failure. This annotation works in tandem with the toleration below.
annotations:
scheduler.alpha.kubernetes.io/critical-pod: ""
labels:
name: cambricon-device-plugin-ds
spec:
tolerations:
# Allow this pod to be rescheduled while the node is in "critical add-ons only" mode.
# This, along with the annotation above marks this pod as a critical add-on.
- key: CriticalAddonsOnly
operator: Exists
- key: cambricon.com/mlu
operator: Exists
effect: NoSchedule
containers:
- image: cambricon-k8s-device-plugin:v1.1.1
name: cambricon-device-plugin-ctr
command:
- /usr/bin/k8s-device-plugin
args:
- -mode
- default # switch mode here
env:
# change this if env-share mode or sriov mode is enabled.
- name: VIRTUALIZATION_NUM
value: "0"
securityContext:
privileged: true
volumeMounts:
- name: device-plugin
mountPath: /var/lib/kubelet/device-plugins
# mount sys if sriov mode is enabled
- name: sys
mountPath: /sys
volumes:
- name: device-plugin
hostPath:
path: /var/lib/kubelet/device-plugins
# mount sys if sriov mode is enabled
- name: sys
hostPath:
path: /sys

+ 0
- 48
third-party/cambricon-k8s-device-plugin/device-plugin/examples/cambricon-device-plugin-static-pod.yaml View File

@@ -1,48 +0,0 @@
# Copyright 2020 Cambricon, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

apiVersion: v1
kind: Pod
metadata:
name: cambricon-device-plugin-static-pod
namespace: kube-system
spec:
containers:
- image: cambricon-k8s-device-plugin:v1.1.1
name: cambricon-device-plugin-ctr
command:
- /usr/bin/k8s-device-plugin
args:
- -mode
- default # switch mode here
env:
# change this if env-share mode or sriov mode is enabled.
- name: VIRTUALIZATION_NUM
value: "0"
securityContext:
privileged: true
volumeMounts:
- name: device-plugin
mountPath: /var/lib/kubelet/device-plugins
# mount sys if sriov mode is enabled
- name: sys
mountPath: /sys
volumes:
- name: device-plugin
hostPath:
path: /var/lib/kubelet/device-plugins
# mount sys if sriov mode is enabled
- name: sys
hostPath:
path: /sys

+ 0
- 38
third-party/cambricon-k8s-device-plugin/device-plugin/examples/deployment.yaml View File

@@ -1,38 +0,0 @@
# Copyright 2020 Cambricon, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

apiVersion: apps/v1
kind: Deployment
metadata:
name: binpack-n1
labels:
app: binpack-n1
spec:
replicas: 1
selector: # define how the deployment finds the pods it mangages
matchLabels:
app: binpack-1
template: # define the pods specifications
metadata:
labels:
app: binpack-1
spec:
containers:
- name: binpack-1
image: ubuntu:18.04
command: ["sleep"]
args: ["100000"]
resources:
limits:
cambricon.com/mlu: 1

+ 0
- 11
third-party/cambricon-k8s-device-plugin/device-plugin/go.mod View File

@@ -1,11 +0,0 @@
module github.com/cambricon/cambricon-k8s-device-plugin/device-plugin

go 1.13

require (
github.com/fsnotify/fsnotify v1.4.9
github.com/stretchr/testify v1.4.0
golang.org/x/net v0.0.0-20200822124328-c89045814202
google.golang.org/grpc v1.31.1
k8s.io/kubelet v0.19.0
)

+ 0
- 373
third-party/cambricon-k8s-device-plugin/device-plugin/go.sum View File

@@ -1,373 +0,0 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
cloud.google.com/go v0.51.0/go.mod h1:hWtGJ6gnXH+KgDv+V0zFGDvpi07n3z8ZNj3T1RW0Gcw=
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI=
github.com/Azure/go-autorest/autorest v0.9.6/go.mod h1:/FALq9T/kS7b5J5qsQ+RSTUdAmGFqi0vUdVNNx8q630=
github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0=
github.com/Azure/go-autorest/autorest/adal v0.8.2/go.mod h1:ZjhuQClTqx435SRJ2iMlOxPYt3d2C/T/7TiQCVZSn3Q=
github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA=
github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g=
github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM=
github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc=
github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/blang/semver v3.5.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0=
github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg=
github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc=
github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls=
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg=
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs=
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
github.com/moby/term v0.0.0-20200312100748-672ec06f55cd/go.mod h1:DdlQx2hp0Ss5/fLikoLlEeIYiATotOjgB//nb973jeo=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200822124328-c89045814202 h1:VvcQYSHwXgi7W+TpUR6A9g6Up98WAHf3f/ulnJ62IyA=
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4 h1:5/PjkGUjvEU5Gl6BxmvKRPpqo2uNMv4rcHBMwzk/st8=
golang.org/x/sys v0.0.0-20200622214017-ed371f2e16b4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.31.1 h1:SfXqXS5hkufcdZ/mHtYCh53P2b+92WQq/DZcKLgsFRs=
google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.24.0 h1:UhZDfRO8JRQru4/+LlLE0BRKGF8L+PICnvYZmx/fEGA=
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
k8s.io/api v0.19.0/go.mod h1:I1K45XlvTrDjmj5LoM5LuP/KYrhWbjUKT/SoPG0qTjw=
k8s.io/apimachinery v0.19.0/go.mod h1:DnPGDnARWFvYa3pMHgSxtbZb7gpzzAZ1pTfaUNDVlmA=
k8s.io/client-go v0.19.0/go.mod h1:H9E/VT95blcFQnlyShFgnFT9ZnJOAceiUHM3MlRC+mU=
k8s.io/component-base v0.19.0/go.mod h1:dKsY8BxkA+9dZIAh2aWJLL/UdASFDNtGYTCItL4LM7Y=
k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
k8s.io/kube-openapi v0.0.0-20200805222855-6aeccd4b50c6/go.mod h1:UuqjUnNftUyPE5H64/qeyjQoUZhGpeFDVdxjTeEVN2o=
k8s.io/kubelet v0.19.0 h1:1x+ZC2o7rRKy+bMen5u3PpBdterOck7i4EpZUM3zDfE=
k8s.io/kubelet v0.19.0/go.mod h1:cGds22piF/LnFzfAaIT+efvOYBHVYdunqka6NVuNw9g=
k8s.io/utils v0.0.0-20200729134348-d5654de09c73/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
sigs.k8s.io/structured-merge-diff/v4 v4.0.1/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=

+ 0
- 135
third-party/cambricon-k8s-device-plugin/device-plugin/main.go View File

@@ -1,135 +0,0 @@
// Copyright 2020 Cambricon, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package main

import (
"flag"
"log"
"os"
"os/signal"
"syscall"

"github.com/cambricon/cambricon-k8s-device-plugin/device-plugin/pkg/cndev"
"github.com/fsnotify/fsnotify"
pluginapi "k8s.io/kubelet/pkg/apis/deviceplugin/v1beta1"
)

const (
sriovShare int = iota + 1
envShare
)

var mode = flag.String("mode", "default",
`default: default version; mode number 0.
sriov: MLU is divided into VFs by SR-IOV on host machine; mode number 1.
env-share: A whole MLU can be allocated to multiple containers; A container can only use one MLU. mode number 2.
`)

func main() {

flag.Parse()

log.Println("Loading CNDEV")
if err := cndev.Init(); err != nil {
log.Printf("Failed to initialize CNDEV: %s.", err)

select {}
}
defer func() { log.Println("Shutdown of CNDEV returned:", cndev.Release()) }()

log.Println("Fetching devices.")
n, err := cndev.GetDeviceCount()
check(err)
if n == 0 {
log.Println("No devices found. Waiting indefinitely.")
select {}
}

log.Println("Starting FS watcher.")
watcher, err := startFSWatcher(pluginapi.DevicePluginPath)
if err != nil {
log.Println("Failed to created FS watcher.")
os.Exit(1)
}
defer watcher.Close()

log.Println("Starting OS watcher.")
sigs := startOSWatcher(syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT)

restart := true
var devicePlugin *CambriconDevicePlugin

L:
for {
if restart {
if devicePlugin != nil {
devicePlugin.Stop()
}

devicePlugin = NewCambriconDevicePlugin()
if err := devicePlugin.Serve(); err != nil {
log.Println("Could not contact Kubelet, retrying. Did you enable the device plugin feature gate?")
} else {
restart = false
}
}

select {
case event := <-watcher.Events:
if event.Name == pluginapi.KubeletSocket && event.Op&fsnotify.Create == fsnotify.Create {
log.Printf("inotify: %s created, restarting.", pluginapi.KubeletSocket)
restart = true
}

case err := <-watcher.Errors:
log.Printf("inotify: %s", err)

case s := <-sigs:
switch s {
case syscall.SIGHUP:
log.Println("Received SIGHUP, restarting.")
restart = true
default:
log.Printf("Received signal \"%v\", shutting down.", s)
devicePlugin.Stop()
break L
}
}
}
}

func startFSWatcher(files ...string) (*fsnotify.Watcher, error) {
watcher, err := fsnotify.NewWatcher()
if err != nil {
return nil, err
}

for _, f := range files {
err = watcher.Add(f)
if err != nil {
watcher.Close()
return nil, err
}
}

return watcher, nil
}

func startOSWatcher(sigs ...os.Signal) chan os.Signal {
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, sigs...)

return sigChan
}

+ 0
- 112
third-party/cambricon-k8s-device-plugin/device-plugin/pkg/cndev/bindings.go View File

@@ -1,112 +0,0 @@
// Copyright 2020 Cambricon, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package cndev

// #cgo LDFLAGS: -ldl
// #include "include/cndev.h"
// #include "cndev_dl.h"
import "C"

import (
"errors"
"fmt"
"time"
)

func errorString(ret C.cndevRet_t) error {
if ret == C.CNDEV_SUCCESS {
return nil
}
err := C.GoString(C.cndevGetErrorString(ret))
return fmt.Errorf("cndev: %v", err)
}

func Init() error {
r := C.cndevInit_dl()
if r == C.CNDEV_ERROR_UNINITIALIZED {
return errors.New("could not load CNDEV library")
}
return errorString(r)
}

func Release() error {
r := C.cndevRelease_dl()
return errorString(r)
}

func GetDeviceCount() (uint, error) {
var cardInfos C.cndevCardInfo_t
cardInfos.version = C.int(1)
r := C.cndevGetDeviceCount(&cardInfos)
return uint(cardInfos.Number), errorString(r)
}

func getDeviceUUID(idx uint) (string, error) {
var cardSN C.cndevCardSN_t
cardSN.version = C.int(3)
r := C.cndevGetCardSN(&cardSN, C.int(idx))
err := errorString(r)
if err != nil {
return "", err
}
sn := fmt.Sprintf("%x", int(cardSN.sn))
uuid := "MLU-" + sn
return uuid, nil
}

func getDevicePath(idx uint) (string, error) {
var cardName C.cndevCardName_t
var path string
cardName.version = C.int(3)
r := C.cndevGetCardName(&cardName, C.int(idx))
err := errorString(r)
if err != nil {
return "", err
}
cardType := cardName.id
if cardType == C.MLU100 {
path = fmt.Sprintf("/dev/cambricon_c10Dev%d", idx)
} else {
path = fmt.Sprintf("/dev/cambricon_dev%d", idx)
}
return path, nil
}

func getDeviceHealthState(idx uint, delayTime int) (int, error) {
var ret C.cndevRet_t
var cardHealthState C.cndevCardHealthState_t
var healthCode int
cardHealthState.version = C.int(3)
// sleep for some seconds
time.Sleep(time.Duration(delayTime) * time.Second)
ret = C.cndevGetCardHealthState(&cardHealthState, C.int(idx))
healthCode = int(cardHealthState.health)
return healthCode, errorString(ret)
}

func getDevicePCIeInfo(idx uint) (*pcie, error) {
var pcieInfo C.cndevPCIeInfo_t
pcieInfo.version = C.int(3)
r := C.cndevGetPCIeInfo(&pcieInfo, C.int(idx))
if err := errorString(r); err != nil {
return nil, err
}
return &pcie{
domain: int(pcieInfo.domain),
bus: int(pcieInfo.bus),
device: int(pcieInfo.device),
function: int(pcieInfo.function),
}, nil
}

+ 0
- 72
third-party/cambricon-k8s-device-plugin/device-plugin/pkg/cndev/bindings_test.go View File

@@ -1,72 +0,0 @@
// Copyright 2020 Cambricon, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package cndev

import (
"fmt"
"log"
"os"
"testing"

"github.com/stretchr/testify/assert"
)

func TestMain(m *testing.M) {
err := Init()
if err != nil {
log.Fatal(err)
}
ret := m.Run()
if ret != 0 {
os.Exit(ret)
}
err = Release()
if err != nil {
log.Fatal(err)
}
}

func TestGetDeviceCount(t *testing.T) {
count, err := GetDeviceCount()
assert.NoError(t, err)
assert.Equal(t, uint(8), count)
}

func TestGetDeviceUUID(t *testing.T) {
uuid, err := getDeviceUUID(uint(0))
assert.NoError(t, err)
assert.Equal(t, fmt.Sprintf("MLU-%x", 2701111), uuid)
}

func TestGetDevicePath(t *testing.T) {
path, err := getDevicePath(uint(1))
assert.NoError(t, err)
assert.Equal(t, "/dev/cambricon_dev1", path)
}

func TestGetDeviceHealthState(t *testing.T) {
health, err := getDeviceHealthState(uint(0), 1)
assert.NoError(t, err)
assert.Equal(t, 1, health)
}

func TestGetDevicePCIeInfo(t *testing.T) {
pcie, err := getDevicePCIeInfo(uint(0))
assert.NoError(t, err)
assert.Equal(t, 0, pcie.domain)
assert.Equal(t, 12, pcie.bus)
assert.Equal(t, 13, pcie.device)
assert.Equal(t, 1, pcie.function)
}

+ 0
- 155
third-party/cambricon-k8s-device-plugin/device-plugin/pkg/cndev/cndev.go View File

@@ -1,155 +0,0 @@
// Copyright 2020 Cambricon, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package cndev

import (
"bytes"
"errors"
"fmt"
"io/ioutil"
"log"
"os/exec"
"strconv"
"strings"
"time"
)

type pcie struct {
domain int
bus int
device int
function int
}

type Device struct {
Slot uint
UUID string
Path string
pcie *pcie
}

func NewDeviceLite(idx uint, pcieAware bool) (*Device, error) {
var pcie *pcie

uuid, err := getDeviceUUID(idx)
if err != nil {
return nil, err
}
path, err := getDevicePath(idx)
if err != nil {
return nil, err
}

if pcieAware {
pcie, err = getDevicePCIeInfo(idx)
if err != nil {
return nil, err
}
}

return &Device{
Slot: idx,
UUID: uuid,
Path: path,
pcie: pcie,
}, nil
}

func (d *Device) GetGeviceHealthState(delayTime int) (int, error) {
return getDeviceHealthState(d.Slot, delayTime)
}

func (d *Device) GetPCIeID() (string, error) {
if d.pcie == nil {
return "", errors.New("device has no PCIe info")
}
domain := strconv.FormatInt(int64(d.pcie.domain), 16)
domain = strings.Repeat("0", 4-len([]byte(domain))) + domain
bus := strconv.FormatInt(int64(d.pcie.bus), 16)
if d.pcie.bus < 16 {
bus = "0" + bus
}
device := strconv.FormatInt(int64(d.pcie.device), 16)
if d.pcie.device < 16 {
device = "0" + device
}
function := strconv.FormatInt(int64(d.pcie.function), 16)
return domain + ":" + bus + ":" + device + "." + function, nil
}

func (d *Device) EnableSriov(num int) error {
err := d.ValidateSriovNum(num)
if err != nil {
return err
}
id, err := d.GetPCIeID()
if err != nil {
return err
}
path := "/sys/bus/pci/devices/" + id + "/sriov_numvfs"
vf, err := getNumFromFile(path)
if err != nil {
return err
}
if vf == 0 {
return enableSriov(id, num)
}
if vf != num {
return fmt.Errorf("sriov enabled. vf number %d different from set %d", vf, num)
}
log.Println("sriov already enabled, pass")
return nil
}

func (d *Device) ValidateSriovNum(num int) error {
id, err := d.GetPCIeID()
if err != nil {
return err
}
path := "/sys/bus/pci/devices/" + id + "/sriov_totalvfs"
max, err := getNumFromFile(path)
if err != nil {
return err
}
if num < 1 || num > max {
return fmt.Errorf("invalid sriov number %d, maximum: %d, minimum: 1", num, max)
}
return nil
}

func getNumFromFile(path string) (int, error) {
output, err := ioutil.ReadFile(path)
if err != nil {
return 0, err
}
output = bytes.Trim(output, "\n")
num, err := strconv.ParseInt(string(output), 10, 64)
return int(num), err
}

func enableSriov(id string, num int) error {
path := "/sys/bus/pci/devices/" + id + "/sriov_numvfs"
command := "echo " + strconv.Itoa(num) + " > " + path
err := exec.Command("bash", "-c", command).Run()
if err != nil {
return err
}
time.Sleep(time.Second)
newNum, err := getNumFromFile(path)
if err != nil || newNum != num {
return fmt.Errorf("the number of VFs is still not correct after enabling vf again. new: %d, err: %v", newNum, err)
}
return nil
}

+ 0
- 158
third-party/cambricon-k8s-device-plugin/device-plugin/pkg/cndev/cndev_dl.c View File

@@ -1,158 +0,0 @@
/*
* Copyright 2020 Cambricon, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include <stddef.h>
#include <dlfcn.h>
#include <stdlib.h>
#include "cndev_dl.h"
#include "./include/cndev.h"

void *cndevHandle;

cndevRet_t (*cndevInitFunc)(int);

cndevRet_t (*cndevReleaseFunc)(void);

const char *(*cndevGetErrorStringFunc)(cndevRet_t errorId);
const char *cndevGetErrorString(cndevRet_t errorId)
{
if (cndevGetErrorStringFunc == NULL)
{
return "cndevGetErrorString Function not found";
}
return cndevGetErrorStringFunc(errorId);
}

cndevRet_t (*cndevGetDeviceCountFunc)(cndevCardInfo_t *cardNum);
cndevRet_t cndevGetDeviceCount(cndevCardInfo_t *cardNum)
{
if (cndevGetDeviceCountFunc == NULL)
{
return CNDEV_ERROR_UNKNOWN;
}
return cndevGetDeviceCountFunc(cardNum);
}

cndevRet_t (*cndevGetCardSNFunc)(cndevCardSN_t *cardSN, int devId);
cndevRet_t cndevGetCardSN(cndevCardSN_t *cardSN, int devId)
{
if (cndevGetCardSNFunc == NULL)
{
return CNDEV_ERROR_UNKNOWN;
}
return cndevGetCardSNFunc(cardSN, devId);
}

cndevRet_t (*cndevGetCardNameFunc)(cndevCardName_t *cardName, int devId);
cndevRet_t cndevGetCardName(cndevCardName_t *cardName, int devId)
{
if (cndevGetCardNameFunc == NULL)
{
return CNDEV_ERROR_UNKNOWN;
}
return cndevGetCardNameFunc(cardName, devId);
}

cndevRet_t (*cndevGetCardHealthStateFunc)(cndevCardHealthState_t *cardHealthState, int devId);
cndevRet_t cndevGetCardHealthState(cndevCardHealthState_t *cardHealthState, int devId)
{
if (cndevGetCardHealthStateFunc == NULL)
{
return CNDEV_ERROR_UNKNOWN;
}
return cndevGetCardHealthStateFunc(cardHealthState, devId);
}

cndevRet_t (*cndevGetPCIeInfoFunc)(cndevPCIeInfo_t *deviceInfo, int devId);
cndevRet_t cndevGetPCIeInfo(cndevPCIeInfo_t *deviceInfo, int devId)
{
if (cndevGetPCIeInfoFunc == NULL)
{
return CNDEV_ERROR_UNKNOWN;
}
return cndevGetPCIeInfoFunc(deviceInfo, devId);
}

cndevRet_t CNDEV_DL(cndevInit)(void)
{
cndevHandle = dlopen("libcndev.so", RTLD_LAZY);
if (cndevHandle == NULL)
{
return CNDEV_ERROR_UNINITIALIZED;
}
cndevInitFunc = dlsym(cndevHandle, "cndevInit");
if (cndevInitFunc == NULL)
{
return CNDEV_ERROR_UNKNOWN;
}
cndevReleaseFunc = dlsym(cndevHandle, "cndevRelease");
if (cndevReleaseFunc == NULL)
{
return CNDEV_ERROR_UNKNOWN;
}
cndevGetErrorStringFunc = dlsym(cndevHandle, "cndevGetErrorString");
if (cndevGetErrorStringFunc == NULL)
{
return CNDEV_ERROR_UNKNOWN;
}
cndevGetDeviceCountFunc = dlsym(cndevHandle, "cndevGetDeviceCount");
if (cndevGetDeviceCountFunc == NULL)
{
return CNDEV_ERROR_UNKNOWN;
}
cndevGetCardSNFunc = dlsym(cndevHandle, "cndevGetCardSN");
if (cndevGetCardSNFunc == NULL)
{
return CNDEV_ERROR_UNKNOWN;
}
cndevGetCardNameFunc = dlsym(cndevHandle, "cndevGetCardName");
if (cndevGetCardNameFunc == NULL)
{
return CNDEV_ERROR_UNKNOWN;
}
cndevGetCardHealthStateFunc = dlsym(cndevHandle, "cndevGetCardHealthState");
if (cndevGetCardHealthStateFunc == NULL)
{
return CNDEV_ERROR_UNKNOWN;
}
cndevGetPCIeInfoFunc = dlsym(cndevHandle, "cndevGetPCIeInfo");
cndevRet_t result = cndevInitFunc(0);
if (result != CNDEV_SUCCESS)
{
dlclose(cndevHandle);
cndevHandle = NULL;
return result;
}
return CNDEV_SUCCESS;
}

cndevRet_t CNDEV_DL(cndevRelease)(void)
{
if (cndevHandle == NULL)
{
return CNDEV_SUCCESS;
}
if (cndevReleaseFunc == NULL)
{
return CNDEV_ERROR_UNKNOWN;
}
cndevRet_t r = cndevReleaseFunc();
if (r != CNDEV_SUCCESS)
{
return r;
}
return (dlclose(cndevHandle) ? CNDEV_ERROR_UNKNOWN : CNDEV_SUCCESS);
}

+ 0
- 26
third-party/cambricon-k8s-device-plugin/device-plugin/pkg/cndev/cndev_dl.h View File

@@ -1,26 +0,0 @@
/*
* Copyright 2020 Cambricon, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#ifndef _CNDEV_DL_H_
#define _CNDEV_DL_H_

#include "./include/cndev.h"

#define CNDEV_DL(x) x##_dl

extern cndevRet_t CNDEV_DL(cndevInit)(void);
extern cndevRet_t CNDEV_DL(cndevRelease)(void);
#endif // _CNDEV_DL_H_

+ 0
- 54
third-party/cambricon-k8s-device-plugin/device-plugin/pkg/cndev/cndev_test.go View File

@@ -1,54 +0,0 @@
// Copyright 2020 Cambricon, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package cndev

import (
"os"
"testing"

"github.com/stretchr/testify/assert"
)

func TestGetPCIeID(t *testing.T) {
d := &Device{
pcie: &pcie{
domain: 0,
bus: 3,
device: 15,
function: 1,
},
}
id, err := d.GetPCIeID()
assert.NoError(t, err)
assert.Equal(t, "0000:03:0f.1", id)
}

func TestGetNumFromFile(t *testing.T) {
path := "/tmp/device_plugin_cndev_ut"
f, err := os.Create(path)
assert.NoError(t, err)

data := []byte("4\n")
_, err = f.Write(data)
assert.NoError(t, err)
num, err := getNumFromFile(path)
assert.NoError(t, err)
assert.Equal(t, 4, num)

err = f.Close()
assert.NoError(t, err)
err = os.Remove(path)
assert.NoError(t, err)
}

+ 0
- 1471
third-party/cambricon-k8s-device-plugin/device-plugin/pkg/cndev/include/cndev.h View File

@@ -1,1471 +0,0 @@
/*
* Copyright 2020 Cambricon, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#ifndef INCLUDE_CNDEV_H_
#define INCLUDE_CNDEV_H_

#ifndef WIN32
#include <libgen.h>
#include <linux/pci_regs.h>
#include <unistd.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if defined(__cplusplus)
extern "C" {
#endif /*__cplusplus*/

// api versions
#define CNDEV_VERSION_1 1
#define CNDEV_VERSION_2 2
#define CNDEV_VERSION_3 3
#define CNDEV_VERSION_4 4
#define CNDEV_VERSION_5 5

#define CCLINK_PORT 6

#if defined(WIN32) || defined(WINDOWS)
#define EXPORT __declspec(dllexport)
#elif defined(LINUX) || defined(__linux) || defined(__CYGWIN__)
#define EXPORT __attribute__((visibility("default")))
#endif

#ifdef WIN32
typedef unsigned char __uint8_t; // NOLINT
typedef unsigned short __uint16_t; // NOLINT
typedef int __int32_t; // NOLINT
typedef unsigned int __uint32_t; // NOLINT
typedef unsigned long long __uint64_t;// NOLINT
typedef long __int64_t; // NOLINT
#endif
/**< Error codes */
typedef enum {
CNDEV_SUCCESS = 0, /**< No error */
CNDEV_ERROR_NO_DRIVER = 1, /**< No Driver */
CNDEV_ERROR_LOW_DRIVER_VERSION = 2, /**< Driver Version Low*/
CNDEV_ERROR_UNSUPPORTED_API_VERSION = 3, /**< API Version is not support*/
CNDEV_ERROR_UNINITIALIZED = 4, /**< API not Initial*/
CNDEV_ERROR_INVALID_ARGUMENT = 5, /**< Invalid pointer*/
CNDEV_ERROR_INVALID_DEVICE_ID = 6, /**< Invalid device id*/
CNDEV_ERROR_UNKNOWN = 7, /**< Unknown error*/
CNDEV_ERROR_MALLOC = 8, /**< internal malloc fail*/
CNDEV_ERROR_INSUFFICIENT_SPACE = 9, /**< cndevInfoCount has not enough space*/
CNDEV_ERROR_NOT_SUPPORTED = 10, /**< not supported*/
CNDEV_ERROR_INVALID_LINK = 11 /**< Invalid link port*/
} cndevRet_t;

typedef enum {
MLU100 = 0, /**< MLU100 */
MLU270 = 1, /**< MLU270 */
MLU220_M2 = 16, /**< MLU220_M2 */
MLU220_EDGE = 17, /**< MLU220_EDGE */
MLU220_EVB = 18, /**< MLU220_EVB */
MLU220_M2i = 19, /**< MLU220_M2i */
MLU290 = 20 /**< MLU290 */
} cndevNameEnum_t;

typedef enum {
SELF = 0,
INTERNAL = 1, /**< devices that are on the same board*/
SINGLE = 2, /**< all devices that only need traverse a single PCIe switch*/
MULTIPLE = 3, /**< all devices that need not traverse a host bridge*/
HOST_BRIDGE = 4, /**< all devices that are connected to the same host bridge*/
CPU = 5, /**< all devices that are connected to the same CPU but possibly multiple host bridges*/
SYSTEM = 6 /**< all device in the system*/
} cndevTopologyRelationshipEnum_t;

typedef enum {
SPEED_FMT_NRZ = 0,
SPEED_FMT_PM4 = 1
} cclinkSpeedEnum_t;

typedef enum {
CCLINK_CNTR_RD_BYTE = 0,
CCLINK_CNTR_RD_PKG = 1,
CCLINK_CNTR_WR_BYTE = 2,
CCLINK_CNTR_WR_PKG = 3,
CCLINK_ERR_RPY = 4,
CCLINK_ERR_FTL = 5,
CCLINK_ERR_ECC_DEB = 6,
CCLINK_ERR_CRC24 = 7,
CCLINK_ERR_CRC32 = 8,
CCLINK_ERR_CORR = 9,
CCLINK_ERR_UNCORR = 10
} cclinkCounterEnum_t;

typedef enum {
CNDEV_FEATURE_ENABLED = 0,
CNDEV_FEATURE_DISABLED = 1
} cndevEnableStatusEnum_t;

/**
* @ brief translate the error ID to the corresponding message
*
* @ param errorId the error ID
*
*@ return "Cndev_ERROR not found!" if the corresponding message cant't be found, otherwise the corresponding message will be
*returned
*/
EXPORT
const char *cndevGetErrorString(cndevRet_t errorId);

#ifdef WIN32
#define basename(file) "UNSUPPORTED"
#endif

#ifndef cndevCheckErrors
#define __cndevCheckErrors(err, file, line) \
do { \
cndevRet_t _err = (err); \
if (CNDEV_SUCCESS != _err) { \
fprintf(stderr, "cndevCheckErrors(%d): %s, from file <%s>, line %i.\n", _err, cndevGetErrorString(_err), basename((char*)file), \
line); \
exit(1); \
} \
} while (0)
#define cndevCheckErrors(err) __cndevCheckErrors((err), __FILE__, __LINE__)
#endif

/**< Card information */
typedef struct {
int version; /**< driver version*/
unsigned Number; /**< card_id*/
} cndevCardInfo_t;

/**< Memory information */
typedef struct {
int version;
__int64_t PhysicalMemoryTotal; /**< MLU physical total memory, unit:MB*/
__int64_t PhysicalMemoryUsed; /**< MLU physical used memory, unit:MB*/
__int64_t VirtualMemoryTotal; /**< MLU virtual total memory, unit:MB*/
__int64_t VirtualMemoryUsed; /**< MLU virtual used memory, unit:MB*/
__int64_t ChannelNumber; /**< Memory channel number*/
__int64_t ChannelMemoryUsed[20]; /**< Memory used each channel, unit:MB*/
} cndevMemoryInfo_t;

/**< Version information */
typedef struct {
int version;
unsigned MCUMajorVersion; /**< MCU major id*/
unsigned MCUMinorVersion; /**< MCU minor id*/
unsigned MCUBuildVersion; /**< MCU build id*/
unsigned DriverMajorVersion; /**< Driver major id*/
unsigned DriverMinorVersion; /**< Driver minor id*/
unsigned DriverBuildVersion; /**< Driver build id*/
} cndevVersionInfo_t;

/**< ECC information */
typedef struct {
int version;
__uint64_t OneBitError; /**< single single-bit error*/
__uint64_t MultipleOneError; /**< multiple single-bit error*/
__uint64_t MultipleError; /**< single multiple-bits error*/
__uint64_t MultipleMultipleError; /**< multiple multiple-bits error*/
__uint64_t CorrectedError; /**< corrected error*/
__uint64_t UncorrectedError; /**< uncorrected error*/
__uint64_t TotalError; /**< ECC error total times*/
} cndevECCInfo_t;

/**< Power information */
typedef struct {
int version; /**< API version*/
int Usage; /**< current power dissipation,unit:W*/
int Cap; /**< cap power dissipation unit:W*/
int Usage_Decimal; /**< decimal places for current power dissipation*/
int Machine; /**< current machine power dissipation,unit:W*/
} cndevPowerInfo_t;

/**< Temperature information */
typedef struct {
int version; /**< API version*/
int Board; /**< MLU board temperature, unit:℃ */
int Cluster[20]; /**< MLU cluster temperature, unit:℃ */
int MemoryDie[8]; /**< MLU MemoryDie temperature, unit:℃ */
int Chip; /**< MLU Chip temperature, unit:℃ */
int Case; /**< MLU case temperature, unit:℃ */
} cndevTemperatureInfo_t;

/**< Fan speed information*/
typedef struct {
int version; /**< API version*/
int FanSpeed; /**< MLU fan speed,the percentage of the max fan speed*/
} cndevFanSpeedInfo_t;

/**< LLC information*/
typedef struct {
int version; /**< API version*/
__uint64_t Total; /**< LLC total times*/
__uint64_t Hit; /**< LLC hit times*/
} cndevLLCInfo_t;

/**< MLU utilization information*/
typedef struct {
int version; /**< API version*/
int BoardUtilization; /**< MLU board utilization*/
int CoreUtilization[80]; /**< MLU core utilization*/
} cndevUtilizationInfo_t;

/**< MLU frequency information*/
typedef struct {
int version; /**< API version*/
int Frequency; /**< MLU board frequency, unit:MHz*/
int DdrFreq; /**< MLU ddr frequency, unit:MHz*/
__uint8_t OvertempDfsFlag; /* Over-temperature dynamic frequency*/
__uint8_t FastDfsFlag; /* Fast dynamic frequency*/
} cndevFrequencyInfo_t;

/**< Process information*/
typedef struct {
int version; /**< API version*/
unsigned int pid; /**< pid*/
unsigned long PhysicalMemoryUsed; /**< MLU physical memory used, unit:KiB*/
unsigned long VirtualMemoryUsed; /**< MLU virtual memory used, unit:KiB*/
} cndevProcessInfo_t;

/**< Library version information*/
typedef struct {
int version; /**< API version*/
unsigned LibMajorVersion; /**< library major version*/
unsigned LibMinorVersion; /**< library minor version*/
unsigned LibBuildVersion; /**< library build version*/
} cndevLibVersionInfo_t;

/**< Card core count*/
typedef struct {
int version; /** API version*/
int count; /** card core count*/
} cndevCardCoreCount_t;

/**< Card cluster count*/
typedef struct {
int version; /** API version*/
int count; /** card cluster count*/
} cndevCardClusterCount_t;

/**< Card name*/
typedef struct {
int version; /**API version*/
cndevNameEnum_t id; /** card name*/
} cndevCardName_t;

/**< Codec count*/
typedef struct {
int version;
int count; /** card codec count*/
} cndevCodecCount_t;

/**< Codec utilization*/
typedef struct {
int version;
int totalUtilization[20];
} cndevCodecUtilization_t;

/**< SN*/
typedef struct {
int version;
__int64_t sn; /** card SN in hex*/
__int64_t mother_board_sn; /** motherboard SN in hex*/
} cndevCardSN_t;

/**device id information**/
typedef struct {
int version;
unsigned int subsystem_id; /**PCIe Sub-System ID**/
unsigned int device_id; /**PCIe Device ID**/
unsigned short vendor; // NOLINT /**PCIe Vendor ID**/
unsigned short subsystem_vendor; // NOLINT /**PCIe Sub-Vendor ID**/
unsigned int domain; /**PCIe domain**/
unsigned int bus; /**PCIe bus_num**/
unsigned int device; /**PCIe device, slot**/
unsigned int function; /**PCIe function, func**/
const char * phy_slot; /**Physical Slot**/
} cndevPCIeInfo_t;

/**PCie throughput,read and write**/
typedef struct {
int version; /** API version*/
__int64_t pcie_read; /** PCIe throughput read ,unit: Byte*/
__int64_t pcie_write; /** PCIe throughput write ,unit: Byte*/
} cndevPCIethroughput_t;

/**device affinity information**/
typedef struct {
int version;
__uint32_t cpuCount;
/* if there are 80 cpus in the system, bitmap's format is:
* bitmap[0]:31-16:not used, 15-0:cpu79-cpu64
* bitmap[1]:31-0:cpu63-cpu32
* bitmap[2]:31-0:cpu31-cpu0
*/
__uint32_t cpuAffinityBitMap[1024];
} cndevAffinity_t;

typedef struct {
int version;
cndevTopologyRelationshipEnum_t relation;
} cndevTopologyRelationship_t;

typedef struct {
int version; /**API version**/
int currentSpeed; /**PCI current speed**/
int currentWidth; /**PCI current width**/
} cndevCurrentPCIInfo_t;

typedef struct cndevTopologyNodeCapInfo_t {
struct cndevTopologyNodeCapInfo_t *next;
__uint8_t id;
__uint16_t cap;
} cndevTopologyNodeCapInfo_t;

typedef struct cndevTopologyNode_t {
int virtual_root_node; // bool
int domain;
int bus;
int device;
int function;
unsigned int subsystem_id;
unsigned int device_id;
unsigned int vendor;
unsigned int subsystem_vendor;
char const *device_name;
unsigned int class_val; // hex
char const *class_name;
struct cndevTopologyNodeCapInfo_t *first_cap;
struct cndevTopologyNode_t *parent;
struct cndevTopologyNode_t *left;
struct cndevTopologyNode_t *right;
struct cndevTopologyNode_t *child; // first child
unsigned int link_speed;
int is_bridge; // bool
int is_cardbus; // bool
// if is_bridge or is_cardbus, the following fields will be filled, otherwise these will be 0.
unsigned char primary_bus;
unsigned char secondary_bus;
unsigned char subordinate_bus;
} cndevTopologyNode_t;

typedef struct {
int version;
__uint8_t id;
__uint16_t cap;
} cndevCapabilityInfo_t;

/**< health state**/
typedef struct {
int version;
int health;
}cndevCardHealthState_t;

/**< link speed**/
typedef struct {
int version;
int link_speed;
}cndevLinkSpeed_t;

/**< vpu utilization**/
typedef struct {
int version;
int vpuCount;
int vpuCodecUtilization[20];
}cndevVideoCodecUtilization_t;

/**< jpu utilization**/
typedef struct {
int version;
int jpuCount;
int jpuCodecUtilization[20];
}cndevImageCodecUtilization_t;

/**< fast alloc memory**/
typedef struct {
int version;
int fa_memtotal;
int fa_memfree;
}cndevFastAlloc_t;

/**< NUMA node id **/
typedef struct {
int version;
__int32_t nodeId;
} cndevNUMANodeId_t;

typedef struct {
int version;
int scalerCount;
int scalerUtilization[20];
}cndevScalerUtilization_t;

typedef struct {
int version;
int codecTurbo;
}cndevCodecTurbo_t;

typedef struct {
int version; /** API version*/
int count; /** card memorydie count*/
} cndevCardMemoryDieCount_t;

typedef struct {
int version; /** API version*/
int qdd[8]; /** serdes port status*/
} cndevQsfpddStatus_t;

/**< cclink version**/
typedef struct {
int version;
unsigned majorVersion;
unsigned minorVersion;
unsigned buildVersion;
} cndevCclinkVersion_t;

/**< cclink status**/
typedef struct {
int version;
cndevEnableStatusEnum_t isActive;
} cndevCclinkStatus_t;

/**< cclink speed**/
typedef struct {
int version;
int speedValue;
cclinkSpeedEnum_t speedFormat;
} cndevCclinkSpeed_t;

/**< cclink capability**/
typedef struct {
int version;
unsigned p2pTransfer;
unsigned interlakenSerdes;
} cndevCclinkCapability_t;

/**< cclink counter**/
typedef struct {
int version;
int cntrReadByte;
int cntrReadPackage;
int cntrWriteByte;
int cntrWritePackage;
int errReplay;
int errFatal;
int errEccDouble;
int errCRC24;
int errCRC32;
int errCorrected;
int errUncorrected;
} cndevCclinkCounter_t;

/**< reset cclink counter**/
typedef struct {
int version;
cclinkCounterEnum_t setCounter;
} cndevCclinkSetCounter_t;

/**< cclink remote information**/
typedef struct {
int version;
__int64_t mc_sn;
__int64_t ba_sn;
int slot_id;
int port_id;
unsigned dev_ip[16];
unsigned uuid[16];
int dev_ip_version;
int is_ip_valid;
int connect_type;
} cndevCclinkRemoteInfo_t;

/**< cclink bandwidth utilization**/
typedef struct {
int version;
int utilCount;
int util[8];
} cndevCclinkBandwidthUtil_t;

/**< cclink devices sn**/
typedef struct {
int version;
__int64_t cclinkMcSn[6];
__int64_t cclinkBaSn[6];
} cndevCclinkDevSN_t;

typedef int (*CNDEV_TRAVERSE_CALLBACK)(cndevTopologyNode_t *current, void *userdata);
/**
* @ brief do initialization work, check whether the API version and the MLU driver version could be supported
* @ return CNDEV_SUCCESS if success
* @ return CNDEV_NO_DRIVER if the MLU driver is not available
* @ return CNDEV_LOW_DRIVER if the version of the MLU driver is too low to support the cndev library
* @ return CNDEV_ERROR_UNKNOWN if some fault occurs, when the function calls some system function
*/
EXPORT
cndevRet_t cndevInit(int reserved);
/**
* @ brief do aborting work
*
* @ return CNDEV_SUCCESS if success
* @ return CNDEV_ERROR_UNINITIALIZED,if the user don't call the function named cndevInit beforehand
* @ return CNDEV_ERROR_UNKNOWN if some fault occurs, when the function calls some system function
*/
EXPORT
cndevRet_t cndevRelease();

/**
* @ brief get the amount of cards
*
* @ param cardNum will store a pointer to a structure which stores the amount of cards after the function ends
*
* @ return CNDEV_SUCCESS if success
* @ return CNDEV_ERROR_UNINITIALIZED,if the user don't call the function named cndevInit beforehand
* @ return CNDEV_UNSUPPORTED_API_VERSION if the API version is too low (or too high) to be support by the cndev library
*/
EXPORT
cndevRet_t cndevGetDeviceCount(cndevCardInfo_t *cardNum);

/**
* @ brief get the device ID information of PCIe
*
* @ param devId the number of the card which the user selects, starting from 0
* @ param deviceInfo will store a pointer to a structure which stores the information of the device Id after the function ends
*
* @ return CNDEV_SUCCESS if success
* @ return CNDEV_ERROR_UNINITIALIZED if the user don't call the function named cndevInit beforehand
* @ return CNDEV_ERROR_INVALID_ARGUMENT if the parameter is NULL
* @ return CNDEV_ERROR_INVALID_DEVICE_ID if the number of card which the user selects is not available
* @ return CNDEV_ERROR_UNKNOWN if some fault occurs, when the function calls some system function
* @ return CNDEV_UNSUPPORTED_API_VERSION if the API version is too low to be support by the cndev library
*/
EXPORT
cndevRet_t cndevGetPCIeInfo(cndevPCIeInfo_t *deviceInfo, int devId);

/**
* @ brief get the information of card's memory
*
* @ param devId the number of the card which the user selects, starting from 0
* @ param memInfo will store a pointer to a structure which stores the information of the cars's memory after the function ends
*
* @ return CNDEV_SUCCESS if success
* @ return CNDEV_ERROR_UNINITIALIZED if the user don't call the function named cndevInit beforehand
* @ return CNDEV_ERROR_INVALID_ARGUMENT if the parameter is NULL
* @ return CNDEV_ERROR_INVALID_DEVICE_ID if the number of card which the user selects is not available
* @ return CNDEV_ERROR_UNKNOWN if some fault occurs, when the function calls some system function
* @ return CNDEV_UNSUPPORTED_API_VERSION if the API version is too low to be support by the cndev library
*/
EXPORT
cndevRet_t cndevGetMemoryUsage(cndevMemoryInfo_t *memInfo, int devId);

/**
* @ brief get the information of card's MCU version and MLU driver version
*
* @ param devId the number of the card which the user selects, starting from 0
* @ param versInfo will store a pointer to a structure which stores the information of the cars' MCU version and MLU driver
* version after the function ends
*
* @ return CNDEV_SUCCESS if success
* @ return CNDEV_ERROR_UNINITIALIZED if the user don't call the function named cndevInit beforehand
* @ return CNDEV_ERROR_INVALID_ARGUMENT if the parameter is NULL
* @ return CNDEV_ERROR_UNKNOWN if some fault occurs, when the function calls some system function
* @ return CNDEV_ERROR_INVALID_DEVICE_ID if the number of card which the user selects is not available
* @ return CNDEV_UNSUPPORTED_API_VERSION if the API version is too low to be support by the cndev library
*/
EXPORT
cndevRet_t cndevGetVersionInfo(cndevVersionInfo_t *versInfo, int devId);

/**
* @ brief get the information of the card's ECC
*
* @ param devId the number of the card which the user selects, starting from 0

* @ param eccInfo will store a pointer to a structure which stores the information of the cars' ECC
*
* @ return CNDEV_SUCCESS if success
* @ return CNDEV_ERROR_UNINITIALIZED if the user don't call the function named cndevInit beforehand
* @ return CNDEV_ERROR_INVALID_ARGUMENT if the parameter is NULL
* @ return CNDEV_ERROR_UNKNOWN if some fault occurs, when the function calls some system function
* @ return CNDEV_UNSUPPORTED_API_VERSION if the API version is too low to be support by the cndev library
* @ return CNDEV_ERROR_INVALID_DEVICE_ID if the number of card which the user selects is not available
*/
EXPORT
cndevRet_t cndevGetECCInfo(cndevECCInfo_t *eccInfo, int devId);

/**
* @ brief get the information of card's power consumption
*
* @ param devId the number of the card which the user selects, starting from 0
* @ param powerInfo will store a pointer to a structure which stores the information of the card's power consumption after the
* function ends
*
* @ return CNDEV_SUCCESS if success
* @ return CNDEV_ERROR_UNINITIALIZED if the user don't call the function named cndevInit beforehand
* @ return CNDEV_ERROR_INVALID_ARGUMENT if the parameter is NULL
* @ return CNDEV_ERROR_UNKNOWN if some fault occurs, when the function calls some system function
* @ return CNDEV_ERROR_INVALID_DEVICE_ID if the number of card which the user selects is not available
* @ return CNDEV_UNSUPPORTED_API_VERSION if the API version is too low to be support by the cndev library
*/
EXPORT
cndevRet_t cndevGetPowerInfo(cndevPowerInfo_t *powerInfo, int devId);

/**
* @ brief get the information of the card's frequency
*
* @ param devId the number of the card which the user selects, starting from 0
* @ param freqInfo will store a pointer to a structure which stores the information of the card's frequency after the function
* ends
*
* @ return CNDEV_SUCCESS if success
* @ return CNDEV_ERROR_UNINITIALIZED if the user don't call the function named cndevInit beforehand
* @ return CNDEV_ERROR_INVALID_ARGUMENT if the parameter is NULL
* @ return CNDEV_ERROR_UNKNOWN if some fault occurs, when the function calls some system function
* @ return CNDEV_ERROR_INVALID_DEVICE_ID if the number of card which the user selects is not available
* @ return CNDEV_UNSUPPORTED_API_VERSION if the API version is too low to be support by the cndev library
*/
EXPORT
cndevRet_t cndevGetFrequencyInfo(cndevFrequencyInfo_t *freqInfo, int devId);

/**
* @ brief get the information of the card's temperature
*
* @ param devId the number of the card which the user selects, starting from 0
* @ param tempInfo will store a pointer to a structure which stores the information of the card's temperature after the function
* ends
*
* @ return CNDEV_SUCCESS if success
* @ return CNDEV_ERROR_UNINITIALIZED if the user don't call the function named cndevInit beforehand
* @ return CNDEV_ERROR_INVALID_ARGUMENT if the parameter is NULL
* @ return CNDEV_ERROR_UNKNOWN if some fault occurs, when the function calls some system function
* @ return CNDEV_UNSUPPORTED_API_VERSION if the API version is too low to be support by the cndev library
* @ return CNDEV_ERROR_INVALID_DEVICE_ID if the number of card which the user selects is not available
*/
EXPORT
cndevRet_t cndevGetTemperatureInfo(cndevTemperatureInfo_t *tempInfo, int devId);

/**
* @ brief get the information of the card's LLC
*
* @ param devId the number of the card which the user selects, starting from 0
* @ param llcInfo will store a pointer to a structure which stores the information of the card's LLC after the function ends
*
* @ return CNDEV_SUCCESS if success
* @ return CNDEV_ERROR_UNINITIALIZED if the user don't call the function named cndevInit beforehand
* @ return CNDEV_ERROR_INVALID_ARGUMENT if the parameter is NULL
* @ return CNDEV_ERROR_UNKNOWN if some fault occurs, when the function calls some system function
* @ return CNDEV_ERROR_INVALID_DEVICE_ID if the number of card which the user selects is not available
* @ return CNDEV_UNSUPPORTED_API_VERSION if the API version is too low to be support by the cndev library
*/
EXPORT
cndevRet_t cndevGetLLCInfo(cndevLLCInfo_t *llcInfo, int devId);

/**
* @ brief get the information of the card's utilization
*
* @ param devId the number of the card which the user selects, starting from 0
* @parm utilInfo will store a pointer to a structure which stores the information of the cars's utilization after the function
* ends
*
* @ return CNDEV_SUCCESS if success
* @ return CNDEV_ERROR_UNINITIALIZED if the user don't call the function named cndevInit beforehand
* @ return CNDEV_ERROR_INVALID_ARGUMENT if the parameter is NULL
* @ return CNDEV_ERROR_UNKNOWN if some fault occurs, when the function calls some system function
* @ return CNDEV_ERROR_INVALID_DEVICE_ID if the number of card which the user selects is not available
* @ return CNDEV_UNSUPPORTED_API_VERSION if the API version is too low to be support by the cndev library
*/
EXPORT
cndevRet_t cndevGetDeviceUtilizationInfo(cndevUtilizationInfo_t *utilInfo, int devId);

/**
* @ brief get the information of the card's fan speed
*
* @ param devId the number of the card which the user selects, starting from 0
* @ param fanInfo will store a pointer to a structure which stores the information of the cards's fan speed after the function
* ends
*
* @ return CNDEV_SUCCESS if success
* @ return CNDEV_ERROR_UNINITIALIZED if the user don't call the function named cndevInit beforehand
* @ return CNDEV_ERROR_INVALID_ARGUMENT if the parameter is NULL
* @ return CNDEV_ERROR_UNKNOWN if some fault occurs, when the function calls some system function
* @ return CNDEV_ERROR_INVALID_DEVICE_ID if the number of card which the user selects is not available
* @ return CNDEV_UNSUPPORTED_API_VERSION if the API version is too low to be support by the cndev library
*/
EXPORT
cndevRet_t cndevGetFanSpeedInfo(cndevFanSpeedInfo_t *fanInfo, int devId);

/**
* @ brief get the information of the card's processes
*
* @ param devId the number of the card which the user selects, starting from 0
* @ param infoCount the size of the space which the user allocates for storing the information of processes.At the same time,the
* parameter will store a pointer to the size of a space which is suit to store all information after the function ends
* @ param procInfo the pointer of the space which the user allocates for saving the information of processes
*
* @ return CNDEV_SUCCESS if success
* @ return CNDEV_ERROR_UNINITIALIZED if the user don't call the function named cndevInit beforehand
* @ return CNDEV_ERROR_INVALID_ARGUMENT if the parameter is NULL
* @ return CNDEV_ERROR_UNKNOWN if some fault occurs, when the function calls some system function
* @ return CNDEV_ERROR_INVALID_DEVICE_ID if the number of card which the user selects is not available
* @ return CNDEV_ERROR_INSUFFICIENT_SPACE if the the space which the space which the user allocates is too little
* @ return CNDEV_UNSUPPORTED_API_VERSION if the API version is too low to be support by the cndev library
*/
EXPORT
cndevRet_t cndevGetProcessInfo(unsigned *infoCount, cndevProcessInfo_t *procInfo, int devId);

/**
*@ brief get the information of the cndev library version
*
* @ param libVerInfo will store a pointer to a structure which stores the information of the cndev library version after the
*function ends
*
* @ return CNDEV_SUCCESS if success
* @ return CNDEV_ERROR_UNINITIALIZED if the user don't call the function named cndevInit beforehand
* @ return CNDEV_ERROR_INVALID_ARGUMENT if the parameter is NULL
* @ return CNDEV_ERROR_UNKNOWN if some fault occurs, when the function calls some system function
* @ return CNDEV_UNSUPPORTED_API_VERSION if the API version is too low to be support by the cndev library
*/
EXPORT
cndevRet_t cndevGetLibVersion(cndevLibVersionInfo_t *libVerInfo);

/**
* @ brief get the count of the card's cores which the user select
*
* @ param devId the number of the card which the user selects, starting from 0
* @ param cardCoreCount will store a pointer to a structure which stores the count of the cards's core after the function ends
*
* @ return CNDEV_SUCCESS if success
* @ return CNDEV_ERROR_UNINITIALIZED if the user don't call the function named cndevInit beforehand
* @ return CNDEV_ERROR_INVALID_ARGUMENT if the parameter is NULL
* @ return CNDEV_ERROR_UNKNOWN if some fault occurs, when the function calls some system function
* @ return CNDEV_ERROR_INVALID_DEVICE_ID if the number of card which the user selects is not available
* @ return CNDEV_UNSUPPORTED_API_VERSION if the API version is too low to be support by the cndev library
*/
EXPORT
cndevRet_t cndevGetCoreCount(cndevCardCoreCount_t *cardCoreCount, int devId);

/**
* @ brief get the count of codec unit
*
* @ param devId the number of the card which the user selects, starting from 0
* @ param codecCount will store a pointer to a structure which stores the count of codec after the function ends
*
* @ return CNDEV_SUCCESS if success
* @ return CNDEV_ERROR_UNINITIALIZED if the user don't call the function named cndevInit beforehand
* @ return CNDEV_ERROR_INVALID_ARGUMENT if the parameter is NULL
* @ return CNDEV_ERROR_UNKNOWN if some fault occurs, when the function calls some system function
* @ return CNDEV_ERROR_INVALID_DEVICE_ID if the number of card which the user selects is not available
* @ return CNDEV_UNSUPPORTED_API_VERSION if the API version is too low to be support by the cndev library
*/
EXPORT
cndevRet_t cndevGetCodecCount(cndevCodecCount_t *codecCount, int devId);

/**
* @ brief get the utilization of codec unit
*
* @ param devId the number of the card which the user selects, starting from 0
* @ param codecUtilization will store a pointer to a structure which stores the utilization of codec after the function ends
*
* @ return CNDEV_SUCCESS if success
* @ return CNDEV_ERROR_UNINITIALIZED if the user don't call the function named cndevInit beforehand
* @ return CNDEV_ERROR_INVALID_ARGUMENT if the parameter is NULL
* @ return CNDEV_ERROR_UNKNOWN if some fault occurs, when the function calls some system function
* @ return CNDEV_ERROR_INVALID_DEVICE_ID if the number of card which the user selects is not available
* @ return CNDEV_UNSUPPORTED_API_VERSION if the API version is too low to be support by the cndev library
*/
EXPORT
cndevRet_t cndevGetCodecUtilization(cndevCodecUtilization_t *codecUtilization, int devId);

/**
* @ brief get the count of the card's clusters which the user select
*
* @ param devId the number of the card which the user selects, starting from 0
* @ param clusCount will store a pointer to a structure which stores the count of the card's clusters after the function ends
*
* @ return CNDEV_SUCCESS if success
* @ return CNDEV_ERROR_UNINITIALIZED if the user don't call the function named cndevInit beforehand
* @ return CNDEV_ERROR_INVALID_ARGUMENT if the parameter is NULL
* @ return CNDEV_ERROR_UNKNOWN if some fault occurs, when the function calls some system function
* @ return CNDEV_ERROR_INVALID_DEVICE_ID if the number of card which the user selects is not available
* @ return CNDEV_UNSUPPORTED_API_VERSION if the API version is too low to be support by the cndev library
*/
EXPORT
cndevRet_t cndevGetClusterCount(cndevCardClusterCount_t *clusCount, int devId);

/**
* @ brief get the lowest MLU driver version which the cndev library supports
* @ param versInfo will store a pointer to a structure which stores the lowest MLU driver version after the function ends
*
*
* @ return CNDEV_SUCCESS if success
* @ return CNDEV_ERROR_UNINITIALIZED if the user don't call the function named cndevInit beforehand
* @ return CNDEV_ERROR_INVALID_ARGUMENT if the parameter is NULL
* @ return CNDEV_ERROR_UNKNOWN if some fault occurs, when the function calls some system function
* @ return CNDEV_UNSUPPORTED_API_VERSION if the API version is too low to be support by the cndev library
*/
EXPORT
cndevRet_t cndevGetLowestSupportDriverVersion(cndevVersionInfo_t *versInfo);

/**
* @ brief get the index of card's name
*
* @ param devId the number of the card which the user selects, starting from 0
* @ param cardName will store a pointer to a structure which stores the index of a card's name after the function ends
*
* @ return CNDEV_SUCCESS if success
* @ return CNDEV_ERROR_UNINITIALIZED if the user don't call the function named cndevInit beforehand
* @ return CNDEV_ERROR_INVALID_ARGUMENT if the parameter is NULL
* @ return CNDEV_ERROR_UNKNOWN if some fault occurs, when the function calls some system function
* @ return CNDEV_ERROR_INVALID_DEVICE_ID if the number of card which the user selects is not available
* @ return CNDEV_UNSUPPORTED_API_VERSION if the API version is too low to be support by the cndev library
*/
EXPORT
cndevRet_t cndevGetCardName(cndevCardName_t *cardName, int devId);

/**
* @ brief translate the index of a card's name to the string of the card's name
*
* @ param cardName the index of a card's name
*
* @ return "Unknown" if the string of the card's name cant't be found, otherwise the string of the card's name will be returned
*/
EXPORT
const char *cndevGetCardNameString(cndevNameEnum_t cardName);

/**
* @ brief translate the index of a card's name to the string of the card's name
*
* @ param devId the number of the card which the user selects, starting from 0
*
* @ return the string of the card's name by device id
*/
EXPORT
const char *getCardNameStringByDevId(int devId);

/**
* @ brief get the SN(serial number) of the card
*
* @ param devId the number of the card which the user selects, starting from 0
* @ param cardSN will store a pointer to a structure which stores the SN of the card after the function ends
*
* @ return CNDEV_SUCCESS if success
* @ return CNDEV_ERROR_UNINITIALIZED if the user don't call the function named cndevInit beforehand
* @ return CNDEV_ERROR_INVALID_ARGUMENT if the parameter is NULL
* @ return CNDEV_ERROR_UNKNOWN if some fault occurs, when the function calls some system function
* @ return CNDEV_ERROR_INVALID_DEVICE_ID if the number of card which the user selects is not available
* @ return CNDEV_UNSUPPORTED_API_VERSION if the API version is too low to be support by the cndev library
*/
EXPORT
cndevRet_t cndevGetCardSN(cndevCardSN_t *cardSN, int devId);

/**
* @ brief get the PCIe throughput,read and write
*
* @ param devId the number of the card which the user selects, starting from 0
* @ param pciethroughput will store PCIe read and write throughput
*
* @ return CNDEV_SUCCESS if success
* @ return CNDEV_ERROR_UNINITIALIZED if the user don't call the function named cndevInit beforehand
* @ return CNDEV_ERROR_INVALID_ARGUMENT if the parameter is NULL
* @ return CNDEV_ERROR_UNKNOWN if some fault occurs, when the function calls some system function
* @ return CNDEV_ERROR_INVALID_DEVICE_ID if the number of card which the user selects is not available
* @ return CNDEV_UNSUPPORTED_API_VERSION if the API version is too low to be support by the cndev library
*/
EXPORT
cndevRet_t cndevGetPCIethroughput(cndevPCIethroughput_t *pciethroughput, int devId);

/**
* @ brief get device related cpu affinity
*
* @ param devId the number of the card which the user selects, starting from 0
* @ param affinity will store cpu affinity info
*
* @ return CNDEV_SUCCESS if success
* @ return CNDEV_ERROR_UNINITIALIZED if the user don't call the function named cndevInit beforehand
* @ return CNDEV_ERROR_INVALID_DEVICE_ID if the number of card which the user selects is not available
* @ return CNDEV_ERROR_INVALID_ARGUMENT if the parameter is NULL
* @ return CNDEV_ERROR_UNKNOWN if some fault occurs, when the function calls some system function
* @ return CNDEV_UNSUPPORTED_API_VERSION if the API version is too low to be support by the cndev library
*/
EXPORT
cndevRet_t cndevGetDeviceAffinity(cndevAffinity_t *affinity, int devId);

/**
* @ brief clear current thread's cpu affinity, set to defalut
*
* @ param devId the number of the card which the user selects, starting from 0
* @ param version cndev_version
*
* @ return CNDEV_SUCCESS if success
* @ return CNDEV_ERROR_UNINITIALIZED if the user don't call the function named cndevInit beforehand
* @ return CNDEV_ERROR_INVALID_DEVICE_ID if the number of card which the user selects is not available
* @ return CNDEV_ERROR_UNKNOWN if some fault occurs, when the function calls some system function
* @ return CNDEV_UNSUPPORTED_API_VERSION if the API version is too low to be support by the cndev library
*/
EXPORT
cndevRet_t cndevClearCurrentThreadAffinity(int version, int devId);

/**
* @ brief set current thread's cpu affinity to device related cpus
*
* @ param devId the number of the card which the user selects, starting from 0
* @ param version cndev_version
*
* @ return CNDEV_SUCCESS if success
* @ return CNDEV_ERROR_UNINITIALIZED if the user don't call the function named cndevInit beforehand
* @ return CNDEV_ERROR_INVALID_DEVICE_ID if the number of card which the user selects is not available
* @ return CNDEV_ERROR_UNKNOWN if some fault occurs, when the function calls some system function
* @ return CNDEV_UNSUPPORTED_API_VERSION if the API version is too low to be support by the cndev library
*/
EXPORT
cndevRet_t cndevSetCurrentThreadAffinity(int version, int devId);

/**
* @ brief get two devices's relationship
*
* @ param devId1 the number of the card1, starting from 0
* @ param devId2 the number of the card2, starting from 0
* @ param relationship will store two devices's relationship
*
* @ return CNDEV_SUCCESS if success
* @ return CNDEV_ERROR_UNINITIALIZED if the user don't call the function named cndevInit beforehand
* @ return CNDEV_ERROR_INVALID_DEVICE_ID if the number of card which the user selects is not available
* @ return CNDEV_ERROR_INVALID_ARGUMENT if the parameter is NULL
* @ return CNDEV_ERROR_UNKNOWN if some fault occurs, when the function calls some system function
* @ return CNDEV_UNSUPPORTED_API_VERSION if the API version is too low to be support by the cndev library
*/
EXPORT
cndevRet_t cndevTopologyGetRelationship(cndevTopologyRelationship_t *relationship, int devId1, int devId2);

/**
* @ brief get devid nearest devices by relationship
*
* @ param devId the number of the card, starting from 0
* @ param version cndev_version
* @ param count devIdArray's size
* @ param devIdArray will store related devices's id
* @ param rel specified relationship
*
* @ return CNDEV_SUCCESS if success
* @ return CNDEV_ERROR_UNINITIALIZED if the user don't call the function named cndevInit beforehand
* @ return CNDEV_ERROR_INVALID_ARGUMENT if the parameter is NULL
* @ return CNDEV_ERROR_INVALID_DEVICE_ID if the number of card which the user selects is not available
* @ return CNDEV_ERROR_UNKNOWN if some fault occurs, when the function calls some system function
* @ return CNDEV_UNSUPPORTED_API_VERSION if the API version is too low to be support by the cndev library
* @ return CNDEV_ERROR_INSUFFICIENT_SPACE if the the space which the space which the user allocates is too little
*/
EXPORT
cndevRet_t cndevTopologyGetNearestDevices(int version, cndevTopologyRelationshipEnum_t rel, __uint64_t *count,
__uint64_t *devIdArray, int devId);

/**
* @ brief get two devices's relationship
*
* @ param cpuId specified cpu id
* @ param version cndev_version
* @ param count devIdArray's size
* @ param devIdArray will store related devices's id
*
* @ return CNDEV_SUCCESS if success
* @ return CNDEV_ERROR_UNINITIALIZED if the user don't call the function named cndevInit beforehand
* @ return CNDEV_ERROR_INVALID_ARGUMENT if the parameter is NULL
* @ return CNDEV_ERROR_UNKNOWN if some fault occurs, when the function calls some system function
* @ return CNDEV_UNSUPPORTED_API_VERSION if the API version is too low to be support by the cndev library
* @ return CNDEV_ERROR_INSUFFICIENT_SPACE if the the space which the space which the user allocates is too little
*/
EXPORT
cndevRet_t cndevTopologyGetCpuRelatedDevices(int version, int cpuId, __uint64_t *count, __uint64_t *devidArray);

/**
* @ brief get the current information of PCI
*
* @ param devId the number of the card which the user selects, starting from 0
* @ param currentPCIInfo will stores a pointer to a structure which stores the current information of PCI
after the function ends
*
* @ return CNDEV_SUCCESS if success
* @ return CNDEV_ERROR_UNINITIALIZED if the user don't call the function named cndevInit beforehand
* @ return CNDEV_ERROR_INVALID_ARGUMENT if the parameter is NULL
* @ return CNDEV_ERROR_UNKNOWN if some fault occurs, when the function calls some system function
* @ return CNDEV_ERROR_INVALID_DEVICE_ID if the number of card which the user selects is not available
* @ return CNDEV_UNSUPPORTED_API_VERSION if the API version is too low to be support by the cndev library
*/
EXPORT
cndevRet_t cndevGetCurrentPCIInfo(cndevCurrentPCIInfo_t *currentPCIInfo, int devId);

/**
* @ brief get two nodes's relationship
*
* @ param node1 the topology node
* @ param node2 the topology node
* @ param relationship will store two devices's relationship
*
* @ return CNDEV_SUCCESS if success
* @ return CNDEV_ERROR_UNINITIALIZED if the user don't call the function named cndevInit beforehand
* @ return CNDEV_ERROR_INVALID_DEVICE_ID if the number of card which the user selects is not available
* @ return CNDEV_ERROR_INVALID_ARGUMENT if the parameter is NULL
* @ return CNDEV_ERROR_UNKNOWN if some fault occurs, when the function calls some system function
* @ return CNDEV_UNSUPPORTED_API_VERSION if the API version is too low to be support by the cndev library
*/
EXPORT
cndevRet_t cndevTopologyGetRelationshipByNode(cndevTopologyRelationship_t *relationship, cndevTopologyNode_t *node1,
cndevTopologyNode_t *node2);

/**
* @ brief get a topology tree node by bdf
*
* @ param version cndev version
* @ param treeNode a target topolog tree node
* @ param domain the domain number of pci device
* @ param bus the bus bus number of pci device
* @ param device the slot number of pci device
* @ param function the function number of pci device
*
* @ return CNDEV_SUCCESS if success
* @ return CNDEV_ERROR_UNINITIALIZED if the user don't call the function named cndevInit beforehand
* @ return CNDEV_ERROR_INVALID_ARGUMENT if the parameter is NULL
* @ return CNDEV_ERROR_UNKNOWN if some fault occurs, when the function calls some system function
* @ return CNDEV_UNSUPPORTED_API_VERSION if the API version is too low to be support by the cndev library
*/
EXPORT
cndevRet_t cndevGetNodeByBDF(int version, cndevTopologyNode_t **treeNode, unsigned int domain, unsigned int bus,
unsigned int device, unsigned int function);

/**
* @ brief get the device id by bdf
*
* @ param version cndev version
* @ param devId a target device id
* @ param domain the domain number of pci device
* @ param bus the bus bus number of pci device
* @ param device the slot number of pci device
* @ param function the function number of pci device
*
* @ return CNDEV_SUCCESS if success
* @ return CNDEV_ERROR_UNINITIALIZED if the user don't call the function named cndevInit beforehand
* @ return CNDEV_ERROR_INVALID_ARGUMENT if the parameter is NULL
* @ return CNDEV_ERROR_UNKNOWN if some fault occurs, when the function calls some system function
* @ return CNDEV_UNSUPPORTED_API_VERSION if the API version is too low to be support by the cndev library
*/
EXPORT
cndevRet_t cndevGetDevIdByBDF(int version, int *devId, unsigned int domain, unsigned int bus, unsigned int device,
unsigned int function);

/**
* @ brief get a topology tree node by device id
*
* @ param version cndev version
* @ param treeNode a target topolog tree node
* @ param devId the device id
*
* @ return CNDEV_SUCCESS if success
* @ return CNDEV_ERROR_UNINITIALIZED if the user don't call the function named cndevInit beforehand
* @ return CNDEV_ERROR_INVALID_ARGUMENT if the parameter is NULL
* @ return CNDEV_ERROR_UNKNOWN if some fault occurs, when the function calls some system function
* @ return CNDEV_UNSUPPORTED_API_VERSION if the API version is too low to be support by the cndev library
*/
EXPORT
cndevRet_t cndevGetNodeByDevId(int version, cndevTopologyNode_t **treeNode, int devId);

/**
* @ brief get the virtual root node of topology tree
*
* @ param version cndev version
* @ param root the virtual root node of topology tree
*
* @ return CNDEV_SUCCESS if success
* @ return CNDEV_ERROR_UNINITIALIZED if the user don't call the function named cndevInit beforehand
* @ return CNDEV_ERROR_INVALID_ARGUMENT if the parameter is NULL
* @ return CNDEV_ERROR_UNKNOWN if some fault occurs, when the function calls some system function
* @ return CNDEV_UNSUPPORTED_API_VERSION if the API version is too low to be support by the cndev library
*/
EXPORT
cndevRet_t cndevTopologyGetVirtualRootNode(int version, cndevTopologyNode_t **root);

/**
* @ brief traverse the topology tree with a callback function
*
* @ param version cndev version
* @ param callback the name of callback function, traverse the topology tree while the return value of callback function is 1
* while the return value of callback function is zero, the traverse tree function break
* @ param userdata the parameter of callback function
*
* @ return CNDEV_SUCCESS if success
* @ return CNDEV_ERROR_UNINITIALIZED if the user don't call the function named cndevInit beforehand
* @ return CNDEV_ERROR_INVALID_ARGUMENT if the parameter is NULL
* @ return CNDEV_ERROR_UNKNOWN if some fault occurs, when the function calls some system function
* @ return CNDEV_UNSUPPORTED_API_VERSION if the API version is too low to be support by the cndev library
*/
EXPORT
cndevRet_t cndevTopologyTraverseTree(int version, CNDEV_TRAVERSE_CALLBACK callback, void *userdata);

/**
* @ brief get the capability info of tree node
*
* @ param capability the capability info of tree node
* @ param treeNode a target tree node
*
* @ return CNDEV_SUCCESS if success
* @ return CNDEV_ERROR_UNINITIALIZED if the user don't call the function named cndevInit beforehand
* @ return CNDEV_ERROR_INVALID_ARGUMENT if the parameter is NULL
* @ return CNDEV_ERROR_UNKNOWN if some fault occurs, when the function calls some system function
* @ return CNDEV_UNSUPPORTED_API_VERSION if the API version is too low to be support by the cndev library
*/
EXPORT
cndevRet_t cndevGetNodeCapabilityInfo(cndevCapabilityInfo_t *capability, cndevTopologyNode_t *treeNode);

/**
* @ brief get tree nodes by device name
*
* @ param deviceName the name of pci device
* @ param version cndev_version
* @ param count devIdArray's size
* @ param nodeArray will store related devices's node
*
* @ return CNDEV_SUCCESS if success
* @ return CNDEV_ERROR_UNINITIALIZED if the user don't call the function named cndevInit beforehand
* @ return CNDEV_ERROR_INVALID_ARGUMENT if the parameter is NULL
* @ return CNDEV_ERROR_INVALID_DEVICE_ID if the number of card which the user selects is not available
* @ return CNDEV_ERROR_UNKNOWN if some fault occurs, when the function calls some system function
* @ return CNDEV_UNSUPPORTED_API_VERSION if the API version is too low to be support by the cndev library
* @ return CNDEV_ERROR_INSUFFICIENT_SPACE if the the space which the space which the user allocates is too little
*/
EXPORT
cndevRet_t cndevGetNodeByDeviceName(int version, int *count, cndevTopologyNode_t *nodeArray, const char *deviceName);

/**
* @ brief get the healthy state of the card
*
* @ param devId the number of the card which the user selects, starting from 0
* @ param cardHealthState will stores a pointer to a structure which stores the HP of the card after the function ends, 1 means health, 0 means sick
*
* @ return CNDEV_SUCCESS if success
* @ return CNDEV_ERROR_UNINITIALIZED if the user don't call the function named cndevInit beforehand
* @ return CNDEV_ERROR_INVALID_ARGUMENT if the parameter is NULL
* @ return CNDEV_ERROR_UNKNOWN if some fault occurs, when the function calls some system function
* @ return CNDEV_ERROR_INVALID_DEVICE_ID if the number of card which the user selects is not available
* @ return CNDEV_UNSUPPORTED_API_VERSION if the API version is too low to be support by the cndev library
*/
EXPORT
cndevRet_t cndevGetCardHealthState(cndevCardHealthState_t* cardHealthState, int devId);

/**
* @ brief get the pcie switch link speed, need sudo
*
* @ param devId the number of the card which the user selects, starting from 0
* @ param linkspeed will stores a pointer to a structure which stores the pcie switch link speed
*
* @ return CNDEV_SUCCESS if success
* @ return CNDEV_ERROR_UNINITIALIZED if the user don't call the function named cndevInit beforehand
* @ return CNDEV_ERROR_INVALID_ARGUMENT if the parameter is NULL
* @ return CNDEV_ERROR_UNKNOWN if some fault occurs, when the function calls some system function
* @ return CNDEV_ERROR_INVALID_DEVICE_ID if the number of card which the user selects is not available
* @ return CNDEV_UNSUPPORTED_API_VERSION if the API version is too low to be support by the cndev library
*/
EXPORT
cndevRet_t cndevGetLowestLinkSpeed(cndevLinkSpeed_t* linkspeed, int devId);

/**
* @ brief get the jpu codec utilization
*
* @ param devId the number of the card which the user selects, starting from 0
* @ param jpu_util will stores a pointer to a structure which stores the jpu codec utilization
*
* @ return CNDEV_SUCCESS if success
* @ return CNDEV_ERROR_UNINITIALIZED if the user don't call the function named cndevInit beforehand
* @ return CNDEV_ERROR_INVALID_ARGUMENT if the parameter is NULL
* @ return CNDEV_ERROR_UNKNOWN if some fault occurs, when the function calls some system function
* @ return CNDEV_ERROR_INVALID_DEVICE_ID if the number of card which the user selects is not available
* @ return CNDEV_UNSUPPORTED_API_VERSION if the API version is too low to be support by the cndev library
*/
EXPORT
cndevRet_t cndevGetImageCodecUtilization(cndevImageCodecUtilization_t* jpuutil, int devId);

/**
* @ brief get the vpu codec utilization
*
* @ param devId the number of the card which the user selects, starting from 0
* @ param vpu_util will stores a pointer to a structure which stores the vpu codec utilization
*
* @ return CNDEV_SUCCESS if success
* @ return CNDEV_ERROR_UNINITIALIZED if the user don't call the function named cndevInit beforehand
* @ return CNDEV_ERROR_INVALID_ARGUMENT if the parameter is NULL
* @ return CNDEV_ERROR_UNKNOWN if some fault occurs, when the function calls some system function
* @ return CNDEV_ERROR_INVALID_DEVICE_ID if the number of card which the user selects is not available
* @ return CNDEV_UNSUPPORTED_API_VERSION if the API version is too low to be support by the cndev library
*/
EXPORT
cndevRet_t cndevGetVideoCodecUtilization(cndevVideoCodecUtilization_t* vpuutil, int devId);

/**
* @ brief get the fast alloc information
*
* @ param devId the number of the card which the user selects, starting from 0
* @ param fastalloc will stores a pointer to a structure which stores the fast alloc total memory and free memory
*
* @ return CNDEV_SUCCESS if success
* @ return CNDEV_ERROR_UNINITIALIZED if the user don't call the function named cndevInit beforehand
* @ return CNDEV_ERROR_INVALID_ARGUMENT if the parameter is NULL
* @ return CNDEV_ERROR_UNKNOWN if some fault occurs, when the function calls some system function
* @ return CNDEV_ERROR_INVALID_DEVICE_ID if the number of card which the user selects is not available
* @ return CNDEV_UNSUPPORTED_API_VERSION if the API version is too low to be support by the cndev library
*/
EXPORT
cndevRet_t cndevGetFastAlloc(cndevFastAlloc_t* fastalloc, int devId);

/**
* @ brief get the NUMA node id of tree node
*
* @ param numaNodeId the NUMA node id of tree node
* @ param treeNode a target tree node
*
* @ return CNDEV_SUCCESS if success
* @ return CNDEV_ERROR_UNINITIALIZED if the user don't call the function named cndevInit beforehand
* @ return CNDEV_ERROR_INVALID_ARGUMENT if the parameter is NULL
* @ return CNDEV_ERROR_UNKNOWN if some fault occurs, when the function calls some system function
* @ return CNDEV_UNSUPPORTED_API_VERSION if the API version is too low to be support by the cndev library
*/
EXPORT
cndevRet_t cndevGetNUMANodeIdByTopologyNode(cndevNUMANodeId_t* numaNodeId, cndevTopologyNode_t* treeNode);

/**
* @ brief get the scaler utilization
*
* @ param devId the number of the card which the user selects, starting from 0
* @ param scaler_util will stores a pointer to a structure which stores the scaler utilization
*
* @ return CNDEV_SUCCESS if success
* @ return CNDEV_ERROR_UNINITIALIZED if the user don't call the function named cndevInit beforehand
* @ return CNDEV_ERROR_INVALID_ARGUMENT if the parameter is NULL
* @ return CNDEV_ERROR_UNKNOWN if some fault occurs, when the function calls some system function
* @ return CNDEV_ERROR_INVALID_DEVICE_ID if the number of card which the user selects is not available
* @ return CNDEV_UNSUPPORTED_API_VERSION if the API version is too low to be support by the cndev library
*/
EXPORT
cndevRet_t cndevGetScalerUtilization(cndevScalerUtilization_t* scalerutil, int devId);

/**
* @ brief get the codec turbo mode
*
* @ param devId the number of the card which the user selects, starting from 0
* @ param codecTurbo will stores a pointer to a structure which stores the codec turbo information
*
* @ return CNDEV_SUCCESS if success
* @ return CNDEV_ERROR_UNINITIALIZED if the user don't call the function named cndevInit beforehand
* @ return CNDEV_ERROR_INVALID_ARGUMENT if the parameter is NULL
* @ return CNDEV_ERROR_UNKNOWN if some fault occurs, when the function calls some system function
* @ return CNDEV_ERROR_INVALID_DEVICE_ID if the number of card which the user selects is not available
* @ return CNDEV_UNSUPPORTED_API_VERSION if the API version is too low to be support by the cndev library
*/
EXPORT
cndevRet_t cndevGetCodecTurbo(cndevCodecTurbo_t* codecTurbo, int devId);

/**
* @ brief get the memorydie count
*
* @ param devId the number of the card which the user selects, starting from 0
* @ param memorydiecount will stores a pointer to a structure which stores the memorydie count
*
* @ return CNDEV_SUCCESS if success
* @ return CNDEV_ERROR_UNINITIALIZED if the user don't call the function named cndevInit beforehand
* @ return CNDEV_ERROR_INVALID_ARGUMENT if the parameter is NULL
* @ return CNDEV_ERROR_UNKNOWN if some fault occurs, when the function calls some system function
* @ return CNDEV_ERROR_INVALID_DEVICE_ID if the number of card which the user selects is not available
* @ return CNDEV_UNSUPPORTED_API_VERSION if the API version is too low to be support by the cndev library
*/
EXPORT
cndevRet_t cndevGetMemoryDieCount(cndevCardMemoryDieCount_t* memorydiecount, int devId);

/**
* @ brief get the QSFP-DD status
*
* @ param devId the number of the card which the user selects, starting from 0
* @ param qddstatus will stores a pointer to a structure which stores the QSFP-DD status
*
* @ return CNDEV_SUCCESS if success
* @ return CNDEV_ERROR_UNINITIALIZED if the user don't call the function named cndevInit beforehand
* @ return CNDEV_ERROR_INVALID_ARGUMENT if the parameter is NULL
* @ return CNDEV_ERROR_UNKNOWN if some fault occurs, when the function calls some system function
* @ return CNDEV_ERROR_INVALID_DEVICE_ID if the number of card which the user selects is not available
* @ return CNDEV_UNSUPPORTED_API_VERSION if the API version is too low to be support by the cndev library
*/
EXPORT
cndevRet_t cndevGetQsfpddStatus(cndevQsfpddStatus_t* qddstatus, int devId);

/**
* @ brief get the cclink version
*
* @ param version will stores a pointer to a structure which stores the cclink version
* @ param devId the number of the card which the user selects, starting from 0
* @ param link the number of the port which the user selects, starting from 0
*
* @ return CNDEV_SUCCESS if success
* @ return CNDEV_ERROR_UNINITIALIZED if the user don't call the function named cndevInit beforehand
* @ return CNDEV_ERROR_INVALID_ARGUMENT if the parameter is NULL
* @ return CNDEV_ERROR_UNKNOWN if some fault occurs, when the function calls some system function
* @ return CNDEV_ERROR_INVALID_DEVICE_ID if the number of card which the user selects is not available
* @ return CNDEV_UNSUPPORTED_API_VERSION if the API version is too low to be support by the cndev library
* @ return CNDEV_ERROR_INVALID_LINK if the number of link which the user selects is not available
*/
EXPORT
cndevRet_t cndevGetCclinkVersion(cndevCclinkVersion_t *version, int devId, int link);
/**
* @ brief get the cclink status
*
* @ param status will stores a pointer to a structure which stores the cclink status
* @ param devId the number of the card which the user selects, starting from 0
* @ param link the number of the port which the user selects, starting from 0
*
* @ return CNDEV_SUCCESS if success
* @ return CNDEV_ERROR_UNINITIALIZED if the user don't call the function named cndevInit beforehand
* @ return CNDEV_ERROR_INVALID_ARGUMENT if the parameter is NULL
* @ return CNDEV_ERROR_UNKNOWN if some fault occurs, when the function calls some system function
* @ return CNDEV_ERROR_INVALID_DEVICE_ID if the number of card which the user selects is not available
* @ return CNDEV_UNSUPPORTED_API_VERSION if the API version is too low to be support by the cndev library
* @ return CNDEV_ERROR_INVALID_LINK if the number of link which the user selects is not available
*/
EXPORT
cndevRet_t cndevGetCclinkStatus(cndevCclinkStatus_t *status, int devId, int link);
/**
* @ brief get the cclink speed
*
* @ param speed will stores a pointer to a structure which stores the cclink speed
* @ param devId the number of the card which the user selects, starting from 0
* @ param link the number of the port which the user selects, starting from 0
*
* @ return CNDEV_SUCCESS if success
* @ return CNDEV_ERROR_UNINITIALIZED if the user don't call the function named cndevInit beforehand
* @ return CNDEV_ERROR_INVALID_ARGUMENT if the parameter is NULL
* @ return CNDEV_ERROR_UNKNOWN if some fault occurs, when the function calls some system function
* @ return CNDEV_ERROR_INVALID_DEVICE_ID if the number of card which the user selects is not available
* @ return CNDEV_UNSUPPORTED_API_VERSION if the API version is too low to be support by the cndev library
* @ return CNDEV_ERROR_INVALID_LINK if the number of link which the user selects is not available
*/
EXPORT
cndevRet_t cndevGetCclinkSpeedInfo(cndevCclinkSpeed_t *speed, int devId, int link);
/**
* @ brief get the cclink capability
*
* @ param capability will stores a pointer to a structure which stores the cclink capability
* @ param devId the number of the card which the user selects, starting from 0
* @ param link the number of the port which the user selects, starting from 0
*
* @ return CNDEV_SUCCESS if success
* @ return CNDEV_ERROR_UNINITIALIZED if the user don't call the function named cndevInit beforehand
* @ return CNDEV_ERROR_INVALID_ARGUMENT if the parameter is NULL
* @ return CNDEV_ERROR_UNKNOWN if some fault occurs, when the function calls some system function
* @ return CNDEV_ERROR_INVALID_DEVICE_ID if the number of card which the user selects is not available
* @ return CNDEV_UNSUPPORTED_API_VERSION if the API version is too low to be support by the cndev library
* @ return CNDEV_ERROR_INVALID_LINK if the number of link which the user selects is not available
*/
EXPORT
cndevRet_t cndevGetCclinkCapability(cndevCclinkCapability_t *capability, int devId, int link);
/**
* @ brief get the cclink counter information
*
* @ param count will stores a pointer to a structure which stores the cclink counter information
* @ param devId the number of the card which the user selects, starting from 0
* @ param link the number of the port which the user selects, starting from 0
*
* @ return CNDEV_SUCCESS if success
* @ return CNDEV_ERROR_UNINITIALIZED if the user don't call the function named cndevInit beforehand
* @ return CNDEV_ERROR_INVALID_ARGUMENT if the parameter is NULL
* @ return CNDEV_ERROR_UNKNOWN if some fault occurs, when the function calls some system function
* @ return CNDEV_ERROR_INVALID_DEVICE_ID if the number of card which the user selects is not available
* @ return CNDEV_UNSUPPORTED_API_VERSION if the API version is too low to be support by the cndev library
* @ return CNDEV_ERROR_INVALID_LINK if the number of link which the user selects is not available
*/
EXPORT
cndevRet_t cndevGetCclinkCounter(cndevCclinkCounter_t *count, int devId, int link);
/**
* @ brief reset the cclink counter
*
* @ param setcount will stores a pointer to a structure which stores the cclink counter
* @ param devId the number of the card which the user selects, starting from 0
* @ param link the number of the port which the user selects, starting from 0
*
* @ return CNDEV_SUCCESS if success
* @ return CNDEV_ERROR_UNINITIALIZED if the user don't call the function named cndevInit beforehand
* @ return CNDEV_ERROR_INVALID_ARGUMENT if the parameter is NULL
* @ return CNDEV_ERROR_UNKNOWN if some fault occurs, when the function calls some system function
* @ return CNDEV_ERROR_INVALID_DEVICE_ID if the number of card which the user selects is not available
* @ return CNDEV_UNSUPPORTED_API_VERSION if the API version is too low to be support by the cndev library
* @ return CNDEV_ERROR_INVALID_LINK if the number of link which the user selects is not available
*/
EXPORT
cndevRet_t cndevResetCclinkCounter(cndevCclinkSetCounter_t *setcount, int devId, int link);
/**
* @ brief get the cclink remote information
*
* @ param remoteinfo will stores a pointer to a structure which stores the cclink remote information
* @ param devId the number of the card which the user selects, starting from 0
* @ param link the number of the port which the user selects, starting from 0
*
* @ return CNDEV_SUCCESS if success
* @ return CNDEV_ERROR_UNINITIALIZED if the user don't call the function named cndevInit beforehand
* @ return CNDEV_ERROR_INVALID_ARGUMENT if the parameter is NULL
* @ return CNDEV_ERROR_UNKNOWN if some fault occurs, when the function calls some system function
* @ return CNDEV_ERROR_INVALID_DEVICE_ID if the number of card which the user selects is not available
* @ return CNDEV_UNSUPPORTED_API_VERSION if the API version is too low to be support by the cndev library
* @ return CNDEV_ERROR_INVALID_LINK if the number of link which the user selects is not available
*/
EXPORT
cndevRet_t cndevGetCclinkRemoteInfo(cndevCclinkRemoteInfo_t *remoteinfo, int devId, int link);
/**
* @ brief get the cclink bandwidth utilization
*
* @ param bandwidth will stores a pointer to a structure which stores the cclink bandwidth utilization
* @ param devId the number of the card which the user selects, starting from 0
* @ param link the number of the port which the user selects, starting from 0
*
* @ return CNDEV_SUCCESS if success
* @ return CNDEV_ERROR_UNINITIALIZED if the user don't call the function named cndevInit beforehand
* @ return CNDEV_ERROR_INVALID_ARGUMENT if the parameter is NULL
* @ return CNDEV_ERROR_UNKNOWN if some fault occurs, when the function calls some system function
* @ return CNDEV_ERROR_INVALID_DEVICE_ID if the number of card which the user selects is not available
* @ return CNDEV_UNSUPPORTED_API_VERSION if the API version is too low to be support by the cndev library
* @ return CNDEV_ERROR_INVALID_LINK if the number of link which the user selects is not available
*/
EXPORT
cndevRet_t cndevGetCclinkBandwidthUtil(cndevCclinkBandwidthUtil_t *bandwidth, int devId, int link);
/**
* @ brief get the cclink devices' sn
*
* @ param devinfo will stores a pointer to a structure which stores the cclink devices sn
* @ param devId the number of the card which the user selects, starting from 0
*
* @ return CNDEV_SUCCESS if success
* @ return CNDEV_ERROR_UNINITIALIZED if the user don't call the function named cndevInit beforehand
* @ return CNDEV_ERROR_INVALID_ARGUMENT if the parameter is NULL
* @ return CNDEV_ERROR_UNKNOWN if some fault occurs, when the function calls some system function
* @ return CNDEV_ERROR_INVALID_DEVICE_ID if the number of card which the user selects is not available
* @ return CNDEV_UNSUPPORTED_API_VERSION if the API version is too low to be support by the cndev library
*/
EXPORT
cndevRet_t cndevGetCclinkDevSN(cndevCclinkDevSN_t *devinfo, int devId);
/**
* @ brief get the NUMA node id of tree node by device ID
*
* @ param numaNodeId the NUMA node id of tree node
* @ param devId the number of the card which the user selects, starting from 0
*
* @ return CNDEV_SUCCESS if success
* @ return CNDEV_ERROR_UNINITIALIZED if the user don't call the function named cndevInit beforehand
* @ return CNDEV_ERROR_INVALID_ARGUMENT if the parameter is NULL
* @ return CNDEV_ERROR_UNKNOWN if some fault occurs, when the function calls some system function
* @ return CNDEV_UNSUPPORTED_API_VERSION if the API version is too low to be support by the cndev library
*/
EXPORT
cndevRet_t cndevGetNUMANodeIdByDevId(cndevNUMANodeId_t* numaNodeId, int devId);

#if defined(__cplusplus)
}
#endif /*__cplusplus*/
#endif // INCLUDE_CNDEV_H_

+ 0
- 750
third-party/cambricon-k8s-device-plugin/device-plugin/pkg/cndev/mock/cJSON.c View File

@@ -1,750 +0,0 @@
/*
Copyright (c) 2009 Dave Gamble

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

/* cJSON */
/* JSON parser in C. */

#include <string.h>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <float.h>
#include <limits.h>
#include <ctype.h>
#include "cJSON.h"

static const char *ep;

const char *cJSON_GetErrorPtr(void) {return ep;}

static int cJSON_strcasecmp(const char *s1,const char *s2)
{
if (!s1) return (s1==s2)?0:1;if (!s2) return 1;
for(; tolower(*s1) == tolower(*s2); ++s1, ++s2) if(*s1 == 0) return 0;
return tolower(*(const unsigned char *)s1) - tolower(*(const unsigned char *)s2);
}

static void *(*cJSON_malloc)(size_t sz) = malloc;
static void (*cJSON_free)(void *ptr) = free;

static char* cJSON_strdup(const char* str)
{
size_t len;
char* copy;

len = strlen(str) + 1;
if (!(copy = (char*)cJSON_malloc(len))) return 0;
memcpy(copy,str,len);
return copy;
}

void cJSON_InitHooks(cJSON_Hooks* hooks)
{
if (!hooks) { /* Reset hooks */
cJSON_malloc = malloc;
cJSON_free = free;
return;
}

cJSON_malloc = (hooks->malloc_fn)?hooks->malloc_fn:malloc;
cJSON_free = (hooks->free_fn)?hooks->free_fn:free;
}

/* Internal constructor. */
static cJSON *cJSON_New_Item(void)
{
cJSON* node = (cJSON*)cJSON_malloc(sizeof(cJSON));
if (node) memset(node,0,sizeof(cJSON));
return node;
}

/* Delete a cJSON structure. */
void cJSON_Delete(cJSON *c)
{
cJSON *next;
while (c)
{
next=c->next;
if (!(c->type&cJSON_IsReference) && c->child) cJSON_Delete(c->child);
if (!(c->type&cJSON_IsReference) && c->valuestring) cJSON_free(c->valuestring);
if (!(c->type&cJSON_StringIsConst) && c->string) cJSON_free(c->string);
cJSON_free(c);
c=next;
}
}

/* Parse the input text to generate a number, and populate the result into item. */
static const char *parse_number(cJSON *item,const char *num)
{
double n=0,sign=1,scale=0;int subscale=0,signsubscale=1;

if (*num=='-') sign=-1,num++; /* Has sign? */
if (*num=='0') num++; /* is zero */
if (*num>='1' && *num<='9') do n=(n*10.0)+(*num++ -'0'); while (*num>='0' && *num<='9'); /* Number? */
if (*num=='.' && num[1]>='0' && num[1]<='9') {num++; do n=(n*10.0)+(*num++ -'0'),scale--; while (*num>='0' && *num<='9');} /* Fractional part? */
if (*num=='e' || *num=='E') /* Exponent? */
{ num++;if (*num=='+') num++; else if (*num=='-') signsubscale=-1,num++; /* With sign? */
while (*num>='0' && *num<='9') subscale=(subscale*10)+(*num++ - '0'); /* Number? */
}

n=sign*n*pow(10.0,(scale+subscale*signsubscale)); /* number = +/- number.fraction * 10^+/- exponent */
item->valuedouble=n;
item->valueint=(int)n;
item->type=cJSON_Number;
return num;
}

static int pow2gt (int x) { --x; x|=x>>1; x|=x>>2; x|=x>>4; x|=x>>8; x|=x>>16; return x+1; }

typedef struct {char *buffer; int length; int offset; } printbuffer;

static char* ensure(printbuffer *p,int needed)
{
char *newbuffer;int newsize;
if (!p || !p->buffer) return 0;
needed+=p->offset;
if (needed<=p->length) return p->buffer+p->offset;

newsize=pow2gt(needed);
newbuffer=(char*)cJSON_malloc(newsize);
if (!newbuffer) {cJSON_free(p->buffer);p->length=0,p->buffer=0;return 0;}
if (newbuffer) memcpy(newbuffer,p->buffer,p->length);
cJSON_free(p->buffer);
p->length=newsize;
p->buffer=newbuffer;
return newbuffer+p->offset;
}

static int update(printbuffer *p)
{
char *str;
if (!p || !p->buffer) return 0;
str=p->buffer+p->offset;
return p->offset+strlen(str);
}

/* Render the number nicely from the given item into a string. */
static char *print_number(cJSON *item,printbuffer *p)
{
char *str=0;
double d=item->valuedouble;
if (d==0)
{
if (p) str=ensure(p,2);
else str=(char*)cJSON_malloc(2); /* special case for 0. */
if (str) strcpy(str,"0");
}
else if (fabs(((double)item->valueint)-d)<=DBL_EPSILON && d<=INT_MAX && d>=INT_MIN)
{
if (p) str=ensure(p,21);
else str=(char*)cJSON_malloc(21); /* 2^64+1 can be represented in 21 chars. */
if (str) sprintf(str,"%d",item->valueint);
}
else
{
if (p) str=ensure(p,64);
else str=(char*)cJSON_malloc(64); /* This is a nice tradeoff. */
if (str)
{
if (fabs(floor(d)-d)<=DBL_EPSILON && fabs(d)<1.0e60)sprintf(str,"%.0f",d);
else if (fabs(d)<1.0e-6 || fabs(d)>1.0e9) sprintf(str,"%e",d);
else sprintf(str,"%f",d);
}
}
return str;
}

static unsigned parse_hex4(const char *str)
{
unsigned h=0;
if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;
h=h<<4;str++;
if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;
h=h<<4;str++;
if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;
h=h<<4;str++;
if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;
return h;
}

/* Parse the input text into an unescaped cstring, and populate item. */
static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
static const char *parse_string(cJSON *item,const char *str)
{
const char *ptr=str+1;char *ptr2;char *out;int len=0;unsigned uc,uc2;
if (*str!='\"') {ep=str;return 0;} /* not a string! */
while (*ptr!='\"' && *ptr && ++len) if (*ptr++ == '\\') ptr++; /* Skip escaped quotes. */
out=(char*)cJSON_malloc(len+1); /* This is how long we need for the string, roughly. */
if (!out) return 0;
ptr=str+1;ptr2=out;
while (*ptr!='\"' && *ptr)
{
if (*ptr!='\\') *ptr2++=*ptr++;
else
{
ptr++;
switch (*ptr)
{
case 'b': *ptr2++='\b'; break;
case 'f': *ptr2++='\f'; break;
case 'n': *ptr2++='\n'; break;
case 'r': *ptr2++='\r'; break;
case 't': *ptr2++='\t'; break;
case 'u': /* transcode utf16 to utf8. */
uc=parse_hex4(ptr+1);ptr+=4; /* get the unicode char. */

if ((uc>=0xDC00 && uc<=0xDFFF) || uc==0) break; /* check for invalid. */

if (uc>=0xD800 && uc<=0xDBFF) /* UTF16 surrogate pairs. */
{
if (ptr[1]!='\\' || ptr[2]!='u') break; /* missing second-half of surrogate. */
uc2=parse_hex4(ptr+3);ptr+=6;
if (uc2<0xDC00 || uc2>0xDFFF) break; /* invalid second-half of surrogate. */
uc=0x10000 + (((uc&0x3FF)<<10) | (uc2&0x3FF));
}

len=4;if (uc<0x80) len=1;else if (uc<0x800) len=2;else if (uc<0x10000) len=3; ptr2+=len;
switch (len) {
case 4: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
case 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
case 2: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
case 1: *--ptr2 =(uc | firstByteMark[len]);
}
ptr2+=len;
break;
default: *ptr2++=*ptr; break;
}
ptr++;
}
}
*ptr2=0;
if (*ptr=='\"') ptr++;
item->valuestring=out;
item->type=cJSON_String;
return ptr;
}

/* Render the cstring provided to an escaped version that can be printed. */
static char *print_string_ptr(const char *str,printbuffer *p)
{
const char *ptr;char *ptr2,*out;int len=0,flag=0;unsigned char token;
for (ptr=str;*ptr;ptr++) flag|=((*ptr>0 && *ptr<32)||(*ptr=='\"')||(*ptr=='\\'))?1:0;
if (!flag)
{
len=ptr-str;
if (p) out=ensure(p,len+3);
else out=(char*)cJSON_malloc(len+3);
if (!out) return 0;
ptr2=out;*ptr2++='\"';
strcpy(ptr2,str);
ptr2[len]='\"';
ptr2[len+1]=0;
return out;
}
if (!str)
{
if (p) out=ensure(p,3);
else out=(char*)cJSON_malloc(3);
if (!out) return 0;
strcpy(out,"\"\"");
return out;
}
ptr=str;while ((token=*ptr) && ++len) {if (strchr("\"\\\b\f\n\r\t",token)) len++; else if (token<32) len+=5;ptr++;}
if (p) out=ensure(p,len+3);
else out=(char*)cJSON_malloc(len+3);
if (!out) return 0;

ptr2=out;ptr=str;
*ptr2++='\"';
while (*ptr)
{
if ((unsigned char)*ptr>31 && *ptr!='\"' && *ptr!='\\') *ptr2++=*ptr++;
else
{
*ptr2++='\\';
switch (token=*ptr++)
{
case '\\': *ptr2++='\\'; break;
case '\"': *ptr2++='\"'; break;
case '\b': *ptr2++='b'; break;
case '\f': *ptr2++='f'; break;
case '\n': *ptr2++='n'; break;
case '\r': *ptr2++='r'; break;
case '\t': *ptr2++='t'; break;
default: sprintf(ptr2,"u%04x",token);ptr2+=5; break; /* escape and print */
}
}
}
*ptr2++='\"';*ptr2++=0;
return out;
}
/* Invote print_string_ptr (which is useful) on an item. */
static char *print_string(cJSON *item,printbuffer *p) {return print_string_ptr(item->valuestring,p);}

/* Predeclare these prototypes. */
static const char *parse_value(cJSON *item,const char *value);
static char *print_value(cJSON *item,int depth,int fmt,printbuffer *p);
static const char *parse_array(cJSON *item,const char *value);
static char *print_array(cJSON *item,int depth,int fmt,printbuffer *p);
static const char *parse_object(cJSON *item,const char *value);
static char *print_object(cJSON *item,int depth,int fmt,printbuffer *p);

/* Utility to jump whitespace and cr/lf */
static const char *skip(const char *in) {while (in && *in && (unsigned char)*in<=32) in++; return in;}

/* Parse an object - create a new root, and populate. */
cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated)
{
const char *end=0;
cJSON *c=cJSON_New_Item();
ep=0;
if (!c) return 0; /* memory fail */

end=parse_value(c,skip(value));
if (!end) {cJSON_Delete(c);return 0;} /* parse failure. ep is set. */

/* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */
if (require_null_terminated) {end=skip(end);if (*end) {cJSON_Delete(c);ep=end;return 0;}}
if (return_parse_end) *return_parse_end=end;
return c;
}
/* Default options for cJSON_Parse */
cJSON *cJSON_Parse(const char *value) {return cJSON_ParseWithOpts(value,0,0);}

/* Render a cJSON item/entity/structure to text. */
char *cJSON_Print(cJSON *item) {return print_value(item,0,1,0);}
char *cJSON_PrintUnformatted(cJSON *item) {return print_value(item,0,0,0);}

char *cJSON_PrintBuffered(cJSON *item,int prebuffer,int fmt)
{
printbuffer p;
p.buffer=(char*)cJSON_malloc(prebuffer);
p.length=prebuffer;
p.offset=0;
return print_value(item,0,fmt,&p);
return p.buffer;
}


/* Parser core - when encountering text, process appropriately. */
static const char *parse_value(cJSON *item,const char *value)
{
if (!value) return 0; /* Fail on null. */
if (!strncmp(value,"null",4)) { item->type=cJSON_NULL; return value+4; }
if (!strncmp(value,"false",5)) { item->type=cJSON_False; return value+5; }
if (!strncmp(value,"true",4)) { item->type=cJSON_True; item->valueint=1; return value+4; }
if (*value=='\"') { return parse_string(item,value); }
if (*value=='-' || (*value>='0' && *value<='9')) { return parse_number(item,value); }
if (*value=='[') { return parse_array(item,value); }
if (*value=='{') { return parse_object(item,value); }

ep=value;return 0; /* failure. */
}

/* Render a value to text. */
static char *print_value(cJSON *item,int depth,int fmt,printbuffer *p)
{
char *out=0;
if (!item) return 0;
if (p)
{
switch ((item->type)&255)
{
case cJSON_NULL: {out=ensure(p,5); if (out) strcpy(out,"null"); break;}
case cJSON_False: {out=ensure(p,6); if (out) strcpy(out,"false"); break;}
case cJSON_True: {out=ensure(p,5); if (out) strcpy(out,"true"); break;}
case cJSON_Number: out=print_number(item,p);break;
case cJSON_String: out=print_string(item,p);break;
case cJSON_Array: out=print_array(item,depth,fmt,p);break;
case cJSON_Object: out=print_object(item,depth,fmt,p);break;
}
}
else
{
switch ((item->type)&255)
{
case cJSON_NULL: out=cJSON_strdup("null"); break;
case cJSON_False: out=cJSON_strdup("false");break;
case cJSON_True: out=cJSON_strdup("true"); break;
case cJSON_Number: out=print_number(item,0);break;
case cJSON_String: out=print_string(item,0);break;
case cJSON_Array: out=print_array(item,depth,fmt,0);break;
case cJSON_Object: out=print_object(item,depth,fmt,0);break;
}
}
return out;
}

/* Build an array from input text. */
static const char *parse_array(cJSON *item,const char *value)
{
cJSON *child;
if (*value!='[') {ep=value;return 0;} /* not an array! */

item->type=cJSON_Array;
value=skip(value+1);
if (*value==']') return value+1; /* empty array. */

item->child=child=cJSON_New_Item();
if (!item->child) return 0; /* memory fail */
value=skip(parse_value(child,skip(value))); /* skip any spacing, get the value. */
if (!value) return 0;

while (*value==',')
{
cJSON *new_item;
if (!(new_item=cJSON_New_Item())) return 0; /* memory fail */
child->next=new_item;new_item->prev=child;child=new_item;
value=skip(parse_value(child,skip(value+1)));
if (!value) return 0; /* memory fail */
}

if (*value==']') return value+1; /* end of array */
ep=value;return 0; /* malformed. */
}

/* Render an array to text */
static char *print_array(cJSON *item,int depth,int fmt,printbuffer *p)
{
char **entries;
char *out=0,*ptr,*ret;int len=5;
cJSON *child=item->child;
int numentries=0,i=0,fail=0;
size_t tmplen=0;
/* How many entries in the array? */
while (child) numentries++,child=child->next;
/* Explicitly handle numentries==0 */
if (!numentries)
{
if (p) out=ensure(p,3);
else out=(char*)cJSON_malloc(3);
if (out) strcpy(out,"[]");
return out;
}

if (p)
{
/* Compose the output array. */
i=p->offset;
ptr=ensure(p,1);if (!ptr) return 0; *ptr='['; p->offset++;
child=item->child;
while (child && !fail)
{
print_value(child,depth+1,fmt,p);
p->offset=update(p);
if (child->next) {len=fmt?2:1;ptr=ensure(p,len+1);if (!ptr) return 0;*ptr++=',';if(fmt)*ptr++=' ';*ptr=0;p->offset+=len;}
child=child->next;
}
ptr=ensure(p,2);if (!ptr) return 0; *ptr++=']';*ptr=0;
out=(p->buffer)+i;
}
else
{
/* Allocate an array to hold the values for each */
entries=(char**)cJSON_malloc(numentries*sizeof(char*));
if (!entries) return 0;
memset(entries,0,numentries*sizeof(char*));
/* Retrieve all the results: */
child=item->child;
while (child && !fail)
{
ret=print_value(child,depth+1,fmt,0);
entries[i++]=ret;
if (ret) len+=strlen(ret)+2+(fmt?1:0); else fail=1;
child=child->next;
}
/* If we didn't fail, try to malloc the output string */
if (!fail) out=(char*)cJSON_malloc(len);
/* If that fails, we fail. */
if (!out) fail=1;

/* Handle failure. */
if (fail)
{
for (i=0;i<numentries;i++) if (entries[i]) cJSON_free(entries[i]);
cJSON_free(entries);
return 0;
}
/* Compose the output array. */
*out='[';
ptr=out+1;*ptr=0;
for (i=0;i<numentries;i++)
{
tmplen=strlen(entries[i]);memcpy(ptr,entries[i],tmplen);ptr+=tmplen;
if (i!=numentries-1) {*ptr++=',';if(fmt)*ptr++=' ';*ptr=0;}
cJSON_free(entries[i]);
}
cJSON_free(entries);
*ptr++=']';*ptr++=0;
}
return out;
}

/* Build an object from the text. */
static const char *parse_object(cJSON *item,const char *value)
{
cJSON *child;
if (*value!='{') {ep=value;return 0;} /* not an object! */
item->type=cJSON_Object;
value=skip(value+1);
if (*value=='}') return value+1; /* empty array. */
item->child=child=cJSON_New_Item();
if (!item->child) return 0;
value=skip(parse_string(child,skip(value)));
if (!value) return 0;
child->string=child->valuestring;child->valuestring=0;
if (*value!=':') {ep=value;return 0;} /* fail! */
value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. */
if (!value) return 0;
while (*value==',')
{
cJSON *new_item;
if (!(new_item=cJSON_New_Item())) return 0; /* memory fail */
child->next=new_item;new_item->prev=child;child=new_item;
value=skip(parse_string(child,skip(value+1)));
if (!value) return 0;
child->string=child->valuestring;child->valuestring=0;
if (*value!=':') {ep=value;return 0;} /* fail! */
value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. */
if (!value) return 0;
}
if (*value=='}') return value+1; /* end of array */
ep=value;return 0; /* malformed. */
}

/* Render an object to text. */
static char *print_object(cJSON *item,int depth,int fmt,printbuffer *p)
{
char **entries=0,**names=0;
char *out=0,*ptr,*ret,*str;int len=7,i=0,j;
cJSON *child=item->child;
int numentries=0,fail=0;
size_t tmplen=0;
/* Count the number of entries. */
while (child) numentries++,child=child->next;
/* Explicitly handle empty object case */
if (!numentries)
{
if (p) out=ensure(p,fmt?depth+4:3);
else out=(char*)cJSON_malloc(fmt?depth+4:3);
if (!out) return 0;
ptr=out;*ptr++='{';
if (fmt) {*ptr++='\n';for (i=0;i<depth-1;i++) *ptr++='\t';}
*ptr++='}';*ptr++=0;
return out;
}
if (p)
{
/* Compose the output: */
i=p->offset;
len=fmt?2:1; ptr=ensure(p,len+1); if (!ptr) return 0;
*ptr++='{'; if (fmt) *ptr++='\n'; *ptr=0; p->offset+=len;
child=item->child;depth++;
while (child)
{
if (fmt)
{
ptr=ensure(p,depth); if (!ptr) return 0;
for (j=0;j<depth;j++) *ptr++='\t';
p->offset+=depth;
}
print_string_ptr(child->string,p);
p->offset=update(p);
len=fmt?2:1;
ptr=ensure(p,len); if (!ptr) return 0;
*ptr++=':';if (fmt) *ptr++='\t';
p->offset+=len;
print_value(child,depth,fmt,p);
p->offset=update(p);

len=(fmt?1:0)+(child->next?1:0);
ptr=ensure(p,len+1); if (!ptr) return 0;
if (child->next) *ptr++=',';
if (fmt) *ptr++='\n';*ptr=0;
p->offset+=len;
child=child->next;
}
ptr=ensure(p,fmt?(depth+1):2); if (!ptr) return 0;
if (fmt) for (i=0;i<depth-1;i++) *ptr++='\t';
*ptr++='}';*ptr=0;
out=(p->buffer)+i;
}
else
{
/* Allocate space for the names and the objects */
entries=(char**)cJSON_malloc(numentries*sizeof(char*));
if (!entries) return 0;
names=(char**)cJSON_malloc(numentries*sizeof(char*));
if (!names) {cJSON_free(entries);return 0;}
memset(entries,0,sizeof(char*)*numentries);
memset(names,0,sizeof(char*)*numentries);

/* Collect all the results into our arrays: */
child=item->child;depth++;if (fmt) len+=depth;
while (child)
{
names[i]=str=print_string_ptr(child->string,0);
entries[i++]=ret=print_value(child,depth,fmt,0);
if (str && ret) len+=strlen(ret)+strlen(str)+2+(fmt?2+depth:0); else fail=1;
child=child->next;
}
/* Try to allocate the output string */
if (!fail) out=(char*)cJSON_malloc(len);
if (!out) fail=1;

/* Handle failure */
if (fail)
{
for (i=0;i<numentries;i++) {if (names[i]) cJSON_free(names[i]);if (entries[i]) cJSON_free(entries[i]);}
cJSON_free(names);cJSON_free(entries);
return 0;
}
/* Compose the output: */
*out='{';ptr=out+1;if (fmt)*ptr++='\n';*ptr=0;
for (i=0;i<numentries;i++)
{
if (fmt) for (j=0;j<depth;j++) *ptr++='\t';
tmplen=strlen(names[i]);memcpy(ptr,names[i],tmplen);ptr+=tmplen;
*ptr++=':';if (fmt) *ptr++='\t';
strcpy(ptr,entries[i]);ptr+=strlen(entries[i]);
if (i!=numentries-1) *ptr++=',';
if (fmt) *ptr++='\n';*ptr=0;
cJSON_free(names[i]);cJSON_free(entries[i]);
}
cJSON_free(names);cJSON_free(entries);
if (fmt) for (i=0;i<depth-1;i++) *ptr++='\t';
*ptr++='}';*ptr++=0;
}
return out;
}

/* Get Array size/item / object item. */
int cJSON_GetArraySize(cJSON *array) {cJSON *c=array->child;int i=0;while(c)i++,c=c->next;return i;}
cJSON *cJSON_GetArrayItem(cJSON *array,int item) {cJSON *c=array->child; while (c && item>0) item--,c=c->next; return c;}
cJSON *cJSON_GetObjectItem(cJSON *object,const char *string) {cJSON *c=object->child; while (c && cJSON_strcasecmp(c->string,string)) c=c->next; return c;}

/* Utility for array list handling. */
static void suffix_object(cJSON *prev,cJSON *item) {prev->next=item;item->prev=prev;}
/* Utility for handling references. */
static cJSON *create_reference(cJSON *item) {cJSON *ref=cJSON_New_Item();if (!ref) return 0;memcpy(ref,item,sizeof(cJSON));ref->string=0;ref->type|=cJSON_IsReference;ref->next=ref->prev=0;return ref;}

/* Add item to array/object. */
void cJSON_AddItemToArray(cJSON *array, cJSON *item) {cJSON *c=array->child;if (!item) return; if (!c) {array->child=item;} else {while (c && c->next) c=c->next; suffix_object(c,item);}}
void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item) {if (!item) return; if (item->string) cJSON_free(item->string);item->string=cJSON_strdup(string);cJSON_AddItemToArray(object,item);}
void cJSON_AddItemToObjectCS(cJSON *object,const char *string,cJSON *item) {if (!item) return; if (!(item->type&cJSON_StringIsConst) && item->string) cJSON_free(item->string);item->string=(char*)string;item->type|=cJSON_StringIsConst;cJSON_AddItemToArray(object,item);}
void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item) {cJSON_AddItemToArray(array,create_reference(item));}
void cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item) {cJSON_AddItemToObject(object,string,create_reference(item));}

cJSON *cJSON_DetachItemFromArray(cJSON *array,int which) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return 0;
if (c->prev) c->prev->next=c->next;if (c->next) c->next->prev=c->prev;if (c==array->child) array->child=c->next;c->prev=c->next=0;return c;}
void cJSON_DeleteItemFromArray(cJSON *array,int which) {cJSON_Delete(cJSON_DetachItemFromArray(array,which));}
cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string) {int i=0;cJSON *c=object->child;while (c && cJSON_strcasecmp(c->string,string)) i++,c=c->next;if (c) return cJSON_DetachItemFromArray(object,i);return 0;}
void cJSON_DeleteItemFromObject(cJSON *object,const char *string) {cJSON_Delete(cJSON_DetachItemFromObject(object,string));}

/* Replace array/object items with new ones. */
void cJSON_InsertItemInArray(cJSON *array,int which,cJSON *newitem) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) {cJSON_AddItemToArray(array,newitem);return;}
newitem->next=c;newitem->prev=c->prev;c->prev=newitem;if (c==array->child) array->child=newitem; else newitem->prev->next=newitem;}
void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return;
newitem->next=c->next;newitem->prev=c->prev;if (newitem->next) newitem->next->prev=newitem;
if (c==array->child) array->child=newitem; else newitem->prev->next=newitem;c->next=c->prev=0;cJSON_Delete(c);}
void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem){int i=0;cJSON *c=object->child;while(c && cJSON_strcasecmp(c->string,string))i++,c=c->next;if(c){newitem->string=cJSON_strdup(string);cJSON_ReplaceItemInArray(object,i,newitem);}}

/* Create basic types: */
cJSON *cJSON_CreateNull(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_NULL;return item;}
cJSON *cJSON_CreateTrue(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_True;return item;}
cJSON *cJSON_CreateFalse(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_False;return item;}
cJSON *cJSON_CreateBool(int b) {cJSON *item=cJSON_New_Item();if(item)item->type=b?cJSON_True:cJSON_False;return item;}
cJSON *cJSON_CreateNumber(double num) {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_Number;item->valuedouble=num;item->valueint=(int)num;}return item;}
cJSON *cJSON_CreateString(const char *string) {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_String;item->valuestring=cJSON_strdup(string);}return item;}
cJSON *cJSON_CreateArray(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Array;return item;}
cJSON *cJSON_CreateObject(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Object;return item;}

/* Create Arrays: */
cJSON *cJSON_CreateIntArray(const int *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
cJSON *cJSON_CreateFloatArray(const float *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
cJSON *cJSON_CreateDoubleArray(const double *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
cJSON *cJSON_CreateStringArray(const char **strings,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateString(strings[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}

/* Duplication */
cJSON *cJSON_Duplicate(cJSON *item,int recurse)
{
cJSON *newitem,*cptr,*nptr=0,*newchild;
/* Bail on bad ptr */
if (!item) return 0;
/* Create new item */
newitem=cJSON_New_Item();
if (!newitem) return 0;
/* Copy over all vars */
newitem->type=item->type&(~cJSON_IsReference),newitem->valueint=item->valueint,newitem->valuedouble=item->valuedouble;
if (item->valuestring) {newitem->valuestring=cJSON_strdup(item->valuestring); if (!newitem->valuestring) {cJSON_Delete(newitem);return 0;}}
if (item->string) {newitem->string=cJSON_strdup(item->string); if (!newitem->string) {cJSON_Delete(newitem);return 0;}}
/* If non-recursive, then we're done! */
if (!recurse) return newitem;
/* Walk the ->next chain for the child. */
cptr=item->child;
while (cptr)
{
newchild=cJSON_Duplicate(cptr,1); /* Duplicate (with recurse) each item in the ->next chain */
if (!newchild) {cJSON_Delete(newitem);return 0;}
if (nptr) {nptr->next=newchild,newchild->prev=nptr;nptr=newchild;} /* If newitem->child already set, then crosswire ->prev and ->next and move on */
else {newitem->child=newchild;nptr=newchild;} /* Set newitem->child and move to it */
cptr=cptr->next;
}
return newitem;
}

void cJSON_Minify(char *json)
{
char *into=json;
while (*json)
{
if (*json==' ') json++;
else if (*json=='\t') json++; /* Whitespace characters. */
else if (*json=='\r') json++;
else if (*json=='\n') json++;
else if (*json=='/' && json[1]=='/') while (*json && *json!='\n') json++; /* double-slash comments, to end of line. */
else if (*json=='/' && json[1]=='*') {while (*json && !(*json=='*' && json[1]=='/')) json++;json+=2;} /* multiline comments. */
else if (*json=='\"'){*into++=*json++;while (*json && *json!='\"'){if (*json=='\\') *into++=*json++;*into++=*json++;}*into++=*json++;} /* string literals, which are \" sensitive. */
else *into++=*json++; /* All other characters. */
}
*into=0; /* and null-terminate. */
}

+ 0
- 149
third-party/cambricon-k8s-device-plugin/device-plugin/pkg/cndev/mock/cJSON.h View File

@@ -1,149 +0,0 @@
/*
Copyright (c) 2009 Dave Gamble
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

#ifndef cJSON__h
#define cJSON__h

#ifdef __cplusplus
extern "C"
{
#endif

/* cJSON Types: */
#define cJSON_False 0
#define cJSON_True 1
#define cJSON_NULL 2
#define cJSON_Number 3
#define cJSON_String 4
#define cJSON_Array 5
#define cJSON_Object 6
#define cJSON_IsReference 256
#define cJSON_StringIsConst 512

/* The cJSON structure: */
typedef struct cJSON {
struct cJSON *next,*prev; /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
struct cJSON *child; /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */

int type; /* The type of the item, as above. */

char *valuestring; /* The item's string, if type==cJSON_String */
int valueint; /* The item's number, if type==cJSON_Number */
double valuedouble; /* The item's number, if type==cJSON_Number */

char *string; /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
} cJSON;

typedef struct cJSON_Hooks {
void *(*malloc_fn)(size_t sz);
void (*free_fn)(void *ptr);
} cJSON_Hooks;

/* Supply malloc, realloc and free functions to cJSON */
extern void cJSON_InitHooks(cJSON_Hooks* hooks);


/* Supply a block of JSON, and this returns a cJSON object you can interrogate. Call cJSON_Delete when finished. */
extern cJSON *cJSON_Parse(const char *value);
/* Render a cJSON entity to text for transfer/storage. Free the char* when finished. */
extern char *cJSON_Print(cJSON *item);
/* Render a cJSON entity to text for transfer/storage without any formatting. Free the char* when finished. */
extern char *cJSON_PrintUnformatted(cJSON *item);
/* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess at the final size. guessing well reduces reallocation. fmt=0 gives unformatted, =1 gives formatted */
extern char *cJSON_PrintBuffered(cJSON *item,int prebuffer,int fmt);
/* Delete a cJSON entity and all subentities. */
extern void cJSON_Delete(cJSON *c);

/* Returns the number of items in an array (or object). */
extern int cJSON_GetArraySize(cJSON *array);
/* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */
extern cJSON *cJSON_GetArrayItem(cJSON *array,int item);
/* Get item "string" from object. Case insensitive. */
extern cJSON *cJSON_GetObjectItem(cJSON *object,const char *string);

/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */
extern const char *cJSON_GetErrorPtr(void);
/* These calls create a cJSON item of the appropriate type. */
extern cJSON *cJSON_CreateNull(void);
extern cJSON *cJSON_CreateTrue(void);
extern cJSON *cJSON_CreateFalse(void);
extern cJSON *cJSON_CreateBool(int b);
extern cJSON *cJSON_CreateNumber(double num);
extern cJSON *cJSON_CreateString(const char *string);
extern cJSON *cJSON_CreateArray(void);
extern cJSON *cJSON_CreateObject(void);

/* These utilities create an Array of count items. */
extern cJSON *cJSON_CreateIntArray(const int *numbers,int count);
extern cJSON *cJSON_CreateFloatArray(const float *numbers,int count);
extern cJSON *cJSON_CreateDoubleArray(const double *numbers,int count);
extern cJSON *cJSON_CreateStringArray(const char **strings,int count);

/* Append item to the specified array/object. */
extern void cJSON_AddItemToArray(cJSON *array, cJSON *item);
extern void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item);
extern void cJSON_AddItemToObjectCS(cJSON *object,const char *string,cJSON *item); /* Use this when string is definitely const (i.e. a literal, or as good as), and will definitely survive the cJSON object */
/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */
extern void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
extern void cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item);

/* Remove/Detatch items from Arrays/Objects. */
extern cJSON *cJSON_DetachItemFromArray(cJSON *array,int which);
extern void cJSON_DeleteItemFromArray(cJSON *array,int which);
extern cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string);
extern void cJSON_DeleteItemFromObject(cJSON *object,const char *string);
/* Update array items. */
extern void cJSON_InsertItemInArray(cJSON *array,int which,cJSON *newitem); /* Shifts pre-existing items to the right. */
extern void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem);
extern void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);

/* Duplicate a cJSON item */
extern cJSON *cJSON_Duplicate(cJSON *item,int recurse);
/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will
need to be released. With recurse!=0, it will duplicate any children connected to the item.
The item->next and ->prev pointers are always zero on return from Duplicate. */

/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */
extern cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated);

extern void cJSON_Minify(char *json);

/* Macros for creating things quickly. */
#define cJSON_AddNullToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateNull())
#define cJSON_AddTrueToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateTrue())
#define cJSON_AddFalseToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateFalse())
#define cJSON_AddBoolToObject(object,name,b) cJSON_AddItemToObject(object, name, cJSON_CreateBool(b))
#define cJSON_AddNumberToObject(object,name,n) cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n))
#define cJSON_AddStringToObject(object,name,s) cJSON_AddItemToObject(object, name, cJSON_CreateString(s))

/* When assigning an integer value, it needs to be propagated to valuedouble too. */
#define cJSON_SetIntValue(object,val) ((object)?(object)->valueint=(object)->valuedouble=(val):(val))
#define cJSON_SetNumberValue(object,val) ((object)?(object)->valueint=(object)->valuedouble=(val):(val))

#ifdef __cplusplus
}
#endif

#endif

+ 0
- 173
third-party/cambricon-k8s-device-plugin/device-plugin/pkg/cndev/mock/cndev.c View File

@@ -1,173 +0,0 @@
/*
* Copyright 2020 Cambricon, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include "../include/cndev.h"
#include "cJSON.h"
#include <stdio.h>
#include <stdlib.h>

cJSON *readJsonFile()
{
FILE *f;
long len;
char *content;
cJSON *json;
f = fopen(getenv("MOCK_JSON"), "rb");
fseek(f, 0, SEEK_END);
len = ftell(f);
fseek(f, 0, SEEK_SET);
content = (char *)malloc(len + 1);
fread(content, 1, len, f);
fclose(f);
json = cJSON_Parse(content);
if (!json)
{
printf("Error before: [%s]\n", cJSON_GetErrorPtr());
}
return json;
}
cndevRet_t cndevGetDeviceCount(cndevCardInfo_t *cardNum)
{
cJSON *config;
unsigned numMLU;
config = readJsonFile();
cJSON *numObj = cJSON_GetObjectItem(config, "num");
numMLU = numObj->valueint;
cardNum->Number = numMLU;
return CNDEV_SUCCESS;
}
cndevRet_t cndevInit(int reserved)
{
cJSON *config;
cndevRet_t result;
config = readJsonFile();
cJSON *ret = cJSON_GetObjectItem(config, "ret");
int result_int = ret->valueint;
result = CNDEV_SUCCESS;
for (int i = 0; i <= 9; i++)
{
if (i == result_int)
{
return result;
}
result++;
}
}
cndevRet_t cndevGetCardHealthState(cndevCardHealthState_t *cardHealthState, int devId)
{
cJSON *config;
cndevRet_t result;
config = readJsonFile();

cJSON *health_node = cJSON_GetObjectItem(config, "health");
int health_int = cJSON_GetArrayItem(health_node, devId)->valueint;
cardHealthState->health = health_int;

cJSON *ret = cJSON_GetObjectItem(config, "health_ret");
int result_int = cJSON_GetArrayItem(ret, devId)->valueint;
result = CNDEV_SUCCESS;
for (int i = 0; i <= 9; i++)
{
if (i == result_int)
{
return result;
}
result++;
}
}
cndevRet_t cndevGetCardSN(cndevCardSN_t *cardSN, int devId)
{
cJSON *config;
cndevRet_t result;
config = readJsonFile();

cJSON *sn_node = cJSON_GetObjectItem(config, "MLU");
__int64_t sn_int = cJSON_GetArrayItem(sn_node, devId)->valueint;
cardSN->sn = sn_int;

cJSON *ret = cJSON_GetObjectItem(config, "MLU_ret");
int result_int = cJSON_GetArrayItem(ret, devId)->valueint;
result = CNDEV_SUCCESS;
for (int i = 0; i <= 9; i++)
{
if (i == result_int)
{
return result;
}
result++;
}
}
cndevRet_t cndevRelease()
{
return CNDEV_SUCCESS;
}
cndevRet_t cndevGetCardName(cndevCardName_t *cardName, int devId)
{
cJSON *config;
cndevRet_t result;
config = readJsonFile();

cJSON *card_type_node = cJSON_GetObjectItem(config, "card_type");
int card_type = cJSON_GetArrayItem(card_type_node, devId)->valueint;

if (card_type == 0)
{
cardName->id = MLU100;
}
else if (card_type == 1)
{
cardName->id = MLU270;
}
else if (card_type == 16)
{
cardName->id = MLU220_M2;
}
else if (card_type == 18)
{
cardName->id = MLU220_EVB;
}
else if (card_type == 19)
{
cardName->id = MLU220_M2i;
}
else if (card_type == 20)
{
cardName->id = MLU290;
}
return CNDEV_SUCCESS;
}

const char *cndevGetErrorString(cndevRet_t errorId)
{
return "mock return value of cndev get error string";
}

cndevRet_t cndevGetPCIeInfo(cndevPCIeInfo_t *deviceInfo, int devId)
{
cJSON *config;
cndevRet_t result;
config = readJsonFile();

cJSON *pcie_info = cJSON_GetObjectItem(config, "pcie_info");
cJSON *pcie_node = cJSON_GetArrayItem(pcie_info, devId);

deviceInfo->domain = cJSON_GetArrayItem(pcie_node, 0)->valueint;
deviceInfo->bus = cJSON_GetArrayItem(pcie_node, 1)->valueint;
deviceInfo->device = cJSON_GetArrayItem(pcie_node, 2)->valueint;
deviceInfo->function = cJSON_GetArrayItem(pcie_node, 3)->valueint;

return CNDEV_SUCCESS;
}

+ 0
- 76
third-party/cambricon-k8s-device-plugin/device-plugin/pkg/cndev/mock/main.c View File

@@ -1,76 +0,0 @@
/*
* Copyright 2020 Cambricon, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include "../include/cndev.h"
#include <stdio.h>
int Test_cndevGetDeviceCount()
{
cndevCardInfo_t *cardNum;
cardNum = (cndevCardInfo_t *)malloc(sizeof(cndevCardInfo_t));
cardNum->version = 1;
cndevRet_t result;
result = cndevGetDeviceCount(cardNum);
printf("=== Test cndevGetDeviceCount() ===\nnumMLU:%d\nretMLU:%d\n", cardNum->Number, result);
return cardNum->Number;
}
void Test_cndevInit()
{
cndevRet_t result;
result = cndevInit(0);
printf("=== Test cndevInit() ===\nretMLU:%d\n", result);
}
void Test_cndevGetCardHealthState(int id)
{
cndevCardHealthState_t *cardHealthState;
cardHealthState = (cndevCardHealthState_t *)malloc(sizeof(cndevCardHealthState_t));
cardHealthState->version = 3;
cndevRet_t result;
result = cndevGetCardHealthState(cardHealthState, id);
printf("=== Test cndevGetCardHealthState() ===\nhealthMLU:%d\nretMLU:%d\n", cardHealthState->health, result);
}
void Test_cndevGetCardSN(int id)
{
cndevCardSN_t *cardSN;
cardSN = (cndevCardSN_t *)malloc(sizeof(cndevCardSN_t));
cardSN->version = 3;
cndevRet_t result;
result = cndevGetCardSN(cardSN, id);
printf("=== Test cndevGetCardSN() ===\nsnMLU:%x\nmotherBoard:%x\nretsnMLU:%d\n", cardSN->sn, cardSN->mother_board_sn, result);
}
void Test_cndevGetPCIeInfo(int id)
{
cndevPCIeInfo_t *cardPcie;
cardPcie = (cndevPCIeInfo_t *)malloc(sizeof(cndevPCIeInfo_t));
cardPcie->version = 3;
cndevRet_t result;
result = cndevGetPCIeInfo(cardPcie, id);
printf("=== Test Test_cndevGetPcieInfo() ===\ndomain:%d\nbus:%d\ndevice:%d\nfunction:%d\nretMLU:%d\n", cardPcie->domain, cardPcie->bus, cardPcie->device, cardPcie->function, result);
}

int main()
{
Test_cndevInit();
int num;
num = Test_cndevGetDeviceCount();
for (int i = 0; i < num; ++i)
{
printf("================ Test card id %d =============\n", i);
Test_cndevGetCardHealthState(i);
Test_cndevGetCardSN(i);
Test_cndevGetPCIeInfo(i);
}
return 0;
}

+ 0
- 336
third-party/cambricon-k8s-device-plugin/device-plugin/server.go View File

@@ -1,336 +0,0 @@
// Copyright 2020 Cambricon, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package main

import (
"fmt"
"log"
"net"
"os"
"path"
"strconv"
"strings"
"time"

"github.com/cambricon/cambricon-k8s-device-plugin/device-plugin/pkg/cndev"
"golang.org/x/net/context"
"google.golang.org/grpc"
pluginapi "k8s.io/kubelet/pkg/apis/deviceplugin/v1beta1"
)

const (
resourceName = "cambricon.com/mlu"
serverSock = pluginapi.DevicePluginPath + "cambricon.sock"
envDisableHealthChecks = "DP_DISABLE_HEALTHCHECKS"
)

// CambriconDevicePlugin implements the Kubernetes device plugin API
type CambriconDevicePlugin struct {
devs []*pluginapi.Device
devsInfo []*cndev.Device
socket string
stop chan interface{}
health chan *pluginapi.Device
server *grpc.Server
feature int
deviceList *deviceList
}

// NewCambriconDevicePlugin returns an initialized CambriconDevicePlugin
func NewCambriconDevicePlugin() *CambriconDevicePlugin {
feature := getFeature()
devs, devsInfo := getDevices(feature)
return &CambriconDevicePlugin{
devs: devs,
devsInfo: devsInfo,
socket: serverSock,

stop: make(chan interface{}),
health: make(chan *pluginapi.Device),
feature: feature,
deviceList: newDeviceList(),
}
}

func (m *CambriconDevicePlugin) GetDevicePluginOptions(context.Context, *pluginapi.Empty) (*pluginapi.DevicePluginOptions, error) {
return &pluginapi.DevicePluginOptions{}, nil
}

// dial establishes the gRPC communication with the registered device plugin.
func dial(unixSocketPath string, timeout time.Duration) (*grpc.ClientConn, error) {
c, err := grpc.Dial(unixSocketPath, grpc.WithInsecure(), grpc.WithBlock(),
grpc.WithTimeout(timeout),
grpc.WithDialer(func(addr string, timeout time.Duration) (net.Conn, error) {
return net.DialTimeout("unix", addr, timeout)
}),
)

if err != nil {
return nil, err
}

return c, nil
}

// Start starts the gRPC server of the device plugin
func (m *CambriconDevicePlugin) Start() error {
err := m.cleanup()
if err != nil {
return err
}

sock, err := net.Listen("unix", m.socket)
if err != nil {
return err
}

m.server = grpc.NewServer([]grpc.ServerOption{}...)
pluginapi.RegisterDevicePluginServer(m.server, m)

go m.server.Serve(sock)

// Wait for server to start by launching a blocking connection
conn, err := dial(m.socket, 5*time.Second)
if err != nil {
return err
}
conn.Close()

go m.healthcheck()

return nil
}

// Stop stops the gRPC server
func (m *CambriconDevicePlugin) Stop() error {
if m.server == nil {
return nil
}

m.server.Stop()
m.server = nil
close(m.stop)

return m.cleanup()
}

// Register registers the device plugin for the given resourceName with Kubelet.
func (m *CambriconDevicePlugin) Register(kubeletEndpoint, resourceName string) error {
conn, err := dial(kubeletEndpoint, 5*time.Second)
if err != nil {
return err
}
defer conn.Close()

client := pluginapi.NewRegistrationClient(conn)
reqt := &pluginapi.RegisterRequest{
Version: pluginapi.Version,
Endpoint: path.Base(m.socket),
ResourceName: resourceName,
}

_, err = client.Register(context.Background(), reqt)
if err != nil {
return err
}
return nil
}

// ListAndWatch lists devices and update that list according to the health status
func (m *CambriconDevicePlugin) ListAndWatch(e *pluginapi.Empty, s pluginapi.DevicePlugin_ListAndWatchServer) error {
s.Send(&pluginapi.ListAndWatchResponse{Devices: m.devs})

for {
select {
case <-m.stop:
return nil
case d := <-m.health:
// FIXME: there is no way to recover from the Unhealthy state.
d.Health = pluginapi.Unhealthy
s.Send(&pluginapi.ListAndWatchResponse{Devices: m.devs})
}
}
}

func (m *CambriconDevicePlugin) unhealthy(dev *pluginapi.Device) {
m.health <- dev
}

func (m *CambriconDevicePlugin) PrepareResponse(req *pluginapi.ContainerAllocateRequest) pluginapi.ContainerAllocateResponse {

resp := pluginapi.ContainerAllocateResponse{}
devpaths := m.uuidToPath(req.DevicesIDs)

if m.deviceList.hasC10Dev {
if m.deviceList.hasCnmonDev {
addDevice(&resp, mlu100MonitorDeviceName, mlu100MonitorDeviceName)
}
if m.deviceList.hasCodecDev {
addDevice(&resp, mlu100CodecDeviceName, mlu100CodecDeviceName)
}
for id, devpath := range devpaths {
addDevice(&resp, devpath, mlu100DeviceName+strconv.Itoa(id))
}
return resp
}

if m.deviceList.hasCtrlDev {
addDevice(&resp, mluMonitorDeviceName, mluMonitorDeviceName)
}

for id, devpath := range devpaths {
if m.feature == sriovShare {
vfid := strings.Split(devpath, mluDeviceName)[1]
if m.deviceList.hasCommuDev {
addDevice(&resp, mluCommuDeviceName+vfid, mluCommuDeviceName+strconv.Itoa(id))
}
addDevice(&resp, devpath, mluDeviceName+strconv.Itoa(id))
if id == len(devpaths)-1 {
break
}
continue
}

var index int
_, err := fmt.Sscanf(devpath, mluDeviceName+"%d", &index)
if err != nil {
log.Printf("Failed to get device index for device path %v", err)
continue
}
if m.deviceList.hasMsgqDev {
addDevice(&resp, fmt.Sprintf(mluMsgqDeviceName+":%d", index), fmt.Sprintf(mluMsgqDeviceName+":%d", id))
}
if m.deviceList.hasRPCDev {
addDevice(&resp, fmt.Sprintf(mluRPCDeviceName+":%d", index), fmt.Sprintf(mluRPCDeviceName+":%d", id))
}
if m.deviceList.hasCmsgDev {
addDevice(&resp, fmt.Sprintf(mluCmsgDeviceName+"%d", index), fmt.Sprintf(mluCmsgDeviceName+"%d", id))
}
if m.deviceList.hasCommuDev {
addDevice(&resp, fmt.Sprintf(mluCommuDeviceName+"%d", index), fmt.Sprintf(mluCommuDeviceName+"%d", id))
}
addDevice(&resp, devpath, mluDeviceName+strconv.Itoa(id))
}
return resp
}

// Allocate which return list of devices.
func (m *CambriconDevicePlugin) Allocate(ctx context.Context, reqs *pluginapi.AllocateRequest) (*pluginapi.AllocateResponse, error) {
devs := m.devs
responses := pluginapi.AllocateResponse{}

for _, req := range reqs.ContainerRequests {

car := m.PrepareResponse(req)
responses.ContainerResponses = append(responses.ContainerResponses, &car)
for _, id := range req.DevicesIDs {
if !deviceExists(devs, id) {
return nil, fmt.Errorf("invalid allocation request: unknown device: %s", id)
}
}
}
return &responses, nil
}

func (m *CambriconDevicePlugin) uuidToPath(uuids []string) []string {
var paths []string
for _, uuid := range uuids {
for _, dev := range m.devsInfo {
if dev.UUID == uuid {
paths = append(paths, dev.Path)
}
}
}
return paths
}

func (m *CambriconDevicePlugin) PreStartContainer(context.Context, *pluginapi.PreStartContainerRequest) (*pluginapi.PreStartContainerResponse, error) {
return &pluginapi.PreStartContainerResponse{}, nil
}

func (m *CambriconDevicePlugin) cleanup() error {
if err := os.Remove(m.socket); err != nil && !os.IsNotExist(err) {
return err
}

return nil
}

func (m *CambriconDevicePlugin) healthcheck() {
disableHealthChecks := strings.ToLower(os.Getenv(envDisableHealthChecks))

ctx, cancel := context.WithCancel(context.Background())

var unhealthy chan *pluginapi.Device
if !strings.Contains(disableHealthChecks, "all") {
unhealthy = make(chan *pluginapi.Device)
go watchUnhealthy(ctx, m.devs, m.devsInfo, unhealthy)
}

for {
select {
case <-m.stop:
cancel()
return
case dev := <-unhealthy:
m.unhealthy(dev)
}
}
}

// Serve starts the gRPC server and register the device plugin to Kubelet
func (m *CambriconDevicePlugin) Serve() error {
err := m.Start()
if err != nil {
log.Printf("Could not start device plugin: %s", err)
return err
}
log.Println("Starting to serve on", m.socket)

err = m.Register(pluginapi.KubeletSocket, resourceName)
if err != nil {
log.Printf("Could not register device plugin: %s", err)
m.Stop()
return err
}
log.Println("Registered device plugin with Kubelet")

return nil
}

func (m *CambriconDevicePlugin) GetPreferredAllocation(ctx context.Context, r *pluginapi.PreferredAllocationRequest) (*pluginapi.PreferredAllocationResponse, error) {
response := &pluginapi.PreferredAllocationResponse{}
return response, nil
}

func addDevice(car *pluginapi.ContainerAllocateResponse, hostPath string, containerPath string) {
dev := new(pluginapi.DeviceSpec)
dev.HostPath = hostPath
dev.ContainerPath = containerPath
dev.Permissions = "rw"
car.Devices = append(car.Devices, dev)
}

func getFeature() int {
feature := 0
switch *mode {
case "sriov":
feature = sriovShare
case "env-share":
feature = envShare
}
log.Printf("device plugin feature mode number %d. \n", feature)
return feature
}

+ 0
- 423
third-party/cambricon-k8s-device-plugin/device-plugin/server_test.go View File

@@ -1,423 +0,0 @@
// Copyright 2020 Cambricon, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package main

import (
"testing"

"github.com/cambricon/cambricon-k8s-device-plugin/device-plugin/pkg/cndev"
"github.com/stretchr/testify/assert"
"golang.org/x/net/context"
pluginapi "k8s.io/kubelet/pkg/apis/deviceplugin/v1beta1"
)

func TestCambriconDevicePluginAllocateMLU100(t *testing.T) {
devs := []*pluginapi.Device{
{
ID: "MLU-testdevice-sn0001",
},
{
ID: "MLU-testdevice-sn0002",
},
}
devsInfo := []*cndev.Device{
{
UUID: "MLU-testdevice-sn0001",
Path: "/dev/cambricon_c10Dev0",
},
{
UUID: "MLU-testdevice-sn0002",
Path: "/dev/cambricon_c10Dev1",
},
}

tests := []struct {
m *CambriconDevicePlugin
req *pluginapi.AllocateRequest
}{
{
m: &CambriconDevicePlugin{
devs: devs,
devsInfo: devsInfo,
feature: 0,
deviceList: &deviceList{
hasCnmonDev: true,
hasCodecDev: true,
hasC10Dev: true,
},
},
req: &pluginapi.AllocateRequest{
ContainerRequests: []*pluginapi.ContainerAllocateRequest{
{
DevicesIDs: []string{
"MLU-testdevice-sn0002",
},
},
},
},
},
{
m: &CambriconDevicePlugin{
devs: devs,
devsInfo: devsInfo,
feature: 0,
deviceList: &deviceList{
hasCnmonDev: true,
hasC10Dev: true,
},
},
req: &pluginapi.AllocateRequest{
ContainerRequests: []*pluginapi.ContainerAllocateRequest{
{
DevicesIDs: []string{
"MLU-testdevice-sn0002",
},
},
},
},
},
{
m: &CambriconDevicePlugin{
devs: devs,
devsInfo: devsInfo,
feature: 0,
deviceList: &deviceList{
hasCnmonDev: true,
hasC10Dev: true,
},
},
req: &pluginapi.AllocateRequest{
ContainerRequests: []*pluginapi.ContainerAllocateRequest{
{
DevicesIDs: []string{
"MLU-testdevice-sn0001",
"MLU-testdevice-sn0002",
},
},
},
},
},
}

for i, tt := range tests {
t.Run("", func(t *testing.T) {
ctx := context.TODO()
resp, err := tt.m.Allocate(ctx, tt.req)
assert.NoError(t, err)
assert.Equal(t, 1, len(resp.ContainerResponses))
devices := resp.ContainerResponses[0].Devices
assert.Equal(t, mlu100MonitorDeviceName, devices[0].HostPath)
switch i {
case 0:
assert.Equal(t, 3, len(devices))
assert.Equal(t, mlu100CodecDeviceName, devices[1].HostPath)
assert.Equal(t, mlu100DeviceName+"1", devices[2].HostPath)
case 1:
assert.Equal(t, 2, len(devices))
assert.Equal(t, mlu100DeviceName+"1", devices[1].HostPath)
case 3:
assert.Equal(t, 3, len(devices))
assert.Equal(t, mlu100DeviceName+"0", devices[1].HostPath)
assert.Equal(t, mlu100DeviceName+"1", devices[2].HostPath)
}
})
}
}

func TestCambriconDevicePluginAllocate(t *testing.T) {
devs := []*pluginapi.Device{
{
ID: "MLU-testdevice-sn0001",
},
{
ID: "MLU-testdevice-sn0002",
},
}
devsInfo := []*cndev.Device{
{
UUID: "MLU-testdevice-sn0001",
Path: "/dev/cambricon_dev0",
},
{
UUID: "MLU-testdevice-sn0002",
Path: "/dev/cambricon_dev1",
},
}

tests := []struct {
m *CambriconDevicePlugin
req *pluginapi.AllocateRequest
}{
{
m: &CambriconDevicePlugin{
devs: devs,
devsInfo: devsInfo,
feature: 0,
deviceList: &deviceList{
hasCtrlDev: true,
hasMsgqDev: true,
hasRPCDev: true,
hasCmsgDev: true,
hasCommuDev: true,
},
},
req: &pluginapi.AllocateRequest{
ContainerRequests: []*pluginapi.ContainerAllocateRequest{
{
DevicesIDs: []string{
"MLU-testdevice-sn0001",
"MLU-testdevice-sn0002",
},
},
},
},
},
{
m: &CambriconDevicePlugin{
devs: devs,
devsInfo: devsInfo,
feature: 0,
deviceList: &deviceList{
hasCtrlDev: true,
hasCommuDev: true,
},
},
req: &pluginapi.AllocateRequest{
ContainerRequests: []*pluginapi.ContainerAllocateRequest{
{
DevicesIDs: []string{
"MLU-testdevice-sn0002",
},
},
},
},
},
}

for i, tt := range tests {
t.Run("", func(t *testing.T) {
ctx := context.TODO()
resp, err := tt.m.Allocate(ctx, tt.req)
assert.NoError(t, err)
assert.Equal(t, 1, len(resp.ContainerResponses))
devices := resp.ContainerResponses[0].Devices
assert.Equal(t, mluMonitorDeviceName, devices[0].HostPath)
switch i {
case 0:
assert.Equal(t, 11, len(devices))
assert.Equal(t, mluMonitorDeviceName, devices[0].HostPath)
assert.Equal(t, mluMsgqDeviceName+":0", devices[1].HostPath)
assert.Equal(t, mluRPCDeviceName+":0", devices[2].HostPath)
assert.Equal(t, mluCmsgDeviceName+"0", devices[3].HostPath)
assert.Equal(t, mluCommuDeviceName+"0", devices[4].HostPath)
assert.Equal(t, mluDeviceName+"0", devices[5].HostPath)
assert.Equal(t, mluMsgqDeviceName+":1", devices[6].HostPath)
assert.Equal(t, mluRPCDeviceName+":1", devices[7].HostPath)
assert.Equal(t, mluCmsgDeviceName+"1", devices[8].HostPath)
assert.Equal(t, mluCommuDeviceName+"1", devices[9].HostPath)
assert.Equal(t, mluDeviceName+"1", devices[10].HostPath)
case 1:
assert.Equal(t, 3, len(devices))
assert.Equal(t, mluMonitorDeviceName, devices[0].HostPath)
assert.Equal(t, mluCommuDeviceName+"1", devices[1].HostPath)
assert.Equal(t, mluDeviceName+"1", devices[2].HostPath)
}
})
}
}

func TestCambriconDevicePluginAllocateSriov(t *testing.T) {
devs := []*pluginapi.Device{
{
ID: "MLU-testdevice-sn0001--fake--1",
},
{
ID: "MLU-testdevice-sn0001--fake--2",
},
}
devsInfo := []*cndev.Device{
{
UUID: "MLU-testdevice-sn0001--fake--1",
Path: "/dev/cambricon_dev0vf1",
},
{
UUID: "MLU-testdevice-sn0001--fake--2",
Path: "/dev/cambricon_dev0vf2",
},
}

tests := []struct {
m *CambriconDevicePlugin
req *pluginapi.AllocateRequest
}{
{
m: &CambriconDevicePlugin{
devs: devs,
devsInfo: devsInfo,
feature: sriovShare,
deviceList: &deviceList{
hasCtrlDev: true,
hasMsgqDev: true,
hasRPCDev: true,
hasCmsgDev: true,
hasCommuDev: true,
},
},
req: &pluginapi.AllocateRequest{
ContainerRequests: []*pluginapi.ContainerAllocateRequest{
{
DevicesIDs: []string{
"MLU-testdevice-sn0001--fake--1",
"MLU-testdevice-sn0001--fake--2",
},
},
},
},
},
{
m: &CambriconDevicePlugin{
devs: devs,
devsInfo: devsInfo,
feature: sriovShare,
deviceList: &deviceList{
hasCtrlDev: true,
hasCommuDev: true,
},
},
req: &pluginapi.AllocateRequest{
ContainerRequests: []*pluginapi.ContainerAllocateRequest{
{
DevicesIDs: []string{
"MLU-testdevice-sn0001--fake--2",
},
},
},
},
},
}

for i, tt := range tests {
t.Run("", func(t *testing.T) {
ctx := context.TODO()
resp, err := tt.m.Allocate(ctx, tt.req)
assert.NoError(t, err)
assert.Equal(t, 1, len(resp.ContainerResponses))
devices := resp.ContainerResponses[0].Devices
assert.Equal(t, mluMonitorDeviceName, devices[0].HostPath)
switch i {
case 0:
assert.Equal(t, 5, len(devices))
assert.Equal(t, mluMonitorDeviceName, devices[0].HostPath)
assert.Equal(t, mluCommuDeviceName+"0vf1", devices[1].HostPath)
assert.Equal(t, mluDeviceName+"0vf1", devices[2].HostPath)
assert.Equal(t, mluCommuDeviceName+"0vf2", devices[3].HostPath)
assert.Equal(t, mluDeviceName+"0vf2", devices[4].HostPath)
case 1:
assert.Equal(t, 3, len(devices))
assert.Equal(t, mluMonitorDeviceName, devices[0].HostPath)
assert.Equal(t, mluCommuDeviceName+"0vf2", devices[1].HostPath)
assert.Equal(t, mluDeviceName+"0vf2", devices[2].HostPath)
}
})
}
}

func TestCambriconDevicePluginAllocateEnvShare(t *testing.T) {
devs := []*pluginapi.Device{
{
ID: "MLU-testdevice-sn0001-_-1",
},
{
ID: "MLU-testdevice-sn0001-_-2",
},
}
devsInfo := []*cndev.Device{
{
UUID: "MLU-testdevice-sn0001-_-1",
Path: "/dev/cambricon_dev0",
},
{
UUID: "MLU-testdevice-sn0001-_-2",
Path: "/dev/cambricon_dev0",
},
}
req := &pluginapi.AllocateRequest{
ContainerRequests: []*pluginapi.ContainerAllocateRequest{
{
DevicesIDs: []string{
"MLU-testdevice-sn0001-_-1",
},
},
},
}

tests := []struct {
m *CambriconDevicePlugin
req *pluginapi.AllocateRequest
}{
{
m: &CambriconDevicePlugin{
devs: devs,
devsInfo: devsInfo,
feature: envShare,
deviceList: &deviceList{
hasCtrlDev: true,
hasMsgqDev: true,
hasRPCDev: true,
hasCmsgDev: true,
hasCommuDev: true,
},
},
req: req,
},
{
m: &CambriconDevicePlugin{
devs: devs,
devsInfo: devsInfo,
feature: envShare,
deviceList: &deviceList{
hasCtrlDev: true,
hasCommuDev: true,
},
},
req: req,
},
}

for i, tt := range tests {
t.Run("", func(t *testing.T) {
ctx := context.TODO()
resp, err := tt.m.Allocate(ctx, tt.req)
assert.NoError(t, err)
assert.Equal(t, 1, len(resp.ContainerResponses))
devices := resp.ContainerResponses[0].Devices
switch i {
case 0:
assert.Equal(t, 6, len(devices))
assert.Equal(t, mluMonitorDeviceName, devices[0].HostPath)
assert.Equal(t, mluMsgqDeviceName+":0", devices[1].HostPath)
assert.Equal(t, mluRPCDeviceName+":0", devices[2].HostPath)
assert.Equal(t, mluCmsgDeviceName+"0", devices[3].HostPath)
assert.Equal(t, mluCommuDeviceName+"0", devices[4].HostPath)
assert.Equal(t, mluDeviceName+"0", devices[5].HostPath)
case 1:
assert.Equal(t, 3, len(devices))
assert.Equal(t, mluMonitorDeviceName, devices[0].HostPath)
assert.Equal(t, mluCommuDeviceName+"0", devices[1].HostPath)
assert.Equal(t, mluDeviceName+"0", devices[2].HostPath)
}
})
}
}

+ 0
- 18
third-party/cambricon-k8s-device-plugin/device-plugin/test/Dockerfile View File

@@ -1,18 +0,0 @@
# Copyright 2020 Cambricon, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

ARG BASE_IMAGE
FROM ${BASE_IMAGE}
ENV MOCK_JSON=/mock.json
COPY mock.json /

+ 0
- 137
third-party/cambricon-k8s-device-plugin/device-plugin/test/device-plugin-integration-test.sh View File

@@ -1,137 +0,0 @@
#!/bin/bash
# Copyright 2020 Cambricon, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

function mock_mlu100() {
sudo mknod /dev/cambricon_c10Dev0 c 239 0 || true
sudo mknod /dev/cambricon_c10Dev1 c 239 1 || true
sudo mknod /dev/cambricon_c10Dev2 c 239 2 || true
sudo mknod /dev/cambricon_c10Dev3 c 239 3 || true
sudo mknod /dev/cncodec_dev c 10 58 || true
sudo mknod /dev/cnmon_dev c 238 0 || true
}

function mock_mlu270() {
sudo mknod /dev/cambricon_dev0 c 240 0 || true
sudo mknod /dev/cambricon_dev1 c 240 1 || true
sudo mknod /dev/cambricon_dev2 c 240 2 || true
sudo mknod /dev/cambricon_dev3 c 240 3 || true
sudo mknod /dev/cambricon_dev4 c 240 4 || true
sudo mknod /dev/cambricon_dev5 c 240 5 || true
sudo mknod /dev/cambricon_dev6 c 240 6 || true
sudo mknod /dev/cambricon_dev7 c 240 7 || true

sudo mknod /dev/cambr-msgq:0 c 241 0 || true
sudo mknod /dev/cambr-msgq:1 c 241 1 || true
sudo mknod /dev/cambr-msgq:2 c 241 2 || true
sudo mknod /dev/cambr-msgq:3 c 241 3 || true
sudo mknod /dev/cambr-msgq:4 c 241 4 || true
sudo mknod /dev/cambr-msgq:5 c 241 5 || true
sudo mknod /dev/cambr-msgq:6 c 241 6 || true
sudo mknod /dev/cambr-msgq:7 c 241 7 || true

sudo mknod /dev/cambr-rpc:0 c 242 0 || true
sudo mknod /dev/cambr-rpc:1 c 242 1 || true
sudo mknod /dev/cambr-rpc:2 c 242 2 || true
sudo mknod /dev/cambr-rpc:3 c 242 3 || true
sudo mknod /dev/cambr-rpc:4 c 242 4 || true
sudo mknod /dev/cambr-rpc:5 c 242 5 || true
sudo mknod /dev/cambr-rpc:6 c 242 6 || true
sudo mknod /dev/cambr-rpc:7 c 242 7 || true

sudo mknod /dev/cmsg_ctrl0 c 243 0 || true
sudo mknod /dev/cmsg_ctrl1 c 243 1 || true
sudo mknod /dev/cmsg_ctrl2 c 243 2 || true
sudo mknod /dev/cmsg_ctrl3 c 243 3 || true
sudo mknod /dev/cmsg_ctrl4 c 243 4 || true
sudo mknod /dev/cmsg_ctrl5 c 243 5 || true
sudo mknod /dev/cmsg_ctrl6 c 243 6 || true
sudo mknod /dev/cmsg_ctrl7 c 243 7 || true

sudo mknod /dev/commu0 c 244 0 || true
sudo mknod /dev/commu1 c 244 1 || true
sudo mknod /dev/commu2 c 244 2 || true
sudo mknod /dev/commu3 c 244 3 || true
sudo mknod /dev/commu4 c 244 4 || true
sudo mknod /dev/commu5 c 244 5 || true
sudo mknod /dev/commu6 c 244 6 || true
sudo mknod /dev/commu7 c 244 7 || true

sudo mknod /dev/cambricon_ctl c 245 0 || true
}

function remove_devices() {
sudo rm -f /dev/cambricon_c10Dev* || true
sudo rm -f /dev/cncodec_dev || true
sudo rm -f /dev/cnmon_dev || true

sudo rm -f /dev/cambricon_dev* || true
sudo rm -f /dev/cambr-msgq* || true
sudo rm -f /dev/cambr-rpc* || true
sudo rm -f /dev/cmsg_ctrl* || true
sudo rm -f /dev/commu* || true
sudo rm -f /dev/cambricon_ctl || true
}

function do_recover() {
echo "Recovering testing environments"

remove_devices

kubectl delete ds cambricon-device-plugin-daemonset -n kube-system || true
pod=$(kubectl get pods -n kube-system -o name -l name=cambricon-device-plugin-ds) || true
kubectl wait --for=delete "$pod" -n kube-system --timeout=120s || true
rm -f test/mock.json || true
kubectl delete deployment binpack-n1 || true
mapfile -t PODS < <(kubectl get pods -o name -l app=binpack-1) || true
kubectl wait --for=delete "${PODS[0]}" --timeout=120s || true
mapfile -t images < <(docker images -q cambricon-k8s-device-plugin) || true
mapfile -t -O "${#images[@]}" images < <(docker images -f "dangling=true" -q) || true
for image in "${images[@]}"; do
docker rmi "$image" || true
done
}

do_recover

mock_mlu100

./test/do-test-device-plugin.sh MLU100 || {
echo "MLU100 Device Plugin Test Failed"
exit 1
}

echo "=================================="
echo "MLU100 Device Plugin Test Passed"
echo "=================================="

do_recover

mock_mlu270
./test/do-test-device-plugin.sh MLU270 default || {
echo "MLU270 Device Plugin Test Default Mode Failed"
exit 1
}

do_recover

mock_mlu270
./test/do-test-device-plugin.sh MLU270 env_share || {
echo "MLU270 Device Plugin Test Env Share Mode Failed"
exit 1
}

echo "=================================="
echo "MLU270 Device Plugin Test Passed"
echo "=================================="

+ 0
- 107
third-party/cambricon-k8s-device-plugin/device-plugin/test/do-test-device-plugin.sh View File

@@ -1,107 +0,0 @@
#!/bin/bash
# Copyright 2020 Cambricon, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.


set -e

function test_mlu100() {
sed "s|replicas: .*|replicas: 2|" examples/deployment.yaml >test/mock-deployment.yaml
sed -i "s|cambricon.com/mlu: .*|cambricon.com/mlu: 2|" test/mock-deployment.yaml
kubectl create -f test/cambricon-device-plugin.yml
pod=$(kubectl get pods -n kube-system -o name -l name=cambricon-device-plugin-ds)
kubectl wait --for=condition=Ready "$pod" -n kube-system --timeout=120s
kubectl create -f test/mock-deployment.yaml
mapfile -t PODS < <( kubectl get pods -o name -l app=binpack-1 )
for var in "${PODS[@]}"; do
kubectl wait --for=condition=Ready "$var" --timeout=120s
test "$(kubectl exec -ti "${var:4}" -- ls -l /dev | grep cambricon_c10Dev -c)" -eq 2
test "$(kubectl exec -ti "${var:4}" -- ls -l /dev | grep cnmon_dev -c)" -eq 1
test "$(kubectl exec -ti "${var:4}" -- ls -l /dev | grep cncodec_dev -c)" -eq 1
done
}

function test_mlu270_default() {
sed "s|replicas: .*|replicas: 2|" examples/deployment.yaml >test/mock-deployment.yaml
sed -i "s|cambricon.com/mlu: .*|cambricon.com/mlu: 2|" test/mock-deployment.yaml
kubectl create -f test/cambricon-device-plugin.yml
pod=$(kubectl get pods -n kube-system -o name -l name=cambricon-device-plugin-ds)
kubectl wait --for=condition=Ready "$pod" -n kube-system --timeout=120s
kubectl create -f test/mock-deployment.yaml
mapfile -t PODS < <( kubectl get pods -o name -l app=binpack-1 )
for var in "${PODS[@]}"; do
kubectl wait --for=condition=Ready "$var" --timeout=120s
test "$(kubectl exec -ti "${var:4}" -- ls -l /dev | grep cambricon_dev -c)" -eq 2
test "$(kubectl exec -ti "${var:4}" -- ls -l /dev | grep cambr-msgq -c)" -eq 2
test "$(kubectl exec -ti "${var:4}" -- ls -l /dev | grep cambr-rpc -c)" -eq 2
test "$(kubectl exec -ti "${var:4}" -- ls -l /dev | grep cmsg_ctrl -c)" -eq 2
test "$(kubectl exec -ti "${var:4}" -- ls -l /dev | grep commu -c)" -eq 2
test "$(kubectl exec -ti "${var:4}" -- ls -l /dev | grep cambricon_ctl -c)" -eq 1
done
}

function test_mlu270_env_share() {
sed -i "s|default|env-share|" test/cambricon-device-plugin.yml
sed "s|replicas: .*|replicas: 16|" examples/deployment.yaml >test/mock-deployment.yaml
sed -i "s|cambricon.com/mlu: .*|cambricon.com/mlu: 1|" test/mock-deployment.yaml
sed -i "s|value: \"0\"|value: \"2\"|" test/cambricon-device-plugin.yml
kubectl create -f test/cambricon-device-plugin.yml
pod=$(kubectl get pods -n kube-system -o name -l name=cambricon-device-plugin-ds)
kubectl wait --for=condition=Ready "$pod" -n kube-system --timeout=120s
kubectl create -f test/mock-deployment.yaml
mapfile -t PODS < <( kubectl get pods -o name -l app=binpack-1 )
for var in "${PODS[@]}"; do
kubectl wait --for=condition=Ready "$var" --timeout=120s
test "$(kubectl exec -ti "${var:4}" -- ls -l /dev | grep cambricon_dev -c)" -eq 1
test "$(kubectl exec -ti "${var:4}" -- ls -l /dev | grep cambr-msgq -c)" -eq 1
test "$(kubectl exec -ti "${var:4}" -- ls -l /dev | grep cambr-rpc -c)" -eq 1
test "$(kubectl exec -ti "${var:4}" -- ls -l /dev | grep cmsg_ctrl -c)" -eq 1
test "$(kubectl exec -ti "${var:4}" -- ls -l /dev | grep commu -c)" -eq 1
test "$(kubectl exec -ti "${var:4}" -- ls -l /dev | grep cambricon_ctl -c)" -eq 1
done
}

function test_mlu270() {
if [ "$1" == "default" ]; then
test_mlu270_default
elif [ "$1" == "env_share" ]; then
test_mlu270_env_share
fi
}

tag=$(date +%s)
mock_file="test/mockmlu100.json"

if [ "$1" == "MLU100" ]; then
echo "Test MLU100 Device Plugin"
mock_file="test/mockmlu100.json"
elif [ "$1" == "MLU270" ]; then
echo "Test MLU270 Device Plugin"
mock_file="test/mockmlu270.json"
fi

cp $mock_file test/mock.json

TAG=$tag LIBCNDEV=pkg/cndev/mock/libcndev.so ./build_image.sh
docker build --build-arg "BASE_IMAGE=cambricon-k8s-device-plugin:$tag" -t "cambricon-k8s-device-plugin:mock-$tag" test

sed "s|cambricon-k8s-device-plugin:[A-Za-z0-9\.]*|cambricon-k8s-device-plugin:mock-$tag|" examples/cambricon-device-plugin-daemonset.yaml >test/cambricon-device-plugin.yml

if [ "$1" == "MLU100" ]; then
test_mlu100
fi

if [ "$1" == "MLU270" ]; then
test_mlu270 "$2"
fi

+ 0
- 9
third-party/cambricon-k8s-device-plugin/device-plugin/test/mockmlu100.json View File

@@ -1,9 +0,0 @@
{
"num": 4,
"ret": 0,
"MLU": [1001111, 1001112, 1001113, 1001114],
"MLU_ret": [0, 0, 0, 0],
"health": [1, 1, 1, 1],
"health_ret": [0, 0, 0, 0],
"card_type": [0, 0, 0, 0]
}

+ 0
- 28
third-party/cambricon-k8s-device-plugin/device-plugin/test/mockmlu270.json View File

@@ -1,28 +0,0 @@
{
"num": 8,
"ret": 0,
"MLU": [
2701111,
2701112,
2701113,
2701114,
2701115,
2701116,
2701117,
2701118
],
"MLU_ret": [0, 0, 0, 0, 0, 0, 0, 0],
"health": [1, 1, 1, 1, 1, 1, 1, 1],
"health_ret": [0, 0, 0, 0, 0, 0, 0, 0],
"card_type": [1, 1, 1, 1, 1, 1, 1, 1],
"pcie_info": [
[0, 12, 13, 1],
[0, 12, 13, 2],
[0, 12, 13, 3],
[0, 12, 13, 4],
[0, 12, 13, 5],
[0, 12, 13, 6],
[0, 12, 13, 7],
[0, 12, 13, 8]
]
}

+ 0
- 34
third-party/k8s-fpga-device-plugin/.drone.yml View File

@@ -1,34 +0,0 @@
kind: pipeline
name: pipeline-octopus-k8s-fpga-device-plugin
platform:
os: linux
arch: amd64
steps:

- name: containerize
image: docker:18.09.7
volumes:
# - name: dockerlib
# path: /var/lib/docker
- name: dockersock
path: /var/run/docker.sock
- name: drone
path: /etc/drone
commands:
- . /etc/drone/env.sh
- . /etc/drone/docker_build.sh

trigger:
event:
- tag

volumes:
- name: dockerlib
host:
path: /var/lib/docker
- name: dockersock
host:
path: /var/run/docker.sock
- name: drone
host:
path: /etc/drone

+ 0
- 30
third-party/k8s-fpga-device-plugin/Dockerfile View File

@@ -1,30 +0,0 @@
#Copyright 2018 Xilinx Corporation. All Rights Reserved.
#Author: Brian Xu(brianx@xilinx.com)
#
#Licensed under the Apache License, Version 2.0 (the "License");
#you may not use this file except in compliance with the License.
#You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
#Unless required by applicable law or agreed to in writing, software
#distributed under the License is distributed on an "AS IS" BASIS,
#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#See the License for the specific language governing permissions and
#limitations under the License.

from golang:1.13 as builder
WORKDIR /app
COPY ./ ./

ENV GOPATH /app
ENV CGO_ENABLED 0
ENV GO111MODULE off

RUN go build -o k8s-fpga-device-plugin .

FROM ubuntu:16.04

COPY --from=builder /app/k8s-fpga-device-plugin /usr/local/bin/

ENTRYPOINT ["k8s-fpga-device-plugin"]

+ 0
- 17
third-party/k8s-fpga-device-plugin/FAQ.md View File

@@ -1,17 +0,0 @@
# FAQ
**Question: When I reserve a machine looking for a U250, I am assigned a node with a U250, but from within the pod, I can see the U250 and also the U280 (which is also present on that node). Is this intended behavior?**

**Answer:** This issue has been fixed form kubernetes version 1.17, if you are using previous versions of kubernetes you can try updating your kubernetes cluster to the latest version. The previous problem is multiple types of FGPA cards or Shell on one node can not be handled by Kubernetes. You can Check the following link for detailed info: [https://github.com/kubernetes/kubernetes/issues/70350](https://github.com/kubernetes/kubernetes/issues/70350)

**Question: When testing Vitis in AWS FPGA environment. There is an AFI agfi-069ddd533a748059b which is first loaded when I do the systemctl start mpd for the very first time when I boot the machine. Then, at the end inside my-pod when running the ./helloworld vector_addition_hw.awsxclbin, this time is the one associated to the vector_addition_hw.awsxclbin, AFI agfi-2 is loaded, and the one effectively used. Is both have “vector_addition_hw” in their name?**

**Answer:** AWS F1 allows a user to use FPGA in two ways: traditional hardware design flow using [HDK](https://clicktime.symantec.com/3DiMRHsPYvzA8YqaAYokmLV6H2?u=https%3A%2F%2Fgithub.com%2Faws%2Faws-fpga%2Fblob%2Fmaster%2Fhdk%2FREADME.md) and 2) software like flow using Use [SDAccel/Vitis](https://clicktime.symantec.com/3MGuf45R2JanX4SS6wJtNTM6H2?u=https%3A%2F%2Fgithub.com%2Faws%2Faws-fpga%2Fblob%2Fmaster%2FSDAccel%2FREADME.md). The flow you are using is the SDAccel/Vitis one. In order to differentiate the two flows, AWS came up with a device ID scheme that Xilinx adheres to. There is a Xilinx Run Time deamon named [MPD](https://clicktime.symantec.com/3Rz2catG2XLeoDpWiMmdeq36H2?u=https%3A%2F%2Fxilinx.github.io%2FXRT%2Fmaster%2Fhtml%2Fcloud_vendor_support.html) that is started using the command “systemctl start mpd” as part of installing XRT. This daemon is required to download the prebuilt AFI “agfi-069ddd533a748059b” to allow AWS hardware to differentiate the SDAccel/Vitis from form the HDK flow. When user application runs, the AFI is replaced by the user AFI. Every time you reboot the machine, the [MPD](https://clicktime.symantec.com/3Rz2catG2XLeoDpWiMmdeq36H2?u=https%3A%2F%2Fxilinx.github.io%2FXRT%2Fmaster%2Fhtml%2Fcloud_vendor_support.html) will be restarted and hence you will see that agfi-069ddd533a748059b got installed. Once the Accelerator Pod runs, it could install the AFI of interest.

**Question: One application fails to run inside container, with possible error like “Failed to find Xilinx platform”. It can run well outside container. xbutil list show the device existing inside container, same as that outside container.**

**Answer:** Linux is using ICDs ("Installable Client Drivers") to setup OpenCL. /etc/OpenCL/vendors/xilinx.icd is used to tell the ICD loader what OpenCL implementations (ICDs) are installed on the system. Some application is directly link to Linux system standard OpenCL lib but NOT Xilinx specified OpenCL lib. For this case, the OpenCL APIs in application will fail if the icd file is NOT set correctly.

The above problem is due to missing /etc/OpenCL/vendors/xilinx.icd inside container. Using following command to copy /etc/OpenCL/vendors/xilinx.icd (with one line “/opt/xilinx/xrt/lib/libxilinxopencl.so”) from host into container can solve this issue.
```
docker cp /etc/OpenCL/vendors/xilinx.icd containerID:/etc/OpenCL/vendors/xilinx.icd
```

+ 0
- 202
third-party/k8s-fpga-device-plugin/LICENSE View File

@@ -1,202 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/

TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

1. Definitions.

"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.

"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.

"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.

"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.

"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.

"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.

"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).

"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.

"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."

"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.

2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.

3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.

4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:

(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and

(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and

(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and

(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.

You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.

5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.

6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.

7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.

8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.

9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.

END OF TERMS AND CONDITIONS

APPENDIX: How to apply the Apache License to your work.

To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "{}"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.

Copyright {yyyy} {name of copyright owner}

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.


+ 0
- 38
third-party/k8s-fpga-device-plugin/README.md View File

@@ -1,38 +0,0 @@
# k8s-fpga-device-plugin
## 修改说明
源项目地址为https://github.com/Xilinx/FPGA_as_a_Service/tree/master/k8s-fpga-device-plugin
主要修改的地方:
1. 原先resource的格式为xilinx.com/fpga-xilinx_u200_xdma_201830_1-1542252769,带有型号等信息,修改为不带型号信息xilinx.com/fpga(类似nvidia.com/gpu)
2. 修改Dockerfile,增加编译部分

## About
The Xilinx FPGA device plugin for Kubernetes is a [Daemonset]([https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/](https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/)) deployed on the Kubernetes(k8s) cluster which allows you to:

* Discover the FPGAs inserted in each node of the cluster and expose information about FPGA such as number of FPGA, Shell (Target Platform) type and etc.
* Run FPGA accessible containers in the k8s cluster


If you already have an docker and kubernetes environment, you can follow the [Quick Start](https://github.com/Xilinx/FPGA_as_a_Service/blob/master/k8s-fpga-device-plugin/quickstart.md) to test k8s-fpga-device-plugin on your own cluster.
You can check the [Full Tutorial](https://github.com/Xilinx/FPGA_as_a_Service/blob/master/k8s-fpga-device-plugin/full-tutorial.md) if you want to build docker, kuberetes cluster environment and test k8s-fpga-device-plugin from the beginning.


For detailed information about k8s-fpga-device-plugin, Docker and Kubernetes, you can renferece following links:


|Detailed Info | Description |
|---------------|-----------------|
| [Kubernetes device plugin](https://kubernetes.io/docs/concepts/extend-kubernetes/compute-storage-net/device-plugins/) | Kubernetes community documentation about Kubernetes plugin |
| [AWS Kubernetes FPGA Plugin](https://github.com/Xilinx/FPGA_as_a_Service/tree/master/k8s-fpga-device-plugin/aws) | Install and test k8s-fpga-device-plugin on AWS FPGA |
| [Kubernetes Docker tutorial](https://github.com/Xilinx/FPGA_as_a_Service/tree/master/k8s-fpga-device-plugin/docker) | Build docker image and test with k8s-fpga-device-plugin |
| [Quick Start](https://github.com/Xilinx/FPGA_as_a_Service/blob/master/k8s-fpga-device-plugin/quickstart.md) | Quick start on how to install and test k8s-fpga-device-plugin |
| [K8S FPGA Device Plugin Full tutorial](https://github.com/Xilinx/FPGA_as_a_Service/blob/master/k8s-fpga-device-plugin/full-tutorial.md) | Step by step tutorial starts from install docker and Kubernetes cluster |
| [FAQ](https://github.com/Xilinx/FPGA_as_a_Service/blob/master/k8s-fpga-device-plugin/FAQ.md) | Frequently asked questions |

## Prerequisites
* All FPGAs have the Shell(Target Platform) flashed already.
* XRT(version is no older than 2018.3) installed on all worker nodes where there are FPGA(s) inserted
* Container runtime in k8s is docker
* k8s version >= 1.17 (all tests have been running with version 1.17. Old version may or may not work)

## Contact
Email: k8s_dev@xilinx.com

+ 0
- 56
third-party/k8s-fpga-device-plugin/aws-accelator-pod.yaml View File

@@ -1,56 +0,0 @@
#Copyright 2020 Xilinx Corporation. All Rights Reserved.
#Author: Brian Xu(brianx@xilinx.com)
#
#Licensed under the Apache License, Version 2.0 (the "License");
#you may not use this file except in compliance with the License.
#You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
#Unless required by applicable law or agreed to in writing, software
#distributed under the License is distributed on an "AS IS" BASIS,
#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#See the License for the specific language governing permissions and
#limitations under the License.
apiVersion: apps/v1
kind: Deployment
metadata:
name: accelator-pod
spec:
selector:
matchLabels:
app: accelator-pod
replicas: 1
template:
metadata:
labels:
app: accelator-pod
spec:
containers:
- name: accelator-pod
image: memo40k/k8s:accelator_pod
imagePullPolicy: IfNotPresent
resources:
limits:
xilinx.com/fpga-xilinx_aws-vu9p-f1_dynamic_5_0-43981: 1
ports:
- name: server
containerPort: 8010
command: ["/opt/test/run.sh"]
dnsPolicy: ClusterFirst
---
apiVersion: v1
kind: Service
metadata:
name: fpga-server-svc
spec:
selector:
app: accelator-pod
clusterIP: 10.96.59.3
ports:
- name: server
protocol: TCP
port: 8010
type: NodePort
externalTrafficPolicy: Local


+ 0
- 194
third-party/k8s-fpga-device-plugin/aws-readme.md View File

@@ -1,194 +0,0 @@
# xilinx fpga device plugin on AWS F1
## Note

* XRT 2019.2+ is required. Older version of XRT doesn't work
* The awsxclbin used by the helloworld may not be accessible in all AWS regions. So far it is only
accessible in the follow regions,
- us-east-1 (N.Virginia)
- us-west-2 (Oregon)
- eu-west-1 (Ireland)
- asia-pacific (Sydeny)

Please run the following cmd to see if it is available in your F1.
```
# fpga-load-local-image -S 0 -I agfi-08025ce1d75d038c0
AFI 0 agfi-08025ce1d75d038c0 loaded 0 ok 0 0x04261818
AFIDEVICE 0 0x1d0f 0xf010 0000:00:1d.0
```

## Build XRT on F1

```
git clone http://github.com/aws/aws-fgpa.git
git clone -b 2019.2.0.3 http://github.com/xilinx/xrt.git
xrt/src/runtime_src/tools/scripts/xrtdeps.sh
scl enable devtoolset-6 bash (centos only, ubuntu skip)
cd aws-fpga
source sdaccel_setup.sh
cd ../xrt/build
./build.sh
```

## Install XRT

```
cd xrt/build/Release
yum install ./name_of_xrt_pkg
yum install ./name_of_aws_pkg
```

or

```
cd xrt/build/Release
apt install ./name_of_xrt_pkg
apt install ./name_of_aws_pkg
```

check mpd status and fpga status

```
# systemctl status mpd
● mpd.service - Xilinx Management Proxy Daemon (MPD)
Loaded: loaded (/etc/systemd/system/mpd.service; enabled; vendor preset: disabled)
Active: active (running) since Thu 2020-02-06 23:21:10 UTC; 3 days ago
Main PID: 10978 (mpd)
Tasks: 3
Memory: 20.0K
CGroup: /system.slice/mpd.service
└─10978 /opt/xilinx/xrt/bin/mpd
# /opt/xilinx/xrt/bin/xbutil scan
INFO: Found total 1 card(s), 1 are usable
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
System Configuration
OS name: Linux
Release: 3.10.0-1062.4.1.el7.x86_64
Version: #1 SMP Fri Oct 18 17:15:30 UTC 2019
Machine: x86_64
Glibc: 2.17
Distribution: CentOS Linux 7 (Core)
Now: Mon Feb 10 18:12:21 2020
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
XRT Information
Version: 2.3.0
Git Hash: 9e13d57c4563e2c19bf5f518993f6e5a8dadc18a
Git Branch: HEAD
Build Date: 2020-02-06 23:07:50
XOCL: 2.3.0,9e13d57c4563e2c19bf5f518993f6e5a8dadc18a
XCLMGMT: 2.3.0,9e13d57c4563e2c19bf5f518993f6e5a8dadc18a
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
[0] 0000:00:1d.0 xilinx_aws-vu9p-f1_dynamic_5_0(ts=0xabcd) user(inst=128)

```

## Install docker

```
yum install docker
systemctl enable docker
```

or

```
apt install docker.io
systemctl enable docker
```

# Install kubernetes
please refer,

https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/
https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/create-cluster-kubeadm/
```
swapoff -a
cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
EOF
setenforce 0
sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config
yum install -y kubelet kubeadm kubectl --disableexcludes=kubernetes
systemctl enable --now kubelet
```

or

```
swapoff -a
sudo apt-get update && sudo apt-get install -y apt-transport-https curhttps://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/lhttps://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/
curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
cat <<EOF | sudo tee /etc/apt/sources.list.d/kubernetes.list
deb https://apt.kubernetes.io/ kubernetes-xenial main
EOF
sudo apt-get update
sudo apt-get install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl
```

## Create k8s cluster

```
kubeadm init
export KUBECONFIG=/etc/kubernetes/admin.conf
kubectl apply -f https://docs.projectcalico.org/v3.11/manifests/calico.yaml
kubectl taint nodes --all node-role.kubernetes.io/master-
```

## Deploy FPGA device plugin & helloworld add

```
kubectl create -f fpga-device-plugin.yaml
kubectl create -f aws-verify.yaml

```

## Run helloworld

check pod status, there will be a server pod with FPGA access and a client pod without FPGA access

```
# kubectl get pod
NAME READY STATUS RESTARTS AGE
test-server-76759df476-xgv6x 1/1 Running 0 84m
testpod 1/1 Running 0 84m
```

run helloworld -- client pod sends request to server pod, and server pod run helloworld on FPGA, then sends the output back to client as response

```
# kubectl exec testpod python /opt/test/server-test.py client
Send request to server...
Response from server:
Found Platform
Platform Name: Xilinx
Found Device=xilinx_aws-vu9p-f1_dynamic_5_0
INFO: Reading /opt/test/vector_addition_hw.awsxclbin
Loading: '/opt/test/vector_addition_hw.awsxclbin'
Result =
Hello World !!!
Hello World !!!
Hello World !!!
Hello World !!!
Hello World !!!
Hello World !!!
Hello World !!!
Hello World !!!
Hello World !!!
Hello World !!!
Hello World !!!
Hello World !!!
Hello World !!!
Hello World !!!
Hello World !!!
Hello World !!!
TEST PASSED

--END--


+ 0
- 26
third-party/k8s-fpga-device-plugin/aws-test-client-pod.yaml View File

@@ -1,26 +0,0 @@
#Copyright 2020 Xilinx Corporation. All Rights Reserved.
#Author: Brian Xu(brianx@xilinx.com)
#
#Licensed under the Apache License, Version 2.0 (the "License");
#you may not use this file except in compliance with the License.
#You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
#Unless required by applicable law or agreed to in writing, software
#distributed under the License is distributed on an "AS IS" BASIS,
#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#See the License for the specific language governing permissions and
#limitations under the License.
apiVersion: v1
kind: Pod
metadata:
name: test-client-pod
spec:
containers:
- name: test-client-pod
image: memo40k/k8s:test_client_pod
command: ["/bin/sh"]
args: ["-c", "while true; do echo hello; sleep 5;done;"]
dnsPolicy: ClusterFirst


+ 0
- 19
third-party/k8s-fpga-device-plugin/aws/Dockerfile View File

@@ -1,19 +0,0 @@
#Copyright 2019 Xilinx Corporation. All Rights Reserved.
#Author: Brian Xu(brianx@xilinx.com)
#
#Licensed under the Apache License, Version 2.0 (the "License");
#you may not use this file except in compliance with the License.
#You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
#Unless required by applicable law or agreed to in writing, software
#distributed under the License is distributed on an "AS IS" BASIS,
#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#See the License for the specific language governing permissions and
#limitations under the License.
FROM ubuntu:16.04

COPY aws-fpga-device-plugin /usr/local/bin/

ENTRYPOINT ["aws-fpga-device-plugin"]

+ 0
- 84
third-party/k8s-fpga-device-plugin/aws/README.md View File

@@ -1,84 +0,0 @@
# AWS Kubernetes FPGA Plugin

## Note

The FPGA plugin in this folder is only for AWS running XRT prior 2019.2. In XRT 2019.2,
the normal plugin in the parent folder works also for AWS, and there is no limitation
mentioned below for this plugin.

## About

This kubernetes FPGA device plugin is created for cluster running on aws F1 nodes.

The FPGA cards in F1 are different to those Xilinx ones. The differences are in both hardware
and software, so the plugin created for Xilinx FPGA & XRT doesn't work for AWS.

In this dedicated plugin,

* Shell version is hard-coded in XRT for aws, and it is not exported to sysfs. so the
plugin also hard-codes the shell version as "xilinx_aws-vu9p-f1-04261818_dynamic_5_0"
* Shell timestamp is not being used. To keep the same FPGA resource format, the shell
timestamp info is set as "0"

## Limitations on user pods

The plugin itself only relies on a readonly sysfs, so the same to the plugin for Xilinx
FPGAs, this aws plugin is also deployed as normal container in which the sysfs is mounted
as readonly. While for user pods, in order to run awssak scan/list and/or aws specific
fpga- commands, root access has to be granted within the container, which means, in addtion
to the install of xrt/aws-xrt and aws fpga tools from https://github.com/aws/aws-fpga.git,
the user pods have to be deployed in 'privileged' mode.

## Quick start

Once the kubernetes cluster and XRT is being setup on aws, you can follow following step to install and test the kubernetes plugin.

### Step 1: Deploy the plugin as daemonset
Download plugin source:
```
#git clone https://github.com/Xilinx/FPGA_as_a_Service.git
```
Deploy FPGA device plugin as daemonset:
```
#kubectl create -f ./FPGA_as_a_Service/k8s-fpga-device-plugin/trunk/fpga-device-plugin.yml
```
To check the status of daemonset:
```
#kubectl get pod -n kube-system
```
Get node name:
```
#kubectl get node
```
Check FPGA resource in the worker node:
```
#kubectl describe node nodename
```
You should get the FPGA resources name under the pods information.

### Step 2: deploy a user pod
```
#kubectl create -f mypod.yaml
```

For more details, please refer to the README file of the Xilinx FPGA plugin
### Step 3: Run the test in pod
After user pod status turns to Running, run hello world in the pod:
```
#kubectl exec -it my-pod /bin/bash
#my-pod>source /opt/xilinx/xrt/setup.sh
#my-pod>export INTERNAL_BUILD=1
#my-pod>xbutil scan
#my-pod>cd /opt/test/
#my-pod>./helloworld vector_addition_hw.awsxclbin
```
**Note:** Need to set the INTERNAL_BUILD=1 if xbutil complain the version not match:

## Build plugin binary

```
#./build
```

The output is the binary 'aws-fpga-device-plugin' in the current folder


+ 0
- 44
third-party/k8s-fpga-device-plugin/aws/aws-fpga-device-plugin.yaml View File

@@ -1,44 +0,0 @@
#Portions Copyright 2019 Xilinx Inc.
#Author: Brian Xu(brianx@xilinx.com)
#
#Licensed under the Apache License, Version 2.0 (the "License");
#you may not use this file except in compliance with the License.
#You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
#Unless required by applicable law or agreed to in writing, software
#distributed under the License is distributed on an "AS IS" BASIS,
#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#See the License for the specific language governing permissions and
#limitations under the License.
apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
name: fpga-device-plugin-daemonset
namespace: kube-system
spec:
template:
metadata:
annotations:
scheduler.alpha.kubernetes.io/critical-pod: ""
labels:
name: aws-fpga-device-plugin
spec:
tolerations:
- key: CriticalAddonsOnly
operator: Exists
containers:
- image: xilinxatg/aws_k8s_fpga_plugin:06272019
name: aws-fpga-device-plugin
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop: ["ALL"]
volumeMounts:
- name: device-plugin
mountPath: /var/lib/kubelet/device-plugins
volumes:
- name: device-plugin
hostPath:
path: /var/lib/kubelet/device-plugins

+ 0
- 14
third-party/k8s-fpga-device-plugin/aws/build View File

@@ -1,14 +0,0 @@
#!/bin/sh

PLUGIN=aws-fpga-device-plugin

FMT="*.go"
echo "Checking gofmt..."
fmtRes=$(gofmt -l $FMT)
if [ -n "${fmtRes}" ]; then
echo -e "gofmt checking failed:\n${fmtRes}"
exit 255
fi

echo "Building plugins"
go build -o $PLUGIN

+ 0
- 157
third-party/k8s-fpga-device-plugin/aws/fpga_aws.go View File

@@ -1,157 +0,0 @@
// Copyright 2019 Xilinx Corporation. All Rights Reserved.
// Author: Brian Xu(brianx@xilinx.com)
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package main

import (
"fmt"
"io/ioutil"
pluginapi "k8s.io/kubernetes/pkg/kubelet/apis/deviceplugin/v1beta1"
"path"
"strconv"
"strings"
)

const (
SysfsDevices = "/sys/bus/pci/devices"
UserPrefix = "/dev/dri"
UserPFKeyword = "drm"
DRMSTR = "renderD"
VendorFile = "vendor"
DeviceFile = "device"
AWSF1VendorID = "0x1d0f"
AWSF1UserPFDeviceID = "0x1042"
AWSF1UserPFDeviceIDSdx = "0xf010"
AWSDSAVer = "xilinx_aws-vu9p-f1-04261818_dynamic_5_0" //hard coded so far
)

type Pairs struct {
Mgmt string
User string
}

type Device struct {
index string
shellVer string
timestamp string
DBDF string // this is for user pf
deviceID string //devid of the user pf
Healthy string
Nodes *Pairs
}

func GetFileNameFromPrefix(dir string, prefix string) (string, error) {
userFiles, err := ioutil.ReadDir(dir)
if err != nil {
return "", fmt.Errorf("Can't read folder %s \n", dir)
}
for _, userFile := range userFiles {
fname := userFile.Name()

if !strings.HasPrefix(fname, prefix) {
continue
}
return fname, nil
}
return "", nil
}

func GetFileContent(file string) (string, error) {
if buf, err := ioutil.ReadFile(file); err != nil {
return "", fmt.Errorf("Can't read file %s \n", file)
} else {
ret := strings.Trim(string(buf), "\n")
return ret, nil
}
}

func GetDevices() ([]Device, error) {
var devices []Device
pairMap := make(map[string]*Pairs)
pciFiles, err := ioutil.ReadDir(SysfsDevices)
if err != nil {
return nil, fmt.Errorf("Can't read folder %s \n", SysfsDevices)
}

for _, pciFile := range pciFiles {
pciID := pciFile.Name()

fname := path.Join(SysfsDevices, pciID, VendorFile)
vendorID, err := GetFileContent(fname)
if err != nil {
return nil, err
}
if strings.EqualFold(vendorID, AWSF1VendorID) != true {
continue
}
fname = path.Join(SysfsDevices, pciID, DeviceFile)
devID, err := GetFileContent(fname)
if err != nil {
return nil, err
}
if strings.EqualFold(devID, AWSF1UserPFDeviceID) != true &&
strings.EqualFold(devID, AWSF1UserPFDeviceIDSdx) != true {
continue
}

DBD := pciID[:len(pciID)-2]
if _, ok := pairMap[DBD]; !ok {
pairMap[DBD] = &Pairs{
Mgmt: "",
User: "",
}
}

userDBDF := pciID
// get dsa version. So far the info is hard coded and not populated into sysfs.
dsaVer := AWSDSAVer
// get dsa timestamp. So far the info is not used by aws. using "0" here
dsaTs := "0"
// get user PF node
userpf, err := GetFileNameFromPrefix(path.Join(SysfsDevices, pciID, UserPFKeyword), DRMSTR)
if err != nil {
return nil, err
}
userNode := path.Join(UserPrefix, userpf)
pairMap[DBD].User = userNode

//TODO: check temp, power, fan speed etc, to give a healthy level
//so far, return Healthy
healthy := pluginapi.Healthy
devices = append(devices, Device{
index: strconv.Itoa(len(devices) + 1),
shellVer: dsaVer,
timestamp: dsaTs,
DBDF: userDBDF,
deviceID: devID,
Healthy: healthy,
Nodes: pairMap[DBD],
})
}
return devices, nil
}

/*
func main() {
devices, err := GetDevices()
if err != nil {
fmt.Printf("%s !!!\n", err)
return
}
for _, device := range devices {
fmt.Printf("%v", device)
}
}
*/

+ 0
- 1
third-party/k8s-fpga-device-plugin/aws/main.go View File

@@ -1 +0,0 @@
../main.go

+ 0
- 36
third-party/k8s-fpga-device-plugin/aws/mypod.yaml View File

@@ -1,36 +0,0 @@
#Copyright 2019 Xilinx Inc.
#Author: Brian Xu(brianx@xilinx.com)
#
#Licensed under the Apache License, Version 2.0 (the "License");
#you may not use this file except in compliance with the License.
#You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
#Unless required by applicable law or agreed to in writing, software
#distributed under the License is distributed on an "AS IS" BASIS,
#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#See the License for the specific language governing permissions and
#limitations under the License.
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
containers:
- name: my-pod
image: centos:bx #user needs to build its own docker image
securityContext:
privileged: true
resources:
limits:
xilinx.com/fpga-xilinx_aws-vu9p-f1-04261818_dynamic_5_0-0: 1
command: ["/bin/sh"]
args: ["-c", "while true; do echo hello; sleep 10;done"]
volumeMounts:
- name: sys
mountPath: /sys
volumes:
- name: sys
hostPath:
path: /sys

+ 0
- 1
third-party/k8s-fpga-device-plugin/aws/server.go View File

@@ -1 +0,0 @@
../server.go

+ 0
- 1
third-party/k8s-fpga-device-plugin/aws/watcher.go View File

@@ -1 +0,0 @@
../watcher.go

BIN
third-party/k8s-fpga-device-plugin/bin/k8s-fpga-device-plugin View File


+ 0
- 18
third-party/k8s-fpga-device-plugin/build View File

@@ -1,18 +0,0 @@
#!/bin/sh
REPO_PATH="."
export GOPATH=${PWD}

export GO15VENDOREXPERIMENT=1
export GOBIN=${PWD}/bin

FMT="*.go"
echo "Checking gofmt..."
fmtRes=$(gofmt -l $FMT)
if [ -n "${fmtRes}" ]; then
echo -e "gofmt checking failed:\n${fmtRes}"
exit 255
fi

echo "Building plugins"
go install "$@" ${REPO_PATH}
#mv bin/trunk bin/k8s-fpga-device-plugin

+ 0
- 106
third-party/k8s-fpga-device-plugin/docker/README.md View File

@@ -1,106 +0,0 @@
## How to build new docker image and test it in k8s-fpga-device-plugin

We will use an example to explain how a new docker image with desired contents such as your xclbin, your host code etc. can be built. Please note that any accelerator (FPGA) docker image should be derived form the base docker Xilinx image **xilinxatg/aws-fpga-verify:20200131** already hosted at the Docker Hub.

### Prerequisites

To host a docker image, you need some sort of service. You can host it locally if you like (please read online docker instructions for that). However, this instruction uses [Docker Hub](https://hub.docker.com/) as the hosting service.

Go to [https://hub.docker.com/signup](https://hub.docker.com/signup) to create a Docker Hub account (if you do not have one already), and then create a docker repository.

In this document, we are using an example docker account named as **memo40k** and an example repository named as **k8s.** Please substitute these by your account and repository names respectively. Also, please note that you can set your repository as private if you do not want others to see it.

### Prepare docker images

####
Step 1: Login to your Docker Hub account

`#docker login -u <username> -p <password>`

#### Step 2: Create a docker file

Here we will use our github folder [**docker/build_fpga_server_docker**](https://github.com/Xilinx/FPGA_as_a_Service/tree/master/k8s-fpga-device-plugin/docker/build_fpga_server_docker) as an example. In this folder, **"server"** is a file folder that is to be added into our docker image. It has four files:

|File | Description|
|---|---|
| [fpga_algo.awsxclbin](https://github.com/Xilinx/FPGA_as_a_Service/blob/master/k8s-fpga-device-plugin/docker/build_fpga_server_docker/server/fpga_algo.awsxclbin "fpga_algo.awsxclbin")| This is the xclbin of the algorithm implemented on FPGA.|
| [fpga_host_exe](https://github.com/Xilinx/FPGA_as_a_Service/blob/master/k8s-fpga-device-plugin/docker/build_fpga_server_docker/server/fpga_host_exe "fpga_host_exe") | This is the host executable that downloads the xclbin to FPGA and interacts with the FPGA. |
| [fpga_server.py](https://github.com/Xilinx/FPGA_as_a_Service/blob/master/k8s-fpga-device-plugin/docker/build_fpga_server_docker/server/fpga_server.py "fpga_server.py")|This is a representative server program that calls the host executable and has ability to receive command from a client. One can merge this with host executable into one single server program in C++.|
| [run.sh](https://github.com/Xilinx/FPGA_as_a_Service/blob/master/k8s-fpga-device-plugin/docker/build_fpga_server_docker/server/run.sh "run.sh") | This sets environment and calls | fpga_server.py.

You can add any number of folders with any contents you need for your server to work.

The **xilinxatg/aws-fpga-verify:20200131** on docker hub is the base image as mentioned earlier. In this example, the folder **server** will be added to an example location **/opt/xilinx/k8s/** in the docker image.

`#touch Dockerfile `
create a dockerfile under the same folder with server

`#vi Dockerfile `
To add following two lines into Dockerfile
```
FROM xilinxatg/aws-fpga-verify:20200131
COPY docker /opt/xilinx/k8s/server
```
#### Step 3: Build new docker image

`#docker build -t memo40k/k8s:accelator_pod . `
It will build a new docker image called **accelerator_pod** using the docker file "**Dockerfile**" under the current folder
`#docker images `
You can run this command to check whether the new images **accelerator_pod** was created.
`# docker run -it <imageID>`
To test the docker image you just created, run the above. You should see the folder **server** added into the docker image.

#### Step 4: Push new image into docker hub

`#docker push memo40k/k8s:accelator_podk8`

You are all set.



#### Step 5: Create a docker image for client

Please repeat the steps 2 to 4 with your desired executable contents for the client to create another docker image called **test_client_pod**. You can use [build_test_client_docker](https://github.com/Xilinx/FPGA_as_a_Service/tree/master/k8s-fpga-device-plugin/docker/build_test_client_docker) as an example.



### Verify docker image

Use the yaml files: [aws-accelator-pod.yaml](https://github.com/Xilinx/FPGA_as_a_Service/blob/master/k8s-fpga-device-plugin/aws-accelator-pod.yaml) and [aws-test-client-pod.yaml](https://github.com/Xilinx/FPGA_as_a_Service/blob/master/k8s-fpga-device-plugin/aws-test-client-pod.yaml) to create accelerator and client pods respectively.



#### Step 1: Create accelerator and client pods

`#kubectl create -f aws-accelator-pod.yaml `
`#kubectl create -f aws-test-client-pod.yaml`

#### Step 2: Check pod status

After creating the two pods, there will be an accelerator pod with FPGA access, a client pod without FPGA access, an accelerator pod deployment service and a fpga-server-svc network service as shown below.

`#kubectl get pod`
```
NAME READY STATUS RESTARTS AGE
accelator-pod-ff67ff8b8-mwff 1/1 Running 0 22h
test-client-pod 1/1 Running 0 23h
```
`#kubectl get deployment`
```
NAME READY UP-TO-DATE AVAILABLE AGE
accelator-pod 1/1 1 1 22h
```
`#kubectl get service`
```
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
fpga-server-svc NodePort 10.96.59.3 <none> 8010:31600/TCP 22h
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 14d
```
#### Step 3: Run hello world in client pod

`#kubectl exec test-client-pod python /opt/xilinx/k8s/client/client.py`



**Note:**
**If the status of the accelerator pod shows as pending, please check whether the card is already assigned to another running pod. If so, please delete the running pod and recreate the accelerator pod.**

+ 0
- 2
third-party/k8s-fpga-device-plugin/docker/build_fpga_server_docker/Dockerfile View File

@@ -1,2 +0,0 @@
FROM xilinxatg/aws-fpga-verify:20200131
COPY server /opt/xilinx/k8s/server

BIN
third-party/k8s-fpga-device-plugin/docker/build_fpga_server_docker/server/fpga_algo.awsxclbin View File


BIN
third-party/k8s-fpga-device-plugin/docker/build_fpga_server_docker/server/fpga_host_exe View File


+ 0
- 60
third-party/k8s-fpga-device-plugin/docker/build_fpga_server_docker/server/fpga_server.py View File

@@ -1,60 +0,0 @@
import socket
import sys
import os
import subprocess
import datetime
from threading import Thread

SERVER_IP = '10.96.59.3'
SERVER_PORT = 8010
FPGA_CMD = '/opt/xilinx/k8s/server/fpga_host_exe'
FPGA_ARG = '/opt/xilinx/k8s/server/fpga_algo.awsxclbin'

class MyServer():

def __init__(self):
self.server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.server.bind(('0.0.0.0', SERVER_PORT))
self.server.listen(5)

def handle_connection(self, client_socket):
req = client_socket.recv(4096)
# run fpga helloworld, send the output back
out = subprocess.Popen([FPGA_CMD, FPGA_ARG], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
stdout,stderr = out.communicate()
client_socket.send("Response from FPGA server:\n" + stdout)
client_socket.close()

def start(self):
print "Waiting for command from the client..."
while True:
client_sock, address = self.server.accept()
client_handler = Thread(target=self.handle_connection, args=(client_sock,))
client_handler.start()


def client_send():
bind_ip = SERVER_IP
bind_port = SERVER_PORT
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((bind_ip, bind_port))
client.send("hello")
response = client.recv(4096)
client.close()
print "Send request to server..."
print response
print "--END--"

def usage():
print("Usage:")
print("\t%s " % sys.argv[0])

def main():
if (len(sys.argv) != 1):
usage()
exit(0)
print "Started FPGA Server Version 1.0: ",datetime.datetime.now()
server = MyServer()
server.start()
main()


+ 0
- 4
third-party/k8s-fpga-device-plugin/docker/build_fpga_server_docker/server/run.sh View File

@@ -1,4 +0,0 @@
#!/bin/bash
. /opt/xilinx/xrt/setup.sh
python /opt/xilinx/k8s/server/fpga_server.py
while true

+ 0
- 2
third-party/k8s-fpga-device-plugin/docker/build_test_client_docker/Dockerfile View File

@@ -1,2 +0,0 @@
FROM xilinxatg/aws-fpga-verify:20200131
COPY client /opt/xilinx/k8s/client

+ 0
- 34
third-party/k8s-fpga-device-plugin/docker/build_test_client_docker/client/client.py View File

@@ -1,34 +0,0 @@
import socket
import sys
import os
import subprocess
from threading import Thread

SERVER_IP = '10.96.59.3'
SERVER_PORT = 8010


def client_send():
bind_ip = SERVER_IP
bind_port = SERVER_PORT
client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((bind_ip, bind_port))
client.send("fpga_sever")
response = client.recv(4096)
client.close()
print "Senddd request to server..."
print response
print "--END--"

def usage():
print("Usage:")
print("\t%s" % sys.argv[0])

def main():
if (len(sys.argv) != 1):
usage()
exit(0)

client_send()
main()


+ 0
- 28
third-party/k8s-fpga-device-plugin/dp-pod.yaml View File

@@ -1,28 +0,0 @@
#Copyright 2018 Xilinx Corporation. All Rights Reserved.
#Author: Brian Xu(brianx@xilinx.com)
#
#Licensed under the Apache License, Version 2.0 (the "License");
#you may not use this file except in compliance with the License.
#You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
#Unless required by applicable law or agreed to in writing, software
#distributed under the License is distributed on an "AS IS" BASIS,
#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#See the License for the specific language governing permissions and
#limitations under the License.
apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
containers:
- name: mypod
image: xilinxatg/fpga-verify:latest
resources:
limits:
xilinx.com/fpga-xilinx_u200_xdma_201830_1-1542252769: 1
command: ["/bin/sh"]
args: ["-c", "while true; do echo hello; sleep 10;done"]


+ 0
- 50
third-party/k8s-fpga-device-plugin/fpga-device-plugin.yml View File

@@ -1,50 +0,0 @@
#Portions Copyright 2018 Xilinx Inc.
#Author: Brian Xu(brianx@xilinx.com)
#
#Licensed under the Apache License, Version 2.0 (the "License");
#you may not use this file except in compliance with the License.
#You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
#Unless required by applicable law or agreed to in writing, software
#distributed under the License is distributed on an "AS IS" BASIS,
#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#See the License for the specific language governing permissions and
#limitations under the License.
apiVersion: apps/v1
#if run with k8s v1.16-, replace the above line with
#apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
name: fpga-device-plugin-daemonset
namespace: kube-system
spec:
#if run with k8s v1.16-, the following 3 lines are not required
selector:
matchLabels:
name: xilinx-fpga-device-plugin
template:
metadata:
annotations:
scheduler.alpha.kubernetes.io/critical-pod: ""
labels:
name: xilinx-fpga-device-plugin
spec:
tolerations:
- key: CriticalAddonsOnly
operator: Exists
containers:
- image: xilinxatg/xilinx_k8s_fpga_plugin:latest
name: xilinx-fpga-device-plugin
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop: ["ALL"]
volumeMounts:
- name: device-plugin
mountPath: /var/lib/kubelet/device-plugins
volumes:
- name: device-plugin
hostPath:
path: /var/lib/kubelet/device-plugins

+ 0
- 274
third-party/k8s-fpga-device-plugin/fpga.go View File

@@ -1,274 +0,0 @@
// Copyright 2018 Xilinx Corporation. All Rights Reserved.
// Author: Brian Xu(brianx@xilinx.com)
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package main

import (
"fmt"
"io/ioutil"
pluginapi "k8s.io/kubernetes/pkg/kubelet/apis/deviceplugin/v1beta1"
"os"
"path"
"strconv"
"strings"
"time"
)

const (
SysfsDevices = "/sys/bus/pci/devices"
MgmtPrefix = "/dev/xclmgmt"
UserPrefix = "/dev/dri"
QdmaPrefix = "/dev/xfpga"
QDMASTR = "dma.qdma.u"
UserPFKeyword = "drm"
DRMSTR = "renderD"
ROMSTR = "rom"
DSAverFile = "VBNV"
DSAtsFile = "timestamp"
InstanceFile = "instance"
MgmtFile = "mgmt_pf"
UserFile = "user_pf"
VendorFile = "vendor"
DeviceFile = "device"
XilinxVendorID = "0x10ee"
ADVANTECH_ID = "0x13fe"
AWS_ID = "0x1d0f"
AristaVendorID = "0x3475"
)

type Pairs struct {
Mgmt string
User string
Qdma string
}

type Device struct {
index string
shellVer string
timestamp string
DBDF string // this is for user pf
deviceID string //devid of the user pf
Healthy string
Nodes *Pairs
}

func GetInstance(DBDF string) (string, error) {
strArray := strings.Split(DBDF, ":")
domain, err := strconv.ParseUint(strArray[0], 16, 16)
if err != nil {
return "", fmt.Errorf("strconv failed: %s\n", strArray[0])
}
bus, err := strconv.ParseUint(strArray[1], 16, 8)
if err != nil {
return "", fmt.Errorf("strconv failed: %s\n", strArray[1])
}
strArray = strings.Split(strArray[2], ".")
dev, err := strconv.ParseUint(strArray[0], 16, 8)
if err != nil {
return "", fmt.Errorf("strconv failed: %s\n", strArray[0])
}
fc, err := strconv.ParseUint(strArray[1], 16, 8)
if err != nil {
return "", fmt.Errorf("strconv failed: %s\n", strArray[1])
}
ret := domain*65536 + bus*256 + dev*8 + fc
return strconv.FormatUint(ret, 10), nil
}

func GetFileNameFromPrefix(dir string, prefix string) (string, error) {
userFiles, err := ioutil.ReadDir(dir)
if err != nil {
return "", fmt.Errorf("Can't read folder %s", dir)
}
for _, userFile := range userFiles {
fname := userFile.Name()

if !strings.HasPrefix(fname, prefix) {
continue
}
return fname, nil
}
return "", nil
}

func GetFileContent(file string) (string, error) {
if buf, err := ioutil.ReadFile(file); err != nil {
return "", fmt.Errorf("Can't read file %s", file)
} else {
ret := strings.Trim(string(buf), "\n")
return ret, nil
}
}

//Prior to 2018.3 release, Xilinx FPGA has mgmt PF as func 1 and user PF
//as func 0. The func numbers of the 2 PFs are swapped after 2018.3 release.
//The FPGA device driver in (and after) 2018.3 release creates sysfs file --
//mgmt_pf and user_pf accordingly to reflect what a PF really is.
//
//The plugin will rely on this info to determine whether the a entry is mgmtPF,
//userPF, or none. This also means, it will not support 2018.2 any more.
func FileExist(fname string) bool {
if _, err := os.Stat(fname); err != nil {
if os.IsNotExist(err) {
return false
}
}
return true
}

func IsMgmtPf(pciID string) bool {
fname := path.Join(SysfsDevices, pciID, MgmtFile)
return FileExist(fname)
}

func IsUserPf(pciID string) bool {
fname := path.Join(SysfsDevices, pciID, UserFile)
return FileExist(fname)
}

func GetDevices() ([]Device, error) {
var devices []Device
pairMap := make(map[string]*Pairs)
pciFiles, err := ioutil.ReadDir(SysfsDevices)
if err != nil {
return nil, fmt.Errorf("Can't read folder %s", SysfsDevices)
}

for _, pciFile := range pciFiles {
pciID := pciFile.Name()

fname := path.Join(SysfsDevices, pciID, VendorFile)
vendorID, err := GetFileContent(fname)
if err != nil {
return nil, err
}
if strings.EqualFold(vendorID, XilinxVendorID) != true &&
strings.EqualFold(vendorID, AristaVendorID) != true &&
strings.EqualFold(vendorID, AWS_ID) != true &&
strings.EqualFold(vendorID, ADVANTECH_ID) != true {
continue
}

DBD := pciID[:len(pciID)-2]
if _, ok := pairMap[DBD]; !ok {
pairMap[DBD] = &Pairs{
Mgmt: "",
User: "",
Qdma: "",
}
}

// For containers deployed on top of baremetal machines, xilinx FPGA
// in sysfs will always appear as pair of mgmt PF and user PF
// For containers deployed on top of VM, there may be only user PF
// available(mgmt PF is not assigned to the VM)
// so mgmt in Pair may be empty
if IsUserPf(pciID) { //user pf
userDBDF := pciID
romFolder, err := GetFileNameFromPrefix(path.Join(SysfsDevices, pciID), ROMSTR)
count := 0
if err != nil {
return nil, err
}
for romFolder == "" {
if count >= 3 {
break
}
time.Sleep(3 * time.Second)
romFolder, err := GetFileNameFromPrefix(path.Join(SysfsDevices, pciID), ROMSTR)
fmt.Println(romFolder, err)
count += 1
}
// get dsa version
fname = path.Join(SysfsDevices, pciID, romFolder, DSAverFile)
content, err := GetFileContent(fname)
if err != nil {
return nil, err
}
dsaVer := content
// get dsa timestamp
fname = path.Join(SysfsDevices, pciID, romFolder, DSAtsFile)
content, err = GetFileContent(fname)
if err != nil {
return nil, err
}
dsaTs := content
// get device id
fname = path.Join(SysfsDevices, pciID, DeviceFile)
content, err = GetFileContent(fname)
if err != nil {
return nil, err
}
devid := content
// get user PF node
userpf, err := GetFileNameFromPrefix(path.Join(SysfsDevices, pciID, UserPFKeyword), DRMSTR)
if err != nil {
return nil, err
}
userNode := path.Join(UserPrefix, userpf)
pairMap[DBD].User = userNode

//get qdma device node if it exists
instance, err := GetInstance(userDBDF)
if err != nil {
return nil, err
}

qdmaFolder, err := GetFileNameFromPrefix(path.Join(SysfsDevices, pciID), QDMASTR)
if err != nil {
return nil, err
}

if qdmaFolder != "" {
pairMap[DBD].Qdma = path.Join(QdmaPrefix, QDMASTR+instance+".0")
}

//TODO: check temp, power, fan speed etc, to give a healthy level
//so far, return Healthy
healthy := pluginapi.Healthy
devices = append(devices, Device{
index: strconv.Itoa(len(devices) + 1),
shellVer: dsaVer,
timestamp: dsaTs,
DBDF: userDBDF,
deviceID: devid,
Healthy: healthy,
Nodes: pairMap[DBD],
})
} else if IsMgmtPf(pciID) { //mgmt pf
// get mgmt instance
fname = path.Join(SysfsDevices, pciID, InstanceFile)
content, err := GetFileContent(fname)
if err != nil {
return nil, err
}
pairMap[DBD].Mgmt = MgmtPrefix + content
}
}
return devices, nil
}

/*
func main() {
devices, err := GetDevices()
if err != nil {
fmt.Printf("%s !!!\n", err)
return
}
for _, device := range devices {
fmt.Printf("%v", device)
}
}
*/

+ 0
- 469
third-party/k8s-fpga-device-plugin/full-tutorial.md View File

@@ -1,469 +0,0 @@
# Xilinx FPGA Plugin Deployment Full Tutorial

This documentation describes how to deploy FPGA plugin with Docker and Kubernetes on CentOS and Ubuntu.
## 1. Install Docker

### Prerequisites

CentOS:

- A maintained/supported version of CentOS
- A user account with sudo privileges
- Terminal access
- CentOS Extras repository – this is enabled by default, but if yours has been disabled you’ll need to re-enable it
- Software package installer yum

Ubuntu:

- Ubuntu operating system
- A user account with sudo privileges
- Command-line/terminal
- Docker software repositories (optional)

### Installing Docker on CentOS 7 With Yum

#### Step 1: Update Docker Package Database

`#sudo yum check-update`

#### Step 2: Install the Dependencies

`#sudo yum install -y yum-utils device-mapper-persistent-data lvm2`

#### Step 3: Add the Docker Repository to CentOS

To install the **edge** or **test** versions of Docker, you need to add the Docker CE stable repository to your system. To do so, run the command:

`#sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo`

A **stable** release is tested more thoroughly and has a slower update cycle. On the other hand, **Edge** release updates are more frequent but aren’t subject to as many stability tests.

**Note:** If you’re only going to use the stable release, don’t enable these extra repositories. The Docker installation process defaults to the latest version of Docker unless you specify otherwise. Leaving the stable repository enabled makes sure that you aren’t accidentally updating from a stable release to an edge release.

#### Step 4: Install Docker On CentOS Using Yum

With everything set, you can finally move on to installing Docker on CentOS 7 by running:

`#sudo yum install docker`

The system should begin the installation. Once it finishes, it will notify you the installation is complete and which version of Docker is now running on your system.

Your operating system may ask you to accept the GPG key. This is like a digital fingerprint, so you know whether to trust the installation.

#### Step 5: Manage Docker Service

Although you have installed Docker on CentOS, the service is still not running.

To start the service, enable it to run at startup. Run the following commands in the order listed below.

Start Docker:

`#sudo systemctl start docker`

Enable Docker:

`#sudo systemctl enable docker`

Check the status of the service:

`#sudo docker run hello-world`

### Installing Docker on Ubuntu With Apt-get

#### Step 1: Update Software Repositories

`#sudo apt-get update`

#### Step 2: Install Docker

`#sudo apt-get install docker.io`

#### Step 3: Manage Docker Service

Although you have installed Docker on Ubuntu, the service is still not running.

To start the service, enable it to run at startup. Run the following commands in the order listed below.

Start Docker:

`#sudo systemctl start docker`

Enable Docker:

`#sudo systemctl enable docker`

Check the status of the service:

`#sudo docker run hello-world`

## 2. Install Kubernetes

You will install these packages on all of your machines:

- `kubeadm`: the command to bootstrap the cluster.

- `kubelet`: the component that runs on all of the machines in your cluster and does things like starting pods and containers.

- `kubectl`: the command line util to talk to your cluster.


Here is the referred document from Kubernetes:

[https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/](https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/)

### Installing kubeadm, kubelet and kubectl on CentOS

#### Step 1: Set kubernetes repo

`#update-alternatives --set iptables /usr/sbin/iptables-legacy`

`#cat /etc/yum.repos.d/kubernetes.repo`

```
[kubernetes]
name=Kubernetes
baseurl=[https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64](https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64)
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
```

#### Step 2: Set SELinux in permissive mode (effectively disabling it)

`#sudo setence 0 `

`#sudo sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config `

**Note**: Setting SELinux in permissive mode by running setenforce 0 and sed ... effectively disables it. This is required to allow containers to access the host filesystem, which is needed by pod networks for example. You have to do this until SELinux support is improved in the kubelet.

Some users on RHEL/CentOS 7 have reported issues with traffic being routed incorrectly due to iptables being bypassed. You should ensure net.bridge.bridge-nf-call-iptables is set to 1 in your sysctl config, e.g.

`#cat /etc/sysctl.d/k8s.conf `

net.bridge.bridge-nf-call-iptables = 1

`#sudo sysctl --system `

Make sure that the br_netfilter module is loaded before this step. This can be done by running

`#lsmod | grep br_netfilter`

To load it explicitly call

`#sudo modprobe br_netfilter`

#### Step 3: Install Kubernetes

`#sudo yum install -y kubelet kubeadm kubectl --disableexcludes=kubernetes`

`#sudo systemctl enable --now kubelet`

### Installing kubeadm, kubelet and kubectl on Ubuntu

#### Step 1: Set kubernetes repo

`#sudo apt-get update`

`#sudo apt-get install -y iptables arptables ebtable`

#### Step 2: Install Kubernetes

```bash
#sudo apt-get update && sudo apt-get install -y apt-transport-https curl
#curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -
#sudo apt-get update
#sudo apt-get install -y kubelet kubeadm kubectl
#sudo apt-mark hold kubelet kubeadm kubectl
```
## 3. Configure Cluster

Here will just create **master** node and use it.

### Disable swap

`#sudo swapoff -a`

**Note**: If there is no enough space on system, please try disable swap and remove the swap file.

This command only temporary disable swap, run this command each time after reboot the machine.

### Create and Configure node

#### Step 1: init master node
```
#sudo kubeadm init --pod-network-cidr=10.244.0.0/16
#sudo mkdir -p $HOME/.kube
#sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
#sudo chown $(id -u):$(id -g) $HOME/.kube/config
```

**Note:** For issues like: "The connection to the server localhost:8080 was refused - did you specify the right host or port?"

Check port status:

`#netstat -nltp | grep apiserver`

Adding environment variable in ~/.bash_porfile

`#export KUBECONFIG=/etc/kubernetes/admin.conf`

`#source ~/.bash_profile`

#### Step 2: configure flannel


install flannel (for Kubernetes version 1.7+)

`#sysctl net.bridge.bridge-nf-call-iptables=1 `

`#kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml`

For other version, please refer [https://github.com/coreos/flannel](https://github.com/coreos/flannel) to do the configuration.

#### Step 3: check the pod

`#sudo kubectl get pod -n kube-system -o wide`

**NOTE**: If there is multiple AWS instances, then go ahead to create slave node on other instance and use "kubeadm join" to add the slave node into cluster.

## 4. Install Xilinx Runtime

Download XRT from github, build and install it with following command line.

For bare-metal machine you can directly install it with "apt install" and "yum install". Here we mainly introduce how to install XRT on AWS.

### Setup tool

`#scl enable devtoolset-6 bash`

If scl and devtoolset is not installed, then need to install the listed tools.

### Setup AWS FGPA

Here need to download aws FGPA because XRT build will depend on the it.

`#git clone http://github.com/aws/aws-fpga.git`

`#export AWS_FPGA_REPO_DIR="path of aws-fpga"`

### Build and Install XRT

**Note:** Based on current test, XRT 2019.2.0.3 works well on AWS F1, the master version has issue on some F1 instance. So here we recommend to use 2019.2.0.3 version.

#### Step 1: Build XRT
```
#git clone -b 2019.2.0.3 https://github.com/Xilinx/XRT.git
#./src/runtime_src/tools/scripts/xrtdeps.sh
#cd build
#./build.sh
#cd Release
#make package
```
**Note**: Need to make sure $AWS_FPGA_REPO_DIR is set to the right directory of aws-fpga before running build.

#### Step 2: Install XRT

`#yum install xrt_201920.2.3.0_7.7.1908-xrt.rpm`

`#yum install xrt_201920.2.3.0_7.7.1908-aws.rpm`

Please refer to the full instruction on how to build and install XRT:

[https://github.com/Xilinx/XRT/blob/master/src/runtime_src/doc/toc/build.rst](https://github.com/Xilinx/XRT/blob/master/src/runtime_src/doc/toc/build.rst)

`#source /opt/xilinx/xrt/setup.sh`

To check the FPGA device on the system:

```
#systemctl start mpd
#systemctl status mpd
#xbutil scan
```

## 5. Install Kubernetes FPGA Plugin

Here we only have one node (master), and plan to deploy the FPGA plug on this node, to enable this configuration, we need to configure the control plan node.

### Control plane node isolation

By default, your cluster will not schedule Pods on the control-plane node for security reasons. If you want to be able to schedule Pods on the control-plane node, e.g. for a single-machine Kubernetes cluster for development, run:

`#kubectl taint nodes --all node-role.kubernetes.io/master-`

### Install Kubernetes FPGA plugin

####
Step 1: down plugin source

`#git clone https://github.com/Xilinx/FPGA_as_a_Service.git`

Deploy FPGA device plugin as daemonset:

`#kubectl create -f ./FPGA_as_a_Service/k8s-fpga-device-plugin/fpga-device-plugin.yml `

To check the status of daemonset:

`#kubectl get pod -n kube-system `

Get node name:

`#kubectl get node `

Check FPGA resource in the worker node:

`#kubectl describe node nodename `

You should get the FPGA resources name under the pods information.

#### Step 2: Deploy user pod

`#kubectl create -f mypod.yaml`

**Note:**

1) mypod.yaml is under ./aws
2) modify the image to be "xilinxatg/aws-fpga-verify:20200131"
3) modify the resources: set limits same as the that in worker node like "[xilinx.com/fpga-xilinx_aws-vu9p-f1_dynamic_5_0-43981](http://xilinx.com/fpga-xilinx_aws-vu9p-f1_dynamic_5_0-43981): 1". To run "kubectl describe node nodename" to find out the resource.

To check status of the deployed pod:

`#kubectl get pod`

#### Step 3: Run the test in pod
after the pod status truns to Running, run hello world in the pod:

`#kubectl exec -it my-pod /bin/bash `

`#my-pod>source /opt/xilinx/xrt/setup.sh `

**Note:** Need to set the INTERNAL_BUILD=1 if xbutil complain the version not match:

```
#my-pod>export INTERNAL_BUILD=1
#my-pod>xbutil scan
#my-pod>cd /opt/test/
#my-pod>./helloworld vector_addition_hw.awsxclbin
```
## 6. How to build new docker image

We will use an example to explain how a new docker image with desired contents such as your xclbin, your host code etc. can be built. Please note that any accelerator (FPGA) docker image should be derived form the base docker Xilinx image **xilinxatg/aws-fpga-verify:20200131** already hosted at the Docker Hub.

### Prerequisites

To host a docker image, you need some sort of service. You can host it locally if you like (please read online docker instructions for that). However, this instruction uses [Docker Hub](https://hub.docker.com/) as the hosting service.

Go to [https://hub.docker.com/signup](https://hub.docker.com/signup) to create a Docker Hub account (if you do not have one already), and then create a docker repository.

In this document, we are using an example docker account named as **memo40k** and an example repository named as **k8s.** Please substitute these by your account and repository names respectively. Also, please note that you can set your repository as private if you do not want others to see it.

### Prepare docker images

####
Step 1: Login to your Docker Hub account

`#docker login -u <username> -p <password>`

#### Step 2: Create a docker file

Here we will use our github folder [**docker/build_fpga_server_docker**](https://github.com/Xilinx/FPGA_as_a_Service/tree/master/k8s-fpga-device-plugin/docker/build_fpga_server_docker) as an example. In this folder, **"server"** is a file folder that is to be added into our docker image. It has four files:

|File | Description|
|---|---|
| [fpga_algo.awsxclbin](https://github.com/Xilinx/FPGA_as_a_Service/blob/master/k8s-fpga-device-plugin/docker/build_fpga_server_docker/server/fpga_algo.awsxclbin "fpga_algo.awsxclbin")| This is the xclbin of the algorithm implemented on FPGA.|
| [fpga_host_exe](https://github.com/Xilinx/FPGA_as_a_Service/blob/master/k8s-fpga-device-plugin/docker/build_fpga_server_docker/server/fpga_host_exe "fpga_host_exe") | This is the host executable that downloads the xclbin to FPGA and interacts with the FPGA. |
| [fpga_server.py](https://github.com/Xilinx/FPGA_as_a_Service/blob/master/k8s-fpga-device-plugin/docker/build_fpga_server_docker/server/fpga_server.py "fpga_server.py")|This is a representative server program that calls the host executable and has ability to receive command from a client. One can merge this with host executable into one single server program in C++.|
| [run.sh](https://github.com/Xilinx/FPGA_as_a_Service/blob/master/k8s-fpga-device-plugin/docker/build_fpga_server_docker/server/run.sh "run.sh") | This sets environment and calls | fpga_server.py.

You can add any number of folders with any contents you need for your server to work.

The **xilinxatg/aws-fpga-verify:20200131** on docker hub is the base image as mentioned earlier. In this example, the folder **server** will be added to an example location **/opt/xilinx/k8s/** in the docker image.

`#touch Dockerfile `

create a dockerfile under the same folder with server

`#vi Dockerfile `

To add following two lines into Dockerfile

```
FROM xilinxatg/aws-fpga-verify:20200131
COPY docker /opt/xilinx/k8s/server
```
#### Step 3: Build new docker image

`#docker build -t memo40k/k8s:accelator_pod . `

It will build a new docker image called **accelerator_pod** using the docker file "**Dockerfile**" under the current folder

`#docker images `

You can run this command to check whether the new images **accelerator_pod** was created.

`# docker run -it <imageID>`

To test the docker image you just created, run the above. You should see the folder **server** added into the docker image.

#### Step 4: Push new image into docker hub

`#docker push memo40k/k8s:accelator_podk8`




#### Step 5: Create a docker image for client

Please repeat the steps 2 to 4 with your desired executable contents for the client to create another docker image called **test_client_pod**. You can use [build_test_client_docker](https://github.com/Xilinx/FPGA_as_a_Service/tree/master/k8s-fpga-device-plugin/docker/build_test_client_docker) as an example.



### Verify docker image

Use the yaml files: [aws-accelator-pod.yaml](https://github.com/Xilinx/FPGA_as_a_Service/blob/master/k8s-fpga-device-plugin/aws-accelator-pod.yaml) and [aws-test-client-pod.yaml](https://github.com/Xilinx/FPGA_as_a_Service/blob/master/k8s-fpga-device-plugin/aws-test-client-pod.yaml) to create accelerator and client pods respectively.



#### Step 1: Create accelerator and client pods

`#kubectl create -f aws-accelator-pod.yaml `

`#kubectl create -f aws-test-client-pod.yaml`

#### Step 2: Check pod status

After creating the two pods, there will be an accelerator pod with FPGA access, a client pod without FPGA access, an accelerator pod deployment service and a fpga-server-svc network service as shown below.

`#kubectl get pod`

```
NAME READY STATUS RESTARTS AGE
accelator-pod-ff67ff8b8-mwff 1/1 Running 0 22h
test-client-pod 1/1 Running 0 23h
```

`#kubectl get deployment`

```
NAME READY UP-TO-DATE AVAILABLE AGE
accelator-pod 1/1 1 1 22h
```

`#kubectl get service`

```
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
fpga-server-svc NodePort 10.96.59.3 <none> 8010:31600/TCP 22h
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 14d
```

#### Step 3: Run hello world in client pod

`#kubectl exec test-client-pod python /opt/xilinx/k8s/client/client.py`



**Note:**

**If the status of the accelerator pod shows as pending, please check whether the card is already assigned to another running pod. If so, please delete the running pod and recreate the accelerator pod.**

+ 0
- 84
third-party/k8s-fpga-device-plugin/main.go View File

@@ -1,84 +0,0 @@
// Portions Copyright 2018 Xilinx Inc.
// Author: Brian Xu(brianx@xilinx.com)
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package main

import (
"flag"
"os"
"syscall"

log "github.com/Sirupsen/logrus"
"github.com/fsnotify/fsnotify"
pluginapi "k8s.io/kubernetes/pkg/kubelet/apis/deviceplugin/v1beta1"
)

func main() {
// Parse command-line arguments
flag.CommandLine = flag.NewFlagSet(os.Args[0], flag.ExitOnError)
flagLogLevel := flag.String("log-level", "info", "Define the logging level: error, info, debug.")
flag.Parse()

switch *flagLogLevel {
case "debug":
log.SetLevel(log.DebugLevel)
case "info":
log.SetLevel(log.InfoLevel)
}

log.Println("Starting FS watcher.")
watcher, err := newFSWatcher(pluginapi.DevicePluginPath)
if err != nil {
log.Printf("Failed to created FS watcher: %s.", err)
os.Exit(1)
}
defer watcher.Close()

log.Println("Starting OS watcher.")
sigs := newOSWatcher(syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT)

restart := true
var devicePlugin *FPGADevicePlugin
L:
for {
if restart {
devicePlugin = NewFPGADevicePlugin()
restart = false
}

select {
case update := <-devicePlugin.updateChan:
devicePlugin.checkDeviceUpdate(update)

case event := <-watcher.Events:
if event.Name == pluginapi.KubeletSocket && event.Op&fsnotify.Create == fsnotify.Create {
log.Printf("inotify: %s created, restarting.", pluginapi.KubeletSocket)
restart = true
}

case err := <-watcher.Errors:
log.Printf("inotify: %s", err)

case s := <-sigs:
switch s {
case syscall.SIGHUP:
log.Println("Received SIGHUP, restarting.")
restart = true
default:
log.Printf("Received signal \"%v\", shutting down.", s)
break L
}
}
}
}

+ 0
- 171
third-party/k8s-fpga-device-plugin/quickstart.md View File

@@ -1,171 +0,0 @@
## Quick start
Assume there is a running k8s cluster already.

This part shows examples how the FPGA device plugin is deployed and how user APPs are deployed accessing the FPGA(s)

All cmds mentioned in this part run on the master node of k8s cluster. The output of cmds may differ depending on the
yaml file being used.

### Enable Xilinx FPGA support in k8s
#### Deploy FPGA device plugin as daemonset
```
$kubectl create -f fpga-device-plugin.yml
```
#### Check status of daemonset
```
$kubectl get pod -n kube-system

...snippet...

fpga-device-plugin-daemonset-cgq9d 1/1 Running 0 15d
fpga-device-plugin-daemonset-fq689 1/1 Running 0 15d
fpga-device-plugin-daemonset-hmnjr 1/1 Running 0 15d
fpga-device-plugin-daemonset-mkghl 1/1 Running 0 15d

...snippet...
```

Please note, the daemonset will be running on each node of the cluster whether or not there are FPGAs in the node.
If there are FPGAs in the node, logs of the daemonset running there will show something like,

```
$kubectl logs fpga-device-plugin-daemonset-fq689 -n kube-system

time="2019-04-25T18:22:55Z" level=info msg="Starting FS watcher."
time="2019-04-25T18:22:55Z" level=info msg="Starting OS watcher."
time="2019-04-25T18:22:55Z" level=info msg="Starting to serve on /var/lib/kubelet/device-plugins/xilinx_u200_xdma_201820_1-1535712995-fpga.sock"
2019/04/25 18:22:55 grpc: Server.Serve failed to create ServerTransport: connection error: desc = "transport: write unix /var/lib/kubelet/device-plugins/xilinx_u200_xdma_201820_1-1535712995-fpga.sock->@: write: broken pipe"
time="2019-04-25T18:22:55Z" level=info msg="Registered device plugin with Kubelet xilinx.com/fpga-xilinx_u200_xdma_201820_1-1535712995"
time="2019-04-25T18:22:55Z" level=info msg="Sending 1 device(s) [&Device{ID:1,Health:Healthy,}] to kubelet"
time="2019-04-25T18:32:06Z" level=info msg="Receiving request 1"
time="2019-05-09T18:36:41Z" level=info msg="Receiving request 1"
```
#### Check nodes status and the FPGA resource status on the node

List the nodes in the cluster
```
$kubectl get node

NAME STATUS ROLES AGE VERSION
fpga-1525-0 Ready <none> 15d v1.15.0-alpha.1.109+888d26d1191880-dirty
fpga-u200-0 Ready <none> 15d v1.15.0-alpha.1.109+888d26d1191880-dirty
fpga-u200-1 Ready <none> 15d v1.15.0-alpha.1.109+888d26d1191880-dirty
fpga-u200-2 Ready <none> 15d v1.15.0-alpha.1.109+888d26d1191880-dirty
fpga-u200-3 Ready <none> 15d v1.15.0-alpha.1.109+888d26d1191880-dirty
k8smaster Ready master 15d v1.15.0-alpha.1.109+888d26d1191880-dirty
test1 Ready <none> 15d v1.15.0-alpha.1.109+888d26d1191880-dirty
test5 Ready <none> 15d v1.15.0-alpha.1.109+888d26d1191880-dirty
```

Check FPGA resource in the worker node
```
$kubectl describe node fpga-1525-0

...snippet...

Capacity:
cpu: 4
ephemeral-storage: 102685624Ki
hugepages-1Gi: 0
hugepages-2Mi: 0
memory: 16425412Ki
pods: 110
xilinx.com/fpga-xilinx_vcu1525_dynamic_5_1-1521279439: 1
Allocatable:
cpu: 4
ephemeral-storage: 94635070922
hugepages-1Gi: 0
hugepages-2Mi: 0
memory: 16323012Ki
pods: 110
xilinx.com/fpga-xilinx_vcu1525_dynamic_5_1-1521279439: 1

...snippet...

```

### Run jobs accessing FPGA
The Xilinx FPGA resources all have name with following format

xilinx.com/fpga-shell-timestamp

eg. xilinx.com/fpga-xilinx_u200_xdma_201820_1-1535712995

Here, xilinx_u200_xdma_201820_1 is the shell(DSA) version on the FPGA board, and
1535712995 is the timestamp when the shell was built.
```
$date -d @1535712995
Fri Aug 31 03:56:35 PDT 2018
```

The exact name of the FPGA resource on each node can be extracted from the output of
```
$kubectl describe node <node_name>
```

#### Deploy user pod

Here is an example of the yaml file which defines the pod to be deployed.
In the yaml file, the docker image, which has been uploaded to a docker registry, should be specified.
What should be specified as well is, the type and number of FPGA resource being used by the pod.
```
$cat dp-pod.yaml

apiVersion: v1
kind: Pod
metadata:
name: mypod
spec:
containers:
- name: mypod
image: xilinxatg/fpga-verify:latest
resources:
limits:
xilinx.com/fpga-xilinx_u200_xdma_201830_1-1542252769: 1
command: ["/bin/sh"]
args: ["-c", "while true; do echo hello; sleep 10;done"]
```

Deploy the pod now

```
$kubectl create -f dp-pod.yaml
```
#### Check status of the deployed pod
```
$kubectl get pod

...snippet...

mypod 1/1 Running 0 7s

...snippet...

```
```
$kubectl describe pod mypod

...snippet...

Limits:
xilinx.com/fpga-xilinx_u200_xdma_201820_1-1535712995: 1
Requests:
xilinx.com/fpga-xilinx_u200_xdma_201820_1-1535712995: 1

...snippet...

```
#### Run hello world in the pod
```
$kubectl exec -it mypod /bin/bash
my-pod>source /opt/xilinx/xrt/setup.sh
my-pod>xbutil scan
my-pod>cd /tmp/alveo-u200/xilinx_u200_xdma_201830_1/test/
my-pod>./validate.exe ./verify.xclbin
```
In this test case, the container image (xilinxatg/fgpa-verify:latest) has been pushed to docker hub. It can be publicly accessed

The image contains verify.xclbin for many types of FPGA, please select the type matching the FPGA resource the pod requests.




+ 0
- 383
third-party/k8s-fpga-device-plugin/server.go View File

@@ -1,383 +0,0 @@
// Portions Copyright 2018 Xilinx Inc.
// Author: Brian Xu(brianx@xilinx.com)
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package main

import (
"fmt"
"net"
"os"
"path"
"reflect"
_ "runtime/debug"
"time"

log "github.com/Sirupsen/logrus"
"golang.org/x/net/context"
"google.golang.org/grpc"
pluginapi "k8s.io/kubernetes/pkg/kubelet/apis/deviceplugin/v1beta1"
)

const (
resourceNamePrefix = "xilinx.com/fpga"
serverSockPath = pluginapi.DevicePluginPath
)

// FPGADevicePluginServer implements the Kubernetes device plugin API
type FPGADevicePluginServer struct {
devType string
devices map[string]Device
socket string
stop chan interface{}
update chan map[string]Device

server *grpc.Server
}

type FPGADevicePlugin struct {
devices map[string]map[string]Device
servers map[string]*FPGADevicePluginServer
updateChan chan map[string]map[string]Device
}

// NewFPGADevicePlugin returns an initialized FPGADevicePlugin
func NewFPGADevicePlugin() *FPGADevicePlugin {
log.Debugf("create FPGA device plugin")
updateChan := make(chan map[string]map[string]Device)
plugin := FPGADevicePlugin{
devices: make(map[string]map[string]Device),
servers: make(map[string]*FPGADevicePluginServer),
updateChan: updateChan,
}

go func() {
for {
devices, err := GetDevices()
if err != nil {
log.Errorf("Error to get FPGA devices: %v", err)
break
}
devMap := make(map[string]map[string]Device)
for _, device := range devices {
DSAtype := device.shellVer + "-" + device.timestamp
id := device.DBDF
if subMap, ok := devMap[DSAtype]; ok {
subMap = devMap[DSAtype]
subMap[id] = device
} else {
subMap = make(map[string]Device)
devMap[DSAtype] = subMap
subMap[id] = device
}
}
//log.Debugf("newly reported FPGA device list: %v", devMap)
updateChan <- devMap
time.Sleep(5 * time.Second)
}
close(updateChan)
}()

return &plugin
}

func (m *FPGADevicePlugin) checkDeviceUpdate(n map[string]map[string]Device) {
added := make(map[string]map[string]Device)
updated := make(map[string]map[string]Device)
removed := make(map[string]map[string]Device)

for oDevType, oDevices := range m.devices {
if nDevices, ok := n[oDevType]; ok {
if !reflect.DeepEqual(oDevices, nDevices) {
updated[oDevType] = nDevices
}
delete(n, oDevType)
} else {
removed[oDevType] = oDevices
}
}
for nDevType, nDevices := range n {
added[nDevType] = nDevices
}

//log.Debugf("added FPGA device list: %v", added)
//log.Debugf("removed FPGA device list: %v", removed)
//log.Debugf("updated FPGA device list: %v", updated)
//create new server for added devices
for aDevType, aDevices := range added {
devicePluginServer := m.NewFPGADevicePluginServer(aDevType, aDevices)
m.devices[aDevType] = aDevices
m.servers[aDevType] = devicePluginServer
go func(aDevType string, aDevices map[string]Device, name string) {
if err := m.servers[aDevType].Serve(name); err != nil {
log.Println("Could not contact Kubelet, Exit. Did you enable the device plugin feature gate?")
os.Exit(1)
}
m.servers[aDevType].update <- aDevices
}(aDevType, aDevices, resourceNamePrefix)
}

//stop server for removed devices
for rDevType, rDevices := range removed {
log.Debugf("Remove device %v", rDevices)
m.servers[rDevType].Stop()
delete(m.servers, rDevType)
delete(m.devices, rDevType)
}

//send update for updated devices
for uDevType, uDevices := range updated {
m.devices[uDevType] = uDevices
m.servers[uDevType].update <- uDevices
}
}

// NewFPGADevicePluginServer returns an initialized FPGADevicePluginServer
func (m *FPGADevicePlugin) NewFPGADevicePluginServer(devType string, devices map[string]Device) *FPGADevicePluginServer {
return &FPGADevicePluginServer{
devType: devType,
devices: devices,
socket: path.Join(serverSockPath, devType+"-fpga.sock"),
stop: make(chan interface{}),
update: make(chan map[string]Device, 1),
}
}

// waitForServer checks if grpc server is alive
// by making grpc blocking connection to the server socket
func waitForServer(socket string, timeout time.Duration) error {
ctx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()
conn, err := grpc.DialContext(ctx, socket, grpc.WithInsecure(), grpc.WithBlock(),
grpc.WithDialer(func(addr string, timeout time.Duration) (net.Conn, error) {
return net.DialTimeout("unix", addr, timeout)
}),
)
if conn != nil {
conn.Close()
}

if err != nil {
fmt.Errorf("Failed dial context at %s", socket)
return err
}
return nil
}

func (m *FPGADevicePluginServer) deviceExists(id string) bool {
for k, _ := range m.devices {
if k == id {
return true
}
}
return false
}

func (m *FPGADevicePluginServer) PreStartContainer(ctx context.Context, rqt *pluginapi.PreStartContainerRequest) (*pluginapi.PreStartContainerResponse, error) {
return nil, fmt.Errorf("PreStartContainer() should not be called")
}

func (m *FPGADevicePluginServer) GetDevicePluginOptions(ctx context.Context, empty *pluginapi.Empty) (*pluginapi.DevicePluginOptions, error) {
fmt.Println("GetDevicePluginOptions: return empty options")
return new(pluginapi.DevicePluginOptions), nil
}

// Start starts the gRPC server of the device plugin
func (m *FPGADevicePluginServer) Start() error {
err := m.cleanup()
if err != nil {
return err
}

sock, err := net.Listen("unix", m.socket)
if err != nil {
return err
}

m.server = grpc.NewServer()
pluginapi.RegisterDevicePluginServer(m.server, m)

go m.server.Serve(sock)

// Wait for the server to start
if err = waitForServer(m.socket, 10*time.Second); err != nil {
return err
}

return nil
}

// Stop stops the gRPC server
func (m *FPGADevicePluginServer) Stop() error {
if m.server == nil {
return nil
}

m.server.Stop()
m.server = nil
close(m.stop)
close(m.update)

return m.cleanup()
}

func (m *FPGADevicePluginServer) cleanup() error {
if err := os.Remove(m.socket); err != nil && !os.IsNotExist(err) {
return err
}

return nil
}

// Register registers the device plugin for the given resourceName with Kubelet.
func (m *FPGADevicePluginServer) Register(kubeletEndpoint, resourceName string) error {
conn, err := grpc.Dial(kubeletEndpoint, grpc.WithInsecure(),
grpc.WithDialer(func(addr string, timeout time.Duration) (net.Conn, error) {
return net.DialTimeout("unix", addr, timeout)
}))

if err != nil {
log.Debugf("Cann't connect to kubelet service")
return err
}
defer conn.Close()

client := pluginapi.NewRegistrationClient(conn)
reqt := &pluginapi.RegisterRequest{
Version: pluginapi.Version,
Endpoint: path.Base(m.socket),
ResourceName: resourceName,
}

_, err = client.Register(context.Background(), reqt)
if err != nil {
log.Debugf("Cann't register to kubelet service")
return err
}
return nil
}

func (m *FPGADevicePluginServer) sendDevices(s pluginapi.DevicePlugin_ListAndWatchServer) error {
resp := new(pluginapi.ListAndWatchResponse)
for _, device := range m.devices {
resp.Devices = append(resp.Devices, &pluginapi.Device{device.DBDF, device.Healthy})
}
log.Printf("Sending %d device(s) %v to kubelet", len(resp.Devices), resp.Devices)
if err := s.Send(resp); err != nil {
m.Stop()
log.Debugf("Cannot update device list")
return err
}
return nil
}

// ListAndWatch lists devices and update that list according to the health status
func (m *FPGADevicePluginServer) ListAndWatch(e *pluginapi.Empty, s pluginapi.DevicePlugin_ListAndWatchServer) error {
log.Debugf("In ListAndWatch(%s): stream: %v", m.devType, s)
//debug.PrintStack()
for m.devices = range m.update {
if err := m.sendDevices(s); err != nil {
return err
}
}
return nil
}

// Allocate which return list of devices.
func (m *FPGADevicePluginServer) Allocate(ctx context.Context, req *pluginapi.AllocateRequest) (*pluginapi.AllocateResponse, error) {
log.Debugf("In Allocate()")
response := new(pluginapi.AllocateResponse)

for _, creq := range req.ContainerRequests {
log.Debugf("Request IDs: %v", creq.DevicesIDs)
cres := new(pluginapi.ContainerAllocateResponse)
for _, id := range creq.DevicesIDs {
log.Printf("Receiving request %s", id)
dev, ok := m.devices[id]
if !ok {
return nil, fmt.Errorf("Invalid allocation request with non-existing device %s", id)
}
if !m.deviceExists(id) {
return nil, fmt.Errorf("invalid allocation request: unknown device: %s", id)
}

// Before we have mgmt and user pf separated, we add both to the device cgroup.
// It is still safe with mgmt pf assigned to container since xilinx device driver
// makes sure flashing DSA(shell) through mgmt pf in container is denied.
// This is not good. we will change that later, then only the user pf node is
// required to be assigned to container(device cgroup of the container)
//
// When containers are on top of VM, it is possible only user PF is assigned
// to VM, so the Mgmt is empty. Don't add it to cgroup in that case
if dev.Nodes.Mgmt != "" {
cres.Devices = append(cres.Devices, &pluginapi.DeviceSpec{
HostPath: dev.Nodes.Mgmt,
ContainerPath: dev.Nodes.Mgmt,
Permissions: "rwm",
})
cres.Mounts = append(cres.Mounts, &pluginapi.Mount{
HostPath: dev.Nodes.Mgmt,
ContainerPath: dev.Nodes.Mgmt,
ReadOnly: false,
})
}
cres.Devices = append(cres.Devices, &pluginapi.DeviceSpec{
HostPath: dev.Nodes.User,
ContainerPath: dev.Nodes.User,
Permissions: "rwm",
})
cres.Mounts = append(cres.Mounts, &pluginapi.Mount{
HostPath: dev.Nodes.User,
ContainerPath: dev.Nodes.User,
ReadOnly: false,
})
// if this device supports qdma, assign the qdma node to pod too
if dev.Nodes.Qdma != "" {
cres.Devices = append(cres.Devices, &pluginapi.DeviceSpec{
HostPath: dev.Nodes.Qdma,
ContainerPath: dev.Nodes.Qdma,
Permissions: "rwm",
})
cres.Mounts = append(cres.Mounts, &pluginapi.Mount{
HostPath: dev.Nodes.Qdma,
ContainerPath: dev.Nodes.Qdma,
ReadOnly: false,
})
}
}
response.ContainerResponses = append(response.ContainerResponses, cres)
}

return response, nil
}

// Serve starts the gRPC server and register the device plugin to Kubelet
func (m *FPGADevicePluginServer) Serve(resourceName string) error {
log.Debugf("In Serve(%s)", m.socket)
err := m.Start()
if err != nil {
log.Errorf("Could not start device plugin: %v", err)
return err
}
log.Infof("Starting to serve on %s", m.socket)

err = m.Register(pluginapi.KubeletSocket, resourceName)
if err != nil {
log.Errorf("Could not register device plugin: %v", err)
m.Stop()
return err
}
log.Infof("Registered device plugin with Kubelet %s", resourceName)

return nil
}

+ 0
- 1
third-party/k8s-fpga-device-plugin/src View File

@@ -1 +0,0 @@
vendor

+ 0
- 31
third-party/k8s-fpga-device-plugin/watcher.go View File

@@ -1,31 +0,0 @@
package main

import (
"github.com/fsnotify/fsnotify"
"os"
"os/signal"
)

func newFSWatcher(files ...string) (*fsnotify.Watcher, error) {
watcher, err := fsnotify.NewWatcher()
if err != nil {
return nil, err
}

for _, f := range files {
err = watcher.Add(f)
if err != nil {
watcher.Close()
return nil, err
}
}

return watcher, nil
}

func newOSWatcher(sigs ...os.Signal) chan os.Signal {
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, sigs...)

return sigChan
}

Loading…
Cancel
Save