-
Notifications
You must be signed in to change notification settings - Fork 22
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This commit adds the initial implementation of the macvtap device plugin. Includes manifests & templates for deployment, as well as some basic tests. Further changes are expected as the macvtap cni is integrated. RBAC and more thorough testing pending for a later patch.
- Loading branch information
Showing
447 changed files
with
88,158 additions
and
2,945 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,11 @@ | ||
# Multi-stage dockerfile building a container image with both binaries included | ||
|
||
FROM golang:1.13 as builder | ||
ENV GOPATH=/go | ||
WORKDIR /go/src/github.com/kubevirt/macvtap-cni | ||
COPY . . | ||
RUN GOOS=linux CGO_ENABLED=0 go build -o /macvtap github.com/kubevirt/macvtap-cni/cmd/deviceplugin | ||
|
||
FROM registry.access.redhat.com/ubi8/ubi-minimal | ||
COPY --from=builder /macvtap /macvtap | ||
ENTRYPOINT [ "./macvtap", "-v", "3", "-logtostderr"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package main | ||
|
||
import ( | ||
"flag" | ||
"os" | ||
|
||
"github.com/golang/glog" | ||
"github.com/kubevirt/device-plugin-manager/pkg/dpm" | ||
macvtap "github.com/kubevirt/macvtap-cni/pkg/deviceplugin" | ||
) | ||
|
||
func main() { | ||
flag.Parse() | ||
|
||
_, configDefined := os.LookupEnv(macvtap.ConfigEnvironmentVariable) | ||
if !configDefined { | ||
glog.Exitf("%s environment variable must be set", macvtap.ConfigEnvironmentVariable) | ||
} | ||
|
||
manager := dpm.NewManager(macvtap.MacvtapLister{}) | ||
manager.Run() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
kind: ConfigMap | ||
apiVersion: v1 | ||
metadata: | ||
name: macvtap-deviceplugin-config | ||
data: | ||
DP_MACVTAP_CONF: >- | ||
[ { | ||
"name" : "eth0", | ||
"master" : "eth0", | ||
"mode": "bridge", | ||
"capacity" : 50 | ||
} ] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
apiVersion: apps/v1 | ||
kind: DaemonSet | ||
metadata: | ||
name: macvtap-cni | ||
spec: | ||
selector: | ||
matchLabels: | ||
name: macvtap-cni | ||
template: | ||
metadata: | ||
labels: | ||
name: macvtap-cni | ||
spec: | ||
hostNetwork: true | ||
hostPID: true | ||
containers: | ||
- name: macvtap-cni | ||
image: quay.io/kubevirt/macvtap-cni:latest | ||
securityContext: | ||
privileged: true | ||
envFrom: | ||
- configMapRef: | ||
name: macvtap-deviceplugin-config | ||
volumeMounts: | ||
- name: deviceplugin | ||
mountPath: /var/lib/kubelet/device-plugins | ||
volumes: | ||
- name: deviceplugin | ||
hostPath: | ||
path: /var/lib/kubelet/device-plugins |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package deviceplugin_test | ||
|
||
import ( | ||
"testing" | ||
|
||
. "github.com/onsi/ginkgo" | ||
. "github.com/onsi/gomega" | ||
) | ||
|
||
func TestDevicePlugin(t *testing.T) { | ||
RegisterFailHandler(Fail) | ||
RunSpecs(t, "Deviceplugin Suite") | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
package deviceplugin | ||
|
||
import ( | ||
"encoding/json" | ||
"os" | ||
|
||
"github.com/golang/glog" | ||
"github.com/kubevirt/device-plugin-manager/pkg/dpm" | ||
) | ||
|
||
const ( | ||
resourceNamespace = "macvtap.network.kubevirt.io" | ||
ConfigEnvironmentVariable = "DP_MACVTAP_CONF" | ||
) | ||
|
||
type MacvtapConfig struct { | ||
Name string `json:"name"` | ||
Master string `json:"master"` | ||
Mode string `json:"mode"` | ||
Capacity int `json:"capacity"` | ||
} | ||
|
||
type MacvtapLister struct { | ||
} | ||
|
||
func (ml MacvtapLister) GetResourceNamespace() string { | ||
return resourceNamespace | ||
} | ||
|
||
func readConfig() (map[string]MacvtapConfig, error) { | ||
var config []MacvtapConfig | ||
configMap := make(map[string]MacvtapConfig) | ||
|
||
configEnv := os.Getenv(ConfigEnvironmentVariable) | ||
err := json.Unmarshal([]byte(configEnv), &config) | ||
if err != nil { | ||
return configMap, err | ||
} | ||
|
||
for _, macvtapConfig := range config { | ||
configMap[macvtapConfig.Name] = macvtapConfig | ||
} | ||
|
||
return configMap, nil | ||
} | ||
|
||
func (ml MacvtapLister) Discover(pluginListCh chan dpm.PluginNameList) { | ||
var plugins = make(dpm.PluginNameList, 0) | ||
|
||
config, err := readConfig() | ||
if err != nil { | ||
glog.Errorf("Error reading config: %v", err) | ||
return | ||
} | ||
|
||
glog.V(3).Infof("Read configuration %+v", config) | ||
|
||
for _, macvtapConfig := range config { | ||
plugins = append(plugins, macvtapConfig.Name) | ||
} | ||
|
||
pluginListCh <- plugins | ||
} | ||
|
||
func (ml MacvtapLister) NewPlugin(name string) dpm.PluginInterface { | ||
config, _ := readConfig() | ||
glog.V(3).Infof("Creating device plugin with config %+v", config[name]) | ||
return NewMacvtapDevicePlugin( | ||
config[name].Name, | ||
config[name].Master, | ||
config[name].Mode, | ||
config[name].Capacity, | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
package deviceplugin | ||
|
||
import ( | ||
"fmt" | ||
|
||
"github.com/golang/glog" | ||
"golang.org/x/net/context" | ||
pluginapi "k8s.io/kubernetes/pkg/kubelet/apis/deviceplugin/v1beta1" | ||
|
||
"github.com/kubevirt/macvtap-cni/pkg/util" | ||
) | ||
|
||
const ( | ||
tapPath = "/dev/tap" | ||
suffix = "Mvp" | ||
defaultCapacity = 100 | ||
) | ||
|
||
type MacvtapDevicePlugin struct { | ||
Name string | ||
Master string | ||
Mode string | ||
Capacity int | ||
stopWatcher chan struct{} | ||
} | ||
|
||
func NewMacvtapDevicePlugin(name string, master string, mode string, capacity int) *MacvtapDevicePlugin { | ||
return &MacvtapDevicePlugin{ | ||
Name: name, | ||
Master: master, | ||
Mode: mode, | ||
Capacity: capacity, | ||
stopWatcher: make(chan struct{}), | ||
} | ||
} | ||
|
||
func (mdp *MacvtapDevicePlugin) generateMacvtapDevices() []*pluginapi.Device { | ||
var macvtapDevs []*pluginapi.Device | ||
|
||
var capacity = mdp.Capacity | ||
if capacity <= 0 { | ||
capacity = defaultCapacity | ||
} | ||
|
||
for i := 0; i < capacity; i++ { | ||
name := fmt.Sprint(mdp.Name, suffix, i) | ||
macvtapDevs = append(macvtapDevs, &pluginapi.Device{ | ||
ID: name, | ||
Health: pluginapi.Healthy, | ||
}) | ||
} | ||
return macvtapDevs | ||
} | ||
|
||
func masterExists(master string) bool { | ||
if err := util.LinkExists(master); err != nil { | ||
glog.Warningf("Master %s not found: %v", master, err) | ||
return false | ||
} | ||
return true | ||
} | ||
|
||
func (mdp *MacvtapDevicePlugin) ListAndWatch(e *pluginapi.Empty, s pluginapi.DevicePlugin_ListAndWatchServer) error { | ||
masterDevs := mdp.generateMacvtapDevices() | ||
noMasterDevs := make([]*pluginapi.Device, 0) | ||
emitResponse := func(masterExists bool) { | ||
if masterExists { | ||
glog.V(3).Info("Master exists, sending ListAndWatch response with available devices") | ||
s.Send(&pluginapi.ListAndWatchResponse{Devices: masterDevs}) | ||
} else { | ||
glog.V(3).Info("Master does not exist, sending ListAndWatch response with no devices") | ||
s.Send(&pluginapi.ListAndWatchResponse{Devices: noMasterDevs}) | ||
} | ||
} | ||
|
||
didMasterExist := false | ||
onMasterEvent := func() { | ||
doesMasterExist := masterExists(mdp.Master) | ||
if didMasterExist != doesMasterExist { | ||
emitResponse(doesMasterExist) | ||
didMasterExist = doesMasterExist | ||
} | ||
} | ||
|
||
util.OnLinkEvent( | ||
mdp.Master, | ||
onMasterEvent, | ||
mdp.stopWatcher, | ||
func(err error) { | ||
glog.Error(err) | ||
}) | ||
|
||
return nil | ||
} | ||
|
||
func (mdp *MacvtapDevicePlugin) Allocate(ctx context.Context, r *pluginapi.AllocateRequest) (*pluginapi.AllocateResponse, error) { | ||
var response pluginapi.AllocateResponse | ||
|
||
for _, req := range r.ContainerRequests { | ||
var devices []*pluginapi.DeviceSpec | ||
for _, name := range req.DevicesIDs { | ||
dev := new(pluginapi.DeviceSpec) | ||
index, err := util.RecreateMacvtap(name, mdp.Master, mdp.Mode) | ||
if err != nil { | ||
return nil, err | ||
} | ||
devPath := fmt.Sprint(tapPath, index) | ||
dev.HostPath = devPath | ||
dev.ContainerPath = devPath | ||
dev.Permissions = "rw" | ||
devices = append(devices, dev) | ||
} | ||
|
||
response.ContainerResponses = append(response.ContainerResponses, &pluginapi.ContainerAllocateResponse{ | ||
Devices: devices, | ||
}) | ||
} | ||
|
||
return &response, nil | ||
} | ||
|
||
func (mdp *MacvtapDevicePlugin) PreStartContainer(context.Context, *pluginapi.PreStartContainerRequest) (*pluginapi.PreStartContainerResponse, error) { | ||
return nil, nil | ||
} | ||
|
||
func (mdp *MacvtapDevicePlugin) GetDevicePluginOptions(context.Context, *pluginapi.Empty) (*pluginapi.DevicePluginOptions, error) { | ||
return nil, nil | ||
} | ||
|
||
func (mdp *MacvtapDevicePlugin) Stop() error { | ||
close(mdp.stopWatcher) | ||
return nil | ||
} |
Oops, something went wrong.