Repository: intel/intel-device-plugins-for-kubernetes
Pull request #770 (2021-11-29 15:00:09)

e2e: add dlb test
I made e2e test for dlb. It needs both pf and vf in the node where the e2e test runs.
@mythi Sorry, I don't remember where you said to put the information about this matter. Please tell me again. 

In addition, I put resource requests and limits for both of resources. Would it be better to divide same as the yaml file of the demo file?

Signed-off-by: Hyeongju Johannes Lee <hyeongju.lee@intel.com>

mythi: @hj-johannes-lee I did not have any concrete proposal but we could have a section in the README to guide users to setup the VFs.
hj-johannes-lee: @mythi @bart0sh Sorry, idk whether you noticed or not, but at some point my laptop stopped working, and it happened after the meeting ended... I lost all of my notes.. so I did as far as I remember.! If I forgot something, plz let me know.!

Patch:
diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml
index 36f01783..52a0e313 100644
--- a/.github/workflows/ci.yaml
+++ b/.github/workflows/ci.yaml
@@ -85,7 +85,7 @@ jobs:
           - intel-sgx-plugin
           - intel-sgx-initcontainer
           - intel-dsa-plugin
-          - intel-idxd-config-initcontainer
+          - intel-idxd-initcontainer
           - intel-dlb-plugin
 
           # Demo images
diff --git a/Makefile b/Makefile
index 7e8dba5b..3ef76cee 100644
--- a/Makefile
+++ b/Makefile
@@ -29,8 +29,6 @@ OLM_MANIFESTS = deployments/operator/manifests
 
 WEBHOOK_IMAGE_FILE = intel-fpga-admissionwebhook-devel.tgz
 
-TESTDATA_DIR = pkg/topology/testdata
-
 pkgs  = $(shell $(GO) list ./... | grep -v vendor | grep -v e2e | grep -v envtest)
 cmds = $(shell ls --ignore=internal cmd)
 e2e_tmp_dir := $(shell mktemp -u -t e2e-tests.XXXXXXXXXX)
@@ -47,13 +45,7 @@ go-mod-tidy:
 	$(GO) mod download
 	@report=`$(GO) mod tidy -v 2>&1` ; if [ -n "$$report" ]; then echo "$$report"; exit 1; fi
 
-update-fixture:
-	@scripts/ttar -C $(TESTDATA_DIR) -c -f $(TESTDATA_DIR)/sys.ttar sys/
-
-fixture:
-	@scripts/ttar --recursive-unlink -C $(TESTDATA_DIR) -x -f $(TESTDATA_DIR)/sys.ttar
-
-test: fixture
+test:
 ifndef WHAT
 	@$(GO) test -tags $(BUILDTAGS) -race -coverprofile=coverage.txt -covermode=atomic $(pkgs)
 else
@@ -65,7 +57,7 @@ else
             exit $$rc
 endif
 
-test-with-kind: fixture
+test-with-kind:
 	@build/docker/build-image.sh intel/intel-fpga-admissionwebhook buildah
 	@$(PODMAN) tag localhost/intel/intel-fpga-admissionwebhook:devel docker.io/intel/intel-fpga-admissionwebhook:devel
 	@mkdir -p $(e2e_tmp_dir)
@@ -181,7 +173,7 @@ check-github-actions:
 	jq -e '$(images_json) - .jobs.image.strategy.matrix.image == []' > /dev/null || \
 	(echo "Make sure all images are listed in .github/workflows/ci.yaml"; exit 1)
 
-.PHONY: all format test lint build images $(cmds) $(images) lock-images vendor pre-pull set-version check-github-actions envtest fixture update-fixture
+.PHONY: all format test lint build images $(cmds) $(images) lock-images vendor pre-pull set-version check-github-actions envtest
 
 SPHINXOPTS    =
 SPHINXBUILD   = sphinx-build
diff --git a/build/docker/intel-idxd-config-initcontainer.Dockerfile b/build/docker/intel-idxd-initcontainer.Dockerfile
similarity index 53%
rename from build/docker/intel-idxd-config-initcontainer.Dockerfile
rename to build/docker/intel-idxd-initcontainer.Dockerfile
index ff5ea3fb..1fd420d1 100644
--- a/build/docker/intel-idxd-config-initcontainer.Dockerfile
+++ b/build/docker/intel-idxd-initcontainer.Dockerfile
@@ -12,49 +12,38 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-FROM debian:unstable-slim AS builder
+FROM debian:unstable AS builder
 
-RUN echo "deb-src http://deb.debian.org/debian unstable main" >> \
-        /etc/apt/sources.list.d/deb-src.list && \
-    apt update && apt install -y --no-install-recommends \
-        gcc make patch autoconf automake libtool pkg-config \
-        libjson-c-dev uuid-dev curl ca-certificates && \
-    mkdir -p /usr/local/share/package-sources && \
-    cd /usr/local/share/package-sources && \
-    apt --download-only source uuid libjson-c5 && cd /
+RUN apt-get update && apt-get install -y \
+            build-essential autoconf automake autotools-dev libtool \
+            pkgconf asciidoc xmlto uuid-dev libjson-c-dev libkmod-dev \
+            libudev-dev libkeyutils-dev curl
 
 ARG ACCEL_CONFIG_VERSION="3.4.2"
 ARG ACCEL_CONFIG_DOWNLOAD_URL="https://github.com/intel/idxd-config/archive/accel-config-v$ACCEL_CONFIG_VERSION.tar.gz"
 ARG ACCEL_CONFIG_SHA256="9cb2151e86f83949a28f06a885be3bf3100906f9e3af667fa01b56e7666a3c1c"
 
-RUN curl -fsSL "$ACCEL_CONFIG_DOWNLOAD_URL" -o accel-config.tar.gz && \
-    echo "$ACCEL_CONFIG_SHA256 accel-config.tar.gz" | sha256sum -c - && \
-    tar -xzf accel-config.tar.gz
-
-ADD demo/idxd-config-kmod.patch /
+RUN curl -fsSL "$ACCEL_CONFIG_DOWNLOAD_URL" -o accel-config.tar.gz \
+    && echo "$ACCEL_CONFIG_SHA256 accel-config.tar.gz" | sha256sum -c - \
+    && tar -xzf accel-config.tar.gz \
+    && rm accel-config.tar.gz
 
 RUN cd idxd-config-accel-config-v$ACCEL_CONFIG_VERSION && \
-    patch -p1 < ../idxd-config-kmod.patch && \
-    ./git-version-gen && \
-    autoreconf -i && \
-    ./configure -q --libdir=/usr/lib64 --disable-test --disable-docs && \
+    mkdir m4 && \
+    ./autogen.sh && \
+    ./configure CFLAGS='-g -O2' --prefix=/usr --sysconfdir=/etc --libdir=/usr/lib64 --disable-test --disable-docs && \
     make && \
     make install
 
 FROM debian:unstable-slim
 
-RUN apt update && apt install -y uuid libjson-c5 jq
+RUN apt-get update && apt-get install -y uuid libjson-c5 kmod udev jq
 
 COPY --from=builder /usr/lib64/libaccel-config.so.1.0.0 /lib/x86_64-linux-gnu/
 RUN ldconfig
 
 COPY --from=builder /usr/bin/accel-config /usr/bin/
 
-COPY --from=builder /usr/local/share/package-sources/ \
-    /usr/local/share/package-sources/
-COPY --from=builder /accel-config.tar.gz /usr/local/share/package-sources/
-COPY --from=builder /idxd-config-kmod.patch /usr/local/share/package-sources/
-
 ADD demo/idxd-init.sh /idxd-init/
 ADD demo/dsa.conf /idxd-init/
 
diff --git a/cmd/dsa_plugin/README.md b/cmd/dsa_plugin/README.md
index 821c6be1..e1cd6b34 100644
--- a/cmd/dsa_plugin/README.md
+++ b/cmd/dsa_plugin/README.md
@@ -56,7 +56,7 @@ There's a sample [DSA initcontainer](https://github.com/intel/intel-device-plugi
 $ kubectl apply -k deployments/dsa_plugin/overlays/dsa_initcontainer/
 ```
 
-The provisioning [script](https://github.com/intel/intel-device-plugins-for-kubernetes/blob/main/demo/idxd-init.sh) and [template](https://github.com/intel/intel-device-plugins-for-kubernetes/blob/master/demo/dsa.conf) are available for customization.
+The provisioning [script](https://github.com/intel/intel-device-plugins-for-kubernetes/blob/main/demo/dsa-init.sh) and [template](https://github.com/intel/intel-device-plugins-for-kubernetes/blob/master/demo/dsa.conf) are available for customization.
 
 ### Deploy with initcontainer and provisioning config in the ConfigMap
 
diff --git a/cmd/sgx_plugin/README.md b/cmd/sgx_plugin/README.md
index 9d198a4b..97358ab9 100644
--- a/cmd/sgx_plugin/README.md
+++ b/cmd/sgx_plugin/README.md
@@ -44,8 +44,8 @@ The SGX plugin can take a number of command line arguments, summarised in the fo
 
 | Flag | Argument | Meaning |
 |:---- |:-------- |:------- |
-| -enclave-limit | int | the number of containers per worker node allowed to use `/dev/sgx_enclave` device node (default: `20`) |
-| -provision-limit | int | the number of containers per worker node allowed to use `/dev/sgx_provision` device node (default: `20`) |
+| -enclave-limit | int | the number of containers per node allowed to use `/dev/sgx/enclave` (default: `20`) |
+| -provision-limit | int | the number of containers per node allowed to use `/dev/sgx/provision` (default: `20`) |
 
 The plugin also accepts a number of other arguments related to logging. Please use the `-h` option to see
 the complete list of logging related options.
diff --git a/demo/idxd-config-kmod.patch b/demo/idxd-config-kmod.patch
deleted file mode 100644
index 2aa2e145..00000000
--- a/demo/idxd-config-kmod.patch
+++ /dev/null
@@ -1,158 +0,0 @@
-From 58038bf811e9942aebd6a812c7b0abceee66fc0c Mon Sep 17 00:00:00 2001
-From: Oleg Zhurakivskyy <oleg.zhurakivskyy@intel.com>
-Date: Mon, 29 Nov 2021 20:49:25 +0200
-Subject: [PATCH] accel-config: Make libkmod, libudev optional
-
-Signed-off-by: Oleg Zhurakivskyy <oleg.zhurakivskyy@intel.com>
----
- accfg/accel-config.c | 15 +++++++++++++--
- accfg/lib/libaccfg.c |  1 +
- accfg/lib/private.h  |  9 +++++++++
- configure.ac         | 11 +++++++++--
- 4 files changed, 32 insertions(+), 4 deletions(-)
-
-diff --git a/accfg/accel-config.c b/accfg/accel-config.c
-index 0840e0b..c5ee687 100644
---- a/accfg/accel-config.c
-+++ b/accfg/accel-config.c
-@@ -7,7 +7,9 @@
- #include <unistd.h>
- #include <sys/stat.h>
- #include <sys/types.h>
-+#ifdef HAVE_KMOD
- #include <libkmod.h>
-+#endif
- #include <builtin.h>
- #include <accfg/libaccel_config.h>
- #include <ccan/array_size/array_size.h>
-@@ -75,6 +77,7 @@ static struct cmd_struct commands[] = {
- #endif
- };
- 
-+#ifdef HAVE_KMOD
- static int idxd_kmod_init(struct kmod_ctx **ctx, struct kmod_module **mod)
- {
- 	int rc;
-@@ -97,12 +100,15 @@ static int idxd_kmod_init(struct kmod_ctx **ctx, struct kmod_module **mod)
- 
- 	return rc;
- }
-+#endif
- 
- int main(int argc, const char **argv)
- {
- 	struct accfg_ctx *ctx;
-+#ifdef HAVE_KMOD
- 	struct kmod_ctx *kmod_ctx;
- 	struct kmod_module *mod;
-+#endif
- 	unsigned int last_error;
- 	int rc;
- 
-@@ -122,16 +128,19 @@ int main(int argc, const char **argv)
- 		return -EINVAL;
- 	}
- 
-+#ifdef HAVE_KMOD
- 	rc = idxd_kmod_init(&kmod_ctx, &mod);
- 	if (rc < 0) {
- 		fprintf(stderr, "Failed initializing kernel module\n");
- 		goto error_exit;
- 	}
--
-+#endif
- 	rc = accfg_new(&ctx);
- 	if (rc) {
-+#ifdef HAVE_KMOD
- 		kmod_module_unref(mod);
- 		kmod_unref(kmod_ctx);
-+#endif
- 		goto error_exit;
- 	}
- 
-@@ -161,9 +170,11 @@ int main(int argc, const char **argv)
- 		printf(": %s\n", accfg_ctx_get_last_error_str(ctx));
- 	}
- 	accfg_unref(ctx);
-+
-+#ifdef HAVE_KMOD
- 	kmod_module_unref(mod);
- 	kmod_unref(kmod_ctx);
--
-+#endif
- 	if (!rc)
- 		return EXIT_SUCCESS;
- error_exit:
-diff --git a/accfg/lib/libaccfg.c b/accfg/lib/libaccfg.c
-index f4fc17e..7897091 100644
---- a/accfg/lib/libaccfg.c
-+++ b/accfg/lib/libaccfg.c
-@@ -10,6 +10,7 @@
- #include <unistd.h>
- #include <uuid/uuid.h>
- #include <errno.h>
-+#include <inttypes.h>
- #include <ctype.h>
- #include <libgen.h>
- #include <string.h>
-diff --git a/accfg/lib/private.h b/accfg/lib/private.h
-index 57aa1ed..ecb9bd7 100644
---- a/accfg/lib/private.h
-+++ b/accfg/lib/private.h
-@@ -8,8 +8,12 @@
- #include <stdbool.h>
- #include <syslog.h>
- #include <string.h>
-+#ifdef HAVE_UDEV
- #include <libudev.h>
-+#endif
-+#ifdef HAVE_KMOD
- #include <libkmod.h>
-+#endif
- #include <util/log.h>
- #include <uuid/uuid.h>
- #include <ccan/list/list.h>
-@@ -160,13 +164,18 @@ struct accfg_ctx {
- 	struct accfg_error_ctx *error_ctx;
- };
- 
-+#ifdef HAVE_UDEV
- static inline int check_udev(struct udev *udev)
- {
- 	return udev ? 0 : -ENXIO;
- }
-+#endif
- 
-+#ifdef HAVE_KMOD
- static inline int check_kmod(struct kmod_ctx *kmod_ctx)
- {
- 	return kmod_ctx ? 0 : -ENXIO;
- }
-+#endif
-+
- #endif /* _LIBACCFG_PRIVATE_H_ */
-diff --git a/configure.ac b/configure.ac
-index b2ef6d0..b3c2ede 100755
---- a/configure.ac
-+++ b/configure.ac
-@@ -97,8 +97,15 @@ AM_CONDITIONAL([ENABLE_TEST], [test "x$enable_test" = "xyes"])
- PKG_CHECK_MODULES([UUID], [uuid],
-         [AC_DEFINE([HAVE_UUID], [1], [Define to 1 if using libuuid])])
- PKG_CHECK_MODULES([JSON], [json-c])
--PKG_CHECK_MODULES([KMOD], [libkmod])
--PKG_CHECK_MODULES([UDEV], [libudev])
-+PKG_CHECK_MODULES([KMOD], [libkmod],
-+			  [AC_DEFINE([HAVE_KMOD], [1], [Defined if using libkmod])],
-+			  KMOD_CFLAGS=""
-+			  KMOD_LIBS="")
-+
-+PKG_CHECK_MODULES([UDEV], [libudev],
-+			  [AC_DEFINE([HAVE_UDEV], [1], [Defined if using libudev])],
-+			  UDEV_CFLAGS=""
-+			  UDEV_LIBS="")
- 
- AC_ARG_WITH([bash-completion-dir],
- 	AS_HELP_STRING([--with-bash-completion-dir[=PATH]],
--- 
-2.34.1
-
diff --git a/demo/opae-nlb-demo/Dockerfile b/demo/opae-nlb-demo/Dockerfile
index 70aecc03..53a91367 100644
--- a/demo/opae-nlb-demo/Dockerfile
+++ b/demo/opae-nlb-demo/Dockerfile
@@ -26,21 +26,13 @@ RUN cd /usr/src/opae/opae-sdk-${OPAE_RELEASE} && \
     make -j xfpga nlb0 nlb3
 
 # Copy required nlb* utils and their dependencies to the final image
-
 FROM debian:unstable-slim
-
 COPY --from=builder /usr/src/opae/opae-sdk-*/build/bin/nlb* /usr/local/bin/
 COPY --from=builder /usr/src/opae/opae-sdk-*/build/lib /usr/local/lib/
 RUN rm -rf /usr/local/lib/python3
 RUN ldconfig
 
-RUN echo "deb-src http://deb.debian.org/debian unstable main" >> \
-        /etc/apt/sources.list.d/deb-src.list && \
-    apt update && apt install -y libjson-c4 && \
-    mkdir -p /usr/local/share/package-sources && \
-    cd /usr/local/share/package-sources && \
-    apt --download-only source libjson-c4 && cd / && \
-    rm -v /etc/apt/sources.list.d/deb-src.list && apt clean
+RUN apt-get update && apt-get install -y libjson-c4
 
 COPY test_fpga.sh /usr/local/bin/
 ENTRYPOINT ["/usr/local/bin/test_fpga.sh"]
diff --git a/deployments/dsa_plugin/overlays/dsa_initcontainer/dsa_initcontainer.yaml b/deployments/dsa_plugin/overlays/dsa_initcontainer/dsa_initcontainer.yaml
index 07f0568c..2dbbebbe 100644
--- a/deployments/dsa_plugin/overlays/dsa_initcontainer/dsa_initcontainer.yaml
+++ b/deployments/dsa_plugin/overlays/dsa_initcontainer/dsa_initcontainer.yaml
@@ -6,7 +6,7 @@ spec:
   template:
     spec:
       initContainers:
-      - name: intel-idxd-config-initcontainer
+      - name: intel-dsa-initcontainer
         env:
           - name: NODE_NAME
             valueFrom:
diff --git a/deployments/operator/crd/bases/deviceplugin.intel.com_dsadeviceplugins.yaml b/deployments/operator/crd/bases/deviceplugin.intel.com_dsadeviceplugins.yaml
index 6dec7df6..3311a705 100644
--- a/deployments/operator/crd/bases/deviceplugin.intel.com_dsadeviceplugins.yaml
+++ b/deployments/operator/crd/bases/deviceplugin.intel.com_dsadeviceplugins.yaml
@@ -53,8 +53,7 @@ spec:
             properties:
               InitImage:
                 description: InitImage is an initcontainer image to configure and
-                  enable DSA devices and workqueues with idxd-config (accel-config)
-                  utility
+                  enable DSA devices and workqueues with accel-config utility
                 type: string
               image:
                 description: Image is a container image with DSA device plugin executable.
@@ -70,8 +69,8 @@ spec:
                   plugin pods to nodes with particular labels.
                 type: object
               provisioningConfig:
-                description: ProvisioningConfig is a ConfigMap used to pass the DSA
-                  devices and workqueues configuration into idxd-config initcontainer.
+                description: ProvisioningConfig is a ConfigMap used to pass the configuration
+                  into DSA initcontainer.
                 type: string
               sharedDevNum:
                 description: SharedDevNum is a number of containers that can share
diff --git a/pkg/apis/deviceplugin/v1/dsadeviceplugin_types.go b/pkg/apis/deviceplugin/v1/dsadeviceplugin_types.go
index 97fd6fce..6953e47b 100644
--- a/pkg/apis/deviceplugin/v1/dsadeviceplugin_types.go
+++ b/pkg/apis/deviceplugin/v1/dsadeviceplugin_types.go
@@ -31,10 +31,10 @@ type DsaDevicePluginSpec struct {
 	// Image is a container image with DSA device plugin executable.
 	Image string `json:"image,omitempty"`
 
-	// InitImage is an initcontainer image to configure and enable DSA devices and workqueues with idxd-config (accel-config) utility
+	// InitImage is an initcontainer image to configure and enable DSA devices and workqueues with accel-config utility
 	InitImage string `json:"InitImage,omitempty"`
 
-	// ProvisioningConfig is a ConfigMap used to pass the DSA devices and workqueues configuration into idxd-config initcontainer.
+	// ProvisioningConfig is a ConfigMap used to pass the configuration into DSA initcontainer.
 	ProvisioningConfig string `json:"provisioningConfig,omitempty"`
 
 	// SharedDevNum is a number of containers that can share the same DSA device.
diff --git a/pkg/apis/deviceplugin/v1/dsadeviceplugin_webhook.go b/pkg/apis/deviceplugin/v1/dsadeviceplugin_webhook.go
index 30cbeccd..68db1e4b 100644
--- a/pkg/apis/deviceplugin/v1/dsadeviceplugin_webhook.go
+++ b/pkg/apis/deviceplugin/v1/dsadeviceplugin_webhook.go
@@ -95,7 +95,7 @@ func (r *DsaDevicePlugin) validatePlugin() error {
 	}
 
 	if len(r.Spec.InitImage) > 0 {
-		return validatePluginImage(r.Spec.InitImage, "intel-idxd-config-initcontainer", dsaMinVersion)
+		return validatePluginImage(r.Spec.InitImage, "intel-idxd-initcontainer", dsaMinVersion)
 	}
 
 	return nil
diff --git a/pkg/controllers/dsa/controller.go b/pkg/controllers/dsa/controller.go
index 9483fb72..ce1269f3 100644
--- a/pkg/controllers/dsa/controller.go
+++ b/pkg/controllers/dsa/controller.go
@@ -35,9 +35,8 @@ import (
 )
 
 const (
-	ownerKey         = ".metadata.controller.dsa"
-	amd64            = "amd64"
-	inicontainerName = "intel-idxd-config-initcontainer"
+	ownerKey = ".metadata.controller.dsa"
+	amd64    = "amd64"
 )
 
 // +kubebuilder:rbac:groups=deviceplugin.intel.com,resources=dsadeviceplugins,verbs=get;list;watch;create;update;patch;delete
@@ -77,83 +76,33 @@ func (c *controller) GetTotalObjectCount(ctx context.Context, clnt client.Client
 	return len(list.Items), nil
 }
 
-func removeInitContainer(ds *apps.DaemonSet, dp *devicepluginv1.DsaDevicePlugin) {
-	newInitContainers := []v1.Container{}
-	for _, container := range ds.Spec.Template.Spec.InitContainers {
-		if container.Name == inicontainerName {
-			continue
-		}
-		newInitContainers = append(newInitContainers, container)
-	}
-	ds.Spec.Template.Spec.InitContainers = newInitContainers
-
-	newVolumes := []v1.Volume{}
-	for _, volume := range ds.Spec.Template.Spec.Volumes {
-		if volume.Name == "intel-dsa-config-volume" || volume.Name == "sys-devices" {
-			continue
-		}
-		newVolumes = append(newVolumes, volume)
-	}
-	ds.Spec.Template.Spec.Volumes = newVolumes
-}
-
-func addInitContainer(ds *apps.DaemonSet, dp *devicepluginv1.DsaDevicePlugin) {
+func setInitContainer(spec *v1.PodSpec, imageName string) {
 	yes := true
-	ds.Spec.Template.Spec.InitContainers = append(ds.Spec.Template.Spec.InitContainers, v1.Container{
-		Image:           dp.Spec.InitImage,
-		ImagePullPolicy: "IfNotPresent",
-		Name:            inicontainerName,
-		Env: []v1.EnvVar{
-			{
-				Name: "NODE_NAME",
-				ValueFrom: &v1.EnvVarSource{
-					FieldRef: &v1.ObjectFieldSelector{
-						FieldPath: "spec.nodeName",
+	spec.InitContainers = []v1.Container{
+		{
+			Image:           imageName,
+			ImagePullPolicy: "IfNotPresent",
+			Name:            "intel-idxd-initcontainer",
+			Env: []v1.EnvVar{
+				{
+					Name: "NODE_NAME",
+					ValueFrom: &v1.EnvVarSource{
+						FieldRef: &v1.ObjectFieldSelector{
+							FieldPath: "spec.nodeName",
+						},
 					},
 				},
 			},
-			{
-				Name:  "IDXD_DEVICE_TYPE",
-				Value: "dsa",
-			},
-		},
-		SecurityContext: &v1.SecurityContext{
-			Privileged: &yes,
-		},
-		VolumeMounts: []v1.VolumeMount{
-			{
-				Name:      "sys-devices",
-				MountPath: "/sys/devices",
+			SecurityContext: &v1.SecurityContext{
+				Privileged: &yes,
 			},
-		},
-	})
-	ds.Spec.Template.Spec.Volumes = append(ds.Spec.Template.Spec.Volumes, v1.Volume{
-		Name: "sys-devices",
-		VolumeSource: v1.VolumeSource{
-			HostPath: &v1.HostPathVolumeSource{
-				Path: "/sys/devices",
-			},
-		},
-	})
-
-	if dp.Spec.ProvisioningConfig != "" {
-		ds.Spec.Template.Spec.Volumes = append(ds.Spec.Template.Spec.Volumes, v1.Volume{
-			Name: "intel-dsa-config-volume",
-			VolumeSource: v1.VolumeSource{
-				ConfigMap: &v1.ConfigMapVolumeSource{
-					LocalObjectReference: v1.LocalObjectReference{Name: dp.Spec.ProvisioningConfig}},
+			VolumeMounts: []v1.VolumeMount{
+				{
+					Name:      "sys-devices",
+					MountPath: "/sys/devices",
+				},
 			},
-		})
-
-		for i, initcontainer := range ds.Spec.Template.Spec.InitContainers {
-			if initcontainer.Name == inicontainerName {
-				ds.Spec.Template.Spec.InitContainers[i].VolumeMounts = append(ds.Spec.Template.Spec.InitContainers[i].VolumeMounts, v1.VolumeMount{
-					Name:      "intel-dsa-config-volume",
-					MountPath: "/idxd-init/conf",
-				})
-			}
-		}
-	}
+		}}
 }
 
 func (c *controller) NewDaemonSet(rawObj client.Object) *apps.DaemonSet {
@@ -177,37 +126,40 @@ func (c *controller) NewDaemonSet(rawObj client.Object) *apps.DaemonSet {
 	daemonSet.Spec.Template.Spec.Containers[0].Args = getPodArgs(devicePlugin)
 	daemonSet.Spec.Template.Spec.Containers[0].Image = devicePlugin.Spec.Image
 
+	// add the optional init container
 	if devicePlugin.Spec.InitImage != "" {
-		addInitContainer(daemonSet, devicePlugin)
-	}
+		setInitContainer(&daemonSet.Spec.Template.Spec, devicePlugin.Spec.InitImage)
 
-	return daemonSet
-}
-
-func provisioningUpdate(ds *apps.DaemonSet, dp *devicepluginv1.DsaDevicePlugin) bool {
-	update := false
-	found := false
-
-	for _, container := range ds.Spec.Template.Spec.InitContainers {
-		if container.Name == inicontainerName && container.Image != dp.Spec.InitImage {
-			found = true
-			update = true
-			break
-		}
-	}
+		daemonSet.Spec.Template.Spec.Volumes = append(daemonSet.Spec.Template.Spec.Volumes, v1.Volume{
+			Name: "sys-devices",
+			VolumeSource: v1.VolumeSource{
+				HostPath: &v1.HostPathVolumeSource{
+					Path: "/sys/devices",
+				},
+			},
+		})
 
-	for _, volume := range ds.Spec.Template.Spec.Volumes {
-		if volume.Name == "intel-dsa-config-volume" && volume.ConfigMap.Name != dp.Spec.ProvisioningConfig {
-			update = true
-			break
+		if devicePlugin.Spec.ProvisioningConfig != "" {
+			daemonSet.Spec.Template.Spec.Volumes = append(daemonSet.Spec.Template.Spec.Volumes, v1.Volume{
+				Name: "intel-dsa-config-volume",
+				VolumeSource: v1.VolumeSource{
+					ConfigMap: &v1.ConfigMapVolumeSource{
+						LocalObjectReference: v1.LocalObjectReference{Name: devicePlugin.Spec.ProvisioningConfig}},
+				},
+			})
+
+			for i, initcontainer := range daemonSet.Spec.Template.Spec.InitContainers {
+				if initcontainer.Name == "intel-idxd-initcontainer" {
+					daemonSet.Spec.Template.Spec.InitContainers[i].VolumeMounts = append(daemonSet.Spec.Template.Spec.InitContainers[i].VolumeMounts, v1.VolumeMount{
+						Name:      "intel-dsa-config-volume",
+						MountPath: "/idxd-init/conf",
+					})
+				}
+			}
 		}
 	}
 
-	if !found && dp.Spec.InitImage != "" {
-		update = true
-	}
-
-	return update
+	return daemonSet
 }
 
 func (c *controller) UpdateDaemonSet(rawObj client.Object, ds *apps.DaemonSet) (updated bool) {
@@ -218,14 +170,6 @@ func (c *controller) UpdateDaemonSet(rawObj client.Object, ds *apps.DaemonSet) (
 		updated = true
 	}
 
-	if provisioningUpdate(ds, dp) {
-		removeInitContainer(ds, dp)
-		if dp.Spec.InitImage != "" {
-			addInitContainer(ds, dp)
-		}
-		updated = true
-	}
-
 	if dp.Spec.NodeSelector == nil {
 		dp.Spec.NodeSelector = map[string]string{"kubernetes.io/arch": amd64}
 	} else {
diff --git a/scripts/ttar b/scripts/ttar
deleted file mode 100755
index 19ef02b8..00000000
--- a/scripts/ttar
+++ /dev/null
@@ -1,413 +0,0 @@
-#!/usr/bin/env bash
-
-# Purpose: plain text tar format
-# Limitations: - only suitable for text files, directories, and symlinks
-#              - stores only filename, content, and mode
-#              - not designed for untrusted input
-#
-# Note: must work with bash version 3.2 (macOS)
-
-# Copyright 2017 Roger Luethi
-#
-# 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 -o errexit -o nounset
-
-# Sanitize environment (for instance, standard sorting of glob matches)
-export LC_ALL=C
-
-path=""
-CMD=""
-ARG_STRING="$*"
-
-#------------------------------------------------------------------------------
-# Not all sed implementations can work on null bytes. In order to make ttar
-# work out of the box on macOS, use Python as a stream editor.
-
-USE_PYTHON=0
-
-PYTHON_CREATE_FILTER=$(cat << 'PCF'
-#!/usr/bin/env python
-
-import re
-import sys
-
-for line in sys.stdin:
-    line = re.sub(r'EOF', r'\EOF', line)
-    line = re.sub(r'NULLBYTE', r'\NULLBYTE', line)
-    line = re.sub('\x00', r'NULLBYTE', line)
-    sys.stdout.write(line)
-PCF
-)
-
-PYTHON_EXTRACT_FILTER=$(cat << 'PEF'
-#!/usr/bin/env python
-
-import re
-import sys
-
-for line in sys.stdin:
-    line = re.sub(r'(?<!\\)NULLBYTE', '\x00', line)
-    line = re.sub(r'\\NULLBYTE', 'NULLBYTE', line)
-    line = re.sub(r'([^\\])EOF', r'\1', line)
-    line = re.sub(r'\\EOF', 'EOF', line)
-    sys.stdout.write(line)
-PEF
-)
-
-function test_environment {
-    if [[ "$(echo "a" | sed 's/a/\x0/' | wc -c)" -ne 2 ]]; then
-        echo "WARNING sed unable to handle null bytes, using Python (slow)."
-        if ! which python >/dev/null; then
-            echo "ERROR Python not found. Aborting."
-            exit 2
-        fi
-        USE_PYTHON=1
-    fi
-}
-
-#------------------------------------------------------------------------------
-
-function usage {
-    bname=$(basename "$0")
-    cat << USAGE
-Usage:   $bname [-C <DIR>] -c -f <ARCHIVE> <FILE...> (create archive)
-         $bname            -t -f <ARCHIVE>           (list archive contents)
-         $bname [-C <DIR>] -x -f <ARCHIVE>           (extract archive)
-
-Options:
-         -C <DIR>           (change directory)
-         -v                 (verbose)
-         --recursive-unlink (recursively delete existing directory if path
-                             collides with file or directory to extract)
-
-Example: Change to sysfs directory, create ttar file from fixtures directory
-         $bname -C sysfs -c -f sysfs/fixtures.ttar fixtures/
-USAGE
-exit "$1"
-}
-
-function vecho {
-    if [ "${VERBOSE:-}" == "yes" ]; then
-        echo >&7 "$@"
-    fi
-}
-
-function set_cmd {
-    if [ -n "$CMD" ]; then
-        echo "ERROR: more than one command given"
-        echo
-        usage 2
-    fi
-    CMD=$1
-}
-
-unset VERBOSE
-unset RECURSIVE_UNLINK
-
-while getopts :cf:-:htxvC: opt; do
-    case $opt in
-        c)
-            set_cmd "create"
-            ;;
-        f)
-            ARCHIVE=$OPTARG
-            ;;
-        h)
-            usage 0
-            ;;
-        t)
-            set_cmd "list"
-            ;;
-        x)
-            set_cmd "extract"
-            ;;
-        v)
-            VERBOSE=yes
-            exec 7>&1
-            ;;
-        C)
-            CDIR=$OPTARG
-            ;;
-        -)
-            case $OPTARG in
-                recursive-unlink)
-                    RECURSIVE_UNLINK="yes"
-                    ;;
-                *)
-                    echo -e "Error: invalid option -$OPTARG"
-                    echo
-                    usage 1
-                    ;;
-            esac
-            ;;
-        *)
-            echo >&2 "ERROR: invalid option -$OPTARG"
-            echo
-            usage 1
-            ;;
-    esac
-done
-
-# Remove processed options from arguments
-shift $(( OPTIND - 1 ));
-
-if [ "${CMD:-}" == "" ]; then
-    echo >&2 "ERROR: no command given"
-    echo
-    usage 1
-elif [ "${ARCHIVE:-}" == "" ]; then
-    echo >&2 "ERROR: no archive name given"
-    echo
-    usage 1
-fi
-
-function list {
-    local path=""
-    local size=0
-    local line_no=0
-    local ttar_file=$1
-    if [ -n "${2:-}" ]; then
-        echo >&2 "ERROR: too many arguments."
-        echo
-        usage 1
-    fi
-    if [ ! -e "$ttar_file" ]; then
-        echo >&2 "ERROR: file not found ($ttar_file)"
-        echo
-        usage 1
-    fi
-    while read -r line; do
-        line_no=$(( line_no + 1 ))
-        if [ $size -gt 0 ]; then
-            size=$(( size - 1 ))
-            continue
-        fi
-        if [[ $line =~ ^Path:\ (.*)$ ]]; then
-            path=${BASH_REMATCH[1]}
-        elif [[ $line =~ ^Lines:\ (.*)$ ]]; then
-            size=${BASH_REMATCH[1]}
-            echo "$path"
-        elif [[ $line =~ ^Directory:\ (.*)$ ]]; then
-            path=${BASH_REMATCH[1]}
-            echo "$path/"
-        elif [[ $line =~ ^SymlinkTo:\ (.*)$ ]]; then
-            echo  "$path -> ${BASH_REMATCH[1]}"
-        fi
-    done < "$ttar_file"
-}
-
-function extract {
-    local path=""
-    local size=0
-    local line_no=0
-    local ttar_file=$1
-    if [ -n "${2:-}" ]; then
-        echo >&2 "ERROR: too many arguments."
-        echo
-        usage 1
-    fi
-    if [ ! -e "$ttar_file" ]; then
-        echo >&2 "ERROR: file not found ($ttar_file)"
-        echo
-        usage 1
-    fi
-    while IFS= read -r line; do
-        line_no=$(( line_no + 1 ))
-        local eof_without_newline
-        if [ "$size" -gt 0 ]; then
-            if [[ "$line" =~ [^\\]EOF ]]; then
-                # An EOF not preceded by a backslash indicates that the line
-                # does not end with a newline
-                eof_without_newline=1
-            else
-                eof_without_newline=0
-            fi
-            # Replace NULLBYTE with null byte if at beginning of line
-            # Replace NULLBYTE with null byte unless preceded by backslash
-            # Remove one backslash in front of NULLBYTE (if any)
-            # Remove EOF unless preceded by backslash
-            # Remove one backslash in front of EOF
-            if [ $USE_PYTHON -eq 1 ]; then
-                echo -n "$line" | python -c "$PYTHON_EXTRACT_FILTER" >> "$path"
-            else
-                # The repeated pattern makes up for sed's lack of negative
-                # lookbehind assertions (for consecutive null bytes).
-                echo -n "$line" | \
-                    sed -e 's/^NULLBYTE/\x0/g;
-                            s/\([^\\]\)NULLBYTE/\1\x0/g;
-                            s/\([^\\]\)NULLBYTE/\1\x0/g;
-                            s/\\NULLBYTE/NULLBYTE/g;
-                            s/\([^\\]\)EOF/\1/g;
-                            s/\\EOF/EOF/g;
-                    ' >> "$path"
-            fi
-            if [[ "$eof_without_newline" -eq 0 ]]; then
-                echo >> "$path"
-            fi
-            size=$(( size - 1 ))
-            continue
-        fi
-        if [[ $line =~ ^Path:\ (.*)$ ]]; then
-            path=${BASH_REMATCH[1]}
-            if [ -L "$path" ]; then
-                rm "$path"
-            elif [ -d "$path" ]; then
-                if [ "${RECURSIVE_UNLINK:-}" == "yes" ]; then
-                    rm -r "$path"
-                else
-                    # Safe because symlinks to directories are dealt with above
-                    rmdir "$path"
-                fi
-            elif [ -e "$path" ]; then
-                rm "$path"
-            fi
-        elif [[ $line =~ ^Lines:\ (.*)$ ]]; then
-            size=${BASH_REMATCH[1]}
-            # Create file even if it is zero-length.
-            touch "$path"
-            vecho "    $path"
-        elif [[ $line =~ ^Mode:\ (.*)$ ]]; then
-            mode=${BASH_REMATCH[1]}
-            chmod "$mode" "$path"
-            vecho "$mode"
-        elif [[ $line =~ ^Directory:\ (.*)$ ]]; then
-            path=${BASH_REMATCH[1]}
-            mkdir -p "$path"
-            vecho "    $path/"
-        elif [[ $line =~ ^SymlinkTo:\ (.*)$ ]]; then
-            ln -s "${BASH_REMATCH[1]}" "$path"
-            vecho "    $path -> ${BASH_REMATCH[1]}"
-        elif [[ $line =~ ^# ]]; then
-            # Ignore comments between files
-            continue
-        else
-            echo >&2 "ERROR: Unknown keyword on line $line_no: $line"
-            exit 1
-        fi
-    done < "$ttar_file"
-}
-
-function div {
-    echo "# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -" \
-         "- - - - - -"
-}
-
-function get_mode {
-    local mfile=$1
-    if [ -z "${STAT_OPTION:-}" ]; then
-        if stat -c '%a' "$mfile" >/dev/null 2>&1; then
-            # GNU stat
-            STAT_OPTION='-c'
-            STAT_FORMAT='%a'
-        else
-            # BSD stat
-            STAT_OPTION='-f'
-            # Octal output, user/group/other (omit file type, sticky bit)
-            STAT_FORMAT='%OLp'
-        fi
-    fi
-    stat "${STAT_OPTION}" "${STAT_FORMAT}" "$mfile"
-}
-
-function _create {
-    shopt -s nullglob
-    local mode
-    local eof_without_newline
-    while (( "$#" )); do
-        file=$1
-        if [ -L "$file" ]; then
-            echo "Path: $file"
-            symlinkTo=$(readlink "$file")
-            echo "SymlinkTo: $symlinkTo"
-            vecho "    $file -> $symlinkTo"
-            div
-        elif [ -d "$file" ]; then
-            # Strip trailing slash (if there is one)
-            file=${file%/}
-            echo "Directory: $file"
-            mode=$(get_mode "$file")
-            echo "Mode: $mode"
-            vecho "$mode $file/"
-            div
-            # Find all files and dirs, including hidden/dot files
-            for x in "$file/"{*,.[^.]*}; do
-                _create "$x"
-            done
-        elif [ -f "$file" ]; then
-            echo "Path: $file"
-            lines=$(wc -l "$file"|awk '{print $1}')
-            eof_without_newline=0
-            if [[ "$(wc -c "$file"|awk '{print $1}')" -gt 0 ]] && \
-                    [[ "$(tail -c 1 "$file" | wc -l)" -eq 0 ]]; then
-                eof_without_newline=1
-                lines=$((lines+1))
-            fi
-            echo "Lines: $lines"
-            # Add backslash in front of EOF
-            # Add backslash in front of NULLBYTE
-            # Replace null byte with NULLBYTE
-            if [ $USE_PYTHON -eq 1 ]; then
-                < "$file" python -c "$PYTHON_CREATE_FILTER"
-            else
-                < "$file" \
-                    sed 's/EOF/\\EOF/g;
-                            s/NULLBYTE/\\NULLBYTE/g;
-                            s/\x0/NULLBYTE/g;
-                    '
-            fi
-            if [[ "$eof_without_newline" -eq 1 ]]; then
-                # Finish line with EOF to indicate that the original line did
-                # not end with a linefeed
-                echo "EOF"
-            fi
-            mode=$(get_mode "$file")
-            echo "Mode: $mode"
-            vecho "$mode $file"
-            div
-        else
-            echo >&2 "ERROR: file not found ($file in $(pwd))"
-            exit 2
-        fi
-        shift
-    done
-}
-
-function create {
-    ttar_file=$1
-    shift
-    if [ -z "${1:-}" ]; then
-        echo >&2 "ERROR: missing arguments."
-        echo
-        usage 1
-    fi
-    if [ -e "$ttar_file" ]; then
-        rm "$ttar_file"
-    fi
-    exec > "$ttar_file"
-    echo "# Archive created by ttar $ARG_STRING"
-    _create "$@"
-}
-
-test_environment
-
-if [ -n "${CDIR:-}" ]; then
-    if [[ "$ARCHIVE" != /* ]]; then
-        # Relative path: preserve the archive's location before changing
-        # directory
-        ARCHIVE="$(pwd)/$ARCHIVE"
-    fi
-    cd "$CDIR"
-fi
-
-"$CMD" "$ARCHIVE" "$@"


Test patch:
diff --git a/pkg/controllers/dsa/controller_test.go b/pkg/controllers/dsa/controller_test.go
index a33920f5..356a0413 100644
--- a/pkg/controllers/dsa/controller_test.go
+++ b/pkg/controllers/dsa/controller_test.go
@@ -156,7 +156,35 @@ func (c *controller) newDaemonSetExpected(rawObj client.Object) *apps.DaemonSet
 
 	// add the optional init container
 	if devicePlugin.Spec.InitImage != "" {
-		addInitContainer(&daemonSet, devicePlugin)
+		setInitContainer(&daemonSet.Spec.Template.Spec, devicePlugin.Spec.InitImage)
+
+		daemonSet.Spec.Template.Spec.Volumes = append(daemonSet.Spec.Template.Spec.Volumes, v1.Volume{
+			Name: "sys-devices",
+			VolumeSource: v1.VolumeSource{
+				HostPath: &v1.HostPathVolumeSource{
+					Path: "/sys/devices",
+				},
+			},
+		})
+
+		if devicePlugin.Spec.ProvisioningConfig != "" {
+			daemonSet.Spec.Template.Spec.Volumes = append(daemonSet.Spec.Template.Spec.Volumes, v1.Volume{
+				Name: "intel-dsa-config-volume",
+				VolumeSource: v1.VolumeSource{
+					ConfigMap: &v1.ConfigMapVolumeSource{
+						LocalObjectReference: v1.LocalObjectReference{Name: devicePlugin.Spec.ProvisioningConfig}},
+				},
+			})
+
+			for i, initcontainer := range daemonSet.Spec.Template.Spec.InitContainers {
+				if initcontainer.Name == "intel-idxd-initcontainer" {
+					daemonSet.Spec.Template.Spec.InitContainers[i].VolumeMounts = append(daemonSet.Spec.Template.Spec.InitContainers[i].VolumeMounts, v1.VolumeMount{
+						Name:      "intel-dsa-config-volume",
+						MountPath: "/idxd-init/conf",
+					})
+				}
+			}
+		}
 	}
 
 	return &daemonSet
diff --git a/pkg/topology/testdata/go.mod b/pkg/topology/testdata/go.mod
new file mode 100644
index 00000000..0fc0d9c1
--- /dev/null
+++ b/pkg/topology/testdata/go.mod
@@ -0,0 +1,3 @@
+// This is a kludge to work around the golang toolchain not being able
+// to handle packages with any files with a colon (:) in their name,
+// even if those are not golang sources.
diff --git a/pkg/topology/testdata/sys.ttar b/pkg/topology/testdata/sys.ttar
deleted file mode 100644
index 1f2a6f62..00000000
--- a/pkg/topology/testdata/sys.ttar
+++ /dev/null
@@ -1,125 +0,0 @@
-# Archive created by ttar -C pkg/topology/testdata -c -f pkg/topology/testdata/sys.ttar sys/
-Directory: sys
-Mode: 775
-# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-Directory: sys/devices
-Mode: 775
-# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-Directory: sys/devices/pci0000:00
-Mode: 775
-# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-Directory: sys/devices/pci0000:00/0000:00:02.0
-Mode: 775
-# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-Path: sys/devices/pci0000:00/0000:00:02.0/class
-Lines: 1
-0x030000
-Mode: 664
-# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-Path: sys/devices/pci0000:00/0000:00:02.0/device
-Lines: 1
-0x5912
-Mode: 664
-# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-Directory: sys/devices/pci0000:00/0000:00:02.0/drm
-Mode: 775
-# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-Directory: sys/devices/pci0000:00/0000:00:02.0/drm/card1
-Mode: 775
-# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-Path: sys/devices/pci0000:00/0000:00:02.0/drm/card1/dev
-Lines: 1
-226:1
-Mode: 664
-# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-Directory: sys/devices/pci0000:00/0000:00:02.0/drm/renderD129
-Mode: 775
-# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-Path: sys/devices/pci0000:00/0000:00:02.0/drm/renderD129/dev
-Lines: 1
-226:129
-Mode: 664
-# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-Path: sys/devices/pci0000:00/0000:00:02.0/local_cpulist
-Lines: 1
-0-7
-Mode: 664
-# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-Path: sys/devices/pci0000:00/0000:00:02.0/local_cpus
-Lines: 1
-ff
-Mode: 664
-# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-Path: sys/devices/pci0000:00/0000:00:02.0/numa_node
-Lines: 1
--1
-Mode: 664
-# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-Path: sys/devices/pci0000:00/0000:00:02.0/vendor
-Lines: 1
-0x8086
-Mode: 664
-# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-Directory: sys/devices/virtual
-Mode: 775
-# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-Directory: sys/devices/virtual/mem
-Mode: 775
-# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-Directory: sys/devices/virtual/mem/null
-Mode: 775
-# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-Path: sys/devices/virtual/mem/null/local_cpulist
-Lines: 1
-0-7
-Mode: 664
-# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-Path: sys/devices/virtual/mem/null/numa_node
-Lines: 1
-1,2,3
-Mode: 664
-# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-Directory: sys/devices/virtual/mem/random
-Mode: 775
-# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-Path: sys/devices/virtual/mem/random/local_cpulist
-Lines: 1
-0-7
-Mode: 664
-# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-Path: sys/devices/virtual/mem/random/numa_node
-Lines: 1
--1
-Mode: 664
-# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-Directory: sys/devices/virtual/tty
-Mode: 775
-# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-Directory: sys/devices/virtual/tty/tty
-Mode: 775
-# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-Path: sys/devices/virtual/tty/tty/local_cpulist
-Lines: 1
-0-7
-Mode: 664
-# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-Path: sys/devices/virtual/tty/tty/numa_node
-Lines: 1
-4,5,6
-Mode: 664
-# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-Directory: sys/kernel
-Mode: 775
-# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-Directory: sys/kernel/iommu_groups
-Mode: 775
-# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-Directory: sys/kernel/iommu_groups/42
-Mode: 775
-# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-Directory: sys/kernel/iommu_groups/42/devices
-Mode: 775
-# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-Path: sys/kernel/iommu_groups/42/devices/0000:00:02.0
-SymlinkTo: ../../../../devices/pci0000:00/0000:00:02.0/
-# ttar - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/pkg/topology/testdata/sys/devices/pci0000:00/0000:00:02.0/class b/pkg/topology/testdata/sys/devices/pci0000:00/0000:00:02.0/class
new file mode 100644
index 00000000..c5f02e33
--- /dev/null
+++ b/pkg/topology/testdata/sys/devices/pci0000:00/0000:00:02.0/class
@@ -0,0 +1,1 @@
+0x030000
diff --git a/pkg/topology/testdata/sys/devices/pci0000:00/0000:00:02.0/device b/pkg/topology/testdata/sys/devices/pci0000:00/0000:00:02.0/device
new file mode 100644
index 00000000..70d6a1ce
--- /dev/null
+++ b/pkg/topology/testdata/sys/devices/pci0000:00/0000:00:02.0/device
@@ -0,0 +1,1 @@
+0x5912
diff --git a/pkg/topology/testdata/sys/devices/pci0000:00/0000:00:02.0/drm/card1/dev b/pkg/topology/testdata/sys/devices/pci0000:00/0000:00:02.0/drm/card1/dev
new file mode 100644
index 00000000..fdd256a9
--- /dev/null
+++ b/pkg/topology/testdata/sys/devices/pci0000:00/0000:00:02.0/drm/card1/dev
@@ -0,0 +1,1 @@
+226:1
diff --git a/pkg/topology/testdata/sys/devices/pci0000:00/0000:00:02.0/drm/renderD129/dev b/pkg/topology/testdata/sys/devices/pci0000:00/0000:00:02.0/drm/renderD129/dev
new file mode 100644
index 00000000..c8d81347
--- /dev/null
+++ b/pkg/topology/testdata/sys/devices/pci0000:00/0000:00:02.0/drm/renderD129/dev
@@ -0,0 +1,1 @@
+226:129
diff --git a/pkg/topology/testdata/sys/devices/pci0000:00/0000:00:02.0/local_cpulist b/pkg/topology/testdata/sys/devices/pci0000:00/0000:00:02.0/local_cpulist
new file mode 100644
index 00000000..74fc2fb6
--- /dev/null
+++ b/pkg/topology/testdata/sys/devices/pci0000:00/0000:00:02.0/local_cpulist
@@ -0,0 +1,1 @@
+0-7
diff --git a/pkg/topology/testdata/sys/devices/pci0000:00/0000:00:02.0/local_cpus b/pkg/topology/testdata/sys/devices/pci0000:00/0000:00:02.0/local_cpus
new file mode 100644
index 00000000..fcd15acf
--- /dev/null
+++ b/pkg/topology/testdata/sys/devices/pci0000:00/0000:00:02.0/local_cpus
@@ -0,0 +1,1 @@
+ff
diff --git a/pkg/topology/testdata/sys/devices/pci0000:00/0000:00:02.0/numa_node b/pkg/topology/testdata/sys/devices/pci0000:00/0000:00:02.0/numa_node
new file mode 100644
index 00000000..3a2e3f49
--- /dev/null
+++ b/pkg/topology/testdata/sys/devices/pci0000:00/0000:00:02.0/numa_node
@@ -0,0 +1,1 @@
+-1
diff --git a/pkg/topology/testdata/sys/devices/pci0000:00/0000:00:02.0/vendor b/pkg/topology/testdata/sys/devices/pci0000:00/0000:00:02.0/vendor
new file mode 100644
index 00000000..ce6dc4da
--- /dev/null
+++ b/pkg/topology/testdata/sys/devices/pci0000:00/0000:00:02.0/vendor
@@ -0,0 +1,1 @@
+0x8086
diff --git a/pkg/topology/testdata/sys/devices/virtual/mem/null/local_cpulist b/pkg/topology/testdata/sys/devices/virtual/mem/null/local_cpulist
new file mode 100644
index 00000000..74fc2fb6
--- /dev/null
+++ b/pkg/topology/testdata/sys/devices/virtual/mem/null/local_cpulist
@@ -0,0 +1,1 @@
+0-7
diff --git a/pkg/topology/testdata/sys/devices/virtual/mem/null/numa_node b/pkg/topology/testdata/sys/devices/virtual/mem/null/numa_node
new file mode 100644
index 00000000..b0246d59
--- /dev/null
+++ b/pkg/topology/testdata/sys/devices/virtual/mem/null/numa_node
@@ -0,0 +1,1 @@
+1,2,3
diff --git a/pkg/topology/testdata/sys/devices/virtual/mem/random/local_cpulist b/pkg/topology/testdata/sys/devices/virtual/mem/random/local_cpulist
new file mode 100644
index 00000000..74fc2fb6
--- /dev/null
+++ b/pkg/topology/testdata/sys/devices/virtual/mem/random/local_cpulist
@@ -0,0 +1,1 @@
+0-7
diff --git a/pkg/topology/testdata/sys/devices/virtual/mem/random/numa_node b/pkg/topology/testdata/sys/devices/virtual/mem/random/numa_node
new file mode 100644
index 00000000..3a2e3f49
--- /dev/null
+++ b/pkg/topology/testdata/sys/devices/virtual/mem/random/numa_node
@@ -0,0 +1,1 @@
+-1
diff --git a/pkg/topology/testdata/sys/devices/virtual/tty/tty/local_cpulist b/pkg/topology/testdata/sys/devices/virtual/tty/tty/local_cpulist
new file mode 100644
index 00000000..74fc2fb6
--- /dev/null
+++ b/pkg/topology/testdata/sys/devices/virtual/tty/tty/local_cpulist
@@ -0,0 +1,1 @@
+0-7
diff --git a/pkg/topology/testdata/sys/devices/virtual/tty/tty/numa_node b/pkg/topology/testdata/sys/devices/virtual/tty/tty/numa_node
new file mode 100644
index 00000000..6400ac84
--- /dev/null
+++ b/pkg/topology/testdata/sys/devices/virtual/tty/tty/numa_node
@@ -0,0 +1,1 @@
+4,5,6
diff --git a/pkg/topology/testdata/sys/kernel/iommu_groups/42/devices/0000:00:02.0 b/pkg/topology/testdata/sys/kernel/iommu_groups/42/devices/0000:00:02.0
new file mode 120000
index 00000000..485b1d27
--- /dev/null
+++ b/pkg/topology/testdata/sys/kernel/iommu_groups/42/devices/0000:00:02.0
@@ -0,0 +1,1 @@
+../../../../devices/pci0000:00/0000:00:02.0/
\ No newline at end of file
diff --git a/test/e2e/deviceplugins_suite_test.go b/test/e2e/deviceplugins_suite_test.go
index deee74e7..1cd1c641 100644
--- a/test/e2e/deviceplugins_suite_test.go
+++ b/test/e2e/deviceplugins_suite_test.go
@@ -22,6 +22,7 @@ import (
 	"github.com/onsi/ginkgo"
 	"github.com/onsi/gomega"
 
+	_ "github.com/intel/intel-device-plugins-for-kubernetes/test/e2e/dlb"
 	_ "github.com/intel/intel-device-plugins-for-kubernetes/test/e2e/fpga"
 	_ "github.com/intel/intel-device-plugins-for-kubernetes/test/e2e/fpgaadmissionwebhook"
 	_ "github.com/intel/intel-device-plugins-for-kubernetes/test/e2e/gpu"
diff --git a/test/e2e/dlb/dlb.go b/test/e2e/dlb/dlb.go
new file mode 100644
index 00000000..706ef273
--- /dev/null
+++ b/test/e2e/dlb/dlb.go
@@ -0,0 +1,101 @@
+// Copyright 2021 Intel Corporation. All Rights Reserved.
+//
+// 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 dlb
+
+import (
+	"context"
+	"path/filepath"
+	"time"
+
+	"github.com/intel/intel-device-plugins-for-kubernetes/test/e2e/utils"
+	"github.com/onsi/ginkgo"
+	v1 "k8s.io/api/core/v1"
+	"k8s.io/apimachinery/pkg/api/resource"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+	"k8s.io/apimachinery/pkg/labels"
+	"k8s.io/kubernetes/test/e2e/framework"
+	"k8s.io/kubernetes/test/e2e/framework/kubectl"
+	e2epod "k8s.io/kubernetes/test/e2e/framework/pod"
+)
+
+const (
+	kustomizationYaml = "deployments/dlb_plugin/kustomization.yaml"
+)
+
+func init() {
+	ginkgo.Describe("dlb plugin", describe)
+}
+
+func describe() {
+	f := framework.NewDefaultFramework("dlbplugin")
+
+	kustomizationPath, err := utils.LocateRepoFile(kustomizationYaml)
+	if err != nil {
+		framework.Failf("unable to locate %q: %v", kustomizationYaml, err)
+	}
+
+	ginkgo.It("checks availability of DLB resources", func() {
+		ginkgo.By("deploying DLB plugin")
+		framework.RunKubectlOrDie(f.Namespace.Name, "--namespace", f.Namespace.Name, "apply", "-k", filepath.Dir(kustomizationPath))
+
+		ginkgo.By("waiting for DLB plugin's availability")
+		if _, err := e2epod.WaitForPodsWithLabelRunningReady(f.ClientSet, f.Namespace.Name,
+			labels.Set{"app": "intel-dlb-plugin"}.AsSelector(), 1 /* one replica */, 100*time.Second); err != nil {
+			framework.DumpAllNamespaceInfo(f.ClientSet, f.Namespace.Name)
+			kubectl.LogFailedContainers(f.ClientSet, f.Namespace.Name, framework.Logf)
+			framework.Failf("unable to wait for all pods to be running and ready: %v", err)
+		}
+
+		ginkgo.By("checking the pf resource is allocatable")
+		if err := utils.WaitForNodesWithResource(f.ClientSet, "dlb.intel.com/pf", 30*time.Second); err != nil {
+			framework.Failf("unable to wait for nodes to have positive allocatable resource: %v", err)
+		}
+		ginkgo.By("checking the vf resource is allocatable")
+		if err := utils.WaitForNodesWithResource(f.ClientSet, "dlb.intel.com/vf", 30*time.Second); err != nil {
+			framework.Failf("unable to wait for nodes to have positive allocatable resource: %v", err)
+		}
+
+		ginkgo.By("submitting a pod requesting DLB resources")
+		podSpec := &v1.Pod{
+			ObjectMeta: metav1.ObjectMeta{Name: "dlbplugin-tester"},
+			Spec: v1.PodSpec{
+				Containers: []v1.Container{
+					{
+						Name:  "testcontainer-pf",
+						Image: "intel/dlb-libdlb-demo:devel",
+						Resources: v1.ResourceRequirements{
+							Requests: v1.ResourceList{"dlb.intel.com/pf": resource.MustParse("1")},
+							Limits:   v1.ResourceList{"dlb.intel.com/pf": resource.MustParse("1")},
+						},
+					},
+					{
+						Name:  "testcontainer-vf",
+						Image: "intel/dlb-dpdk-demo:devel",
+						Resources: v1.ResourceRequirements{
+							Requests: v1.ResourceList{"dlb.intel.com/vf": resource.MustParse("1")},
+							Limits:   v1.ResourceList{"dlb.intel.com/vf": resource.MustParse("1")},
+						},
+					},
+				},
+				RestartPolicy: v1.RestartPolicyNever,
+			},
+		}
+		pod, err := f.ClientSet.CoreV1().Pods(f.Namespace.Name).Create(context.TODO(), podSpec, metav1.CreateOptions{})
+		framework.ExpectNoError(err, "pod Create API error")
+
+		ginkgo.By("waiting the pod to finnish successfully")
+		f.PodClient().WaitForFinish(pod.ObjectMeta.Name, 60*time.Second)
+	})
+}
diff --git a/test/envtest/dlbdeviceplugin_controller_test.go b/test/envtest/dlbdeviceplugin_controller_test.go
deleted file mode 100644
index e82cb570..00000000
--- a/test/envtest/dlbdeviceplugin_controller_test.go
+++ /dev/null
@@ -1,105 +0,0 @@
-// Copyright 2021 Intel Corporation. All Rights Reserved.
-//
-// 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 envtest
-
-import (
-	"context"
-	"time"
-
-	. "github.com/onsi/ginkgo"
-	. "github.com/onsi/gomega"
-	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
-	"k8s.io/apimachinery/pkg/types"
-
-	devicepluginv1 "github.com/intel/intel-device-plugins-for-kubernetes/pkg/apis/deviceplugin/v1"
-)
-
-var _ = Describe("DlbDevicePlugin Controller", func() {
-
-	const timeout = time.Second * 30
-	const interval = time.Second * 1
-
-	AfterEach(func() {
-		time.Sleep(time.Second * 2)
-
-	})
-
-	Context("Basic CRUD operations", func() {
-		It("should handle DlbDevicePlugin objects correctly", func() {
-			spec := devicepluginv1.DlbDevicePluginSpec{
-				Image:        "testimage",
-				NodeSelector: map[string]string{"feature.node.kubernetes.io/dlb": "true"},
-				LogLevel:     4,
-			}
-
-			key := types.NamespacedName{
-				Name: "dlbdeviceplugin-test",
-			}
-
-			toCreate := &devicepluginv1.DlbDevicePlugin{
-				ObjectMeta: metav1.ObjectMeta{
-					Name: key.Name,
-				},
-				Spec: spec,
-			}
-
-			By("creating DlbDevicePlugin successfully")
-			Expect(k8sClient.Create(context.Background(), toCreate)).Should(Succeed())
-			time.Sleep(time.Second * 5)
-
-			fetched := &devicepluginv1.DlbDevicePlugin{}
-			Eventually(func() bool {
-				_ = k8sClient.Get(context.Background(), key, fetched)
-				return len(fetched.Status.ControlledDaemonSet.UID) > 0
-			}, timeout, interval).Should(BeTrue())
-
-			Eventually(func() devicepluginv1.DlbDevicePluginSpec {
-				_ = k8sClient.Get(context.Background(), key, fetched)
-				return fetched.Spec
-			}, timeout, interval).Should(Equal(spec))
-
-			By("updating image name successfully")
-			updatedImage := "updated-dlb-testimage"
-			updatedNodeSelector := map[string]string{"updated-dlb-nodeSelector": "true"}
-			updatedLogLevel := 3
-			fetched.Spec.Image = updatedImage
-			fetched.Spec.NodeSelector = updatedNodeSelector
-			fetched.Spec.LogLevel = updatedLogLevel
-
-			Expect(k8sClient.Update(context.Background(), fetched)).Should(Succeed())
-			fetchedUpdated := &devicepluginv1.DlbDevicePlugin{}
-			Eventually(func() devicepluginv1.DlbDevicePluginSpec {
-				_ = k8sClient.Get(context.Background(), key, fetchedUpdated)
-				return fetchedUpdated.Spec
-			}, timeout, interval).Should(Equal(
-				devicepluginv1.DlbDevicePluginSpec{
-					Image:        updatedImage,
-					NodeSelector: updatedNodeSelector,
-					LogLevel:     updatedLogLevel}))
-
-			By("deleting DlbDevicePlugin successfully")
-			Eventually(func() error {
-				f := &devicepluginv1.DlbDevicePlugin{}
-				_ = k8sClient.Get(context.Background(), key, f)
-				return k8sClient.Delete(context.Background(), f)
-			}, timeout, interval).Should(Succeed())
-
-			Eventually(func() error {
-				f := &devicepluginv1.DlbDevicePlugin{}
-				return k8sClient.Get(context.Background(), key, f)
-			}, timeout, interval).ShouldNot(Succeed())
-		})
-	})
-})
diff --git a/test/envtest/suite_test.go b/test/envtest/suite_test.go
index 7cdd6ebc..c59d4e74 100644
--- a/test/envtest/suite_test.go
+++ b/test/envtest/suite_test.go
@@ -31,7 +31,6 @@ import (
 	logf "sigs.k8s.io/controller-runtime/pkg/log"
 
 	devicepluginv1 "github.com/intel/intel-device-plugins-for-kubernetes/pkg/apis/deviceplugin/v1"
-	dlbctr "github.com/intel/intel-device-plugins-for-kubernetes/pkg/controllers/dlb"
 	dsactr "github.com/intel/intel-device-plugins-for-kubernetes/pkg/controllers/dsa"
 	fpgactr "github.com/intel/intel-device-plugins-for-kubernetes/pkg/controllers/fpga"
 	gpuctr "github.com/intel/intel-device-plugins-for-kubernetes/pkg/controllers/gpu"
@@ -92,8 +91,6 @@ var _ = BeforeSuite(func() {
 	Expect(err).ToNot(HaveOccurred())
 	err = dsactr.SetupReconciler(k8sManager, metav1.NamespaceSystem, !withWebhook)
 	Expect(err).ToNot(HaveOccurred())
-	err = dlbctr.SetupReconciler(k8sManager, metav1.NamespaceSystem, !withWebhook)
-	Expect(err).ToNot(HaveOccurred())
 
 	go func() {
 		err = k8sManager.Start(ctx)