in cns/multitenantcontroller/multitenantoperator/multitenantcrdreconciler.go [48:174]
func (r *multiTenantCrdReconciler) Reconcile(ctx context.Context, request reconcile.Request) (reconcile.Result, error) {
logger.Printf("Reconcling MultiTenantNetworkContainer %v", request.NamespacedName.String())
var nc ncapi.MultiTenantNetworkContainer
if err := r.KubeClient.Get(ctx, request.NamespacedName, &nc); err != nil {
if apierrors.IsNotFound(err) {
logger.Printf("MultiTenantNetworkContainer %s not found, skip reconciling", request.NamespacedName.String())
return ctrl.Result{}, nil
}
logger.Errorf("Failed to fetch network container %s: %v", request.NamespacedName.String(), err)
return ctrl.Result{}, err
}
if !nc.ObjectMeta.DeletionTimestamp.IsZero() {
// Do nothing if the NC has already in Terminated state.
if nc.Status.State == NCStateTerminated {
logger.Printf("MultiTenantNetworkContainer %s already terminated, skip reconciling", request.NamespacedName.String())
return ctrl.Result{}, nil
}
// Remove the deleted network container from CNS.
responseCode := r.CNSRestService.DeleteNetworkContainerInternal(cns.DeleteNetworkContainerRequest{
NetworkContainerid: nc.Spec.UUID,
})
err := restserver.ResponseCodeToError(responseCode)
if err != nil {
logger.Errorf("Failed to delete NC %s (UUID: %s) from CNS: %v", request.NamespacedName.String(), nc.Spec.UUID, err)
return ctrl.Result{}, err
}
// Update NC state to Terminated.
nc.Status.State = NCStateTerminated
if err := r.KubeClient.Status().Update(ctx, &nc); err != nil {
logger.Errorf("Failed to update network container state for %s (UUID: %s): %v", request.NamespacedName.String(), nc.Spec.UUID, err)
return ctrl.Result{}, err
}
logger.Printf("NC has been terminated for %s (UUID: %s)", request.NamespacedName.String(), nc.Spec.UUID)
return ctrl.Result{}, nil
}
// Do nothing if the network container hasn't been initialized yet from control plane.
if nc.Status.State != NCStateInitialized {
logger.Printf("MultiTenantNetworkContainer %s hasn't initialized yet, skip reconciling", request.NamespacedName.String())
return ctrl.Result{}, nil
}
// Parse KubernetesPodInfo as orchestratorContext.
podInfo := cns.KubernetesPodInfo{
PodName: nc.Name,
PodNamespace: nc.Namespace,
}
orchestratorContext, err := json.Marshal(podInfo)
if err != nil {
logger.Errorf("Failed to marshal podInfo (%v): %v", podInfo, err)
return ctrl.Result{}, err
}
// Check CNS NC states.
_, returnCode := r.CNSRestService.GetNetworkContainerInternal(cns.GetNetworkContainerRequest{
NetworkContainerid: nc.Spec.UUID,
OrchestratorContext: orchestratorContext,
})
err = restserver.ResponseCodeToError(returnCode)
if err == nil {
logger.Printf("NC %s (UUID: %s) has already been created in CNS", request.NamespacedName.String(), nc.Spec.UUID)
return ctrl.Result{}, nil
}
// return any error except UnknownContainerID
var cnsRESTErr *restserver.CNSRESTError
if !errors.As(err, &cnsRESTErr) || cnsRESTErr.ResponseCode != types.UnknownContainerID {
logger.Errorf("Failed to fetch NC %s (UUID: %s) from CNS: %v", request.NamespacedName.String(), nc.Spec.UUID, err)
return ctrl.Result{}, err
}
// Check that the MultiTenantInfo is set
if reflect.DeepEqual(ncapi.MultiTenantInfo{}, nc.Status.MultiTenantInfo) {
logger.Errorf("expected NC status multitenant info to not be empty for object %s", request.NamespacedName)
// There is no reason to requeue since we will reconcile this object when the multitenant info is added
return ctrl.Result{}, nil
}
// Persist NC states into CNS.
_, ipNet, err := net.ParseCIDR(nc.Status.IPSubnet)
if err != nil {
logger.Errorf("Failed to parse IPSubnet %s for NC %s: %v", nc.Status.IPSubnet, nc.Spec.UUID, err)
return ctrl.Result{}, err
}
prefixLength, _ := ipNet.Mask.Size()
networkContainerRequest := &cns.CreateNetworkContainerRequest{
NetworkContainerid: nc.Spec.UUID,
OrchestratorContext: orchestratorContext,
NetworkContainerType: cns.Kubernetes,
Version: "0",
IPConfiguration: cns.IPConfiguration{
IPSubnet: cns.IPSubnet{
IPAddress: nc.Status.IP,
PrefixLength: uint8(prefixLength),
},
GatewayIPAddress: nc.Status.Gateway,
},
PrimaryInterfaceIdentifier: nc.Status.PrimaryInterfaceIdentifier,
MultiTenancyInfo: cns.MultiTenancyInfo{
EncapType: nc.Status.MultiTenantInfo.EncapType,
ID: int(nc.Status.MultiTenantInfo.ID),
},
}
logger.Printf("CreateOrUpdateNC with networkContainerRequest: %#v", networkContainerRequest)
responseCode := r.CNSRestService.CreateOrUpdateNetworkContainerInternal(networkContainerRequest)
err = restserver.ResponseCodeToError(responseCode)
if err != nil {
logger.Errorf("Failed to persist state for NC %s (UUID: %s) to CNS: %v", request.NamespacedName.String(), nc.Spec.UUID, err)
return ctrl.Result{}, err
}
// Update NC state to Succeeded.
nc.Status.State = NCStateSucceeded
if err := r.KubeClient.Status().Update(ctx, &nc); err != nil {
logger.Errorf("Failed to update network container state for %s (UUID: %s): %v", request.NamespacedName.String(), nc.Spec.UUID, err)
return ctrl.Result{}, err
}
logger.Printf("Reconciled NC %s (UUID: %s)", request.NamespacedName.String(), nc.Spec.UUID)
return reconcile.Result{}, nil
}