From 2f5a71880d345af8c47afce9e60a6f56ebe00a92 Mon Sep 17 00:00:00 2001 From: Igor Velichkovich Date: Tue, 16 Apr 2024 17:00:52 -0700 Subject: [PATCH] fast node slice initial implementation --- .gitignore | 2 + Dockerfile | 1 + backup-ip-pools | 269 + .../node_slice_controller.go | 91 + doc/crds/daemonset-install.yaml | 5 + doc/crds/node-slice-controller.yaml | 123 + ...hereabouts.cni.cncf.io_nodeslicepools.yaml | 76 + e2e/client/ippool.go | 32 + e2e/client/node.go | 1 + e2e/client/nodeslicepool.go | 20 + e2e/client/whereabouts.go | 21 + e2e/e2e_node_slice_test.go | 349 + e2e/e2e_test.go | 202 +- e2e/poolconsistency/node_slice_checker.go | 75 + e2e/util/util.go | 232 + hack/build-go.sh | 2 + hack/cni-install.yml | 6 +- hack/e2e-setup-kind-cluster.sh | 4 +- kubeconfig.yaml | 19 + .../v1alpha1/nodeslicepool_types.go | 52 + .../v1alpha1/register.go | 2 + .../v1alpha1/zz_generated.deepcopy.go | 109 + .../v1alpha1/fake/fake_nodeslicepool.go | 141 + .../fake_whereabouts.cni.cncf.io_client.go | 4 + .../v1alpha1/generated_expansion.go | 2 + .../v1alpha1/nodeslicepool.go | 194 + .../whereabouts.cni.cncf.io_client.go | 5 + .../informers/externalversions/generic.go | 2 + .../v1alpha1/interface.go | 7 + .../v1alpha1/nodeslicepool.go | 89 + .../v1alpha1/expansion_generated.go | 8 + .../v1alpha1/nodeslicepool.go | 98 + pkg/config/config.go | 1 + pkg/iphelpers/iphelpers.go | 58 + pkg/iphelpers/iphelpers_test.go | 66 + pkg/logging/logging.go | 16 +- pkg/logging/logging_test.go | 6 +- pkg/node-controller/controller.go | 622 ++ pkg/node-controller/controller_test.go | 972 ++ pkg/node-controller/signals/signals.go | 28 + pkg/node-controller/signals/signals_posix.go | 8 + pkg/storage/kubernetes/ipam.go | 152 +- pkg/storage/kubernetes/ipam_test.go | 54 + pkg/types/types.go | 6 + temp | 8213 +++++++++++++++++ 45 files changed, 12245 insertions(+), 200 deletions(-) create mode 100644 backup-ip-pools create mode 100644 cmd/nodeslicecontroller/node_slice_controller.go create mode 100644 doc/crds/node-slice-controller.yaml create mode 100644 doc/crds/whereabouts.cni.cncf.io_nodeslicepools.yaml create mode 100644 e2e/client/node.go create mode 100644 e2e/client/nodeslicepool.go create mode 100644 e2e/e2e_node_slice_test.go create mode 100644 e2e/poolconsistency/node_slice_checker.go create mode 100644 e2e/util/util.go create mode 100644 kubeconfig.yaml create mode 100644 pkg/api/whereabouts.cni.cncf.io/v1alpha1/nodeslicepool_types.go create mode 100644 pkg/client/clientset/versioned/typed/whereabouts.cni.cncf.io/v1alpha1/fake/fake_nodeslicepool.go create mode 100644 pkg/client/clientset/versioned/typed/whereabouts.cni.cncf.io/v1alpha1/nodeslicepool.go create mode 100644 pkg/client/informers/externalversions/whereabouts.cni.cncf.io/v1alpha1/nodeslicepool.go create mode 100644 pkg/client/listers/whereabouts.cni.cncf.io/v1alpha1/nodeslicepool.go create mode 100644 pkg/node-controller/controller.go create mode 100644 pkg/node-controller/controller_test.go create mode 100644 pkg/node-controller/signals/signals.go create mode 100644 pkg/node-controller/signals/signals_posix.go create mode 100644 pkg/storage/kubernetes/ipam_test.go create mode 100644 temp diff --git a/.gitignore b/.gitignore index 1eecf4af1..a10637778 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,8 @@ # Output of the go coverage tool, specifically when used with LiteIDE *.out +.idea +kind/ bin/ /github.com/ diff --git a/Dockerfile b/Dockerfile index a76f26af1..ae6dd8eba 100644 --- a/Dockerfile +++ b/Dockerfile @@ -9,5 +9,6 @@ FROM alpine:latest LABEL org.opencontainers.image.source https://github.com/k8snetworkplumbingwg/whereabouts COPY --from=0 /go/src/github.com/k8snetworkplumbingwg/whereabouts/bin/whereabouts . COPY --from=0 /go/src/github.com/k8snetworkplumbingwg/whereabouts/bin/ip-control-loop . +COPY --from=0 /go/src/github.com/k8snetworkplumbingwg/whereabouts/bin/node-slice-controller . COPY script/install-cni.sh . CMD ["/install-cni.sh"] diff --git a/backup-ip-pools b/backup-ip-pools new file mode 100644 index 000000000..279801bcf --- /dev/null +++ b/backup-ip-pools @@ -0,0 +1,269 @@ +apiVersion: v1 +items: +- apiVersion: whereabouts.cni.cncf.io/v1alpha1 + kind: IPPool + metadata: + creationTimestamp: "2024-05-13T18:06:14Z" + generation: 1 + name: wa-nad-kind-control-plane + namespace: kube-system + resourceVersion: "89341" + uid: dd4f0db6-ab76-42bd-af65-51f851527b3e + spec: + allocations: {} + range: 10.0.0.0/8 +- apiVersion: whereabouts.cni.cncf.io/v1alpha1 + kind: IPPool + metadata: + creationTimestamp: "2024-05-13T18:06:11Z" + generation: 2 + name: wa-nad-kind-worker + namespace: kube-system + resourceVersion: "89175" + uid: 0cf74918-2359-4ae0-a0b0-5e59c1f10f23 + spec: + allocations: + "1": + id: 15e56cd8f50603a504f8852857fd32a81fdc177384258d39e0cce930cf26f5bf + podref: default/web-3 + range: 10.0.64.0/20 +- apiVersion: whereabouts.cni.cncf.io/v1alpha1 + kind: IPPool + metadata: + creationTimestamp: "2024-05-13T18:06:11Z" + generation: 2 + name: wa-nad-kind-worker10 + namespace: kube-system + resourceVersion: "89199" + uid: fa824bd7-8baf-495a-87c1-250deb643529 + spec: + allocations: + "1": + id: 4c7ef4d2c2364903a9eb95d48f6020a145d76dcd9426d255280f30e664c94f7c + podref: default/web-0 + range: 10.0.128.0/20 +- apiVersion: whereabouts.cni.cncf.io/v1alpha1 + kind: IPPool + metadata: + creationTimestamp: "2024-05-13T18:06:11Z" + generation: 3 + name: wa-nad-kind-worker11 + namespace: kube-system + resourceVersion: "89205" + uid: ec1151ef-5494-47e8-bc16-06c9b4141fa3 + spec: + allocations: + "1": + id: 0d81f7b32979f895d4744a640f95f85fdee3c843622307813822da471830b216 + podref: default/web-16 + "2": + id: 65bffaae9cee8201cdb558f9eec95111a6bf06ae3903b8f45850bd0e9788879d + podref: default/web-13 + range: 10.0.144.0/20 +- apiVersion: whereabouts.cni.cncf.io/v1alpha1 + kind: IPPool + metadata: + creationTimestamp: "2024-05-13T18:06:09Z" + generation: 2 + name: wa-nad-kind-worker12 + namespace: kube-system + resourceVersion: "89102" + uid: 0ec20afa-425d-4cc7-a94c-6e56b989fe14 + spec: + allocations: + "1": + id: b65a1853354b42a413245835cf40d78baafdeab3e15092f0bb6cf315ae9145a9 + podref: default/web-7 + range: 10.0.0.0/20 +- apiVersion: whereabouts.cni.cncf.io/v1alpha1 + kind: IPPool + metadata: + creationTimestamp: "2024-05-13T18:06:11Z" + generation: 2 + name: wa-nad-kind-worker13 + namespace: kube-system + resourceVersion: "89248" + uid: 632ab0ab-0eca-4286-8a26-a9049500c7d1 + spec: + allocations: + "1": + id: 69052635b467754fd351616c62075759c73ec8f73c9a20427cf7f3ed854b08ce + podref: default/web-9 + range: 10.0.160.0/20 +- apiVersion: whereabouts.cni.cncf.io/v1alpha1 + kind: IPPool + metadata: + creationTimestamp: "2024-05-13T18:06:11Z" + generation: 2 + name: wa-nad-kind-worker14 + namespace: kube-system + resourceVersion: "89168" + uid: da9fdb1f-24b1-4a65-831e-8e09efd54158 + spec: + allocations: + "1": + id: 1ed33682057dd7c11ae1d70c386008ae9cdf6e8eaf999fb0a088eac72f6e6092 + podref: default/web-6 + range: 10.0.176.0/20 +- apiVersion: whereabouts.cni.cncf.io/v1alpha1 + kind: IPPool + metadata: + creationTimestamp: "2024-05-13T18:06:12Z" + generation: 2 + name: wa-nad-kind-worker15 + namespace: kube-system + resourceVersion: "89319" + uid: 365b2337-edac-4dab-abb2-7e2fbf01cc3c + spec: + allocations: + "1": + id: 3334f1ae4dc5432c56aaf82b746bdc410d6047d80733811812f0975317f1e7fa + podref: default/web-12 + range: 10.0.16.0/20 +- apiVersion: whereabouts.cni.cncf.io/v1alpha1 + kind: IPPool + metadata: + creationTimestamp: "2024-05-13T18:06:09Z" + generation: 2 + name: wa-nad-kind-worker16 + namespace: kube-system + resourceVersion: "89078" + uid: 147e4979-b2d9-44d2-b88c-6f425eea2894 + spec: + allocations: + "1": + id: 652a78a6a20356b161d9759228809f898249ea5282e8b60b9da26e76096da096 + podref: default/web-1 + range: 10.0.32.0/20 +- apiVersion: whereabouts.cni.cncf.io/v1alpha1 + kind: IPPool + metadata: + creationTimestamp: "2024-05-13T18:06:11Z" + generation: 2 + name: wa-nad-kind-worker2 + namespace: kube-system + resourceVersion: "89153" + uid: fe4a0b26-897e-495f-8ddf-7dd2937e7ba8 + spec: + allocations: + "1": + id: 03ec29893896071efc51537912d499adf414edb4692b9a2ae0de106e2bc630f9 + podref: default/web-8 + range: 10.0.192.0/20 +- apiVersion: whereabouts.cni.cncf.io/v1alpha1 + kind: IPPool + metadata: + creationTimestamp: "2024-05-13T18:06:12Z" + generation: 2 + name: wa-nad-kind-worker3 + namespace: kube-system + resourceVersion: "89279" + uid: 809444fc-3a7c-4c84-90c5-69f537706964 + spec: + allocations: + "1": + id: f887517a5770729e6815c8b05233c193c737ccdbcaf4f944e8a924d887104fac + podref: default/web-19 + range: 10.0.208.0/20 +- apiVersion: whereabouts.cni.cncf.io/v1alpha1 + kind: IPPool + metadata: + creationTimestamp: "2024-05-13T18:06:09Z" + generation: 2 + name: wa-nad-kind-worker4 + namespace: kube-system + resourceVersion: "89074" + uid: e2f79eff-2d62-4b90-9ab2-71d56db54371 + spec: + allocations: + "1": + id: f52adf7bc90a10cffc46017d939c89574b7d2a73200a4bb88b917e993b1e22d8 + podref: default/web-2 + range: 10.0.48.0/20 +- apiVersion: whereabouts.cni.cncf.io/v1alpha1 + kind: IPPool + metadata: + creationTimestamp: "2024-05-13T18:06:11Z" + generation: 3 + name: wa-nad-kind-worker5 + namespace: kube-system + resourceVersion: "89237" + uid: ea5bfc24-45bf-431a-a1f6-5c6d574537b9 + spec: + allocations: + "1": + id: c079825def9e249408d639aad537b5a9f4c9ea70efd74b59a920c55e896d0809 + podref: default/web-11 + "2": + id: 3d4cc3799d6abe91578f85d5b54223a4ce0cf0c5003b61878347d2aab8bb90f7 + podref: default/web-15 + range: 10.0.96.0/20 +- apiVersion: whereabouts.cni.cncf.io/v1alpha1 + kind: IPPool + metadata: + creationTimestamp: "2024-05-13T18:06:09Z" + generation: 3 + name: wa-nad-kind-worker6 + namespace: kube-system + resourceVersion: "89103" + uid: 19ee6861-b60c-4191-9954-c563f2b6fdab + spec: + allocations: + "1": + id: 7a82e54f4aed85584b3140ebe32ec1a4e3c07f92cd7ce97b0771d25174e14b00 + podref: default/web-14 + "2": + id: f798a65997b572a3654937452fbee5b866ba7aaa4fa04d97f501cbebbf18fac5 + podref: default/web-18 + range: 10.0.224.0/20 +- apiVersion: whereabouts.cni.cncf.io/v1alpha1 + kind: IPPool + metadata: + creationTimestamp: "2024-05-13T18:06:11Z" + generation: 2 + name: wa-nad-kind-worker7 + namespace: kube-system + resourceVersion: "89222" + uid: f96d1a90-c99a-402b-85bb-fde3ad9cb576 + spec: + allocations: + "1": + id: 8c568d2c1b96bd400a2d3649c86eebf195519246dafcb7b7ed0ab3e320c84f14 + podref: default/web-10 + range: 10.0.80.0/20 +- apiVersion: whereabouts.cni.cncf.io/v1alpha1 + kind: IPPool + metadata: + creationTimestamp: "2024-05-13T18:06:09Z" + generation: 2 + name: wa-nad-kind-worker8 + namespace: kube-system + resourceVersion: "89109" + uid: c7632c7b-d465-430c-9979-cb58fed4b6bc + spec: + allocations: + "1": + id: 90e7c856df1951f79748e6fb21eba4ea1613c084a6aca66546b46c1f945244ae + podref: default/web-5 + range: 10.0.240.0/20 +- apiVersion: whereabouts.cni.cncf.io/v1alpha1 + kind: IPPool + metadata: + creationTimestamp: "2024-05-13T18:06:11Z" + generation: 3 + name: wa-nad-kind-worker9 + namespace: kube-system + resourceVersion: "89224" + uid: 0b976109-aa6b-4e66-9198-0adf145bd6dd + spec: + allocations: + "1": + id: bc4d86106b2cb4a67154e8c2dcd3e801c0ce5892c54e74bfa59b9f116457e645 + podref: default/web-17 + "2": + id: 6286beace20b5c785abc3192b79b21d3968cfd2869c8bef1d902d0f210693162 + podref: default/web-4 + range: 10.1.0.0/20 +kind: List +metadata: + resourceVersion: "" diff --git a/cmd/nodeslicecontroller/node_slice_controller.go b/cmd/nodeslicecontroller/node_slice_controller.go new file mode 100644 index 000000000..679f13feb --- /dev/null +++ b/cmd/nodeslicecontroller/node_slice_controller.go @@ -0,0 +1,91 @@ +package main + +import ( + "flag" + nadclient "github.com/k8snetworkplumbingwg/network-attachment-definition-client/pkg/client/clientset/versioned" + nadinformers "github.com/k8snetworkplumbingwg/network-attachment-definition-client/pkg/client/informers/externalversions" + clientset "github.com/k8snetworkplumbingwg/whereabouts/pkg/client/clientset/versioned" + informers "github.com/k8snetworkplumbingwg/whereabouts/pkg/client/informers/externalversions" + node_controller "github.com/k8snetworkplumbingwg/whereabouts/pkg/node-controller" + + "time" + + kubeinformers "k8s.io/client-go/informers" + "k8s.io/client-go/kubernetes" + "k8s.io/client-go/tools/clientcmd" + "k8s.io/klog/v2" + + "github.com/k8snetworkplumbingwg/whereabouts/pkg/node-controller/signals" +) + +var ( + masterURL string + kubeconfig string +) + +// TODO: leader election +func main() { + klog.InitFlags(nil) + flag.Parse() + + // set up signals so we handle the shutdown signal gracefully + ctx := signals.SetupSignalHandler() + logger := klog.FromContext(ctx) + + cfg, err := clientcmd.BuildConfigFromFlags(masterURL, kubeconfig) + if err != nil { + logger.Error(err, "Error building kubeconfig") + klog.FlushAndExit(klog.ExitFlushTimeout, 1) + } + + kubeClient, err := kubernetes.NewForConfig(cfg) + if err != nil { + logger.Error(err, "Error building kubernetes clientset") + klog.FlushAndExit(klog.ExitFlushTimeout, 1) + } + + whereaboutsClient, err := clientset.NewForConfig(cfg) + if err != nil { + logger.Error(err, "Error building kubernetes clientset") + klog.FlushAndExit(klog.ExitFlushTimeout, 1) + } + + nadClient, err := nadclient.NewForConfig(cfg) + if err != nil { + logger.Error(err, "Error building kubernetes clientset") + klog.FlushAndExit(klog.ExitFlushTimeout, 1) + } + + kubeInformerFactory := kubeinformers.NewSharedInformerFactory(kubeClient, time.Second*30) + whereaboutsInformerFactory := informers.NewSharedInformerFactory(whereaboutsClient, time.Second*30) + nadInformerFactory := nadinformers.NewSharedInformerFactory(nadClient, time.Second*30) + + controller := node_controller.NewController( + ctx, + kubeClient, + whereaboutsClient, + nadClient, + kubeInformerFactory.Core().V1().Nodes(), + whereaboutsInformerFactory.Whereabouts().V1alpha1().NodeSlicePools(), + whereaboutsInformerFactory.Whereabouts().V1alpha1().IPPools(), + nadInformerFactory.K8sCniCncfIo().V1().NetworkAttachmentDefinitions(), + false, + ) + + // notice that there is no need to run Start methods in a separate goroutine. (i.e. go kubeInformerFactory.Start(ctx.done()) + // Start method is non-blocking and runs all registered informers in a dedicated goroutine. + kubeInformerFactory.Start(ctx.Done()) + whereaboutsInformerFactory.Start(ctx.Done()) + nadInformerFactory.Start(ctx.Done()) + + //TODO: make workers configurable via flag, what is a sane value here? How will concurrency work? + if err = controller.Run(ctx, 1); err != nil { + logger.Error(err, "Error running controller") + klog.FlushAndExit(klog.ExitFlushTimeout, 1) + } +} + +func init() { + flag.StringVar(&kubeconfig, "kubeconfig", "", "Path to a kubeconfig. Only required if out-of-cluster.") + flag.StringVar(&masterURL, "master", "", "The address of the Kubernetes API server. Overrides any value in kubeconfig. Only required if out-of-cluster.") +} diff --git a/doc/crds/daemonset-install.yaml b/doc/crds/daemonset-install.yaml index 63d9dc637..3d465cd80 100644 --- a/doc/crds/daemonset-install.yaml +++ b/doc/crds/daemonset-install.yaml @@ -28,6 +28,7 @@ rules: resources: - ippools - overlappingrangeipreservations + - nodeslicepools verbs: - get - list @@ -48,11 +49,14 @@ rules: verbs: - list - watch + - get - apiGroups: [""] resources: - nodes verbs: - get + - list + - watch - apiGroups: ["k8s.cni.cncf.io"] resources: - network-attachment-definitions @@ -118,6 +122,7 @@ spec: SLEEP=false /install-cni.sh && /ip-control-loop -log-level debug image: ghcr.io/k8snetworkplumbingwg/whereabouts:latest + imagePullPolicy: IfNotPresent env: - name: NODENAME valueFrom: diff --git a/doc/crds/node-slice-controller.yaml b/doc/crds/node-slice-controller.yaml new file mode 100644 index 000000000..17d3b9ed4 --- /dev/null +++ b/doc/crds/node-slice-controller.yaml @@ -0,0 +1,123 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: whereabouts-controller + namespace: kube-system +spec: + replicas: 1 + selector: + matchLabels: + app: whereabouts-controller + template: + metadata: + labels: + app: whereabouts-controller + spec: + containers: + - command: + - /node-slice-controller + env: + - name: NODENAME + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: spec.nodeName + - name: WHEREABOUTS_NAMESPACE + valueFrom: + fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + image: ghcr.io/k8snetworkplumbingwg/whereabouts:latest + imagePullPolicy: IfNotPresent + name: whereabouts + resources: + limits: + cpu: 100m + memory: 200Mi + requests: + cpu: 100m + memory: 100Mi + securityContext: + privileged: true + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File + volumeMounts: + - mountPath: /host/opt/cni/bin + name: cnibin + - mountPath: /host/etc/cni/net.d + name: cni-net-dir + - mountPath: /cron-schedule + name: cron-scheduler-configmap + - mountPath: /var/run/secrets/kubernetes.io/serviceaccount + name: kube-api-access-6kd6k + readOnly: true + dnsPolicy: ClusterFirst + enableServiceLinks: true + hostNetwork: true + nodeName: kind-worker3 + preemptionPolicy: PreemptLowerPriority + priority: 0 + restartPolicy: Always + schedulerName: default-scheduler + securityContext: {} + serviceAccount: whereabouts + serviceAccountName: whereabouts + terminationGracePeriodSeconds: 30 + tolerations: + - effect: NoSchedule + operator: Exists + - effect: NoExecute + key: node.kubernetes.io/not-ready + operator: Exists + - effect: NoExecute + key: node.kubernetes.io/unreachable + operator: Exists + - effect: NoSchedule + key: node.kubernetes.io/disk-pressure + operator: Exists + - effect: NoSchedule + key: node.kubernetes.io/memory-pressure + operator: Exists + - effect: NoSchedule + key: node.kubernetes.io/pid-pressure + operator: Exists + - effect: NoSchedule + key: node.kubernetes.io/unschedulable + operator: Exists + - effect: NoSchedule + key: node.kubernetes.io/network-unavailable + operator: Exists + volumes: + - hostPath: + path: /opt/cni/bin + type: "" + name: cnibin + - hostPath: + path: /etc/cni/net.d + type: "" + name: cni-net-dir + - configMap: + defaultMode: 484 + items: + - key: cron-expression + path: config + name: whereabouts-config + name: cron-scheduler-configmap + - name: kube-api-access-6kd6k + projected: + defaultMode: 420 + sources: + - serviceAccountToken: + expirationSeconds: 3607 + path: token + - configMap: + items: + - key: ca.crt + path: ca.crt + name: kube-root-ca.crt + - downwardAPI: + items: + - fieldRef: + apiVersion: v1 + fieldPath: metadata.namespace + path: namespace \ No newline at end of file diff --git a/doc/crds/whereabouts.cni.cncf.io_nodeslicepools.yaml b/doc/crds/whereabouts.cni.cncf.io_nodeslicepools.yaml new file mode 100644 index 000000000..fa4f6a2d7 --- /dev/null +++ b/doc/crds/whereabouts.cni.cncf.io_nodeslicepools.yaml @@ -0,0 +1,76 @@ + +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.4.1 + creationTimestamp: null + name: nodeslicepools.whereabouts.cni.cncf.io +spec: + group: whereabouts.cni.cncf.io + names: + kind: NodeSlicePool + listKind: NodeSlicePoolList + plural: nodeslicepools + singular: nodeslicepool + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: NodeSlicePool is the Schema for the nodesliceippools API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: NodeSlicePoolSpec defines the desired state of NodeSlicePool + properties: + range: + description: Range is a RFC 4632/4291-style string that represents + an IP address and prefix length in CIDR notation this refers to + the entire range where the node is allocated a subset + type: string + sliceSize: + type: string + required: + - range + - sliceSize + type: object + status: + description: NodeSlicePoolStatus defines the desired state of NodeSlicePool + properties: + allocations: + items: + properties: + nodeName: + type: string + sliceRange: + type: string + required: + - nodeName + - sliceRange + type: object + type: array + required: + - allocations + type: object + type: object + served: true + storage: true +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/e2e/client/ippool.go b/e2e/client/ippool.go index 49d1ced77..f8adbd629 100644 --- a/e2e/client/ippool.go +++ b/e2e/client/ippool.go @@ -7,6 +7,7 @@ import ( "context" "errors" "fmt" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "time" kubeClient "github.com/k8snetworkplumbingwg/whereabouts/pkg/storage/kubernetes" @@ -31,8 +32,39 @@ func isIPPoolAllocationsEmpty(ctx context.Context, k8sIPAM *kubeClient.Kubernete } } +func isIPPoolAllocationsEmptyForNodeSlices(k8sIPAM *kubeClient.KubernetesIPAM, ipPoolCIDR string, clientInfo *ClientInfo) wait.ConditionFunc { + return func() (bool, error) { + nodes, err := clientInfo.Client.CoreV1().Nodes().List(context.TODO(), metav1.ListOptions{}) + if err != nil { + return false, err + } + for _, node := range nodes.Items { + ipPool, err := k8sIPAM.GetIPPool(context.Background(), kubeClient.PoolIdentifier{NodeName: node.Name, IpRange: ipPoolCIDR, NetworkName: k8sIPAM.Config.NetworkName}) + //noPoolError := fmt.Errorf("k8s pool initialized") + if err != nil { + if err.Error() == "k8s pool initialized" { + continue + } else { + return false, err + } + } + + if len(ipPool.Allocations()) != 0 { + return false, nil + } + } + return true, nil + } +} + // WaitForZeroIPPoolAllocations polls up to timeout seconds for IP pool allocations to be gone from the Kubernetes cluster. // Returns an error if any IP pool allocations remain after time limit, or if GETing IP pools causes an error. func WaitForZeroIPPoolAllocations(ctx context.Context, k8sIPAM *kubeClient.KubernetesIPAM, ipPoolCIDR string, timeout time.Duration) error { return wait.PollUntilContextTimeout(ctx, time.Second, timeout, true, isIPPoolAllocationsEmpty(ctx, k8sIPAM, ipPoolCIDR)) } + +// WaitForZeroIPPoolAllocationsAcrossNodeSlices polls up to timeout seconds for IP pool allocations to be gone from the Kubernetes cluster. +// Returns an error if any IP pool allocations remain after time limit, or if GETing IP pools causes an error. +func WaitForZeroIPPoolAllocationsAcrossNodeSlices(k8sIPAM *kubeClient.KubernetesIPAM, ipPoolCIDR string, timeout time.Duration, clientInfo *ClientInfo) error { + return wait.PollImmediate(time.Second, timeout, isIPPoolAllocationsEmptyForNodeSlices(k8sIPAM, ipPoolCIDR, clientInfo)) +} diff --git a/e2e/client/node.go b/e2e/client/node.go new file mode 100644 index 000000000..da13c8ef3 --- /dev/null +++ b/e2e/client/node.go @@ -0,0 +1 @@ +package client diff --git a/e2e/client/nodeslicepool.go b/e2e/client/nodeslicepool.go new file mode 100644 index 000000000..aa7a127ae --- /dev/null +++ b/e2e/client/nodeslicepool.go @@ -0,0 +1,20 @@ +package client + +import ( + "context" + "fmt" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +func GetNodeSubnet(cs *ClientInfo, nodeName, sliceName, namespace string) (string, error) { + slice, err := cs.WbClient.WhereaboutsV1alpha1().NodeSlicePools(namespace).Get(context.TODO(), sliceName, metav1.GetOptions{}) + if err != nil { + return "", err + } + for _, allocation := range slice.Status.Allocations { + if allocation.NodeName == nodeName { + return allocation.SliceRange, nil + } + } + return "", fmt.Errorf("slice range not found for node") +} diff --git a/e2e/client/whereabouts.go b/e2e/client/whereabouts.go index 93fcdf041..7546e39ac 100644 --- a/e2e/client/whereabouts.go +++ b/e2e/client/whereabouts.go @@ -2,6 +2,9 @@ package client import ( "context" + "fmt" + whereaboutscnicncfiov1alpha1 "github.com/k8snetworkplumbingwg/whereabouts/pkg/api/whereabouts.cni.cncf.io/v1alpha1" + "k8s.io/apimachinery/pkg/api/errors" "time" appsv1 "k8s.io/api/apps/v1" @@ -53,6 +56,16 @@ func NewClientInfo(config *rest.Config) (*ClientInfo, error) { }, nil } +func (c *ClientInfo) GetNodeSlicePool(name string, namespace string) (*whereaboutscnicncfiov1alpha1.NodeSlicePool, error) { + sliceCreateTimeout := 5 * time.Second + time.Sleep(sliceCreateTimeout) + nodeslice, err := c.WbClient.WhereaboutsV1alpha1().NodeSlicePools(namespace).Get(context.TODO(), name, metav1.GetOptions{}) + if err != nil { + return nil, err + } + return nodeslice, nil +} + func (c *ClientInfo) AddNetAttachDef(netattach *nettypes.NetworkAttachmentDefinition) (*nettypes.NetworkAttachmentDefinition, error) { return c.NetClient.NetworkAttachmentDefinitions(netattach.ObjectMeta.Namespace).Create(context.TODO(), netattach, metav1.CreateOptions{}) } @@ -61,6 +74,14 @@ func (c *ClientInfo) DelNetAttachDef(netattach *nettypes.NetworkAttachmentDefini return c.NetClient.NetworkAttachmentDefinitions(netattach.ObjectMeta.Namespace).Delete(context.TODO(), netattach.Name, metav1.DeleteOptions{}) } +func (c *ClientInfo) NodeSliceDeleted(name, namespace string) error { + _, err := c.WbClient.WhereaboutsV1alpha1().NodeSlicePools(namespace).Get(context.TODO(), name, metav1.GetOptions{}) + if err == nil || !errors.IsNotFound(err) { + return fmt.Errorf("expected not found nodeslice") + } + return nil +} + func (c *ClientInfo) ProvisionPod(podName string, namespace string, label, annotations map[string]string) (*corev1.Pod, error) { ctx := context.Background() pod := entities.PodObject(podName, namespace, label, annotations) diff --git a/e2e/e2e_node_slice_test.go b/e2e/e2e_node_slice_test.go new file mode 100644 index 000000000..7bcdba12f --- /dev/null +++ b/e2e/e2e_node_slice_test.go @@ -0,0 +1,349 @@ +package whereabouts_e2e + +import ( + "context" + nettypes "github.com/k8snetworkplumbingwg/network-attachment-definition-client/pkg/apis/k8s.cni.cncf.io/v1" + wbtestclient "github.com/k8snetworkplumbingwg/whereabouts/e2e/client" + "github.com/k8snetworkplumbingwg/whereabouts/e2e/entities" + "github.com/k8snetworkplumbingwg/whereabouts/e2e/poolconsistency" + "github.com/k8snetworkplumbingwg/whereabouts/e2e/retrievers" + testenv "github.com/k8snetworkplumbingwg/whereabouts/e2e/testenvironment" + "github.com/k8snetworkplumbingwg/whereabouts/e2e/util" + "github.com/k8snetworkplumbingwg/whereabouts/pkg/api/whereabouts.cni.cncf.io/v1alpha1" + "github.com/k8snetworkplumbingwg/whereabouts/pkg/storage" + wbstorage "github.com/k8snetworkplumbingwg/whereabouts/pkg/storage/kubernetes" + "github.com/k8snetworkplumbingwg/whereabouts/pkg/types" + . "github.com/onsi/ginkgo" + "github.com/onsi/ginkgo/extensions/table" + . "github.com/onsi/gomega" + v1 "k8s.io/api/apps/v1" + core "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/rest" + "testing" + "time" +) + +func TestWhereaboutsE2ENodeSlice(t *testing.T) { + RegisterFailHandler(Fail) + RunSpecs(t, "whereabouts-e2e-node-slice") +} + +var _ = Describe("Whereabouts node slice functionality", func() { + Context("Test setup", func() { + const ( + testNamespace = "default" + ipv4TestRange = "10.0.0.0/8" + sliceSize = "/20" // tests will depend on subnets being > node count of test environment + testNetworkName = "wa-nad" + subnets = 4096 + rsName = "whereabouts-scale-test" + ) + + var ( + clientInfo *wbtestclient.ClientInfo + testConfig *testenv.Configuration + netAttachDef *nettypes.NetworkAttachmentDefinition + replicaSet *v1.ReplicaSet + pod *core.Pod + ) + + BeforeEach(func() { + var ( + config *rest.Config + err error + ) + + testConfig, err = testenv.NewConfig() + Expect(err).NotTo(HaveOccurred()) + + config, err = util.ClusterConfig() + Expect(err).NotTo(HaveOccurred()) + + clientInfo, err = wbtestclient.NewClientInfo(config) + Expect(err).NotTo(HaveOccurred()) + + netAttachDef = util.MacvlanNetworkWithNodeSlice(testNetworkName, testNamespace, ipv4TestRange, testNetworkName, sliceSize) + + By("creating a NetworkAttachmentDefinition for whereabouts") + _, err = clientInfo.AddNetAttachDef(netAttachDef) + Expect(err).NotTo(HaveOccurred()) + + By("checking node slices have been allocated and nodes are assigned") + Expect(util.ValidateNodeSlicePoolSlicesCreatedAndNodesAssigned(testNetworkName, testNamespace, subnets, clientInfo)).To(Succeed()) + }) + + AfterEach(func() { + Expect(clientInfo.DelNetAttachDef(netAttachDef)).To(Succeed()) + time.Sleep(1 * time.Second) + Expect(clientInfo.NodeSliceDeleted(testNetworkName, testNamespace)).To(Succeed()) + }) + + Context("Single pod tests node slice", func() { + BeforeEach(func() { + const singlePodName = "whereabouts-basic-test" + var err error + + By("creating a pod with whereabouts net-attach-def") + pod, err = clientInfo.ProvisionPod( + singlePodName, + testNamespace, + util.PodTierLabel(singlePodName), + entities.PodNetworkSelectionElements(testNetworkName), + ) + Expect(err).NotTo(HaveOccurred()) + }) + + AfterEach(func() { + By("deleting pod with whereabouts net-attach-def") + Expect(clientInfo.DeletePod(pod)).To(Succeed()) + }) + + It("allocates a single pod within the correct IP range", func() { + By("checking pod IP is within whereabouts IPAM range") + secondaryIfaceIPs, err := retrievers.SecondaryIfaceIPValue(pod) + Expect(err).NotTo(HaveOccurred()) + Expect(secondaryIfaceIPs).NotTo(BeEmpty()) + Expect(util.InNodeRange(clientInfo, pod.Spec.NodeName, testNetworkName, testNamespace, secondaryIfaceIPs[0])).To(Succeed()) + }) + }) + + Context("Replicaset tests node slice", func() { + const ( + emptyReplicaSet = 0 + rsSteadyTimeout = 1200 * time.Second + ) + + var k8sIPAM *wbstorage.KubernetesIPAM + + BeforeEach(func() { + By("creating a replicaset with whereabouts net-attach-def") + var err error + + const ipPoolNamespace = "kube-system" + k8sIPAM, err = wbstorage.NewKubernetesIPAMWithNamespace("", types.IPAMConfig{ + Kubernetes: types.KubernetesConfig{ + KubeConfigPath: testConfig.KubeconfigPath, + }, + NodeSliceSize: sliceSize, + NetworkName: testNetworkName, + Namespace: testNamespace, + }, ipPoolNamespace) + Expect(err).NotTo(HaveOccurred()) + + replicaSet, err = clientInfo.ProvisionReplicaSet( + rsName, + testNamespace, + emptyReplicaSet, + util.PodTierLabel(rsName), + entities.PodNetworkSelectionElements(testNetworkName), + ) + Expect(err).NotTo(HaveOccurred()) + }) + + AfterEach(func() { + By("removing replicas and expecting 0 IP pool allocations") + Expect( + util.CheckZeroIPPoolAllocationsAndReplicas( + clientInfo, k8sIPAM, rsName, testNamespace, ipv4TestRange, testNetworkName)).To(Succeed()) + + By("deleting replicaset with whereabouts net-attach-def") + Expect(clientInfo.DeleteReplicaSet(replicaSet)).To(Succeed()) + }) + + It("allocates each IP pool entry with a unique pod IP", func() { + By("creating max number of pods and checking IP Pool validity") + for i := 0; i < testConfig.NumberOfIterations; i++ { + Expect( + util.CheckZeroIPPoolAllocationsAndReplicas( + clientInfo, k8sIPAM, rsName, testNamespace, ipv4TestRange, testNetworkName)).To(Succeed()) + + allPods, err := clientInfo.Client.CoreV1().Pods(core.NamespaceAll).List(context.TODO(), metav1.ListOptions{}) + Expect(err).NotTo(HaveOccurred()) + + replicaSet, err = clientInfo.UpdateReplicaSet( + entities.ReplicaSetObject( + testConfig.MaxReplicas(allPods.Items), + rsName, + testNamespace, + util.PodTierLabel(rsName), + entities.PodNetworkSelectionElements(testNetworkName), + )) + Expect(err).NotTo(HaveOccurred()) + Expect( + wbtestclient.WaitForReplicaSetSteadyState( + clientInfo.Client, + testNamespace, + entities.ReplicaSetQuery(rsName), + replicaSet, + rsSteadyTimeout)).To(Succeed()) + + podList, err := wbtestclient.ListPods(clientInfo.Client, testNamespace, entities.ReplicaSetQuery(rsName)) + Expect(err).NotTo(HaveOccurred()) + Expect(podList.Items).NotTo(BeEmpty()) + nodes, err := clientInfo.Client.CoreV1().Nodes().List(context.TODO(), metav1.ListOptions{}) + Expect(err).NotTo(HaveOccurred()) + Expect(nodes.Items).NotTo(BeEmpty()) + ipPools := []storage.IPPool{} + for _, node := range nodes.Items { + nodeSliceRange, err := wbstorage.GetNodeSlicePoolRange(context.TODO(), k8sIPAM, node.Name) + Expect(err).NotTo(HaveOccurred()) + ipPool, err := k8sIPAM.GetIPPool(context.Background(), wbstorage.PoolIdentifier{IpRange: nodeSliceRange, NetworkName: testNetworkName, NodeName: node.Name}) + if err == nil { + ipPools = append(ipPools, ipPool) + } + } + Expect(poolconsistency.NewNodeSliceConsistencyCheck(ipPools, podList.Items).MissingIPs()).To(BeEmpty()) + Expect(poolconsistency.NewNodeSliceConsistencyCheck(ipPools, podList.Items).StaleIPs()).To(BeEmpty()) + } + }) + }) + + Context("stateful set tests", func() { + const ( + initialReplicaNumber = 20 + ipPoolNamespace = "kube-system" + namespace = "default" + serviceName = "web" + selector = "app=" + serviceName + statefulSetName = "statefulthingy" + ) + + podList := func(podList *core.PodList) []core.Pod { return podList.Items } + var k8sIPAM *wbstorage.KubernetesIPAM + + Context("regular sized network", func() { + BeforeEach(func() { + var err error + _, err = clientInfo.ProvisionStatefulSet(statefulSetName, namespace, serviceName, initialReplicaNumber, testNetworkName) + Expect(err).NotTo(HaveOccurred()) + Expect( + clientInfo.Client.CoreV1().Pods(namespace).List( + context.TODO(), metav1.ListOptions{LabelSelector: selector})).To( + WithTransform(podList, HaveLen(initialReplicaNumber))) + + const ipPoolNamespace = "kube-system" + k8sIPAM, err = wbstorage.NewKubernetesIPAMWithNamespace("", types.IPAMConfig{ + Kubernetes: types.KubernetesConfig{ + KubeConfigPath: testConfig.KubeconfigPath, + }, + NodeSliceSize: sliceSize, + NetworkName: testNetworkName, + Namespace: testNamespace, + }, ipPoolNamespace) + Expect(err).NotTo(HaveOccurred()) + }) + + AfterEach(func() { + Expect(clientInfo.DeleteStatefulSet(namespace, serviceName, selector)).To(Succeed()) + Expect( + clientInfo.Client.CoreV1().Pods(namespace).List( + context.TODO(), metav1.ListOptions{LabelSelector: selector})).To( + WithTransform(podList, BeEmpty()), + "cannot have leaked pods in the system") + + poolAllocations := func(ipPool *v1alpha1.IPPool) map[string]v1alpha1.IPAllocation { + return ipPool.Spec.Allocations + } + nodes, err := clientInfo.Client.CoreV1().Nodes().List(context.TODO(), metav1.ListOptions{}) + Expect(err).NotTo(HaveOccurred()) + Expect(nodes.Items).NotTo(BeEmpty()) + for _, node := range nodes.Items { + Expect( + clientInfo.WbClient.WhereaboutsV1alpha1().IPPools(ipPoolNamespace).Get( + context.TODO(), + wbstorage.IPPoolName(wbstorage.PoolIdentifier{IpRange: ipv4TestRange, NetworkName: testNetworkName, NodeName: node.Name}), + metav1.GetOptions{})).To( + WithTransform(poolAllocations, BeEmpty()), + "cannot have leaked IPAllocations in the system") + } + }) + + It("IPPools feature allocations", func() { + nodes, err := clientInfo.Client.CoreV1().Nodes().List(context.TODO(), metav1.ListOptions{}) + Expect(err).NotTo(HaveOccurred()) + Expect(nodes.Items).NotTo(BeEmpty()) + ipPools := []storage.IPPool{} + podList, err := clientInfo.Client.CoreV1().Pods(testNamespace).List(context.TODO(), metav1.ListOptions{}) + Expect(err).NotTo(HaveOccurred()) + Expect(podList.Items).NotTo(BeEmpty()) + for _, node := range nodes.Items { + nodeSliceRange, err := wbstorage.GetNodeSlicePoolRange(context.TODO(), k8sIPAM, node.Name) + Expect(err).NotTo(HaveOccurred()) + ipPool, err := k8sIPAM.GetIPPool(context.Background(), wbstorage.PoolIdentifier{IpRange: nodeSliceRange, NetworkName: testNetworkName, NodeName: node.Name}) + if err == nil { + ipPools = append(ipPools, ipPool) + } + } + Expect(poolconsistency.NewNodeSliceConsistencyCheck(ipPools, podList.Items).MissingIPs()).To(BeEmpty()) + totalAllocations := 0 + for _, node := range nodes.Items { + nodeSliceRange, err := wbstorage.GetNodeSlicePoolRange(context.TODO(), k8sIPAM, node.Name) + Expect(err).NotTo(HaveOccurred()) + ipPool, err := clientInfo.WbClient.WhereaboutsV1alpha1().IPPools(ipPoolNamespace).Get(context.TODO(), + wbstorage.IPPoolName(wbstorage.PoolIdentifier{IpRange: nodeSliceRange, NetworkName: testNetworkName, NodeName: node.Name}), + metav1.GetOptions{}) + // error is okay because pod may not land on every node + if err == nil { + totalAllocations = totalAllocations + len(ipPool.Spec.Allocations) + } + } + + Expect(totalAllocations).To(Equal(initialReplicaNumber)) + }) + + table.DescribeTable("stateful sets scale up / down", func(testSetup func(int), instanceDelta int) { + const scaleTimeout = util.CreatePodTimeout * 6 + + testSetup(instanceDelta) + + Eventually(func() (int, error) { + totalAllocations := 0 + nodes, err := clientInfo.Client.CoreV1().Nodes().List(context.TODO(), metav1.ListOptions{}) + Expect(err).NotTo(HaveOccurred()) + Expect(nodes.Items).NotTo(BeEmpty()) + for _, node := range nodes.Items { + nodeSliceRange, err := wbstorage.GetNodeSlicePoolRange(context.TODO(), k8sIPAM, node.Name) + Expect(err).NotTo(HaveOccurred()) + ipPool, err := clientInfo.WbClient.WhereaboutsV1alpha1().IPPools(ipPoolNamespace).Get(context.TODO(), + wbstorage.IPPoolName(wbstorage.PoolIdentifier{IpRange: nodeSliceRange, NetworkName: testNetworkName, NodeName: node.Name}), + metav1.GetOptions{}) + // error is okay because pod may not land on every node + if err == nil { + totalAllocations = totalAllocations + len(ipPool.Spec.Allocations) + } + } + + return totalAllocations, nil + }, scaleTimeout).Should( + Equal(initialReplicaNumber), "we should have one allocation for each live pod") + }, + table.Entry("scale up then down 5 replicas", func(deltaInstances int) { + Expect(clientInfo.ScaleStatefulSet(serviceName, namespace, deltaInstances)).To(Succeed()) + Expect(clientInfo.ScaleStatefulSet(serviceName, namespace, -deltaInstances)).To(Succeed()) + }, 5), + table.Entry("scale up then down 10 replicas", func(deltaInstances int) { + Expect(clientInfo.ScaleStatefulSet(serviceName, namespace, deltaInstances)).To(Succeed()) + Expect(clientInfo.ScaleStatefulSet(serviceName, namespace, -deltaInstances)).To(Succeed()) + }, 10), + table.Entry("scale up then down 20 replicas", func(deltaInstances int) { + Expect(clientInfo.ScaleStatefulSet(serviceName, namespace, deltaInstances)).To(Succeed()) + Expect(clientInfo.ScaleStatefulSet(serviceName, namespace, -deltaInstances)).To(Succeed()) + }, 20), + table.Entry("scale down then up 5 replicas", func(deltaInstances int) { + Expect(clientInfo.ScaleStatefulSet(serviceName, namespace, -deltaInstances)).To(Succeed()) + Expect(clientInfo.ScaleStatefulSet(serviceName, namespace, deltaInstances)).To(Succeed()) + }, 5), + table.Entry("scale down then up 10 replicas", func(deltaInstances int) { + Expect(clientInfo.ScaleStatefulSet(serviceName, namespace, -deltaInstances)).To(Succeed()) + Expect(clientInfo.ScaleStatefulSet(serviceName, namespace, deltaInstances)).To(Succeed()) + }, 10), + table.Entry("scale down then up 20 replicas", func(deltaInstances int) { + Expect(clientInfo.ScaleStatefulSet(serviceName, namespace, -deltaInstances)).To(Succeed()) + Expect(clientInfo.ScaleStatefulSet(serviceName, namespace, deltaInstances)).To(Succeed()) + }, 20), + ) + }) + }) + }) +}) diff --git a/e2e/e2e_test.go b/e2e/e2e_test.go index 9a0b2274d..759e8641b 100644 --- a/e2e/e2e_test.go +++ b/e2e/e2e_test.go @@ -3,8 +3,7 @@ package whereabouts_e2e import ( "context" "fmt" - "net" - "os" + "github.com/k8snetworkplumbingwg/whereabouts/e2e/util" "strings" "testing" "time" @@ -13,13 +12,11 @@ import ( "github.com/onsi/ginkgo/extensions/table" . "github.com/onsi/gomega" + nettypes "github.com/k8snetworkplumbingwg/network-attachment-definition-client/pkg/apis/k8s.cni.cncf.io/v1" v1 "k8s.io/api/apps/v1" core "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/client-go/rest" - "k8s.io/client-go/tools/clientcmd" - - nettypes "github.com/k8snetworkplumbingwg/network-attachment-definition-client/pkg/apis/k8s.cni.cncf.io/v1" wbtestclient "github.com/k8snetworkplumbingwg/whereabouts/e2e/client" "github.com/k8snetworkplumbingwg/whereabouts/e2e/entities" @@ -31,10 +28,6 @@ import ( "github.com/k8snetworkplumbingwg/whereabouts/pkg/types" ) -const ( - createPodTimeout = 10 * time.Second -) - func TestWhereaboutsE2E(t *testing.T) { RegisterFailHandler(Fail) RunSpecs(t, "whereabouts-e2e") @@ -68,13 +61,13 @@ var _ = Describe("Whereabouts functionality", func() { testConfig, err = testenv.NewConfig() Expect(err).NotTo(HaveOccurred()) - config, err = clusterConfig() + config, err = util.ClusterConfig() Expect(err).NotTo(HaveOccurred()) clientInfo, err = wbtestclient.NewClientInfo(config) Expect(err).NotTo(HaveOccurred()) - netAttachDef = macvlanNetworkWithWhereaboutsIPAMNetwork(testNetworkName, testNamespace, ipv4TestRange, []string{}, wbstorage.UnnamedNetwork, true) + netAttachDef = util.MacvlanNetworkWithWhereaboutsIPAMNetwork(testNetworkName, testNamespace, ipv4TestRange, []string{}, wbstorage.UnnamedNetwork, true) By("creating a NetworkAttachmentDefinition for whereabouts") _, err = clientInfo.AddNetAttachDef(netAttachDef) @@ -94,7 +87,7 @@ var _ = Describe("Whereabouts functionality", func() { pod, err = clientInfo.ProvisionPod( singlePodName, testNamespace, - podTierLabel(singlePodName), + util.PodTierLabel(singlePodName), entities.PodNetworkSelectionElements(testNetworkName), ) Expect(err).NotTo(HaveOccurred()) @@ -110,7 +103,7 @@ var _ = Describe("Whereabouts functionality", func() { secondaryIfaceIPs, err := retrievers.SecondaryIfaceIPValue(pod) Expect(err).NotTo(HaveOccurred()) Expect(secondaryIfaceIPs).NotTo(BeEmpty()) - Expect(inRange(ipv4TestRange, secondaryIfaceIPs[0])).To(Succeed()) + Expect(util.InRange(ipv4TestRange, secondaryIfaceIPs[0])).To(Succeed()) }) }) @@ -131,7 +124,7 @@ var _ = Describe("Whereabouts functionality", func() { const dualstackPodName = "whereabouts-dualstack-test" var err error - netAttachDefDualStack = macvlanNetworkWithWhereaboutsIPAMNetwork( + netAttachDefDualStack = util.MacvlanNetworkWithWhereaboutsIPAMNetwork( testDualStackNetworkName, testNamespace, "", @@ -145,7 +138,7 @@ var _ = Describe("Whereabouts functionality", func() { pod, err = clientInfo.ProvisionPod( dualstackPodName, testNamespace, - podTierLabel(dualstackPodName), + util.PodTierLabel(dualstackPodName), entities.PodNetworkSelectionElements(testDualStackNetworkName), ) Expect(err).NotTo(HaveOccurred()) @@ -163,8 +156,8 @@ var _ = Describe("Whereabouts functionality", func() { secondaryIfaceIPs, err := retrievers.SecondaryIfaceIPValue(pod) Expect(err).NotTo(HaveOccurred()) Expect(secondaryIfaceIPs).To(HaveLen(2)) - Expect(inRange(dualStackIPv4Range, secondaryIfaceIPs[0])).To(Succeed()) - Expect(inRange(dualStackIPv6Range, secondaryIfaceIPs[1])).To(Succeed()) + Expect(util.InRange(dualStackIPv4Range, secondaryIfaceIPs[0])).To(Succeed()) + Expect(util.InRange(dualStackIPv6Range, secondaryIfaceIPs[1])).To(Succeed()) }) }) @@ -173,7 +166,7 @@ var _ = Describe("Whereabouts functionality", func() { const dualstackPodName = "whereabouts-dualstack-test" var err error - netAttachDefDualStack = macvlanNetworkWithWhereaboutsIPAMNetwork( + netAttachDefDualStack = util.MacvlanNetworkWithWhereaboutsIPAMNetwork( testDualStackNetworkName, testNamespace, ipv4TestRange, @@ -187,7 +180,7 @@ var _ = Describe("Whereabouts functionality", func() { pod, err = clientInfo.ProvisionPod( dualstackPodName, testNamespace, - podTierLabel(dualstackPodName), + util.PodTierLabel(dualstackPodName), entities.PodNetworkSelectionElements(testDualStackNetworkName), ) Expect(err).NotTo(HaveOccurred()) @@ -205,9 +198,9 @@ var _ = Describe("Whereabouts functionality", func() { secondaryIfaceIPs, err := retrievers.SecondaryIfaceIPValue(pod) Expect(err).NotTo(HaveOccurred()) Expect(secondaryIfaceIPs).To(HaveLen(3)) - Expect(inRange(ipv4TestRange, secondaryIfaceIPs[0])).To(Succeed()) - Expect(inRange(dualStackIPv4Range, secondaryIfaceIPs[1])).To(Succeed()) - Expect(inRange(dualStackIPv6Range, secondaryIfaceIPs[2])).To(Succeed()) + Expect(util.InRange(ipv4TestRange, secondaryIfaceIPs[0])).To(Succeed()) + Expect(util.InRange(dualStackIPv4Range, secondaryIfaceIPs[1])).To(Succeed()) + Expect(util.InRange(dualStackIPv6Range, secondaryIfaceIPs[2])).To(Succeed()) }) }) }) @@ -237,7 +230,7 @@ var _ = Describe("Whereabouts functionality", func() { rsName, testNamespace, emptyReplicaSet, - podTierLabel(rsName), + util.PodTierLabel(rsName), entities.PodNetworkSelectionElements(testNetworkName), ) Expect(err).NotTo(HaveOccurred()) @@ -246,8 +239,8 @@ var _ = Describe("Whereabouts functionality", func() { AfterEach(func() { By("removing replicas and expecting 0 IP pool allocations") Expect( - checkZeroIPPoolAllocationsAndReplicas( - ctx, clientInfo, k8sIPAM, rsName, testNamespace, ipPoolCIDR, testNetworkName)).To(Succeed()) + util.CheckZeroIPPoolAllocationsAndReplicas( + clientInfo, k8sIPAM, rsName, testNamespace, ipPoolCIDR, testNetworkName)).To(Succeed()) By("deleting replicaset with whereabouts net-attach-def") Expect(clientInfo.DeleteReplicaSet(replicaSet)).To(Succeed()) @@ -257,8 +250,8 @@ var _ = Describe("Whereabouts functionality", func() { By("creating max number of pods and checking IP Pool validity") for i := 0; i < testConfig.NumberOfIterations; i++ { Expect( - checkZeroIPPoolAllocationsAndReplicas( - ctx, clientInfo, k8sIPAM, rsName, testNamespace, ipPoolCIDR, testNetworkName)).To(Succeed()) + util.CheckZeroIPPoolAllocationsAndReplicas( + clientInfo, k8sIPAM, rsName, testNamespace, ipPoolCIDR, testNetworkName)).To(Succeed()) allPods, err := clientInfo.Client.CoreV1().Pods(core.NamespaceAll).List(ctx, metav1.ListOptions{}) Expect(err).NotTo(HaveOccurred()) @@ -268,7 +261,7 @@ var _ = Describe("Whereabouts functionality", func() { testConfig.MaxReplicas(allPods.Items), rsName, testNamespace, - podTierLabel(rsName), + util.PodTierLabel(rsName), entities.PodNetworkSelectionElements(testNetworkName), )) Expect(err).NotTo(HaveOccurred()) @@ -345,7 +338,7 @@ var _ = Describe("Whereabouts functionality", func() { }) table.DescribeTable("stateful sets scale up / down", func(testSetup func(int), instanceDelta int) { - const scaleTimeout = createPodTimeout * 6 + const scaleTimeout = util.CreatePodTimeout * 6 testSetup(instanceDelta) @@ -403,7 +396,7 @@ var _ = Describe("Whereabouts functionality", func() { BeforeEach(func() { var err error tinyNetwork, err = clientInfo.AddNetAttachDef( - macvlanNetworkWithWhereaboutsIPAMNetwork(networkName, namespace, rangeWithTwoIPs, []string{}, wbstorage.UnnamedNetwork, true)) + util.MacvlanNetworkWithWhereaboutsIPAMNetwork(networkName, namespace, rangeWithTwoIPs, []string{}, wbstorage.UnnamedNetwork, true)) Expect(err).NotTo(HaveOccurred()) _, err = clientInfo.ProvisionStatefulSet(statefulSetName, namespace, serviceName, replicaNumber, networkName) @@ -465,7 +458,7 @@ var _ = Describe("Whereabouts functionality", func() { time.Second, wbtestclient.IsStatefulSetDegradedPredicate)).Should(Succeed()) - scaleUpTimeout := 2 * createPodTimeout + scaleUpTimeout := 2 * util.CreatePodTimeout Expect(wbtestclient.WaitForStatefulSetCondition( ctx, clientInfo.Client, @@ -484,7 +477,7 @@ var _ = Describe("Whereabouts functionality", func() { Expect(err).NotTo(HaveOccurred()) Expect(ipPool.Spec.Allocations).NotTo(BeEmpty()) - Expect(allocationForPodRef(podRef, *ipPool).ContainerID).NotTo(Equal(containerID)) + Expect(util.AllocationForPodRef(podRef, *ipPool).ContainerID).NotTo(Equal(containerID)) }) }) }) @@ -503,7 +496,7 @@ var _ = Describe("Whereabouts functionality", func() { When(fmt.Sprintf("a second net-attach-definition with \"enable_overlapping_ranges\": %t is created", enableOverlappingRanges), func() { BeforeEach(func() { - netAttachDef2 = macvlanNetworkWithWhereaboutsIPAMNetwork(testNetwork2Name, testNamespace, + netAttachDef2 = util.MacvlanNetworkWithWhereaboutsIPAMNetwork(testNetwork2Name, testNamespace, ipv4TestRangeOverlapping, []string{}, "", false) By("creating a second NetworkAttachmentDefinition for whereabouts") @@ -526,7 +519,7 @@ var _ = Describe("Whereabouts functionality", func() { pod, err = clientInfo.ProvisionPod( singlePodName, testNamespace, - podTierLabel(singlePodName), + util.PodTierLabel(singlePodName), entities.PodNetworkSelectionElements(testNetworkName), ) Expect(err).NotTo(HaveOccurred()) @@ -535,7 +528,7 @@ var _ = Describe("Whereabouts functionality", func() { pod2, err = clientInfo.ProvisionPod( singlePod2Name, testNamespace, - podTierLabel(singlePodName), + util.PodTierLabel(singlePodName), entities.PodNetworkSelectionElements(testNetwork2Name), ) Expect(err).NotTo(HaveOccurred()) @@ -590,9 +583,9 @@ var _ = Describe("Whereabouts functionality", func() { err error ) - netAttachDef2 = macvlanNetworkWithWhereaboutsIPAMNetwork(testNetwork2Name, testNamespace, + netAttachDef2 = util.MacvlanNetworkWithWhereaboutsIPAMNetwork(testNetwork2Name, testNamespace, ipv4TestRange, []string{}, namedNetworkName, true) - netAttachDef3 = macvlanNetworkWithWhereaboutsIPAMNetwork(testNetwork3Name, testNamespace, + netAttachDef3 = util.MacvlanNetworkWithWhereaboutsIPAMNetwork(testNetwork3Name, testNamespace, ipv4TestRangeOverlapping, []string{}, namedNetworkName, true) By("creating a second NetworkAttachmentDefinition for whereabouts") @@ -621,7 +614,7 @@ var _ = Describe("Whereabouts functionality", func() { pod, err = clientInfo.ProvisionPod( singlePodName, testNamespace, - podTierLabel(singlePodName), + util.PodTierLabel(singlePodName), entities.PodNetworkSelectionElements(testNetworkName), ) Expect(err).NotTo(HaveOccurred()) @@ -630,7 +623,7 @@ var _ = Describe("Whereabouts functionality", func() { pod2, err = clientInfo.ProvisionPod( singlePod2Name, testNamespace, - podTierLabel(singlePodName), + util.PodTierLabel(singlePodName), entities.PodNetworkSelectionElements(testNetwork2Name), ) Expect(err).NotTo(HaveOccurred()) @@ -639,7 +632,7 @@ var _ = Describe("Whereabouts functionality", func() { pod3, err = clientInfo.ProvisionPod( singlePod3Name, testNamespace, - podTierLabel(singlePodName), + util.PodTierLabel(singlePodName), entities.PodNetworkSelectionElements(testNetwork3Name), ) Expect(err).NotTo(HaveOccurred()) @@ -675,132 +668,3 @@ var _ = Describe("Whereabouts functionality", func() { }) }) }) - -func allocationForPodRef(podRef string, ipPool v1alpha1.IPPool) *v1alpha1.IPAllocation { - for _, allocation := range ipPool.Spec.Allocations { - if allocation.PodRef == podRef { - return &allocation - } - } - return nil -} - -func clusterConfig() (*rest.Config, error) { - const kubeconfig = "KUBECONFIG" - - kubeconfigPath, found := os.LookupEnv(kubeconfig) - if !found { - return nil, fmt.Errorf("must provide the path to the kubeconfig via the `KUBECONFIG` env variable") - } - - config, err := clientcmd.BuildConfigFromFlags("", kubeconfigPath) - if err != nil { - return nil, err - } - return config, nil -} - -func podTierLabel(podTier string) map[string]string { - const tier = "tier" - return map[string]string{tier: podTier} -} - -// Waits for all replicas to be fully removed from replicaset, and checks that there are 0 ip pool allocations -func checkZeroIPPoolAllocationsAndReplicas(ctx context.Context, clientInfo *wbtestclient.ClientInfo, k8sIPAM *wbstorage.KubernetesIPAM, rsName, namespace string, ipPoolCIDR string, networkNames ...string) error { - const ( - emptyReplicaSet = 0 - rsSteadyTimeout = 1200 * time.Second - zeroIPPoolTimeout = 2 * time.Minute - ) - var err error - - replicaSet, err := clientInfo.UpdateReplicaSet( - entities.ReplicaSetObject( - emptyReplicaSet, - rsName, - namespace, - podTierLabel(rsName), - entities.PodNetworkSelectionElements(networkNames...), - )) - if err != nil { - return err - } - - matchingLabel := entities.ReplicaSetQuery(rsName) - if err = wbtestclient.WaitForReplicaSetSteadyState(ctx, clientInfo.Client, namespace, matchingLabel, replicaSet, rsSteadyTimeout); err != nil { - return err - } - - if err = wbtestclient.WaitForZeroIPPoolAllocations(ctx, k8sIPAM, ipPoolCIDR, zeroIPPoolTimeout); err != nil { - return err - } - - return nil -} - -// Returns a network attachment definition object configured by provided parameters -func generateNetAttachDefSpec(name, namespace, config string) *nettypes.NetworkAttachmentDefinition { - return &nettypes.NetworkAttachmentDefinition{ - TypeMeta: metav1.TypeMeta{ - APIVersion: "v1", - Kind: "NetworkAttachmentDefinition", - }, - ObjectMeta: metav1.ObjectMeta{ - Name: name, - Namespace: namespace, - }, - Spec: nettypes.NetworkAttachmentDefinitionSpec{ - Config: config, - }, - } -} - -func macvlanNetworkWithWhereaboutsIPAMNetwork(networkName string, namespaceName string, ipRange string, ipRanges []string, poolName string, enableOverlappingRanges bool) *nettypes.NetworkAttachmentDefinition { - macvlanConfig := fmt.Sprintf(`{ - "cniVersion": "0.3.0", - "disableCheck": true, - "plugins": [ - { - "type": "macvlan", - "master": "eth0", - "mode": "bridge", - "ipam": { - "type": "whereabouts", - "leader_lease_duration": 1500, - "leader_renew_deadline": 1000, - "leader_retry_period": 500, - "range": "%s", - "ipRanges": %s, - "log_level": "debug", - "log_file": "/tmp/wb", - "network_name": "%s", - "enable_overlapping_ranges": %v - } - } - ] - }`, ipRange, createIPRanges(ipRanges), poolName, enableOverlappingRanges) - return generateNetAttachDefSpec(networkName, namespaceName, macvlanConfig) -} - -func inRange(cidr string, ip string) error { - _, cidrRange, err := net.ParseCIDR(cidr) - if err != nil { - return err - } - - if cidrRange.Contains(net.ParseIP(ip)) { - return nil - } - - return fmt.Errorf("ip [%s] is NOT in range %s", ip, cidr) -} - -func createIPRanges(ranges []string) string { - formattedRanges := []string{} - for _, ipRange := range ranges { - singleRange := fmt.Sprintf(`{"range": "%s"}`, ipRange) - formattedRanges = append(formattedRanges, singleRange) - } - ipRanges := "[" + strings.Join(formattedRanges[:], ",") + "]" - return ipRanges -} diff --git a/e2e/poolconsistency/node_slice_checker.go b/e2e/poolconsistency/node_slice_checker.go new file mode 100644 index 000000000..09db1e6cb --- /dev/null +++ b/e2e/poolconsistency/node_slice_checker.go @@ -0,0 +1,75 @@ +package poolconsistency + +import ( + corev1 "k8s.io/api/core/v1" + + "github.com/k8snetworkplumbingwg/whereabouts/e2e/retrievers" + "github.com/k8snetworkplumbingwg/whereabouts/pkg/storage" +) + +type NodeSliceChecker struct { + ipPools []storage.IPPool + podList []corev1.Pod +} + +func NewNodeSliceConsistencyCheck(ipPools []storage.IPPool, podList []corev1.Pod) *NodeSliceChecker { + return &NodeSliceChecker{ + ipPools: ipPools, + podList: podList, + } +} + +func (pc *NodeSliceChecker) MissingIPs() []string { + var mismatchedIPs []string + for _, pod := range pc.podList { + podIPs, err := retrievers.SecondaryIfaceIPValue(&pod) + podIP := podIPs[len(podIPs)-1] + if err != nil { + return []string{} + } + + var found bool + for _, pool := range pc.ipPools { + for _, allocation := range pool.Allocations() { + reservedIP := allocation.IP.String() + + if reservedIP == podIP { + found = true + break + } + } + } + if !found { + mismatchedIPs = append(mismatchedIPs, podIP) + } + } + return mismatchedIPs +} + +func (pc *NodeSliceChecker) StaleIPs() []string { + var staleIPs []string + for _, pool := range pc.ipPools { + for _, allocation := range pool.Allocations() { + reservedIP := allocation.IP.String() + found := false + for _, pod := range pc.podList { + podIPs, err := retrievers.SecondaryIfaceIPValue(&pod) + podIP := podIPs[len(podIPs)-1] + if err != nil { + continue + } + + if reservedIP == podIP { + found = true + break + } + } + + if !found { + staleIPs = append(staleIPs, allocation.IP.String()) + } + } + } + + return staleIPs +} diff --git a/e2e/util/util.go b/e2e/util/util.go new file mode 100644 index 000000000..42b3f7f52 --- /dev/null +++ b/e2e/util/util.go @@ -0,0 +1,232 @@ +package util + +import ( + "context" + "fmt" + nettypes "github.com/k8snetworkplumbingwg/network-attachment-definition-client/pkg/apis/k8s.cni.cncf.io/v1" + wbtestclient "github.com/k8snetworkplumbingwg/whereabouts/e2e/client" + "github.com/k8snetworkplumbingwg/whereabouts/e2e/entities" + "github.com/k8snetworkplumbingwg/whereabouts/pkg/api/whereabouts.cni.cncf.io/v1alpha1" + wbstorage "github.com/k8snetworkplumbingwg/whereabouts/pkg/storage/kubernetes" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/rest" + "k8s.io/client-go/tools/clientcmd" + "net" + "os" + "strings" + "time" +) + +const ( + CreatePodTimeout = 10 * time.Second +) + +func AllocationForPodRef(podRef string, ipPool v1alpha1.IPPool) *v1alpha1.IPAllocation { + for _, allocation := range ipPool.Spec.Allocations { + if allocation.PodRef == podRef { + return &allocation + } + } + return nil +} + +func ClusterConfig() (*rest.Config, error) { + const kubeconfig = "KUBECONFIG" + + kubeconfigPath, found := os.LookupEnv(kubeconfig) + if !found { + return nil, fmt.Errorf("must provide the path to the kubeconfig via the `KUBECONFIG` env variable") + } + + config, err := clientcmd.BuildConfigFromFlags("", kubeconfigPath) + if err != nil { + return nil, err + } + return config, nil +} + +func PodTierLabel(podTier string) map[string]string { + const tier = "tier" + return map[string]string{tier: podTier} +} + +// This will check that the count of subnets has been created and that each node has a unique allocation +// NOTE: this requires that there are not more nodes than subnets in the nodeslicepool +func ValidateNodeSlicePoolSlicesCreatedAndNodesAssigned(nodesliceName string, nodeSliceNamespace string, expectedSubnets int, clientInfo *wbtestclient.ClientInfo) error { + nodeSlice, err := clientInfo.GetNodeSlicePool(nodesliceName, nodeSliceNamespace) + if err != nil { + return err + } + // Should create subnets + if len(nodeSlice.Status.Allocations) != expectedSubnets { + return fmt.Errorf("expected allocations %v but got allocations %v", expectedSubnets, len(nodeSlice.Status.Allocations)) + } + // Each subnet should have a unique range + allocationMap := map[string]struct{}{} + nodeMap := map[string]struct{}{} + for _, allocation := range nodeSlice.Status.Allocations { + if _, ok := allocationMap[allocation.SliceRange]; ok { + return fmt.Errorf("error allocation has duplication in subnet %v", allocation.SliceRange) + } + if _, ok := allocationMap[allocation.NodeName]; allocation.NodeName != "" && ok { + return fmt.Errorf("error allocation has duplication in nodes %v", allocation.NodeName) + } + allocationMap[allocation.SliceRange] = struct{}{} + nodeMap[allocation.NodeName] = struct{}{} + } + // All nodes should be assigned exactly one time + nodes, err := clientInfo.Client.CoreV1().Nodes().List(context.TODO(), metav1.ListOptions{}) + if err != nil { + return err + } + for _, node := range nodes.Items { + if _, ok := nodeMap[node.Name]; !ok { + //TODO: CP nodes? + return fmt.Errorf("node not assinged to slice %v", node.Name) + } + } + return nil +} + +// Waits for all replicas to be fully removed from replicaset, and checks that there are 0 ip pool allocations +func CheckZeroIPPoolAllocationsAndReplicas(clientInfo *wbtestclient.ClientInfo, k8sIPAM *wbstorage.KubernetesIPAM, rsName, namespace string, ipPoolCIDR string, networkNames ...string) error { + const ( + emptyReplicaSet = 0 + rsSteadyTimeout = 1200 * time.Second + zeroIPPoolTimeout = 2 * time.Minute + ) + var err error + + replicaSet, err := clientInfo.UpdateReplicaSet( + entities.ReplicaSetObject( + emptyReplicaSet, + rsName, + namespace, + PodTierLabel(rsName), + entities.PodNetworkSelectionElements(networkNames...), + )) + if err != nil { + return err + } + + matchingLabel := entities.ReplicaSetQuery(rsName) + if err = wbtestclient.WaitForReplicaSetSteadyState(clientInfo.Client, namespace, matchingLabel, replicaSet, rsSteadyTimeout); err != nil { + return err + } + + if k8sIPAM.Config.NodeSliceSize == "" { + if err = wbtestclient.WaitForZeroIPPoolAllocations(k8sIPAM, ipPoolCIDR, zeroIPPoolTimeout); err != nil { + return err + } + } else { + if err = wbtestclient.WaitForZeroIPPoolAllocationsAcrossNodeSlices(k8sIPAM, ipPoolCIDR, zeroIPPoolTimeout, clientInfo); err != nil { + return err + } + } + + return nil +} + +// Returns a network attachment definition object configured by provided parameters +func GenerateNetAttachDefSpec(name, namespace, config string) *nettypes.NetworkAttachmentDefinition { + return &nettypes.NetworkAttachmentDefinition{ + TypeMeta: metav1.TypeMeta{ + APIVersion: "v1", + Kind: "NetworkAttachmentDefinition", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: namespace, + }, + Spec: nettypes.NetworkAttachmentDefinitionSpec{ + Config: config, + }, + } +} + +func MacvlanNetworkWithWhereaboutsIPAMNetwork(networkName string, namespaceName string, ipRange string, ipRanges []string, poolName string, enableOverlappingRanges bool) *nettypes.NetworkAttachmentDefinition { + macvlanConfig := fmt.Sprintf(`{ + "cniVersion": "0.3.0", + "disableCheck": true, + "plugins": [ + { + "type": "macvlan", + "master": "eth0", + "mode": "bridge", + "ipam": { + "type": "whereabouts", + "leader_lease_duration": 1500, + "leader_renew_deadline": 1000, + "leader_retry_period": 500, + "range": "%s", + "ipRanges": %s, + "log_level": "debug", + "log_file": "/tmp/wb", + "network_name": "%s", + "enable_overlapping_ranges": %v + } + } + ] + }`, ipRange, CreateIPRanges(ipRanges), poolName, enableOverlappingRanges) + return GenerateNetAttachDefSpec(networkName, namespaceName, macvlanConfig) +} + +func MacvlanNetworkWithNodeSlice(networkName, namespaceName, ipRange, poolName, sliceSize string) *nettypes.NetworkAttachmentDefinition { + //TODO: fails without leader timeouts set + macvlanConfig := fmt.Sprintf(`{ + "cniVersion": "0.3.0", + "disableCheck": true, + "plugins": [ + { + "type": "macvlan", + "master": "eth0", + "mode": "bridge", + "ipam": { + "type": "whereabouts", + "leader_lease_duration": 1500, + "leader_renew_deadline": 1000, + "leader_retry_period": 500, + "namespace": "%s", + "range": "%s", + "log_level": "debug", + "log_file": "/tmp/wb", + "network_name": "%s", + "node_slice_size": "%s" + } + } + ] + }`, namespaceName, ipRange, poolName, sliceSize) + return GenerateNetAttachDefSpec(networkName, namespaceName, macvlanConfig) +} + +func InNodeRange(clientInfo *wbtestclient.ClientInfo, nodeName, sliceName, namespace, ip string) error { + cidrRange, err := wbtestclient.GetNodeSubnet(clientInfo, nodeName, sliceName, namespace) + if err != nil { + return err + } + + return InRange(cidrRange, ip) +} + +func InRange(cidr string, ip string) error { + _, cidrRange, err := net.ParseCIDR(cidr) + if err != nil { + return err + } + + if cidrRange.Contains(net.ParseIP(ip)) { + return nil + } + + return fmt.Errorf("ip [%s] is NOT in range %s", ip, cidr) +} + +func CreateIPRanges(ranges []string) string { + formattedRanges := []string{} + for _, ipRange := range ranges { + singleRange := fmt.Sprintf(`{"range": "%s"}`, ipRange) + formattedRanges = append(formattedRanges, singleRange) + } + ipRanges := "[" + strings.Join(formattedRanges[:], ",") + "]" + return ipRanges +} diff --git a/hack/build-go.sh b/hack/build-go.sh index 0d615169e..f8b9f78e1 100755 --- a/hack/build-go.sh +++ b/hack/build-go.sh @@ -46,3 +46,5 @@ GLDFLAGS="${GLDFLAGS} ${VERSION_LDFLAGS}" CGO_ENABLED=0 GOOS=${GOOS} GOARCH=${GOARCH} ${GO} build ${GOFLAGS} -ldflags "${GLDFLAGS}" -o bin/${cmd} cmd/${cmd}.go CGO_ENABLED=0 GOOS=${GOOS} GOARCH=${GOARCH} ${GO} build ${GOFLAGS} -ldflags "${GLDFLAGS}" -o bin/ip-control-loop cmd/controlloop/*.go +CGO_ENABLED=0 GOOS=${GOOS} GOARCH=${GOARCH} ${GO} build ${GOFLAGS} -ldflags "${GLDFLAGS}" -o bin/node-slice-controller cmd/nodeslicecontroller/*.go + diff --git a/hack/cni-install.yml b/hack/cni-install.yml index 1d57fd4d4..56063cf6e 100644 --- a/hack/cni-install.yml +++ b/hack/cni-install.yml @@ -7,9 +7,9 @@ metadata: data: install_cni.sh: | cd /tmp - wget https://github.com/containernetworking/plugins/releases/download/v1.1.1/cni-plugins-linux-amd64-v1.1.1.tgz + wget https://github.com/containernetworking/plugins/releases/download/v1.1.1/cni-plugins-linux-arm64-v1.1.1.tgz cd /host/opt/cni/bin - tar xvfzp /tmp/cni-plugins-linux-amd64-v1.1.1.tgz + tar xvfzp /tmp/cni-plugins-linux-arm64-v1.1.1.tgz sleep infinite --- apiVersion: apps/v1 @@ -30,7 +30,7 @@ spec: spec: hostNetwork: true nodeSelector: - kubernetes.io/arch: amd64 + kubernetes.io/arch: arm64 tolerations: - operator: Exists effect: NoSchedule diff --git a/hack/e2e-setup-kind-cluster.sh b/hack/e2e-setup-kind-cluster.sh index db0fbedc9..875ba95f5 100755 --- a/hack/e2e-setup-kind-cluster.sh +++ b/hack/e2e-setup-kind-cluster.sh @@ -98,10 +98,10 @@ trap "rm /tmp/whereabouts-img.tar || true" EXIT kind load image-archive --name "$KIND_CLUSTER_NAME" /tmp/whereabouts-img.tar echo "## install whereabouts" -for file in "daemonset-install.yaml" "whereabouts.cni.cncf.io_ippools.yaml" "whereabouts.cni.cncf.io_overlappingrangeipreservations.yaml"; do +for file in "daemonset-install.yaml" "whereabouts.cni.cncf.io_ippools.yaml" "whereabouts.cni.cncf.io_overlappingrangeipreservations.yaml" "node-slice-controller.yaml"; do # insert 'imagePullPolicy: Never' under the container 'image' so it is certain that the image used # by the daemonset is the one loaded into KinD and not one pulled from a repo - sed '/ image:/a\ imagePullPolicy: Never' "$ROOT/doc/crds/$file" | retry kubectl apply -f - + sed '/ image:/a\ imagePullPolicy: Never' "./doc/crds/$file" | kubectl apply -f - done retry kubectl wait -n kube-system --for=condition=ready -l app=whereabouts pod --timeout=$TIMEOUT_K8 echo "## done" diff --git a/kubeconfig.yaml b/kubeconfig.yaml new file mode 100644 index 000000000..384247e50 --- /dev/null +++ b/kubeconfig.yaml @@ -0,0 +1,19 @@ +apiVersion: v1 +clusters: +- cluster: + certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURCVENDQWUyZ0F3SUJBZ0lJZEVXaHJjZVdjeGN3RFFZSktvWklodmNOQVFFTEJRQXdGVEVUTUJFR0ExVUUKQXhNS2EzVmlaWEp1WlhSbGN6QWVGdzB5TkRBMU1UTXhPRFUwTkRKYUZ3MHpOREExTVRFeE9EVTVOREphTUJVeApFekFSQmdOVkJBTVRDbXQxWW1WeWJtVjBaWE13Z2dFaU1BMEdDU3FHU0liM0RRRUJBUVVBQTRJQkR3QXdnZ0VLCkFvSUJBUUN2SGNQZkNZdHdJamZULy9hSjEyYWhEMUF1Q3lmODBFZDRkbWRJSmJjbEJvdUpvN1ZWbDgxUkRwOW4KUkdPRm5XdHRtbDJZNkZCenhRdksxdm40NXFFR1NPZEFJdVp5aThtWS9mblVMdUlsOEVxNWdzYVhWWDN2VjBUdQpUVHA1NlJ2QUV0dk9JK09LSTAzM2lCZ2lieW1ZN0pLSXVWalpnY3BTTGZHamthYURBK1JaV3JXbCtTaC8vTUpaClAwSHNsZGx2ZWRiN1pWMU5PQk0yVUhwcWVGZ09VTy9kWDl4QmdPS0RXd0k4NnhJMC9TVTNZNSs1WjRCTVM0NTEKNll6SlQ0NWQxcVk0QnkyVkYrUEFOdm1RMm5SVUIybGFLYkhMUmt4YjZhNEtrV1c3akp0V0hjVGJ4dE9SUlJZbApGeTZabFk1akpLdStRTjM2RU9WaC9qeUtQUWEzQWdNQkFBR2pXVEJYTUE0R0ExVWREd0VCL3dRRUF3SUNwREFQCkJnTlZIUk1CQWY4RUJUQURBUUgvTUIwR0ExVWREZ1FXQkJRVVpyVzg4MWV1VmtyVlc0Z0hYUHowSlVnNmFEQVYKQmdOVkhSRUVEakFNZ2dwcmRXSmxjbTVsZEdWek1BMEdDU3FHU0liM0RRRUJDd1VBQTRJQkFRQ0NJbDUwb1hPUQpsaE5Yc0JyTFJrL3ptejhQYkR0RnFYVDlMeUsyODdpUHpQUWpvZFVOZFIvMVpkcWNscDlnUGZsa1hRbG8yWTMyCjlrci9jdFBrcHYzVWxMelNJaE9POXB0UExGVGdKUnRBL3krR2JzeUtmUkd3bXlISUVJYjgvUzRxd1NVd2F3SWsKYnM3Z3phMm43VU54YUZmQ2dLZUtUVkFwdjlVMEZCSnhjU3B4STZoZWxIVURJNExFQU5wSENZOEFyUXJRMGV5RQpuSzJWUUMwdXpiSmNiK2V0U3JiQmtpeWFSamlCc2hTNWd6Sm1BbFA0MnozdHMyQXh3NENYSTdiK0VUWXA0T2ZIClQvVkRoRUl0dWNuT1VPRUM0aVc3MFhkT3VtcnpyK21ISGhrTTIyeVRlOVNnZENDczF3OHpTQ1dzbnJOeXdvWkIKeE9JaDVteGs3dHhnCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + server: https://127.0.0.1:54174 + name: kind-kind +contexts: +- context: + cluster: kind-kind + user: kind-kind + name: kind-kind +current-context: kind-kind +kind: Config +preferences: {} +users: +- name: kind-kind + user: + client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURLVENDQWhHZ0F3SUJBZ0lJYmJXaVJZRmhpVGN3RFFZSktvWklodmNOQVFFTEJRQXdGVEVUTUJFR0ExVUUKQXhNS2EzVmlaWEp1WlhSbGN6QWVGdzB5TkRBMU1UTXhPRFUwTkRKYUZ3MHlOVEExTVRNeE9EVTVOREphTUR3eApIekFkQmdOVkJBb1RGbXQxWW1WaFpHMDZZMngxYzNSbGNpMWhaRzFwYm5NeEdUQVhCZ05WQkFNVEVHdDFZbVZ5CmJtVjBaWE10WVdSdGFXNHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCRHdBd2dnRUtBb0lCQVFDd2VhZlAKS3hIdlpsS09UNGIvcll3bFVOZmp5WG52WEZWb1BVb1ZGaElWMHlYUGxUSGFBbmNmMmFGeWlVSjF2b1RaTWo2TgpYVTlYTGxxaTVMdWVpcEZ2dE9SeTVLMm9MbUROYlV3WDI5N0p3dXRQdnExbDFJUTAwb2ZvOWpyYVp3U0RBRzIvClpyQllRMzR3NVdEUjRIeXI4dWQ2cVY3N3IzUEFnSEZNVENkK0FxWmRvbFZ1bzhjRGZkRFhlTWdBdHIxSUpVTlQKN0lHb2d6ajNZT1Y5VG8zZHZZbzU0cHE2MmpiTzU0aGh1Q3R0Q1c3WjVnZklQUk1DVERYTk5Rb3lxMWlQOXdtaQpMaDZyK1A2TGRVdnRaZTVmR21NTHE3MnliSWsxeFphSWJ2VlVqOFdKUjN6OUNXa3F4V09qSWhLaFN4T2MvU2tMCi9vcGN1L1RuRmZ6WC85T1RBZ01CQUFHalZqQlVNQTRHQTFVZER3RUIvd1FFQXdJRm9EQVRCZ05WSFNVRUREQUsKQmdnckJnRUZCUWNEQWpBTUJnTlZIUk1CQWY4RUFqQUFNQjhHQTFVZEl3UVlNQmFBRkJSbXRienpWNjVXU3RWYgppQWRjL1BRbFNEcG9NQTBHQ1NxR1NJYjNEUUVCQ3dVQUE0SUJBUUJUZHQ0OUpITlFPcnF3bjZPeWpMTDUyTEhsClZ6d1Z1YmxQRGxrSC83aWc2TXBJNk1FREw1RjFYOUdHVG1wVVRIMUVCYm8xb2VvL2Z1VnVMMnVrajZONUhMdEwKQS9pOTNNSG0rbzF6Y3RMaTltby80TW9CMUhONU1POEF1STIrbkxxU2lOWVd4Vko0cVR0S2tDdEdpR3BOUE9Hcwp0U0xkeXEzUXh4aWNrZ1BuRFhOUGNiRHdxUmNOaVRYSGgrbmh5ZFYxQmJsR3pZdG1RVTV4cU1mV0NsMk9CdXZxCmNiYTVoMzExTWJFRnVMc2pDUS9pcVpMK1pTK3hIbEQ5SGxBNGtKVy92N3NFeWJGazRTTU5yYnBXUG1ZRzdOUXgKOHNySnBOMEtrZC9lUHlPT3k4M0hsZE11Q1YvYTRoN0hjOExTOFY3MjZyZEdPZmxNUDJvbnRQY3NlVkdDCi0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K + client-key-data: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFb2dJQkFBS0NBUUVBc0htbnp5c1I3MlpTamsrRy82Mk1KVkRYNDhsNTcxeFZhRDFLRlJZU0ZkTWx6NVV4CjJnSjNIOW1oY29sQ2RiNkUyVEkralYxUFZ5NWFvdVM3bm9xUmI3VGtjdVN0cUM1Z3pXMU1GOXZleWNMclQ3NnQKWmRTRU5OS0g2UFk2Mm1jRWd3QnR2MmF3V0VOK01PVmcwZUI4cS9MbmVxbGUrNjl6d0lCeFRFd25mZ0ttWGFKVgpicVBIQTMzUTEzaklBTGE5U0NWRFUreUJxSU00OTJEbGZVNk4zYjJLT2VLYXV0bzJ6dWVJWWJncmJRbHUyZVlICnlEMFRBa3cxelRVS01xdFlqL2NKb2k0ZXEvaitpM1ZMN1dYdVh4cGpDNnU5c215Sk5jV1dpRzcxVkkvRmlVZDgKL1FscEtzVmpveUlTb1VzVG5QMHBDLzZLWEx2MDV4WDgxLy9Ua3dJREFRQUJBb0lCQUVYdVQzTW16QnFqMzM4SgpRS084cjlaeHJMdFZNWDZLaGtXaVUrTDdOZnQwQ24yeHoybG1wTEg0V2FPN2hKeUgvTGpjMGpET2t3d25FRCtRCmlGQ1E5SVRobDgxM2xPRWFUNzNYMjlsd2hWNUtZVmplWkhQL3ZNdjV5V1dsZlRqaXJjVUR2SG1tUmFjVVI4TTAKZ2lObzQ3NTNxUWJRYXhVdE41OUd4cDdIWnJibHlYV2FlK3IyZjc5NXI5RW8wWVgrWTNzS1pXanBDcGZWRUhqdgpYUFp5bExjak5ub3ZPM216aEVKVUhOdUdzZWJhbEkrM21GNmx1MkEzZUdDOFFXTko5dnk4YmlvWVd4aW0ybElHCjMvNloxdVZoREZhMGgvL0NNa3BxZXZvUUNyOUd3RzJkQUQzVGxBSE9jQTV1TUZtYWxFN0d2b1NXR25zV3N3dm4KZXV2UHdLRUNnWUVBMWgyTzJscEpJK1h5UG5wdUZoTlk5dVJEMXpaUElWYkdBcTQ3d1lyZWhjSHZ6bzlIQyt6OApPWDZjTS96ekpiZmRuSmtZb1dYYTZQb21Id0NPbzhNdTAxQ2o1MlU3VkxmNEtxaEVPRUJtcmJhTWtRWGVObEtHCjJaR1RDL21jclIxWDlEVFgrb2dGcnpheWprRGRjSUlRd21uaHVqV3FCamE4K1lkaG9hNXYvb2tDZ1lFQTB2OG4KckhpZTUwVkcwQVlYbFBvOXVUVFhkamQwN1FSY1kyN21xaGNTbkRzSWNzUWZMY3dCRUIrVEhzV3hlSGsyZ3p0MQpRTWtKNjF1eFhyelZFSUNHenh6ZVdrTlp4TUlWMEl3RkNJQ2p6S1Njak9KbjN2eEdiV21Zd0FVUDhWdWQ4ZEVQCllXTUVPSXpESllsbWFzMjNjeE9TaWQrSDdDeExENTJCaXRJVVdqc0NnWUJNbGxJTXhKSzQ1bjFaMzgwVTFHTFUKSFI0dkV0d0hIdFRCRExXUEt5OGhSUmVVR1NmZW1pdzJISldlK3ZHMklpaUE1VG9zTVJTMmxST2hyejlXVUhDbApZWWpmTWhTZzN4VkRuT0NhQmw4ejc4SWo5YWRnWXZDZFRqYjg1NUlsVWdPdDlHRDAya2ErUDZCcXhjVHZnM2FmCk0rUnNDTm9DVXY0UmUxMXV5Y2lCa1FLQmdES0c0NnRMbjFIbXB4Ujl3UHZ1Q1FYbS80blJzZkJvVU8rR3lUb0cKR0hETk9qS3hnSDNwRW9BWDc1VTQ1a3poU2dxWEhIY05MWkRzL2thZmxhNUQrUVJ6OTFOS09aOENrMUxEbFJqNgpKVCtHVSs3dzhNclhRczVFc1UyYWFMejFvWmNjNXovOUJDKytsYVRSaUhNZkhFVTBkSzBMbUhNWUVFbUhBRlNNCkJrK3RBb0dBUXpsTGJsQ1c2OWtXVmlIYlhaWHpvRUo3NHo3ZUJ4OWdNNjZ3NmRrRzZ4THVlWmRNODdCcEFwS3AKTFpmMk9PS3pQc0xQWGJpR2tTTUtOY0xVeGQvaWl2QjFGVHBxRE0vU3V3KzhmeTJlcnhxNUVZRlhkK2Nhc0NuNwpQSk1vbkFvcVF1QVNiOGxwbHZ2bWVxN0ZaV0dweU5sVGorWUZnRitlM0FtdHZpMG1ieVE9Ci0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tCg== diff --git a/pkg/api/whereabouts.cni.cncf.io/v1alpha1/nodeslicepool_types.go b/pkg/api/whereabouts.cni.cncf.io/v1alpha1/nodeslicepool_types.go new file mode 100644 index 000000000..03b75af24 --- /dev/null +++ b/pkg/api/whereabouts.cni.cncf.io/v1alpha1/nodeslicepool_types.go @@ -0,0 +1,52 @@ +package v1alpha1 + +import ( + "net" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// NodeSlicePoolSpec defines the desired state of NodeSlicePool +type NodeSlicePoolSpec struct { + // Range is a RFC 4632/4291-style string that represents an IP address and prefix length in CIDR notation + // this refers to the entire range where the node is allocated a subset + Range string `json:"range"` + + SliceSize string `json:"sliceSize"` +} + +// NodeSlicePoolStatus defines the desired state of NodeSlicePool +type NodeSlicePoolStatus struct { + Allocations []NodeSliceAllocation `json:"allocations"` +} + +type NodeSliceAllocation struct { + NodeName string `json:"nodeName"` + SliceRange string `json:"sliceRange"` +} + +// ParseCIDR formats the Range of the IPPool +func (i NodeSlicePool) ParseCIDR() (net.IP, *net.IPNet, error) { + return net.ParseCIDR(i.Spec.Range) +} + +// +genclient +// +kubebuilder:object:root=true + +// NodeSlicePool is the Schema for the nodesliceippools API +type NodeSlicePool struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec NodeSlicePoolSpec `json:"spec,omitempty"` + Status NodeSlicePoolStatus `json:"status,omitempty"` +} + +// +kubebuilder:object:root=true + +// NodeSlicePoolList contains a list of NodeSlicePool +type NodeSlicePoolList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []NodeSlicePool `json:"items"` +} diff --git a/pkg/api/whereabouts.cni.cncf.io/v1alpha1/register.go b/pkg/api/whereabouts.cni.cncf.io/v1alpha1/register.go index b3a1b6f27..1c96503bd 100644 --- a/pkg/api/whereabouts.cni.cncf.io/v1alpha1/register.go +++ b/pkg/api/whereabouts.cni.cncf.io/v1alpha1/register.go @@ -58,6 +58,8 @@ func addKnownTypes(scheme *runtime.Scheme) error { &IPPoolList{}, &OverlappingRangeIPReservation{}, &OverlappingRangeIPReservationList{}, + &NodeSlicePool{}, + &NodeSlicePoolList{}, ) metav1.AddToGroupVersion(scheme, SchemeGroupVersion) return nil diff --git a/pkg/api/whereabouts.cni.cncf.io/v1alpha1/zz_generated.deepcopy.go b/pkg/api/whereabouts.cni.cncf.io/v1alpha1/zz_generated.deepcopy.go index 18d1e4b1f..c23bbddc4 100644 --- a/pkg/api/whereabouts.cni.cncf.io/v1alpha1/zz_generated.deepcopy.go +++ b/pkg/api/whereabouts.cni.cncf.io/v1alpha1/zz_generated.deepcopy.go @@ -104,6 +104,115 @@ func (in *IPPoolSpec) DeepCopy() *IPPoolSpec { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NodeSliceAllocation) DeepCopyInto(out *NodeSliceAllocation) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NodeSliceAllocation. +func (in *NodeSliceAllocation) DeepCopy() *NodeSliceAllocation { + if in == nil { + return nil + } + out := new(NodeSliceAllocation) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NodeSlicePool) DeepCopyInto(out *NodeSlicePool) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + out.Spec = in.Spec + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NodeSlicePool. +func (in *NodeSlicePool) DeepCopy() *NodeSlicePool { + if in == nil { + return nil + } + out := new(NodeSlicePool) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *NodeSlicePool) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NodeSlicePoolList) DeepCopyInto(out *NodeSlicePoolList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]NodeSlicePool, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NodeSlicePoolList. +func (in *NodeSlicePoolList) DeepCopy() *NodeSlicePoolList { + if in == nil { + return nil + } + out := new(NodeSlicePoolList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *NodeSlicePoolList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NodeSlicePoolSpec) DeepCopyInto(out *NodeSlicePoolSpec) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NodeSlicePoolSpec. +func (in *NodeSlicePoolSpec) DeepCopy() *NodeSlicePoolSpec { + if in == nil { + return nil + } + out := new(NodeSlicePoolSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NodeSlicePoolStatus) DeepCopyInto(out *NodeSlicePoolStatus) { + *out = *in + if in.Allocations != nil { + in, out := &in.Allocations, &out.Allocations + *out = make([]NodeSliceAllocation, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NodeSlicePoolStatus. +func (in *NodeSlicePoolStatus) DeepCopy() *NodeSlicePoolStatus { + if in == nil { + return nil + } + out := new(NodeSlicePoolStatus) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *OverlappingRangeIPReservation) DeepCopyInto(out *OverlappingRangeIPReservation) { *out = *in diff --git a/pkg/client/clientset/versioned/typed/whereabouts.cni.cncf.io/v1alpha1/fake/fake_nodeslicepool.go b/pkg/client/clientset/versioned/typed/whereabouts.cni.cncf.io/v1alpha1/fake/fake_nodeslicepool.go new file mode 100644 index 000000000..4f250df4d --- /dev/null +++ b/pkg/client/clientset/versioned/typed/whereabouts.cni.cncf.io/v1alpha1/fake/fake_nodeslicepool.go @@ -0,0 +1,141 @@ +/* +Copyright 2024 The Kubernetes 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. +*/ +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + "context" + + v1alpha1 "github.com/k8snetworkplumbingwg/whereabouts/pkg/api/whereabouts.cni.cncf.io/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + schema "k8s.io/apimachinery/pkg/runtime/schema" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" +) + +// FakeNodeSlicePools implements NodeSlicePoolInterface +type FakeNodeSlicePools struct { + Fake *FakeWhereaboutsV1alpha1 + ns string +} + +var nodeslicepoolsResource = schema.GroupVersionResource{Group: "whereabouts.cni.cncf.io", Version: "v1alpha1", Resource: "nodeslicepools"} + +var nodeslicepoolsKind = schema.GroupVersionKind{Group: "whereabouts.cni.cncf.io", Version: "v1alpha1", Kind: "NodeSlicePool"} + +// Get takes name of the nodeSlicePool, and returns the corresponding nodeSlicePool object, and an error if there is any. +func (c *FakeNodeSlicePools) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.NodeSlicePool, err error) { + obj, err := c.Fake. + Invokes(testing.NewGetAction(nodeslicepoolsResource, c.ns, name), &v1alpha1.NodeSlicePool{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.NodeSlicePool), err +} + +// List takes label and field selectors, and returns the list of NodeSlicePools that match those selectors. +func (c *FakeNodeSlicePools) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.NodeSlicePoolList, err error) { + obj, err := c.Fake. + Invokes(testing.NewListAction(nodeslicepoolsResource, nodeslicepoolsKind, c.ns, opts), &v1alpha1.NodeSlicePoolList{}) + + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &v1alpha1.NodeSlicePoolList{ListMeta: obj.(*v1alpha1.NodeSlicePoolList).ListMeta} + for _, item := range obj.(*v1alpha1.NodeSlicePoolList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +// Watch returns a watch.Interface that watches the requested nodeSlicePools. +func (c *FakeNodeSlicePools) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewWatchAction(nodeslicepoolsResource, c.ns, opts)) + +} + +// Create takes the representation of a nodeSlicePool and creates it. Returns the server's representation of the nodeSlicePool, and an error, if there is any. +func (c *FakeNodeSlicePools) Create(ctx context.Context, nodeSlicePool *v1alpha1.NodeSlicePool, opts v1.CreateOptions) (result *v1alpha1.NodeSlicePool, err error) { + obj, err := c.Fake. + Invokes(testing.NewCreateAction(nodeslicepoolsResource, c.ns, nodeSlicePool), &v1alpha1.NodeSlicePool{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.NodeSlicePool), err +} + +// Update takes the representation of a nodeSlicePool and updates it. Returns the server's representation of the nodeSlicePool, and an error, if there is any. +func (c *FakeNodeSlicePools) Update(ctx context.Context, nodeSlicePool *v1alpha1.NodeSlicePool, opts v1.UpdateOptions) (result *v1alpha1.NodeSlicePool, err error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateAction(nodeslicepoolsResource, c.ns, nodeSlicePool), &v1alpha1.NodeSlicePool{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.NodeSlicePool), err +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *FakeNodeSlicePools) UpdateStatus(ctx context.Context, nodeSlicePool *v1alpha1.NodeSlicePool, opts v1.UpdateOptions) (*v1alpha1.NodeSlicePool, error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateSubresourceAction(nodeslicepoolsResource, "status", c.ns, nodeSlicePool), &v1alpha1.NodeSlicePool{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.NodeSlicePool), err +} + +// Delete takes name of the nodeSlicePool and deletes it. Returns an error if one occurs. +func (c *FakeNodeSlicePools) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewDeleteActionWithOptions(nodeslicepoolsResource, c.ns, name, opts), &v1alpha1.NodeSlicePool{}) + + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeNodeSlicePools) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + action := testing.NewDeleteCollectionAction(nodeslicepoolsResource, c.ns, listOpts) + + _, err := c.Fake.Invokes(action, &v1alpha1.NodeSlicePoolList{}) + return err +} + +// Patch applies the patch and returns the patched nodeSlicePool. +func (c *FakeNodeSlicePools) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.NodeSlicePool, err error) { + obj, err := c.Fake. + Invokes(testing.NewPatchSubresourceAction(nodeslicepoolsResource, c.ns, name, pt, data, subresources...), &v1alpha1.NodeSlicePool{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.NodeSlicePool), err +} diff --git a/pkg/client/clientset/versioned/typed/whereabouts.cni.cncf.io/v1alpha1/fake/fake_whereabouts.cni.cncf.io_client.go b/pkg/client/clientset/versioned/typed/whereabouts.cni.cncf.io/v1alpha1/fake/fake_whereabouts.cni.cncf.io_client.go index dd1177fbe..b8aa1b141 100644 --- a/pkg/client/clientset/versioned/typed/whereabouts.cni.cncf.io/v1alpha1/fake/fake_whereabouts.cni.cncf.io_client.go +++ b/pkg/client/clientset/versioned/typed/whereabouts.cni.cncf.io/v1alpha1/fake/fake_whereabouts.cni.cncf.io_client.go @@ -31,6 +31,10 @@ func (c *FakeWhereaboutsV1alpha1) IPPools(namespace string) v1alpha1.IPPoolInter return &FakeIPPools{c, namespace} } +func (c *FakeWhereaboutsV1alpha1) NodeSlicePools(namespace string) v1alpha1.NodeSlicePoolInterface { + return &FakeNodeSlicePools{c, namespace} +} + func (c *FakeWhereaboutsV1alpha1) OverlappingRangeIPReservations(namespace string) v1alpha1.OverlappingRangeIPReservationInterface { return &FakeOverlappingRangeIPReservations{c, namespace} } diff --git a/pkg/client/clientset/versioned/typed/whereabouts.cni.cncf.io/v1alpha1/generated_expansion.go b/pkg/client/clientset/versioned/typed/whereabouts.cni.cncf.io/v1alpha1/generated_expansion.go index 529523cbb..bd49da3fb 100644 --- a/pkg/client/clientset/versioned/typed/whereabouts.cni.cncf.io/v1alpha1/generated_expansion.go +++ b/pkg/client/clientset/versioned/typed/whereabouts.cni.cncf.io/v1alpha1/generated_expansion.go @@ -19,4 +19,6 @@ package v1alpha1 type IPPoolExpansion interface{} +type NodeSlicePoolExpansion interface{} + type OverlappingRangeIPReservationExpansion interface{} diff --git a/pkg/client/clientset/versioned/typed/whereabouts.cni.cncf.io/v1alpha1/nodeslicepool.go b/pkg/client/clientset/versioned/typed/whereabouts.cni.cncf.io/v1alpha1/nodeslicepool.go new file mode 100644 index 000000000..b099dd7f4 --- /dev/null +++ b/pkg/client/clientset/versioned/typed/whereabouts.cni.cncf.io/v1alpha1/nodeslicepool.go @@ -0,0 +1,194 @@ +/* +Copyright 2024 The Kubernetes 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. +*/ +// Code generated by client-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "context" + "time" + + v1alpha1 "github.com/k8snetworkplumbingwg/whereabouts/pkg/api/whereabouts.cni.cncf.io/v1alpha1" + scheme "github.com/k8snetworkplumbingwg/whereabouts/pkg/client/clientset/versioned/scheme" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + rest "k8s.io/client-go/rest" +) + +// NodeSlicePoolsGetter has a method to return a NodeSlicePoolInterface. +// A group's client should implement this interface. +type NodeSlicePoolsGetter interface { + NodeSlicePools(namespace string) NodeSlicePoolInterface +} + +// NodeSlicePoolInterface has methods to work with NodeSlicePool resources. +type NodeSlicePoolInterface interface { + Create(ctx context.Context, nodeSlicePool *v1alpha1.NodeSlicePool, opts v1.CreateOptions) (*v1alpha1.NodeSlicePool, error) + Update(ctx context.Context, nodeSlicePool *v1alpha1.NodeSlicePool, opts v1.UpdateOptions) (*v1alpha1.NodeSlicePool, error) + UpdateStatus(ctx context.Context, nodeSlicePool *v1alpha1.NodeSlicePool, opts v1.UpdateOptions) (*v1alpha1.NodeSlicePool, error) + Delete(ctx context.Context, name string, opts v1.DeleteOptions) error + DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error + Get(ctx context.Context, name string, opts v1.GetOptions) (*v1alpha1.NodeSlicePool, error) + List(ctx context.Context, opts v1.ListOptions) (*v1alpha1.NodeSlicePoolList, error) + Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) + Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.NodeSlicePool, err error) + NodeSlicePoolExpansion +} + +// nodeSlicePools implements NodeSlicePoolInterface +type nodeSlicePools struct { + client rest.Interface + ns string +} + +// newNodeSlicePools returns a NodeSlicePools +func newNodeSlicePools(c *WhereaboutsV1alpha1Client, namespace string) *nodeSlicePools { + return &nodeSlicePools{ + client: c.RESTClient(), + ns: namespace, + } +} + +// Get takes name of the nodeSlicePool, and returns the corresponding nodeSlicePool object, and an error if there is any. +func (c *nodeSlicePools) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.NodeSlicePool, err error) { + result = &v1alpha1.NodeSlicePool{} + err = c.client.Get(). + Namespace(c.ns). + Resource("nodeslicepools"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(ctx). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of NodeSlicePools that match those selectors. +func (c *nodeSlicePools) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.NodeSlicePoolList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v1alpha1.NodeSlicePoolList{} + err = c.client.Get(). + Namespace(c.ns). + Resource("nodeslicepools"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(ctx). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested nodeSlicePools. +func (c *nodeSlicePools) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + opts.Watch = true + return c.client.Get(). + Namespace(c.ns). + Resource("nodeslicepools"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch(ctx) +} + +// Create takes the representation of a nodeSlicePool and creates it. Returns the server's representation of the nodeSlicePool, and an error, if there is any. +func (c *nodeSlicePools) Create(ctx context.Context, nodeSlicePool *v1alpha1.NodeSlicePool, opts v1.CreateOptions) (result *v1alpha1.NodeSlicePool, err error) { + result = &v1alpha1.NodeSlicePool{} + err = c.client.Post(). + Namespace(c.ns). + Resource("nodeslicepools"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(nodeSlicePool). + Do(ctx). + Into(result) + return +} + +// Update takes the representation of a nodeSlicePool and updates it. Returns the server's representation of the nodeSlicePool, and an error, if there is any. +func (c *nodeSlicePools) Update(ctx context.Context, nodeSlicePool *v1alpha1.NodeSlicePool, opts v1.UpdateOptions) (result *v1alpha1.NodeSlicePool, err error) { + result = &v1alpha1.NodeSlicePool{} + err = c.client.Put(). + Namespace(c.ns). + Resource("nodeslicepools"). + Name(nodeSlicePool.Name). + VersionedParams(&opts, scheme.ParameterCodec). + Body(nodeSlicePool). + Do(ctx). + Into(result) + return +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *nodeSlicePools) UpdateStatus(ctx context.Context, nodeSlicePool *v1alpha1.NodeSlicePool, opts v1.UpdateOptions) (result *v1alpha1.NodeSlicePool, err error) { + result = &v1alpha1.NodeSlicePool{} + err = c.client.Put(). + Namespace(c.ns). + Resource("nodeslicepools"). + Name(nodeSlicePool.Name). + SubResource("status"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(nodeSlicePool). + Do(ctx). + Into(result) + return +} + +// Delete takes name of the nodeSlicePool and deletes it. Returns an error if one occurs. +func (c *nodeSlicePools) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + return c.client.Delete(). + Namespace(c.ns). + Resource("nodeslicepools"). + Name(name). + Body(&opts). + Do(ctx). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *nodeSlicePools) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + var timeout time.Duration + if listOpts.TimeoutSeconds != nil { + timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second + } + return c.client.Delete(). + Namespace(c.ns). + Resource("nodeslicepools"). + VersionedParams(&listOpts, scheme.ParameterCodec). + Timeout(timeout). + Body(&opts). + Do(ctx). + Error() +} + +// Patch applies the patch and returns the patched nodeSlicePool. +func (c *nodeSlicePools) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.NodeSlicePool, err error) { + result = &v1alpha1.NodeSlicePool{} + err = c.client.Patch(pt). + Namespace(c.ns). + Resource("nodeslicepools"). + Name(name). + SubResource(subresources...). + VersionedParams(&opts, scheme.ParameterCodec). + Body(data). + Do(ctx). + Into(result) + return +} diff --git a/pkg/client/clientset/versioned/typed/whereabouts.cni.cncf.io/v1alpha1/whereabouts.cni.cncf.io_client.go b/pkg/client/clientset/versioned/typed/whereabouts.cni.cncf.io/v1alpha1/whereabouts.cni.cncf.io_client.go index a4a261a45..c841c614e 100644 --- a/pkg/client/clientset/versioned/typed/whereabouts.cni.cncf.io/v1alpha1/whereabouts.cni.cncf.io_client.go +++ b/pkg/client/clientset/versioned/typed/whereabouts.cni.cncf.io/v1alpha1/whereabouts.cni.cncf.io_client.go @@ -28,6 +28,7 @@ import ( type WhereaboutsV1alpha1Interface interface { RESTClient() rest.Interface IPPoolsGetter + NodeSlicePoolsGetter OverlappingRangeIPReservationsGetter } @@ -40,6 +41,10 @@ func (c *WhereaboutsV1alpha1Client) IPPools(namespace string) IPPoolInterface { return newIPPools(c, namespace) } +func (c *WhereaboutsV1alpha1Client) NodeSlicePools(namespace string) NodeSlicePoolInterface { + return newNodeSlicePools(c, namespace) +} + func (c *WhereaboutsV1alpha1Client) OverlappingRangeIPReservations(namespace string) OverlappingRangeIPReservationInterface { return newOverlappingRangeIPReservations(c, namespace) } diff --git a/pkg/client/informers/externalversions/generic.go b/pkg/client/informers/externalversions/generic.go index 24f0e1b1d..4d2c3dc0f 100644 --- a/pkg/client/informers/externalversions/generic.go +++ b/pkg/client/informers/externalversions/generic.go @@ -54,6 +54,8 @@ func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource // Group=whereabouts.cni.cncf.io, Version=v1alpha1 case v1alpha1.SchemeGroupVersion.WithResource("ippools"): return &genericInformer{resource: resource.GroupResource(), informer: f.Whereabouts().V1alpha1().IPPools().Informer()}, nil + case v1alpha1.SchemeGroupVersion.WithResource("nodeslicepools"): + return &genericInformer{resource: resource.GroupResource(), informer: f.Whereabouts().V1alpha1().NodeSlicePools().Informer()}, nil case v1alpha1.SchemeGroupVersion.WithResource("overlappingrangeipreservations"): return &genericInformer{resource: resource.GroupResource(), informer: f.Whereabouts().V1alpha1().OverlappingRangeIPReservations().Informer()}, nil diff --git a/pkg/client/informers/externalversions/whereabouts.cni.cncf.io/v1alpha1/interface.go b/pkg/client/informers/externalversions/whereabouts.cni.cncf.io/v1alpha1/interface.go index cd1e4cf02..e2546214d 100644 --- a/pkg/client/informers/externalversions/whereabouts.cni.cncf.io/v1alpha1/interface.go +++ b/pkg/client/informers/externalversions/whereabouts.cni.cncf.io/v1alpha1/interface.go @@ -25,6 +25,8 @@ import ( type Interface interface { // IPPools returns a IPPoolInformer. IPPools() IPPoolInformer + // NodeSlicePools returns a NodeSlicePoolInformer. + NodeSlicePools() NodeSlicePoolInformer // OverlappingRangeIPReservations returns a OverlappingRangeIPReservationInformer. OverlappingRangeIPReservations() OverlappingRangeIPReservationInformer } @@ -45,6 +47,11 @@ func (v *version) IPPools() IPPoolInformer { return &iPPoolInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} } +// NodeSlicePools returns a NodeSlicePoolInformer. +func (v *version) NodeSlicePools() NodeSlicePoolInformer { + return &nodeSlicePoolInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} +} + // OverlappingRangeIPReservations returns a OverlappingRangeIPReservationInformer. func (v *version) OverlappingRangeIPReservations() OverlappingRangeIPReservationInformer { return &overlappingRangeIPReservationInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions} diff --git a/pkg/client/informers/externalversions/whereabouts.cni.cncf.io/v1alpha1/nodeslicepool.go b/pkg/client/informers/externalversions/whereabouts.cni.cncf.io/v1alpha1/nodeslicepool.go new file mode 100644 index 000000000..39ea336fa --- /dev/null +++ b/pkg/client/informers/externalversions/whereabouts.cni.cncf.io/v1alpha1/nodeslicepool.go @@ -0,0 +1,89 @@ +/* +Copyright 2024 The Kubernetes 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. +*/ +// Code generated by informer-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + "context" + time "time" + + whereaboutscnicncfiov1alpha1 "github.com/k8snetworkplumbingwg/whereabouts/pkg/api/whereabouts.cni.cncf.io/v1alpha1" + versioned "github.com/k8snetworkplumbingwg/whereabouts/pkg/client/clientset/versioned" + internalinterfaces "github.com/k8snetworkplumbingwg/whereabouts/pkg/client/informers/externalversions/internalinterfaces" + v1alpha1 "github.com/k8snetworkplumbingwg/whereabouts/pkg/client/listers/whereabouts.cni.cncf.io/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + watch "k8s.io/apimachinery/pkg/watch" + cache "k8s.io/client-go/tools/cache" +) + +// NodeSlicePoolInformer provides access to a shared informer and lister for +// NodeSlicePools. +type NodeSlicePoolInformer interface { + Informer() cache.SharedIndexInformer + Lister() v1alpha1.NodeSlicePoolLister +} + +type nodeSlicePoolInformer struct { + factory internalinterfaces.SharedInformerFactory + tweakListOptions internalinterfaces.TweakListOptionsFunc + namespace string +} + +// NewNodeSlicePoolInformer constructs a new informer for NodeSlicePool type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewNodeSlicePoolInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer { + return NewFilteredNodeSlicePoolInformer(client, namespace, resyncPeriod, indexers, nil) +} + +// NewFilteredNodeSlicePoolInformer constructs a new informer for NodeSlicePool type. +// Always prefer using an informer factory to get a shared informer instead of getting an independent +// one. This reduces memory footprint and number of connections to the server. +func NewFilteredNodeSlicePoolInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer { + return cache.NewSharedIndexInformer( + &cache.ListWatch{ + ListFunc: func(options v1.ListOptions) (runtime.Object, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.WhereaboutsV1alpha1().NodeSlicePools(namespace).List(context.TODO(), options) + }, + WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { + if tweakListOptions != nil { + tweakListOptions(&options) + } + return client.WhereaboutsV1alpha1().NodeSlicePools(namespace).Watch(context.TODO(), options) + }, + }, + &whereaboutscnicncfiov1alpha1.NodeSlicePool{}, + resyncPeriod, + indexers, + ) +} + +func (f *nodeSlicePoolInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer { + return NewFilteredNodeSlicePoolInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions) +} + +func (f *nodeSlicePoolInformer) Informer() cache.SharedIndexInformer { + return f.factory.InformerFor(&whereaboutscnicncfiov1alpha1.NodeSlicePool{}, f.defaultInformer) +} + +func (f *nodeSlicePoolInformer) Lister() v1alpha1.NodeSlicePoolLister { + return v1alpha1.NewNodeSlicePoolLister(f.Informer().GetIndexer()) +} diff --git a/pkg/client/listers/whereabouts.cni.cncf.io/v1alpha1/expansion_generated.go b/pkg/client/listers/whereabouts.cni.cncf.io/v1alpha1/expansion_generated.go index 8fcd90e06..6495d1a1a 100644 --- a/pkg/client/listers/whereabouts.cni.cncf.io/v1alpha1/expansion_generated.go +++ b/pkg/client/listers/whereabouts.cni.cncf.io/v1alpha1/expansion_generated.go @@ -25,6 +25,14 @@ type IPPoolListerExpansion interface{} // IPPoolNamespaceLister. type IPPoolNamespaceListerExpansion interface{} +// NodeSlicePoolListerExpansion allows custom methods to be added to +// NodeSlicePoolLister. +type NodeSlicePoolListerExpansion interface{} + +// NodeSlicePoolNamespaceListerExpansion allows custom methods to be added to +// NodeSlicePoolNamespaceLister. +type NodeSlicePoolNamespaceListerExpansion interface{} + // OverlappingRangeIPReservationListerExpansion allows custom methods to be added to // OverlappingRangeIPReservationLister. type OverlappingRangeIPReservationListerExpansion interface{} diff --git a/pkg/client/listers/whereabouts.cni.cncf.io/v1alpha1/nodeslicepool.go b/pkg/client/listers/whereabouts.cni.cncf.io/v1alpha1/nodeslicepool.go new file mode 100644 index 000000000..1e6ae8bb5 --- /dev/null +++ b/pkg/client/listers/whereabouts.cni.cncf.io/v1alpha1/nodeslicepool.go @@ -0,0 +1,98 @@ +/* +Copyright 2024 The Kubernetes 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. +*/ +// Code generated by lister-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + v1alpha1 "github.com/k8snetworkplumbingwg/whereabouts/pkg/api/whereabouts.cni.cncf.io/v1alpha1" + "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/client-go/tools/cache" +) + +// NodeSlicePoolLister helps list NodeSlicePools. +// All objects returned here must be treated as read-only. +type NodeSlicePoolLister interface { + // List lists all NodeSlicePools in the indexer. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1alpha1.NodeSlicePool, err error) + // NodeSlicePools returns an object that can list and get NodeSlicePools. + NodeSlicePools(namespace string) NodeSlicePoolNamespaceLister + NodeSlicePoolListerExpansion +} + +// nodeSlicePoolLister implements the NodeSlicePoolLister interface. +type nodeSlicePoolLister struct { + indexer cache.Indexer +} + +// NewNodeSlicePoolLister returns a new NodeSlicePoolLister. +func NewNodeSlicePoolLister(indexer cache.Indexer) NodeSlicePoolLister { + return &nodeSlicePoolLister{indexer: indexer} +} + +// List lists all NodeSlicePools in the indexer. +func (s *nodeSlicePoolLister) List(selector labels.Selector) (ret []*v1alpha1.NodeSlicePool, err error) { + err = cache.ListAll(s.indexer, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha1.NodeSlicePool)) + }) + return ret, err +} + +// NodeSlicePools returns an object that can list and get NodeSlicePools. +func (s *nodeSlicePoolLister) NodeSlicePools(namespace string) NodeSlicePoolNamespaceLister { + return nodeSlicePoolNamespaceLister{indexer: s.indexer, namespace: namespace} +} + +// NodeSlicePoolNamespaceLister helps list and get NodeSlicePools. +// All objects returned here must be treated as read-only. +type NodeSlicePoolNamespaceLister interface { + // List lists all NodeSlicePools in the indexer for a given namespace. + // Objects returned here must be treated as read-only. + List(selector labels.Selector) (ret []*v1alpha1.NodeSlicePool, err error) + // Get retrieves the NodeSlicePool from the indexer for a given namespace and name. + // Objects returned here must be treated as read-only. + Get(name string) (*v1alpha1.NodeSlicePool, error) + NodeSlicePoolNamespaceListerExpansion +} + +// nodeSlicePoolNamespaceLister implements the NodeSlicePoolNamespaceLister +// interface. +type nodeSlicePoolNamespaceLister struct { + indexer cache.Indexer + namespace string +} + +// List lists all NodeSlicePools in the indexer for a given namespace. +func (s nodeSlicePoolNamespaceLister) List(selector labels.Selector) (ret []*v1alpha1.NodeSlicePool, err error) { + err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) { + ret = append(ret, m.(*v1alpha1.NodeSlicePool)) + }) + return ret, err +} + +// Get retrieves the NodeSlicePool from the indexer for a given namespace and name. +func (s nodeSlicePoolNamespaceLister) Get(name string) (*v1alpha1.NodeSlicePool, error) { + obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name) + if err != nil { + return nil, err + } + if !exists { + return nil, errors.NewNotFound(v1alpha1.Resource("nodeslicepool"), name) + } + return obj.(*v1alpha1.NodeSlicePool), nil +} diff --git a/pkg/config/config.go b/pkg/config/config.go index ba94ce61c..6753371f1 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -109,6 +109,7 @@ func LoadIPAMConfig(bytes []byte, envArgs string, extraConfigPaths ...string) (* } else { firstip, ipNet, err := netutils.ParseCIDRSloppy(n.IPAM.IPRanges[idx].Range) if err != nil { + logging.Debugf("invalid cidr error on range %v, within ranges %v", n.IPAM.IPRanges[idx].Range, n.IPAM.IPRanges) return nil, "", fmt.Errorf("invalid CIDR %s: %s", n.IPAM.IPRanges[idx].Range, err) } n.IPAM.IPRanges[idx].Range = ipNet.String() diff --git a/pkg/iphelpers/iphelpers.go b/pkg/iphelpers/iphelpers.go index f70591cfd..db2b19272 100644 --- a/pkg/iphelpers/iphelpers.go +++ b/pkg/iphelpers/iphelpers.go @@ -1,9 +1,13 @@ package iphelpers import ( + "encoding/binary" + "errors" "fmt" "math" "net" + "strconv" + "strings" ) // CompareIPs reports whether out of 2 given IPs, ipX and ipY, ipY is smaller (-1), the same (0) or larger (1). @@ -25,6 +29,60 @@ func CompareIPs(ipX net.IP, ipY net.IP) int { return 0 } +// DivideRangeBySize takes an ipRange i.e. 11.0.0.0/8 and a sliceSize i.e. /24 +// and returns a list of IPNets that divide the input range into sizes +func DivideRangeBySize(inputNetwork string, sliceSizeString string) ([]string, error) { + // Remove "/" from the start of the sliceSize + sliceSizeString = strings.TrimPrefix(sliceSizeString, "/") + + sliceSize, err := strconv.Atoi(sliceSizeString) + if err != nil { + fmt.Println("Error:", err) + return nil, nil + } + ip, ipNet, err := net.ParseCIDR(inputNetwork) + if err != nil { + return nil, err + } + if !ip.Equal(ipNet.IP) { + return nil, errors.New("netCIDR is not a valid network address") + } + netMaskSize, _ := ipNet.Mask.Size() + if netMaskSize > int(sliceSize) { + return nil, errors.New("subnetMaskSize must be greater or equal than netMaskSize") + } + + totalSubnetsInNetwork := math.Pow(2, float64(sliceSize)-float64(netMaskSize)) + totalHostsInSubnet := math.Pow(2, 32-float64(sliceSize)) + subnetIntAddresses := make([]uint32, int(totalSubnetsInNetwork)) + // first subnet address is same as the network address + subnetIntAddresses[0] = ip2int(ip.To4()) + for i := 1; i < int(totalSubnetsInNetwork); i++ { + subnetIntAddresses[i] = subnetIntAddresses[i-1] + uint32(totalHostsInSubnet) + } + + subnetCIDRs := make([]string, 0) + for _, sia := range subnetIntAddresses { + subnetCIDRs = append( + subnetCIDRs, + int2ip(sia).String()+"/"+strconv.Itoa(int(sliceSize)), + ) + } + return subnetCIDRs, nil +} + +func ip2int(ip net.IP) uint32 { + if len(ip) == 16 { + panic("cannot convert IPv6 into uint32") + } + return binary.BigEndian.Uint32(ip) +} +func int2ip(nn uint32) net.IP { + ip := make(net.IP, 4) + binary.BigEndian.PutUint32(ip, nn) + return ip +} + // IsIPInRange returns true if a given IP is within the continuous range of start and end IP (inclusively). func IsIPInRange(in net.IP, start net.IP, end net.IP) (bool, error) { if in == nil || start == nil || end == nil { diff --git a/pkg/iphelpers/iphelpers_test.go b/pkg/iphelpers/iphelpers_test.go index 78a65dc0a..517feebaa 100644 --- a/pkg/iphelpers/iphelpers_test.go +++ b/pkg/iphelpers/iphelpers_test.go @@ -923,3 +923,69 @@ var _ = Describe("IPAddOffset operations", func() { Expect(fmt.Sprint(newIP)).To(Equal("2000::1:0")) }) }) + +func TestDivideRangeBySize(t *testing.T) { + cases := []struct { + name string + netRange string + sliceSize string + expectedResult []string + expectError bool + }{ + { + name: "Network divided by same size slice", + netRange: "10.0.0.0/8", + sliceSize: "/8", + expectedResult: []string{"10.0.0.0/8"}, + }, + { + name: "Network divided /8 by /10", + netRange: "10.0.0.0/8", + sliceSize: "/10", + expectedResult: []string{"10.0.0.0/10", "10.64.0.0/10", "10.128.0.0/10", "10.192.0.0/10"}, + }, + { + name: "Network divided /10 by /8", + netRange: "10.0.0.0/10", + sliceSize: "/8", + expectError: true, + }, + { + name: "Network divided /8 by /11", + netRange: "10.0.0.0/8", + sliceSize: "/11", + expectedResult: []string{"10.0.0.0/11", "10.32.0.0/11", "10.64.0.0/11", "10.96.0.0/11", "10.128.0.0/11", "10.160.0.0/11", "10.192.0.0/11", "10.224.0.0/11"}, + }, + { + name: "Network divided /10 by /12", + netRange: "10.0.0.0/10", + sliceSize: "/12", + expectedResult: []string{"10.0.0.0/12", "10.16.0.0/12", "10.32.0.0/12", "10.48.0.0/12"}, + }, + { + name: "Network divided /8 by /10 without / in slice", + netRange: "10.0.0.0/8", + sliceSize: "10", + expectedResult: []string{"10.0.0.0/10", "10.64.0.0/10", "10.128.0.0/10", "10.192.0.0/10"}, + }, + } + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + result, err := DivideRangeBySize(tc.netRange, tc.sliceSize) + if err != nil && !tc.expectError { + t.Errorf("unexpected error: %v", err) + } + if err == nil && tc.expectError { + t.Fatalf("expected error but did not get it") + } + if len(result) != len(tc.expectedResult) { + t.Fatalf("Expected result: %s, got result: %s", tc.expectedResult, result) + } + for i := range result { + if result[i] != tc.expectedResult[i] { + t.Fatalf("Expected result: %s, got result: %s", tc.expectedResult, result) + } + } + }) + } +} diff --git a/pkg/logging/logging.go b/pkg/logging/logging.go index 5d1b59305..a47f35fba 100644 --- a/pkg/logging/logging.go +++ b/pkg/logging/logging.go @@ -37,7 +37,7 @@ const ( ) var loggingStderr bool -var loggingFp *os.File +var LoggingFp *os.File var loggingLevel Level const defaultTimestampFormat = time.RFC3339 @@ -70,10 +70,10 @@ func Printf(level Level, format string, a ...interface{}) { fmt.Fprintf(os.Stderr, "\n") } - if loggingFp != nil { - fmt.Fprintf(loggingFp, header, t.Format(defaultTimestampFormat), level) - fmt.Fprintf(loggingFp, format, a...) - fmt.Fprintf(loggingFp, "\n") + if LoggingFp != nil { + fmt.Fprintf(LoggingFp, header, t.Format(defaultTimestampFormat), level) + fmt.Fprintf(LoggingFp, format, a...) + fmt.Fprintf(LoggingFp, "\n") } } @@ -142,14 +142,14 @@ func SetLogFile(filename string) { fp, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644) if err != nil { - loggingFp = nil + LoggingFp = nil fmt.Fprintf(os.Stderr, "Whereabouts logging: cannot open %s", filename) } - loggingFp = fp + LoggingFp = fp } func init() { loggingStderr = true - loggingFp = nil + LoggingFp = nil loggingLevel = DebugLevel } diff --git a/pkg/logging/logging_test.go b/pkg/logging/logging_test.go index be99a7edb..ad86a0b0c 100644 --- a/pkg/logging/logging_test.go +++ b/pkg/logging/logging_test.go @@ -30,18 +30,18 @@ var _ = Describe("logging operations", func() { BeforeEach(func() { loggingStderr = false - loggingFp = nil + LoggingFp = nil loggingLevel = PanicLevel }) It("Check file setter with empty", func() { SetLogFile("") - Expect(loggingFp).To(BeNil()) + Expect(LoggingFp).To(BeNil()) }) It("Check file setter with empty", func() { SetLogFile("/tmp/foobar.logging") - Expect(loggingFp).NotTo(Equal(nil)) + Expect(LoggingFp).NotTo(Equal(nil)) }) It("Check loglevel setter", func() { diff --git a/pkg/node-controller/controller.go b/pkg/node-controller/controller.go new file mode 100644 index 000000000..9521358d1 --- /dev/null +++ b/pkg/node-controller/controller.go @@ -0,0 +1,622 @@ +package node_controller + +import ( + "context" + "fmt" + cncfV1 "github.com/k8snetworkplumbingwg/network-attachment-definition-client/pkg/apis/k8s.cni.cncf.io/v1" + nadclient "github.com/k8snetworkplumbingwg/network-attachment-definition-client/pkg/client/clientset/versioned" + nadinformers "github.com/k8snetworkplumbingwg/network-attachment-definition-client/pkg/client/informers/externalversions/k8s.cni.cncf.io/v1" + nadlisters "github.com/k8snetworkplumbingwg/network-attachment-definition-client/pkg/client/listers/k8s.cni.cncf.io/v1" + "github.com/k8snetworkplumbingwg/whereabouts/pkg/api/whereabouts.cni.cncf.io/v1alpha1" + clientset "github.com/k8snetworkplumbingwg/whereabouts/pkg/client/clientset/versioned" + whereaboutsInformers "github.com/k8snetworkplumbingwg/whereabouts/pkg/client/informers/externalversions/whereabouts.cni.cncf.io/v1alpha1" + whereaboutsListers "github.com/k8snetworkplumbingwg/whereabouts/pkg/client/listers/whereabouts.cni.cncf.io/v1alpha1" + "github.com/k8snetworkplumbingwg/whereabouts/pkg/config" + "github.com/k8snetworkplumbingwg/whereabouts/pkg/iphelpers" + "github.com/k8snetworkplumbingwg/whereabouts/pkg/types" + "k8s.io/apimachinery/pkg/api/errors" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "sort" + "time" + + "golang.org/x/time/rate" + "k8s.io/apimachinery/pkg/labels" + + corev1 "k8s.io/api/core/v1" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + "k8s.io/apimachinery/pkg/util/wait" + coreinformers "k8s.io/client-go/informers/core/v1" + "k8s.io/client-go/kubernetes" + "k8s.io/client-go/kubernetes/scheme" + typedcorev1 "k8s.io/client-go/kubernetes/typed/core/v1" + corelisters "k8s.io/client-go/listers/core/v1" + "k8s.io/client-go/tools/cache" + "k8s.io/client-go/tools/record" + "k8s.io/client-go/util/workqueue" + "k8s.io/klog/v2" +) + +const controllerAgentName = "node-controller" + +const ( + whereaboutsConfigPath = "/etc/cni/net.d/whereabouts.d/whereabouts.conf" +) + +// Controller is the controller implementation for Foo resources +type Controller struct { + // kubeclientset is a standard kubernetes clientset + kubeclientset kubernetes.Interface + // sampleclientset is a clientset for our own API group + whereaboutsclientset clientset.Interface + + nadclientset nadclient.Interface + + nodeLister corelisters.NodeLister + nodeInformer coreinformers.NodeInformer + nodesSynced cache.InformerSynced + ipPoolLister whereaboutsListers.IPPoolLister + ipPoolInformer whereaboutsInformers.IPPoolInformer + + nodeSlicePoolLister whereaboutsListers.NodeSlicePoolLister + nodeSlicePoolInformer whereaboutsInformers.NodeSlicePoolInformer + nodeSlicePoolSynced cache.InformerSynced + + nadInformer nadinformers.NetworkAttachmentDefinitionInformer + nadLister nadlisters.NetworkAttachmentDefinitionLister + nadSynced cache.InformerSynced + + // workqueue is a rate limited work queue. This is used to queue work to be + // processed instead of performing it as soon as a change happens. This + // means we can ensure we only process a fixed amount of resources at a + // time, and makes it easy to ensure we are never processing the same item + // simultaneously in two different workers. + workqueue workqueue.RateLimitingInterface + + // recorder is an event recorder for recording Event resources to the + // Kubernetes API. + recorder record.EventRecorder + + //For testing, sort nodes before assigning to get consistent return values + sortResults bool +} + +// NewController returns a new sample controller +func NewController( + ctx context.Context, + kubeclientset kubernetes.Interface, + whereaboutsclientset clientset.Interface, + nadclientset nadclient.Interface, + nodeInformer coreinformers.NodeInformer, + nodeSlicePoolInformer whereaboutsInformers.NodeSlicePoolInformer, + ipPoolInformer whereaboutsInformers.IPPoolInformer, + nadInformer nadinformers.NetworkAttachmentDefinitionInformer, + sortResults bool, +) *Controller { + logger := klog.FromContext(ctx) + + logger.V(4).Info("Creating event broadcaster") + + eventBroadcaster := record.NewBroadcaster() + eventBroadcaster.StartStructuredLogging(0) + eventBroadcaster.StartRecordingToSink(&typedcorev1.EventSinkImpl{Interface: kubeclientset.CoreV1().Events("")}) + recorder := eventBroadcaster.NewRecorder(scheme.Scheme, corev1.EventSource{Component: controllerAgentName}) + ratelimiter := workqueue.NewMaxOfRateLimiter( + workqueue.NewItemExponentialFailureRateLimiter(5*time.Millisecond, 1000*time.Second), + &workqueue.BucketRateLimiter{Limiter: rate.NewLimiter(rate.Limit(50), 300)}, + ) + + c := &Controller{ + kubeclientset: kubeclientset, + nodeLister: nodeInformer.Lister(), + nodeInformer: nodeInformer, + nodesSynced: nodeInformer.Informer().HasSynced, + whereaboutsclientset: whereaboutsclientset, + nodeSlicePoolLister: nodeSlicePoolInformer.Lister(), + nodeSlicePoolInformer: nodeSlicePoolInformer, + nodeSlicePoolSynced: nodeSlicePoolInformer.Informer().HasSynced, + ipPoolLister: ipPoolInformer.Lister(), //TODO: does this use IP Pools + ipPoolInformer: ipPoolInformer, + nadclientset: nadclientset, + nadInformer: nadInformer, + nadLister: nadInformer.Lister(), + nadSynced: nadInformer.Informer().HasSynced, + workqueue: workqueue.NewRateLimitingQueue(ratelimiter), + recorder: recorder, + sortResults: sortResults, + } + + logger.Info("Setting up event handlers") + + nadInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ + AddFunc: c.onNadEvent, + UpdateFunc: func(old, cur interface{}) { + c.onNadEvent(cur) + }, + DeleteFunc: c.onNadEvent, + }) + + nodeInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ + AddFunc: c.requeueNADs, + UpdateFunc: func(old, cur interface{}) { + c.requeueNADs(cur) + }, + DeleteFunc: c.requeueNADs, + }) + + nodeSlicePoolInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{ + AddFunc: c.requeueNADs, + UpdateFunc: func(old, cur interface{}) { + c.requeueNADs(cur) + }, + DeleteFunc: c.requeueNADs, + }) + + return c +} + +func (c *Controller) onNadEvent(obj interface{}) { + klog.Info("handling nad event") + var object metav1.Object + var ok bool + if object, ok = obj.(metav1.Object); !ok { + tombstone, ok := obj.(cache.DeletedFinalStateUnknown) + if !ok { + utilruntime.HandleError(fmt.Errorf("error decoding object, invalid type")) + return + } + object, ok = tombstone.Obj.(metav1.Object) + if !ok { + utilruntime.HandleError(fmt.Errorf("error decoding object tombstone, invalid type")) + return + } + } + key, err := cache.MetaNamespaceKeyFunc(object) + klog.Info(key) + if err != nil { + utilruntime.HandleError(fmt.Errorf("couldn't get key for object %+v: %v", obj, err)) + return + } + c.workqueue.Add(key) +} + +// TODO: we may want to require nodes to have an annotation similar to what pods have to receive a slice +// in this case we get all applicable NADs for the node rather than requeuing all +// same applies to other node event handlers +func (c *Controller) requeueNADs(obj interface{}) { + nadlist, err := c.nadLister.List(labels.Everything()) + if err != nil { + utilruntime.HandleError(fmt.Errorf("couldn't get network-attachment-definition list from informer: %v", err)) + return + } + for _, nad := range nadlist { + //TODO: cache.MetaNamespaceKeyFunc(nad) returns an error with "object has no meta: object does not implement the Object interfaces" + key, err := cache.MetaNamespaceKeyFunc(nad) + if err != nil { + utilruntime.HandleError(fmt.Errorf("couldn't get key for object %+v: %v", nad, err)) + return + } + c.workqueue.Add(key) + } +} + +// Run will set up the event handlers for types we are interested in, as well +// as syncing informer caches and starting workers. It will block until stopCh +// is closed, at which point it will shutdown the workqueue and wait for +// workers to finish processing their current work items. +func (c *Controller) Run(ctx context.Context, workers int) error { + defer utilruntime.HandleCrash() + defer c.workqueue.ShutDown() + logger := klog.FromContext(ctx) + + // Start the informer factories to begin populating the informer caches + logger.Info("Starting node-slice controller") + + // Wait for the caches to be synced before starting workers + logger.Info("Waiting for informer caches to sync") + + if ok := cache.WaitForCacheSync(ctx.Done(), c.nodesSynced); !ok { + return fmt.Errorf("failed to wait for nodes caches to sync") + } + if ok := cache.WaitForCacheSync(ctx.Done(), c.nodeSlicePoolSynced); !ok { + return fmt.Errorf("failed to wait for nodeslices caches to sync") + } + if ok := cache.WaitForCacheSync(ctx.Done(), c.nadSynced); !ok { + return fmt.Errorf("failed to wait for nad caches to sync") + } + + logger.Info("Starting workers", "count", workers) + // Launch two workers to process Foo resources + for i := 0; i < workers; i++ { + go wait.UntilWithContext(ctx, c.runWorker, time.Second) + } + + logger.Info("Started workers") + <-ctx.Done() + logger.Info("Shutting down workers") + + return nil +} + +// runWorker is a long-running function that will continually call the +// processNextWorkItem function in order to read and process a message on the +// workqueue. +func (c *Controller) runWorker(ctx context.Context) { + for c.processNextWorkItem(ctx) { + } +} + +// processNextWorkItem will read a single work item off the workqueue and +// attempt to process it, by calling the syncHandler. +func (c *Controller) processNextWorkItem(ctx context.Context) bool { + obj, shutdown := c.workqueue.Get() + logger := klog.FromContext(ctx) + + if shutdown { + return false + } + + // We wrap this block in a func so we can defer c.workqueue.Done. + err := func(obj interface{}) error { + // We call Done here so the workqueue knows we have finished + // processing this item. We also must remember to call Forget if we + // do not want this work item being re-queued. For example, we do + // not call Forget if a transient error occurs, instead the item is + // put back on the workqueue and attempted again after a back-off + // period. + defer c.workqueue.Done(obj) + var key string + var ok bool + // We expect strings to come off the workqueue. These are of the + // form namespace/name. We do this as the delayed nature of the + // workqueue means the items in the informer cache may actually be + // more up to date that when the item was initially put onto the + // workqueue. + if key, ok = obj.(string); !ok { + // As the item in the workqueue is actually invalid, we call + // Forget here else we'd go into a loop of attempting to + // process a work item that is invalid. + c.workqueue.Forget(obj) + utilruntime.HandleError(fmt.Errorf("expected string in workqueue but got %#v", obj)) + return nil + } + // Run the syncHandler, passing it the namespace/name string of the + // Foo resource to be synced. + if err := c.syncHandler(ctx, key); err != nil { + // Put the item back on the workqueue to handle any transient errors. + c.workqueue.AddRateLimited(key) + return fmt.Errorf("error syncing '%s': %s, requeuing", key, err.Error()) + } + // Finally, if no error occurs we Forget this item so it does not + // get queued again until another change happens. + c.workqueue.Forget(obj) + logger.Info("Successfully synced", "resourceName", key) + return nil + }(obj) + + if err != nil { + utilruntime.HandleError(err) + return true + } + + return true +} + +// syncHandler compares the actual state with the desired, and attempts to +// converge the two. It then updates the Status block of the Foo resource +// with the current status of the resource. +func (c *Controller) syncHandler(ctx context.Context, key string) error { + // Convert the namespace/name string into a distinct namespace and name + logger := klog.LoggerWithValues(klog.FromContext(ctx), "resourceName", key) + + namespace, name, err := cache.SplitMetaNamespaceKey(key) + if err != nil { + utilruntime.HandleError(fmt.Errorf("invalid resource key: %s", key)) + return nil + } + //TODO: use a named error + err = c.checkForMultiNadMismatch(name, namespace) + if err != nil { + return err + } + + nad, err := c.nadLister.NetworkAttachmentDefinitions(namespace).Get(name) + if err != nil { + if !errors.IsNotFound(err) { + return err + } + // in this case the nad dne so it must've been deleted so we will cleanup nodeslicepools + // if we are down during the delete this could be missed similar to endpoints see kubernetes #6877 + //TODO: do we want to cleanup IP Pools? + nodeSlices, err := c.nodeSlicePoolLister.List(labels.Everything()) + if err != nil { + return nil + } + for _, nodeSlice := range nodeSlices { + if hasOwnerRef(nodeSlice, name) { + if len(nodeSlice.OwnerReferences) == 1 { + //this is the last NAD owning this so delete + err = c.whereaboutsclientset.WhereaboutsV1alpha1().NodeSlicePools(namespace).Delete(ctx, name, metav1.DeleteOptions{}) + if err != nil && !errors.IsNotFound(err) { + return err + } + } + } + } + return nil + } + //nad does exist so did it change node_slice_range or slice_size + ipamConf, err := ipamConfiguration(nad, "") + if err != nil { + return err + } + + // This is to support several NADs and interfaces on the same network + logger.Info(fmt.Sprintf("%v", ipamConf)) + logger.Info(fmt.Sprintf("slicesize: %v", ipamConf.NodeSliceSize)) + if ipamConf.NodeSliceSize == "" || len(ipamConf.IPRanges) == 0 { + logger.Info("skipping update node slices for network-attachment-definition due missing node slice or range configurations", + "network-attachment-definition", klog.KRef(namespace, name)) + return nil + } + + logger.Info("About to update node slices for network-attachment-definition", + "network-attachment-definition", klog.KRef(namespace, name)) + + currentNodeSlicePool, err := c.nodeSlicePoolLister.NodeSlicePools(namespace).Get(getSliceName(ipamConf)) + if err != nil { + logger.Info("node slice pool does not exist, creating") + if !errors.IsNotFound(err) { + return err + } + //Create + nodeslice := &v1alpha1.NodeSlicePool{ + TypeMeta: metav1.TypeMeta{ + Kind: "NodeSlicePool", + APIVersion: "whereabouts.cni.cncf.io/v1alpha1", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: getSliceName(ipamConf), + Namespace: namespace, + OwnerReferences: []metav1.OwnerReference{ + *metav1.NewControllerRef(nad, cncfV1.SchemeGroupVersion.WithKind("NetworkAttachmentDefinition")), + }, + }, + // only supports single range with node slice + Spec: v1alpha1.NodeSlicePoolSpec{ + Range: ipamConf.IPRanges[0].Range, + SliceSize: ipamConf.NodeSliceSize, + }, + } + allocations := []v1alpha1.NodeSliceAllocation{} + logger.Info(fmt.Sprintf("node slice: %v\n", nodeslice)) + + //TODO: handle case when full, we could fire an event + subnets, err := iphelpers.DivideRangeBySize(nodeslice.Spec.Range, ipamConf.NodeSliceSize) + if err != nil { + return err + } + logger.Info(fmt.Sprintf("subnets: %v\n", subnets)) + for _, subnet := range subnets { + allocations = append(allocations, v1alpha1.NodeSliceAllocation{ + SliceRange: subnet, + }) + } + nodes, err := c.getNodeList() + if err != nil { + return err + } + for _, node := range nodes { + logger.Info(fmt.Sprintf("assigning node to slice: %v\n", node.Name)) + assignNodeToSlice(allocations, node.Name) + } + nodeslice.Status = v1alpha1.NodeSlicePoolStatus{ + Allocations: allocations, + } + logger.Info(fmt.Sprintf("final allocations: %v\n", allocations)) + _, err = c.whereaboutsclientset.WhereaboutsV1alpha1().NodeSlicePools(namespace).Create(ctx, nodeslice, metav1.CreateOptions{}) + if err != nil { + return err + } + } else { + nodeslice := currentNodeSlicePool.DeepCopy() + // make sure if multiple NADs act on this NodeSlicePool they are all listed as owners + nadIsOwner := false + for _, ownerRef := range nodeslice.OwnerReferences { + if ownerRef.Name == name { + nadIsOwner = true + } + } + if !nadIsOwner { + nodeslice.OwnerReferences = append(nodeslice.OwnerReferences, getAuxiliaryOwnerRef(nad)) + } + logger.Info(fmt.Sprintf("owner references: %v\n", nodeslice.OwnerReferences)) + // node slice currently exists + //TODO: validation that nad configs are compatible between different nads with same network-name + if currentNodeSlicePool.Spec.SliceSize != ipamConf.NodeSliceSize || + currentNodeSlicePool.Spec.Range != ipamConf.IPRanges[0].Range { + logger.Info("network-attachment-definition range or slice size changed, re-allocating node slices") + // slices have changed so redo the slicing and reassign nodes + subnets, err := iphelpers.DivideRangeBySize(ipamConf.Range, ipamConf.NodeSliceSize) + if err != nil { + return err + } + + allocations := []v1alpha1.NodeSliceAllocation{} + for _, subnet := range subnets { + allocations = append(allocations, v1alpha1.NodeSliceAllocation{ + SliceRange: subnet, + }) + } + nodes, err := c.getNodeList() + if err != nil { + return err + } + for _, node := range nodes { + assignNodeToSlice(allocations, node.Name) + } + + //TODO: is it better to use UpdateStatus instead of Update? + nodeslice.Status = v1alpha1.NodeSlicePoolStatus{ + Allocations: allocations, + } + _, err = c.whereaboutsclientset.WhereaboutsV1alpha1().NodeSlicePools(namespace).Update(ctx, nodeslice, metav1.UpdateOptions{}) + if err != nil { + return err + } + } else { + logger.Info("node slice exists and range configuration did not change, ensuring nodes assigned") + //slices have not changed so only make sure all nodes are assigned + allocations := nodeslice.Status.Allocations + nodes, err := c.getNodeList() + if err != nil { + return err + } + for _, node := range nodes { + assignNodeToSlice(allocations, node.Name) + } + removeUnusedNodes(allocations, nodes) + nodeslice.Status.Allocations = allocations + + _, err = c.whereaboutsclientset.WhereaboutsV1alpha1().NodeSlicePools(namespace).Update(context.TODO(), nodeslice, metav1.UpdateOptions{}) + if err != nil { + logger.Info(fmt.Sprintf("Error updating NSP with no changes: %v", err)) + return err + } + } + } + + //TODO: recorder events + //c.recorder.Event(foo, corev1.EventTypeNormal, SuccessSynced, MessageResourceSynced) + return nil +} + +func (c *Controller) getNodeList() ([]*corev1.Node, error) { + nodes, err := c.nodeLister.List(labels.Everything()) + if err != nil { + return nil, err + } + if !c.sortResults { + return nodes, nil + } + sort.Slice(nodes, func(i, j int) bool { + return nodes[i].Name < nodes[j].Name + }) + return nodes, nil +} + +// since multiple NADs can be attached to the same BE Network, we need to make sure their settings match in this case +func (c *Controller) checkForMultiNadMismatch(name, namespace string) error { + nad, err := c.nadLister.NetworkAttachmentDefinitions(namespace).Get(name) + if err != nil { + if !errors.IsNotFound(err) { + return err + } + return nil + } + ipamConf, err := ipamConfiguration(nad, "") + if err != nil { + return err + } + + nadList, err := c.nadLister.List(labels.Everything()) + if err != nil { + return err + } + for _, additionalNad := range nadList { + additionalIpamConf, err := ipamConfiguration(additionalNad, "") + if err != nil { + return err + } + if !checkIpamConfMatch(ipamConf, additionalIpamConf) { + return fmt.Errorf("found IPAM conf mismatch for network-attachment-definitions with same network name") + } + } + return nil +} + +func checkIpamConfMatch(conf1, conf2 *types.IPAMConfig) bool { + if conf1.NetworkName == conf2.NetworkName { + return conf1.IPRanges[0].Range == conf2.IPRanges[0].Range && conf1.NodeSliceSize == conf2.NodeSliceSize + } + return true +} + +func hasOwnerRef(nodeSlice *v1alpha1.NodeSlicePool, name string) bool { + for _, ownerRef := range nodeSlice.OwnerReferences { + if ownerRef.Name == name { + return true + } + } + return false +} + +func getSliceName(ipamConf *types.IPAMConfig) string { + sliceName := ipamConf.Name + if ipamConf.NetworkName != "" { + sliceName = ipamConf.NetworkName + } + return sliceName +} + +// since multiple nads can share a nodeslicepool we need to set multiple owner refs but only +// one controller owner ref +func getAuxiliaryOwnerRef(nad *cncfV1.NetworkAttachmentDefinition) metav1.OwnerReference { + return metav1.OwnerReference{ + APIVersion: nad.APIVersion, + Kind: nad.Kind, + Name: nad.Name, + UID: nad.UID, + } +} + +func removeUnusedNodes(allocations []v1alpha1.NodeSliceAllocation, nodes []*corev1.Node) { + //create map for fast lookup, we only care about keys so use empty struct b/c takes up no memory + nodeMap := make(map[string]struct{}, len(nodes)) + for _, node := range nodes { + nodeMap[node.Name] = struct{}{} + } + for i, allocation := range allocations { + if allocation.NodeName != "" { + if _, ok := nodeMap[allocation.NodeName]; !ok { + allocations[i] = v1alpha1.NodeSliceAllocation{ + SliceRange: allocation.SliceRange, + } + } + } + } +} + +// TODO: this shouldnt depend on localfile only nad +func ipamConfiguration(nad *cncfV1.NetworkAttachmentDefinition, mountPath string) (*types.IPAMConfig, error) { + mounterWhereaboutsConfigFilePath := mountPath + whereaboutsConfigPath + + ipamConfig, err := config.LoadIPAMConfiguration([]byte(nad.Spec.Config), "", mounterWhereaboutsConfigFilePath) + if err != nil { + return nil, err + } + return ipamConfig, nil +} + +func assignNodeToSlice(allocations []v1alpha1.NodeSliceAllocation, nodeName string) { + if nodeHasAllocation(allocations, nodeName) { + return + } + for i, allocation := range allocations { + if allocation.NodeName == "" { + allocations[i] = v1alpha1.NodeSliceAllocation{ + SliceRange: allocation.SliceRange, + NodeName: nodeName, + } + return + } + } +} + +func nodeHasAllocation(allocations []v1alpha1.NodeSliceAllocation, nodeName string) bool { + for _, allocation := range allocations { + if allocation.NodeName == nodeName { + return true + } + } + return false +} diff --git a/pkg/node-controller/controller_test.go b/pkg/node-controller/controller_test.go new file mode 100644 index 000000000..2f8d70d03 --- /dev/null +++ b/pkg/node-controller/controller_test.go @@ -0,0 +1,972 @@ +/* +Copyright 2024 The Kubernetes 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 node_controller + +import ( + "context" + "fmt" + k8snetplumbersv1 "github.com/k8snetworkplumbingwg/network-attachment-definition-client/pkg/apis/k8s.cni.cncf.io/v1" + "github.com/k8snetworkplumbingwg/whereabouts/pkg/api/whereabouts.cni.cncf.io/v1alpha1" + v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime/schema" + "k8s.io/client-go/tools/cache" + "os" + "reflect" + "testing" + "time" + + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/util/diff" + kubeinformers "k8s.io/client-go/informers" + k8sfake "k8s.io/client-go/kubernetes/fake" + core "k8s.io/client-go/testing" + "k8s.io/client-go/tools/record" + + k8snetplumbersv1fake "github.com/k8snetworkplumbingwg/network-attachment-definition-client/pkg/client/clientset/versioned/fake" + nadinformers "github.com/k8snetworkplumbingwg/network-attachment-definition-client/pkg/client/informers/externalversions" + "github.com/k8snetworkplumbingwg/whereabouts/pkg/client/clientset/versioned/fake" + informers "github.com/k8snetworkplumbingwg/whereabouts/pkg/client/informers/externalversions" +) + +var ( + alwaysReady = func() bool { return true } + noResyncPeriodFunc = func() time.Duration { return 0 } +) + +type fixture struct { + t *testing.T + + whereaboutsclient *fake.Clientset + kubeclient *k8sfake.Clientset + nadClient *k8snetplumbersv1fake.Clientset + // Objects to put in the store. + nadLister []*k8snetplumbersv1.NetworkAttachmentDefinition + nodeSlicePoolLister []*v1alpha1.NodeSlicePool + nodeLister []*v1.Node + + // Actions expected to happen on the client. + whereaboutsactions []core.Action + + // Objects from here preloaded into NewSimpleFake. + kubeobjects []runtime.Object + whereaboutsObjects []runtime.Object + nadObjects []runtime.Object +} + +func newFixture(t *testing.T) *fixture { + f := &fixture{} + f.t = t + f.whereaboutsObjects = []runtime.Object{} + f.kubeobjects = []runtime.Object{} + f.nadObjects = []runtime.Object{} + return f +} + +func newNad(name string, networkName string, networkRange string, sliceSize string) *k8snetplumbersv1.NetworkAttachmentDefinition { + return &k8snetplumbersv1.NetworkAttachmentDefinition{ + TypeMeta: metav1.TypeMeta{ + APIVersion: k8snetplumbersv1.SchemeGroupVersion.String(), + Kind: "NetworkAttachmentDefinition", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: metav1.NamespaceDefault, + }, + Spec: k8snetplumbersv1.NetworkAttachmentDefinitionSpec{ + Config: fmt.Sprintf(` + { + "cniVersion": "0.3.1", + "name": "test-name", + "plugins": + [ + { + "type": "macvlan", + "master": "test", + "mode": "bridge", + "mtu": "mtu", + "ipam": + { + "configuration_path": "/tmp/whereabouts.conf", + "type": "whereabouts", + "range": "%s", + "node_slice_size": "%s", + "network_name": "%s", + "enable_overlapping_ranges": false + } + } + ] + }`, networkRange, sliceSize, networkName), + }, + } +} + +func getOwnerRefs(nads []*k8snetplumbersv1.NetworkAttachmentDefinition) []metav1.OwnerReference { + if len(nads) == 1 { + return []metav1.OwnerReference{ + *metav1.NewControllerRef(nads[0], k8snetplumbersv1.SchemeGroupVersion.WithKind("NetworkAttachmentDefinition")), + } + } else if len(nads) > 1 { + refs := []metav1.OwnerReference{ + *metav1.NewControllerRef(nads[0], k8snetplumbersv1.SchemeGroupVersion.WithKind("NetworkAttachmentDefinition")), + } + for i, nad := range nads { + if i == 0 { + continue + } + refs = append(refs, metav1.OwnerReference{ + APIVersion: nad.APIVersion, + Kind: nad.Kind, + Name: nad.Name, + UID: nad.UID, + }) + } + return refs + } + return []metav1.OwnerReference{} +} + +func newNodeSlicePool(name string, rangeSize string, sliceSize string, status v1alpha1.NodeSlicePoolStatus, nad ...*k8snetplumbersv1.NetworkAttachmentDefinition) *v1alpha1.NodeSlicePool { + return &v1alpha1.NodeSlicePool{ + TypeMeta: metav1.TypeMeta{ + APIVersion: v1alpha1.SchemeGroupVersion.String(), + Kind: "NodeSlicePool", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: metav1.NamespaceDefault, + OwnerReferences: getOwnerRefs(nad), + }, + Spec: v1alpha1.NodeSlicePoolSpec{ + Range: rangeSize, + SliceSize: sliceSize, + }, + Status: status, + } +} + +func newNode(name string) *v1.Node { + return &v1.Node{ + TypeMeta: metav1.TypeMeta{ + APIVersion: v1.SchemeGroupVersion.String(), + Kind: "Node", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: name, + Namespace: metav1.NamespaceDefault, + }, + } +} + +func (f *fixture) newController(ctx context.Context) (*Controller, informers.SharedInformerFactory, kubeinformers.SharedInformerFactory, nadinformers.SharedInformerFactory) { + f.whereaboutsclient = fake.NewSimpleClientset(f.whereaboutsObjects...) + f.kubeclient = k8sfake.NewSimpleClientset(f.kubeobjects...) + f.nadClient = k8snetplumbersv1fake.NewSimpleClientset() + // We have to manually Create the resources in the tracker for nad because + // k8s.io/client-go/testing/fixture.go uses meta.UnsafeGuessKindToResource(gvk) to convert gvk to gvr + // this leads to tracker containing resource of 'networkattachmentdefinition' instead of 'network-attachment-definition' + // which causes the informer to trigger deletes because there is no 'network-attachment-definition' + for _, nad := range f.nadObjects { + //TODO: clean way to set GVR + f.nadClient.Tracker().Create(schema.GroupVersionResource{ + Group: "k8s.cni.cncf.io", + Version: "v1", + Resource: "network-attachment-definitions", + }, nad, "default") + } + + whereaboutsInformerFactory := informers.NewSharedInformerFactory(f.whereaboutsclient, noResyncPeriodFunc()) + kubeInformerFactory := kubeinformers.NewSharedInformerFactory(f.kubeclient, noResyncPeriodFunc()) + nadInformerFactory := nadinformers.NewSharedInformerFactory(f.nadClient, noResyncPeriodFunc()) + + c := NewController( + ctx, + f.kubeclient, + f.whereaboutsclient, + f.nadClient, + kubeInformerFactory.Core().V1().Nodes(), + whereaboutsInformerFactory.Whereabouts().V1alpha1().NodeSlicePools(), + whereaboutsInformerFactory.Whereabouts().V1alpha1().IPPools(), + nadInformerFactory.K8sCniCncfIo().V1().NetworkAttachmentDefinitions(), + true) + + //TODO: add sync for IP Pool or remove IP pool if not used + c.nadSynced = alwaysReady + c.nodesSynced = alwaysReady + c.nodeSlicePoolSynced = alwaysReady + c.recorder = &record.FakeRecorder{} + + for _, node := range f.nodeLister { + err := kubeInformerFactory.Core().V1().Nodes().Informer().GetIndexer().Add(node) + if err != nil { + f.t.Error("error adding nodes to informer mock") + } + } + + for _, nad := range f.nadLister { + err := nadInformerFactory.K8sCniCncfIo().V1().NetworkAttachmentDefinitions().Informer().GetIndexer().Add(nad) + if err != nil { + f.t.Error("error adding nads to informer mock") + } + } + + for _, nodeSlicePool := range f.nodeSlicePoolLister { + err := whereaboutsInformerFactory.Whereabouts().V1alpha1().NodeSlicePools().Informer().GetIndexer().Add(nodeSlicePool) + if err != nil { + f.t.Error("error adding nodeslicepools to informer mock") + } + } + + return c, whereaboutsInformerFactory, kubeInformerFactory, nadInformerFactory +} + +func (f *fixture) run(ctx context.Context, name string) { + //requires conf file to run + globalconf := `{ + "datastore": "kubernetes", + "kubernetes": { + "kubeconfig": "/etc/cni/net.d/whereabouts.d/whereabouts.kubeconfig" + }, + "log_file": "/tmp/whereabouts.log", + "log_level": "debug", + "gateway": "192.168.5.5" + }` + + err := os.WriteFile("/tmp/whereabouts.conf", []byte(globalconf), 0755) + if err != nil { + f.t.Error("error writing /tmp/whereabouts.conf") + } + f.runController(ctx, name, true, false) +} + +func (f *fixture) runExpectError(ctx context.Context, name string) { + f.runController(ctx, name, true, true) +} + +func (f *fixture) runController(ctx context.Context, nadName string, startInformers bool, expectError bool) { + c, whereaboutsInformer, kubeInformer, nadInformer := f.newController(ctx) + if startInformers { + whereaboutsInformer.Start(ctx.Done()) + kubeInformer.Start(ctx.Done()) + nadInformer.Start(ctx.Done()) + } + + err := c.syncHandler(ctx, nadName) + if !expectError && err != nil { + f.t.Errorf("error syncing nad: %v", err) + } else if expectError && err == nil { + f.t.Error("expected error syncing nad, got nil") + } + + whereaboutsActions := filterInformerActions(f.whereaboutsclient.Actions()) + for i, action := range whereaboutsActions { + if len(f.whereaboutsactions) < i+1 { + f.t.Errorf("%d unexpected actions: %+v", len(whereaboutsActions)-len(f.whereaboutsactions), whereaboutsActions[i:]) + break + } + + expectedAction := f.whereaboutsactions[i] + checkAction(expectedAction, action, f.t) + } + + if len(f.whereaboutsactions) > len(whereaboutsActions) { + f.t.Errorf("%d additional expected actions:%+v", len(f.whereaboutsactions)-len(whereaboutsActions), f.whereaboutsactions[len(whereaboutsActions):]) + } +} + +// checkAction verifies that expected and actual actions are equal and both have +// same attached resources +func checkAction(expected, actual core.Action, t *testing.T) { + if !(expected.Matches(actual.GetVerb(), actual.GetResource().Resource) && actual.GetSubresource() == expected.GetSubresource()) { + t.Errorf("Expected\n\t%#v\ngot\n\t%#v", expected, actual) + return + } + + if reflect.TypeOf(actual) != reflect.TypeOf(expected) { + t.Errorf("Action has wrong type. Expected: %t. Got: %t", expected, actual) + return + } + + switch a := actual.(type) { + case core.CreateActionImpl: + e, _ := expected.(core.CreateActionImpl) + expObject := e.GetObject() + object := a.GetObject() + + if !reflect.DeepEqual(expObject, object) { + t.Errorf("Action %s %s has wrong object\nDiff:\n %s", + a.GetVerb(), a.GetResource().Resource, diff.ObjectGoPrintSideBySide(expObject, object)) + } + case core.UpdateActionImpl: + e, _ := expected.(core.UpdateActionImpl) + expObject := e.GetObject() + object := a.GetObject() + + if !reflect.DeepEqual(expObject, object) { + t.Errorf("Action %s %s has wrong object\nDiff:\n %s", + a.GetVerb(), a.GetResource().Resource, diff.ObjectGoPrintSideBySide(expObject, object)) + } + case core.PatchActionImpl: + e, _ := expected.(core.PatchActionImpl) + expPatch := e.GetPatch() + patch := a.GetPatch() + + if !reflect.DeepEqual(expPatch, patch) { + t.Errorf("Action %s %s has wrong patch\nDiff:\n %s", + a.GetVerb(), a.GetResource().Resource, diff.ObjectGoPrintSideBySide(expPatch, patch)) + } + case core.DeleteActionImpl: + e, _ := expected.(core.DeleteActionImpl) + expName := e.GetName() + name := a.GetName() + expNamespace := e.GetNamespace() + namespace := a.GetNamespace() + + if expName != name || expNamespace != namespace { + t.Errorf("Action %s %s has wrong namespace or name. Expected %s/%s, actual %s/%s", + a.GetVerb(), a.GetResource().Resource, expNamespace, expName, namespace, name) + } + default: + t.Errorf("Uncaptured Action %s %s, you should explicitly add a case to capture it", + actual.GetVerb(), actual.GetResource().Resource) + } +} + +// filterInformerActions filters list and watch actions for testing resources. +// Since list and watch don't change resource state we can filter it to lower +// nose level in our tests. +func filterInformerActions(actions []core.Action) []core.Action { + ret := []core.Action{} + for _, action := range actions { + if len(action.GetNamespace()) == 0 && + (action.Matches("list", "network-attachment-definitions") || + action.Matches("watch", "network-attachment-definitions") || + action.Matches("list", "nodeslicepools") || + action.Matches("watch", "nodeslicepools") || + action.Matches("list", "nodes") || + action.Matches("watch", "nodes") || + action.Matches("list", "ippools") || + action.Matches("watch", "ippools")) { + continue + } + ret = append(ret, action) + } + + return ret +} + +func (f *fixture) expectNodeSlicePoolCreateAction(nodeSlicePool *v1alpha1.NodeSlicePool) { + f.whereaboutsactions = append(f.whereaboutsactions, core.NewCreateAction(schema.GroupVersionResource{Resource: "nodeslicepools"}, nodeSlicePool.Namespace, nodeSlicePool)) +} + +func (f *fixture) expectNodeSlicePoolUpdateAction(nodeSlicePool *v1alpha1.NodeSlicePool) { + f.whereaboutsactions = append(f.whereaboutsactions, core.NewUpdateAction(schema.GroupVersionResource{Resource: "nodeslicepools"}, nodeSlicePool.Namespace, nodeSlicePool)) +} + +func (f *fixture) expectNodeSlicePoolDeleteAction(nodeSlicePool *v1alpha1.NodeSlicePool) { + f.whereaboutsactions = append(f.whereaboutsactions, core.NewDeleteAction(schema.GroupVersionResource{Resource: "nodeslicepools"}, nodeSlicePool.Namespace, nodeSlicePool.Name)) +} + +// TestCreatesNodeSlicePoolsNoNodes tests nad creation results in a new nodeslicepool being created correctly when no nodes in cluster +func TestCreatesNodeSlicePoolsNoNodes(t *testing.T) { + f := newFixture(t) + nad := newNad("test", "test", "10.0.0.0/8", "/10") + nodeSlicePool := newNodeSlicePool("test", "10.0.0.0/8", "/10", + v1alpha1.NodeSlicePoolStatus{ + Allocations: []v1alpha1.NodeSliceAllocation{ + { + NodeName: "", + SliceRange: "10.0.0.0/10", + }, + { + NodeName: "", + SliceRange: "10.64.0.0/10", + }, + { + NodeName: "", + SliceRange: "10.128.0.0/10", + }, + { + NodeName: "", + SliceRange: "10.192.0.0/10", + }, + }, + }, nad) + + f.nadLister = append(f.nadLister, nad) + f.nadObjects = append(f.nadObjects, nad) + f.expectNodeSlicePoolCreateAction(nodeSlicePool) + + f.run(context.TODO(), getKey(nad, t)) +} + +// TestCreatesNodeSlicePoolsWithNodes tests that a new nad with existing nodes will be result in nodeslicepool created correctly +func TestCreatesNodeSlicePoolsWithNodes(t *testing.T) { + f := newFixture(t) + nad := newNad("test", "test", "10.0.0.0/8", "/10") + node1 := newNode("node1") + node2 := newNode("node2") + nodeSlicePool := newNodeSlicePool("test", "10.0.0.0/8", "/10", + v1alpha1.NodeSlicePoolStatus{ + Allocations: []v1alpha1.NodeSliceAllocation{ + { + NodeName: "node1", + SliceRange: "10.0.0.0/10", + }, + { + NodeName: "node2", + SliceRange: "10.64.0.0/10", + }, + { + NodeName: "", + SliceRange: "10.128.0.0/10", + }, + { + NodeName: "", + SliceRange: "10.192.0.0/10", + }, + }, + }, nad) + + f.nadLister = append(f.nadLister, nad) + f.nodeLister = append(f.nodeLister, node1, node2) + f.kubeobjects = append(f.kubeobjects, node1, node2) + f.nadObjects = append(f.nadObjects, nad) + f.expectNodeSlicePoolCreateAction(nodeSlicePool) + + f.run(context.TODO(), getKey(nad, t)) +} + +// TestDoNothing checks for no action taken when no nad exists +func TestDoNothing(t *testing.T) { + f := newFixture(t) + nad := newNad("test", "test", "10.0.0.0/8", "/10") + node1 := newNode("node1") + node2 := newNode("node2") + f.nodeLister = append(f.nodeLister, node1, node2) + f.kubeobjects = append(f.kubeobjects, node1, node2) + + f.run(context.TODO(), getKey(nad, t)) +} + +// TestNodeJoins test for node addition to nodeslicepool after node is added +func TestNodeJoins(t *testing.T) { + f := newFixture(t) + nad := newNad("test", "test", "10.0.0.0/8", "/10") + node1 := newNode("node1") + nodeSlicePool := newNodeSlicePool("test", "10.0.0.0/8", "/10", + v1alpha1.NodeSlicePoolStatus{ + Allocations: []v1alpha1.NodeSliceAllocation{ + { + NodeName: "", + SliceRange: "10.0.0.0/10", + }, + { + NodeName: "", + SliceRange: "10.64.0.0/10", + }, + { + NodeName: "", + SliceRange: "10.128.0.0/10", + }, + { + NodeName: "", + SliceRange: "10.192.0.0/10", + }, + }, + }, nad) + + expectedNodeSlicePool := newNodeSlicePool("test", "10.0.0.0/8", "/10", + v1alpha1.NodeSlicePoolStatus{ + Allocations: []v1alpha1.NodeSliceAllocation{ + { + NodeName: "node1", + SliceRange: "10.0.0.0/10", + }, + { + NodeName: "", + SliceRange: "10.64.0.0/10", + }, + { + NodeName: "", + SliceRange: "10.128.0.0/10", + }, + { + NodeName: "", + SliceRange: "10.192.0.0/10", + }, + }, + }, nad) + + f.nadLister = append(f.nadLister, nad) + f.nodeSlicePoolLister = append(f.nodeSlicePoolLister, nodeSlicePool) + f.whereaboutsObjects = append(f.whereaboutsObjects, nodeSlicePool) + f.kubeobjects = append(f.kubeobjects, node1) + f.nodeLister = append(f.nodeLister, node1) + f.nadObjects = append(f.nadObjects, nad) + f.expectNodeSlicePoolUpdateAction(expectedNodeSlicePool) + f.run(context.TODO(), getKey(nad, t)) +} + +// TestNodeLeaves tests for node removal from nodeslicepool after the node no longer exists +func TestNodeLeaves(t *testing.T) { + f := newFixture(t) + nad := newNad("test", "test", "10.0.0.0/8", "/10") + nodeSlicePool := newNodeSlicePool("test", "10.0.0.0/8", "/10", + v1alpha1.NodeSlicePoolStatus{ + Allocations: []v1alpha1.NodeSliceAllocation{ + { + NodeName: "node1", + SliceRange: "10.0.0.0/10", + }, + { + NodeName: "", + SliceRange: "10.64.0.0/10", + }, + { + NodeName: "", + SliceRange: "10.128.0.0/10", + }, + { + NodeName: "", + SliceRange: "10.192.0.0/10", + }, + }, + }, nad) + + expectedNodeSlicePool := newNodeSlicePool("test", "10.0.0.0/8", "/10", + v1alpha1.NodeSlicePoolStatus{ + Allocations: []v1alpha1.NodeSliceAllocation{ + { + NodeName: "", + SliceRange: "10.0.0.0/10", + }, + { + NodeName: "", + SliceRange: "10.64.0.0/10", + }, + { + NodeName: "", + SliceRange: "10.128.0.0/10", + }, + { + NodeName: "", + SliceRange: "10.192.0.0/10", + }, + }, + }, nad) + + f.nadLister = append(f.nadLister, nad) + f.nadObjects = append(f.nadObjects, nad) + f.nodeSlicePoolLister = append(f.nodeSlicePoolLister, nodeSlicePool) + f.whereaboutsObjects = append(f.whereaboutsObjects, nodeSlicePool) + f.expectNodeSlicePoolUpdateAction(expectedNodeSlicePool) + f.run(context.TODO(), getKey(nad, t)) +} + +// TestNadDelete tests the deletion of NodeSlicePool after its only owning NAD is deleted +func TestNadDelete(t *testing.T) { + f := newFixture(t) + nad := newNad("test", "test", "10.0.0.0/8", "/10") + node1 := newNode("node1") + node2 := newNode("node2") + nodeSlicePool := newNodeSlicePool("test", "10.0.0.0/8", "/10", + v1alpha1.NodeSlicePoolStatus{ + Allocations: []v1alpha1.NodeSliceAllocation{ + { + NodeName: "node1", + SliceRange: "10.0.0.0/10", + }, + { + NodeName: "node2", + SliceRange: "10.64.0.0/10", + }, + { + NodeName: "", + SliceRange: "10.128.0.0/10", + }, + { + NodeName: "", + SliceRange: "10.192.0.0/10", + }, + }, + }, nad) + + f.nodeLister = append(f.nodeLister, node1, node2) + f.kubeobjects = append(f.kubeobjects, node1, node2) + f.nadObjects = append(f.nadObjects, nad) + f.nodeSlicePoolLister = append(f.nodeSlicePoolLister, nodeSlicePool) + f.whereaboutsObjects = append(f.whereaboutsObjects, nodeSlicePool) + f.expectNodeSlicePoolDeleteAction(nodeSlicePool) + + f.run(context.TODO(), getKey(nad, t)) +} + +// TestUpdateNoImpactfulChange tests for a change to NAD with existing node slice pool where the change does +// not cause a reslicing of the nodeslicepool +func TestUpdateNoImpactfulChange(t *testing.T) { + f := newFixture(t) + nad := newNad("test2", "test", "10.0.0.0/8", "/10") + node1 := newNode("node1") + node2 := newNode("node2") + nodeSlicePool := newNodeSlicePool("test", "10.0.0.0/8", "/10", + v1alpha1.NodeSlicePoolStatus{ + Allocations: []v1alpha1.NodeSliceAllocation{ + { + NodeName: "node1", + SliceRange: "10.0.0.0/10", + }, + { + NodeName: "node2", + SliceRange: "10.64.0.0/10", + }, + { + NodeName: "", + SliceRange: "10.128.0.0/10", + }, + { + NodeName: "", + SliceRange: "10.192.0.0/10", + }, + }, + }, nad) + + f.nodeLister = append(f.nodeLister, node1, node2) + f.kubeobjects = append(f.kubeobjects, node1, node2) + f.nadLister = append(f.nadLister, nad) + f.nadObjects = append(f.nadObjects, nad) + f.nodeSlicePoolLister = append(f.nodeSlicePoolLister, nodeSlicePool) + f.whereaboutsObjects = append(f.whereaboutsObjects, nodeSlicePool) +} + +// TestUpdateRangeChangeAndSliceChange tests update where range and slice changes +func TestUpdateRangeChangeAndSliceChange(t *testing.T) { + f := newFixture(t) + nad := newNad("test", "test", "10.0.0.0/10", "/12") + node1 := newNode("node1") + node2 := newNode("node2") + nodeSlicePool := newNodeSlicePool("test", "10.0.0.0/8", "/10", + v1alpha1.NodeSlicePoolStatus{ + Allocations: []v1alpha1.NodeSliceAllocation{ + { + NodeName: "node1", + SliceRange: "10.0.0.0/10", + }, + { + NodeName: "node2", + SliceRange: "10.64.0.0/10", + }, + { + NodeName: "", + SliceRange: "10.128.0.0/10", + }, + { + NodeName: "", + SliceRange: "10.192.0.0/10", + }, + }, + }, nad) + expectedNodeSlicePool := newNodeSlicePool("test", "10.0.0.0/10", "/12", + v1alpha1.NodeSlicePoolStatus{ + Allocations: []v1alpha1.NodeSliceAllocation{ + { + NodeName: "node1", + SliceRange: "10.0.0.0/12", + }, + { + NodeName: "node2", + SliceRange: "10.16.0.0/12", + }, + { + NodeName: "", + SliceRange: "10.32.0.0/12", + }, + { + NodeName: "", + SliceRange: "10.48.0.0/12", + }, + }, + }, nad) + + f.nodeLister = append(f.nodeLister, node1, node2) + f.kubeobjects = append(f.kubeobjects, node1, node2) + f.nadLister = append(f.nadLister, nad) + f.nadObjects = append(f.nadObjects, nad) + f.nodeSlicePoolLister = append(f.nodeSlicePoolLister, nodeSlicePool) + f.whereaboutsObjects = append(f.whereaboutsObjects, nodeSlicePool) + + f.expectNodeSlicePoolUpdateAction(expectedNodeSlicePool) +} + +// TestUpdateRangeChangeChange tests update where range changes +func TestUpdateRangeChangeChange(t *testing.T) { + f := newFixture(t) + nad := newNad("test", "test", "11.0.0.0/8", "/10") + node1 := newNode("node1") + node2 := newNode("node2") + nodeSlicePool := newNodeSlicePool("test", "10.0.0.0/8", "/10", + v1alpha1.NodeSlicePoolStatus{ + Allocations: []v1alpha1.NodeSliceAllocation{ + { + NodeName: "node1", + SliceRange: "10.0.0.0/10", + }, + { + NodeName: "node2", + SliceRange: "10.64.0.0/10", + }, + { + NodeName: "", + SliceRange: "10.128.0.0/10", + }, + { + NodeName: "", + SliceRange: "10.192.0.0/10", + }, + }, + }, nad) + expectedNodeSlicePool := newNodeSlicePool("test", "11.0.0.0/8", "/10", + v1alpha1.NodeSlicePoolStatus{ + Allocations: []v1alpha1.NodeSliceAllocation{ + { + NodeName: "node1", + SliceRange: "11.0.0.0/10", + }, + { + NodeName: "node2", + SliceRange: "11.64.0.0/10", + }, + { + NodeName: "", + SliceRange: "11.128.0.0/10", + }, + { + NodeName: "", + SliceRange: "11.192.0.0/10", + }, + }, + }, nad) + + f.nodeLister = append(f.nodeLister, node1, node2) + f.kubeobjects = append(f.kubeobjects, node1, node2) + f.nadLister = append(f.nadLister, nad) + f.nadObjects = append(f.nadObjects, nad) + f.nodeSlicePoolLister = append(f.nodeSlicePoolLister, nodeSlicePool) + f.whereaboutsObjects = append(f.whereaboutsObjects, nodeSlicePool) + + f.expectNodeSlicePoolUpdateAction(expectedNodeSlicePool) +} + +// TestUpdateChangeSliceChange tests update where slice changes +func TestUpdateChangeSliceChange(t *testing.T) { + f := newFixture(t) + nad := newNad("test", "test", "10.0.0.0/8", "/11") + node1 := newNode("node1") + node2 := newNode("node2") + nodeSlicePool := newNodeSlicePool("test", "10.0.0.0/8", "/10", + v1alpha1.NodeSlicePoolStatus{ + Allocations: []v1alpha1.NodeSliceAllocation{ + { + NodeName: "node1", + SliceRange: "10.0.0.0/10", + }, + { + NodeName: "node2", + SliceRange: "10.64.0.0/10", + }, + { + NodeName: "", + SliceRange: "10.128.0.0/10", + }, + { + NodeName: "", + SliceRange: "10.192.0.0/10", + }, + }, + }, nad) + expectedNodeSlicePool := newNodeSlicePool("test", "10.0.0.0/8", "/11", + v1alpha1.NodeSlicePoolStatus{ + Allocations: []v1alpha1.NodeSliceAllocation{ + { + NodeName: "node1", + SliceRange: "10.0.0.0/11", + }, + { + NodeName: "node2", + SliceRange: "10.32.0.0/11", + }, + { + NodeName: "", + SliceRange: "10.64.0.0/11", + }, + { + NodeName: "", + SliceRange: "10.96.0.0/11", + }, + { + NodeName: "", + SliceRange: "10.128.0.0/11", + }, + { + NodeName: "", + SliceRange: "10.160.0.0/11", + }, + { + NodeName: "", + SliceRange: "10.192.0.0/11", + }, + { + NodeName: "", + SliceRange: "10.224.0.0/11", + }, + }, + }, nad) + + f.nodeLister = append(f.nodeLister, node1, node2) + f.kubeobjects = append(f.kubeobjects, node1, node2) + f.nadLister = append(f.nadLister, nad) + f.nadObjects = append(f.nadObjects, nad) + f.nodeSlicePoolLister = append(f.nodeSlicePoolLister, nodeSlicePool) + f.whereaboutsObjects = append(f.whereaboutsObjects, nodeSlicePool) + + f.expectNodeSlicePoolUpdateAction(expectedNodeSlicePool) +} + +// TestMultipleNadsSameNetworkName tests that if nad and node slice already exist and new nad with same network name is +// created it appends the new owner ref +func TestMultipleNadsSameNetworkName(t *testing.T) { + f := newFixture(t) + nad1 := newNad("test1", "test", "10.0.0.0/8", "/10") + nad2 := newNad("test2", "test", "10.0.0.0/8", "/10") + node1 := newNode("node1") + node2 := newNode("node2") + nodeSlicePool := newNodeSlicePool("test", "10.0.0.0/8", "/10", + v1alpha1.NodeSlicePoolStatus{ + Allocations: []v1alpha1.NodeSliceAllocation{ + { + NodeName: "node1", + SliceRange: "10.0.0.0/10", + }, + { + NodeName: "node2", + SliceRange: "10.64.0.0/10", + }, + { + NodeName: "", + SliceRange: "10.128.0.0/10", + }, + { + NodeName: "", + SliceRange: "10.192.0.0/10", + }, + }, + }, nad1) + expectedNodeSlicePool := newNodeSlicePool("test", "10.0.0.0/8", "/10", + v1alpha1.NodeSlicePoolStatus{ + Allocations: []v1alpha1.NodeSliceAllocation{ + { + NodeName: "node1", + SliceRange: "10.0.0.0/10", + }, + { + NodeName: "node2", + SliceRange: "10.64.0.0/10", + }, + { + NodeName: "", + SliceRange: "10.128.0.0/10", + }, + { + NodeName: "", + SliceRange: "10.192.0.0/10", + }, + }, + }, nad1, nad2) + f.nadObjects = append(f.nadObjects, nad1, nad2) + f.nadLister = append(f.nadLister, nad1, nad2) + f.kubeobjects = append(f.kubeobjects, node1, node2) + f.nodeLister = append(f.nodeLister, node1, node2) + f.nodeSlicePoolLister = append(f.nodeSlicePoolLister, nodeSlicePool) + f.whereaboutsObjects = append(f.whereaboutsObjects, nodeSlicePool) + + f.expectNodeSlicePoolUpdateAction(expectedNodeSlicePool) + + f.run(context.TODO(), getKey(nad2, t)) +} + +// TestMultipleNadsSameNetworkNameDeleteOneNad tests nothing is done if multiple nads share ownership of nodeslice pool +// and one is deleted +func TestMultipleNadsSameNetworkNameDeleteOneNad(t *testing.T) { + f := newFixture(t) + nad1 := newNad("test1", "test", "10.0.0.0/8", "/10") + nad2 := newNad("test2", "test", "10.0.0.0/8", "/10") + node1 := newNode("node1") + node2 := newNode("node2") + nodeSlicePool := newNodeSlicePool("test", "10.0.0.0/8", "/10", + v1alpha1.NodeSlicePoolStatus{ + Allocations: []v1alpha1.NodeSliceAllocation{ + { + NodeName: "node1", + SliceRange: "10.0.0.0/10", + }, + { + NodeName: "node2", + SliceRange: "10.64.0.0/10", + }, + { + NodeName: "", + SliceRange: "10.128.0.0/10", + }, + { + NodeName: "", + SliceRange: "10.192.0.0/10", + }, + }, + }, nad1, nad2) + f.nadObjects = append(f.nadObjects, nad1) + f.nadLister = append(f.nadLister, nad1) + f.kubeobjects = append(f.kubeobjects, node1, node2) + f.nodeSlicePoolLister = append(f.nodeSlicePoolLister, nodeSlicePool) + f.whereaboutsObjects = append(f.whereaboutsObjects, nodeSlicePool) + f.nodeLister = append(f.nodeLister, node1, node2) + + f.run(context.TODO(), getKey(nad2, t)) +} + +// TestTwoNetworksRangeAndSliceMismatch tests that error is thrown if multiple nads share network name with dif configs +func TestTwoNetworksRangeAndSliceMismatch(t *testing.T) { + f := newFixture(t) + nad1 := newNad("test1", "test", "10.0.0.0/8", "/10") + nad2 := newNad("test2", "test", "10.0.0.0/8", "/8") + node1 := newNode("node1") + node2 := newNode("node2") + f.nadObjects = append(f.nadObjects, nad1, nad2) + f.nadLister = append(f.nadLister, nad1, nad2) + f.kubeobjects = append(f.kubeobjects, node1, node2) + f.nodeLister = append(f.nodeLister, node1, node2) + + f.runExpectError(context.TODO(), getKey(nad2, t)) +} + +func getKey(nad *k8snetplumbersv1.NetworkAttachmentDefinition, t *testing.T) string { + key, err := cache.DeletionHandlingMetaNamespaceKeyFunc(nad) + if err != nil { + t.Errorf("Unexpected error getting key for nad %v: %v", nad.Name, err) + return "" + } + return key +} diff --git a/pkg/node-controller/signals/signals.go b/pkg/node-controller/signals/signals.go new file mode 100644 index 000000000..8991d6a62 --- /dev/null +++ b/pkg/node-controller/signals/signals.go @@ -0,0 +1,28 @@ +package signals + +import ( + "context" + "os" + "os/signal" +) + +var onlyOneSignalHandler = make(chan struct{}) + +// SetupSignalHandler registered for SIGTERM and SIGINT. A context is returned +// which is cancelled on one of these signals. If a second signal is caught, +// the program is terminated with exit code 1. +func SetupSignalHandler() context.Context { + close(onlyOneSignalHandler) // panics when called twice + + c := make(chan os.Signal, 2) + ctx, cancel := context.WithCancel(context.Background()) + signal.Notify(c, shutdownSignals...) + go func() { + <-c + cancel() + <-c + os.Exit(1) // second signal. Exit directly. + }() + + return ctx +} diff --git a/pkg/node-controller/signals/signals_posix.go b/pkg/node-controller/signals/signals_posix.go new file mode 100644 index 000000000..2519e917a --- /dev/null +++ b/pkg/node-controller/signals/signals_posix.go @@ -0,0 +1,8 @@ +package signals + +import ( + "os" + "syscall" +) + +var shutdownSignals = []os.Signal{os.Interrupt, syscall.SIGTERM} diff --git a/pkg/storage/kubernetes/ipam.go b/pkg/storage/kubernetes/ipam.go index 299c3ee58..96cc59d4b 100644 --- a/pkg/storage/kubernetes/ipam.go +++ b/pkg/storage/kubernetes/ipam.go @@ -5,6 +5,7 @@ import ( "encoding/json" "fmt" "net" + "os" "strconv" "strings" "sync" @@ -80,6 +81,7 @@ const UnnamedNetwork string = "" type PoolIdentifier struct { IpRange string NetworkName string + NodeName string } func toIPReservationList(allocations map[string]whereaboutsv1alpha1.IPAllocation, firstip net.IP) []whereaboutstypes.IPReservation { @@ -128,10 +130,20 @@ func (i *KubernetesIPAM) GetIPPool(ctx context.Context, poolIdentifier PoolIdent } func IPPoolName(poolIdentifier PoolIdentifier) string { - if poolIdentifier.NetworkName == UnnamedNetwork { - return normalizeRange(poolIdentifier.IpRange) + if poolIdentifier.NodeName != "" { + // fast node range naming convention + if poolIdentifier.NetworkName == UnnamedNetwork { + return fmt.Sprintf("%v-%v", poolIdentifier.NodeName, normalizeRange(poolIdentifier.IpRange)) + } else { + return fmt.Sprintf("%v-%v-%v", poolIdentifier.NetworkName, poolIdentifier.NodeName, normalizeRange(poolIdentifier.IpRange)) + } } else { - return fmt.Sprintf("%s-%s", poolIdentifier.NetworkName, normalizeRange(poolIdentifier.IpRange)) + // default naming convention + if poolIdentifier.NetworkName == UnnamedNetwork { + return normalizeRange(poolIdentifier.IpRange) + } else { + return fmt.Sprintf("%s-%s", poolIdentifier.NetworkName, normalizeRange(poolIdentifier.IpRange)) + } } } @@ -171,6 +183,17 @@ func (i *KubernetesIPAM) getPool(ctx context.Context, name string, iprange strin } else if err != nil { return nil, fmt.Errorf("k8s get error: %s", err) } + //if pool.Spec.Range != iprange { + // logging.Debugf("got ippool with range %v, but should have range %v, updating", pool.Spec.Range, iprange) + // newPool := pool.DeepCopy() + // newPool.Spec.Range = iprange + // result, err := i.client.WhereaboutsV1alpha1().IPPools(i.namespace).Update(ctxWithTimeout, newPool, metav1.UpdateOptions{}) + // if err != nil { + // logging.Errorf("error updating pool range: %v", err) + // return nil, err + // } + // return result, nil + //} return pool, nil } @@ -343,9 +366,36 @@ func (p *KubernetesIPPool) Update(ctx context.Context, reservations []whereabout return nil } +// TODO: what's the best way to discover the node name? this should work in both controller pod and whereabouts host process +func getNodeName() (string, error) { + envName := os.Getenv("NODENAME") + if envName != "" { + return strings.TrimSpace(envName), nil + } + file, err := os.Open("/etc/hostname") + if err != nil { + logging.Errorf("Error opening file /etc/hostname: %v", err) + return "", err + } + defer file.Close() + + // Read the contents of the file + data := make([]byte, 1024) // Adjust the buffer size as needed + n, err := file.Read(data) + if err != nil { + logging.Errorf("Error reading file /etc/hostname: %v", err) + } + + // Convert bytes to string + hostname := string(data[:n]) + hostname = strings.TrimSpace(hostname) + logging.Debugf("discovered current hostname as: %s", hostname) + return hostname, nil +} + // newLeaderElector creates a new leaderelection.LeaderElector and associated // channels by which to observe elections and depositions. -func newLeaderElector(clientset kubernetes.Interface, namespace string, podNamespace string, podID string, leaseDuration int, renewDeadline int, retryPeriod int) (*leaderelection.LeaderElector, chan struct{}, chan struct{}) { +func newLeaderElector(ctx context.Context, clientset kubernetes.Interface, namespace string, ipamConf *KubernetesIPAM) (*leaderelection.LeaderElector, chan struct{}, chan struct{}) { //log.WithField("context", "leaderelection") // leaderOK will block gRPC startup until it's closed. leaderOK := make(chan struct{}) @@ -353,14 +403,31 @@ func newLeaderElector(clientset kubernetes.Interface, namespace string, podNames // we are deposed as leader so that we can clean up. deposed := make(chan struct{}) + leaseName := "whereabouts" + if ipamConf.Config.NodeSliceSize != "" { + // we lock per IP Pool so just use the pool name for the lease name + hostname, err := getNodeName() + if err != nil { + logging.Errorf("Failed to create leader elector: %v", err) + return nil, leaderOK, deposed + } + nodeSliceRange, err := GetNodeSlicePoolRange(ctx, ipamConf, hostname) + if err != nil { + logging.Errorf("Failed to create leader elector: %v", err) + return nil, leaderOK, deposed + } + leaseName = IPPoolName(PoolIdentifier{IpRange: nodeSliceRange, NodeName: hostname, NetworkName: ipamConf.Config.NetworkName}) + } + logging.Debugf("using lease with name: %v", leaseName) + var rl = &resourcelock.LeaseLock{ LeaseMeta: metav1.ObjectMeta{ - Name: "whereabouts", + Name: leaseName, Namespace: namespace, }, Client: clientset.CoordinationV1(), LockConfig: resourcelock.ResourceLockConfig{ - Identity: fmt.Sprintf("%s/%s", podNamespace, podID), + Identity: fmt.Sprintf("%s/%s", ipamConf.Config.PodNamespace, ipamConf.Config.PodName), }, } @@ -368,9 +435,9 @@ func newLeaderElector(clientset kubernetes.Interface, namespace string, podNames // !bang le, err := leaderelection.NewLeaderElector(leaderelection.LeaderElectionConfig{ Lock: rl, - LeaseDuration: time.Duration(leaseDuration) * time.Millisecond, - RenewDeadline: time.Duration(renewDeadline) * time.Millisecond, - RetryPeriod: time.Duration(retryPeriod) * time.Millisecond, + LeaseDuration: time.Duration(ipamConf.Config.LeaderLeaseDuration) * time.Millisecond, + RenewDeadline: time.Duration(ipamConf.Config.LeaderRenewDeadline) * time.Millisecond, + RetryPeriod: time.Duration(ipamConf.Config.LeaderRetryPeriod) * time.Millisecond, ReleaseOnCancel: true, Callbacks: leaderelection.LeaderCallbacks{ OnStartedLeading: func(_ context.Context) { @@ -401,7 +468,7 @@ func IPManagement(ctx context.Context, mode int, ipamConf whereaboutstypes.IPAMC } // setup leader election - le, leader, deposed := newLeaderElector(client.clientSet, client.namespace, ipamConf.PodNamespace, ipamConf.PodName, ipamConf.LeaderLeaseDuration, ipamConf.LeaderRenewDeadline, ipamConf.LeaderRetryPeriod) + le, leader, deposed := newLeaderElector(ctx, client.clientSet, client.namespace, client) var wg sync.WaitGroup wg.Add(2) @@ -448,18 +515,40 @@ func IPManagement(ctx context.Context, mode int, ipamConf whereaboutstypes.IPAMC leCancel() result <- (<-res) }() - wg.Wait() close(stopM) logging.Debugf("IPManagement: %v, %v", newips, err) return newips, err } +func GetNodeSlicePoolRange(ctx context.Context, ipam *KubernetesIPAM, nodeName string) (string, error) { + logging.Debugf("ipam namespace is %v", ipam.namespace) + nodeSlice, err := ipam.client.WhereaboutsV1alpha1().NodeSlicePools(ipam.Config.Namespace).Get(ctx, getNodeSliceName(ipam), metav1.GetOptions{}) + if err != nil { + logging.Errorf("error getting node slice %s/%s %v", ipam.Config.Namespace, getNodeSliceName(ipam), err) + return "", err + } + for _, allocation := range nodeSlice.Status.Allocations { + if allocation.NodeName == nodeName { + logging.Debugf("found matching node slice allocation for hostname %v: %v", nodeName, allocation) + return allocation.SliceRange, nil + } + } + logging.Errorf("error finding node within node slice allocations") + return "", fmt.Errorf("no allocated node slice for node") +} + +func getNodeSliceName(ipam *KubernetesIPAM) string { + if ipam.Config.NetworkName == UnnamedNetwork { + return ipam.Config.Name + } + return ipam.Config.NetworkName +} + // IPManagementKubernetesUpdate manages k8s updates func IPManagementKubernetesUpdate(ctx context.Context, mode int, ipam *KubernetesIPAM, ipamConf whereaboutstypes.IPAMConfig, containerID string, podRef string) ([]net.IPNet, error) { logging.Debugf("IPManagement -- mode: %v / containerID: %v / podRef: %v", mode, containerID, podRef) - var newips []net.IPNet var newip net.IPNet // Skip invalid modes @@ -494,14 +583,47 @@ func IPManagementKubernetesUpdate(ctx context.Context, mode int, ipam *Kubernete default: // retry the IPAM loop if the context has not been cancelled } - overlappingrangestore, err = ipam.GetOverlappingRangeStore() if err != nil { logging.Errorf("IPAM error getting OverlappingRangeStore: %v", err) return newips, err } - - pool, err = ipam.GetIPPool(requestCtx, PoolIdentifier{IpRange: ipRange.Range, NetworkName: ipamConf.NetworkName}) + poolIdentifier := PoolIdentifier{IpRange: ipRange.Range, NetworkName: ipamConf.NetworkName} + if ipamConf.NodeSliceSize != "" { + hostname, err := getNodeName() + if err != nil { + logging.Errorf("Failed to get node hostname: %v", err) + return newips, err + } + poolIdentifier.NodeName = hostname + nodeSliceRange, err := GetNodeSlicePoolRange(ctx, ipam, hostname) + if err != nil { + return newips, err + } + _, ipNet, err := net.ParseCIDR(nodeSliceRange) + if err != nil { + logging.Errorf("Error parsing node slice cidr to net.IPNet: %v", err) + return newips, err + } + poolIdentifier.IpRange = nodeSliceRange + rangeStart, err := iphelpers.FirstUsableIP(*ipNet) + if err != nil { + logging.Errorf("Error parsing node slice cidr to range start: %v", err) + return newips, err + } + rangeEnd, err := iphelpers.LastUsableIP(*ipNet) + if err != nil { + logging.Errorf("Error parsing node slice cidr to range start: %v", err) + return newips, err + } + ipRange = whereaboutstypes.RangeConfiguration{ + Range: nodeSliceRange, + RangeStart: rangeStart, + RangeEnd: rangeEnd, + } + } + logging.Debugf("using pool identifier: %v", poolIdentifier) + pool, err = ipam.GetIPPool(requestCtx, poolIdentifier) if err != nil { logging.Errorf("IPAM error reading pool allocations (attempt: %d): %v", j, err) if e, ok := err.(storage.Temporary); ok && e.Temporary() { diff --git a/pkg/storage/kubernetes/ipam_test.go b/pkg/storage/kubernetes/ipam_test.go new file mode 100644 index 000000000..66f62e03f --- /dev/null +++ b/pkg/storage/kubernetes/ipam_test.go @@ -0,0 +1,54 @@ +package kubernetes + +import "testing" + +func TestIPPoolName(t *testing.T) { + cases := []struct { + name string + poolIdentifier PoolIdentifier + expectedResult string + }{ + { + name: "No node name, unnamed network", + poolIdentifier: PoolIdentifier{ + NetworkName: UnnamedNetwork, + IpRange: "10.0.0.0/8", + }, + expectedResult: "10.0.0.0-8", + }, + { + name: "No node name, named network", + poolIdentifier: PoolIdentifier{ + NetworkName: "test", + IpRange: "10.0.0.0/8", + }, + expectedResult: "test-10.0.0.0-8", + }, + { + name: "Node name, unnamed network", + poolIdentifier: PoolIdentifier{ + NetworkName: UnnamedNetwork, + NodeName: "testnode", + IpRange: "10.0.0.0/8", + }, + expectedResult: "testnode-10.0.0.0-8", + }, + { + name: "Node name, named network", + poolIdentifier: PoolIdentifier{ + NetworkName: "testnetwork", + NodeName: "testnode", + IpRange: "10.0.0.0/8", + }, + expectedResult: "testnetwork-testnode-10.0.0.0-8", + }, + } + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + result := IPPoolName(tc.poolIdentifier) + if result != tc.expectedResult { + t.Errorf("Expected result: %s, got result: %s", tc.expectedResult, result) + } + }) + } +} diff --git a/pkg/types/types.go b/pkg/types/types.go index 519a094a5..515671207 100644 --- a/pkg/types/types.go +++ b/pkg/types/types.go @@ -54,6 +54,8 @@ type IPAMConfig struct { OmitRanges []string `json:"exclude,omitempty"` DNS cnitypes.DNS `json:"dns"` Range string `json:"range"` + NodeSliceSize string `json:"node_slice_size"` + Namespace string `json:"namespace"` //TODO: best way to get namespace of the NAD? RangeStart net.IP `json:"range_start,omitempty"` RangeEnd net.IP `json:"range_end,omitempty"` GatewayStr string `json:"gateway"` @@ -81,6 +83,8 @@ func (ic *IPAMConfig) UnmarshalJSON(data []byte) error { Datastore string `json:"datastore"` Addresses []Address `json:"addresses,omitempty"` IPRanges []RangeConfiguration `json:"ipRanges"` + NodeSliceSize string `json:"node_slice_size"` + Namespace string `json:"namespace"` //TODO: best way to get namespace of the NAD? OmitRanges []string `json:"exclude,omitempty"` DNS cnitypes.DNS `json:"dns"` Range string `json:"range"` @@ -126,8 +130,10 @@ func (ic *IPAMConfig) UnmarshalJSON(data []byte) error { OmitRanges: ipamConfigAlias.OmitRanges, DNS: ipamConfigAlias.DNS, Range: ipamConfigAlias.Range, + Namespace: ipamConfigAlias.Namespace, RangeStart: backwardsCompatibleIPAddress(ipamConfigAlias.RangeStart), RangeEnd: backwardsCompatibleIPAddress(ipamConfigAlias.RangeEnd), + NodeSliceSize: ipamConfigAlias.NodeSliceSize, GatewayStr: ipamConfigAlias.GatewayStr, LeaderLeaseDuration: ipamConfigAlias.LeaderLeaseDuration, LeaderRenewDeadline: ipamConfigAlias.LeaderRenewDeadline, diff --git a/temp b/temp new file mode 100644 index 000000000..0cf98cbcb --- /dev/null +++ b/temp @@ -0,0 +1,8213 @@ +apiVersion: whereabouts.cni.cncf.io/v1alpha1 +kind: NodeSlicePool +metadata: + creationTimestamp: "2024-05-13T18:19:48Z" + generation: 1 + name: wa-nad + namespace: default + ownerReferences: + - apiVersion: k8s.cni.cncf.io/v1 + blockOwnerDeletion: true + controller: true + kind: NetworkAttachmentDefinition + name: wa-nad + uid: c52ea002-198e-4c32-9055-f721fcf4ec0b + resourceVersion: "93488" + uid: cc556f93-c38c-4819-9c46-fb45e42b1f4b +spec: + range: 10.0.0.0/8 + sliceSize: /20 +status: + allocations: + - nodeName: kind-worker + sliceRange: 10.0.0.0/20 + - nodeName: kind-worker7 + sliceRange: 10.0.16.0/20 + - nodeName: kind-control-plane + sliceRange: 10.0.32.0/20 + - nodeName: kind-worker10 + sliceRange: 10.0.48.0/20 + - nodeName: kind-worker11 + sliceRange: 10.0.64.0/20 + - nodeName: kind-worker13 + sliceRange: 10.0.80.0/20 + - nodeName: kind-worker14 + sliceRange: 10.0.96.0/20 + - nodeName: kind-worker2 + sliceRange: 10.0.112.0/20 + - nodeName: kind-worker3 + sliceRange: 10.0.128.0/20 + - nodeName: kind-worker5 + sliceRange: 10.0.144.0/20 + - nodeName: kind-worker6 + sliceRange: 10.0.160.0/20 + - nodeName: kind-worker8 + sliceRange: 10.0.176.0/20 + - nodeName: kind-worker9 + sliceRange: 10.0.192.0/20 + - nodeName: kind-worker12 + sliceRange: 10.0.208.0/20 + - nodeName: kind-worker15 + sliceRange: 10.0.224.0/20 + - nodeName: kind-worker16 + sliceRange: 10.0.240.0/20 + - nodeName: kind-worker4 + sliceRange: 10.1.0.0/20 + - nodeName: "" + sliceRange: 10.1.16.0/20 + - nodeName: "" + sliceRange: 10.1.32.0/20 + - nodeName: "" + sliceRange: 10.1.48.0/20 + - nodeName: "" + sliceRange: 10.1.64.0/20 + - nodeName: "" + sliceRange: 10.1.80.0/20 + - nodeName: "" + sliceRange: 10.1.96.0/20 + - nodeName: "" + sliceRange: 10.1.112.0/20 + - nodeName: "" + sliceRange: 10.1.128.0/20 + - nodeName: "" + sliceRange: 10.1.144.0/20 + - nodeName: "" + sliceRange: 10.1.160.0/20 + - nodeName: "" + sliceRange: 10.1.176.0/20 + - nodeName: "" + sliceRange: 10.1.192.0/20 + - nodeName: "" + sliceRange: 10.1.208.0/20 + - nodeName: "" + sliceRange: 10.1.224.0/20 + - nodeName: "" + sliceRange: 10.1.240.0/20 + - nodeName: "" + sliceRange: 10.2.0.0/20 + - nodeName: "" + sliceRange: 10.2.16.0/20 + - nodeName: "" + sliceRange: 10.2.32.0/20 + - nodeName: "" + sliceRange: 10.2.48.0/20 + - nodeName: "" + sliceRange: 10.2.64.0/20 + - nodeName: "" + sliceRange: 10.2.80.0/20 + - nodeName: "" + sliceRange: 10.2.96.0/20 + - nodeName: "" + sliceRange: 10.2.112.0/20 + - nodeName: "" + sliceRange: 10.2.128.0/20 + - nodeName: "" + sliceRange: 10.2.144.0/20 + - nodeName: "" + sliceRange: 10.2.160.0/20 + - nodeName: "" + sliceRange: 10.2.176.0/20 + - nodeName: "" + sliceRange: 10.2.192.0/20 + - nodeName: "" + sliceRange: 10.2.208.0/20 + - nodeName: "" + sliceRange: 10.2.224.0/20 + - nodeName: "" + sliceRange: 10.2.240.0/20 + - nodeName: "" + sliceRange: 10.3.0.0/20 + - nodeName: "" + sliceRange: 10.3.16.0/20 + - nodeName: "" + sliceRange: 10.3.32.0/20 + - nodeName: "" + sliceRange: 10.3.48.0/20 + - nodeName: "" + sliceRange: 10.3.64.0/20 + - nodeName: "" + sliceRange: 10.3.80.0/20 + - nodeName: "" + sliceRange: 10.3.96.0/20 + - nodeName: "" + sliceRange: 10.3.112.0/20 + - nodeName: "" + sliceRange: 10.3.128.0/20 + - nodeName: "" + sliceRange: 10.3.144.0/20 + - nodeName: "" + sliceRange: 10.3.160.0/20 + - nodeName: "" + sliceRange: 10.3.176.0/20 + - nodeName: "" + sliceRange: 10.3.192.0/20 + - nodeName: "" + sliceRange: 10.3.208.0/20 + - nodeName: "" + sliceRange: 10.3.224.0/20 + - nodeName: "" + sliceRange: 10.3.240.0/20 + - nodeName: "" + sliceRange: 10.4.0.0/20 + - nodeName: "" + sliceRange: 10.4.16.0/20 + - nodeName: "" + sliceRange: 10.4.32.0/20 + - nodeName: "" + sliceRange: 10.4.48.0/20 + - nodeName: "" + sliceRange: 10.4.64.0/20 + - nodeName: "" + sliceRange: 10.4.80.0/20 + - nodeName: "" + sliceRange: 10.4.96.0/20 + - nodeName: "" + sliceRange: 10.4.112.0/20 + - nodeName: "" + sliceRange: 10.4.128.0/20 + - nodeName: "" + sliceRange: 10.4.144.0/20 + - nodeName: "" + sliceRange: 10.4.160.0/20 + - nodeName: "" + sliceRange: 10.4.176.0/20 + - nodeName: "" + sliceRange: 10.4.192.0/20 + - nodeName: "" + sliceRange: 10.4.208.0/20 + - nodeName: "" + sliceRange: 10.4.224.0/20 + - nodeName: "" + sliceRange: 10.4.240.0/20 + - nodeName: "" + sliceRange: 10.5.0.0/20 + - nodeName: "" + sliceRange: 10.5.16.0/20 + - nodeName: "" + sliceRange: 10.5.32.0/20 + - nodeName: "" + sliceRange: 10.5.48.0/20 + - nodeName: "" + sliceRange: 10.5.64.0/20 + - nodeName: "" + sliceRange: 10.5.80.0/20 + - nodeName: "" + sliceRange: 10.5.96.0/20 + - nodeName: "" + sliceRange: 10.5.112.0/20 + - nodeName: "" + sliceRange: 10.5.128.0/20 + - nodeName: "" + sliceRange: 10.5.144.0/20 + - nodeName: "" + sliceRange: 10.5.160.0/20 + - nodeName: "" + sliceRange: 10.5.176.0/20 + - nodeName: "" + sliceRange: 10.5.192.0/20 + - nodeName: "" + sliceRange: 10.5.208.0/20 + - nodeName: "" + sliceRange: 10.5.224.0/20 + - nodeName: "" + sliceRange: 10.5.240.0/20 + - nodeName: "" + sliceRange: 10.6.0.0/20 + - nodeName: "" + sliceRange: 10.6.16.0/20 + - nodeName: "" + sliceRange: 10.6.32.0/20 + - nodeName: "" + sliceRange: 10.6.48.0/20 + - nodeName: "" + sliceRange: 10.6.64.0/20 + - nodeName: "" + sliceRange: 10.6.80.0/20 + - nodeName: "" + sliceRange: 10.6.96.0/20 + - nodeName: "" + sliceRange: 10.6.112.0/20 + - nodeName: "" + sliceRange: 10.6.128.0/20 + - nodeName: "" + sliceRange: 10.6.144.0/20 + - nodeName: "" + sliceRange: 10.6.160.0/20 + - nodeName: "" + sliceRange: 10.6.176.0/20 + - nodeName: "" + sliceRange: 10.6.192.0/20 + - nodeName: "" + sliceRange: 10.6.208.0/20 + - nodeName: "" + sliceRange: 10.6.224.0/20 + - nodeName: "" + sliceRange: 10.6.240.0/20 + - nodeName: "" + sliceRange: 10.7.0.0/20 + - nodeName: "" + sliceRange: 10.7.16.0/20 + - nodeName: "" + sliceRange: 10.7.32.0/20 + - nodeName: "" + sliceRange: 10.7.48.0/20 + - nodeName: "" + sliceRange: 10.7.64.0/20 + - nodeName: "" + sliceRange: 10.7.80.0/20 + - nodeName: "" + sliceRange: 10.7.96.0/20 + - nodeName: "" + sliceRange: 10.7.112.0/20 + - nodeName: "" + sliceRange: 10.7.128.0/20 + - nodeName: "" + sliceRange: 10.7.144.0/20 + - nodeName: "" + sliceRange: 10.7.160.0/20 + - nodeName: "" + sliceRange: 10.7.176.0/20 + - nodeName: "" + sliceRange: 10.7.192.0/20 + - nodeName: "" + sliceRange: 10.7.208.0/20 + - nodeName: "" + sliceRange: 10.7.224.0/20 + - nodeName: "" + sliceRange: 10.7.240.0/20 + - nodeName: "" + sliceRange: 10.8.0.0/20 + - nodeName: "" + sliceRange: 10.8.16.0/20 + - nodeName: "" + sliceRange: 10.8.32.0/20 + - nodeName: "" + sliceRange: 10.8.48.0/20 + - nodeName: "" + sliceRange: 10.8.64.0/20 + - nodeName: "" + sliceRange: 10.8.80.0/20 + - nodeName: "" + sliceRange: 10.8.96.0/20 + - nodeName: "" + sliceRange: 10.8.112.0/20 + - nodeName: "" + sliceRange: 10.8.128.0/20 + - nodeName: "" + sliceRange: 10.8.144.0/20 + - nodeName: "" + sliceRange: 10.8.160.0/20 + - nodeName: "" + sliceRange: 10.8.176.0/20 + - nodeName: "" + sliceRange: 10.8.192.0/20 + - nodeName: "" + sliceRange: 10.8.208.0/20 + - nodeName: "" + sliceRange: 10.8.224.0/20 + - nodeName: "" + sliceRange: 10.8.240.0/20 + - nodeName: "" + sliceRange: 10.9.0.0/20 + - nodeName: "" + sliceRange: 10.9.16.0/20 + - nodeName: "" + sliceRange: 10.9.32.0/20 + - nodeName: "" + sliceRange: 10.9.48.0/20 + - nodeName: "" + sliceRange: 10.9.64.0/20 + - nodeName: "" + sliceRange: 10.9.80.0/20 + - nodeName: "" + sliceRange: 10.9.96.0/20 + - nodeName: "" + sliceRange: 10.9.112.0/20 + - nodeName: "" + sliceRange: 10.9.128.0/20 + - nodeName: "" + sliceRange: 10.9.144.0/20 + - nodeName: "" + sliceRange: 10.9.160.0/20 + - nodeName: "" + sliceRange: 10.9.176.0/20 + - nodeName: "" + sliceRange: 10.9.192.0/20 + - nodeName: "" + sliceRange: 10.9.208.0/20 + - nodeName: "" + sliceRange: 10.9.224.0/20 + - nodeName: "" + sliceRange: 10.9.240.0/20 + - nodeName: "" + sliceRange: 10.10.0.0/20 + - nodeName: "" + sliceRange: 10.10.16.0/20 + - nodeName: "" + sliceRange: 10.10.32.0/20 + - nodeName: "" + sliceRange: 10.10.48.0/20 + - nodeName: "" + sliceRange: 10.10.64.0/20 + - nodeName: "" + sliceRange: 10.10.80.0/20 + - nodeName: "" + sliceRange: 10.10.96.0/20 + - nodeName: "" + sliceRange: 10.10.112.0/20 + - nodeName: "" + sliceRange: 10.10.128.0/20 + - nodeName: "" + sliceRange: 10.10.144.0/20 + - nodeName: "" + sliceRange: 10.10.160.0/20 + - nodeName: "" + sliceRange: 10.10.176.0/20 + - nodeName: "" + sliceRange: 10.10.192.0/20 + - nodeName: "" + sliceRange: 10.10.208.0/20 + - nodeName: "" + sliceRange: 10.10.224.0/20 + - nodeName: "" + sliceRange: 10.10.240.0/20 + - nodeName: "" + sliceRange: 10.11.0.0/20 + - nodeName: "" + sliceRange: 10.11.16.0/20 + - nodeName: "" + sliceRange: 10.11.32.0/20 + - nodeName: "" + sliceRange: 10.11.48.0/20 + - nodeName: "" + sliceRange: 10.11.64.0/20 + - nodeName: "" + sliceRange: 10.11.80.0/20 + - nodeName: "" + sliceRange: 10.11.96.0/20 + - nodeName: "" + sliceRange: 10.11.112.0/20 + - nodeName: "" + sliceRange: 10.11.128.0/20 + - nodeName: "" + sliceRange: 10.11.144.0/20 + - nodeName: "" + sliceRange: 10.11.160.0/20 + - nodeName: "" + sliceRange: 10.11.176.0/20 + - nodeName: "" + sliceRange: 10.11.192.0/20 + - nodeName: "" + sliceRange: 10.11.208.0/20 + - nodeName: "" + sliceRange: 10.11.224.0/20 + - nodeName: "" + sliceRange: 10.11.240.0/20 + - nodeName: "" + sliceRange: 10.12.0.0/20 + - nodeName: "" + sliceRange: 10.12.16.0/20 + - nodeName: "" + sliceRange: 10.12.32.0/20 + - nodeName: "" + sliceRange: 10.12.48.0/20 + - nodeName: "" + sliceRange: 10.12.64.0/20 + - nodeName: "" + sliceRange: 10.12.80.0/20 + - nodeName: "" + sliceRange: 10.12.96.0/20 + - nodeName: "" + sliceRange: 10.12.112.0/20 + - nodeName: "" + sliceRange: 10.12.128.0/20 + - nodeName: "" + sliceRange: 10.12.144.0/20 + - nodeName: "" + sliceRange: 10.12.160.0/20 + - nodeName: "" + sliceRange: 10.12.176.0/20 + - nodeName: "" + sliceRange: 10.12.192.0/20 + - nodeName: "" + sliceRange: 10.12.208.0/20 + - nodeName: "" + sliceRange: 10.12.224.0/20 + - nodeName: "" + sliceRange: 10.12.240.0/20 + - nodeName: "" + sliceRange: 10.13.0.0/20 + - nodeName: "" + sliceRange: 10.13.16.0/20 + - nodeName: "" + sliceRange: 10.13.32.0/20 + - nodeName: "" + sliceRange: 10.13.48.0/20 + - nodeName: "" + sliceRange: 10.13.64.0/20 + - nodeName: "" + sliceRange: 10.13.80.0/20 + - nodeName: "" + sliceRange: 10.13.96.0/20 + - nodeName: "" + sliceRange: 10.13.112.0/20 + - nodeName: "" + sliceRange: 10.13.128.0/20 + - nodeName: "" + sliceRange: 10.13.144.0/20 + - nodeName: "" + sliceRange: 10.13.160.0/20 + - nodeName: "" + sliceRange: 10.13.176.0/20 + - nodeName: "" + sliceRange: 10.13.192.0/20 + - nodeName: "" + sliceRange: 10.13.208.0/20 + - nodeName: "" + sliceRange: 10.13.224.0/20 + - nodeName: "" + sliceRange: 10.13.240.0/20 + - nodeName: "" + sliceRange: 10.14.0.0/20 + - nodeName: "" + sliceRange: 10.14.16.0/20 + - nodeName: "" + sliceRange: 10.14.32.0/20 + - nodeName: "" + sliceRange: 10.14.48.0/20 + - nodeName: "" + sliceRange: 10.14.64.0/20 + - nodeName: "" + sliceRange: 10.14.80.0/20 + - nodeName: "" + sliceRange: 10.14.96.0/20 + - nodeName: "" + sliceRange: 10.14.112.0/20 + - nodeName: "" + sliceRange: 10.14.128.0/20 + - nodeName: "" + sliceRange: 10.14.144.0/20 + - nodeName: "" + sliceRange: 10.14.160.0/20 + - nodeName: "" + sliceRange: 10.14.176.0/20 + - nodeName: "" + sliceRange: 10.14.192.0/20 + - nodeName: "" + sliceRange: 10.14.208.0/20 + - nodeName: "" + sliceRange: 10.14.224.0/20 + - nodeName: "" + sliceRange: 10.14.240.0/20 + - nodeName: "" + sliceRange: 10.15.0.0/20 + - nodeName: "" + sliceRange: 10.15.16.0/20 + - nodeName: "" + sliceRange: 10.15.32.0/20 + - nodeName: "" + sliceRange: 10.15.48.0/20 + - nodeName: "" + sliceRange: 10.15.64.0/20 + - nodeName: "" + sliceRange: 10.15.80.0/20 + - nodeName: "" + sliceRange: 10.15.96.0/20 + - nodeName: "" + sliceRange: 10.15.112.0/20 + - nodeName: "" + sliceRange: 10.15.128.0/20 + - nodeName: "" + sliceRange: 10.15.144.0/20 + - nodeName: "" + sliceRange: 10.15.160.0/20 + - nodeName: "" + sliceRange: 10.15.176.0/20 + - nodeName: "" + sliceRange: 10.15.192.0/20 + - nodeName: "" + sliceRange: 10.15.208.0/20 + - nodeName: "" + sliceRange: 10.15.224.0/20 + - nodeName: "" + sliceRange: 10.15.240.0/20 + - nodeName: "" + sliceRange: 10.16.0.0/20 + - nodeName: "" + sliceRange: 10.16.16.0/20 + - nodeName: "" + sliceRange: 10.16.32.0/20 + - nodeName: "" + sliceRange: 10.16.48.0/20 + - nodeName: "" + sliceRange: 10.16.64.0/20 + - nodeName: "" + sliceRange: 10.16.80.0/20 + - nodeName: "" + sliceRange: 10.16.96.0/20 + - nodeName: "" + sliceRange: 10.16.112.0/20 + - nodeName: "" + sliceRange: 10.16.128.0/20 + - nodeName: "" + sliceRange: 10.16.144.0/20 + - nodeName: "" + sliceRange: 10.16.160.0/20 + - nodeName: "" + sliceRange: 10.16.176.0/20 + - nodeName: "" + sliceRange: 10.16.192.0/20 + - nodeName: "" + sliceRange: 10.16.208.0/20 + - nodeName: "" + sliceRange: 10.16.224.0/20 + - nodeName: "" + sliceRange: 10.16.240.0/20 + - nodeName: "" + sliceRange: 10.17.0.0/20 + - nodeName: "" + sliceRange: 10.17.16.0/20 + - nodeName: "" + sliceRange: 10.17.32.0/20 + - nodeName: "" + sliceRange: 10.17.48.0/20 + - nodeName: "" + sliceRange: 10.17.64.0/20 + - nodeName: "" + sliceRange: 10.17.80.0/20 + - nodeName: "" + sliceRange: 10.17.96.0/20 + - nodeName: "" + sliceRange: 10.17.112.0/20 + - nodeName: "" + sliceRange: 10.17.128.0/20 + - nodeName: "" + sliceRange: 10.17.144.0/20 + - nodeName: "" + sliceRange: 10.17.160.0/20 + - nodeName: "" + sliceRange: 10.17.176.0/20 + - nodeName: "" + sliceRange: 10.17.192.0/20 + - nodeName: "" + sliceRange: 10.17.208.0/20 + - nodeName: "" + sliceRange: 10.17.224.0/20 + - nodeName: "" + sliceRange: 10.17.240.0/20 + - nodeName: "" + sliceRange: 10.18.0.0/20 + - nodeName: "" + sliceRange: 10.18.16.0/20 + - nodeName: "" + sliceRange: 10.18.32.0/20 + - nodeName: "" + sliceRange: 10.18.48.0/20 + - nodeName: "" + sliceRange: 10.18.64.0/20 + - nodeName: "" + sliceRange: 10.18.80.0/20 + - nodeName: "" + sliceRange: 10.18.96.0/20 + - nodeName: "" + sliceRange: 10.18.112.0/20 + - nodeName: "" + sliceRange: 10.18.128.0/20 + - nodeName: "" + sliceRange: 10.18.144.0/20 + - nodeName: "" + sliceRange: 10.18.160.0/20 + - nodeName: "" + sliceRange: 10.18.176.0/20 + - nodeName: "" + sliceRange: 10.18.192.0/20 + - nodeName: "" + sliceRange: 10.18.208.0/20 + - nodeName: "" + sliceRange: 10.18.224.0/20 + - nodeName: "" + sliceRange: 10.18.240.0/20 + - nodeName: "" + sliceRange: 10.19.0.0/20 + - nodeName: "" + sliceRange: 10.19.16.0/20 + - nodeName: "" + sliceRange: 10.19.32.0/20 + - nodeName: "" + sliceRange: 10.19.48.0/20 + - nodeName: "" + sliceRange: 10.19.64.0/20 + - nodeName: "" + sliceRange: 10.19.80.0/20 + - nodeName: "" + sliceRange: 10.19.96.0/20 + - nodeName: "" + sliceRange: 10.19.112.0/20 + - nodeName: "" + sliceRange: 10.19.128.0/20 + - nodeName: "" + sliceRange: 10.19.144.0/20 + - nodeName: "" + sliceRange: 10.19.160.0/20 + - nodeName: "" + sliceRange: 10.19.176.0/20 + - nodeName: "" + sliceRange: 10.19.192.0/20 + - nodeName: "" + sliceRange: 10.19.208.0/20 + - nodeName: "" + sliceRange: 10.19.224.0/20 + - nodeName: "" + sliceRange: 10.19.240.0/20 + - nodeName: "" + sliceRange: 10.20.0.0/20 + - nodeName: "" + sliceRange: 10.20.16.0/20 + - nodeName: "" + sliceRange: 10.20.32.0/20 + - nodeName: "" + sliceRange: 10.20.48.0/20 + - nodeName: "" + sliceRange: 10.20.64.0/20 + - nodeName: "" + sliceRange: 10.20.80.0/20 + - nodeName: "" + sliceRange: 10.20.96.0/20 + - nodeName: "" + sliceRange: 10.20.112.0/20 + - nodeName: "" + sliceRange: 10.20.128.0/20 + - nodeName: "" + sliceRange: 10.20.144.0/20 + - nodeName: "" + sliceRange: 10.20.160.0/20 + - nodeName: "" + sliceRange: 10.20.176.0/20 + - nodeName: "" + sliceRange: 10.20.192.0/20 + - nodeName: "" + sliceRange: 10.20.208.0/20 + - nodeName: "" + sliceRange: 10.20.224.0/20 + - nodeName: "" + sliceRange: 10.20.240.0/20 + - nodeName: "" + sliceRange: 10.21.0.0/20 + - nodeName: "" + sliceRange: 10.21.16.0/20 + - nodeName: "" + sliceRange: 10.21.32.0/20 + - nodeName: "" + sliceRange: 10.21.48.0/20 + - nodeName: "" + sliceRange: 10.21.64.0/20 + - nodeName: "" + sliceRange: 10.21.80.0/20 + - nodeName: "" + sliceRange: 10.21.96.0/20 + - nodeName: "" + sliceRange: 10.21.112.0/20 + - nodeName: "" + sliceRange: 10.21.128.0/20 + - nodeName: "" + sliceRange: 10.21.144.0/20 + - nodeName: "" + sliceRange: 10.21.160.0/20 + - nodeName: "" + sliceRange: 10.21.176.0/20 + - nodeName: "" + sliceRange: 10.21.192.0/20 + - nodeName: "" + sliceRange: 10.21.208.0/20 + - nodeName: "" + sliceRange: 10.21.224.0/20 + - nodeName: "" + sliceRange: 10.21.240.0/20 + - nodeName: "" + sliceRange: 10.22.0.0/20 + - nodeName: "" + sliceRange: 10.22.16.0/20 + - nodeName: "" + sliceRange: 10.22.32.0/20 + - nodeName: "" + sliceRange: 10.22.48.0/20 + - nodeName: "" + sliceRange: 10.22.64.0/20 + - nodeName: "" + sliceRange: 10.22.80.0/20 + - nodeName: "" + sliceRange: 10.22.96.0/20 + - nodeName: "" + sliceRange: 10.22.112.0/20 + - nodeName: "" + sliceRange: 10.22.128.0/20 + - nodeName: "" + sliceRange: 10.22.144.0/20 + - nodeName: "" + sliceRange: 10.22.160.0/20 + - nodeName: "" + sliceRange: 10.22.176.0/20 + - nodeName: "" + sliceRange: 10.22.192.0/20 + - nodeName: "" + sliceRange: 10.22.208.0/20 + - nodeName: "" + sliceRange: 10.22.224.0/20 + - nodeName: "" + sliceRange: 10.22.240.0/20 + - nodeName: "" + sliceRange: 10.23.0.0/20 + - nodeName: "" + sliceRange: 10.23.16.0/20 + - nodeName: "" + sliceRange: 10.23.32.0/20 + - nodeName: "" + sliceRange: 10.23.48.0/20 + - nodeName: "" + sliceRange: 10.23.64.0/20 + - nodeName: "" + sliceRange: 10.23.80.0/20 + - nodeName: "" + sliceRange: 10.23.96.0/20 + - nodeName: "" + sliceRange: 10.23.112.0/20 + - nodeName: "" + sliceRange: 10.23.128.0/20 + - nodeName: "" + sliceRange: 10.23.144.0/20 + - nodeName: "" + sliceRange: 10.23.160.0/20 + - nodeName: "" + sliceRange: 10.23.176.0/20 + - nodeName: "" + sliceRange: 10.23.192.0/20 + - nodeName: "" + sliceRange: 10.23.208.0/20 + - nodeName: "" + sliceRange: 10.23.224.0/20 + - nodeName: "" + sliceRange: 10.23.240.0/20 + - nodeName: "" + sliceRange: 10.24.0.0/20 + - nodeName: "" + sliceRange: 10.24.16.0/20 + - nodeName: "" + sliceRange: 10.24.32.0/20 + - nodeName: "" + sliceRange: 10.24.48.0/20 + - nodeName: "" + sliceRange: 10.24.64.0/20 + - nodeName: "" + sliceRange: 10.24.80.0/20 + - nodeName: "" + sliceRange: 10.24.96.0/20 + - nodeName: "" + sliceRange: 10.24.112.0/20 + - nodeName: "" + sliceRange: 10.24.128.0/20 + - nodeName: "" + sliceRange: 10.24.144.0/20 + - nodeName: "" + sliceRange: 10.24.160.0/20 + - nodeName: "" + sliceRange: 10.24.176.0/20 + - nodeName: "" + sliceRange: 10.24.192.0/20 + - nodeName: "" + sliceRange: 10.24.208.0/20 + - nodeName: "" + sliceRange: 10.24.224.0/20 + - nodeName: "" + sliceRange: 10.24.240.0/20 + - nodeName: "" + sliceRange: 10.25.0.0/20 + - nodeName: "" + sliceRange: 10.25.16.0/20 + - nodeName: "" + sliceRange: 10.25.32.0/20 + - nodeName: "" + sliceRange: 10.25.48.0/20 + - nodeName: "" + sliceRange: 10.25.64.0/20 + - nodeName: "" + sliceRange: 10.25.80.0/20 + - nodeName: "" + sliceRange: 10.25.96.0/20 + - nodeName: "" + sliceRange: 10.25.112.0/20 + - nodeName: "" + sliceRange: 10.25.128.0/20 + - nodeName: "" + sliceRange: 10.25.144.0/20 + - nodeName: "" + sliceRange: 10.25.160.0/20 + - nodeName: "" + sliceRange: 10.25.176.0/20 + - nodeName: "" + sliceRange: 10.25.192.0/20 + - nodeName: "" + sliceRange: 10.25.208.0/20 + - nodeName: "" + sliceRange: 10.25.224.0/20 + - nodeName: "" + sliceRange: 10.25.240.0/20 + - nodeName: "" + sliceRange: 10.26.0.0/20 + - nodeName: "" + sliceRange: 10.26.16.0/20 + - nodeName: "" + sliceRange: 10.26.32.0/20 + - nodeName: "" + sliceRange: 10.26.48.0/20 + - nodeName: "" + sliceRange: 10.26.64.0/20 + - nodeName: "" + sliceRange: 10.26.80.0/20 + - nodeName: "" + sliceRange: 10.26.96.0/20 + - nodeName: "" + sliceRange: 10.26.112.0/20 + - nodeName: "" + sliceRange: 10.26.128.0/20 + - nodeName: "" + sliceRange: 10.26.144.0/20 + - nodeName: "" + sliceRange: 10.26.160.0/20 + - nodeName: "" + sliceRange: 10.26.176.0/20 + - nodeName: "" + sliceRange: 10.26.192.0/20 + - nodeName: "" + sliceRange: 10.26.208.0/20 + - nodeName: "" + sliceRange: 10.26.224.0/20 + - nodeName: "" + sliceRange: 10.26.240.0/20 + - nodeName: "" + sliceRange: 10.27.0.0/20 + - nodeName: "" + sliceRange: 10.27.16.0/20 + - nodeName: "" + sliceRange: 10.27.32.0/20 + - nodeName: "" + sliceRange: 10.27.48.0/20 + - nodeName: "" + sliceRange: 10.27.64.0/20 + - nodeName: "" + sliceRange: 10.27.80.0/20 + - nodeName: "" + sliceRange: 10.27.96.0/20 + - nodeName: "" + sliceRange: 10.27.112.0/20 + - nodeName: "" + sliceRange: 10.27.128.0/20 + - nodeName: "" + sliceRange: 10.27.144.0/20 + - nodeName: "" + sliceRange: 10.27.160.0/20 + - nodeName: "" + sliceRange: 10.27.176.0/20 + - nodeName: "" + sliceRange: 10.27.192.0/20 + - nodeName: "" + sliceRange: 10.27.208.0/20 + - nodeName: "" + sliceRange: 10.27.224.0/20 + - nodeName: "" + sliceRange: 10.27.240.0/20 + - nodeName: "" + sliceRange: 10.28.0.0/20 + - nodeName: "" + sliceRange: 10.28.16.0/20 + - nodeName: "" + sliceRange: 10.28.32.0/20 + - nodeName: "" + sliceRange: 10.28.48.0/20 + - nodeName: "" + sliceRange: 10.28.64.0/20 + - nodeName: "" + sliceRange: 10.28.80.0/20 + - nodeName: "" + sliceRange: 10.28.96.0/20 + - nodeName: "" + sliceRange: 10.28.112.0/20 + - nodeName: "" + sliceRange: 10.28.128.0/20 + - nodeName: "" + sliceRange: 10.28.144.0/20 + - nodeName: "" + sliceRange: 10.28.160.0/20 + - nodeName: "" + sliceRange: 10.28.176.0/20 + - nodeName: "" + sliceRange: 10.28.192.0/20 + - nodeName: "" + sliceRange: 10.28.208.0/20 + - nodeName: "" + sliceRange: 10.28.224.0/20 + - nodeName: "" + sliceRange: 10.28.240.0/20 + - nodeName: "" + sliceRange: 10.29.0.0/20 + - nodeName: "" + sliceRange: 10.29.16.0/20 + - nodeName: "" + sliceRange: 10.29.32.0/20 + - nodeName: "" + sliceRange: 10.29.48.0/20 + - nodeName: "" + sliceRange: 10.29.64.0/20 + - nodeName: "" + sliceRange: 10.29.80.0/20 + - nodeName: "" + sliceRange: 10.29.96.0/20 + - nodeName: "" + sliceRange: 10.29.112.0/20 + - nodeName: "" + sliceRange: 10.29.128.0/20 + - nodeName: "" + sliceRange: 10.29.144.0/20 + - nodeName: "" + sliceRange: 10.29.160.0/20 + - nodeName: "" + sliceRange: 10.29.176.0/20 + - nodeName: "" + sliceRange: 10.29.192.0/20 + - nodeName: "" + sliceRange: 10.29.208.0/20 + - nodeName: "" + sliceRange: 10.29.224.0/20 + - nodeName: "" + sliceRange: 10.29.240.0/20 + - nodeName: "" + sliceRange: 10.30.0.0/20 + - nodeName: "" + sliceRange: 10.30.16.0/20 + - nodeName: "" + sliceRange: 10.30.32.0/20 + - nodeName: "" + sliceRange: 10.30.48.0/20 + - nodeName: "" + sliceRange: 10.30.64.0/20 + - nodeName: "" + sliceRange: 10.30.80.0/20 + - nodeName: "" + sliceRange: 10.30.96.0/20 + - nodeName: "" + sliceRange: 10.30.112.0/20 + - nodeName: "" + sliceRange: 10.30.128.0/20 + - nodeName: "" + sliceRange: 10.30.144.0/20 + - nodeName: "" + sliceRange: 10.30.160.0/20 + - nodeName: "" + sliceRange: 10.30.176.0/20 + - nodeName: "" + sliceRange: 10.30.192.0/20 + - nodeName: "" + sliceRange: 10.30.208.0/20 + - nodeName: "" + sliceRange: 10.30.224.0/20 + - nodeName: "" + sliceRange: 10.30.240.0/20 + - nodeName: "" + sliceRange: 10.31.0.0/20 + - nodeName: "" + sliceRange: 10.31.16.0/20 + - nodeName: "" + sliceRange: 10.31.32.0/20 + - nodeName: "" + sliceRange: 10.31.48.0/20 + - nodeName: "" + sliceRange: 10.31.64.0/20 + - nodeName: "" + sliceRange: 10.31.80.0/20 + - nodeName: "" + sliceRange: 10.31.96.0/20 + - nodeName: "" + sliceRange: 10.31.112.0/20 + - nodeName: "" + sliceRange: 10.31.128.0/20 + - nodeName: "" + sliceRange: 10.31.144.0/20 + - nodeName: "" + sliceRange: 10.31.160.0/20 + - nodeName: "" + sliceRange: 10.31.176.0/20 + - nodeName: "" + sliceRange: 10.31.192.0/20 + - nodeName: "" + sliceRange: 10.31.208.0/20 + - nodeName: "" + sliceRange: 10.31.224.0/20 + - nodeName: "" + sliceRange: 10.31.240.0/20 + - nodeName: "" + sliceRange: 10.32.0.0/20 + - nodeName: "" + sliceRange: 10.32.16.0/20 + - nodeName: "" + sliceRange: 10.32.32.0/20 + - nodeName: "" + sliceRange: 10.32.48.0/20 + - nodeName: "" + sliceRange: 10.32.64.0/20 + - nodeName: "" + sliceRange: 10.32.80.0/20 + - nodeName: "" + sliceRange: 10.32.96.0/20 + - nodeName: "" + sliceRange: 10.32.112.0/20 + - nodeName: "" + sliceRange: 10.32.128.0/20 + - nodeName: "" + sliceRange: 10.32.144.0/20 + - nodeName: "" + sliceRange: 10.32.160.0/20 + - nodeName: "" + sliceRange: 10.32.176.0/20 + - nodeName: "" + sliceRange: 10.32.192.0/20 + - nodeName: "" + sliceRange: 10.32.208.0/20 + - nodeName: "" + sliceRange: 10.32.224.0/20 + - nodeName: "" + sliceRange: 10.32.240.0/20 + - nodeName: "" + sliceRange: 10.33.0.0/20 + - nodeName: "" + sliceRange: 10.33.16.0/20 + - nodeName: "" + sliceRange: 10.33.32.0/20 + - nodeName: "" + sliceRange: 10.33.48.0/20 + - nodeName: "" + sliceRange: 10.33.64.0/20 + - nodeName: "" + sliceRange: 10.33.80.0/20 + - nodeName: "" + sliceRange: 10.33.96.0/20 + - nodeName: "" + sliceRange: 10.33.112.0/20 + - nodeName: "" + sliceRange: 10.33.128.0/20 + - nodeName: "" + sliceRange: 10.33.144.0/20 + - nodeName: "" + sliceRange: 10.33.160.0/20 + - nodeName: "" + sliceRange: 10.33.176.0/20 + - nodeName: "" + sliceRange: 10.33.192.0/20 + - nodeName: "" + sliceRange: 10.33.208.0/20 + - nodeName: "" + sliceRange: 10.33.224.0/20 + - nodeName: "" + sliceRange: 10.33.240.0/20 + - nodeName: "" + sliceRange: 10.34.0.0/20 + - nodeName: "" + sliceRange: 10.34.16.0/20 + - nodeName: "" + sliceRange: 10.34.32.0/20 + - nodeName: "" + sliceRange: 10.34.48.0/20 + - nodeName: "" + sliceRange: 10.34.64.0/20 + - nodeName: "" + sliceRange: 10.34.80.0/20 + - nodeName: "" + sliceRange: 10.34.96.0/20 + - nodeName: "" + sliceRange: 10.34.112.0/20 + - nodeName: "" + sliceRange: 10.34.128.0/20 + - nodeName: "" + sliceRange: 10.34.144.0/20 + - nodeName: "" + sliceRange: 10.34.160.0/20 + - nodeName: "" + sliceRange: 10.34.176.0/20 + - nodeName: "" + sliceRange: 10.34.192.0/20 + - nodeName: "" + sliceRange: 10.34.208.0/20 + - nodeName: "" + sliceRange: 10.34.224.0/20 + - nodeName: "" + sliceRange: 10.34.240.0/20 + - nodeName: "" + sliceRange: 10.35.0.0/20 + - nodeName: "" + sliceRange: 10.35.16.0/20 + - nodeName: "" + sliceRange: 10.35.32.0/20 + - nodeName: "" + sliceRange: 10.35.48.0/20 + - nodeName: "" + sliceRange: 10.35.64.0/20 + - nodeName: "" + sliceRange: 10.35.80.0/20 + - nodeName: "" + sliceRange: 10.35.96.0/20 + - nodeName: "" + sliceRange: 10.35.112.0/20 + - nodeName: "" + sliceRange: 10.35.128.0/20 + - nodeName: "" + sliceRange: 10.35.144.0/20 + - nodeName: "" + sliceRange: 10.35.160.0/20 + - nodeName: "" + sliceRange: 10.35.176.0/20 + - nodeName: "" + sliceRange: 10.35.192.0/20 + - nodeName: "" + sliceRange: 10.35.208.0/20 + - nodeName: "" + sliceRange: 10.35.224.0/20 + - nodeName: "" + sliceRange: 10.35.240.0/20 + - nodeName: "" + sliceRange: 10.36.0.0/20 + - nodeName: "" + sliceRange: 10.36.16.0/20 + - nodeName: "" + sliceRange: 10.36.32.0/20 + - nodeName: "" + sliceRange: 10.36.48.0/20 + - nodeName: "" + sliceRange: 10.36.64.0/20 + - nodeName: "" + sliceRange: 10.36.80.0/20 + - nodeName: "" + sliceRange: 10.36.96.0/20 + - nodeName: "" + sliceRange: 10.36.112.0/20 + - nodeName: "" + sliceRange: 10.36.128.0/20 + - nodeName: "" + sliceRange: 10.36.144.0/20 + - nodeName: "" + sliceRange: 10.36.160.0/20 + - nodeName: "" + sliceRange: 10.36.176.0/20 + - nodeName: "" + sliceRange: 10.36.192.0/20 + - nodeName: "" + sliceRange: 10.36.208.0/20 + - nodeName: "" + sliceRange: 10.36.224.0/20 + - nodeName: "" + sliceRange: 10.36.240.0/20 + - nodeName: "" + sliceRange: 10.37.0.0/20 + - nodeName: "" + sliceRange: 10.37.16.0/20 + - nodeName: "" + sliceRange: 10.37.32.0/20 + - nodeName: "" + sliceRange: 10.37.48.0/20 + - nodeName: "" + sliceRange: 10.37.64.0/20 + - nodeName: "" + sliceRange: 10.37.80.0/20 + - nodeName: "" + sliceRange: 10.37.96.0/20 + - nodeName: "" + sliceRange: 10.37.112.0/20 + - nodeName: "" + sliceRange: 10.37.128.0/20 + - nodeName: "" + sliceRange: 10.37.144.0/20 + - nodeName: "" + sliceRange: 10.37.160.0/20 + - nodeName: "" + sliceRange: 10.37.176.0/20 + - nodeName: "" + sliceRange: 10.37.192.0/20 + - nodeName: "" + sliceRange: 10.37.208.0/20 + - nodeName: "" + sliceRange: 10.37.224.0/20 + - nodeName: "" + sliceRange: 10.37.240.0/20 + - nodeName: "" + sliceRange: 10.38.0.0/20 + - nodeName: "" + sliceRange: 10.38.16.0/20 + - nodeName: "" + sliceRange: 10.38.32.0/20 + - nodeName: "" + sliceRange: 10.38.48.0/20 + - nodeName: "" + sliceRange: 10.38.64.0/20 + - nodeName: "" + sliceRange: 10.38.80.0/20 + - nodeName: "" + sliceRange: 10.38.96.0/20 + - nodeName: "" + sliceRange: 10.38.112.0/20 + - nodeName: "" + sliceRange: 10.38.128.0/20 + - nodeName: "" + sliceRange: 10.38.144.0/20 + - nodeName: "" + sliceRange: 10.38.160.0/20 + - nodeName: "" + sliceRange: 10.38.176.0/20 + - nodeName: "" + sliceRange: 10.38.192.0/20 + - nodeName: "" + sliceRange: 10.38.208.0/20 + - nodeName: "" + sliceRange: 10.38.224.0/20 + - nodeName: "" + sliceRange: 10.38.240.0/20 + - nodeName: "" + sliceRange: 10.39.0.0/20 + - nodeName: "" + sliceRange: 10.39.16.0/20 + - nodeName: "" + sliceRange: 10.39.32.0/20 + - nodeName: "" + sliceRange: 10.39.48.0/20 + - nodeName: "" + sliceRange: 10.39.64.0/20 + - nodeName: "" + sliceRange: 10.39.80.0/20 + - nodeName: "" + sliceRange: 10.39.96.0/20 + - nodeName: "" + sliceRange: 10.39.112.0/20 + - nodeName: "" + sliceRange: 10.39.128.0/20 + - nodeName: "" + sliceRange: 10.39.144.0/20 + - nodeName: "" + sliceRange: 10.39.160.0/20 + - nodeName: "" + sliceRange: 10.39.176.0/20 + - nodeName: "" + sliceRange: 10.39.192.0/20 + - nodeName: "" + sliceRange: 10.39.208.0/20 + - nodeName: "" + sliceRange: 10.39.224.0/20 + - nodeName: "" + sliceRange: 10.39.240.0/20 + - nodeName: "" + sliceRange: 10.40.0.0/20 + - nodeName: "" + sliceRange: 10.40.16.0/20 + - nodeName: "" + sliceRange: 10.40.32.0/20 + - nodeName: "" + sliceRange: 10.40.48.0/20 + - nodeName: "" + sliceRange: 10.40.64.0/20 + - nodeName: "" + sliceRange: 10.40.80.0/20 + - nodeName: "" + sliceRange: 10.40.96.0/20 + - nodeName: "" + sliceRange: 10.40.112.0/20 + - nodeName: "" + sliceRange: 10.40.128.0/20 + - nodeName: "" + sliceRange: 10.40.144.0/20 + - nodeName: "" + sliceRange: 10.40.160.0/20 + - nodeName: "" + sliceRange: 10.40.176.0/20 + - nodeName: "" + sliceRange: 10.40.192.0/20 + - nodeName: "" + sliceRange: 10.40.208.0/20 + - nodeName: "" + sliceRange: 10.40.224.0/20 + - nodeName: "" + sliceRange: 10.40.240.0/20 + - nodeName: "" + sliceRange: 10.41.0.0/20 + - nodeName: "" + sliceRange: 10.41.16.0/20 + - nodeName: "" + sliceRange: 10.41.32.0/20 + - nodeName: "" + sliceRange: 10.41.48.0/20 + - nodeName: "" + sliceRange: 10.41.64.0/20 + - nodeName: "" + sliceRange: 10.41.80.0/20 + - nodeName: "" + sliceRange: 10.41.96.0/20 + - nodeName: "" + sliceRange: 10.41.112.0/20 + - nodeName: "" + sliceRange: 10.41.128.0/20 + - nodeName: "" + sliceRange: 10.41.144.0/20 + - nodeName: "" + sliceRange: 10.41.160.0/20 + - nodeName: "" + sliceRange: 10.41.176.0/20 + - nodeName: "" + sliceRange: 10.41.192.0/20 + - nodeName: "" + sliceRange: 10.41.208.0/20 + - nodeName: "" + sliceRange: 10.41.224.0/20 + - nodeName: "" + sliceRange: 10.41.240.0/20 + - nodeName: "" + sliceRange: 10.42.0.0/20 + - nodeName: "" + sliceRange: 10.42.16.0/20 + - nodeName: "" + sliceRange: 10.42.32.0/20 + - nodeName: "" + sliceRange: 10.42.48.0/20 + - nodeName: "" + sliceRange: 10.42.64.0/20 + - nodeName: "" + sliceRange: 10.42.80.0/20 + - nodeName: "" + sliceRange: 10.42.96.0/20 + - nodeName: "" + sliceRange: 10.42.112.0/20 + - nodeName: "" + sliceRange: 10.42.128.0/20 + - nodeName: "" + sliceRange: 10.42.144.0/20 + - nodeName: "" + sliceRange: 10.42.160.0/20 + - nodeName: "" + sliceRange: 10.42.176.0/20 + - nodeName: "" + sliceRange: 10.42.192.0/20 + - nodeName: "" + sliceRange: 10.42.208.0/20 + - nodeName: "" + sliceRange: 10.42.224.0/20 + - nodeName: "" + sliceRange: 10.42.240.0/20 + - nodeName: "" + sliceRange: 10.43.0.0/20 + - nodeName: "" + sliceRange: 10.43.16.0/20 + - nodeName: "" + sliceRange: 10.43.32.0/20 + - nodeName: "" + sliceRange: 10.43.48.0/20 + - nodeName: "" + sliceRange: 10.43.64.0/20 + - nodeName: "" + sliceRange: 10.43.80.0/20 + - nodeName: "" + sliceRange: 10.43.96.0/20 + - nodeName: "" + sliceRange: 10.43.112.0/20 + - nodeName: "" + sliceRange: 10.43.128.0/20 + - nodeName: "" + sliceRange: 10.43.144.0/20 + - nodeName: "" + sliceRange: 10.43.160.0/20 + - nodeName: "" + sliceRange: 10.43.176.0/20 + - nodeName: "" + sliceRange: 10.43.192.0/20 + - nodeName: "" + sliceRange: 10.43.208.0/20 + - nodeName: "" + sliceRange: 10.43.224.0/20 + - nodeName: "" + sliceRange: 10.43.240.0/20 + - nodeName: "" + sliceRange: 10.44.0.0/20 + - nodeName: "" + sliceRange: 10.44.16.0/20 + - nodeName: "" + sliceRange: 10.44.32.0/20 + - nodeName: "" + sliceRange: 10.44.48.0/20 + - nodeName: "" + sliceRange: 10.44.64.0/20 + - nodeName: "" + sliceRange: 10.44.80.0/20 + - nodeName: "" + sliceRange: 10.44.96.0/20 + - nodeName: "" + sliceRange: 10.44.112.0/20 + - nodeName: "" + sliceRange: 10.44.128.0/20 + - nodeName: "" + sliceRange: 10.44.144.0/20 + - nodeName: "" + sliceRange: 10.44.160.0/20 + - nodeName: "" + sliceRange: 10.44.176.0/20 + - nodeName: "" + sliceRange: 10.44.192.0/20 + - nodeName: "" + sliceRange: 10.44.208.0/20 + - nodeName: "" + sliceRange: 10.44.224.0/20 + - nodeName: "" + sliceRange: 10.44.240.0/20 + - nodeName: "" + sliceRange: 10.45.0.0/20 + - nodeName: "" + sliceRange: 10.45.16.0/20 + - nodeName: "" + sliceRange: 10.45.32.0/20 + - nodeName: "" + sliceRange: 10.45.48.0/20 + - nodeName: "" + sliceRange: 10.45.64.0/20 + - nodeName: "" + sliceRange: 10.45.80.0/20 + - nodeName: "" + sliceRange: 10.45.96.0/20 + - nodeName: "" + sliceRange: 10.45.112.0/20 + - nodeName: "" + sliceRange: 10.45.128.0/20 + - nodeName: "" + sliceRange: 10.45.144.0/20 + - nodeName: "" + sliceRange: 10.45.160.0/20 + - nodeName: "" + sliceRange: 10.45.176.0/20 + - nodeName: "" + sliceRange: 10.45.192.0/20 + - nodeName: "" + sliceRange: 10.45.208.0/20 + - nodeName: "" + sliceRange: 10.45.224.0/20 + - nodeName: "" + sliceRange: 10.45.240.0/20 + - nodeName: "" + sliceRange: 10.46.0.0/20 + - nodeName: "" + sliceRange: 10.46.16.0/20 + - nodeName: "" + sliceRange: 10.46.32.0/20 + - nodeName: "" + sliceRange: 10.46.48.0/20 + - nodeName: "" + sliceRange: 10.46.64.0/20 + - nodeName: "" + sliceRange: 10.46.80.0/20 + - nodeName: "" + sliceRange: 10.46.96.0/20 + - nodeName: "" + sliceRange: 10.46.112.0/20 + - nodeName: "" + sliceRange: 10.46.128.0/20 + - nodeName: "" + sliceRange: 10.46.144.0/20 + - nodeName: "" + sliceRange: 10.46.160.0/20 + - nodeName: "" + sliceRange: 10.46.176.0/20 + - nodeName: "" + sliceRange: 10.46.192.0/20 + - nodeName: "" + sliceRange: 10.46.208.0/20 + - nodeName: "" + sliceRange: 10.46.224.0/20 + - nodeName: "" + sliceRange: 10.46.240.0/20 + - nodeName: "" + sliceRange: 10.47.0.0/20 + - nodeName: "" + sliceRange: 10.47.16.0/20 + - nodeName: "" + sliceRange: 10.47.32.0/20 + - nodeName: "" + sliceRange: 10.47.48.0/20 + - nodeName: "" + sliceRange: 10.47.64.0/20 + - nodeName: "" + sliceRange: 10.47.80.0/20 + - nodeName: "" + sliceRange: 10.47.96.0/20 + - nodeName: "" + sliceRange: 10.47.112.0/20 + - nodeName: "" + sliceRange: 10.47.128.0/20 + - nodeName: "" + sliceRange: 10.47.144.0/20 + - nodeName: "" + sliceRange: 10.47.160.0/20 + - nodeName: "" + sliceRange: 10.47.176.0/20 + - nodeName: "" + sliceRange: 10.47.192.0/20 + - nodeName: "" + sliceRange: 10.47.208.0/20 + - nodeName: "" + sliceRange: 10.47.224.0/20 + - nodeName: "" + sliceRange: 10.47.240.0/20 + - nodeName: "" + sliceRange: 10.48.0.0/20 + - nodeName: "" + sliceRange: 10.48.16.0/20 + - nodeName: "" + sliceRange: 10.48.32.0/20 + - nodeName: "" + sliceRange: 10.48.48.0/20 + - nodeName: "" + sliceRange: 10.48.64.0/20 + - nodeName: "" + sliceRange: 10.48.80.0/20 + - nodeName: "" + sliceRange: 10.48.96.0/20 + - nodeName: "" + sliceRange: 10.48.112.0/20 + - nodeName: "" + sliceRange: 10.48.128.0/20 + - nodeName: "" + sliceRange: 10.48.144.0/20 + - nodeName: "" + sliceRange: 10.48.160.0/20 + - nodeName: "" + sliceRange: 10.48.176.0/20 + - nodeName: "" + sliceRange: 10.48.192.0/20 + - nodeName: "" + sliceRange: 10.48.208.0/20 + - nodeName: "" + sliceRange: 10.48.224.0/20 + - nodeName: "" + sliceRange: 10.48.240.0/20 + - nodeName: "" + sliceRange: 10.49.0.0/20 + - nodeName: "" + sliceRange: 10.49.16.0/20 + - nodeName: "" + sliceRange: 10.49.32.0/20 + - nodeName: "" + sliceRange: 10.49.48.0/20 + - nodeName: "" + sliceRange: 10.49.64.0/20 + - nodeName: "" + sliceRange: 10.49.80.0/20 + - nodeName: "" + sliceRange: 10.49.96.0/20 + - nodeName: "" + sliceRange: 10.49.112.0/20 + - nodeName: "" + sliceRange: 10.49.128.0/20 + - nodeName: "" + sliceRange: 10.49.144.0/20 + - nodeName: "" + sliceRange: 10.49.160.0/20 + - nodeName: "" + sliceRange: 10.49.176.0/20 + - nodeName: "" + sliceRange: 10.49.192.0/20 + - nodeName: "" + sliceRange: 10.49.208.0/20 + - nodeName: "" + sliceRange: 10.49.224.0/20 + - nodeName: "" + sliceRange: 10.49.240.0/20 + - nodeName: "" + sliceRange: 10.50.0.0/20 + - nodeName: "" + sliceRange: 10.50.16.0/20 + - nodeName: "" + sliceRange: 10.50.32.0/20 + - nodeName: "" + sliceRange: 10.50.48.0/20 + - nodeName: "" + sliceRange: 10.50.64.0/20 + - nodeName: "" + sliceRange: 10.50.80.0/20 + - nodeName: "" + sliceRange: 10.50.96.0/20 + - nodeName: "" + sliceRange: 10.50.112.0/20 + - nodeName: "" + sliceRange: 10.50.128.0/20 + - nodeName: "" + sliceRange: 10.50.144.0/20 + - nodeName: "" + sliceRange: 10.50.160.0/20 + - nodeName: "" + sliceRange: 10.50.176.0/20 + - nodeName: "" + sliceRange: 10.50.192.0/20 + - nodeName: "" + sliceRange: 10.50.208.0/20 + - nodeName: "" + sliceRange: 10.50.224.0/20 + - nodeName: "" + sliceRange: 10.50.240.0/20 + - nodeName: "" + sliceRange: 10.51.0.0/20 + - nodeName: "" + sliceRange: 10.51.16.0/20 + - nodeName: "" + sliceRange: 10.51.32.0/20 + - nodeName: "" + sliceRange: 10.51.48.0/20 + - nodeName: "" + sliceRange: 10.51.64.0/20 + - nodeName: "" + sliceRange: 10.51.80.0/20 + - nodeName: "" + sliceRange: 10.51.96.0/20 + - nodeName: "" + sliceRange: 10.51.112.0/20 + - nodeName: "" + sliceRange: 10.51.128.0/20 + - nodeName: "" + sliceRange: 10.51.144.0/20 + - nodeName: "" + sliceRange: 10.51.160.0/20 + - nodeName: "" + sliceRange: 10.51.176.0/20 + - nodeName: "" + sliceRange: 10.51.192.0/20 + - nodeName: "" + sliceRange: 10.51.208.0/20 + - nodeName: "" + sliceRange: 10.51.224.0/20 + - nodeName: "" + sliceRange: 10.51.240.0/20 + - nodeName: "" + sliceRange: 10.52.0.0/20 + - nodeName: "" + sliceRange: 10.52.16.0/20 + - nodeName: "" + sliceRange: 10.52.32.0/20 + - nodeName: "" + sliceRange: 10.52.48.0/20 + - nodeName: "" + sliceRange: 10.52.64.0/20 + - nodeName: "" + sliceRange: 10.52.80.0/20 + - nodeName: "" + sliceRange: 10.52.96.0/20 + - nodeName: "" + sliceRange: 10.52.112.0/20 + - nodeName: "" + sliceRange: 10.52.128.0/20 + - nodeName: "" + sliceRange: 10.52.144.0/20 + - nodeName: "" + sliceRange: 10.52.160.0/20 + - nodeName: "" + sliceRange: 10.52.176.0/20 + - nodeName: "" + sliceRange: 10.52.192.0/20 + - nodeName: "" + sliceRange: 10.52.208.0/20 + - nodeName: "" + sliceRange: 10.52.224.0/20 + - nodeName: "" + sliceRange: 10.52.240.0/20 + - nodeName: "" + sliceRange: 10.53.0.0/20 + - nodeName: "" + sliceRange: 10.53.16.0/20 + - nodeName: "" + sliceRange: 10.53.32.0/20 + - nodeName: "" + sliceRange: 10.53.48.0/20 + - nodeName: "" + sliceRange: 10.53.64.0/20 + - nodeName: "" + sliceRange: 10.53.80.0/20 + - nodeName: "" + sliceRange: 10.53.96.0/20 + - nodeName: "" + sliceRange: 10.53.112.0/20 + - nodeName: "" + sliceRange: 10.53.128.0/20 + - nodeName: "" + sliceRange: 10.53.144.0/20 + - nodeName: "" + sliceRange: 10.53.160.0/20 + - nodeName: "" + sliceRange: 10.53.176.0/20 + - nodeName: "" + sliceRange: 10.53.192.0/20 + - nodeName: "" + sliceRange: 10.53.208.0/20 + - nodeName: "" + sliceRange: 10.53.224.0/20 + - nodeName: "" + sliceRange: 10.53.240.0/20 + - nodeName: "" + sliceRange: 10.54.0.0/20 + - nodeName: "" + sliceRange: 10.54.16.0/20 + - nodeName: "" + sliceRange: 10.54.32.0/20 + - nodeName: "" + sliceRange: 10.54.48.0/20 + - nodeName: "" + sliceRange: 10.54.64.0/20 + - nodeName: "" + sliceRange: 10.54.80.0/20 + - nodeName: "" + sliceRange: 10.54.96.0/20 + - nodeName: "" + sliceRange: 10.54.112.0/20 + - nodeName: "" + sliceRange: 10.54.128.0/20 + - nodeName: "" + sliceRange: 10.54.144.0/20 + - nodeName: "" + sliceRange: 10.54.160.0/20 + - nodeName: "" + sliceRange: 10.54.176.0/20 + - nodeName: "" + sliceRange: 10.54.192.0/20 + - nodeName: "" + sliceRange: 10.54.208.0/20 + - nodeName: "" + sliceRange: 10.54.224.0/20 + - nodeName: "" + sliceRange: 10.54.240.0/20 + - nodeName: "" + sliceRange: 10.55.0.0/20 + - nodeName: "" + sliceRange: 10.55.16.0/20 + - nodeName: "" + sliceRange: 10.55.32.0/20 + - nodeName: "" + sliceRange: 10.55.48.0/20 + - nodeName: "" + sliceRange: 10.55.64.0/20 + - nodeName: "" + sliceRange: 10.55.80.0/20 + - nodeName: "" + sliceRange: 10.55.96.0/20 + - nodeName: "" + sliceRange: 10.55.112.0/20 + - nodeName: "" + sliceRange: 10.55.128.0/20 + - nodeName: "" + sliceRange: 10.55.144.0/20 + - nodeName: "" + sliceRange: 10.55.160.0/20 + - nodeName: "" + sliceRange: 10.55.176.0/20 + - nodeName: "" + sliceRange: 10.55.192.0/20 + - nodeName: "" + sliceRange: 10.55.208.0/20 + - nodeName: "" + sliceRange: 10.55.224.0/20 + - nodeName: "" + sliceRange: 10.55.240.0/20 + - nodeName: "" + sliceRange: 10.56.0.0/20 + - nodeName: "" + sliceRange: 10.56.16.0/20 + - nodeName: "" + sliceRange: 10.56.32.0/20 + - nodeName: "" + sliceRange: 10.56.48.0/20 + - nodeName: "" + sliceRange: 10.56.64.0/20 + - nodeName: "" + sliceRange: 10.56.80.0/20 + - nodeName: "" + sliceRange: 10.56.96.0/20 + - nodeName: "" + sliceRange: 10.56.112.0/20 + - nodeName: "" + sliceRange: 10.56.128.0/20 + - nodeName: "" + sliceRange: 10.56.144.0/20 + - nodeName: "" + sliceRange: 10.56.160.0/20 + - nodeName: "" + sliceRange: 10.56.176.0/20 + - nodeName: "" + sliceRange: 10.56.192.0/20 + - nodeName: "" + sliceRange: 10.56.208.0/20 + - nodeName: "" + sliceRange: 10.56.224.0/20 + - nodeName: "" + sliceRange: 10.56.240.0/20 + - nodeName: "" + sliceRange: 10.57.0.0/20 + - nodeName: "" + sliceRange: 10.57.16.0/20 + - nodeName: "" + sliceRange: 10.57.32.0/20 + - nodeName: "" + sliceRange: 10.57.48.0/20 + - nodeName: "" + sliceRange: 10.57.64.0/20 + - nodeName: "" + sliceRange: 10.57.80.0/20 + - nodeName: "" + sliceRange: 10.57.96.0/20 + - nodeName: "" + sliceRange: 10.57.112.0/20 + - nodeName: "" + sliceRange: 10.57.128.0/20 + - nodeName: "" + sliceRange: 10.57.144.0/20 + - nodeName: "" + sliceRange: 10.57.160.0/20 + - nodeName: "" + sliceRange: 10.57.176.0/20 + - nodeName: "" + sliceRange: 10.57.192.0/20 + - nodeName: "" + sliceRange: 10.57.208.0/20 + - nodeName: "" + sliceRange: 10.57.224.0/20 + - nodeName: "" + sliceRange: 10.57.240.0/20 + - nodeName: "" + sliceRange: 10.58.0.0/20 + - nodeName: "" + sliceRange: 10.58.16.0/20 + - nodeName: "" + sliceRange: 10.58.32.0/20 + - nodeName: "" + sliceRange: 10.58.48.0/20 + - nodeName: "" + sliceRange: 10.58.64.0/20 + - nodeName: "" + sliceRange: 10.58.80.0/20 + - nodeName: "" + sliceRange: 10.58.96.0/20 + - nodeName: "" + sliceRange: 10.58.112.0/20 + - nodeName: "" + sliceRange: 10.58.128.0/20 + - nodeName: "" + sliceRange: 10.58.144.0/20 + - nodeName: "" + sliceRange: 10.58.160.0/20 + - nodeName: "" + sliceRange: 10.58.176.0/20 + - nodeName: "" + sliceRange: 10.58.192.0/20 + - nodeName: "" + sliceRange: 10.58.208.0/20 + - nodeName: "" + sliceRange: 10.58.224.0/20 + - nodeName: "" + sliceRange: 10.58.240.0/20 + - nodeName: "" + sliceRange: 10.59.0.0/20 + - nodeName: "" + sliceRange: 10.59.16.0/20 + - nodeName: "" + sliceRange: 10.59.32.0/20 + - nodeName: "" + sliceRange: 10.59.48.0/20 + - nodeName: "" + sliceRange: 10.59.64.0/20 + - nodeName: "" + sliceRange: 10.59.80.0/20 + - nodeName: "" + sliceRange: 10.59.96.0/20 + - nodeName: "" + sliceRange: 10.59.112.0/20 + - nodeName: "" + sliceRange: 10.59.128.0/20 + - nodeName: "" + sliceRange: 10.59.144.0/20 + - nodeName: "" + sliceRange: 10.59.160.0/20 + - nodeName: "" + sliceRange: 10.59.176.0/20 + - nodeName: "" + sliceRange: 10.59.192.0/20 + - nodeName: "" + sliceRange: 10.59.208.0/20 + - nodeName: "" + sliceRange: 10.59.224.0/20 + - nodeName: "" + sliceRange: 10.59.240.0/20 + - nodeName: "" + sliceRange: 10.60.0.0/20 + - nodeName: "" + sliceRange: 10.60.16.0/20 + - nodeName: "" + sliceRange: 10.60.32.0/20 + - nodeName: "" + sliceRange: 10.60.48.0/20 + - nodeName: "" + sliceRange: 10.60.64.0/20 + - nodeName: "" + sliceRange: 10.60.80.0/20 + - nodeName: "" + sliceRange: 10.60.96.0/20 + - nodeName: "" + sliceRange: 10.60.112.0/20 + - nodeName: "" + sliceRange: 10.60.128.0/20 + - nodeName: "" + sliceRange: 10.60.144.0/20 + - nodeName: "" + sliceRange: 10.60.160.0/20 + - nodeName: "" + sliceRange: 10.60.176.0/20 + - nodeName: "" + sliceRange: 10.60.192.0/20 + - nodeName: "" + sliceRange: 10.60.208.0/20 + - nodeName: "" + sliceRange: 10.60.224.0/20 + - nodeName: "" + sliceRange: 10.60.240.0/20 + - nodeName: "" + sliceRange: 10.61.0.0/20 + - nodeName: "" + sliceRange: 10.61.16.0/20 + - nodeName: "" + sliceRange: 10.61.32.0/20 + - nodeName: "" + sliceRange: 10.61.48.0/20 + - nodeName: "" + sliceRange: 10.61.64.0/20 + - nodeName: "" + sliceRange: 10.61.80.0/20 + - nodeName: "" + sliceRange: 10.61.96.0/20 + - nodeName: "" + sliceRange: 10.61.112.0/20 + - nodeName: "" + sliceRange: 10.61.128.0/20 + - nodeName: "" + sliceRange: 10.61.144.0/20 + - nodeName: "" + sliceRange: 10.61.160.0/20 + - nodeName: "" + sliceRange: 10.61.176.0/20 + - nodeName: "" + sliceRange: 10.61.192.0/20 + - nodeName: "" + sliceRange: 10.61.208.0/20 + - nodeName: "" + sliceRange: 10.61.224.0/20 + - nodeName: "" + sliceRange: 10.61.240.0/20 + - nodeName: "" + sliceRange: 10.62.0.0/20 + - nodeName: "" + sliceRange: 10.62.16.0/20 + - nodeName: "" + sliceRange: 10.62.32.0/20 + - nodeName: "" + sliceRange: 10.62.48.0/20 + - nodeName: "" + sliceRange: 10.62.64.0/20 + - nodeName: "" + sliceRange: 10.62.80.0/20 + - nodeName: "" + sliceRange: 10.62.96.0/20 + - nodeName: "" + sliceRange: 10.62.112.0/20 + - nodeName: "" + sliceRange: 10.62.128.0/20 + - nodeName: "" + sliceRange: 10.62.144.0/20 + - nodeName: "" + sliceRange: 10.62.160.0/20 + - nodeName: "" + sliceRange: 10.62.176.0/20 + - nodeName: "" + sliceRange: 10.62.192.0/20 + - nodeName: "" + sliceRange: 10.62.208.0/20 + - nodeName: "" + sliceRange: 10.62.224.0/20 + - nodeName: "" + sliceRange: 10.62.240.0/20 + - nodeName: "" + sliceRange: 10.63.0.0/20 + - nodeName: "" + sliceRange: 10.63.16.0/20 + - nodeName: "" + sliceRange: 10.63.32.0/20 + - nodeName: "" + sliceRange: 10.63.48.0/20 + - nodeName: "" + sliceRange: 10.63.64.0/20 + - nodeName: "" + sliceRange: 10.63.80.0/20 + - nodeName: "" + sliceRange: 10.63.96.0/20 + - nodeName: "" + sliceRange: 10.63.112.0/20 + - nodeName: "" + sliceRange: 10.63.128.0/20 + - nodeName: "" + sliceRange: 10.63.144.0/20 + - nodeName: "" + sliceRange: 10.63.160.0/20 + - nodeName: "" + sliceRange: 10.63.176.0/20 + - nodeName: "" + sliceRange: 10.63.192.0/20 + - nodeName: "" + sliceRange: 10.63.208.0/20 + - nodeName: "" + sliceRange: 10.63.224.0/20 + - nodeName: "" + sliceRange: 10.63.240.0/20 + - nodeName: "" + sliceRange: 10.64.0.0/20 + - nodeName: "" + sliceRange: 10.64.16.0/20 + - nodeName: "" + sliceRange: 10.64.32.0/20 + - nodeName: "" + sliceRange: 10.64.48.0/20 + - nodeName: "" + sliceRange: 10.64.64.0/20 + - nodeName: "" + sliceRange: 10.64.80.0/20 + - nodeName: "" + sliceRange: 10.64.96.0/20 + - nodeName: "" + sliceRange: 10.64.112.0/20 + - nodeName: "" + sliceRange: 10.64.128.0/20 + - nodeName: "" + sliceRange: 10.64.144.0/20 + - nodeName: "" + sliceRange: 10.64.160.0/20 + - nodeName: "" + sliceRange: 10.64.176.0/20 + - nodeName: "" + sliceRange: 10.64.192.0/20 + - nodeName: "" + sliceRange: 10.64.208.0/20 + - nodeName: "" + sliceRange: 10.64.224.0/20 + - nodeName: "" + sliceRange: 10.64.240.0/20 + - nodeName: "" + sliceRange: 10.65.0.0/20 + - nodeName: "" + sliceRange: 10.65.16.0/20 + - nodeName: "" + sliceRange: 10.65.32.0/20 + - nodeName: "" + sliceRange: 10.65.48.0/20 + - nodeName: "" + sliceRange: 10.65.64.0/20 + - nodeName: "" + sliceRange: 10.65.80.0/20 + - nodeName: "" + sliceRange: 10.65.96.0/20 + - nodeName: "" + sliceRange: 10.65.112.0/20 + - nodeName: "" + sliceRange: 10.65.128.0/20 + - nodeName: "" + sliceRange: 10.65.144.0/20 + - nodeName: "" + sliceRange: 10.65.160.0/20 + - nodeName: "" + sliceRange: 10.65.176.0/20 + - nodeName: "" + sliceRange: 10.65.192.0/20 + - nodeName: "" + sliceRange: 10.65.208.0/20 + - nodeName: "" + sliceRange: 10.65.224.0/20 + - nodeName: "" + sliceRange: 10.65.240.0/20 + - nodeName: "" + sliceRange: 10.66.0.0/20 + - nodeName: "" + sliceRange: 10.66.16.0/20 + - nodeName: "" + sliceRange: 10.66.32.0/20 + - nodeName: "" + sliceRange: 10.66.48.0/20 + - nodeName: "" + sliceRange: 10.66.64.0/20 + - nodeName: "" + sliceRange: 10.66.80.0/20 + - nodeName: "" + sliceRange: 10.66.96.0/20 + - nodeName: "" + sliceRange: 10.66.112.0/20 + - nodeName: "" + sliceRange: 10.66.128.0/20 + - nodeName: "" + sliceRange: 10.66.144.0/20 + - nodeName: "" + sliceRange: 10.66.160.0/20 + - nodeName: "" + sliceRange: 10.66.176.0/20 + - nodeName: "" + sliceRange: 10.66.192.0/20 + - nodeName: "" + sliceRange: 10.66.208.0/20 + - nodeName: "" + sliceRange: 10.66.224.0/20 + - nodeName: "" + sliceRange: 10.66.240.0/20 + - nodeName: "" + sliceRange: 10.67.0.0/20 + - nodeName: "" + sliceRange: 10.67.16.0/20 + - nodeName: "" + sliceRange: 10.67.32.0/20 + - nodeName: "" + sliceRange: 10.67.48.0/20 + - nodeName: "" + sliceRange: 10.67.64.0/20 + - nodeName: "" + sliceRange: 10.67.80.0/20 + - nodeName: "" + sliceRange: 10.67.96.0/20 + - nodeName: "" + sliceRange: 10.67.112.0/20 + - nodeName: "" + sliceRange: 10.67.128.0/20 + - nodeName: "" + sliceRange: 10.67.144.0/20 + - nodeName: "" + sliceRange: 10.67.160.0/20 + - nodeName: "" + sliceRange: 10.67.176.0/20 + - nodeName: "" + sliceRange: 10.67.192.0/20 + - nodeName: "" + sliceRange: 10.67.208.0/20 + - nodeName: "" + sliceRange: 10.67.224.0/20 + - nodeName: "" + sliceRange: 10.67.240.0/20 + - nodeName: "" + sliceRange: 10.68.0.0/20 + - nodeName: "" + sliceRange: 10.68.16.0/20 + - nodeName: "" + sliceRange: 10.68.32.0/20 + - nodeName: "" + sliceRange: 10.68.48.0/20 + - nodeName: "" + sliceRange: 10.68.64.0/20 + - nodeName: "" + sliceRange: 10.68.80.0/20 + - nodeName: "" + sliceRange: 10.68.96.0/20 + - nodeName: "" + sliceRange: 10.68.112.0/20 + - nodeName: "" + sliceRange: 10.68.128.0/20 + - nodeName: "" + sliceRange: 10.68.144.0/20 + - nodeName: "" + sliceRange: 10.68.160.0/20 + - nodeName: "" + sliceRange: 10.68.176.0/20 + - nodeName: "" + sliceRange: 10.68.192.0/20 + - nodeName: "" + sliceRange: 10.68.208.0/20 + - nodeName: "" + sliceRange: 10.68.224.0/20 + - nodeName: "" + sliceRange: 10.68.240.0/20 + - nodeName: "" + sliceRange: 10.69.0.0/20 + - nodeName: "" + sliceRange: 10.69.16.0/20 + - nodeName: "" + sliceRange: 10.69.32.0/20 + - nodeName: "" + sliceRange: 10.69.48.0/20 + - nodeName: "" + sliceRange: 10.69.64.0/20 + - nodeName: "" + sliceRange: 10.69.80.0/20 + - nodeName: "" + sliceRange: 10.69.96.0/20 + - nodeName: "" + sliceRange: 10.69.112.0/20 + - nodeName: "" + sliceRange: 10.69.128.0/20 + - nodeName: "" + sliceRange: 10.69.144.0/20 + - nodeName: "" + sliceRange: 10.69.160.0/20 + - nodeName: "" + sliceRange: 10.69.176.0/20 + - nodeName: "" + sliceRange: 10.69.192.0/20 + - nodeName: "" + sliceRange: 10.69.208.0/20 + - nodeName: "" + sliceRange: 10.69.224.0/20 + - nodeName: "" + sliceRange: 10.69.240.0/20 + - nodeName: "" + sliceRange: 10.70.0.0/20 + - nodeName: "" + sliceRange: 10.70.16.0/20 + - nodeName: "" + sliceRange: 10.70.32.0/20 + - nodeName: "" + sliceRange: 10.70.48.0/20 + - nodeName: "" + sliceRange: 10.70.64.0/20 + - nodeName: "" + sliceRange: 10.70.80.0/20 + - nodeName: "" + sliceRange: 10.70.96.0/20 + - nodeName: "" + sliceRange: 10.70.112.0/20 + - nodeName: "" + sliceRange: 10.70.128.0/20 + - nodeName: "" + sliceRange: 10.70.144.0/20 + - nodeName: "" + sliceRange: 10.70.160.0/20 + - nodeName: "" + sliceRange: 10.70.176.0/20 + - nodeName: "" + sliceRange: 10.70.192.0/20 + - nodeName: "" + sliceRange: 10.70.208.0/20 + - nodeName: "" + sliceRange: 10.70.224.0/20 + - nodeName: "" + sliceRange: 10.70.240.0/20 + - nodeName: "" + sliceRange: 10.71.0.0/20 + - nodeName: "" + sliceRange: 10.71.16.0/20 + - nodeName: "" + sliceRange: 10.71.32.0/20 + - nodeName: "" + sliceRange: 10.71.48.0/20 + - nodeName: "" + sliceRange: 10.71.64.0/20 + - nodeName: "" + sliceRange: 10.71.80.0/20 + - nodeName: "" + sliceRange: 10.71.96.0/20 + - nodeName: "" + sliceRange: 10.71.112.0/20 + - nodeName: "" + sliceRange: 10.71.128.0/20 + - nodeName: "" + sliceRange: 10.71.144.0/20 + - nodeName: "" + sliceRange: 10.71.160.0/20 + - nodeName: "" + sliceRange: 10.71.176.0/20 + - nodeName: "" + sliceRange: 10.71.192.0/20 + - nodeName: "" + sliceRange: 10.71.208.0/20 + - nodeName: "" + sliceRange: 10.71.224.0/20 + - nodeName: "" + sliceRange: 10.71.240.0/20 + - nodeName: "" + sliceRange: 10.72.0.0/20 + - nodeName: "" + sliceRange: 10.72.16.0/20 + - nodeName: "" + sliceRange: 10.72.32.0/20 + - nodeName: "" + sliceRange: 10.72.48.0/20 + - nodeName: "" + sliceRange: 10.72.64.0/20 + - nodeName: "" + sliceRange: 10.72.80.0/20 + - nodeName: "" + sliceRange: 10.72.96.0/20 + - nodeName: "" + sliceRange: 10.72.112.0/20 + - nodeName: "" + sliceRange: 10.72.128.0/20 + - nodeName: "" + sliceRange: 10.72.144.0/20 + - nodeName: "" + sliceRange: 10.72.160.0/20 + - nodeName: "" + sliceRange: 10.72.176.0/20 + - nodeName: "" + sliceRange: 10.72.192.0/20 + - nodeName: "" + sliceRange: 10.72.208.0/20 + - nodeName: "" + sliceRange: 10.72.224.0/20 + - nodeName: "" + sliceRange: 10.72.240.0/20 + - nodeName: "" + sliceRange: 10.73.0.0/20 + - nodeName: "" + sliceRange: 10.73.16.0/20 + - nodeName: "" + sliceRange: 10.73.32.0/20 + - nodeName: "" + sliceRange: 10.73.48.0/20 + - nodeName: "" + sliceRange: 10.73.64.0/20 + - nodeName: "" + sliceRange: 10.73.80.0/20 + - nodeName: "" + sliceRange: 10.73.96.0/20 + - nodeName: "" + sliceRange: 10.73.112.0/20 + - nodeName: "" + sliceRange: 10.73.128.0/20 + - nodeName: "" + sliceRange: 10.73.144.0/20 + - nodeName: "" + sliceRange: 10.73.160.0/20 + - nodeName: "" + sliceRange: 10.73.176.0/20 + - nodeName: "" + sliceRange: 10.73.192.0/20 + - nodeName: "" + sliceRange: 10.73.208.0/20 + - nodeName: "" + sliceRange: 10.73.224.0/20 + - nodeName: "" + sliceRange: 10.73.240.0/20 + - nodeName: "" + sliceRange: 10.74.0.0/20 + - nodeName: "" + sliceRange: 10.74.16.0/20 + - nodeName: "" + sliceRange: 10.74.32.0/20 + - nodeName: "" + sliceRange: 10.74.48.0/20 + - nodeName: "" + sliceRange: 10.74.64.0/20 + - nodeName: "" + sliceRange: 10.74.80.0/20 + - nodeName: "" + sliceRange: 10.74.96.0/20 + - nodeName: "" + sliceRange: 10.74.112.0/20 + - nodeName: "" + sliceRange: 10.74.128.0/20 + - nodeName: "" + sliceRange: 10.74.144.0/20 + - nodeName: "" + sliceRange: 10.74.160.0/20 + - nodeName: "" + sliceRange: 10.74.176.0/20 + - nodeName: "" + sliceRange: 10.74.192.0/20 + - nodeName: "" + sliceRange: 10.74.208.0/20 + - nodeName: "" + sliceRange: 10.74.224.0/20 + - nodeName: "" + sliceRange: 10.74.240.0/20 + - nodeName: "" + sliceRange: 10.75.0.0/20 + - nodeName: "" + sliceRange: 10.75.16.0/20 + - nodeName: "" + sliceRange: 10.75.32.0/20 + - nodeName: "" + sliceRange: 10.75.48.0/20 + - nodeName: "" + sliceRange: 10.75.64.0/20 + - nodeName: "" + sliceRange: 10.75.80.0/20 + - nodeName: "" + sliceRange: 10.75.96.0/20 + - nodeName: "" + sliceRange: 10.75.112.0/20 + - nodeName: "" + sliceRange: 10.75.128.0/20 + - nodeName: "" + sliceRange: 10.75.144.0/20 + - nodeName: "" + sliceRange: 10.75.160.0/20 + - nodeName: "" + sliceRange: 10.75.176.0/20 + - nodeName: "" + sliceRange: 10.75.192.0/20 + - nodeName: "" + sliceRange: 10.75.208.0/20 + - nodeName: "" + sliceRange: 10.75.224.0/20 + - nodeName: "" + sliceRange: 10.75.240.0/20 + - nodeName: "" + sliceRange: 10.76.0.0/20 + - nodeName: "" + sliceRange: 10.76.16.0/20 + - nodeName: "" + sliceRange: 10.76.32.0/20 + - nodeName: "" + sliceRange: 10.76.48.0/20 + - nodeName: "" + sliceRange: 10.76.64.0/20 + - nodeName: "" + sliceRange: 10.76.80.0/20 + - nodeName: "" + sliceRange: 10.76.96.0/20 + - nodeName: "" + sliceRange: 10.76.112.0/20 + - nodeName: "" + sliceRange: 10.76.128.0/20 + - nodeName: "" + sliceRange: 10.76.144.0/20 + - nodeName: "" + sliceRange: 10.76.160.0/20 + - nodeName: "" + sliceRange: 10.76.176.0/20 + - nodeName: "" + sliceRange: 10.76.192.0/20 + - nodeName: "" + sliceRange: 10.76.208.0/20 + - nodeName: "" + sliceRange: 10.76.224.0/20 + - nodeName: "" + sliceRange: 10.76.240.0/20 + - nodeName: "" + sliceRange: 10.77.0.0/20 + - nodeName: "" + sliceRange: 10.77.16.0/20 + - nodeName: "" + sliceRange: 10.77.32.0/20 + - nodeName: "" + sliceRange: 10.77.48.0/20 + - nodeName: "" + sliceRange: 10.77.64.0/20 + - nodeName: "" + sliceRange: 10.77.80.0/20 + - nodeName: "" + sliceRange: 10.77.96.0/20 + - nodeName: "" + sliceRange: 10.77.112.0/20 + - nodeName: "" + sliceRange: 10.77.128.0/20 + - nodeName: "" + sliceRange: 10.77.144.0/20 + - nodeName: "" + sliceRange: 10.77.160.0/20 + - nodeName: "" + sliceRange: 10.77.176.0/20 + - nodeName: "" + sliceRange: 10.77.192.0/20 + - nodeName: "" + sliceRange: 10.77.208.0/20 + - nodeName: "" + sliceRange: 10.77.224.0/20 + - nodeName: "" + sliceRange: 10.77.240.0/20 + - nodeName: "" + sliceRange: 10.78.0.0/20 + - nodeName: "" + sliceRange: 10.78.16.0/20 + - nodeName: "" + sliceRange: 10.78.32.0/20 + - nodeName: "" + sliceRange: 10.78.48.0/20 + - nodeName: "" + sliceRange: 10.78.64.0/20 + - nodeName: "" + sliceRange: 10.78.80.0/20 + - nodeName: "" + sliceRange: 10.78.96.0/20 + - nodeName: "" + sliceRange: 10.78.112.0/20 + - nodeName: "" + sliceRange: 10.78.128.0/20 + - nodeName: "" + sliceRange: 10.78.144.0/20 + - nodeName: "" + sliceRange: 10.78.160.0/20 + - nodeName: "" + sliceRange: 10.78.176.0/20 + - nodeName: "" + sliceRange: 10.78.192.0/20 + - nodeName: "" + sliceRange: 10.78.208.0/20 + - nodeName: "" + sliceRange: 10.78.224.0/20 + - nodeName: "" + sliceRange: 10.78.240.0/20 + - nodeName: "" + sliceRange: 10.79.0.0/20 + - nodeName: "" + sliceRange: 10.79.16.0/20 + - nodeName: "" + sliceRange: 10.79.32.0/20 + - nodeName: "" + sliceRange: 10.79.48.0/20 + - nodeName: "" + sliceRange: 10.79.64.0/20 + - nodeName: "" + sliceRange: 10.79.80.0/20 + - nodeName: "" + sliceRange: 10.79.96.0/20 + - nodeName: "" + sliceRange: 10.79.112.0/20 + - nodeName: "" + sliceRange: 10.79.128.0/20 + - nodeName: "" + sliceRange: 10.79.144.0/20 + - nodeName: "" + sliceRange: 10.79.160.0/20 + - nodeName: "" + sliceRange: 10.79.176.0/20 + - nodeName: "" + sliceRange: 10.79.192.0/20 + - nodeName: "" + sliceRange: 10.79.208.0/20 + - nodeName: "" + sliceRange: 10.79.224.0/20 + - nodeName: "" + sliceRange: 10.79.240.0/20 + - nodeName: "" + sliceRange: 10.80.0.0/20 + - nodeName: "" + sliceRange: 10.80.16.0/20 + - nodeName: "" + sliceRange: 10.80.32.0/20 + - nodeName: "" + sliceRange: 10.80.48.0/20 + - nodeName: "" + sliceRange: 10.80.64.0/20 + - nodeName: "" + sliceRange: 10.80.80.0/20 + - nodeName: "" + sliceRange: 10.80.96.0/20 + - nodeName: "" + sliceRange: 10.80.112.0/20 + - nodeName: "" + sliceRange: 10.80.128.0/20 + - nodeName: "" + sliceRange: 10.80.144.0/20 + - nodeName: "" + sliceRange: 10.80.160.0/20 + - nodeName: "" + sliceRange: 10.80.176.0/20 + - nodeName: "" + sliceRange: 10.80.192.0/20 + - nodeName: "" + sliceRange: 10.80.208.0/20 + - nodeName: "" + sliceRange: 10.80.224.0/20 + - nodeName: "" + sliceRange: 10.80.240.0/20 + - nodeName: "" + sliceRange: 10.81.0.0/20 + - nodeName: "" + sliceRange: 10.81.16.0/20 + - nodeName: "" + sliceRange: 10.81.32.0/20 + - nodeName: "" + sliceRange: 10.81.48.0/20 + - nodeName: "" + sliceRange: 10.81.64.0/20 + - nodeName: "" + sliceRange: 10.81.80.0/20 + - nodeName: "" + sliceRange: 10.81.96.0/20 + - nodeName: "" + sliceRange: 10.81.112.0/20 + - nodeName: "" + sliceRange: 10.81.128.0/20 + - nodeName: "" + sliceRange: 10.81.144.0/20 + - nodeName: "" + sliceRange: 10.81.160.0/20 + - nodeName: "" + sliceRange: 10.81.176.0/20 + - nodeName: "" + sliceRange: 10.81.192.0/20 + - nodeName: "" + sliceRange: 10.81.208.0/20 + - nodeName: "" + sliceRange: 10.81.224.0/20 + - nodeName: "" + sliceRange: 10.81.240.0/20 + - nodeName: "" + sliceRange: 10.82.0.0/20 + - nodeName: "" + sliceRange: 10.82.16.0/20 + - nodeName: "" + sliceRange: 10.82.32.0/20 + - nodeName: "" + sliceRange: 10.82.48.0/20 + - nodeName: "" + sliceRange: 10.82.64.0/20 + - nodeName: "" + sliceRange: 10.82.80.0/20 + - nodeName: "" + sliceRange: 10.82.96.0/20 + - nodeName: "" + sliceRange: 10.82.112.0/20 + - nodeName: "" + sliceRange: 10.82.128.0/20 + - nodeName: "" + sliceRange: 10.82.144.0/20 + - nodeName: "" + sliceRange: 10.82.160.0/20 + - nodeName: "" + sliceRange: 10.82.176.0/20 + - nodeName: "" + sliceRange: 10.82.192.0/20 + - nodeName: "" + sliceRange: 10.82.208.0/20 + - nodeName: "" + sliceRange: 10.82.224.0/20 + - nodeName: "" + sliceRange: 10.82.240.0/20 + - nodeName: "" + sliceRange: 10.83.0.0/20 + - nodeName: "" + sliceRange: 10.83.16.0/20 + - nodeName: "" + sliceRange: 10.83.32.0/20 + - nodeName: "" + sliceRange: 10.83.48.0/20 + - nodeName: "" + sliceRange: 10.83.64.0/20 + - nodeName: "" + sliceRange: 10.83.80.0/20 + - nodeName: "" + sliceRange: 10.83.96.0/20 + - nodeName: "" + sliceRange: 10.83.112.0/20 + - nodeName: "" + sliceRange: 10.83.128.0/20 + - nodeName: "" + sliceRange: 10.83.144.0/20 + - nodeName: "" + sliceRange: 10.83.160.0/20 + - nodeName: "" + sliceRange: 10.83.176.0/20 + - nodeName: "" + sliceRange: 10.83.192.0/20 + - nodeName: "" + sliceRange: 10.83.208.0/20 + - nodeName: "" + sliceRange: 10.83.224.0/20 + - nodeName: "" + sliceRange: 10.83.240.0/20 + - nodeName: "" + sliceRange: 10.84.0.0/20 + - nodeName: "" + sliceRange: 10.84.16.0/20 + - nodeName: "" + sliceRange: 10.84.32.0/20 + - nodeName: "" + sliceRange: 10.84.48.0/20 + - nodeName: "" + sliceRange: 10.84.64.0/20 + - nodeName: "" + sliceRange: 10.84.80.0/20 + - nodeName: "" + sliceRange: 10.84.96.0/20 + - nodeName: "" + sliceRange: 10.84.112.0/20 + - nodeName: "" + sliceRange: 10.84.128.0/20 + - nodeName: "" + sliceRange: 10.84.144.0/20 + - nodeName: "" + sliceRange: 10.84.160.0/20 + - nodeName: "" + sliceRange: 10.84.176.0/20 + - nodeName: "" + sliceRange: 10.84.192.0/20 + - nodeName: "" + sliceRange: 10.84.208.0/20 + - nodeName: "" + sliceRange: 10.84.224.0/20 + - nodeName: "" + sliceRange: 10.84.240.0/20 + - nodeName: "" + sliceRange: 10.85.0.0/20 + - nodeName: "" + sliceRange: 10.85.16.0/20 + - nodeName: "" + sliceRange: 10.85.32.0/20 + - nodeName: "" + sliceRange: 10.85.48.0/20 + - nodeName: "" + sliceRange: 10.85.64.0/20 + - nodeName: "" + sliceRange: 10.85.80.0/20 + - nodeName: "" + sliceRange: 10.85.96.0/20 + - nodeName: "" + sliceRange: 10.85.112.0/20 + - nodeName: "" + sliceRange: 10.85.128.0/20 + - nodeName: "" + sliceRange: 10.85.144.0/20 + - nodeName: "" + sliceRange: 10.85.160.0/20 + - nodeName: "" + sliceRange: 10.85.176.0/20 + - nodeName: "" + sliceRange: 10.85.192.0/20 + - nodeName: "" + sliceRange: 10.85.208.0/20 + - nodeName: "" + sliceRange: 10.85.224.0/20 + - nodeName: "" + sliceRange: 10.85.240.0/20 + - nodeName: "" + sliceRange: 10.86.0.0/20 + - nodeName: "" + sliceRange: 10.86.16.0/20 + - nodeName: "" + sliceRange: 10.86.32.0/20 + - nodeName: "" + sliceRange: 10.86.48.0/20 + - nodeName: "" + sliceRange: 10.86.64.0/20 + - nodeName: "" + sliceRange: 10.86.80.0/20 + - nodeName: "" + sliceRange: 10.86.96.0/20 + - nodeName: "" + sliceRange: 10.86.112.0/20 + - nodeName: "" + sliceRange: 10.86.128.0/20 + - nodeName: "" + sliceRange: 10.86.144.0/20 + - nodeName: "" + sliceRange: 10.86.160.0/20 + - nodeName: "" + sliceRange: 10.86.176.0/20 + - nodeName: "" + sliceRange: 10.86.192.0/20 + - nodeName: "" + sliceRange: 10.86.208.0/20 + - nodeName: "" + sliceRange: 10.86.224.0/20 + - nodeName: "" + sliceRange: 10.86.240.0/20 + - nodeName: "" + sliceRange: 10.87.0.0/20 + - nodeName: "" + sliceRange: 10.87.16.0/20 + - nodeName: "" + sliceRange: 10.87.32.0/20 + - nodeName: "" + sliceRange: 10.87.48.0/20 + - nodeName: "" + sliceRange: 10.87.64.0/20 + - nodeName: "" + sliceRange: 10.87.80.0/20 + - nodeName: "" + sliceRange: 10.87.96.0/20 + - nodeName: "" + sliceRange: 10.87.112.0/20 + - nodeName: "" + sliceRange: 10.87.128.0/20 + - nodeName: "" + sliceRange: 10.87.144.0/20 + - nodeName: "" + sliceRange: 10.87.160.0/20 + - nodeName: "" + sliceRange: 10.87.176.0/20 + - nodeName: "" + sliceRange: 10.87.192.0/20 + - nodeName: "" + sliceRange: 10.87.208.0/20 + - nodeName: "" + sliceRange: 10.87.224.0/20 + - nodeName: "" + sliceRange: 10.87.240.0/20 + - nodeName: "" + sliceRange: 10.88.0.0/20 + - nodeName: "" + sliceRange: 10.88.16.0/20 + - nodeName: "" + sliceRange: 10.88.32.0/20 + - nodeName: "" + sliceRange: 10.88.48.0/20 + - nodeName: "" + sliceRange: 10.88.64.0/20 + - nodeName: "" + sliceRange: 10.88.80.0/20 + - nodeName: "" + sliceRange: 10.88.96.0/20 + - nodeName: "" + sliceRange: 10.88.112.0/20 + - nodeName: "" + sliceRange: 10.88.128.0/20 + - nodeName: "" + sliceRange: 10.88.144.0/20 + - nodeName: "" + sliceRange: 10.88.160.0/20 + - nodeName: "" + sliceRange: 10.88.176.0/20 + - nodeName: "" + sliceRange: 10.88.192.0/20 + - nodeName: "" + sliceRange: 10.88.208.0/20 + - nodeName: "" + sliceRange: 10.88.224.0/20 + - nodeName: "" + sliceRange: 10.88.240.0/20 + - nodeName: "" + sliceRange: 10.89.0.0/20 + - nodeName: "" + sliceRange: 10.89.16.0/20 + - nodeName: "" + sliceRange: 10.89.32.0/20 + - nodeName: "" + sliceRange: 10.89.48.0/20 + - nodeName: "" + sliceRange: 10.89.64.0/20 + - nodeName: "" + sliceRange: 10.89.80.0/20 + - nodeName: "" + sliceRange: 10.89.96.0/20 + - nodeName: "" + sliceRange: 10.89.112.0/20 + - nodeName: "" + sliceRange: 10.89.128.0/20 + - nodeName: "" + sliceRange: 10.89.144.0/20 + - nodeName: "" + sliceRange: 10.89.160.0/20 + - nodeName: "" + sliceRange: 10.89.176.0/20 + - nodeName: "" + sliceRange: 10.89.192.0/20 + - nodeName: "" + sliceRange: 10.89.208.0/20 + - nodeName: "" + sliceRange: 10.89.224.0/20 + - nodeName: "" + sliceRange: 10.89.240.0/20 + - nodeName: "" + sliceRange: 10.90.0.0/20 + - nodeName: "" + sliceRange: 10.90.16.0/20 + - nodeName: "" + sliceRange: 10.90.32.0/20 + - nodeName: "" + sliceRange: 10.90.48.0/20 + - nodeName: "" + sliceRange: 10.90.64.0/20 + - nodeName: "" + sliceRange: 10.90.80.0/20 + - nodeName: "" + sliceRange: 10.90.96.0/20 + - nodeName: "" + sliceRange: 10.90.112.0/20 + - nodeName: "" + sliceRange: 10.90.128.0/20 + - nodeName: "" + sliceRange: 10.90.144.0/20 + - nodeName: "" + sliceRange: 10.90.160.0/20 + - nodeName: "" + sliceRange: 10.90.176.0/20 + - nodeName: "" + sliceRange: 10.90.192.0/20 + - nodeName: "" + sliceRange: 10.90.208.0/20 + - nodeName: "" + sliceRange: 10.90.224.0/20 + - nodeName: "" + sliceRange: 10.90.240.0/20 + - nodeName: "" + sliceRange: 10.91.0.0/20 + - nodeName: "" + sliceRange: 10.91.16.0/20 + - nodeName: "" + sliceRange: 10.91.32.0/20 + - nodeName: "" + sliceRange: 10.91.48.0/20 + - nodeName: "" + sliceRange: 10.91.64.0/20 + - nodeName: "" + sliceRange: 10.91.80.0/20 + - nodeName: "" + sliceRange: 10.91.96.0/20 + - nodeName: "" + sliceRange: 10.91.112.0/20 + - nodeName: "" + sliceRange: 10.91.128.0/20 + - nodeName: "" + sliceRange: 10.91.144.0/20 + - nodeName: "" + sliceRange: 10.91.160.0/20 + - nodeName: "" + sliceRange: 10.91.176.0/20 + - nodeName: "" + sliceRange: 10.91.192.0/20 + - nodeName: "" + sliceRange: 10.91.208.0/20 + - nodeName: "" + sliceRange: 10.91.224.0/20 + - nodeName: "" + sliceRange: 10.91.240.0/20 + - nodeName: "" + sliceRange: 10.92.0.0/20 + - nodeName: "" + sliceRange: 10.92.16.0/20 + - nodeName: "" + sliceRange: 10.92.32.0/20 + - nodeName: "" + sliceRange: 10.92.48.0/20 + - nodeName: "" + sliceRange: 10.92.64.0/20 + - nodeName: "" + sliceRange: 10.92.80.0/20 + - nodeName: "" + sliceRange: 10.92.96.0/20 + - nodeName: "" + sliceRange: 10.92.112.0/20 + - nodeName: "" + sliceRange: 10.92.128.0/20 + - nodeName: "" + sliceRange: 10.92.144.0/20 + - nodeName: "" + sliceRange: 10.92.160.0/20 + - nodeName: "" + sliceRange: 10.92.176.0/20 + - nodeName: "" + sliceRange: 10.92.192.0/20 + - nodeName: "" + sliceRange: 10.92.208.0/20 + - nodeName: "" + sliceRange: 10.92.224.0/20 + - nodeName: "" + sliceRange: 10.92.240.0/20 + - nodeName: "" + sliceRange: 10.93.0.0/20 + - nodeName: "" + sliceRange: 10.93.16.0/20 + - nodeName: "" + sliceRange: 10.93.32.0/20 + - nodeName: "" + sliceRange: 10.93.48.0/20 + - nodeName: "" + sliceRange: 10.93.64.0/20 + - nodeName: "" + sliceRange: 10.93.80.0/20 + - nodeName: "" + sliceRange: 10.93.96.0/20 + - nodeName: "" + sliceRange: 10.93.112.0/20 + - nodeName: "" + sliceRange: 10.93.128.0/20 + - nodeName: "" + sliceRange: 10.93.144.0/20 + - nodeName: "" + sliceRange: 10.93.160.0/20 + - nodeName: "" + sliceRange: 10.93.176.0/20 + - nodeName: "" + sliceRange: 10.93.192.0/20 + - nodeName: "" + sliceRange: 10.93.208.0/20 + - nodeName: "" + sliceRange: 10.93.224.0/20 + - nodeName: "" + sliceRange: 10.93.240.0/20 + - nodeName: "" + sliceRange: 10.94.0.0/20 + - nodeName: "" + sliceRange: 10.94.16.0/20 + - nodeName: "" + sliceRange: 10.94.32.0/20 + - nodeName: "" + sliceRange: 10.94.48.0/20 + - nodeName: "" + sliceRange: 10.94.64.0/20 + - nodeName: "" + sliceRange: 10.94.80.0/20 + - nodeName: "" + sliceRange: 10.94.96.0/20 + - nodeName: "" + sliceRange: 10.94.112.0/20 + - nodeName: "" + sliceRange: 10.94.128.0/20 + - nodeName: "" + sliceRange: 10.94.144.0/20 + - nodeName: "" + sliceRange: 10.94.160.0/20 + - nodeName: "" + sliceRange: 10.94.176.0/20 + - nodeName: "" + sliceRange: 10.94.192.0/20 + - nodeName: "" + sliceRange: 10.94.208.0/20 + - nodeName: "" + sliceRange: 10.94.224.0/20 + - nodeName: "" + sliceRange: 10.94.240.0/20 + - nodeName: "" + sliceRange: 10.95.0.0/20 + - nodeName: "" + sliceRange: 10.95.16.0/20 + - nodeName: "" + sliceRange: 10.95.32.0/20 + - nodeName: "" + sliceRange: 10.95.48.0/20 + - nodeName: "" + sliceRange: 10.95.64.0/20 + - nodeName: "" + sliceRange: 10.95.80.0/20 + - nodeName: "" + sliceRange: 10.95.96.0/20 + - nodeName: "" + sliceRange: 10.95.112.0/20 + - nodeName: "" + sliceRange: 10.95.128.0/20 + - nodeName: "" + sliceRange: 10.95.144.0/20 + - nodeName: "" + sliceRange: 10.95.160.0/20 + - nodeName: "" + sliceRange: 10.95.176.0/20 + - nodeName: "" + sliceRange: 10.95.192.0/20 + - nodeName: "" + sliceRange: 10.95.208.0/20 + - nodeName: "" + sliceRange: 10.95.224.0/20 + - nodeName: "" + sliceRange: 10.95.240.0/20 + - nodeName: "" + sliceRange: 10.96.0.0/20 + - nodeName: "" + sliceRange: 10.96.16.0/20 + - nodeName: "" + sliceRange: 10.96.32.0/20 + - nodeName: "" + sliceRange: 10.96.48.0/20 + - nodeName: "" + sliceRange: 10.96.64.0/20 + - nodeName: "" + sliceRange: 10.96.80.0/20 + - nodeName: "" + sliceRange: 10.96.96.0/20 + - nodeName: "" + sliceRange: 10.96.112.0/20 + - nodeName: "" + sliceRange: 10.96.128.0/20 + - nodeName: "" + sliceRange: 10.96.144.0/20 + - nodeName: "" + sliceRange: 10.96.160.0/20 + - nodeName: "" + sliceRange: 10.96.176.0/20 + - nodeName: "" + sliceRange: 10.96.192.0/20 + - nodeName: "" + sliceRange: 10.96.208.0/20 + - nodeName: "" + sliceRange: 10.96.224.0/20 + - nodeName: "" + sliceRange: 10.96.240.0/20 + - nodeName: "" + sliceRange: 10.97.0.0/20 + - nodeName: "" + sliceRange: 10.97.16.0/20 + - nodeName: "" + sliceRange: 10.97.32.0/20 + - nodeName: "" + sliceRange: 10.97.48.0/20 + - nodeName: "" + sliceRange: 10.97.64.0/20 + - nodeName: "" + sliceRange: 10.97.80.0/20 + - nodeName: "" + sliceRange: 10.97.96.0/20 + - nodeName: "" + sliceRange: 10.97.112.0/20 + - nodeName: "" + sliceRange: 10.97.128.0/20 + - nodeName: "" + sliceRange: 10.97.144.0/20 + - nodeName: "" + sliceRange: 10.97.160.0/20 + - nodeName: "" + sliceRange: 10.97.176.0/20 + - nodeName: "" + sliceRange: 10.97.192.0/20 + - nodeName: "" + sliceRange: 10.97.208.0/20 + - nodeName: "" + sliceRange: 10.97.224.0/20 + - nodeName: "" + sliceRange: 10.97.240.0/20 + - nodeName: "" + sliceRange: 10.98.0.0/20 + - nodeName: "" + sliceRange: 10.98.16.0/20 + - nodeName: "" + sliceRange: 10.98.32.0/20 + - nodeName: "" + sliceRange: 10.98.48.0/20 + - nodeName: "" + sliceRange: 10.98.64.0/20 + - nodeName: "" + sliceRange: 10.98.80.0/20 + - nodeName: "" + sliceRange: 10.98.96.0/20 + - nodeName: "" + sliceRange: 10.98.112.0/20 + - nodeName: "" + sliceRange: 10.98.128.0/20 + - nodeName: "" + sliceRange: 10.98.144.0/20 + - nodeName: "" + sliceRange: 10.98.160.0/20 + - nodeName: "" + sliceRange: 10.98.176.0/20 + - nodeName: "" + sliceRange: 10.98.192.0/20 + - nodeName: "" + sliceRange: 10.98.208.0/20 + - nodeName: "" + sliceRange: 10.98.224.0/20 + - nodeName: "" + sliceRange: 10.98.240.0/20 + - nodeName: "" + sliceRange: 10.99.0.0/20 + - nodeName: "" + sliceRange: 10.99.16.0/20 + - nodeName: "" + sliceRange: 10.99.32.0/20 + - nodeName: "" + sliceRange: 10.99.48.0/20 + - nodeName: "" + sliceRange: 10.99.64.0/20 + - nodeName: "" + sliceRange: 10.99.80.0/20 + - nodeName: "" + sliceRange: 10.99.96.0/20 + - nodeName: "" + sliceRange: 10.99.112.0/20 + - nodeName: "" + sliceRange: 10.99.128.0/20 + - nodeName: "" + sliceRange: 10.99.144.0/20 + - nodeName: "" + sliceRange: 10.99.160.0/20 + - nodeName: "" + sliceRange: 10.99.176.0/20 + - nodeName: "" + sliceRange: 10.99.192.0/20 + - nodeName: "" + sliceRange: 10.99.208.0/20 + - nodeName: "" + sliceRange: 10.99.224.0/20 + - nodeName: "" + sliceRange: 10.99.240.0/20 + - nodeName: "" + sliceRange: 10.100.0.0/20 + - nodeName: "" + sliceRange: 10.100.16.0/20 + - nodeName: "" + sliceRange: 10.100.32.0/20 + - nodeName: "" + sliceRange: 10.100.48.0/20 + - nodeName: "" + sliceRange: 10.100.64.0/20 + - nodeName: "" + sliceRange: 10.100.80.0/20 + - nodeName: "" + sliceRange: 10.100.96.0/20 + - nodeName: "" + sliceRange: 10.100.112.0/20 + - nodeName: "" + sliceRange: 10.100.128.0/20 + - nodeName: "" + sliceRange: 10.100.144.0/20 + - nodeName: "" + sliceRange: 10.100.160.0/20 + - nodeName: "" + sliceRange: 10.100.176.0/20 + - nodeName: "" + sliceRange: 10.100.192.0/20 + - nodeName: "" + sliceRange: 10.100.208.0/20 + - nodeName: "" + sliceRange: 10.100.224.0/20 + - nodeName: "" + sliceRange: 10.100.240.0/20 + - nodeName: "" + sliceRange: 10.101.0.0/20 + - nodeName: "" + sliceRange: 10.101.16.0/20 + - nodeName: "" + sliceRange: 10.101.32.0/20 + - nodeName: "" + sliceRange: 10.101.48.0/20 + - nodeName: "" + sliceRange: 10.101.64.0/20 + - nodeName: "" + sliceRange: 10.101.80.0/20 + - nodeName: "" + sliceRange: 10.101.96.0/20 + - nodeName: "" + sliceRange: 10.101.112.0/20 + - nodeName: "" + sliceRange: 10.101.128.0/20 + - nodeName: "" + sliceRange: 10.101.144.0/20 + - nodeName: "" + sliceRange: 10.101.160.0/20 + - nodeName: "" + sliceRange: 10.101.176.0/20 + - nodeName: "" + sliceRange: 10.101.192.0/20 + - nodeName: "" + sliceRange: 10.101.208.0/20 + - nodeName: "" + sliceRange: 10.101.224.0/20 + - nodeName: "" + sliceRange: 10.101.240.0/20 + - nodeName: "" + sliceRange: 10.102.0.0/20 + - nodeName: "" + sliceRange: 10.102.16.0/20 + - nodeName: "" + sliceRange: 10.102.32.0/20 + - nodeName: "" + sliceRange: 10.102.48.0/20 + - nodeName: "" + sliceRange: 10.102.64.0/20 + - nodeName: "" + sliceRange: 10.102.80.0/20 + - nodeName: "" + sliceRange: 10.102.96.0/20 + - nodeName: "" + sliceRange: 10.102.112.0/20 + - nodeName: "" + sliceRange: 10.102.128.0/20 + - nodeName: "" + sliceRange: 10.102.144.0/20 + - nodeName: "" + sliceRange: 10.102.160.0/20 + - nodeName: "" + sliceRange: 10.102.176.0/20 + - nodeName: "" + sliceRange: 10.102.192.0/20 + - nodeName: "" + sliceRange: 10.102.208.0/20 + - nodeName: "" + sliceRange: 10.102.224.0/20 + - nodeName: "" + sliceRange: 10.102.240.0/20 + - nodeName: "" + sliceRange: 10.103.0.0/20 + - nodeName: "" + sliceRange: 10.103.16.0/20 + - nodeName: "" + sliceRange: 10.103.32.0/20 + - nodeName: "" + sliceRange: 10.103.48.0/20 + - nodeName: "" + sliceRange: 10.103.64.0/20 + - nodeName: "" + sliceRange: 10.103.80.0/20 + - nodeName: "" + sliceRange: 10.103.96.0/20 + - nodeName: "" + sliceRange: 10.103.112.0/20 + - nodeName: "" + sliceRange: 10.103.128.0/20 + - nodeName: "" + sliceRange: 10.103.144.0/20 + - nodeName: "" + sliceRange: 10.103.160.0/20 + - nodeName: "" + sliceRange: 10.103.176.0/20 + - nodeName: "" + sliceRange: 10.103.192.0/20 + - nodeName: "" + sliceRange: 10.103.208.0/20 + - nodeName: "" + sliceRange: 10.103.224.0/20 + - nodeName: "" + sliceRange: 10.103.240.0/20 + - nodeName: "" + sliceRange: 10.104.0.0/20 + - nodeName: "" + sliceRange: 10.104.16.0/20 + - nodeName: "" + sliceRange: 10.104.32.0/20 + - nodeName: "" + sliceRange: 10.104.48.0/20 + - nodeName: "" + sliceRange: 10.104.64.0/20 + - nodeName: "" + sliceRange: 10.104.80.0/20 + - nodeName: "" + sliceRange: 10.104.96.0/20 + - nodeName: "" + sliceRange: 10.104.112.0/20 + - nodeName: "" + sliceRange: 10.104.128.0/20 + - nodeName: "" + sliceRange: 10.104.144.0/20 + - nodeName: "" + sliceRange: 10.104.160.0/20 + - nodeName: "" + sliceRange: 10.104.176.0/20 + - nodeName: "" + sliceRange: 10.104.192.0/20 + - nodeName: "" + sliceRange: 10.104.208.0/20 + - nodeName: "" + sliceRange: 10.104.224.0/20 + - nodeName: "" + sliceRange: 10.104.240.0/20 + - nodeName: "" + sliceRange: 10.105.0.0/20 + - nodeName: "" + sliceRange: 10.105.16.0/20 + - nodeName: "" + sliceRange: 10.105.32.0/20 + - nodeName: "" + sliceRange: 10.105.48.0/20 + - nodeName: "" + sliceRange: 10.105.64.0/20 + - nodeName: "" + sliceRange: 10.105.80.0/20 + - nodeName: "" + sliceRange: 10.105.96.0/20 + - nodeName: "" + sliceRange: 10.105.112.0/20 + - nodeName: "" + sliceRange: 10.105.128.0/20 + - nodeName: "" + sliceRange: 10.105.144.0/20 + - nodeName: "" + sliceRange: 10.105.160.0/20 + - nodeName: "" + sliceRange: 10.105.176.0/20 + - nodeName: "" + sliceRange: 10.105.192.0/20 + - nodeName: "" + sliceRange: 10.105.208.0/20 + - nodeName: "" + sliceRange: 10.105.224.0/20 + - nodeName: "" + sliceRange: 10.105.240.0/20 + - nodeName: "" + sliceRange: 10.106.0.0/20 + - nodeName: "" + sliceRange: 10.106.16.0/20 + - nodeName: "" + sliceRange: 10.106.32.0/20 + - nodeName: "" + sliceRange: 10.106.48.0/20 + - nodeName: "" + sliceRange: 10.106.64.0/20 + - nodeName: "" + sliceRange: 10.106.80.0/20 + - nodeName: "" + sliceRange: 10.106.96.0/20 + - nodeName: "" + sliceRange: 10.106.112.0/20 + - nodeName: "" + sliceRange: 10.106.128.0/20 + - nodeName: "" + sliceRange: 10.106.144.0/20 + - nodeName: "" + sliceRange: 10.106.160.0/20 + - nodeName: "" + sliceRange: 10.106.176.0/20 + - nodeName: "" + sliceRange: 10.106.192.0/20 + - nodeName: "" + sliceRange: 10.106.208.0/20 + - nodeName: "" + sliceRange: 10.106.224.0/20 + - nodeName: "" + sliceRange: 10.106.240.0/20 + - nodeName: "" + sliceRange: 10.107.0.0/20 + - nodeName: "" + sliceRange: 10.107.16.0/20 + - nodeName: "" + sliceRange: 10.107.32.0/20 + - nodeName: "" + sliceRange: 10.107.48.0/20 + - nodeName: "" + sliceRange: 10.107.64.0/20 + - nodeName: "" + sliceRange: 10.107.80.0/20 + - nodeName: "" + sliceRange: 10.107.96.0/20 + - nodeName: "" + sliceRange: 10.107.112.0/20 + - nodeName: "" + sliceRange: 10.107.128.0/20 + - nodeName: "" + sliceRange: 10.107.144.0/20 + - nodeName: "" + sliceRange: 10.107.160.0/20 + - nodeName: "" + sliceRange: 10.107.176.0/20 + - nodeName: "" + sliceRange: 10.107.192.0/20 + - nodeName: "" + sliceRange: 10.107.208.0/20 + - nodeName: "" + sliceRange: 10.107.224.0/20 + - nodeName: "" + sliceRange: 10.107.240.0/20 + - nodeName: "" + sliceRange: 10.108.0.0/20 + - nodeName: "" + sliceRange: 10.108.16.0/20 + - nodeName: "" + sliceRange: 10.108.32.0/20 + - nodeName: "" + sliceRange: 10.108.48.0/20 + - nodeName: "" + sliceRange: 10.108.64.0/20 + - nodeName: "" + sliceRange: 10.108.80.0/20 + - nodeName: "" + sliceRange: 10.108.96.0/20 + - nodeName: "" + sliceRange: 10.108.112.0/20 + - nodeName: "" + sliceRange: 10.108.128.0/20 + - nodeName: "" + sliceRange: 10.108.144.0/20 + - nodeName: "" + sliceRange: 10.108.160.0/20 + - nodeName: "" + sliceRange: 10.108.176.0/20 + - nodeName: "" + sliceRange: 10.108.192.0/20 + - nodeName: "" + sliceRange: 10.108.208.0/20 + - nodeName: "" + sliceRange: 10.108.224.0/20 + - nodeName: "" + sliceRange: 10.108.240.0/20 + - nodeName: "" + sliceRange: 10.109.0.0/20 + - nodeName: "" + sliceRange: 10.109.16.0/20 + - nodeName: "" + sliceRange: 10.109.32.0/20 + - nodeName: "" + sliceRange: 10.109.48.0/20 + - nodeName: "" + sliceRange: 10.109.64.0/20 + - nodeName: "" + sliceRange: 10.109.80.0/20 + - nodeName: "" + sliceRange: 10.109.96.0/20 + - nodeName: "" + sliceRange: 10.109.112.0/20 + - nodeName: "" + sliceRange: 10.109.128.0/20 + - nodeName: "" + sliceRange: 10.109.144.0/20 + - nodeName: "" + sliceRange: 10.109.160.0/20 + - nodeName: "" + sliceRange: 10.109.176.0/20 + - nodeName: "" + sliceRange: 10.109.192.0/20 + - nodeName: "" + sliceRange: 10.109.208.0/20 + - nodeName: "" + sliceRange: 10.109.224.0/20 + - nodeName: "" + sliceRange: 10.109.240.0/20 + - nodeName: "" + sliceRange: 10.110.0.0/20 + - nodeName: "" + sliceRange: 10.110.16.0/20 + - nodeName: "" + sliceRange: 10.110.32.0/20 + - nodeName: "" + sliceRange: 10.110.48.0/20 + - nodeName: "" + sliceRange: 10.110.64.0/20 + - nodeName: "" + sliceRange: 10.110.80.0/20 + - nodeName: "" + sliceRange: 10.110.96.0/20 + - nodeName: "" + sliceRange: 10.110.112.0/20 + - nodeName: "" + sliceRange: 10.110.128.0/20 + - nodeName: "" + sliceRange: 10.110.144.0/20 + - nodeName: "" + sliceRange: 10.110.160.0/20 + - nodeName: "" + sliceRange: 10.110.176.0/20 + - nodeName: "" + sliceRange: 10.110.192.0/20 + - nodeName: "" + sliceRange: 10.110.208.0/20 + - nodeName: "" + sliceRange: 10.110.224.0/20 + - nodeName: "" + sliceRange: 10.110.240.0/20 + - nodeName: "" + sliceRange: 10.111.0.0/20 + - nodeName: "" + sliceRange: 10.111.16.0/20 + - nodeName: "" + sliceRange: 10.111.32.0/20 + - nodeName: "" + sliceRange: 10.111.48.0/20 + - nodeName: "" + sliceRange: 10.111.64.0/20 + - nodeName: "" + sliceRange: 10.111.80.0/20 + - nodeName: "" + sliceRange: 10.111.96.0/20 + - nodeName: "" + sliceRange: 10.111.112.0/20 + - nodeName: "" + sliceRange: 10.111.128.0/20 + - nodeName: "" + sliceRange: 10.111.144.0/20 + - nodeName: "" + sliceRange: 10.111.160.0/20 + - nodeName: "" + sliceRange: 10.111.176.0/20 + - nodeName: "" + sliceRange: 10.111.192.0/20 + - nodeName: "" + sliceRange: 10.111.208.0/20 + - nodeName: "" + sliceRange: 10.111.224.0/20 + - nodeName: "" + sliceRange: 10.111.240.0/20 + - nodeName: "" + sliceRange: 10.112.0.0/20 + - nodeName: "" + sliceRange: 10.112.16.0/20 + - nodeName: "" + sliceRange: 10.112.32.0/20 + - nodeName: "" + sliceRange: 10.112.48.0/20 + - nodeName: "" + sliceRange: 10.112.64.0/20 + - nodeName: "" + sliceRange: 10.112.80.0/20 + - nodeName: "" + sliceRange: 10.112.96.0/20 + - nodeName: "" + sliceRange: 10.112.112.0/20 + - nodeName: "" + sliceRange: 10.112.128.0/20 + - nodeName: "" + sliceRange: 10.112.144.0/20 + - nodeName: "" + sliceRange: 10.112.160.0/20 + - nodeName: "" + sliceRange: 10.112.176.0/20 + - nodeName: "" + sliceRange: 10.112.192.0/20 + - nodeName: "" + sliceRange: 10.112.208.0/20 + - nodeName: "" + sliceRange: 10.112.224.0/20 + - nodeName: "" + sliceRange: 10.112.240.0/20 + - nodeName: "" + sliceRange: 10.113.0.0/20 + - nodeName: "" + sliceRange: 10.113.16.0/20 + - nodeName: "" + sliceRange: 10.113.32.0/20 + - nodeName: "" + sliceRange: 10.113.48.0/20 + - nodeName: "" + sliceRange: 10.113.64.0/20 + - nodeName: "" + sliceRange: 10.113.80.0/20 + - nodeName: "" + sliceRange: 10.113.96.0/20 + - nodeName: "" + sliceRange: 10.113.112.0/20 + - nodeName: "" + sliceRange: 10.113.128.0/20 + - nodeName: "" + sliceRange: 10.113.144.0/20 + - nodeName: "" + sliceRange: 10.113.160.0/20 + - nodeName: "" + sliceRange: 10.113.176.0/20 + - nodeName: "" + sliceRange: 10.113.192.0/20 + - nodeName: "" + sliceRange: 10.113.208.0/20 + - nodeName: "" + sliceRange: 10.113.224.0/20 + - nodeName: "" + sliceRange: 10.113.240.0/20 + - nodeName: "" + sliceRange: 10.114.0.0/20 + - nodeName: "" + sliceRange: 10.114.16.0/20 + - nodeName: "" + sliceRange: 10.114.32.0/20 + - nodeName: "" + sliceRange: 10.114.48.0/20 + - nodeName: "" + sliceRange: 10.114.64.0/20 + - nodeName: "" + sliceRange: 10.114.80.0/20 + - nodeName: "" + sliceRange: 10.114.96.0/20 + - nodeName: "" + sliceRange: 10.114.112.0/20 + - nodeName: "" + sliceRange: 10.114.128.0/20 + - nodeName: "" + sliceRange: 10.114.144.0/20 + - nodeName: "" + sliceRange: 10.114.160.0/20 + - nodeName: "" + sliceRange: 10.114.176.0/20 + - nodeName: "" + sliceRange: 10.114.192.0/20 + - nodeName: "" + sliceRange: 10.114.208.0/20 + - nodeName: "" + sliceRange: 10.114.224.0/20 + - nodeName: "" + sliceRange: 10.114.240.0/20 + - nodeName: "" + sliceRange: 10.115.0.0/20 + - nodeName: "" + sliceRange: 10.115.16.0/20 + - nodeName: "" + sliceRange: 10.115.32.0/20 + - nodeName: "" + sliceRange: 10.115.48.0/20 + - nodeName: "" + sliceRange: 10.115.64.0/20 + - nodeName: "" + sliceRange: 10.115.80.0/20 + - nodeName: "" + sliceRange: 10.115.96.0/20 + - nodeName: "" + sliceRange: 10.115.112.0/20 + - nodeName: "" + sliceRange: 10.115.128.0/20 + - nodeName: "" + sliceRange: 10.115.144.0/20 + - nodeName: "" + sliceRange: 10.115.160.0/20 + - nodeName: "" + sliceRange: 10.115.176.0/20 + - nodeName: "" + sliceRange: 10.115.192.0/20 + - nodeName: "" + sliceRange: 10.115.208.0/20 + - nodeName: "" + sliceRange: 10.115.224.0/20 + - nodeName: "" + sliceRange: 10.115.240.0/20 + - nodeName: "" + sliceRange: 10.116.0.0/20 + - nodeName: "" + sliceRange: 10.116.16.0/20 + - nodeName: "" + sliceRange: 10.116.32.0/20 + - nodeName: "" + sliceRange: 10.116.48.0/20 + - nodeName: "" + sliceRange: 10.116.64.0/20 + - nodeName: "" + sliceRange: 10.116.80.0/20 + - nodeName: "" + sliceRange: 10.116.96.0/20 + - nodeName: "" + sliceRange: 10.116.112.0/20 + - nodeName: "" + sliceRange: 10.116.128.0/20 + - nodeName: "" + sliceRange: 10.116.144.0/20 + - nodeName: "" + sliceRange: 10.116.160.0/20 + - nodeName: "" + sliceRange: 10.116.176.0/20 + - nodeName: "" + sliceRange: 10.116.192.0/20 + - nodeName: "" + sliceRange: 10.116.208.0/20 + - nodeName: "" + sliceRange: 10.116.224.0/20 + - nodeName: "" + sliceRange: 10.116.240.0/20 + - nodeName: "" + sliceRange: 10.117.0.0/20 + - nodeName: "" + sliceRange: 10.117.16.0/20 + - nodeName: "" + sliceRange: 10.117.32.0/20 + - nodeName: "" + sliceRange: 10.117.48.0/20 + - nodeName: "" + sliceRange: 10.117.64.0/20 + - nodeName: "" + sliceRange: 10.117.80.0/20 + - nodeName: "" + sliceRange: 10.117.96.0/20 + - nodeName: "" + sliceRange: 10.117.112.0/20 + - nodeName: "" + sliceRange: 10.117.128.0/20 + - nodeName: "" + sliceRange: 10.117.144.0/20 + - nodeName: "" + sliceRange: 10.117.160.0/20 + - nodeName: "" + sliceRange: 10.117.176.0/20 + - nodeName: "" + sliceRange: 10.117.192.0/20 + - nodeName: "" + sliceRange: 10.117.208.0/20 + - nodeName: "" + sliceRange: 10.117.224.0/20 + - nodeName: "" + sliceRange: 10.117.240.0/20 + - nodeName: "" + sliceRange: 10.118.0.0/20 + - nodeName: "" + sliceRange: 10.118.16.0/20 + - nodeName: "" + sliceRange: 10.118.32.0/20 + - nodeName: "" + sliceRange: 10.118.48.0/20 + - nodeName: "" + sliceRange: 10.118.64.0/20 + - nodeName: "" + sliceRange: 10.118.80.0/20 + - nodeName: "" + sliceRange: 10.118.96.0/20 + - nodeName: "" + sliceRange: 10.118.112.0/20 + - nodeName: "" + sliceRange: 10.118.128.0/20 + - nodeName: "" + sliceRange: 10.118.144.0/20 + - nodeName: "" + sliceRange: 10.118.160.0/20 + - nodeName: "" + sliceRange: 10.118.176.0/20 + - nodeName: "" + sliceRange: 10.118.192.0/20 + - nodeName: "" + sliceRange: 10.118.208.0/20 + - nodeName: "" + sliceRange: 10.118.224.0/20 + - nodeName: "" + sliceRange: 10.118.240.0/20 + - nodeName: "" + sliceRange: 10.119.0.0/20 + - nodeName: "" + sliceRange: 10.119.16.0/20 + - nodeName: "" + sliceRange: 10.119.32.0/20 + - nodeName: "" + sliceRange: 10.119.48.0/20 + - nodeName: "" + sliceRange: 10.119.64.0/20 + - nodeName: "" + sliceRange: 10.119.80.0/20 + - nodeName: "" + sliceRange: 10.119.96.0/20 + - nodeName: "" + sliceRange: 10.119.112.0/20 + - nodeName: "" + sliceRange: 10.119.128.0/20 + - nodeName: "" + sliceRange: 10.119.144.0/20 + - nodeName: "" + sliceRange: 10.119.160.0/20 + - nodeName: "" + sliceRange: 10.119.176.0/20 + - nodeName: "" + sliceRange: 10.119.192.0/20 + - nodeName: "" + sliceRange: 10.119.208.0/20 + - nodeName: "" + sliceRange: 10.119.224.0/20 + - nodeName: "" + sliceRange: 10.119.240.0/20 + - nodeName: "" + sliceRange: 10.120.0.0/20 + - nodeName: "" + sliceRange: 10.120.16.0/20 + - nodeName: "" + sliceRange: 10.120.32.0/20 + - nodeName: "" + sliceRange: 10.120.48.0/20 + - nodeName: "" + sliceRange: 10.120.64.0/20 + - nodeName: "" + sliceRange: 10.120.80.0/20 + - nodeName: "" + sliceRange: 10.120.96.0/20 + - nodeName: "" + sliceRange: 10.120.112.0/20 + - nodeName: "" + sliceRange: 10.120.128.0/20 + - nodeName: "" + sliceRange: 10.120.144.0/20 + - nodeName: "" + sliceRange: 10.120.160.0/20 + - nodeName: "" + sliceRange: 10.120.176.0/20 + - nodeName: "" + sliceRange: 10.120.192.0/20 + - nodeName: "" + sliceRange: 10.120.208.0/20 + - nodeName: "" + sliceRange: 10.120.224.0/20 + - nodeName: "" + sliceRange: 10.120.240.0/20 + - nodeName: "" + sliceRange: 10.121.0.0/20 + - nodeName: "" + sliceRange: 10.121.16.0/20 + - nodeName: "" + sliceRange: 10.121.32.0/20 + - nodeName: "" + sliceRange: 10.121.48.0/20 + - nodeName: "" + sliceRange: 10.121.64.0/20 + - nodeName: "" + sliceRange: 10.121.80.0/20 + - nodeName: "" + sliceRange: 10.121.96.0/20 + - nodeName: "" + sliceRange: 10.121.112.0/20 + - nodeName: "" + sliceRange: 10.121.128.0/20 + - nodeName: "" + sliceRange: 10.121.144.0/20 + - nodeName: "" + sliceRange: 10.121.160.0/20 + - nodeName: "" + sliceRange: 10.121.176.0/20 + - nodeName: "" + sliceRange: 10.121.192.0/20 + - nodeName: "" + sliceRange: 10.121.208.0/20 + - nodeName: "" + sliceRange: 10.121.224.0/20 + - nodeName: "" + sliceRange: 10.121.240.0/20 + - nodeName: "" + sliceRange: 10.122.0.0/20 + - nodeName: "" + sliceRange: 10.122.16.0/20 + - nodeName: "" + sliceRange: 10.122.32.0/20 + - nodeName: "" + sliceRange: 10.122.48.0/20 + - nodeName: "" + sliceRange: 10.122.64.0/20 + - nodeName: "" + sliceRange: 10.122.80.0/20 + - nodeName: "" + sliceRange: 10.122.96.0/20 + - nodeName: "" + sliceRange: 10.122.112.0/20 + - nodeName: "" + sliceRange: 10.122.128.0/20 + - nodeName: "" + sliceRange: 10.122.144.0/20 + - nodeName: "" + sliceRange: 10.122.160.0/20 + - nodeName: "" + sliceRange: 10.122.176.0/20 + - nodeName: "" + sliceRange: 10.122.192.0/20 + - nodeName: "" + sliceRange: 10.122.208.0/20 + - nodeName: "" + sliceRange: 10.122.224.0/20 + - nodeName: "" + sliceRange: 10.122.240.0/20 + - nodeName: "" + sliceRange: 10.123.0.0/20 + - nodeName: "" + sliceRange: 10.123.16.0/20 + - nodeName: "" + sliceRange: 10.123.32.0/20 + - nodeName: "" + sliceRange: 10.123.48.0/20 + - nodeName: "" + sliceRange: 10.123.64.0/20 + - nodeName: "" + sliceRange: 10.123.80.0/20 + - nodeName: "" + sliceRange: 10.123.96.0/20 + - nodeName: "" + sliceRange: 10.123.112.0/20 + - nodeName: "" + sliceRange: 10.123.128.0/20 + - nodeName: "" + sliceRange: 10.123.144.0/20 + - nodeName: "" + sliceRange: 10.123.160.0/20 + - nodeName: "" + sliceRange: 10.123.176.0/20 + - nodeName: "" + sliceRange: 10.123.192.0/20 + - nodeName: "" + sliceRange: 10.123.208.0/20 + - nodeName: "" + sliceRange: 10.123.224.0/20 + - nodeName: "" + sliceRange: 10.123.240.0/20 + - nodeName: "" + sliceRange: 10.124.0.0/20 + - nodeName: "" + sliceRange: 10.124.16.0/20 + - nodeName: "" + sliceRange: 10.124.32.0/20 + - nodeName: "" + sliceRange: 10.124.48.0/20 + - nodeName: "" + sliceRange: 10.124.64.0/20 + - nodeName: "" + sliceRange: 10.124.80.0/20 + - nodeName: "" + sliceRange: 10.124.96.0/20 + - nodeName: "" + sliceRange: 10.124.112.0/20 + - nodeName: "" + sliceRange: 10.124.128.0/20 + - nodeName: "" + sliceRange: 10.124.144.0/20 + - nodeName: "" + sliceRange: 10.124.160.0/20 + - nodeName: "" + sliceRange: 10.124.176.0/20 + - nodeName: "" + sliceRange: 10.124.192.0/20 + - nodeName: "" + sliceRange: 10.124.208.0/20 + - nodeName: "" + sliceRange: 10.124.224.0/20 + - nodeName: "" + sliceRange: 10.124.240.0/20 + - nodeName: "" + sliceRange: 10.125.0.0/20 + - nodeName: "" + sliceRange: 10.125.16.0/20 + - nodeName: "" + sliceRange: 10.125.32.0/20 + - nodeName: "" + sliceRange: 10.125.48.0/20 + - nodeName: "" + sliceRange: 10.125.64.0/20 + - nodeName: "" + sliceRange: 10.125.80.0/20 + - nodeName: "" + sliceRange: 10.125.96.0/20 + - nodeName: "" + sliceRange: 10.125.112.0/20 + - nodeName: "" + sliceRange: 10.125.128.0/20 + - nodeName: "" + sliceRange: 10.125.144.0/20 + - nodeName: "" + sliceRange: 10.125.160.0/20 + - nodeName: "" + sliceRange: 10.125.176.0/20 + - nodeName: "" + sliceRange: 10.125.192.0/20 + - nodeName: "" + sliceRange: 10.125.208.0/20 + - nodeName: "" + sliceRange: 10.125.224.0/20 + - nodeName: "" + sliceRange: 10.125.240.0/20 + - nodeName: "" + sliceRange: 10.126.0.0/20 + - nodeName: "" + sliceRange: 10.126.16.0/20 + - nodeName: "" + sliceRange: 10.126.32.0/20 + - nodeName: "" + sliceRange: 10.126.48.0/20 + - nodeName: "" + sliceRange: 10.126.64.0/20 + - nodeName: "" + sliceRange: 10.126.80.0/20 + - nodeName: "" + sliceRange: 10.126.96.0/20 + - nodeName: "" + sliceRange: 10.126.112.0/20 + - nodeName: "" + sliceRange: 10.126.128.0/20 + - nodeName: "" + sliceRange: 10.126.144.0/20 + - nodeName: "" + sliceRange: 10.126.160.0/20 + - nodeName: "" + sliceRange: 10.126.176.0/20 + - nodeName: "" + sliceRange: 10.126.192.0/20 + - nodeName: "" + sliceRange: 10.126.208.0/20 + - nodeName: "" + sliceRange: 10.126.224.0/20 + - nodeName: "" + sliceRange: 10.126.240.0/20 + - nodeName: "" + sliceRange: 10.127.0.0/20 + - nodeName: "" + sliceRange: 10.127.16.0/20 + - nodeName: "" + sliceRange: 10.127.32.0/20 + - nodeName: "" + sliceRange: 10.127.48.0/20 + - nodeName: "" + sliceRange: 10.127.64.0/20 + - nodeName: "" + sliceRange: 10.127.80.0/20 + - nodeName: "" + sliceRange: 10.127.96.0/20 + - nodeName: "" + sliceRange: 10.127.112.0/20 + - nodeName: "" + sliceRange: 10.127.128.0/20 + - nodeName: "" + sliceRange: 10.127.144.0/20 + - nodeName: "" + sliceRange: 10.127.160.0/20 + - nodeName: "" + sliceRange: 10.127.176.0/20 + - nodeName: "" + sliceRange: 10.127.192.0/20 + - nodeName: "" + sliceRange: 10.127.208.0/20 + - nodeName: "" + sliceRange: 10.127.224.0/20 + - nodeName: "" + sliceRange: 10.127.240.0/20 + - nodeName: "" + sliceRange: 10.128.0.0/20 + - nodeName: "" + sliceRange: 10.128.16.0/20 + - nodeName: "" + sliceRange: 10.128.32.0/20 + - nodeName: "" + sliceRange: 10.128.48.0/20 + - nodeName: "" + sliceRange: 10.128.64.0/20 + - nodeName: "" + sliceRange: 10.128.80.0/20 + - nodeName: "" + sliceRange: 10.128.96.0/20 + - nodeName: "" + sliceRange: 10.128.112.0/20 + - nodeName: "" + sliceRange: 10.128.128.0/20 + - nodeName: "" + sliceRange: 10.128.144.0/20 + - nodeName: "" + sliceRange: 10.128.160.0/20 + - nodeName: "" + sliceRange: 10.128.176.0/20 + - nodeName: "" + sliceRange: 10.128.192.0/20 + - nodeName: "" + sliceRange: 10.128.208.0/20 + - nodeName: "" + sliceRange: 10.128.224.0/20 + - nodeName: "" + sliceRange: 10.128.240.0/20 + - nodeName: "" + sliceRange: 10.129.0.0/20 + - nodeName: "" + sliceRange: 10.129.16.0/20 + - nodeName: "" + sliceRange: 10.129.32.0/20 + - nodeName: "" + sliceRange: 10.129.48.0/20 + - nodeName: "" + sliceRange: 10.129.64.0/20 + - nodeName: "" + sliceRange: 10.129.80.0/20 + - nodeName: "" + sliceRange: 10.129.96.0/20 + - nodeName: "" + sliceRange: 10.129.112.0/20 + - nodeName: "" + sliceRange: 10.129.128.0/20 + - nodeName: "" + sliceRange: 10.129.144.0/20 + - nodeName: "" + sliceRange: 10.129.160.0/20 + - nodeName: "" + sliceRange: 10.129.176.0/20 + - nodeName: "" + sliceRange: 10.129.192.0/20 + - nodeName: "" + sliceRange: 10.129.208.0/20 + - nodeName: "" + sliceRange: 10.129.224.0/20 + - nodeName: "" + sliceRange: 10.129.240.0/20 + - nodeName: "" + sliceRange: 10.130.0.0/20 + - nodeName: "" + sliceRange: 10.130.16.0/20 + - nodeName: "" + sliceRange: 10.130.32.0/20 + - nodeName: "" + sliceRange: 10.130.48.0/20 + - nodeName: "" + sliceRange: 10.130.64.0/20 + - nodeName: "" + sliceRange: 10.130.80.0/20 + - nodeName: "" + sliceRange: 10.130.96.0/20 + - nodeName: "" + sliceRange: 10.130.112.0/20 + - nodeName: "" + sliceRange: 10.130.128.0/20 + - nodeName: "" + sliceRange: 10.130.144.0/20 + - nodeName: "" + sliceRange: 10.130.160.0/20 + - nodeName: "" + sliceRange: 10.130.176.0/20 + - nodeName: "" + sliceRange: 10.130.192.0/20 + - nodeName: "" + sliceRange: 10.130.208.0/20 + - nodeName: "" + sliceRange: 10.130.224.0/20 + - nodeName: "" + sliceRange: 10.130.240.0/20 + - nodeName: "" + sliceRange: 10.131.0.0/20 + - nodeName: "" + sliceRange: 10.131.16.0/20 + - nodeName: "" + sliceRange: 10.131.32.0/20 + - nodeName: "" + sliceRange: 10.131.48.0/20 + - nodeName: "" + sliceRange: 10.131.64.0/20 + - nodeName: "" + sliceRange: 10.131.80.0/20 + - nodeName: "" + sliceRange: 10.131.96.0/20 + - nodeName: "" + sliceRange: 10.131.112.0/20 + - nodeName: "" + sliceRange: 10.131.128.0/20 + - nodeName: "" + sliceRange: 10.131.144.0/20 + - nodeName: "" + sliceRange: 10.131.160.0/20 + - nodeName: "" + sliceRange: 10.131.176.0/20 + - nodeName: "" + sliceRange: 10.131.192.0/20 + - nodeName: "" + sliceRange: 10.131.208.0/20 + - nodeName: "" + sliceRange: 10.131.224.0/20 + - nodeName: "" + sliceRange: 10.131.240.0/20 + - nodeName: "" + sliceRange: 10.132.0.0/20 + - nodeName: "" + sliceRange: 10.132.16.0/20 + - nodeName: "" + sliceRange: 10.132.32.0/20 + - nodeName: "" + sliceRange: 10.132.48.0/20 + - nodeName: "" + sliceRange: 10.132.64.0/20 + - nodeName: "" + sliceRange: 10.132.80.0/20 + - nodeName: "" + sliceRange: 10.132.96.0/20 + - nodeName: "" + sliceRange: 10.132.112.0/20 + - nodeName: "" + sliceRange: 10.132.128.0/20 + - nodeName: "" + sliceRange: 10.132.144.0/20 + - nodeName: "" + sliceRange: 10.132.160.0/20 + - nodeName: "" + sliceRange: 10.132.176.0/20 + - nodeName: "" + sliceRange: 10.132.192.0/20 + - nodeName: "" + sliceRange: 10.132.208.0/20 + - nodeName: "" + sliceRange: 10.132.224.0/20 + - nodeName: "" + sliceRange: 10.132.240.0/20 + - nodeName: "" + sliceRange: 10.133.0.0/20 + - nodeName: "" + sliceRange: 10.133.16.0/20 + - nodeName: "" + sliceRange: 10.133.32.0/20 + - nodeName: "" + sliceRange: 10.133.48.0/20 + - nodeName: "" + sliceRange: 10.133.64.0/20 + - nodeName: "" + sliceRange: 10.133.80.0/20 + - nodeName: "" + sliceRange: 10.133.96.0/20 + - nodeName: "" + sliceRange: 10.133.112.0/20 + - nodeName: "" + sliceRange: 10.133.128.0/20 + - nodeName: "" + sliceRange: 10.133.144.0/20 + - nodeName: "" + sliceRange: 10.133.160.0/20 + - nodeName: "" + sliceRange: 10.133.176.0/20 + - nodeName: "" + sliceRange: 10.133.192.0/20 + - nodeName: "" + sliceRange: 10.133.208.0/20 + - nodeName: "" + sliceRange: 10.133.224.0/20 + - nodeName: "" + sliceRange: 10.133.240.0/20 + - nodeName: "" + sliceRange: 10.134.0.0/20 + - nodeName: "" + sliceRange: 10.134.16.0/20 + - nodeName: "" + sliceRange: 10.134.32.0/20 + - nodeName: "" + sliceRange: 10.134.48.0/20 + - nodeName: "" + sliceRange: 10.134.64.0/20 + - nodeName: "" + sliceRange: 10.134.80.0/20 + - nodeName: "" + sliceRange: 10.134.96.0/20 + - nodeName: "" + sliceRange: 10.134.112.0/20 + - nodeName: "" + sliceRange: 10.134.128.0/20 + - nodeName: "" + sliceRange: 10.134.144.0/20 + - nodeName: "" + sliceRange: 10.134.160.0/20 + - nodeName: "" + sliceRange: 10.134.176.0/20 + - nodeName: "" + sliceRange: 10.134.192.0/20 + - nodeName: "" + sliceRange: 10.134.208.0/20 + - nodeName: "" + sliceRange: 10.134.224.0/20 + - nodeName: "" + sliceRange: 10.134.240.0/20 + - nodeName: "" + sliceRange: 10.135.0.0/20 + - nodeName: "" + sliceRange: 10.135.16.0/20 + - nodeName: "" + sliceRange: 10.135.32.0/20 + - nodeName: "" + sliceRange: 10.135.48.0/20 + - nodeName: "" + sliceRange: 10.135.64.0/20 + - nodeName: "" + sliceRange: 10.135.80.0/20 + - nodeName: "" + sliceRange: 10.135.96.0/20 + - nodeName: "" + sliceRange: 10.135.112.0/20 + - nodeName: "" + sliceRange: 10.135.128.0/20 + - nodeName: "" + sliceRange: 10.135.144.0/20 + - nodeName: "" + sliceRange: 10.135.160.0/20 + - nodeName: "" + sliceRange: 10.135.176.0/20 + - nodeName: "" + sliceRange: 10.135.192.0/20 + - nodeName: "" + sliceRange: 10.135.208.0/20 + - nodeName: "" + sliceRange: 10.135.224.0/20 + - nodeName: "" + sliceRange: 10.135.240.0/20 + - nodeName: "" + sliceRange: 10.136.0.0/20 + - nodeName: "" + sliceRange: 10.136.16.0/20 + - nodeName: "" + sliceRange: 10.136.32.0/20 + - nodeName: "" + sliceRange: 10.136.48.0/20 + - nodeName: "" + sliceRange: 10.136.64.0/20 + - nodeName: "" + sliceRange: 10.136.80.0/20 + - nodeName: "" + sliceRange: 10.136.96.0/20 + - nodeName: "" + sliceRange: 10.136.112.0/20 + - nodeName: "" + sliceRange: 10.136.128.0/20 + - nodeName: "" + sliceRange: 10.136.144.0/20 + - nodeName: "" + sliceRange: 10.136.160.0/20 + - nodeName: "" + sliceRange: 10.136.176.0/20 + - nodeName: "" + sliceRange: 10.136.192.0/20 + - nodeName: "" + sliceRange: 10.136.208.0/20 + - nodeName: "" + sliceRange: 10.136.224.0/20 + - nodeName: "" + sliceRange: 10.136.240.0/20 + - nodeName: "" + sliceRange: 10.137.0.0/20 + - nodeName: "" + sliceRange: 10.137.16.0/20 + - nodeName: "" + sliceRange: 10.137.32.0/20 + - nodeName: "" + sliceRange: 10.137.48.0/20 + - nodeName: "" + sliceRange: 10.137.64.0/20 + - nodeName: "" + sliceRange: 10.137.80.0/20 + - nodeName: "" + sliceRange: 10.137.96.0/20 + - nodeName: "" + sliceRange: 10.137.112.0/20 + - nodeName: "" + sliceRange: 10.137.128.0/20 + - nodeName: "" + sliceRange: 10.137.144.0/20 + - nodeName: "" + sliceRange: 10.137.160.0/20 + - nodeName: "" + sliceRange: 10.137.176.0/20 + - nodeName: "" + sliceRange: 10.137.192.0/20 + - nodeName: "" + sliceRange: 10.137.208.0/20 + - nodeName: "" + sliceRange: 10.137.224.0/20 + - nodeName: "" + sliceRange: 10.137.240.0/20 + - nodeName: "" + sliceRange: 10.138.0.0/20 + - nodeName: "" + sliceRange: 10.138.16.0/20 + - nodeName: "" + sliceRange: 10.138.32.0/20 + - nodeName: "" + sliceRange: 10.138.48.0/20 + - nodeName: "" + sliceRange: 10.138.64.0/20 + - nodeName: "" + sliceRange: 10.138.80.0/20 + - nodeName: "" + sliceRange: 10.138.96.0/20 + - nodeName: "" + sliceRange: 10.138.112.0/20 + - nodeName: "" + sliceRange: 10.138.128.0/20 + - nodeName: "" + sliceRange: 10.138.144.0/20 + - nodeName: "" + sliceRange: 10.138.160.0/20 + - nodeName: "" + sliceRange: 10.138.176.0/20 + - nodeName: "" + sliceRange: 10.138.192.0/20 + - nodeName: "" + sliceRange: 10.138.208.0/20 + - nodeName: "" + sliceRange: 10.138.224.0/20 + - nodeName: "" + sliceRange: 10.138.240.0/20 + - nodeName: "" + sliceRange: 10.139.0.0/20 + - nodeName: "" + sliceRange: 10.139.16.0/20 + - nodeName: "" + sliceRange: 10.139.32.0/20 + - nodeName: "" + sliceRange: 10.139.48.0/20 + - nodeName: "" + sliceRange: 10.139.64.0/20 + - nodeName: "" + sliceRange: 10.139.80.0/20 + - nodeName: "" + sliceRange: 10.139.96.0/20 + - nodeName: "" + sliceRange: 10.139.112.0/20 + - nodeName: "" + sliceRange: 10.139.128.0/20 + - nodeName: "" + sliceRange: 10.139.144.0/20 + - nodeName: "" + sliceRange: 10.139.160.0/20 + - nodeName: "" + sliceRange: 10.139.176.0/20 + - nodeName: "" + sliceRange: 10.139.192.0/20 + - nodeName: "" + sliceRange: 10.139.208.0/20 + - nodeName: "" + sliceRange: 10.139.224.0/20 + - nodeName: "" + sliceRange: 10.139.240.0/20 + - nodeName: "" + sliceRange: 10.140.0.0/20 + - nodeName: "" + sliceRange: 10.140.16.0/20 + - nodeName: "" + sliceRange: 10.140.32.0/20 + - nodeName: "" + sliceRange: 10.140.48.0/20 + - nodeName: "" + sliceRange: 10.140.64.0/20 + - nodeName: "" + sliceRange: 10.140.80.0/20 + - nodeName: "" + sliceRange: 10.140.96.0/20 + - nodeName: "" + sliceRange: 10.140.112.0/20 + - nodeName: "" + sliceRange: 10.140.128.0/20 + - nodeName: "" + sliceRange: 10.140.144.0/20 + - nodeName: "" + sliceRange: 10.140.160.0/20 + - nodeName: "" + sliceRange: 10.140.176.0/20 + - nodeName: "" + sliceRange: 10.140.192.0/20 + - nodeName: "" + sliceRange: 10.140.208.0/20 + - nodeName: "" + sliceRange: 10.140.224.0/20 + - nodeName: "" + sliceRange: 10.140.240.0/20 + - nodeName: "" + sliceRange: 10.141.0.0/20 + - nodeName: "" + sliceRange: 10.141.16.0/20 + - nodeName: "" + sliceRange: 10.141.32.0/20 + - nodeName: "" + sliceRange: 10.141.48.0/20 + - nodeName: "" + sliceRange: 10.141.64.0/20 + - nodeName: "" + sliceRange: 10.141.80.0/20 + - nodeName: "" + sliceRange: 10.141.96.0/20 + - nodeName: "" + sliceRange: 10.141.112.0/20 + - nodeName: "" + sliceRange: 10.141.128.0/20 + - nodeName: "" + sliceRange: 10.141.144.0/20 + - nodeName: "" + sliceRange: 10.141.160.0/20 + - nodeName: "" + sliceRange: 10.141.176.0/20 + - nodeName: "" + sliceRange: 10.141.192.0/20 + - nodeName: "" + sliceRange: 10.141.208.0/20 + - nodeName: "" + sliceRange: 10.141.224.0/20 + - nodeName: "" + sliceRange: 10.141.240.0/20 + - nodeName: "" + sliceRange: 10.142.0.0/20 + - nodeName: "" + sliceRange: 10.142.16.0/20 + - nodeName: "" + sliceRange: 10.142.32.0/20 + - nodeName: "" + sliceRange: 10.142.48.0/20 + - nodeName: "" + sliceRange: 10.142.64.0/20 + - nodeName: "" + sliceRange: 10.142.80.0/20 + - nodeName: "" + sliceRange: 10.142.96.0/20 + - nodeName: "" + sliceRange: 10.142.112.0/20 + - nodeName: "" + sliceRange: 10.142.128.0/20 + - nodeName: "" + sliceRange: 10.142.144.0/20 + - nodeName: "" + sliceRange: 10.142.160.0/20 + - nodeName: "" + sliceRange: 10.142.176.0/20 + - nodeName: "" + sliceRange: 10.142.192.0/20 + - nodeName: "" + sliceRange: 10.142.208.0/20 + - nodeName: "" + sliceRange: 10.142.224.0/20 + - nodeName: "" + sliceRange: 10.142.240.0/20 + - nodeName: "" + sliceRange: 10.143.0.0/20 + - nodeName: "" + sliceRange: 10.143.16.0/20 + - nodeName: "" + sliceRange: 10.143.32.0/20 + - nodeName: "" + sliceRange: 10.143.48.0/20 + - nodeName: "" + sliceRange: 10.143.64.0/20 + - nodeName: "" + sliceRange: 10.143.80.0/20 + - nodeName: "" + sliceRange: 10.143.96.0/20 + - nodeName: "" + sliceRange: 10.143.112.0/20 + - nodeName: "" + sliceRange: 10.143.128.0/20 + - nodeName: "" + sliceRange: 10.143.144.0/20 + - nodeName: "" + sliceRange: 10.143.160.0/20 + - nodeName: "" + sliceRange: 10.143.176.0/20 + - nodeName: "" + sliceRange: 10.143.192.0/20 + - nodeName: "" + sliceRange: 10.143.208.0/20 + - nodeName: "" + sliceRange: 10.143.224.0/20 + - nodeName: "" + sliceRange: 10.143.240.0/20 + - nodeName: "" + sliceRange: 10.144.0.0/20 + - nodeName: "" + sliceRange: 10.144.16.0/20 + - nodeName: "" + sliceRange: 10.144.32.0/20 + - nodeName: "" + sliceRange: 10.144.48.0/20 + - nodeName: "" + sliceRange: 10.144.64.0/20 + - nodeName: "" + sliceRange: 10.144.80.0/20 + - nodeName: "" + sliceRange: 10.144.96.0/20 + - nodeName: "" + sliceRange: 10.144.112.0/20 + - nodeName: "" + sliceRange: 10.144.128.0/20 + - nodeName: "" + sliceRange: 10.144.144.0/20 + - nodeName: "" + sliceRange: 10.144.160.0/20 + - nodeName: "" + sliceRange: 10.144.176.0/20 + - nodeName: "" + sliceRange: 10.144.192.0/20 + - nodeName: "" + sliceRange: 10.144.208.0/20 + - nodeName: "" + sliceRange: 10.144.224.0/20 + - nodeName: "" + sliceRange: 10.144.240.0/20 + - nodeName: "" + sliceRange: 10.145.0.0/20 + - nodeName: "" + sliceRange: 10.145.16.0/20 + - nodeName: "" + sliceRange: 10.145.32.0/20 + - nodeName: "" + sliceRange: 10.145.48.0/20 + - nodeName: "" + sliceRange: 10.145.64.0/20 + - nodeName: "" + sliceRange: 10.145.80.0/20 + - nodeName: "" + sliceRange: 10.145.96.0/20 + - nodeName: "" + sliceRange: 10.145.112.0/20 + - nodeName: "" + sliceRange: 10.145.128.0/20 + - nodeName: "" + sliceRange: 10.145.144.0/20 + - nodeName: "" + sliceRange: 10.145.160.0/20 + - nodeName: "" + sliceRange: 10.145.176.0/20 + - nodeName: "" + sliceRange: 10.145.192.0/20 + - nodeName: "" + sliceRange: 10.145.208.0/20 + - nodeName: "" + sliceRange: 10.145.224.0/20 + - nodeName: "" + sliceRange: 10.145.240.0/20 + - nodeName: "" + sliceRange: 10.146.0.0/20 + - nodeName: "" + sliceRange: 10.146.16.0/20 + - nodeName: "" + sliceRange: 10.146.32.0/20 + - nodeName: "" + sliceRange: 10.146.48.0/20 + - nodeName: "" + sliceRange: 10.146.64.0/20 + - nodeName: "" + sliceRange: 10.146.80.0/20 + - nodeName: "" + sliceRange: 10.146.96.0/20 + - nodeName: "" + sliceRange: 10.146.112.0/20 + - nodeName: "" + sliceRange: 10.146.128.0/20 + - nodeName: "" + sliceRange: 10.146.144.0/20 + - nodeName: "" + sliceRange: 10.146.160.0/20 + - nodeName: "" + sliceRange: 10.146.176.0/20 + - nodeName: "" + sliceRange: 10.146.192.0/20 + - nodeName: "" + sliceRange: 10.146.208.0/20 + - nodeName: "" + sliceRange: 10.146.224.0/20 + - nodeName: "" + sliceRange: 10.146.240.0/20 + - nodeName: "" + sliceRange: 10.147.0.0/20 + - nodeName: "" + sliceRange: 10.147.16.0/20 + - nodeName: "" + sliceRange: 10.147.32.0/20 + - nodeName: "" + sliceRange: 10.147.48.0/20 + - nodeName: "" + sliceRange: 10.147.64.0/20 + - nodeName: "" + sliceRange: 10.147.80.0/20 + - nodeName: "" + sliceRange: 10.147.96.0/20 + - nodeName: "" + sliceRange: 10.147.112.0/20 + - nodeName: "" + sliceRange: 10.147.128.0/20 + - nodeName: "" + sliceRange: 10.147.144.0/20 + - nodeName: "" + sliceRange: 10.147.160.0/20 + - nodeName: "" + sliceRange: 10.147.176.0/20 + - nodeName: "" + sliceRange: 10.147.192.0/20 + - nodeName: "" + sliceRange: 10.147.208.0/20 + - nodeName: "" + sliceRange: 10.147.224.0/20 + - nodeName: "" + sliceRange: 10.147.240.0/20 + - nodeName: "" + sliceRange: 10.148.0.0/20 + - nodeName: "" + sliceRange: 10.148.16.0/20 + - nodeName: "" + sliceRange: 10.148.32.0/20 + - nodeName: "" + sliceRange: 10.148.48.0/20 + - nodeName: "" + sliceRange: 10.148.64.0/20 + - nodeName: "" + sliceRange: 10.148.80.0/20 + - nodeName: "" + sliceRange: 10.148.96.0/20 + - nodeName: "" + sliceRange: 10.148.112.0/20 + - nodeName: "" + sliceRange: 10.148.128.0/20 + - nodeName: "" + sliceRange: 10.148.144.0/20 + - nodeName: "" + sliceRange: 10.148.160.0/20 + - nodeName: "" + sliceRange: 10.148.176.0/20 + - nodeName: "" + sliceRange: 10.148.192.0/20 + - nodeName: "" + sliceRange: 10.148.208.0/20 + - nodeName: "" + sliceRange: 10.148.224.0/20 + - nodeName: "" + sliceRange: 10.148.240.0/20 + - nodeName: "" + sliceRange: 10.149.0.0/20 + - nodeName: "" + sliceRange: 10.149.16.0/20 + - nodeName: "" + sliceRange: 10.149.32.0/20 + - nodeName: "" + sliceRange: 10.149.48.0/20 + - nodeName: "" + sliceRange: 10.149.64.0/20 + - nodeName: "" + sliceRange: 10.149.80.0/20 + - nodeName: "" + sliceRange: 10.149.96.0/20 + - nodeName: "" + sliceRange: 10.149.112.0/20 + - nodeName: "" + sliceRange: 10.149.128.0/20 + - nodeName: "" + sliceRange: 10.149.144.0/20 + - nodeName: "" + sliceRange: 10.149.160.0/20 + - nodeName: "" + sliceRange: 10.149.176.0/20 + - nodeName: "" + sliceRange: 10.149.192.0/20 + - nodeName: "" + sliceRange: 10.149.208.0/20 + - nodeName: "" + sliceRange: 10.149.224.0/20 + - nodeName: "" + sliceRange: 10.149.240.0/20 + - nodeName: "" + sliceRange: 10.150.0.0/20 + - nodeName: "" + sliceRange: 10.150.16.0/20 + - nodeName: "" + sliceRange: 10.150.32.0/20 + - nodeName: "" + sliceRange: 10.150.48.0/20 + - nodeName: "" + sliceRange: 10.150.64.0/20 + - nodeName: "" + sliceRange: 10.150.80.0/20 + - nodeName: "" + sliceRange: 10.150.96.0/20 + - nodeName: "" + sliceRange: 10.150.112.0/20 + - nodeName: "" + sliceRange: 10.150.128.0/20 + - nodeName: "" + sliceRange: 10.150.144.0/20 + - nodeName: "" + sliceRange: 10.150.160.0/20 + - nodeName: "" + sliceRange: 10.150.176.0/20 + - nodeName: "" + sliceRange: 10.150.192.0/20 + - nodeName: "" + sliceRange: 10.150.208.0/20 + - nodeName: "" + sliceRange: 10.150.224.0/20 + - nodeName: "" + sliceRange: 10.150.240.0/20 + - nodeName: "" + sliceRange: 10.151.0.0/20 + - nodeName: "" + sliceRange: 10.151.16.0/20 + - nodeName: "" + sliceRange: 10.151.32.0/20 + - nodeName: "" + sliceRange: 10.151.48.0/20 + - nodeName: "" + sliceRange: 10.151.64.0/20 + - nodeName: "" + sliceRange: 10.151.80.0/20 + - nodeName: "" + sliceRange: 10.151.96.0/20 + - nodeName: "" + sliceRange: 10.151.112.0/20 + - nodeName: "" + sliceRange: 10.151.128.0/20 + - nodeName: "" + sliceRange: 10.151.144.0/20 + - nodeName: "" + sliceRange: 10.151.160.0/20 + - nodeName: "" + sliceRange: 10.151.176.0/20 + - nodeName: "" + sliceRange: 10.151.192.0/20 + - nodeName: "" + sliceRange: 10.151.208.0/20 + - nodeName: "" + sliceRange: 10.151.224.0/20 + - nodeName: "" + sliceRange: 10.151.240.0/20 + - nodeName: "" + sliceRange: 10.152.0.0/20 + - nodeName: "" + sliceRange: 10.152.16.0/20 + - nodeName: "" + sliceRange: 10.152.32.0/20 + - nodeName: "" + sliceRange: 10.152.48.0/20 + - nodeName: "" + sliceRange: 10.152.64.0/20 + - nodeName: "" + sliceRange: 10.152.80.0/20 + - nodeName: "" + sliceRange: 10.152.96.0/20 + - nodeName: "" + sliceRange: 10.152.112.0/20 + - nodeName: "" + sliceRange: 10.152.128.0/20 + - nodeName: "" + sliceRange: 10.152.144.0/20 + - nodeName: "" + sliceRange: 10.152.160.0/20 + - nodeName: "" + sliceRange: 10.152.176.0/20 + - nodeName: "" + sliceRange: 10.152.192.0/20 + - nodeName: "" + sliceRange: 10.152.208.0/20 + - nodeName: "" + sliceRange: 10.152.224.0/20 + - nodeName: "" + sliceRange: 10.152.240.0/20 + - nodeName: "" + sliceRange: 10.153.0.0/20 + - nodeName: "" + sliceRange: 10.153.16.0/20 + - nodeName: "" + sliceRange: 10.153.32.0/20 + - nodeName: "" + sliceRange: 10.153.48.0/20 + - nodeName: "" + sliceRange: 10.153.64.0/20 + - nodeName: "" + sliceRange: 10.153.80.0/20 + - nodeName: "" + sliceRange: 10.153.96.0/20 + - nodeName: "" + sliceRange: 10.153.112.0/20 + - nodeName: "" + sliceRange: 10.153.128.0/20 + - nodeName: "" + sliceRange: 10.153.144.0/20 + - nodeName: "" + sliceRange: 10.153.160.0/20 + - nodeName: "" + sliceRange: 10.153.176.0/20 + - nodeName: "" + sliceRange: 10.153.192.0/20 + - nodeName: "" + sliceRange: 10.153.208.0/20 + - nodeName: "" + sliceRange: 10.153.224.0/20 + - nodeName: "" + sliceRange: 10.153.240.0/20 + - nodeName: "" + sliceRange: 10.154.0.0/20 + - nodeName: "" + sliceRange: 10.154.16.0/20 + - nodeName: "" + sliceRange: 10.154.32.0/20 + - nodeName: "" + sliceRange: 10.154.48.0/20 + - nodeName: "" + sliceRange: 10.154.64.0/20 + - nodeName: "" + sliceRange: 10.154.80.0/20 + - nodeName: "" + sliceRange: 10.154.96.0/20 + - nodeName: "" + sliceRange: 10.154.112.0/20 + - nodeName: "" + sliceRange: 10.154.128.0/20 + - nodeName: "" + sliceRange: 10.154.144.0/20 + - nodeName: "" + sliceRange: 10.154.160.0/20 + - nodeName: "" + sliceRange: 10.154.176.0/20 + - nodeName: "" + sliceRange: 10.154.192.0/20 + - nodeName: "" + sliceRange: 10.154.208.0/20 + - nodeName: "" + sliceRange: 10.154.224.0/20 + - nodeName: "" + sliceRange: 10.154.240.0/20 + - nodeName: "" + sliceRange: 10.155.0.0/20 + - nodeName: "" + sliceRange: 10.155.16.0/20 + - nodeName: "" + sliceRange: 10.155.32.0/20 + - nodeName: "" + sliceRange: 10.155.48.0/20 + - nodeName: "" + sliceRange: 10.155.64.0/20 + - nodeName: "" + sliceRange: 10.155.80.0/20 + - nodeName: "" + sliceRange: 10.155.96.0/20 + - nodeName: "" + sliceRange: 10.155.112.0/20 + - nodeName: "" + sliceRange: 10.155.128.0/20 + - nodeName: "" + sliceRange: 10.155.144.0/20 + - nodeName: "" + sliceRange: 10.155.160.0/20 + - nodeName: "" + sliceRange: 10.155.176.0/20 + - nodeName: "" + sliceRange: 10.155.192.0/20 + - nodeName: "" + sliceRange: 10.155.208.0/20 + - nodeName: "" + sliceRange: 10.155.224.0/20 + - nodeName: "" + sliceRange: 10.155.240.0/20 + - nodeName: "" + sliceRange: 10.156.0.0/20 + - nodeName: "" + sliceRange: 10.156.16.0/20 + - nodeName: "" + sliceRange: 10.156.32.0/20 + - nodeName: "" + sliceRange: 10.156.48.0/20 + - nodeName: "" + sliceRange: 10.156.64.0/20 + - nodeName: "" + sliceRange: 10.156.80.0/20 + - nodeName: "" + sliceRange: 10.156.96.0/20 + - nodeName: "" + sliceRange: 10.156.112.0/20 + - nodeName: "" + sliceRange: 10.156.128.0/20 + - nodeName: "" + sliceRange: 10.156.144.0/20 + - nodeName: "" + sliceRange: 10.156.160.0/20 + - nodeName: "" + sliceRange: 10.156.176.0/20 + - nodeName: "" + sliceRange: 10.156.192.0/20 + - nodeName: "" + sliceRange: 10.156.208.0/20 + - nodeName: "" + sliceRange: 10.156.224.0/20 + - nodeName: "" + sliceRange: 10.156.240.0/20 + - nodeName: "" + sliceRange: 10.157.0.0/20 + - nodeName: "" + sliceRange: 10.157.16.0/20 + - nodeName: "" + sliceRange: 10.157.32.0/20 + - nodeName: "" + sliceRange: 10.157.48.0/20 + - nodeName: "" + sliceRange: 10.157.64.0/20 + - nodeName: "" + sliceRange: 10.157.80.0/20 + - nodeName: "" + sliceRange: 10.157.96.0/20 + - nodeName: "" + sliceRange: 10.157.112.0/20 + - nodeName: "" + sliceRange: 10.157.128.0/20 + - nodeName: "" + sliceRange: 10.157.144.0/20 + - nodeName: "" + sliceRange: 10.157.160.0/20 + - nodeName: "" + sliceRange: 10.157.176.0/20 + - nodeName: "" + sliceRange: 10.157.192.0/20 + - nodeName: "" + sliceRange: 10.157.208.0/20 + - nodeName: "" + sliceRange: 10.157.224.0/20 + - nodeName: "" + sliceRange: 10.157.240.0/20 + - nodeName: "" + sliceRange: 10.158.0.0/20 + - nodeName: "" + sliceRange: 10.158.16.0/20 + - nodeName: "" + sliceRange: 10.158.32.0/20 + - nodeName: "" + sliceRange: 10.158.48.0/20 + - nodeName: "" + sliceRange: 10.158.64.0/20 + - nodeName: "" + sliceRange: 10.158.80.0/20 + - nodeName: "" + sliceRange: 10.158.96.0/20 + - nodeName: "" + sliceRange: 10.158.112.0/20 + - nodeName: "" + sliceRange: 10.158.128.0/20 + - nodeName: "" + sliceRange: 10.158.144.0/20 + - nodeName: "" + sliceRange: 10.158.160.0/20 + - nodeName: "" + sliceRange: 10.158.176.0/20 + - nodeName: "" + sliceRange: 10.158.192.0/20 + - nodeName: "" + sliceRange: 10.158.208.0/20 + - nodeName: "" + sliceRange: 10.158.224.0/20 + - nodeName: "" + sliceRange: 10.158.240.0/20 + - nodeName: "" + sliceRange: 10.159.0.0/20 + - nodeName: "" + sliceRange: 10.159.16.0/20 + - nodeName: "" + sliceRange: 10.159.32.0/20 + - nodeName: "" + sliceRange: 10.159.48.0/20 + - nodeName: "" + sliceRange: 10.159.64.0/20 + - nodeName: "" + sliceRange: 10.159.80.0/20 + - nodeName: "" + sliceRange: 10.159.96.0/20 + - nodeName: "" + sliceRange: 10.159.112.0/20 + - nodeName: "" + sliceRange: 10.159.128.0/20 + - nodeName: "" + sliceRange: 10.159.144.0/20 + - nodeName: "" + sliceRange: 10.159.160.0/20 + - nodeName: "" + sliceRange: 10.159.176.0/20 + - nodeName: "" + sliceRange: 10.159.192.0/20 + - nodeName: "" + sliceRange: 10.159.208.0/20 + - nodeName: "" + sliceRange: 10.159.224.0/20 + - nodeName: "" + sliceRange: 10.159.240.0/20 + - nodeName: "" + sliceRange: 10.160.0.0/20 + - nodeName: "" + sliceRange: 10.160.16.0/20 + - nodeName: "" + sliceRange: 10.160.32.0/20 + - nodeName: "" + sliceRange: 10.160.48.0/20 + - nodeName: "" + sliceRange: 10.160.64.0/20 + - nodeName: "" + sliceRange: 10.160.80.0/20 + - nodeName: "" + sliceRange: 10.160.96.0/20 + - nodeName: "" + sliceRange: 10.160.112.0/20 + - nodeName: "" + sliceRange: 10.160.128.0/20 + - nodeName: "" + sliceRange: 10.160.144.0/20 + - nodeName: "" + sliceRange: 10.160.160.0/20 + - nodeName: "" + sliceRange: 10.160.176.0/20 + - nodeName: "" + sliceRange: 10.160.192.0/20 + - nodeName: "" + sliceRange: 10.160.208.0/20 + - nodeName: "" + sliceRange: 10.160.224.0/20 + - nodeName: "" + sliceRange: 10.160.240.0/20 + - nodeName: "" + sliceRange: 10.161.0.0/20 + - nodeName: "" + sliceRange: 10.161.16.0/20 + - nodeName: "" + sliceRange: 10.161.32.0/20 + - nodeName: "" + sliceRange: 10.161.48.0/20 + - nodeName: "" + sliceRange: 10.161.64.0/20 + - nodeName: "" + sliceRange: 10.161.80.0/20 + - nodeName: "" + sliceRange: 10.161.96.0/20 + - nodeName: "" + sliceRange: 10.161.112.0/20 + - nodeName: "" + sliceRange: 10.161.128.0/20 + - nodeName: "" + sliceRange: 10.161.144.0/20 + - nodeName: "" + sliceRange: 10.161.160.0/20 + - nodeName: "" + sliceRange: 10.161.176.0/20 + - nodeName: "" + sliceRange: 10.161.192.0/20 + - nodeName: "" + sliceRange: 10.161.208.0/20 + - nodeName: "" + sliceRange: 10.161.224.0/20 + - nodeName: "" + sliceRange: 10.161.240.0/20 + - nodeName: "" + sliceRange: 10.162.0.0/20 + - nodeName: "" + sliceRange: 10.162.16.0/20 + - nodeName: "" + sliceRange: 10.162.32.0/20 + - nodeName: "" + sliceRange: 10.162.48.0/20 + - nodeName: "" + sliceRange: 10.162.64.0/20 + - nodeName: "" + sliceRange: 10.162.80.0/20 + - nodeName: "" + sliceRange: 10.162.96.0/20 + - nodeName: "" + sliceRange: 10.162.112.0/20 + - nodeName: "" + sliceRange: 10.162.128.0/20 + - nodeName: "" + sliceRange: 10.162.144.0/20 + - nodeName: "" + sliceRange: 10.162.160.0/20 + - nodeName: "" + sliceRange: 10.162.176.0/20 + - nodeName: "" + sliceRange: 10.162.192.0/20 + - nodeName: "" + sliceRange: 10.162.208.0/20 + - nodeName: "" + sliceRange: 10.162.224.0/20 + - nodeName: "" + sliceRange: 10.162.240.0/20 + - nodeName: "" + sliceRange: 10.163.0.0/20 + - nodeName: "" + sliceRange: 10.163.16.0/20 + - nodeName: "" + sliceRange: 10.163.32.0/20 + - nodeName: "" + sliceRange: 10.163.48.0/20 + - nodeName: "" + sliceRange: 10.163.64.0/20 + - nodeName: "" + sliceRange: 10.163.80.0/20 + - nodeName: "" + sliceRange: 10.163.96.0/20 + - nodeName: "" + sliceRange: 10.163.112.0/20 + - nodeName: "" + sliceRange: 10.163.128.0/20 + - nodeName: "" + sliceRange: 10.163.144.0/20 + - nodeName: "" + sliceRange: 10.163.160.0/20 + - nodeName: "" + sliceRange: 10.163.176.0/20 + - nodeName: "" + sliceRange: 10.163.192.0/20 + - nodeName: "" + sliceRange: 10.163.208.0/20 + - nodeName: "" + sliceRange: 10.163.224.0/20 + - nodeName: "" + sliceRange: 10.163.240.0/20 + - nodeName: "" + sliceRange: 10.164.0.0/20 + - nodeName: "" + sliceRange: 10.164.16.0/20 + - nodeName: "" + sliceRange: 10.164.32.0/20 + - nodeName: "" + sliceRange: 10.164.48.0/20 + - nodeName: "" + sliceRange: 10.164.64.0/20 + - nodeName: "" + sliceRange: 10.164.80.0/20 + - nodeName: "" + sliceRange: 10.164.96.0/20 + - nodeName: "" + sliceRange: 10.164.112.0/20 + - nodeName: "" + sliceRange: 10.164.128.0/20 + - nodeName: "" + sliceRange: 10.164.144.0/20 + - nodeName: "" + sliceRange: 10.164.160.0/20 + - nodeName: "" + sliceRange: 10.164.176.0/20 + - nodeName: "" + sliceRange: 10.164.192.0/20 + - nodeName: "" + sliceRange: 10.164.208.0/20 + - nodeName: "" + sliceRange: 10.164.224.0/20 + - nodeName: "" + sliceRange: 10.164.240.0/20 + - nodeName: "" + sliceRange: 10.165.0.0/20 + - nodeName: "" + sliceRange: 10.165.16.0/20 + - nodeName: "" + sliceRange: 10.165.32.0/20 + - nodeName: "" + sliceRange: 10.165.48.0/20 + - nodeName: "" + sliceRange: 10.165.64.0/20 + - nodeName: "" + sliceRange: 10.165.80.0/20 + - nodeName: "" + sliceRange: 10.165.96.0/20 + - nodeName: "" + sliceRange: 10.165.112.0/20 + - nodeName: "" + sliceRange: 10.165.128.0/20 + - nodeName: "" + sliceRange: 10.165.144.0/20 + - nodeName: "" + sliceRange: 10.165.160.0/20 + - nodeName: "" + sliceRange: 10.165.176.0/20 + - nodeName: "" + sliceRange: 10.165.192.0/20 + - nodeName: "" + sliceRange: 10.165.208.0/20 + - nodeName: "" + sliceRange: 10.165.224.0/20 + - nodeName: "" + sliceRange: 10.165.240.0/20 + - nodeName: "" + sliceRange: 10.166.0.0/20 + - nodeName: "" + sliceRange: 10.166.16.0/20 + - nodeName: "" + sliceRange: 10.166.32.0/20 + - nodeName: "" + sliceRange: 10.166.48.0/20 + - nodeName: "" + sliceRange: 10.166.64.0/20 + - nodeName: "" + sliceRange: 10.166.80.0/20 + - nodeName: "" + sliceRange: 10.166.96.0/20 + - nodeName: "" + sliceRange: 10.166.112.0/20 + - nodeName: "" + sliceRange: 10.166.128.0/20 + - nodeName: "" + sliceRange: 10.166.144.0/20 + - nodeName: "" + sliceRange: 10.166.160.0/20 + - nodeName: "" + sliceRange: 10.166.176.0/20 + - nodeName: "" + sliceRange: 10.166.192.0/20 + - nodeName: "" + sliceRange: 10.166.208.0/20 + - nodeName: "" + sliceRange: 10.166.224.0/20 + - nodeName: "" + sliceRange: 10.166.240.0/20 + - nodeName: "" + sliceRange: 10.167.0.0/20 + - nodeName: "" + sliceRange: 10.167.16.0/20 + - nodeName: "" + sliceRange: 10.167.32.0/20 + - nodeName: "" + sliceRange: 10.167.48.0/20 + - nodeName: "" + sliceRange: 10.167.64.0/20 + - nodeName: "" + sliceRange: 10.167.80.0/20 + - nodeName: "" + sliceRange: 10.167.96.0/20 + - nodeName: "" + sliceRange: 10.167.112.0/20 + - nodeName: "" + sliceRange: 10.167.128.0/20 + - nodeName: "" + sliceRange: 10.167.144.0/20 + - nodeName: "" + sliceRange: 10.167.160.0/20 + - nodeName: "" + sliceRange: 10.167.176.0/20 + - nodeName: "" + sliceRange: 10.167.192.0/20 + - nodeName: "" + sliceRange: 10.167.208.0/20 + - nodeName: "" + sliceRange: 10.167.224.0/20 + - nodeName: "" + sliceRange: 10.167.240.0/20 + - nodeName: "" + sliceRange: 10.168.0.0/20 + - nodeName: "" + sliceRange: 10.168.16.0/20 + - nodeName: "" + sliceRange: 10.168.32.0/20 + - nodeName: "" + sliceRange: 10.168.48.0/20 + - nodeName: "" + sliceRange: 10.168.64.0/20 + - nodeName: "" + sliceRange: 10.168.80.0/20 + - nodeName: "" + sliceRange: 10.168.96.0/20 + - nodeName: "" + sliceRange: 10.168.112.0/20 + - nodeName: "" + sliceRange: 10.168.128.0/20 + - nodeName: "" + sliceRange: 10.168.144.0/20 + - nodeName: "" + sliceRange: 10.168.160.0/20 + - nodeName: "" + sliceRange: 10.168.176.0/20 + - nodeName: "" + sliceRange: 10.168.192.0/20 + - nodeName: "" + sliceRange: 10.168.208.0/20 + - nodeName: "" + sliceRange: 10.168.224.0/20 + - nodeName: "" + sliceRange: 10.168.240.0/20 + - nodeName: "" + sliceRange: 10.169.0.0/20 + - nodeName: "" + sliceRange: 10.169.16.0/20 + - nodeName: "" + sliceRange: 10.169.32.0/20 + - nodeName: "" + sliceRange: 10.169.48.0/20 + - nodeName: "" + sliceRange: 10.169.64.0/20 + - nodeName: "" + sliceRange: 10.169.80.0/20 + - nodeName: "" + sliceRange: 10.169.96.0/20 + - nodeName: "" + sliceRange: 10.169.112.0/20 + - nodeName: "" + sliceRange: 10.169.128.0/20 + - nodeName: "" + sliceRange: 10.169.144.0/20 + - nodeName: "" + sliceRange: 10.169.160.0/20 + - nodeName: "" + sliceRange: 10.169.176.0/20 + - nodeName: "" + sliceRange: 10.169.192.0/20 + - nodeName: "" + sliceRange: 10.169.208.0/20 + - nodeName: "" + sliceRange: 10.169.224.0/20 + - nodeName: "" + sliceRange: 10.169.240.0/20 + - nodeName: "" + sliceRange: 10.170.0.0/20 + - nodeName: "" + sliceRange: 10.170.16.0/20 + - nodeName: "" + sliceRange: 10.170.32.0/20 + - nodeName: "" + sliceRange: 10.170.48.0/20 + - nodeName: "" + sliceRange: 10.170.64.0/20 + - nodeName: "" + sliceRange: 10.170.80.0/20 + - nodeName: "" + sliceRange: 10.170.96.0/20 + - nodeName: "" + sliceRange: 10.170.112.0/20 + - nodeName: "" + sliceRange: 10.170.128.0/20 + - nodeName: "" + sliceRange: 10.170.144.0/20 + - nodeName: "" + sliceRange: 10.170.160.0/20 + - nodeName: "" + sliceRange: 10.170.176.0/20 + - nodeName: "" + sliceRange: 10.170.192.0/20 + - nodeName: "" + sliceRange: 10.170.208.0/20 + - nodeName: "" + sliceRange: 10.170.224.0/20 + - nodeName: "" + sliceRange: 10.170.240.0/20 + - nodeName: "" + sliceRange: 10.171.0.0/20 + - nodeName: "" + sliceRange: 10.171.16.0/20 + - nodeName: "" + sliceRange: 10.171.32.0/20 + - nodeName: "" + sliceRange: 10.171.48.0/20 + - nodeName: "" + sliceRange: 10.171.64.0/20 + - nodeName: "" + sliceRange: 10.171.80.0/20 + - nodeName: "" + sliceRange: 10.171.96.0/20 + - nodeName: "" + sliceRange: 10.171.112.0/20 + - nodeName: "" + sliceRange: 10.171.128.0/20 + - nodeName: "" + sliceRange: 10.171.144.0/20 + - nodeName: "" + sliceRange: 10.171.160.0/20 + - nodeName: "" + sliceRange: 10.171.176.0/20 + - nodeName: "" + sliceRange: 10.171.192.0/20 + - nodeName: "" + sliceRange: 10.171.208.0/20 + - nodeName: "" + sliceRange: 10.171.224.0/20 + - nodeName: "" + sliceRange: 10.171.240.0/20 + - nodeName: "" + sliceRange: 10.172.0.0/20 + - nodeName: "" + sliceRange: 10.172.16.0/20 + - nodeName: "" + sliceRange: 10.172.32.0/20 + - nodeName: "" + sliceRange: 10.172.48.0/20 + - nodeName: "" + sliceRange: 10.172.64.0/20 + - nodeName: "" + sliceRange: 10.172.80.0/20 + - nodeName: "" + sliceRange: 10.172.96.0/20 + - nodeName: "" + sliceRange: 10.172.112.0/20 + - nodeName: "" + sliceRange: 10.172.128.0/20 + - nodeName: "" + sliceRange: 10.172.144.0/20 + - nodeName: "" + sliceRange: 10.172.160.0/20 + - nodeName: "" + sliceRange: 10.172.176.0/20 + - nodeName: "" + sliceRange: 10.172.192.0/20 + - nodeName: "" + sliceRange: 10.172.208.0/20 + - nodeName: "" + sliceRange: 10.172.224.0/20 + - nodeName: "" + sliceRange: 10.172.240.0/20 + - nodeName: "" + sliceRange: 10.173.0.0/20 + - nodeName: "" + sliceRange: 10.173.16.0/20 + - nodeName: "" + sliceRange: 10.173.32.0/20 + - nodeName: "" + sliceRange: 10.173.48.0/20 + - nodeName: "" + sliceRange: 10.173.64.0/20 + - nodeName: "" + sliceRange: 10.173.80.0/20 + - nodeName: "" + sliceRange: 10.173.96.0/20 + - nodeName: "" + sliceRange: 10.173.112.0/20 + - nodeName: "" + sliceRange: 10.173.128.0/20 + - nodeName: "" + sliceRange: 10.173.144.0/20 + - nodeName: "" + sliceRange: 10.173.160.0/20 + - nodeName: "" + sliceRange: 10.173.176.0/20 + - nodeName: "" + sliceRange: 10.173.192.0/20 + - nodeName: "" + sliceRange: 10.173.208.0/20 + - nodeName: "" + sliceRange: 10.173.224.0/20 + - nodeName: "" + sliceRange: 10.173.240.0/20 + - nodeName: "" + sliceRange: 10.174.0.0/20 + - nodeName: "" + sliceRange: 10.174.16.0/20 + - nodeName: "" + sliceRange: 10.174.32.0/20 + - nodeName: "" + sliceRange: 10.174.48.0/20 + - nodeName: "" + sliceRange: 10.174.64.0/20 + - nodeName: "" + sliceRange: 10.174.80.0/20 + - nodeName: "" + sliceRange: 10.174.96.0/20 + - nodeName: "" + sliceRange: 10.174.112.0/20 + - nodeName: "" + sliceRange: 10.174.128.0/20 + - nodeName: "" + sliceRange: 10.174.144.0/20 + - nodeName: "" + sliceRange: 10.174.160.0/20 + - nodeName: "" + sliceRange: 10.174.176.0/20 + - nodeName: "" + sliceRange: 10.174.192.0/20 + - nodeName: "" + sliceRange: 10.174.208.0/20 + - nodeName: "" + sliceRange: 10.174.224.0/20 + - nodeName: "" + sliceRange: 10.174.240.0/20 + - nodeName: "" + sliceRange: 10.175.0.0/20 + - nodeName: "" + sliceRange: 10.175.16.0/20 + - nodeName: "" + sliceRange: 10.175.32.0/20 + - nodeName: "" + sliceRange: 10.175.48.0/20 + - nodeName: "" + sliceRange: 10.175.64.0/20 + - nodeName: "" + sliceRange: 10.175.80.0/20 + - nodeName: "" + sliceRange: 10.175.96.0/20 + - nodeName: "" + sliceRange: 10.175.112.0/20 + - nodeName: "" + sliceRange: 10.175.128.0/20 + - nodeName: "" + sliceRange: 10.175.144.0/20 + - nodeName: "" + sliceRange: 10.175.160.0/20 + - nodeName: "" + sliceRange: 10.175.176.0/20 + - nodeName: "" + sliceRange: 10.175.192.0/20 + - nodeName: "" + sliceRange: 10.175.208.0/20 + - nodeName: "" + sliceRange: 10.175.224.0/20 + - nodeName: "" + sliceRange: 10.175.240.0/20 + - nodeName: "" + sliceRange: 10.176.0.0/20 + - nodeName: "" + sliceRange: 10.176.16.0/20 + - nodeName: "" + sliceRange: 10.176.32.0/20 + - nodeName: "" + sliceRange: 10.176.48.0/20 + - nodeName: "" + sliceRange: 10.176.64.0/20 + - nodeName: "" + sliceRange: 10.176.80.0/20 + - nodeName: "" + sliceRange: 10.176.96.0/20 + - nodeName: "" + sliceRange: 10.176.112.0/20 + - nodeName: "" + sliceRange: 10.176.128.0/20 + - nodeName: "" + sliceRange: 10.176.144.0/20 + - nodeName: "" + sliceRange: 10.176.160.0/20 + - nodeName: "" + sliceRange: 10.176.176.0/20 + - nodeName: "" + sliceRange: 10.176.192.0/20 + - nodeName: "" + sliceRange: 10.176.208.0/20 + - nodeName: "" + sliceRange: 10.176.224.0/20 + - nodeName: "" + sliceRange: 10.176.240.0/20 + - nodeName: "" + sliceRange: 10.177.0.0/20 + - nodeName: "" + sliceRange: 10.177.16.0/20 + - nodeName: "" + sliceRange: 10.177.32.0/20 + - nodeName: "" + sliceRange: 10.177.48.0/20 + - nodeName: "" + sliceRange: 10.177.64.0/20 + - nodeName: "" + sliceRange: 10.177.80.0/20 + - nodeName: "" + sliceRange: 10.177.96.0/20 + - nodeName: "" + sliceRange: 10.177.112.0/20 + - nodeName: "" + sliceRange: 10.177.128.0/20 + - nodeName: "" + sliceRange: 10.177.144.0/20 + - nodeName: "" + sliceRange: 10.177.160.0/20 + - nodeName: "" + sliceRange: 10.177.176.0/20 + - nodeName: "" + sliceRange: 10.177.192.0/20 + - nodeName: "" + sliceRange: 10.177.208.0/20 + - nodeName: "" + sliceRange: 10.177.224.0/20 + - nodeName: "" + sliceRange: 10.177.240.0/20 + - nodeName: "" + sliceRange: 10.178.0.0/20 + - nodeName: "" + sliceRange: 10.178.16.0/20 + - nodeName: "" + sliceRange: 10.178.32.0/20 + - nodeName: "" + sliceRange: 10.178.48.0/20 + - nodeName: "" + sliceRange: 10.178.64.0/20 + - nodeName: "" + sliceRange: 10.178.80.0/20 + - nodeName: "" + sliceRange: 10.178.96.0/20 + - nodeName: "" + sliceRange: 10.178.112.0/20 + - nodeName: "" + sliceRange: 10.178.128.0/20 + - nodeName: "" + sliceRange: 10.178.144.0/20 + - nodeName: "" + sliceRange: 10.178.160.0/20 + - nodeName: "" + sliceRange: 10.178.176.0/20 + - nodeName: "" + sliceRange: 10.178.192.0/20 + - nodeName: "" + sliceRange: 10.178.208.0/20 + - nodeName: "" + sliceRange: 10.178.224.0/20 + - nodeName: "" + sliceRange: 10.178.240.0/20 + - nodeName: "" + sliceRange: 10.179.0.0/20 + - nodeName: "" + sliceRange: 10.179.16.0/20 + - nodeName: "" + sliceRange: 10.179.32.0/20 + - nodeName: "" + sliceRange: 10.179.48.0/20 + - nodeName: "" + sliceRange: 10.179.64.0/20 + - nodeName: "" + sliceRange: 10.179.80.0/20 + - nodeName: "" + sliceRange: 10.179.96.0/20 + - nodeName: "" + sliceRange: 10.179.112.0/20 + - nodeName: "" + sliceRange: 10.179.128.0/20 + - nodeName: "" + sliceRange: 10.179.144.0/20 + - nodeName: "" + sliceRange: 10.179.160.0/20 + - nodeName: "" + sliceRange: 10.179.176.0/20 + - nodeName: "" + sliceRange: 10.179.192.0/20 + - nodeName: "" + sliceRange: 10.179.208.0/20 + - nodeName: "" + sliceRange: 10.179.224.0/20 + - nodeName: "" + sliceRange: 10.179.240.0/20 + - nodeName: "" + sliceRange: 10.180.0.0/20 + - nodeName: "" + sliceRange: 10.180.16.0/20 + - nodeName: "" + sliceRange: 10.180.32.0/20 + - nodeName: "" + sliceRange: 10.180.48.0/20 + - nodeName: "" + sliceRange: 10.180.64.0/20 + - nodeName: "" + sliceRange: 10.180.80.0/20 + - nodeName: "" + sliceRange: 10.180.96.0/20 + - nodeName: "" + sliceRange: 10.180.112.0/20 + - nodeName: "" + sliceRange: 10.180.128.0/20 + - nodeName: "" + sliceRange: 10.180.144.0/20 + - nodeName: "" + sliceRange: 10.180.160.0/20 + - nodeName: "" + sliceRange: 10.180.176.0/20 + - nodeName: "" + sliceRange: 10.180.192.0/20 + - nodeName: "" + sliceRange: 10.180.208.0/20 + - nodeName: "" + sliceRange: 10.180.224.0/20 + - nodeName: "" + sliceRange: 10.180.240.0/20 + - nodeName: "" + sliceRange: 10.181.0.0/20 + - nodeName: "" + sliceRange: 10.181.16.0/20 + - nodeName: "" + sliceRange: 10.181.32.0/20 + - nodeName: "" + sliceRange: 10.181.48.0/20 + - nodeName: "" + sliceRange: 10.181.64.0/20 + - nodeName: "" + sliceRange: 10.181.80.0/20 + - nodeName: "" + sliceRange: 10.181.96.0/20 + - nodeName: "" + sliceRange: 10.181.112.0/20 + - nodeName: "" + sliceRange: 10.181.128.0/20 + - nodeName: "" + sliceRange: 10.181.144.0/20 + - nodeName: "" + sliceRange: 10.181.160.0/20 + - nodeName: "" + sliceRange: 10.181.176.0/20 + - nodeName: "" + sliceRange: 10.181.192.0/20 + - nodeName: "" + sliceRange: 10.181.208.0/20 + - nodeName: "" + sliceRange: 10.181.224.0/20 + - nodeName: "" + sliceRange: 10.181.240.0/20 + - nodeName: "" + sliceRange: 10.182.0.0/20 + - nodeName: "" + sliceRange: 10.182.16.0/20 + - nodeName: "" + sliceRange: 10.182.32.0/20 + - nodeName: "" + sliceRange: 10.182.48.0/20 + - nodeName: "" + sliceRange: 10.182.64.0/20 + - nodeName: "" + sliceRange: 10.182.80.0/20 + - nodeName: "" + sliceRange: 10.182.96.0/20 + - nodeName: "" + sliceRange: 10.182.112.0/20 + - nodeName: "" + sliceRange: 10.182.128.0/20 + - nodeName: "" + sliceRange: 10.182.144.0/20 + - nodeName: "" + sliceRange: 10.182.160.0/20 + - nodeName: "" + sliceRange: 10.182.176.0/20 + - nodeName: "" + sliceRange: 10.182.192.0/20 + - nodeName: "" + sliceRange: 10.182.208.0/20 + - nodeName: "" + sliceRange: 10.182.224.0/20 + - nodeName: "" + sliceRange: 10.182.240.0/20 + - nodeName: "" + sliceRange: 10.183.0.0/20 + - nodeName: "" + sliceRange: 10.183.16.0/20 + - nodeName: "" + sliceRange: 10.183.32.0/20 + - nodeName: "" + sliceRange: 10.183.48.0/20 + - nodeName: "" + sliceRange: 10.183.64.0/20 + - nodeName: "" + sliceRange: 10.183.80.0/20 + - nodeName: "" + sliceRange: 10.183.96.0/20 + - nodeName: "" + sliceRange: 10.183.112.0/20 + - nodeName: "" + sliceRange: 10.183.128.0/20 + - nodeName: "" + sliceRange: 10.183.144.0/20 + - nodeName: "" + sliceRange: 10.183.160.0/20 + - nodeName: "" + sliceRange: 10.183.176.0/20 + - nodeName: "" + sliceRange: 10.183.192.0/20 + - nodeName: "" + sliceRange: 10.183.208.0/20 + - nodeName: "" + sliceRange: 10.183.224.0/20 + - nodeName: "" + sliceRange: 10.183.240.0/20 + - nodeName: "" + sliceRange: 10.184.0.0/20 + - nodeName: "" + sliceRange: 10.184.16.0/20 + - nodeName: "" + sliceRange: 10.184.32.0/20 + - nodeName: "" + sliceRange: 10.184.48.0/20 + - nodeName: "" + sliceRange: 10.184.64.0/20 + - nodeName: "" + sliceRange: 10.184.80.0/20 + - nodeName: "" + sliceRange: 10.184.96.0/20 + - nodeName: "" + sliceRange: 10.184.112.0/20 + - nodeName: "" + sliceRange: 10.184.128.0/20 + - nodeName: "" + sliceRange: 10.184.144.0/20 + - nodeName: "" + sliceRange: 10.184.160.0/20 + - nodeName: "" + sliceRange: 10.184.176.0/20 + - nodeName: "" + sliceRange: 10.184.192.0/20 + - nodeName: "" + sliceRange: 10.184.208.0/20 + - nodeName: "" + sliceRange: 10.184.224.0/20 + - nodeName: "" + sliceRange: 10.184.240.0/20 + - nodeName: "" + sliceRange: 10.185.0.0/20 + - nodeName: "" + sliceRange: 10.185.16.0/20 + - nodeName: "" + sliceRange: 10.185.32.0/20 + - nodeName: "" + sliceRange: 10.185.48.0/20 + - nodeName: "" + sliceRange: 10.185.64.0/20 + - nodeName: "" + sliceRange: 10.185.80.0/20 + - nodeName: "" + sliceRange: 10.185.96.0/20 + - nodeName: "" + sliceRange: 10.185.112.0/20 + - nodeName: "" + sliceRange: 10.185.128.0/20 + - nodeName: "" + sliceRange: 10.185.144.0/20 + - nodeName: "" + sliceRange: 10.185.160.0/20 + - nodeName: "" + sliceRange: 10.185.176.0/20 + - nodeName: "" + sliceRange: 10.185.192.0/20 + - nodeName: "" + sliceRange: 10.185.208.0/20 + - nodeName: "" + sliceRange: 10.185.224.0/20 + - nodeName: "" + sliceRange: 10.185.240.0/20 + - nodeName: "" + sliceRange: 10.186.0.0/20 + - nodeName: "" + sliceRange: 10.186.16.0/20 + - nodeName: "" + sliceRange: 10.186.32.0/20 + - nodeName: "" + sliceRange: 10.186.48.0/20 + - nodeName: "" + sliceRange: 10.186.64.0/20 + - nodeName: "" + sliceRange: 10.186.80.0/20 + - nodeName: "" + sliceRange: 10.186.96.0/20 + - nodeName: "" + sliceRange: 10.186.112.0/20 + - nodeName: "" + sliceRange: 10.186.128.0/20 + - nodeName: "" + sliceRange: 10.186.144.0/20 + - nodeName: "" + sliceRange: 10.186.160.0/20 + - nodeName: "" + sliceRange: 10.186.176.0/20 + - nodeName: "" + sliceRange: 10.186.192.0/20 + - nodeName: "" + sliceRange: 10.186.208.0/20 + - nodeName: "" + sliceRange: 10.186.224.0/20 + - nodeName: "" + sliceRange: 10.186.240.0/20 + - nodeName: "" + sliceRange: 10.187.0.0/20 + - nodeName: "" + sliceRange: 10.187.16.0/20 + - nodeName: "" + sliceRange: 10.187.32.0/20 + - nodeName: "" + sliceRange: 10.187.48.0/20 + - nodeName: "" + sliceRange: 10.187.64.0/20 + - nodeName: "" + sliceRange: 10.187.80.0/20 + - nodeName: "" + sliceRange: 10.187.96.0/20 + - nodeName: "" + sliceRange: 10.187.112.0/20 + - nodeName: "" + sliceRange: 10.187.128.0/20 + - nodeName: "" + sliceRange: 10.187.144.0/20 + - nodeName: "" + sliceRange: 10.187.160.0/20 + - nodeName: "" + sliceRange: 10.187.176.0/20 + - nodeName: "" + sliceRange: 10.187.192.0/20 + - nodeName: "" + sliceRange: 10.187.208.0/20 + - nodeName: "" + sliceRange: 10.187.224.0/20 + - nodeName: "" + sliceRange: 10.187.240.0/20 + - nodeName: "" + sliceRange: 10.188.0.0/20 + - nodeName: "" + sliceRange: 10.188.16.0/20 + - nodeName: "" + sliceRange: 10.188.32.0/20 + - nodeName: "" + sliceRange: 10.188.48.0/20 + - nodeName: "" + sliceRange: 10.188.64.0/20 + - nodeName: "" + sliceRange: 10.188.80.0/20 + - nodeName: "" + sliceRange: 10.188.96.0/20 + - nodeName: "" + sliceRange: 10.188.112.0/20 + - nodeName: "" + sliceRange: 10.188.128.0/20 + - nodeName: "" + sliceRange: 10.188.144.0/20 + - nodeName: "" + sliceRange: 10.188.160.0/20 + - nodeName: "" + sliceRange: 10.188.176.0/20 + - nodeName: "" + sliceRange: 10.188.192.0/20 + - nodeName: "" + sliceRange: 10.188.208.0/20 + - nodeName: "" + sliceRange: 10.188.224.0/20 + - nodeName: "" + sliceRange: 10.188.240.0/20 + - nodeName: "" + sliceRange: 10.189.0.0/20 + - nodeName: "" + sliceRange: 10.189.16.0/20 + - nodeName: "" + sliceRange: 10.189.32.0/20 + - nodeName: "" + sliceRange: 10.189.48.0/20 + - nodeName: "" + sliceRange: 10.189.64.0/20 + - nodeName: "" + sliceRange: 10.189.80.0/20 + - nodeName: "" + sliceRange: 10.189.96.0/20 + - nodeName: "" + sliceRange: 10.189.112.0/20 + - nodeName: "" + sliceRange: 10.189.128.0/20 + - nodeName: "" + sliceRange: 10.189.144.0/20 + - nodeName: "" + sliceRange: 10.189.160.0/20 + - nodeName: "" + sliceRange: 10.189.176.0/20 + - nodeName: "" + sliceRange: 10.189.192.0/20 + - nodeName: "" + sliceRange: 10.189.208.0/20 + - nodeName: "" + sliceRange: 10.189.224.0/20 + - nodeName: "" + sliceRange: 10.189.240.0/20 + - nodeName: "" + sliceRange: 10.190.0.0/20 + - nodeName: "" + sliceRange: 10.190.16.0/20 + - nodeName: "" + sliceRange: 10.190.32.0/20 + - nodeName: "" + sliceRange: 10.190.48.0/20 + - nodeName: "" + sliceRange: 10.190.64.0/20 + - nodeName: "" + sliceRange: 10.190.80.0/20 + - nodeName: "" + sliceRange: 10.190.96.0/20 + - nodeName: "" + sliceRange: 10.190.112.0/20 + - nodeName: "" + sliceRange: 10.190.128.0/20 + - nodeName: "" + sliceRange: 10.190.144.0/20 + - nodeName: "" + sliceRange: 10.190.160.0/20 + - nodeName: "" + sliceRange: 10.190.176.0/20 + - nodeName: "" + sliceRange: 10.190.192.0/20 + - nodeName: "" + sliceRange: 10.190.208.0/20 + - nodeName: "" + sliceRange: 10.190.224.0/20 + - nodeName: "" + sliceRange: 10.190.240.0/20 + - nodeName: "" + sliceRange: 10.191.0.0/20 + - nodeName: "" + sliceRange: 10.191.16.0/20 + - nodeName: "" + sliceRange: 10.191.32.0/20 + - nodeName: "" + sliceRange: 10.191.48.0/20 + - nodeName: "" + sliceRange: 10.191.64.0/20 + - nodeName: "" + sliceRange: 10.191.80.0/20 + - nodeName: "" + sliceRange: 10.191.96.0/20 + - nodeName: "" + sliceRange: 10.191.112.0/20 + - nodeName: "" + sliceRange: 10.191.128.0/20 + - nodeName: "" + sliceRange: 10.191.144.0/20 + - nodeName: "" + sliceRange: 10.191.160.0/20 + - nodeName: "" + sliceRange: 10.191.176.0/20 + - nodeName: "" + sliceRange: 10.191.192.0/20 + - nodeName: "" + sliceRange: 10.191.208.0/20 + - nodeName: "" + sliceRange: 10.191.224.0/20 + - nodeName: "" + sliceRange: 10.191.240.0/20 + - nodeName: "" + sliceRange: 10.192.0.0/20 + - nodeName: "" + sliceRange: 10.192.16.0/20 + - nodeName: "" + sliceRange: 10.192.32.0/20 + - nodeName: "" + sliceRange: 10.192.48.0/20 + - nodeName: "" + sliceRange: 10.192.64.0/20 + - nodeName: "" + sliceRange: 10.192.80.0/20 + - nodeName: "" + sliceRange: 10.192.96.0/20 + - nodeName: "" + sliceRange: 10.192.112.0/20 + - nodeName: "" + sliceRange: 10.192.128.0/20 + - nodeName: "" + sliceRange: 10.192.144.0/20 + - nodeName: "" + sliceRange: 10.192.160.0/20 + - nodeName: "" + sliceRange: 10.192.176.0/20 + - nodeName: "" + sliceRange: 10.192.192.0/20 + - nodeName: "" + sliceRange: 10.192.208.0/20 + - nodeName: "" + sliceRange: 10.192.224.0/20 + - nodeName: "" + sliceRange: 10.192.240.0/20 + - nodeName: "" + sliceRange: 10.193.0.0/20 + - nodeName: "" + sliceRange: 10.193.16.0/20 + - nodeName: "" + sliceRange: 10.193.32.0/20 + - nodeName: "" + sliceRange: 10.193.48.0/20 + - nodeName: "" + sliceRange: 10.193.64.0/20 + - nodeName: "" + sliceRange: 10.193.80.0/20 + - nodeName: "" + sliceRange: 10.193.96.0/20 + - nodeName: "" + sliceRange: 10.193.112.0/20 + - nodeName: "" + sliceRange: 10.193.128.0/20 + - nodeName: "" + sliceRange: 10.193.144.0/20 + - nodeName: "" + sliceRange: 10.193.160.0/20 + - nodeName: "" + sliceRange: 10.193.176.0/20 + - nodeName: "" + sliceRange: 10.193.192.0/20 + - nodeName: "" + sliceRange: 10.193.208.0/20 + - nodeName: "" + sliceRange: 10.193.224.0/20 + - nodeName: "" + sliceRange: 10.193.240.0/20 + - nodeName: "" + sliceRange: 10.194.0.0/20 + - nodeName: "" + sliceRange: 10.194.16.0/20 + - nodeName: "" + sliceRange: 10.194.32.0/20 + - nodeName: "" + sliceRange: 10.194.48.0/20 + - nodeName: "" + sliceRange: 10.194.64.0/20 + - nodeName: "" + sliceRange: 10.194.80.0/20 + - nodeName: "" + sliceRange: 10.194.96.0/20 + - nodeName: "" + sliceRange: 10.194.112.0/20 + - nodeName: "" + sliceRange: 10.194.128.0/20 + - nodeName: "" + sliceRange: 10.194.144.0/20 + - nodeName: "" + sliceRange: 10.194.160.0/20 + - nodeName: "" + sliceRange: 10.194.176.0/20 + - nodeName: "" + sliceRange: 10.194.192.0/20 + - nodeName: "" + sliceRange: 10.194.208.0/20 + - nodeName: "" + sliceRange: 10.194.224.0/20 + - nodeName: "" + sliceRange: 10.194.240.0/20 + - nodeName: "" + sliceRange: 10.195.0.0/20 + - nodeName: "" + sliceRange: 10.195.16.0/20 + - nodeName: "" + sliceRange: 10.195.32.0/20 + - nodeName: "" + sliceRange: 10.195.48.0/20 + - nodeName: "" + sliceRange: 10.195.64.0/20 + - nodeName: "" + sliceRange: 10.195.80.0/20 + - nodeName: "" + sliceRange: 10.195.96.0/20 + - nodeName: "" + sliceRange: 10.195.112.0/20 + - nodeName: "" + sliceRange: 10.195.128.0/20 + - nodeName: "" + sliceRange: 10.195.144.0/20 + - nodeName: "" + sliceRange: 10.195.160.0/20 + - nodeName: "" + sliceRange: 10.195.176.0/20 + - nodeName: "" + sliceRange: 10.195.192.0/20 + - nodeName: "" + sliceRange: 10.195.208.0/20 + - nodeName: "" + sliceRange: 10.195.224.0/20 + - nodeName: "" + sliceRange: 10.195.240.0/20 + - nodeName: "" + sliceRange: 10.196.0.0/20 + - nodeName: "" + sliceRange: 10.196.16.0/20 + - nodeName: "" + sliceRange: 10.196.32.0/20 + - nodeName: "" + sliceRange: 10.196.48.0/20 + - nodeName: "" + sliceRange: 10.196.64.0/20 + - nodeName: "" + sliceRange: 10.196.80.0/20 + - nodeName: "" + sliceRange: 10.196.96.0/20 + - nodeName: "" + sliceRange: 10.196.112.0/20 + - nodeName: "" + sliceRange: 10.196.128.0/20 + - nodeName: "" + sliceRange: 10.196.144.0/20 + - nodeName: "" + sliceRange: 10.196.160.0/20 + - nodeName: "" + sliceRange: 10.196.176.0/20 + - nodeName: "" + sliceRange: 10.196.192.0/20 + - nodeName: "" + sliceRange: 10.196.208.0/20 + - nodeName: "" + sliceRange: 10.196.224.0/20 + - nodeName: "" + sliceRange: 10.196.240.0/20 + - nodeName: "" + sliceRange: 10.197.0.0/20 + - nodeName: "" + sliceRange: 10.197.16.0/20 + - nodeName: "" + sliceRange: 10.197.32.0/20 + - nodeName: "" + sliceRange: 10.197.48.0/20 + - nodeName: "" + sliceRange: 10.197.64.0/20 + - nodeName: "" + sliceRange: 10.197.80.0/20 + - nodeName: "" + sliceRange: 10.197.96.0/20 + - nodeName: "" + sliceRange: 10.197.112.0/20 + - nodeName: "" + sliceRange: 10.197.128.0/20 + - nodeName: "" + sliceRange: 10.197.144.0/20 + - nodeName: "" + sliceRange: 10.197.160.0/20 + - nodeName: "" + sliceRange: 10.197.176.0/20 + - nodeName: "" + sliceRange: 10.197.192.0/20 + - nodeName: "" + sliceRange: 10.197.208.0/20 + - nodeName: "" + sliceRange: 10.197.224.0/20 + - nodeName: "" + sliceRange: 10.197.240.0/20 + - nodeName: "" + sliceRange: 10.198.0.0/20 + - nodeName: "" + sliceRange: 10.198.16.0/20 + - nodeName: "" + sliceRange: 10.198.32.0/20 + - nodeName: "" + sliceRange: 10.198.48.0/20 + - nodeName: "" + sliceRange: 10.198.64.0/20 + - nodeName: "" + sliceRange: 10.198.80.0/20 + - nodeName: "" + sliceRange: 10.198.96.0/20 + - nodeName: "" + sliceRange: 10.198.112.0/20 + - nodeName: "" + sliceRange: 10.198.128.0/20 + - nodeName: "" + sliceRange: 10.198.144.0/20 + - nodeName: "" + sliceRange: 10.198.160.0/20 + - nodeName: "" + sliceRange: 10.198.176.0/20 + - nodeName: "" + sliceRange: 10.198.192.0/20 + - nodeName: "" + sliceRange: 10.198.208.0/20 + - nodeName: "" + sliceRange: 10.198.224.0/20 + - nodeName: "" + sliceRange: 10.198.240.0/20 + - nodeName: "" + sliceRange: 10.199.0.0/20 + - nodeName: "" + sliceRange: 10.199.16.0/20 + - nodeName: "" + sliceRange: 10.199.32.0/20 + - nodeName: "" + sliceRange: 10.199.48.0/20 + - nodeName: "" + sliceRange: 10.199.64.0/20 + - nodeName: "" + sliceRange: 10.199.80.0/20 + - nodeName: "" + sliceRange: 10.199.96.0/20 + - nodeName: "" + sliceRange: 10.199.112.0/20 + - nodeName: "" + sliceRange: 10.199.128.0/20 + - nodeName: "" + sliceRange: 10.199.144.0/20 + - nodeName: "" + sliceRange: 10.199.160.0/20 + - nodeName: "" + sliceRange: 10.199.176.0/20 + - nodeName: "" + sliceRange: 10.199.192.0/20 + - nodeName: "" + sliceRange: 10.199.208.0/20 + - nodeName: "" + sliceRange: 10.199.224.0/20 + - nodeName: "" + sliceRange: 10.199.240.0/20 + - nodeName: "" + sliceRange: 10.200.0.0/20 + - nodeName: "" + sliceRange: 10.200.16.0/20 + - nodeName: "" + sliceRange: 10.200.32.0/20 + - nodeName: "" + sliceRange: 10.200.48.0/20 + - nodeName: "" + sliceRange: 10.200.64.0/20 + - nodeName: "" + sliceRange: 10.200.80.0/20 + - nodeName: "" + sliceRange: 10.200.96.0/20 + - nodeName: "" + sliceRange: 10.200.112.0/20 + - nodeName: "" + sliceRange: 10.200.128.0/20 + - nodeName: "" + sliceRange: 10.200.144.0/20 + - nodeName: "" + sliceRange: 10.200.160.0/20 + - nodeName: "" + sliceRange: 10.200.176.0/20 + - nodeName: "" + sliceRange: 10.200.192.0/20 + - nodeName: "" + sliceRange: 10.200.208.0/20 + - nodeName: "" + sliceRange: 10.200.224.0/20 + - nodeName: "" + sliceRange: 10.200.240.0/20 + - nodeName: "" + sliceRange: 10.201.0.0/20 + - nodeName: "" + sliceRange: 10.201.16.0/20 + - nodeName: "" + sliceRange: 10.201.32.0/20 + - nodeName: "" + sliceRange: 10.201.48.0/20 + - nodeName: "" + sliceRange: 10.201.64.0/20 + - nodeName: "" + sliceRange: 10.201.80.0/20 + - nodeName: "" + sliceRange: 10.201.96.0/20 + - nodeName: "" + sliceRange: 10.201.112.0/20 + - nodeName: "" + sliceRange: 10.201.128.0/20 + - nodeName: "" + sliceRange: 10.201.144.0/20 + - nodeName: "" + sliceRange: 10.201.160.0/20 + - nodeName: "" + sliceRange: 10.201.176.0/20 + - nodeName: "" + sliceRange: 10.201.192.0/20 + - nodeName: "" + sliceRange: 10.201.208.0/20 + - nodeName: "" + sliceRange: 10.201.224.0/20 + - nodeName: "" + sliceRange: 10.201.240.0/20 + - nodeName: "" + sliceRange: 10.202.0.0/20 + - nodeName: "" + sliceRange: 10.202.16.0/20 + - nodeName: "" + sliceRange: 10.202.32.0/20 + - nodeName: "" + sliceRange: 10.202.48.0/20 + - nodeName: "" + sliceRange: 10.202.64.0/20 + - nodeName: "" + sliceRange: 10.202.80.0/20 + - nodeName: "" + sliceRange: 10.202.96.0/20 + - nodeName: "" + sliceRange: 10.202.112.0/20 + - nodeName: "" + sliceRange: 10.202.128.0/20 + - nodeName: "" + sliceRange: 10.202.144.0/20 + - nodeName: "" + sliceRange: 10.202.160.0/20 + - nodeName: "" + sliceRange: 10.202.176.0/20 + - nodeName: "" + sliceRange: 10.202.192.0/20 + - nodeName: "" + sliceRange: 10.202.208.0/20 + - nodeName: "" + sliceRange: 10.202.224.0/20 + - nodeName: "" + sliceRange: 10.202.240.0/20 + - nodeName: "" + sliceRange: 10.203.0.0/20 + - nodeName: "" + sliceRange: 10.203.16.0/20 + - nodeName: "" + sliceRange: 10.203.32.0/20 + - nodeName: "" + sliceRange: 10.203.48.0/20 + - nodeName: "" + sliceRange: 10.203.64.0/20 + - nodeName: "" + sliceRange: 10.203.80.0/20 + - nodeName: "" + sliceRange: 10.203.96.0/20 + - nodeName: "" + sliceRange: 10.203.112.0/20 + - nodeName: "" + sliceRange: 10.203.128.0/20 + - nodeName: "" + sliceRange: 10.203.144.0/20 + - nodeName: "" + sliceRange: 10.203.160.0/20 + - nodeName: "" + sliceRange: 10.203.176.0/20 + - nodeName: "" + sliceRange: 10.203.192.0/20 + - nodeName: "" + sliceRange: 10.203.208.0/20 + - nodeName: "" + sliceRange: 10.203.224.0/20 + - nodeName: "" + sliceRange: 10.203.240.0/20 + - nodeName: "" + sliceRange: 10.204.0.0/20 + - nodeName: "" + sliceRange: 10.204.16.0/20 + - nodeName: "" + sliceRange: 10.204.32.0/20 + - nodeName: "" + sliceRange: 10.204.48.0/20 + - nodeName: "" + sliceRange: 10.204.64.0/20 + - nodeName: "" + sliceRange: 10.204.80.0/20 + - nodeName: "" + sliceRange: 10.204.96.0/20 + - nodeName: "" + sliceRange: 10.204.112.0/20 + - nodeName: "" + sliceRange: 10.204.128.0/20 + - nodeName: "" + sliceRange: 10.204.144.0/20 + - nodeName: "" + sliceRange: 10.204.160.0/20 + - nodeName: "" + sliceRange: 10.204.176.0/20 + - nodeName: "" + sliceRange: 10.204.192.0/20 + - nodeName: "" + sliceRange: 10.204.208.0/20 + - nodeName: "" + sliceRange: 10.204.224.0/20 + - nodeName: "" + sliceRange: 10.204.240.0/20 + - nodeName: "" + sliceRange: 10.205.0.0/20 + - nodeName: "" + sliceRange: 10.205.16.0/20 + - nodeName: "" + sliceRange: 10.205.32.0/20 + - nodeName: "" + sliceRange: 10.205.48.0/20 + - nodeName: "" + sliceRange: 10.205.64.0/20 + - nodeName: "" + sliceRange: 10.205.80.0/20 + - nodeName: "" + sliceRange: 10.205.96.0/20 + - nodeName: "" + sliceRange: 10.205.112.0/20 + - nodeName: "" + sliceRange: 10.205.128.0/20 + - nodeName: "" + sliceRange: 10.205.144.0/20 + - nodeName: "" + sliceRange: 10.205.160.0/20 + - nodeName: "" + sliceRange: 10.205.176.0/20 + - nodeName: "" + sliceRange: 10.205.192.0/20 + - nodeName: "" + sliceRange: 10.205.208.0/20 + - nodeName: "" + sliceRange: 10.205.224.0/20 + - nodeName: "" + sliceRange: 10.205.240.0/20 + - nodeName: "" + sliceRange: 10.206.0.0/20 + - nodeName: "" + sliceRange: 10.206.16.0/20 + - nodeName: "" + sliceRange: 10.206.32.0/20 + - nodeName: "" + sliceRange: 10.206.48.0/20 + - nodeName: "" + sliceRange: 10.206.64.0/20 + - nodeName: "" + sliceRange: 10.206.80.0/20 + - nodeName: "" + sliceRange: 10.206.96.0/20 + - nodeName: "" + sliceRange: 10.206.112.0/20 + - nodeName: "" + sliceRange: 10.206.128.0/20 + - nodeName: "" + sliceRange: 10.206.144.0/20 + - nodeName: "" + sliceRange: 10.206.160.0/20 + - nodeName: "" + sliceRange: 10.206.176.0/20 + - nodeName: "" + sliceRange: 10.206.192.0/20 + - nodeName: "" + sliceRange: 10.206.208.0/20 + - nodeName: "" + sliceRange: 10.206.224.0/20 + - nodeName: "" + sliceRange: 10.206.240.0/20 + - nodeName: "" + sliceRange: 10.207.0.0/20 + - nodeName: "" + sliceRange: 10.207.16.0/20 + - nodeName: "" + sliceRange: 10.207.32.0/20 + - nodeName: "" + sliceRange: 10.207.48.0/20 + - nodeName: "" + sliceRange: 10.207.64.0/20 + - nodeName: "" + sliceRange: 10.207.80.0/20 + - nodeName: "" + sliceRange: 10.207.96.0/20 + - nodeName: "" + sliceRange: 10.207.112.0/20 + - nodeName: "" + sliceRange: 10.207.128.0/20 + - nodeName: "" + sliceRange: 10.207.144.0/20 + - nodeName: "" + sliceRange: 10.207.160.0/20 + - nodeName: "" + sliceRange: 10.207.176.0/20 + - nodeName: "" + sliceRange: 10.207.192.0/20 + - nodeName: "" + sliceRange: 10.207.208.0/20 + - nodeName: "" + sliceRange: 10.207.224.0/20 + - nodeName: "" + sliceRange: 10.207.240.0/20 + - nodeName: "" + sliceRange: 10.208.0.0/20 + - nodeName: "" + sliceRange: 10.208.16.0/20 + - nodeName: "" + sliceRange: 10.208.32.0/20 + - nodeName: "" + sliceRange: 10.208.48.0/20 + - nodeName: "" + sliceRange: 10.208.64.0/20 + - nodeName: "" + sliceRange: 10.208.80.0/20 + - nodeName: "" + sliceRange: 10.208.96.0/20 + - nodeName: "" + sliceRange: 10.208.112.0/20 + - nodeName: "" + sliceRange: 10.208.128.0/20 + - nodeName: "" + sliceRange: 10.208.144.0/20 + - nodeName: "" + sliceRange: 10.208.160.0/20 + - nodeName: "" + sliceRange: 10.208.176.0/20 + - nodeName: "" + sliceRange: 10.208.192.0/20 + - nodeName: "" + sliceRange: 10.208.208.0/20 + - nodeName: "" + sliceRange: 10.208.224.0/20 + - nodeName: "" + sliceRange: 10.208.240.0/20 + - nodeName: "" + sliceRange: 10.209.0.0/20 + - nodeName: "" + sliceRange: 10.209.16.0/20 + - nodeName: "" + sliceRange: 10.209.32.0/20 + - nodeName: "" + sliceRange: 10.209.48.0/20 + - nodeName: "" + sliceRange: 10.209.64.0/20 + - nodeName: "" + sliceRange: 10.209.80.0/20 + - nodeName: "" + sliceRange: 10.209.96.0/20 + - nodeName: "" + sliceRange: 10.209.112.0/20 + - nodeName: "" + sliceRange: 10.209.128.0/20 + - nodeName: "" + sliceRange: 10.209.144.0/20 + - nodeName: "" + sliceRange: 10.209.160.0/20 + - nodeName: "" + sliceRange: 10.209.176.0/20 + - nodeName: "" + sliceRange: 10.209.192.0/20 + - nodeName: "" + sliceRange: 10.209.208.0/20 + - nodeName: "" + sliceRange: 10.209.224.0/20 + - nodeName: "" + sliceRange: 10.209.240.0/20 + - nodeName: "" + sliceRange: 10.210.0.0/20 + - nodeName: "" + sliceRange: 10.210.16.0/20 + - nodeName: "" + sliceRange: 10.210.32.0/20 + - nodeName: "" + sliceRange: 10.210.48.0/20 + - nodeName: "" + sliceRange: 10.210.64.0/20 + - nodeName: "" + sliceRange: 10.210.80.0/20 + - nodeName: "" + sliceRange: 10.210.96.0/20 + - nodeName: "" + sliceRange: 10.210.112.0/20 + - nodeName: "" + sliceRange: 10.210.128.0/20 + - nodeName: "" + sliceRange: 10.210.144.0/20 + - nodeName: "" + sliceRange: 10.210.160.0/20 + - nodeName: "" + sliceRange: 10.210.176.0/20 + - nodeName: "" + sliceRange: 10.210.192.0/20 + - nodeName: "" + sliceRange: 10.210.208.0/20 + - nodeName: "" + sliceRange: 10.210.224.0/20 + - nodeName: "" + sliceRange: 10.210.240.0/20 + - nodeName: "" + sliceRange: 10.211.0.0/20 + - nodeName: "" + sliceRange: 10.211.16.0/20 + - nodeName: "" + sliceRange: 10.211.32.0/20 + - nodeName: "" + sliceRange: 10.211.48.0/20 + - nodeName: "" + sliceRange: 10.211.64.0/20 + - nodeName: "" + sliceRange: 10.211.80.0/20 + - nodeName: "" + sliceRange: 10.211.96.0/20 + - nodeName: "" + sliceRange: 10.211.112.0/20 + - nodeName: "" + sliceRange: 10.211.128.0/20 + - nodeName: "" + sliceRange: 10.211.144.0/20 + - nodeName: "" + sliceRange: 10.211.160.0/20 + - nodeName: "" + sliceRange: 10.211.176.0/20 + - nodeName: "" + sliceRange: 10.211.192.0/20 + - nodeName: "" + sliceRange: 10.211.208.0/20 + - nodeName: "" + sliceRange: 10.211.224.0/20 + - nodeName: "" + sliceRange: 10.211.240.0/20 + - nodeName: "" + sliceRange: 10.212.0.0/20 + - nodeName: "" + sliceRange: 10.212.16.0/20 + - nodeName: "" + sliceRange: 10.212.32.0/20 + - nodeName: "" + sliceRange: 10.212.48.0/20 + - nodeName: "" + sliceRange: 10.212.64.0/20 + - nodeName: "" + sliceRange: 10.212.80.0/20 + - nodeName: "" + sliceRange: 10.212.96.0/20 + - nodeName: "" + sliceRange: 10.212.112.0/20 + - nodeName: "" + sliceRange: 10.212.128.0/20 + - nodeName: "" + sliceRange: 10.212.144.0/20 + - nodeName: "" + sliceRange: 10.212.160.0/20 + - nodeName: "" + sliceRange: 10.212.176.0/20 + - nodeName: "" + sliceRange: 10.212.192.0/20 + - nodeName: "" + sliceRange: 10.212.208.0/20 + - nodeName: "" + sliceRange: 10.212.224.0/20 + - nodeName: "" + sliceRange: 10.212.240.0/20 + - nodeName: "" + sliceRange: 10.213.0.0/20 + - nodeName: "" + sliceRange: 10.213.16.0/20 + - nodeName: "" + sliceRange: 10.213.32.0/20 + - nodeName: "" + sliceRange: 10.213.48.0/20 + - nodeName: "" + sliceRange: 10.213.64.0/20 + - nodeName: "" + sliceRange: 10.213.80.0/20 + - nodeName: "" + sliceRange: 10.213.96.0/20 + - nodeName: "" + sliceRange: 10.213.112.0/20 + - nodeName: "" + sliceRange: 10.213.128.0/20 + - nodeName: "" + sliceRange: 10.213.144.0/20 + - nodeName: "" + sliceRange: 10.213.160.0/20 + - nodeName: "" + sliceRange: 10.213.176.0/20 + - nodeName: "" + sliceRange: 10.213.192.0/20 + - nodeName: "" + sliceRange: 10.213.208.0/20 + - nodeName: "" + sliceRange: 10.213.224.0/20 + - nodeName: "" + sliceRange: 10.213.240.0/20 + - nodeName: "" + sliceRange: 10.214.0.0/20 + - nodeName: "" + sliceRange: 10.214.16.0/20 + - nodeName: "" + sliceRange: 10.214.32.0/20 + - nodeName: "" + sliceRange: 10.214.48.0/20 + - nodeName: "" + sliceRange: 10.214.64.0/20 + - nodeName: "" + sliceRange: 10.214.80.0/20 + - nodeName: "" + sliceRange: 10.214.96.0/20 + - nodeName: "" + sliceRange: 10.214.112.0/20 + - nodeName: "" + sliceRange: 10.214.128.0/20 + - nodeName: "" + sliceRange: 10.214.144.0/20 + - nodeName: "" + sliceRange: 10.214.160.0/20 + - nodeName: "" + sliceRange: 10.214.176.0/20 + - nodeName: "" + sliceRange: 10.214.192.0/20 + - nodeName: "" + sliceRange: 10.214.208.0/20 + - nodeName: "" + sliceRange: 10.214.224.0/20 + - nodeName: "" + sliceRange: 10.214.240.0/20 + - nodeName: "" + sliceRange: 10.215.0.0/20 + - nodeName: "" + sliceRange: 10.215.16.0/20 + - nodeName: "" + sliceRange: 10.215.32.0/20 + - nodeName: "" + sliceRange: 10.215.48.0/20 + - nodeName: "" + sliceRange: 10.215.64.0/20 + - nodeName: "" + sliceRange: 10.215.80.0/20 + - nodeName: "" + sliceRange: 10.215.96.0/20 + - nodeName: "" + sliceRange: 10.215.112.0/20 + - nodeName: "" + sliceRange: 10.215.128.0/20 + - nodeName: "" + sliceRange: 10.215.144.0/20 + - nodeName: "" + sliceRange: 10.215.160.0/20 + - nodeName: "" + sliceRange: 10.215.176.0/20 + - nodeName: "" + sliceRange: 10.215.192.0/20 + - nodeName: "" + sliceRange: 10.215.208.0/20 + - nodeName: "" + sliceRange: 10.215.224.0/20 + - nodeName: "" + sliceRange: 10.215.240.0/20 + - nodeName: "" + sliceRange: 10.216.0.0/20 + - nodeName: "" + sliceRange: 10.216.16.0/20 + - nodeName: "" + sliceRange: 10.216.32.0/20 + - nodeName: "" + sliceRange: 10.216.48.0/20 + - nodeName: "" + sliceRange: 10.216.64.0/20 + - nodeName: "" + sliceRange: 10.216.80.0/20 + - nodeName: "" + sliceRange: 10.216.96.0/20 + - nodeName: "" + sliceRange: 10.216.112.0/20 + - nodeName: "" + sliceRange: 10.216.128.0/20 + - nodeName: "" + sliceRange: 10.216.144.0/20 + - nodeName: "" + sliceRange: 10.216.160.0/20 + - nodeName: "" + sliceRange: 10.216.176.0/20 + - nodeName: "" + sliceRange: 10.216.192.0/20 + - nodeName: "" + sliceRange: 10.216.208.0/20 + - nodeName: "" + sliceRange: 10.216.224.0/20 + - nodeName: "" + sliceRange: 10.216.240.0/20 + - nodeName: "" + sliceRange: 10.217.0.0/20 + - nodeName: "" + sliceRange: 10.217.16.0/20 + - nodeName: "" + sliceRange: 10.217.32.0/20 + - nodeName: "" + sliceRange: 10.217.48.0/20 + - nodeName: "" + sliceRange: 10.217.64.0/20 + - nodeName: "" + sliceRange: 10.217.80.0/20 + - nodeName: "" + sliceRange: 10.217.96.0/20 + - nodeName: "" + sliceRange: 10.217.112.0/20 + - nodeName: "" + sliceRange: 10.217.128.0/20 + - nodeName: "" + sliceRange: 10.217.144.0/20 + - nodeName: "" + sliceRange: 10.217.160.0/20 + - nodeName: "" + sliceRange: 10.217.176.0/20 + - nodeName: "" + sliceRange: 10.217.192.0/20 + - nodeName: "" + sliceRange: 10.217.208.0/20 + - nodeName: "" + sliceRange: 10.217.224.0/20 + - nodeName: "" + sliceRange: 10.217.240.0/20 + - nodeName: "" + sliceRange: 10.218.0.0/20 + - nodeName: "" + sliceRange: 10.218.16.0/20 + - nodeName: "" + sliceRange: 10.218.32.0/20 + - nodeName: "" + sliceRange: 10.218.48.0/20 + - nodeName: "" + sliceRange: 10.218.64.0/20 + - nodeName: "" + sliceRange: 10.218.80.0/20 + - nodeName: "" + sliceRange: 10.218.96.0/20 + - nodeName: "" + sliceRange: 10.218.112.0/20 + - nodeName: "" + sliceRange: 10.218.128.0/20 + - nodeName: "" + sliceRange: 10.218.144.0/20 + - nodeName: "" + sliceRange: 10.218.160.0/20 + - nodeName: "" + sliceRange: 10.218.176.0/20 + - nodeName: "" + sliceRange: 10.218.192.0/20 + - nodeName: "" + sliceRange: 10.218.208.0/20 + - nodeName: "" + sliceRange: 10.218.224.0/20 + - nodeName: "" + sliceRange: 10.218.240.0/20 + - nodeName: "" + sliceRange: 10.219.0.0/20 + - nodeName: "" + sliceRange: 10.219.16.0/20 + - nodeName: "" + sliceRange: 10.219.32.0/20 + - nodeName: "" + sliceRange: 10.219.48.0/20 + - nodeName: "" + sliceRange: 10.219.64.0/20 + - nodeName: "" + sliceRange: 10.219.80.0/20 + - nodeName: "" + sliceRange: 10.219.96.0/20 + - nodeName: "" + sliceRange: 10.219.112.0/20 + - nodeName: "" + sliceRange: 10.219.128.0/20 + - nodeName: "" + sliceRange: 10.219.144.0/20 + - nodeName: "" + sliceRange: 10.219.160.0/20 + - nodeName: "" + sliceRange: 10.219.176.0/20 + - nodeName: "" + sliceRange: 10.219.192.0/20 + - nodeName: "" + sliceRange: 10.219.208.0/20 + - nodeName: "" + sliceRange: 10.219.224.0/20 + - nodeName: "" + sliceRange: 10.219.240.0/20 + - nodeName: "" + sliceRange: 10.220.0.0/20 + - nodeName: "" + sliceRange: 10.220.16.0/20 + - nodeName: "" + sliceRange: 10.220.32.0/20 + - nodeName: "" + sliceRange: 10.220.48.0/20 + - nodeName: "" + sliceRange: 10.220.64.0/20 + - nodeName: "" + sliceRange: 10.220.80.0/20 + - nodeName: "" + sliceRange: 10.220.96.0/20 + - nodeName: "" + sliceRange: 10.220.112.0/20 + - nodeName: "" + sliceRange: 10.220.128.0/20 + - nodeName: "" + sliceRange: 10.220.144.0/20 + - nodeName: "" + sliceRange: 10.220.160.0/20 + - nodeName: "" + sliceRange: 10.220.176.0/20 + - nodeName: "" + sliceRange: 10.220.192.0/20 + - nodeName: "" + sliceRange: 10.220.208.0/20 + - nodeName: "" + sliceRange: 10.220.224.0/20 + - nodeName: "" + sliceRange: 10.220.240.0/20 + - nodeName: "" + sliceRange: 10.221.0.0/20 + - nodeName: "" + sliceRange: 10.221.16.0/20 + - nodeName: "" + sliceRange: 10.221.32.0/20 + - nodeName: "" + sliceRange: 10.221.48.0/20 + - nodeName: "" + sliceRange: 10.221.64.0/20 + - nodeName: "" + sliceRange: 10.221.80.0/20 + - nodeName: "" + sliceRange: 10.221.96.0/20 + - nodeName: "" + sliceRange: 10.221.112.0/20 + - nodeName: "" + sliceRange: 10.221.128.0/20 + - nodeName: "" + sliceRange: 10.221.144.0/20 + - nodeName: "" + sliceRange: 10.221.160.0/20 + - nodeName: "" + sliceRange: 10.221.176.0/20 + - nodeName: "" + sliceRange: 10.221.192.0/20 + - nodeName: "" + sliceRange: 10.221.208.0/20 + - nodeName: "" + sliceRange: 10.221.224.0/20 + - nodeName: "" + sliceRange: 10.221.240.0/20 + - nodeName: "" + sliceRange: 10.222.0.0/20 + - nodeName: "" + sliceRange: 10.222.16.0/20 + - nodeName: "" + sliceRange: 10.222.32.0/20 + - nodeName: "" + sliceRange: 10.222.48.0/20 + - nodeName: "" + sliceRange: 10.222.64.0/20 + - nodeName: "" + sliceRange: 10.222.80.0/20 + - nodeName: "" + sliceRange: 10.222.96.0/20 + - nodeName: "" + sliceRange: 10.222.112.0/20 + - nodeName: "" + sliceRange: 10.222.128.0/20 + - nodeName: "" + sliceRange: 10.222.144.0/20 + - nodeName: "" + sliceRange: 10.222.160.0/20 + - nodeName: "" + sliceRange: 10.222.176.0/20 + - nodeName: "" + sliceRange: 10.222.192.0/20 + - nodeName: "" + sliceRange: 10.222.208.0/20 + - nodeName: "" + sliceRange: 10.222.224.0/20 + - nodeName: "" + sliceRange: 10.222.240.0/20 + - nodeName: "" + sliceRange: 10.223.0.0/20 + - nodeName: "" + sliceRange: 10.223.16.0/20 + - nodeName: "" + sliceRange: 10.223.32.0/20 + - nodeName: "" + sliceRange: 10.223.48.0/20 + - nodeName: "" + sliceRange: 10.223.64.0/20 + - nodeName: "" + sliceRange: 10.223.80.0/20 + - nodeName: "" + sliceRange: 10.223.96.0/20 + - nodeName: "" + sliceRange: 10.223.112.0/20 + - nodeName: "" + sliceRange: 10.223.128.0/20 + - nodeName: "" + sliceRange: 10.223.144.0/20 + - nodeName: "" + sliceRange: 10.223.160.0/20 + - nodeName: "" + sliceRange: 10.223.176.0/20 + - nodeName: "" + sliceRange: 10.223.192.0/20 + - nodeName: "" + sliceRange: 10.223.208.0/20 + - nodeName: "" + sliceRange: 10.223.224.0/20 + - nodeName: "" + sliceRange: 10.223.240.0/20 + - nodeName: "" + sliceRange: 10.224.0.0/20 + - nodeName: "" + sliceRange: 10.224.16.0/20 + - nodeName: "" + sliceRange: 10.224.32.0/20 + - nodeName: "" + sliceRange: 10.224.48.0/20 + - nodeName: "" + sliceRange: 10.224.64.0/20 + - nodeName: "" + sliceRange: 10.224.80.0/20 + - nodeName: "" + sliceRange: 10.224.96.0/20 + - nodeName: "" + sliceRange: 10.224.112.0/20 + - nodeName: "" + sliceRange: 10.224.128.0/20 + - nodeName: "" + sliceRange: 10.224.144.0/20 + - nodeName: "" + sliceRange: 10.224.160.0/20 + - nodeName: "" + sliceRange: 10.224.176.0/20 + - nodeName: "" + sliceRange: 10.224.192.0/20 + - nodeName: "" + sliceRange: 10.224.208.0/20 + - nodeName: "" + sliceRange: 10.224.224.0/20 + - nodeName: "" + sliceRange: 10.224.240.0/20 + - nodeName: "" + sliceRange: 10.225.0.0/20 + - nodeName: "" + sliceRange: 10.225.16.0/20 + - nodeName: "" + sliceRange: 10.225.32.0/20 + - nodeName: "" + sliceRange: 10.225.48.0/20 + - nodeName: "" + sliceRange: 10.225.64.0/20 + - nodeName: "" + sliceRange: 10.225.80.0/20 + - nodeName: "" + sliceRange: 10.225.96.0/20 + - nodeName: "" + sliceRange: 10.225.112.0/20 + - nodeName: "" + sliceRange: 10.225.128.0/20 + - nodeName: "" + sliceRange: 10.225.144.0/20 + - nodeName: "" + sliceRange: 10.225.160.0/20 + - nodeName: "" + sliceRange: 10.225.176.0/20 + - nodeName: "" + sliceRange: 10.225.192.0/20 + - nodeName: "" + sliceRange: 10.225.208.0/20 + - nodeName: "" + sliceRange: 10.225.224.0/20 + - nodeName: "" + sliceRange: 10.225.240.0/20 + - nodeName: "" + sliceRange: 10.226.0.0/20 + - nodeName: "" + sliceRange: 10.226.16.0/20 + - nodeName: "" + sliceRange: 10.226.32.0/20 + - nodeName: "" + sliceRange: 10.226.48.0/20 + - nodeName: "" + sliceRange: 10.226.64.0/20 + - nodeName: "" + sliceRange: 10.226.80.0/20 + - nodeName: "" + sliceRange: 10.226.96.0/20 + - nodeName: "" + sliceRange: 10.226.112.0/20 + - nodeName: "" + sliceRange: 10.226.128.0/20 + - nodeName: "" + sliceRange: 10.226.144.0/20 + - nodeName: "" + sliceRange: 10.226.160.0/20 + - nodeName: "" + sliceRange: 10.226.176.0/20 + - nodeName: "" + sliceRange: 10.226.192.0/20 + - nodeName: "" + sliceRange: 10.226.208.0/20 + - nodeName: "" + sliceRange: 10.226.224.0/20 + - nodeName: "" + sliceRange: 10.226.240.0/20 + - nodeName: "" + sliceRange: 10.227.0.0/20 + - nodeName: "" + sliceRange: 10.227.16.0/20 + - nodeName: "" + sliceRange: 10.227.32.0/20 + - nodeName: "" + sliceRange: 10.227.48.0/20 + - nodeName: "" + sliceRange: 10.227.64.0/20 + - nodeName: "" + sliceRange: 10.227.80.0/20 + - nodeName: "" + sliceRange: 10.227.96.0/20 + - nodeName: "" + sliceRange: 10.227.112.0/20 + - nodeName: "" + sliceRange: 10.227.128.0/20 + - nodeName: "" + sliceRange: 10.227.144.0/20 + - nodeName: "" + sliceRange: 10.227.160.0/20 + - nodeName: "" + sliceRange: 10.227.176.0/20 + - nodeName: "" + sliceRange: 10.227.192.0/20 + - nodeName: "" + sliceRange: 10.227.208.0/20 + - nodeName: "" + sliceRange: 10.227.224.0/20 + - nodeName: "" + sliceRange: 10.227.240.0/20 + - nodeName: "" + sliceRange: 10.228.0.0/20 + - nodeName: "" + sliceRange: 10.228.16.0/20 + - nodeName: "" + sliceRange: 10.228.32.0/20 + - nodeName: "" + sliceRange: 10.228.48.0/20 + - nodeName: "" + sliceRange: 10.228.64.0/20 + - nodeName: "" + sliceRange: 10.228.80.0/20 + - nodeName: "" + sliceRange: 10.228.96.0/20 + - nodeName: "" + sliceRange: 10.228.112.0/20 + - nodeName: "" + sliceRange: 10.228.128.0/20 + - nodeName: "" + sliceRange: 10.228.144.0/20 + - nodeName: "" + sliceRange: 10.228.160.0/20 + - nodeName: "" + sliceRange: 10.228.176.0/20 + - nodeName: "" + sliceRange: 10.228.192.0/20 + - nodeName: "" + sliceRange: 10.228.208.0/20 + - nodeName: "" + sliceRange: 10.228.224.0/20 + - nodeName: "" + sliceRange: 10.228.240.0/20 + - nodeName: "" + sliceRange: 10.229.0.0/20 + - nodeName: "" + sliceRange: 10.229.16.0/20 + - nodeName: "" + sliceRange: 10.229.32.0/20 + - nodeName: "" + sliceRange: 10.229.48.0/20 + - nodeName: "" + sliceRange: 10.229.64.0/20 + - nodeName: "" + sliceRange: 10.229.80.0/20 + - nodeName: "" + sliceRange: 10.229.96.0/20 + - nodeName: "" + sliceRange: 10.229.112.0/20 + - nodeName: "" + sliceRange: 10.229.128.0/20 + - nodeName: "" + sliceRange: 10.229.144.0/20 + - nodeName: "" + sliceRange: 10.229.160.0/20 + - nodeName: "" + sliceRange: 10.229.176.0/20 + - nodeName: "" + sliceRange: 10.229.192.0/20 + - nodeName: "" + sliceRange: 10.229.208.0/20 + - nodeName: "" + sliceRange: 10.229.224.0/20 + - nodeName: "" + sliceRange: 10.229.240.0/20 + - nodeName: "" + sliceRange: 10.230.0.0/20 + - nodeName: "" + sliceRange: 10.230.16.0/20 + - nodeName: "" + sliceRange: 10.230.32.0/20 + - nodeName: "" + sliceRange: 10.230.48.0/20 + - nodeName: "" + sliceRange: 10.230.64.0/20 + - nodeName: "" + sliceRange: 10.230.80.0/20 + - nodeName: "" + sliceRange: 10.230.96.0/20 + - nodeName: "" + sliceRange: 10.230.112.0/20 + - nodeName: "" + sliceRange: 10.230.128.0/20 + - nodeName: "" + sliceRange: 10.230.144.0/20 + - nodeName: "" + sliceRange: 10.230.160.0/20 + - nodeName: "" + sliceRange: 10.230.176.0/20 + - nodeName: "" + sliceRange: 10.230.192.0/20 + - nodeName: "" + sliceRange: 10.230.208.0/20 + - nodeName: "" + sliceRange: 10.230.224.0/20 + - nodeName: "" + sliceRange: 10.230.240.0/20 + - nodeName: "" + sliceRange: 10.231.0.0/20 + - nodeName: "" + sliceRange: 10.231.16.0/20 + - nodeName: "" + sliceRange: 10.231.32.0/20 + - nodeName: "" + sliceRange: 10.231.48.0/20 + - nodeName: "" + sliceRange: 10.231.64.0/20 + - nodeName: "" + sliceRange: 10.231.80.0/20 + - nodeName: "" + sliceRange: 10.231.96.0/20 + - nodeName: "" + sliceRange: 10.231.112.0/20 + - nodeName: "" + sliceRange: 10.231.128.0/20 + - nodeName: "" + sliceRange: 10.231.144.0/20 + - nodeName: "" + sliceRange: 10.231.160.0/20 + - nodeName: "" + sliceRange: 10.231.176.0/20 + - nodeName: "" + sliceRange: 10.231.192.0/20 + - nodeName: "" + sliceRange: 10.231.208.0/20 + - nodeName: "" + sliceRange: 10.231.224.0/20 + - nodeName: "" + sliceRange: 10.231.240.0/20 + - nodeName: "" + sliceRange: 10.232.0.0/20 + - nodeName: "" + sliceRange: 10.232.16.0/20 + - nodeName: "" + sliceRange: 10.232.32.0/20 + - nodeName: "" + sliceRange: 10.232.48.0/20 + - nodeName: "" + sliceRange: 10.232.64.0/20 + - nodeName: "" + sliceRange: 10.232.80.0/20 + - nodeName: "" + sliceRange: 10.232.96.0/20 + - nodeName: "" + sliceRange: 10.232.112.0/20 + - nodeName: "" + sliceRange: 10.232.128.0/20 + - nodeName: "" + sliceRange: 10.232.144.0/20 + - nodeName: "" + sliceRange: 10.232.160.0/20 + - nodeName: "" + sliceRange: 10.232.176.0/20 + - nodeName: "" + sliceRange: 10.232.192.0/20 + - nodeName: "" + sliceRange: 10.232.208.0/20 + - nodeName: "" + sliceRange: 10.232.224.0/20 + - nodeName: "" + sliceRange: 10.232.240.0/20 + - nodeName: "" + sliceRange: 10.233.0.0/20 + - nodeName: "" + sliceRange: 10.233.16.0/20 + - nodeName: "" + sliceRange: 10.233.32.0/20 + - nodeName: "" + sliceRange: 10.233.48.0/20 + - nodeName: "" + sliceRange: 10.233.64.0/20 + - nodeName: "" + sliceRange: 10.233.80.0/20 + - nodeName: "" + sliceRange: 10.233.96.0/20 + - nodeName: "" + sliceRange: 10.233.112.0/20 + - nodeName: "" + sliceRange: 10.233.128.0/20 + - nodeName: "" + sliceRange: 10.233.144.0/20 + - nodeName: "" + sliceRange: 10.233.160.0/20 + - nodeName: "" + sliceRange: 10.233.176.0/20 + - nodeName: "" + sliceRange: 10.233.192.0/20 + - nodeName: "" + sliceRange: 10.233.208.0/20 + - nodeName: "" + sliceRange: 10.233.224.0/20 + - nodeName: "" + sliceRange: 10.233.240.0/20 + - nodeName: "" + sliceRange: 10.234.0.0/20 + - nodeName: "" + sliceRange: 10.234.16.0/20 + - nodeName: "" + sliceRange: 10.234.32.0/20 + - nodeName: "" + sliceRange: 10.234.48.0/20 + - nodeName: "" + sliceRange: 10.234.64.0/20 + - nodeName: "" + sliceRange: 10.234.80.0/20 + - nodeName: "" + sliceRange: 10.234.96.0/20 + - nodeName: "" + sliceRange: 10.234.112.0/20 + - nodeName: "" + sliceRange: 10.234.128.0/20 + - nodeName: "" + sliceRange: 10.234.144.0/20 + - nodeName: "" + sliceRange: 10.234.160.0/20 + - nodeName: "" + sliceRange: 10.234.176.0/20 + - nodeName: "" + sliceRange: 10.234.192.0/20 + - nodeName: "" + sliceRange: 10.234.208.0/20 + - nodeName: "" + sliceRange: 10.234.224.0/20 + - nodeName: "" + sliceRange: 10.234.240.0/20 + - nodeName: "" + sliceRange: 10.235.0.0/20 + - nodeName: "" + sliceRange: 10.235.16.0/20 + - nodeName: "" + sliceRange: 10.235.32.0/20 + - nodeName: "" + sliceRange: 10.235.48.0/20 + - nodeName: "" + sliceRange: 10.235.64.0/20 + - nodeName: "" + sliceRange: 10.235.80.0/20 + - nodeName: "" + sliceRange: 10.235.96.0/20 + - nodeName: "" + sliceRange: 10.235.112.0/20 + - nodeName: "" + sliceRange: 10.235.128.0/20 + - nodeName: "" + sliceRange: 10.235.144.0/20 + - nodeName: "" + sliceRange: 10.235.160.0/20 + - nodeName: "" + sliceRange: 10.235.176.0/20 + - nodeName: "" + sliceRange: 10.235.192.0/20 + - nodeName: "" + sliceRange: 10.235.208.0/20 + - nodeName: "" + sliceRange: 10.235.224.0/20 + - nodeName: "" + sliceRange: 10.235.240.0/20 + - nodeName: "" + sliceRange: 10.236.0.0/20 + - nodeName: "" + sliceRange: 10.236.16.0/20 + - nodeName: "" + sliceRange: 10.236.32.0/20 + - nodeName: "" + sliceRange: 10.236.48.0/20 + - nodeName: "" + sliceRange: 10.236.64.0/20 + - nodeName: "" + sliceRange: 10.236.80.0/20 + - nodeName: "" + sliceRange: 10.236.96.0/20 + - nodeName: "" + sliceRange: 10.236.112.0/20 + - nodeName: "" + sliceRange: 10.236.128.0/20 + - nodeName: "" + sliceRange: 10.236.144.0/20 + - nodeName: "" + sliceRange: 10.236.160.0/20 + - nodeName: "" + sliceRange: 10.236.176.0/20 + - nodeName: "" + sliceRange: 10.236.192.0/20 + - nodeName: "" + sliceRange: 10.236.208.0/20 + - nodeName: "" + sliceRange: 10.236.224.0/20 + - nodeName: "" + sliceRange: 10.236.240.0/20 + - nodeName: "" + sliceRange: 10.237.0.0/20 + - nodeName: "" + sliceRange: 10.237.16.0/20 + - nodeName: "" + sliceRange: 10.237.32.0/20 + - nodeName: "" + sliceRange: 10.237.48.0/20 + - nodeName: "" + sliceRange: 10.237.64.0/20 + - nodeName: "" + sliceRange: 10.237.80.0/20 + - nodeName: "" + sliceRange: 10.237.96.0/20 + - nodeName: "" + sliceRange: 10.237.112.0/20 + - nodeName: "" + sliceRange: 10.237.128.0/20 + - nodeName: "" + sliceRange: 10.237.144.0/20 + - nodeName: "" + sliceRange: 10.237.160.0/20 + - nodeName: "" + sliceRange: 10.237.176.0/20 + - nodeName: "" + sliceRange: 10.237.192.0/20 + - nodeName: "" + sliceRange: 10.237.208.0/20 + - nodeName: "" + sliceRange: 10.237.224.0/20 + - nodeName: "" + sliceRange: 10.237.240.0/20 + - nodeName: "" + sliceRange: 10.238.0.0/20 + - nodeName: "" + sliceRange: 10.238.16.0/20 + - nodeName: "" + sliceRange: 10.238.32.0/20 + - nodeName: "" + sliceRange: 10.238.48.0/20 + - nodeName: "" + sliceRange: 10.238.64.0/20 + - nodeName: "" + sliceRange: 10.238.80.0/20 + - nodeName: "" + sliceRange: 10.238.96.0/20 + - nodeName: "" + sliceRange: 10.238.112.0/20 + - nodeName: "" + sliceRange: 10.238.128.0/20 + - nodeName: "" + sliceRange: 10.238.144.0/20 + - nodeName: "" + sliceRange: 10.238.160.0/20 + - nodeName: "" + sliceRange: 10.238.176.0/20 + - nodeName: "" + sliceRange: 10.238.192.0/20 + - nodeName: "" + sliceRange: 10.238.208.0/20 + - nodeName: "" + sliceRange: 10.238.224.0/20 + - nodeName: "" + sliceRange: 10.238.240.0/20 + - nodeName: "" + sliceRange: 10.239.0.0/20 + - nodeName: "" + sliceRange: 10.239.16.0/20 + - nodeName: "" + sliceRange: 10.239.32.0/20 + - nodeName: "" + sliceRange: 10.239.48.0/20 + - nodeName: "" + sliceRange: 10.239.64.0/20 + - nodeName: "" + sliceRange: 10.239.80.0/20 + - nodeName: "" + sliceRange: 10.239.96.0/20 + - nodeName: "" + sliceRange: 10.239.112.0/20 + - nodeName: "" + sliceRange: 10.239.128.0/20 + - nodeName: "" + sliceRange: 10.239.144.0/20 + - nodeName: "" + sliceRange: 10.239.160.0/20 + - nodeName: "" + sliceRange: 10.239.176.0/20 + - nodeName: "" + sliceRange: 10.239.192.0/20 + - nodeName: "" + sliceRange: 10.239.208.0/20 + - nodeName: "" + sliceRange: 10.239.224.0/20 + - nodeName: "" + sliceRange: 10.239.240.0/20 + - nodeName: "" + sliceRange: 10.240.0.0/20 + - nodeName: "" + sliceRange: 10.240.16.0/20 + - nodeName: "" + sliceRange: 10.240.32.0/20 + - nodeName: "" + sliceRange: 10.240.48.0/20 + - nodeName: "" + sliceRange: 10.240.64.0/20 + - nodeName: "" + sliceRange: 10.240.80.0/20 + - nodeName: "" + sliceRange: 10.240.96.0/20 + - nodeName: "" + sliceRange: 10.240.112.0/20 + - nodeName: "" + sliceRange: 10.240.128.0/20 + - nodeName: "" + sliceRange: 10.240.144.0/20 + - nodeName: "" + sliceRange: 10.240.160.0/20 + - nodeName: "" + sliceRange: 10.240.176.0/20 + - nodeName: "" + sliceRange: 10.240.192.0/20 + - nodeName: "" + sliceRange: 10.240.208.0/20 + - nodeName: "" + sliceRange: 10.240.224.0/20 + - nodeName: "" + sliceRange: 10.240.240.0/20 + - nodeName: "" + sliceRange: 10.241.0.0/20 + - nodeName: "" + sliceRange: 10.241.16.0/20 + - nodeName: "" + sliceRange: 10.241.32.0/20 + - nodeName: "" + sliceRange: 10.241.48.0/20 + - nodeName: "" + sliceRange: 10.241.64.0/20 + - nodeName: "" + sliceRange: 10.241.80.0/20 + - nodeName: "" + sliceRange: 10.241.96.0/20 + - nodeName: "" + sliceRange: 10.241.112.0/20 + - nodeName: "" + sliceRange: 10.241.128.0/20 + - nodeName: "" + sliceRange: 10.241.144.0/20 + - nodeName: "" + sliceRange: 10.241.160.0/20 + - nodeName: "" + sliceRange: 10.241.176.0/20 + - nodeName: "" + sliceRange: 10.241.192.0/20 + - nodeName: "" + sliceRange: 10.241.208.0/20 + - nodeName: "" + sliceRange: 10.241.224.0/20 + - nodeName: "" + sliceRange: 10.241.240.0/20 + - nodeName: "" + sliceRange: 10.242.0.0/20 + - nodeName: "" + sliceRange: 10.242.16.0/20 + - nodeName: "" + sliceRange: 10.242.32.0/20 + - nodeName: "" + sliceRange: 10.242.48.0/20 + - nodeName: "" + sliceRange: 10.242.64.0/20 + - nodeName: "" + sliceRange: 10.242.80.0/20 + - nodeName: "" + sliceRange: 10.242.96.0/20 + - nodeName: "" + sliceRange: 10.242.112.0/20 + - nodeName: "" + sliceRange: 10.242.128.0/20 + - nodeName: "" + sliceRange: 10.242.144.0/20 + - nodeName: "" + sliceRange: 10.242.160.0/20 + - nodeName: "" + sliceRange: 10.242.176.0/20 + - nodeName: "" + sliceRange: 10.242.192.0/20 + - nodeName: "" + sliceRange: 10.242.208.0/20 + - nodeName: "" + sliceRange: 10.242.224.0/20 + - nodeName: "" + sliceRange: 10.242.240.0/20 + - nodeName: "" + sliceRange: 10.243.0.0/20 + - nodeName: "" + sliceRange: 10.243.16.0/20 + - nodeName: "" + sliceRange: 10.243.32.0/20 + - nodeName: "" + sliceRange: 10.243.48.0/20 + - nodeName: "" + sliceRange: 10.243.64.0/20 + - nodeName: "" + sliceRange: 10.243.80.0/20 + - nodeName: "" + sliceRange: 10.243.96.0/20 + - nodeName: "" + sliceRange: 10.243.112.0/20 + - nodeName: "" + sliceRange: 10.243.128.0/20 + - nodeName: "" + sliceRange: 10.243.144.0/20 + - nodeName: "" + sliceRange: 10.243.160.0/20 + - nodeName: "" + sliceRange: 10.243.176.0/20 + - nodeName: "" + sliceRange: 10.243.192.0/20 + - nodeName: "" + sliceRange: 10.243.208.0/20 + - nodeName: "" + sliceRange: 10.243.224.0/20 + - nodeName: "" + sliceRange: 10.243.240.0/20 + - nodeName: "" + sliceRange: 10.244.0.0/20 + - nodeName: "" + sliceRange: 10.244.16.0/20 + - nodeName: "" + sliceRange: 10.244.32.0/20 + - nodeName: "" + sliceRange: 10.244.48.0/20 + - nodeName: "" + sliceRange: 10.244.64.0/20 + - nodeName: "" + sliceRange: 10.244.80.0/20 + - nodeName: "" + sliceRange: 10.244.96.0/20 + - nodeName: "" + sliceRange: 10.244.112.0/20 + - nodeName: "" + sliceRange: 10.244.128.0/20 + - nodeName: "" + sliceRange: 10.244.144.0/20 + - nodeName: "" + sliceRange: 10.244.160.0/20 + - nodeName: "" + sliceRange: 10.244.176.0/20 + - nodeName: "" + sliceRange: 10.244.192.0/20 + - nodeName: "" + sliceRange: 10.244.208.0/20 + - nodeName: "" + sliceRange: 10.244.224.0/20 + - nodeName: "" + sliceRange: 10.244.240.0/20 + - nodeName: "" + sliceRange: 10.245.0.0/20 + - nodeName: "" + sliceRange: 10.245.16.0/20 + - nodeName: "" + sliceRange: 10.245.32.0/20 + - nodeName: "" + sliceRange: 10.245.48.0/20 + - nodeName: "" + sliceRange: 10.245.64.0/20 + - nodeName: "" + sliceRange: 10.245.80.0/20 + - nodeName: "" + sliceRange: 10.245.96.0/20 + - nodeName: "" + sliceRange: 10.245.112.0/20 + - nodeName: "" + sliceRange: 10.245.128.0/20 + - nodeName: "" + sliceRange: 10.245.144.0/20 + - nodeName: "" + sliceRange: 10.245.160.0/20 + - nodeName: "" + sliceRange: 10.245.176.0/20 + - nodeName: "" + sliceRange: 10.245.192.0/20 + - nodeName: "" + sliceRange: 10.245.208.0/20 + - nodeName: "" + sliceRange: 10.245.224.0/20 + - nodeName: "" + sliceRange: 10.245.240.0/20 + - nodeName: "" + sliceRange: 10.246.0.0/20 + - nodeName: "" + sliceRange: 10.246.16.0/20 + - nodeName: "" + sliceRange: 10.246.32.0/20 + - nodeName: "" + sliceRange: 10.246.48.0/20 + - nodeName: "" + sliceRange: 10.246.64.0/20 + - nodeName: "" + sliceRange: 10.246.80.0/20 + - nodeName: "" + sliceRange: 10.246.96.0/20 + - nodeName: "" + sliceRange: 10.246.112.0/20 + - nodeName: "" + sliceRange: 10.246.128.0/20 + - nodeName: "" + sliceRange: 10.246.144.0/20 + - nodeName: "" + sliceRange: 10.246.160.0/20 + - nodeName: "" + sliceRange: 10.246.176.0/20 + - nodeName: "" + sliceRange: 10.246.192.0/20 + - nodeName: "" + sliceRange: 10.246.208.0/20 + - nodeName: "" + sliceRange: 10.246.224.0/20 + - nodeName: "" + sliceRange: 10.246.240.0/20 + - nodeName: "" + sliceRange: 10.247.0.0/20 + - nodeName: "" + sliceRange: 10.247.16.0/20 + - nodeName: "" + sliceRange: 10.247.32.0/20 + - nodeName: "" + sliceRange: 10.247.48.0/20 + - nodeName: "" + sliceRange: 10.247.64.0/20 + - nodeName: "" + sliceRange: 10.247.80.0/20 + - nodeName: "" + sliceRange: 10.247.96.0/20 + - nodeName: "" + sliceRange: 10.247.112.0/20 + - nodeName: "" + sliceRange: 10.247.128.0/20 + - nodeName: "" + sliceRange: 10.247.144.0/20 + - nodeName: "" + sliceRange: 10.247.160.0/20 + - nodeName: "" + sliceRange: 10.247.176.0/20 + - nodeName: "" + sliceRange: 10.247.192.0/20 + - nodeName: "" + sliceRange: 10.247.208.0/20 + - nodeName: "" + sliceRange: 10.247.224.0/20 + - nodeName: "" + sliceRange: 10.247.240.0/20 + - nodeName: "" + sliceRange: 10.248.0.0/20 + - nodeName: "" + sliceRange: 10.248.16.0/20 + - nodeName: "" + sliceRange: 10.248.32.0/20 + - nodeName: "" + sliceRange: 10.248.48.0/20 + - nodeName: "" + sliceRange: 10.248.64.0/20 + - nodeName: "" + sliceRange: 10.248.80.0/20 + - nodeName: "" + sliceRange: 10.248.96.0/20 + - nodeName: "" + sliceRange: 10.248.112.0/20 + - nodeName: "" + sliceRange: 10.248.128.0/20 + - nodeName: "" + sliceRange: 10.248.144.0/20 + - nodeName: "" + sliceRange: 10.248.160.0/20 + - nodeName: "" + sliceRange: 10.248.176.0/20 + - nodeName: "" + sliceRange: 10.248.192.0/20 + - nodeName: "" + sliceRange: 10.248.208.0/20 + - nodeName: "" + sliceRange: 10.248.224.0/20 + - nodeName: "" + sliceRange: 10.248.240.0/20 + - nodeName: "" + sliceRange: 10.249.0.0/20 + - nodeName: "" + sliceRange: 10.249.16.0/20 + - nodeName: "" + sliceRange: 10.249.32.0/20 + - nodeName: "" + sliceRange: 10.249.48.0/20 + - nodeName: "" + sliceRange: 10.249.64.0/20 + - nodeName: "" + sliceRange: 10.249.80.0/20 + - nodeName: "" + sliceRange: 10.249.96.0/20 + - nodeName: "" + sliceRange: 10.249.112.0/20 + - nodeName: "" + sliceRange: 10.249.128.0/20 + - nodeName: "" + sliceRange: 10.249.144.0/20 + - nodeName: "" + sliceRange: 10.249.160.0/20 + - nodeName: "" + sliceRange: 10.249.176.0/20 + - nodeName: "" + sliceRange: 10.249.192.0/20 + - nodeName: "" + sliceRange: 10.249.208.0/20 + - nodeName: "" + sliceRange: 10.249.224.0/20 + - nodeName: "" + sliceRange: 10.249.240.0/20 + - nodeName: "" + sliceRange: 10.250.0.0/20 + - nodeName: "" + sliceRange: 10.250.16.0/20 + - nodeName: "" + sliceRange: 10.250.32.0/20 + - nodeName: "" + sliceRange: 10.250.48.0/20 + - nodeName: "" + sliceRange: 10.250.64.0/20 + - nodeName: "" + sliceRange: 10.250.80.0/20 + - nodeName: "" + sliceRange: 10.250.96.0/20 + - nodeName: "" + sliceRange: 10.250.112.0/20 + - nodeName: "" + sliceRange: 10.250.128.0/20 + - nodeName: "" + sliceRange: 10.250.144.0/20 + - nodeName: "" + sliceRange: 10.250.160.0/20 + - nodeName: "" + sliceRange: 10.250.176.0/20 + - nodeName: "" + sliceRange: 10.250.192.0/20 + - nodeName: "" + sliceRange: 10.250.208.0/20 + - nodeName: "" + sliceRange: 10.250.224.0/20 + - nodeName: "" + sliceRange: 10.250.240.0/20 + - nodeName: "" + sliceRange: 10.251.0.0/20 + - nodeName: "" + sliceRange: 10.251.16.0/20 + - nodeName: "" + sliceRange: 10.251.32.0/20 + - nodeName: "" + sliceRange: 10.251.48.0/20 + - nodeName: "" + sliceRange: 10.251.64.0/20 + - nodeName: "" + sliceRange: 10.251.80.0/20 + - nodeName: "" + sliceRange: 10.251.96.0/20 + - nodeName: "" + sliceRange: 10.251.112.0/20 + - nodeName: "" + sliceRange: 10.251.128.0/20 + - nodeName: "" + sliceRange: 10.251.144.0/20 + - nodeName: "" + sliceRange: 10.251.160.0/20 + - nodeName: "" + sliceRange: 10.251.176.0/20 + - nodeName: "" + sliceRange: 10.251.192.0/20 + - nodeName: "" + sliceRange: 10.251.208.0/20 + - nodeName: "" + sliceRange: 10.251.224.0/20 + - nodeName: "" + sliceRange: 10.251.240.0/20 + - nodeName: "" + sliceRange: 10.252.0.0/20 + - nodeName: "" + sliceRange: 10.252.16.0/20 + - nodeName: "" + sliceRange: 10.252.32.0/20 + - nodeName: "" + sliceRange: 10.252.48.0/20 + - nodeName: "" + sliceRange: 10.252.64.0/20 + - nodeName: "" + sliceRange: 10.252.80.0/20 + - nodeName: "" + sliceRange: 10.252.96.0/20 + - nodeName: "" + sliceRange: 10.252.112.0/20 + - nodeName: "" + sliceRange: 10.252.128.0/20 + - nodeName: "" + sliceRange: 10.252.144.0/20 + - nodeName: "" + sliceRange: 10.252.160.0/20 + - nodeName: "" + sliceRange: 10.252.176.0/20 + - nodeName: "" + sliceRange: 10.252.192.0/20 + - nodeName: "" + sliceRange: 10.252.208.0/20 + - nodeName: "" + sliceRange: 10.252.224.0/20 + - nodeName: "" + sliceRange: 10.252.240.0/20 + - nodeName: "" + sliceRange: 10.253.0.0/20 + - nodeName: "" + sliceRange: 10.253.16.0/20 + - nodeName: "" + sliceRange: 10.253.32.0/20 + - nodeName: "" + sliceRange: 10.253.48.0/20 + - nodeName: "" + sliceRange: 10.253.64.0/20 + - nodeName: "" + sliceRange: 10.253.80.0/20 + - nodeName: "" + sliceRange: 10.253.96.0/20 + - nodeName: "" + sliceRange: 10.253.112.0/20 + - nodeName: "" + sliceRange: 10.253.128.0/20 + - nodeName: "" + sliceRange: 10.253.144.0/20 + - nodeName: "" + sliceRange: 10.253.160.0/20 + - nodeName: "" + sliceRange: 10.253.176.0/20 + - nodeName: "" + sliceRange: 10.253.192.0/20 + - nodeName: "" + sliceRange: 10.253.208.0/20 + - nodeName: "" + sliceRange: 10.253.224.0/20 + - nodeName: "" + sliceRange: 10.253.240.0/20 + - nodeName: "" + sliceRange: 10.254.0.0/20 + - nodeName: "" + sliceRange: 10.254.16.0/20 + - nodeName: "" + sliceRange: 10.254.32.0/20 + - nodeName: "" + sliceRange: 10.254.48.0/20 + - nodeName: "" + sliceRange: 10.254.64.0/20 + - nodeName: "" + sliceRange: 10.254.80.0/20 + - nodeName: "" + sliceRange: 10.254.96.0/20 + - nodeName: "" + sliceRange: 10.254.112.0/20 + - nodeName: "" + sliceRange: 10.254.128.0/20 + - nodeName: "" + sliceRange: 10.254.144.0/20 + - nodeName: "" + sliceRange: 10.254.160.0/20 + - nodeName: "" + sliceRange: 10.254.176.0/20 + - nodeName: "" + sliceRange: 10.254.192.0/20 + - nodeName: "" + sliceRange: 10.254.208.0/20 + - nodeName: "" + sliceRange: 10.254.224.0/20 + - nodeName: "" + sliceRange: 10.254.240.0/20 + - nodeName: "" + sliceRange: 10.255.0.0/20 + - nodeName: "" + sliceRange: 10.255.16.0/20 + - nodeName: "" + sliceRange: 10.255.32.0/20 + - nodeName: "" + sliceRange: 10.255.48.0/20 + - nodeName: "" + sliceRange: 10.255.64.0/20 + - nodeName: "" + sliceRange: 10.255.80.0/20 + - nodeName: "" + sliceRange: 10.255.96.0/20 + - nodeName: "" + sliceRange: 10.255.112.0/20 + - nodeName: "" + sliceRange: 10.255.128.0/20 + - nodeName: "" + sliceRange: 10.255.144.0/20 + - nodeName: "" + sliceRange: 10.255.160.0/20 + - nodeName: "" + sliceRange: 10.255.176.0/20 + - nodeName: "" + sliceRange: 10.255.192.0/20 + - nodeName: "" + sliceRange: 10.255.208.0/20 + - nodeName: "" + sliceRange: 10.255.224.0/20 + - nodeName: "" + sliceRange: 10.255.240.0/20