Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add cni plugin #4

Merged
merged 4 commits into from
Feb 25, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
CNI_MOUNT_PATH ?= /opt/cni/bin

IMAGE_REGISTRY ?= quay.io/kubevirt
IMAGE_NAME ?= macvtap-cni
IMAGE_TAG ?= latest
Expand Down Expand Up @@ -75,10 +77,10 @@ test/unit:
@echo "You are not root, run this target as root please"
exit 1
fi
go test ./cmd/... ./pkg/... -v -logtostderr --ginkgo.v
go test ./cmd/... ./pkg/... -v --ginkgo.v

manifests:
IMAGE_REGISTRY=$(IMAGE_REGISTRY) IMAGE_NAME=$(IMAGE_NAME) IMAGE_TAG=$(IMAGE_TAG) ./hack/generate-manifests.sh
IMAGE_REGISTRY=$(IMAGE_REGISTRY) IMAGE_NAME=$(IMAGE_NAME) IMAGE_TAG=$(IMAGE_TAG) CNI_MOUNT_PATH=$(CNI_MOUNT_PATH) ./hack/generate-manifests.sh

vendor:
go mod tidy
Expand Down
7 changes: 4 additions & 3 deletions cmd/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ 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
RUN GOOS=linux CGO_ENABLED=0 go build -o /macvtap-deviceplugin github.com/kubevirt/macvtap-cni/cmd/deviceplugin
RUN GOOS=linux CGO_ENABLED=0 go build -o /macvtap-cni github.com/kubevirt/macvtap-cni/cmd/cni

FROM registry.access.redhat.com/ubi8/ubi-minimal
COPY --from=builder /macvtap /macvtap
ENTRYPOINT [ "./macvtap", "-v", "3", "-logtostderr"]
COPY --from=builder /macvtap-deviceplugin /macvtap-deviceplugin
COPY --from=builder /macvtap-cni /macvtap-cni
12 changes: 12 additions & 0 deletions cmd/cni/macvtap.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package main

import (
"github.com/containernetworking/cni/pkg/skel"
"github.com/containernetworking/cni/pkg/version"
bv "github.com/containernetworking/plugins/pkg/utils/buildversion"
macvtap_cni "github.com/kubevirt/macvtap-cni/pkg/cni"
)

func main() {
skel.PluginMain(macvtap_cni.CmdAdd, macvtap_cni.CmdCheck, macvtap_cni.CmdDel, version.All, bv.BuildString("macvtap"))
}
5 changes: 5 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,20 @@ module github.com/kubevirt/macvtap-cni
go 1.13

require (
github.com/BurntSushi/toml v0.3.1 // indirect
github.com/client9/misspell v0.3.4 // indirect
github.com/containernetworking/cni v0.7.1
github.com/containernetworking/plugins v0.8.5
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b
github.com/kubevirt/device-plugin-manager v1.14.0
github.com/onsi/ginkgo v1.11.0
github.com/onsi/gomega v1.8.1
github.com/vishvananda/netlink v1.1.0
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3 // indirect
golang.org/x/net v0.0.0-20190812203447-cdfb69ac37fc
golang.org/x/tools v0.0.0-20200117220505-0cba7a3a9ee9
google.golang.org/grpc v1.26.0
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc // indirect
k8s.io/client-go v0.0.0
k8s.io/kubernetes v0.0.0-00010101000000-000000000000
)
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ github.com/containernetworking/plugins v0.8.5 h1:pCvEMrFf7yzJI8+/D/7jkvE96KD52b7
github.com/containernetworking/plugins v0.8.5/go.mod h1:UZ2539umj8djuRQmBxuazHeJbYrLV8BSBejkk+she6o=
github.com/coreos/bbolt v1.3.1-coreos.6/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/go-iptables v0.4.5 h1:DpHb9vJrZQEFMcVLFKAAGMUVX0XoRC0ptCthinRYm38=
github.com/coreos/go-iptables v0.4.5/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU=
github.com/coreos/go-oidc v0.0.0-20180117170138-065b426bd416/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc=
github.com/coreos/go-semver v0.0.0-20180108230905-e214231b295a/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
Expand Down Expand Up @@ -239,6 +240,7 @@ github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446/go.mod h1:uY
github.com/robfig/cron v0.0.0-20170309132418-df38d32658d8/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k=
github.com/rubiojr/go-vhd v0.0.0-20160810183302-0bfd3b39853c/go.mod h1:DM5xW0nvfNNm2uytzsvhI3OnX8uzaRAg8UX/CnDqbto=
github.com/russross/blackfriday v0.0.0-20151117072312-300106c228d5/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8 h1:2c1EFnZHIPCW8qKWgHMH/fX2PkSabFc5mrVzfUNdg5U=
github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4=
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
github.com/seccomp/libseccomp-golang v0.0.0-20150813023252-1b506fc7c24e/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo=
Expand Down
2 changes: 2 additions & 0 deletions hack/generate-manifests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

set -ex

CNI_MOUNT_PATH=${CNI_MOUNT_PATH} # the default is stored in Makefile
IMAGE_REGISTRY=${IMAGE_REGISTRY} # the default is stored in Makefile
IMAGE_NAME=${IMAGE_NAME} # the default is stored in Makefile
IMAGE_TAG=${IMAGE_TAG} # the default is store in Makefile
Expand All @@ -14,5 +15,6 @@ for template in templates/*.in; do
-e "s#{{ .ImageRegistry }}#${IMAGE_REGISTRY}#g" \
-e "s#{{ .ImageName }}#${IMAGE_NAME}#g" \
-e "s#{{ .ImageTag }}#${IMAGE_TAG}#g" \
-e "s#{{ .CniMountPath }}#${CNI_MOUNT_PATH}#g" \
${template} > ${DESTINATION}/${name}
done
14 changes: 14 additions & 0 deletions manifests/macvtap.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,24 @@ spec:
envFrom:
- configMapRef:
name: macvtap-deviceplugin-config
command: [ "/macvtap-deviceplugin", "-v", "3", "-logtostderr"]
volumeMounts:
- name: deviceplugin
mountPath: /var/lib/kubelet/device-plugins
initContainers:
- name: install-cni
image: quay.io/kubevirt/macvtap-cni:latest
securityContext:
privileged: true
command: ['cp', '/macvtap-cni', '/host/opt/cni/bin/macvtap']
volumeMounts:
- name: cni
mountPath: /host/opt/cni/bin
mountPropagation: Bidirectional
volumes:
- name: deviceplugin
hostPath:
path: /var/lib/kubelet/device-plugins
- name: cni
hostPath:
path: /opt/cni/bin
13 changes: 13 additions & 0 deletions pkg/cni/cni_suite_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package cni_test

import (
"testing"

. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
)

func TestCni(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "Cni Suite")
}
143 changes: 143 additions & 0 deletions pkg/cni/plugin.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
// Copyright 2019 CNI authors
//
// 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 cni

import (
"encoding/json"
"fmt"
"net"
"runtime"

"github.com/kubevirt/macvtap-cni/pkg/util"

"github.com/containernetworking/cni/pkg/skel"
"github.com/containernetworking/cni/pkg/types"
"github.com/containernetworking/cni/pkg/types/current"

"github.com/containernetworking/plugins/pkg/ip"
"github.com/containernetworking/plugins/pkg/ns"
)

// A NetConf structure represents a Multus network attachment definition configuration
type NetConf struct {
types.NetConf
DeviceID string `json:"deviceID"`
MTU int `json:"mtu,omitempty"`
}

// EnvArgs structure represents inputs sent from each VMI via environment variables
type EnvArgs struct {
types.CommonArgs
MAC types.UnmarshallableString `json:"mac,omitempty"`
}

func init() {
// this ensures that main runs only on main thread (thread group leader).
// since namespace ops (unshare, setns) are done for a single thread, we
// must ensure that the goroutine does not jump from OS thread to thread
runtime.LockOSThread()
}

func loadConf(bytes []byte) (NetConf, string, error) {
n := NetConf{}
if err := json.Unmarshal(bytes, &n); err != nil {
return n, "", fmt.Errorf("failed to load netconf: %v", err)
}

return n, n.CNIVersion, nil
}

func getEnvArgs(envArgsString string) (EnvArgs, error) {
maiqueb marked this conversation as resolved.
Show resolved Hide resolved
e := EnvArgs{}
err := types.LoadArgs(envArgsString, &e)
if err != nil {
return e, err
}
return e, nil
}

// CmdAdd - CNI interface
func CmdAdd(args *skel.CmdArgs) error {
var err error
netConf, cniVersion, err := loadConf(args.StdinData)
if err != nil {
return err
}
maiqueb marked this conversation as resolved.
Show resolved Hide resolved

envArgs, err := getEnvArgs(args.Args)
maiqueb marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
return err
}

var mac *net.HardwareAddr = nil
if envArgs.MAC != "" {
maiqueb marked this conversation as resolved.
Show resolved Hide resolved
aMac, err := net.ParseMAC(string(envArgs.MAC))
mac = &aMac
if err != nil {
return err
}
}

netns, err := ns.GetNS(args.Netns)
if err != nil {
return fmt.Errorf("failed to open netns %q: %v", netns, err)
}

// Delete link if err to avoid link leak in this ns
defer func() {
maiqueb marked this conversation as resolved.
Show resolved Hide resolved
netns.Close()
if err != nil {
maiqueb marked this conversation as resolved.
Show resolved Hide resolved
util.LinkDelete(netConf.DeviceID)
}
phoracek marked this conversation as resolved.
Show resolved Hide resolved
}()

macvtapInterface, err := util.ConfigureInterface(netConf.DeviceID, args.IfName, mac, netConf.MTU, netns)
if err != nil {
return err
}

result := &current.Result{
CNIVersion: cniVersion,
Interfaces: []*current.Interface{macvtapInterface},
}

return types.PrintResult(result, cniVersion)
}

// CmdDel - CNI plugin Interface
func CmdDel(args *skel.CmdArgs) error {
if args.Netns == "" {
return nil
}

// There is a netns so try to clean up. Delete can be called multiple times
// so don't return an error if the device is already removed.
err := ns.WithNetNSPath(args.Netns, func(_ ns.NetNS) error {

maiqueb marked this conversation as resolved.
Show resolved Hide resolved
if err := ip.DelLinkByName(args.IfName); err != nil {
maiqueb marked this conversation as resolved.
Show resolved Hide resolved
if err != ip.ErrLinkNotFound {
return err
}
Comment on lines +129 to +132
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wondered if there was any difference between ip.DelLinkByName and what we have in util/netlink.go @ LinkDelete. The only difference is that the latter would not return ErrLinkNotFound which is not meaningful here. Since we are also using the latter elsewhere, If I were me I would probably change it to that for consistency. Non binding comment.

}
return nil
})

return err
}

// CmdCheck - CNI plugin Interface
func CmdCheck(args *skel.CmdArgs) error {
return nil
}
Loading