diff --git a/config/crd/bases/airship.airshipit.org_vinoes.yaml b/config/crd/bases/airship.airshipit.org_vinoes.yaml
index 5fa782b..86fffb7 100644
--- a/config/crd/bases/airship.airshipit.org_vinoes.yaml
+++ b/config/crd/bases/airship.airshipit.org_vinoes.yaml
@@ -149,6 +149,15 @@ spec:
name:
description: Parameter for Node master or worker-standard
type: string
+ networkDataTemplate:
+ description: NetworkDataTemplate reference a Secret containing
+ a template key
+ properties:
+ name:
+ type: string
+ namespace:
+ type: string
+ type: object
networkInterfaces:
description: NetworkInterface define interface on the VM
properties:
diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml
index 85aefb1..1d3e7b7 100644
--- a/config/rbac/role.yaml
+++ b/config/rbac/role.yaml
@@ -21,6 +21,17 @@ rules:
verbs:
- list
- watch
+- apiGroups:
+ - ""
+ resources:
+ - secrets
+ verbs:
+ - create
+ - get
+ - list
+ - patch
+ - update
+ - watch
- apiGroups:
- airship.airshipit.org
resources:
diff --git a/config/samples/network-template-secret.yaml b/config/samples/network-template-secret.yaml
new file mode 100644
index 0000000..417573c
--- /dev/null
+++ b/config/samples/network-template-secret.yaml
@@ -0,0 +1,8 @@
+apiVersion: v1
+kind: Secret
+metadata:
+ name: test-template
+ namespace: default
+type: Opaque
+stringData:
+ template: REPLACEME
\ No newline at end of file
diff --git a/config/samples/vino_cr.yaml b/config/samples/vino_cr.yaml
index a138d35..ff61b1d 100644
--- a/config/samples/vino_cr.yaml
+++ b/config/samples/vino_cr.yaml
@@ -31,3 +31,7 @@ spec:
nodes:
- name: "worker"
count: 3
+ networkDataTemplate:
+ name: "test-template"
+ namespace: "default"
+
diff --git a/docs/api/vino.md b/docs/api/vino.md
index 9670c78..5a057cb 100644
--- a/docs/api/vino.md
+++ b/docs/api/vino.md
@@ -688,6 +688,19 @@ DiskDrivesTemplate
|
+
+
+networkDataTemplate
+
+
+NamespacedName
+
+
+ |
+
+ NetworkDataTemplate reference a Secret containing a template key
+ |
+
diff --git a/pkg/api/v1/vino_types.go b/pkg/api/v1/vino_types.go
index e5d4654..d8906d5 100644
--- a/pkg/api/v1/vino_types.go
+++ b/pkg/api/v1/vino_types.go
@@ -83,12 +83,14 @@ type VMRoutes struct {
//NodeSet node definitions
type NodeSet struct {
//Parameter for Node master or worker-standard
- Name string `json:"name,omitempty"`
- Count int `json:"count,omitempty"`
- NodeLabel *VMNodeFlavor `json:"labels,omitempty"`
- LibvirtTemplateDefinition NamespacedName `json:"libvirtTemplate,omitempty"`
- NetworkInterface *NetworkInterface `json:"networkInterfaces,omitempty"`
- DiskDrives *DiskDrivesTemplate `json:"diskDrives,omitempty"`
+ Name string `json:"name,omitempty"`
+ Count int `json:"count,omitempty"`
+ NodeLabel *VMNodeFlavor `json:"labels,omitempty"`
+ LibvirtTemplate NamespacedName `json:"libvirtTemplate,omitempty"`
+ NetworkInterface *NetworkInterface `json:"networkInterfaces,omitempty"`
+ DiskDrives *DiskDrivesTemplate `json:"diskDrives,omitempty"`
+ // NetworkDataTemplate reference a Secret containing a template key
+ NetworkDataTemplate NamespacedName `json:"networkDataTemplate,omitempty"`
}
// VMNodeFlavor labels for node to be annotated
diff --git a/pkg/api/v1/zz_generated.deepcopy.go b/pkg/api/v1/zz_generated.deepcopy.go
index 011f9f1..cd6f743 100644
--- a/pkg/api/v1/zz_generated.deepcopy.go
+++ b/pkg/api/v1/zz_generated.deepcopy.go
@@ -282,7 +282,7 @@ func (in *NodeSet) DeepCopyInto(out *NodeSet) {
*out = new(VMNodeFlavor)
(*in).DeepCopyInto(*out)
}
- out.LibvirtTemplateDefinition = in.LibvirtTemplateDefinition
+ out.LibvirtTemplate = in.LibvirtTemplate
if in.NetworkInterface != nil {
in, out := &in.NetworkInterface, &out.NetworkInterface
*out = new(NetworkInterface)
@@ -293,6 +293,7 @@ func (in *NodeSet) DeepCopyInto(out *NodeSet) {
*out = new(DiskDrivesTemplate)
(*in).DeepCopyInto(*out)
}
+ out.NetworkDataTemplate = in.NetworkDataTemplate
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NodeSet.
diff --git a/pkg/controllers/bmh.go b/pkg/controllers/bmh.go
index 716904c..087e84c 100644
--- a/pkg/controllers/bmh.go
+++ b/pkg/controllers/bmh.go
@@ -1,8 +1,26 @@
+/*
+
+
+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 controllers
import (
+ "bytes"
"context"
"fmt"
+ "text/template"
"github.com/go-logr/logr"
metal3 "github.com/metal3-io/baremetal-operator/apis/metal3.io/v1alpha1"
@@ -97,7 +115,7 @@ func (r *VinoReconciler) createBMHperPod(ctx context.Context, vino *vinov1.Vino,
return err
}
- netData, netDataNs, err := r.reconcileBMHNetworkData(ctx, vino)
+ netData, netDataNs, err := r.reconcileBMHNetworkData(ctx, node, vino, nil)
if err != nil {
return err
}
@@ -168,8 +186,62 @@ func (r *VinoReconciler) reconcileBMHCredentials(ctx context.Context, vino *vino
return "credentials", nil
}
-//nolint:unparam
-func (r *VinoReconciler) reconcileBMHNetworkData(_ context.Context, vino *vinov1.Vino) (string, string, error) {
- // TODO implement this
- return "network-data", getRuntimeNamespace(), nil
+func (r *VinoReconciler) reconcileBMHNetworkData(
+ ctx context.Context,
+ node vinov1.NodeSet,
+ vino *vinov1.Vino,
+ values interface{}) (string, string, error) {
+ secret := &corev1.Secret{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: node.NetworkDataTemplate.Name,
+ Namespace: node.NetworkDataTemplate.Namespace,
+ },
+ }
+
+ logger := logr.FromContext(ctx).WithValues("vino node", node.Name, "vino", client.ObjectKeyFromObject(vino))
+
+ objKey := client.ObjectKeyFromObject(secret)
+ logger.Info("Looking for secret with network template for vino node", "secret", objKey)
+ if err := r.Get(ctx, objKey, secret); err != nil {
+ return "", "", err
+ }
+
+ rawTmpl, ok := secret.Data[TemplateDefaultKey]
+ if !ok {
+ return "", "", fmt.Errorf("network template secret %v has no key '%s'", objKey, TemplateDefaultKey)
+ }
+
+ tpl, err := template.New("net-template").Parse(string(rawTmpl))
+ if err != nil {
+ return "", "", err
+ }
+
+ buf := bytes.NewBuffer([]byte{})
+ err = tpl.Execute(buf, values)
+ if err != nil {
+ return "", "", err
+ }
+
+ name := fmt.Sprintf("%s-%s-%s", vino.Namespace, vino.Name, node.Name)
+
+ ns := getRuntimeNamespace()
+ netSecret := &corev1.Secret{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: name,
+ Namespace: ns,
+ },
+ StringData: map[string]string{
+ "networkData": buf.String(),
+ },
+ Type: corev1.SecretTypeOpaque,
+ }
+
+ objKey = client.ObjectKeyFromObject(netSecret)
+
+ logger.Info("Creating network secret for vino node", "secret", objKey)
+
+ if err := applyRuntimeObject(ctx, objKey, netSecret, r.Client); err != nil {
+ return "", "", err
+ }
+ return name, ns, nil
}
diff --git a/pkg/controllers/bmh_test.go b/pkg/controllers/bmh_test.go
index e5c3177..f62339c 100644
--- a/pkg/controllers/bmh_test.go
+++ b/pkg/controllers/bmh_test.go
@@ -1,3 +1,19 @@
+/*
+
+
+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 controllers
import (
@@ -28,6 +44,10 @@ var _ = Describe("Test BMH reconciliation", func() {
{
Name: "worker",
Count: 3,
+ NetworkDataTemplate: vinov1.NamespacedName{
+ Name: "default-template",
+ Namespace: "default",
+ },
},
}
@@ -63,6 +83,17 @@ var _ = Describe("Test BMH reconciliation", func() {
},
}
+ networkTmplSecret := &corev1.Secret{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: "default-template",
+ Namespace: "default",
+ },
+ Type: corev1.SecretTypeOpaque,
+ Data: map[string][]byte{
+ TemplateDefaultKey: []byte("REPLACEME"),
+ },
+ }
+
node1 := &corev1.Node{
ObjectMeta: metav1.ObjectMeta{
Name: "node01",
@@ -92,7 +123,7 @@ var _ = Describe("Test BMH reconciliation", func() {
fake.NewClientBuilder()
reconciler := &VinoReconciler{
- Client: fake.NewFakeClient(podList, node1, node2, vino),
+ Client: fake.NewFakeClient(podList, node1, node2, vino, networkTmplSecret),
}
l := zap.New(zap.UseDevMode(true))
@@ -107,8 +138,18 @@ var _ = Describe("Test BMH reconciliation", func() {
Namespace: "vino-system",
},
}
+
+ networkSecret := &corev1.Secret{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: "default-vino-worker",
+ Namespace: "vino-system",
+ },
+ }
+
Expect(reconciler.Get(ctx, client.ObjectKeyFromObject(bmh), bmh)).Should(Succeed())
Expect(bmh.Spec.BMC.Address).To(Equal("redfish+http://10.0.0.2:8000/redfish/v1/Systems/worker-1"))
+ Expect(reconciler.Get(ctx, client.ObjectKeyFromObject(networkSecret), networkSecret)).Should(Succeed())
+ Expect(networkSecret.StringData["networkData"]).To(Equal("REPLACEME"))
})
})
})
diff --git a/pkg/controllers/vino_controller.go b/pkg/controllers/vino_controller.go
index e8dab35..4442b0e 100644
--- a/pkg/controllers/vino_controller.go
+++ b/pkg/controllers/vino_controller.go
@@ -42,164 +42,11 @@ import (
)
const (
- DaemonSetTemplateDefaultDataKey = "template"
- DaemonSetTemplateDefaultName = "vino-daemonset-template"
+ TemplateDefaultKey = "template"
+ DaemonSetTemplateDefaultName = "vino-daemonset-template"
ContainerNameLibvirt = "libvirt"
ConfigMapKeyVinoSpec = "vino-spec"
-
- // TODO (alexanderhughes) Enable this section of code when ready to integrate the BMH creation
-// sushyDataContent = `
-//{
-// "username": "foo",
-// "password": "bar",
-//}`
-//
-// networkDataContent = `
-//{
-// "links": [
-// {
-// "id": "eno4",
-// "name": "eno4",
-// "type": "phy",
-// "mtu": 1500
-// },
-// {
-// "id": "enp59s0f1",
-// "name": "enp59s0f1",
-// "type": "phy",
-// "mtu": 9100
-// },
-// {
-// "id": "enp216s0f0",
-// "name": "enp216s0f0",
-// "type": "phy",
-// "mtu": 9100
-// },
-// {
-// "id": "bond0",
-// "name": "bond0",
-// "type": "bond",
-// "bond_links": [
-// "enp59s0f1",
-// "enp216s0f0"
-// ],
-// "bond_mode": "802.3ad",
-// "bond_xmit_hash_policy": "layer3+4",
-// "bond_miimon": 100,
-// "mtu": 9100
-// },
-// {
-// "id": "bond0.41",
-// "name": "bond0.41",
-// "type": "vlan",
-// "vlan_link": "bond0",
-// "vlan_id": 41,
-// "mtu": 9100,
-// "vlan_mac_address": null
-// },
-// {
-// "id": "bond0.42",
-// "name": "bond0.42",
-// "type": "vlan",
-// "vlan_link": "bond0",
-// "vlan_id": 42,
-// "mtu": 9100,
-// "vlan_mac_address": null
-// },
-// {
-// "id": "bond0.44",
-// "name": "bond0.44",
-// "type": "vlan",
-// "vlan_link": "bond0",
-// "vlan_id": 44,
-// "mtu": 9100,
-// "vlan_mac_address": null
-// },
-// {
-// "id": "bond0.45",
-// "name": "bond0.45",
-// "type": "vlan",
-// "vlan_link": "bond0",
-// "vlan_id": 45,
-// "mtu": 9100,
-// "vlan_mac_address": null
-// }
-// ],
-// "networks": [
-// {
-// "id": "oam-ipv6",
-// "type": "ipv6",
-// "link": "bond0.41",
-// "ip_address": "2001:1890:1001:293d::139",
-// "routes": [
-// {
-// "network": "::/0",
-// "netmask": "::/0",
-// "gateway": "2001:1890:1001:293d::1"
-// }
-// ]
-// },
-// {
-// "id": "oam-ipv4",
-// "type": "ipv4",
-// "link": "bond0.41",
-// "ip_address": "32.68.51.139",
-// "netmask": "255.255.255.128",
-// "dns_nameservers": [
-// "135.188.34.124",
-// "135.38.244.16",
-// "135.188.34.84"
-// ],
-// "routes": [
-// {
-// "network": "0.0.0.0",
-// "netmask": "0.0.0.0",
-// "gateway": "32.68.51.129"
-// }
-// ]
-// },
-// {
-// "id": "pxe-ipv6",
-// "link": "eno4",
-// "type": "ipv6",
-// "ip_address": "fd00:900:100:138::11"
-// },
-// {
-// "id": "pxe-ipv4",
-// "link": "eno4",
-// "type": "ipv4",
-// "ip_address": "172.30.0.11",
-// "netmask": "255.255.255.128"
-// },
-// {
-// "id": "storage-ipv6",
-// "link": "bond0.42",
-// "type": "ipv6",
-// "ip_address": "fd00:900:100:139::15"
-// },
-// {
-// "id": "storage-ipv4",
-// "link": "bond0.42",
-// "type": "ipv4",
-// "ip_address": "172.31.1.15",
-// "netmask": "255.255.255.128"
-// },
-// {
-// "id": "ksn-ipv6",
-// "link": "bond0.44",
-// "type": "ipv6",
-// "ip_address": "fd00:900:100:13a::11"
-// },
-// {
-// "id": "ksn-ipv4",
-// "link": "bond0.44",
-// "type": "ipv4",
-// "ip_address": "172.29.0.11",
-// "netmask": "255.255.255.128"
-// }
-// ]
-//}`
)
// VinoReconciler reconciles a Vino object
@@ -212,6 +59,7 @@ type VinoReconciler struct {
// +kubebuilder:rbac:groups=airship.airshipit.org,resources=vinoes/status,verbs=get;update;patch
// +kubebuilder:rbac:groups="",resources=pods,verbs=list;watch
// +kubebuilder:rbac:groups="",resources=nodes,verbs=get;list;watch
+// +kubebuilder:rbac:groups="",resources=secrets,verbs=get;list;watch;create;update;patch
func (r *VinoReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
logger := logr.FromContext(ctx)
@@ -615,10 +463,10 @@ func (r *VinoReconciler) daemonSet(ctx context.Context, vino *vinov1.Vino) (*app
return nil, err
}
- template, exist := cm.Data[DaemonSetTemplateDefaultDataKey]
+ template, exist := cm.Data[TemplateDefaultKey]
if !exist {
- logger.Info("malformed template provided data doesn't have key " + DaemonSetTemplateDefaultDataKey)
- return nil, fmt.Errorf("malformed template provided data doesn't have key " + DaemonSetTemplateDefaultDataKey)
+ logger.Info("malformed template provided data doesn't have key " + TemplateDefaultKey)
+ return nil, fmt.Errorf("malformed template provided data doesn't have key " + TemplateDefaultKey)
}
ds := &appsv1.DaemonSet{}
diff --git a/tools/deployment/test-cr.sh b/tools/deployment/test-cr.sh
index 2341785..588333f 100755
--- a/tools/deployment/test-cr.sh
+++ b/tools/deployment/test-cr.sh
@@ -14,6 +14,7 @@ function vinoDebugInfo () {
kubectl apply -f config/samples/vino_cr.yaml
kubectl apply -f config/samples/ippool.yaml
+kubectl apply -f config/samples/network-template-secret.yaml
# Remove logs collection from here, when we will have zuul collect logs job
until [[ $(kubectl get vino vino-test-cr 2>/dev/null) ]]; do
@@ -43,9 +44,10 @@ if ! kubectl -n vino-system rollout status ds default-vino-test-cr --timeout=10s
vinoDebugInfo
fi
-
bmhCount=$(kubectl get baremetalhosts -n vino-system -o name | wc -l)
# with this setup set up, exactly 3 BMHs must have been created by VINO controller
[[ "$bmhCount" -eq "3" ]]
+
+kubectl get secret -o yaml -n vino-system default-vino-test-cr-worker