@@ -115,6 +115,7 @@ type DesignateReconciler struct {
115115// +kubebuilder:rbac:groups=keystone.openstack.org,resources=keystoneapis,verbs=get;list;watch
116116// +kubebuilder:rbac:groups=rabbitmq.openstack.org,resources=transporturls,verbs=get;list;watch;create;update;patch;delete
117117// +kubebuilder:rbac:groups=k8s.cni.cncf.io,resources=network-attachment-definitions,verbs=get;list;watch
118+ // +kubebuilder:rbac:groups="",resources=nodes,verbs=get;list
118119
119120// service account, role, rolebinding
120121// +kubebuilder:rbac:groups="",resources=serviceaccounts,verbs=get;list;watch;create;update;patch
@@ -713,6 +714,112 @@ func (r *DesignateReconciler) reconcileNormal(ctx context.Context, instance *des
713714 }
714715 Log .Info ("Deployment API task reconciled" )
715716
717+ nad , err := nad .GetNADWithName (ctx , helper , instance .Spec .DesignateNetworkAttachment , instance .Namespace )
718+ if err != nil {
719+ return ctrl.Result {}, err
720+ }
721+
722+ networkParameters , err := designate .GetNetworkParametersFromNAD (nad )
723+ if err != nil {
724+ return ctrl.Result {}, err
725+ }
726+
727+ nodeConfigMap := & corev1.ConfigMap {
728+ ObjectMeta : metav1.ObjectMeta {
729+ Name : designate .MdnsPredIPConfigMap ,
730+ Namespace : instance .GetNamespace (),
731+ Labels : labels .GetLabels (instance , labels .GetGroupLabel (instance .ObjectMeta .Name ), map [string ]string {}),
732+ },
733+ Data : make (map [string ]string ),
734+ }
735+
736+ // Look for existing config map and if exists, read existing data and match
737+ // against nodes.
738+ foundMap := & corev1.ConfigMap {}
739+ err = helper .GetClient ().Get (ctx , types.NamespacedName {Name : designate .MdnsPredIPConfigMap , Namespace : instance .GetNamespace ()},
740+ foundMap )
741+ if err != nil {
742+ if k8s_errors .IsNotFound (err ) {
743+ Log .Info (fmt .Sprintf ("Ip map %s doesn't exist, creating." , designate .MdnsPredIPConfigMap ))
744+ } else {
745+ return ctrl.Result {}, err
746+ }
747+ } else {
748+ Log .Info ("Retrieved existing map, updating.." )
749+ nodeConfigMap .Data = foundMap .Data
750+ }
751+
752+ //
753+ // Predictable IPs.
754+ //
755+ // NOTE(oschwart): refactoring this might be nice. This could also be
756+ // optimized but the data sets are small (nodes an IP ranges are less than
757+ // 100) so optimization might be a waste.
758+ //
759+ predictableIPParams , err := designate .GetPredictableIPAM (networkParameters )
760+ if err != nil {
761+ return ctrl.Result {}, err
762+ }
763+ // Get a list of the nodes in the cluster
764+
765+ // TODO(oschwart):
766+ // * confirm whether or not this lists only the nodes we want (i.e. ones
767+ // that will host the daemonset)
768+ // * do we want to provide a mechanism to temporarily disabling this list
769+ // for maintenance windows where nodes might be "coming and going"
770+
771+ nodes , err := helper .GetKClient ().CoreV1 ().Nodes ().List (ctx , metav1.ListOptions {})
772+ if err != nil {
773+ return ctrl.Result {}, err
774+ }
775+ updatedMap := make (map [string ]string )
776+ allocatedIPs := make (map [string ]bool )
777+ var predictableIPsRequired []string
778+
779+ // First scan existing allocations so we can keep existing allocations.
780+ // Keeping track of what's required and what already exists. If a node is
781+ // removed from the cluster, it's IPs will not be added to the allocated
782+ // list and are effectively recycled.
783+ for _ , node := range nodes .Items {
784+ nodeName := fmt .Sprintf ("mdns_%s" , node .Name )
785+ if ipValue , ok := nodeConfigMap .Data [nodeName ]; ok {
786+ updatedMap [nodeName ] = ipValue
787+ allocatedIPs [ipValue ] = true
788+ Log .Info (fmt .Sprintf ("%s has IP mapping %s: %s" , node .Name , nodeName , ipValue ))
789+ } else {
790+ predictableIPsRequired = append (predictableIPsRequired , nodeName )
791+ }
792+ }
793+ // Get new IPs using the range from predictableIPParmas minus the
794+ // allocatedIPs captured above.
795+ Log .Info (fmt .Sprintf ("Allocating %d predictable IPs" , len (predictableIPsRequired )))
796+ for _ , nodeName := range predictableIPsRequired {
797+ nodeIP , err := designate .GetNextIP (predictableIPParams , allocatedIPs )
798+ if err != nil {
799+ // An error here is really unexpected- it means either we have
800+ // messed up the allocatedIPs list or the range we are assuming is
801+ // too small for the number of mdns pod.
802+ return ctrl.Result {}, err
803+ }
804+ updatedMap [nodeName ] = nodeIP
805+ }
806+
807+ mapLabels := labels .GetLabels (instance , labels .GetGroupLabel (instance .ObjectMeta .Name ), map [string ]string {})
808+ _ , err = controllerutil .CreateOrPatch (ctx , helper .GetClient (), nodeConfigMap , func () error {
809+ nodeConfigMap .Labels = util .MergeStringMaps (nodeConfigMap .Labels , mapLabels )
810+ nodeConfigMap .Data = updatedMap
811+ err := controllerutil .SetControllerReference (instance , nodeConfigMap , helper .GetScheme ())
812+ if err != nil {
813+ return err
814+ }
815+ return nil
816+ })
817+
818+ if err != nil {
819+ Log .Info ("Unable to create config map for mdns ips..." )
820+ return ctrl.Result {}, err
821+ }
822+
716823 // deploy designate-central
717824 designateCentral , op , err := r .centralDeploymentCreateOrUpdate (ctx , instance )
718825 if err != nil {
0 commit comments