From 32b4fbea01a50e5fe00ab0d59882bb80956e63f0 Mon Sep 17 00:00:00 2001 From: Martin Schuppert Date: Mon, 7 Aug 2023 18:16:57 +0200 Subject: [PATCH] Create nova route and svc endpoint overrides Creates the route for the nova components, also allows to customize the route via override. Generats the service override for the env with what is configured in the externalEndpoints, or specified in the service template override. Depends-On: https://github.com/openstack-k8s-operators/lib-common/pull/313 Depends-On: https://github.com/openstack-k8s-operators/keystone-operator/pull/289 Depends-On: https://github.com/openstack-k8s-operators/nova-operator/pull/489 Jira: OSP-26690 --- ....openstack.org_openstackcontrolplanes.yaml | 223 +++++++++++++++++- apis/core/v1beta1/conditions.go | 3 + .../v1beta1/openstackcontrolplane_types.go | 17 ++ apis/core/v1beta1/zz_generated.deepcopy.go | 24 ++ ....openstack.org_openstackcontrolplanes.yaml | 223 +++++++++++++++++- ...controlplane_galera_network_isolation.yaml | 34 ++- ...ne_galera_network_isolation_3replicas.yaml | 34 ++- ...enstackcontrolplane_network_isolation.yaml | 34 ++- ...ckcontrolplane_network_isolation_ceph.yaml | 34 ++- pkg/openstack/nova.go | 107 +++++++++ 10 files changed, 673 insertions(+), 60 deletions(-) diff --git a/apis/bases/core.openstack.org_openstackcontrolplanes.yaml b/apis/bases/core.openstack.org_openstackcontrolplanes.yaml index c7ebc50c8..9af57fe38 100644 --- a/apis/bases/core.openstack.org_openstackcontrolplanes.yaml +++ b/apis/bases/core.openstack.org_openstackcontrolplanes.yaml @@ -6762,6 +6762,213 @@ spec: type: object nova: properties: + apiOverride: + properties: + route: + properties: + metadata: + properties: + annotations: + additionalProperties: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + type: object + spec: + properties: + alternateBackends: + items: + properties: + kind: + enum: + - Service + - "" + type: string + name: + type: string + weight: + format: int32 + maximum: 256 + minimum: 0 + type: integer + type: object + maxItems: 3 + type: array + host: + maxLength: 253 + pattern: ^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])(\.([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9]))*$ + type: string + path: + pattern: ^/ + type: string + port: + properties: + targetPort: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - targetPort + type: object + subdomain: + maxLength: 253 + pattern: ^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])(\.([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9]))*$ + type: string + tls: + properties: + caCertificate: + type: string + certificate: + type: string + destinationCACertificate: + type: string + insecureEdgeTerminationPolicy: + type: string + key: + type: string + termination: + enum: + - edge + - reencrypt + - passthrough + type: string + required: + - termination + type: object + to: + properties: + kind: + enum: + - Service + - "" + type: string + name: + type: string + weight: + format: int32 + maximum: 256 + minimum: 0 + type: integer + type: object + wildcardPolicy: + enum: + - None + - Subdomain + - "" + type: string + type: object + type: object + type: object + cellOverride: + additionalProperties: + properties: + noVNCProxy: + properties: + route: + properties: + metadata: + properties: + annotations: + additionalProperties: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + type: object + spec: + properties: + alternateBackends: + items: + properties: + kind: + enum: + - Service + - "" + type: string + name: + type: string + weight: + format: int32 + maximum: 256 + minimum: 0 + type: integer + type: object + maxItems: 3 + type: array + host: + maxLength: 253 + pattern: ^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])(\.([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9]))*$ + type: string + path: + pattern: ^/ + type: string + port: + properties: + targetPort: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - targetPort + type: object + subdomain: + maxLength: 253 + pattern: ^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])(\.([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9]))*$ + type: string + tls: + properties: + caCertificate: + type: string + certificate: + type: string + destinationCACertificate: + type: string + insecureEdgeTerminationPolicy: + type: string + key: + type: string + termination: + enum: + - edge + - reencrypt + - passthrough + type: string + required: + - termination + type: object + to: + properties: + kind: + enum: + - Service + - "" + type: string + name: + type: string + weight: + format: int32 + maximum: 256 + minimum: 0 + type: integer + type: object + wildcardPolicy: + enum: + - None + - Subdomain + - "" + type: string + type: object + type: object + type: object + type: object + type: object enabled: default: true type: boolean @@ -6799,7 +7006,7 @@ spec: override: properties: service: - items: + additionalProperties: properties: endpointURL: type: string @@ -6845,7 +7052,7 @@ spec: type: string type: object type: object - type: array + type: object type: object replicas: default: 1 @@ -6979,7 +7186,7 @@ spec: override: properties: service: - items: + additionalProperties: properties: endpointURL: type: string @@ -7025,7 +7232,7 @@ spec: type: string type: object type: object - type: array + type: object type: object replicas: default: 1 @@ -7086,7 +7293,7 @@ spec: override: properties: service: - items: + additionalProperties: properties: endpointURL: type: string @@ -7132,7 +7339,7 @@ spec: type: string type: object type: object - type: array + type: object type: object replicas: default: 1 @@ -7236,7 +7443,7 @@ spec: override: properties: service: - items: + additionalProperties: properties: endpointURL: type: string @@ -7282,7 +7489,7 @@ spec: type: string type: object type: object - type: array + type: object type: object replicas: default: 1 diff --git a/apis/core/v1beta1/conditions.go b/apis/core/v1beta1/conditions.go index 4ee19903b..b252d731f 100644 --- a/apis/core/v1beta1/conditions.go +++ b/apis/core/v1beta1/conditions.go @@ -66,6 +66,9 @@ const ( // OpenStackControlPlaneNovaReadyCondition Status=True condition which indicates if Nova is configured and operational OpenStackControlPlaneNovaReadyCondition condition.Type = "OpenStackControlPlaneNovaReady" + // OpenStackControlPlaneExposeNovaReadyCondition Status=True condition which indicates if Nova is exposed via a route + OpenStackControlPlaneExposeNovaReadyCondition condition.Type = "OpenStackControlPlaneExposeNovaReady" + // OpenStackControlPlaneHeatReadyCondition Status=True condition which indicates if Heat is configured and operational OpenStackControlPlaneHeatReadyCondition condition.Type = "OpenStackControlPlaneHeatReady" diff --git a/apis/core/v1beta1/openstackcontrolplane_types.go b/apis/core/v1beta1/openstackcontrolplane_types.go index 0a5d01aef..9f4bc1573 100644 --- a/apis/core/v1beta1/openstackcontrolplane_types.go +++ b/apis/core/v1beta1/openstackcontrolplane_types.go @@ -428,6 +428,23 @@ type NovaSection struct { //+operator-sdk:csv:customresourcedefinitions:type=spec // Template - Overrides to use when creating the Nova services Template novav1.NovaSpec `json:"template,omitempty"` + + // +kubebuilder:validation:Optional + // +operator-sdk:csv:customresourcedefinitions:type=spec + // APIOverride, provides the ability to override the generated manifest of several child resources. + APIOverride Override `json:"apiOverride,omitempty"` + + // +kubebuilder:validation:Optional + // +operator-sdk:csv:customresourcedefinitions:type=spec + // CellOverride, provides the ability to override the generated manifest of several child resources + // for a nova cell. + CellOverride map[string]NovaCellOverrideSpec `json:"cellOverride,omitempty"` +} + +// NovaCellOverrideSpec to override the generated manifest of several child resources. +type NovaCellOverrideSpec struct { + // +kubebuilder:validation:Optional + NoVNCProxy Override `json:"noVNCProxy,omitempty"` } // HeatSection defines the desired state of Heat services diff --git a/apis/core/v1beta1/zz_generated.deepcopy.go b/apis/core/v1beta1/zz_generated.deepcopy.go index 061524fe9..74831e057 100644 --- a/apis/core/v1beta1/zz_generated.deepcopy.go +++ b/apis/core/v1beta1/zz_generated.deepcopy.go @@ -281,10 +281,34 @@ func (in *NeutronSection) DeepCopy() *NeutronSection { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *NovaCellOverrideSpec) DeepCopyInto(out *NovaCellOverrideSpec) { + *out = *in + in.NoVNCProxy.DeepCopyInto(&out.NoVNCProxy) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NovaCellOverrideSpec. +func (in *NovaCellOverrideSpec) DeepCopy() *NovaCellOverrideSpec { + if in == nil { + return nil + } + out := new(NovaCellOverrideSpec) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *NovaSection) DeepCopyInto(out *NovaSection) { *out = *in in.Template.DeepCopyInto(&out.Template) + in.APIOverride.DeepCopyInto(&out.APIOverride) + if in.CellOverride != nil { + in, out := &in.CellOverride, &out.CellOverride + *out = make(map[string]NovaCellOverrideSpec, len(*in)) + for key, val := range *in { + (*out)[key] = *val.DeepCopy() + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NovaSection. diff --git a/config/crd/bases/core.openstack.org_openstackcontrolplanes.yaml b/config/crd/bases/core.openstack.org_openstackcontrolplanes.yaml index c7ebc50c8..9af57fe38 100644 --- a/config/crd/bases/core.openstack.org_openstackcontrolplanes.yaml +++ b/config/crd/bases/core.openstack.org_openstackcontrolplanes.yaml @@ -6762,6 +6762,213 @@ spec: type: object nova: properties: + apiOverride: + properties: + route: + properties: + metadata: + properties: + annotations: + additionalProperties: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + type: object + spec: + properties: + alternateBackends: + items: + properties: + kind: + enum: + - Service + - "" + type: string + name: + type: string + weight: + format: int32 + maximum: 256 + minimum: 0 + type: integer + type: object + maxItems: 3 + type: array + host: + maxLength: 253 + pattern: ^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])(\.([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9]))*$ + type: string + path: + pattern: ^/ + type: string + port: + properties: + targetPort: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - targetPort + type: object + subdomain: + maxLength: 253 + pattern: ^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])(\.([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9]))*$ + type: string + tls: + properties: + caCertificate: + type: string + certificate: + type: string + destinationCACertificate: + type: string + insecureEdgeTerminationPolicy: + type: string + key: + type: string + termination: + enum: + - edge + - reencrypt + - passthrough + type: string + required: + - termination + type: object + to: + properties: + kind: + enum: + - Service + - "" + type: string + name: + type: string + weight: + format: int32 + maximum: 256 + minimum: 0 + type: integer + type: object + wildcardPolicy: + enum: + - None + - Subdomain + - "" + type: string + type: object + type: object + type: object + cellOverride: + additionalProperties: + properties: + noVNCProxy: + properties: + route: + properties: + metadata: + properties: + annotations: + additionalProperties: + type: string + type: object + labels: + additionalProperties: + type: string + type: object + type: object + spec: + properties: + alternateBackends: + items: + properties: + kind: + enum: + - Service + - "" + type: string + name: + type: string + weight: + format: int32 + maximum: 256 + minimum: 0 + type: integer + type: object + maxItems: 3 + type: array + host: + maxLength: 253 + pattern: ^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])(\.([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9]))*$ + type: string + path: + pattern: ^/ + type: string + port: + properties: + targetPort: + anyOf: + - type: integer + - type: string + x-kubernetes-int-or-string: true + required: + - targetPort + type: object + subdomain: + maxLength: 253 + pattern: ^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])(\.([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9]))*$ + type: string + tls: + properties: + caCertificate: + type: string + certificate: + type: string + destinationCACertificate: + type: string + insecureEdgeTerminationPolicy: + type: string + key: + type: string + termination: + enum: + - edge + - reencrypt + - passthrough + type: string + required: + - termination + type: object + to: + properties: + kind: + enum: + - Service + - "" + type: string + name: + type: string + weight: + format: int32 + maximum: 256 + minimum: 0 + type: integer + type: object + wildcardPolicy: + enum: + - None + - Subdomain + - "" + type: string + type: object + type: object + type: object + type: object + type: object enabled: default: true type: boolean @@ -6799,7 +7006,7 @@ spec: override: properties: service: - items: + additionalProperties: properties: endpointURL: type: string @@ -6845,7 +7052,7 @@ spec: type: string type: object type: object - type: array + type: object type: object replicas: default: 1 @@ -6979,7 +7186,7 @@ spec: override: properties: service: - items: + additionalProperties: properties: endpointURL: type: string @@ -7025,7 +7232,7 @@ spec: type: string type: object type: object - type: array + type: object type: object replicas: default: 1 @@ -7086,7 +7293,7 @@ spec: override: properties: service: - items: + additionalProperties: properties: endpointURL: type: string @@ -7132,7 +7339,7 @@ spec: type: string type: object type: object - type: array + type: object type: object replicas: default: 1 @@ -7236,7 +7443,7 @@ spec: override: properties: service: - items: + additionalProperties: properties: endpointURL: type: string @@ -7282,7 +7489,7 @@ spec: type: string type: object type: object - type: array + type: object type: object replicas: default: 1 diff --git a/config/samples/core_v1beta1_openstackcontrolplane_galera_network_isolation.yaml b/config/samples/core_v1beta1_openstackcontrolplane_galera_network_isolation.yaml index 349c0ffeb..99017cec8 100644 --- a/config/samples/core_v1beta1_openstackcontrolplane_galera_network_isolation.yaml +++ b/config/samples/core_v1beta1_openstackcontrolplane_galera_network_isolation.yaml @@ -127,20 +127,32 @@ spec: replicas: 1 secret: osp-secret nova: + apiOverride: + route: {} template: apiServiceTemplate: - externalEndpoints: - - endpoint: internal - ipAddressPool: internalapi - loadBalancerIPs: - - 172.17.0.80 - secret: osp-secret + override: + service: + internal: + metadata: + annotations: + metallb.universe.tf/address-pool: internalapi + metallb.universe.tf/allow-shared-ip: internalapi + metallb.universe.tf/loadBalancerIPs: 172.17.0.80 + spec: + type: LoadBalancer metadataServiceTemplate: - externalEndpoints: - - endpoint: internal - ipAddressPool: internalapi - loadBalancerIPs: - - 172.17.0.80 + override: + service: + internal: + metadata: + annotations: + metallb.universe.tf/address-pool: internalapi + metallb.universe.tf/allow-shared-ip: internalapi + metallb.universe.tf/loadBalancerIPs: 172.17.0.80 + spec: + type: LoadBalancer + secret: osp-secret manila: template: manilaAPI: diff --git a/config/samples/core_v1beta1_openstackcontrolplane_galera_network_isolation_3replicas.yaml b/config/samples/core_v1beta1_openstackcontrolplane_galera_network_isolation_3replicas.yaml index 96c18c213..2a6088491 100644 --- a/config/samples/core_v1beta1_openstackcontrolplane_galera_network_isolation_3replicas.yaml +++ b/config/samples/core_v1beta1_openstackcontrolplane_galera_network_isolation_3replicas.yaml @@ -127,20 +127,32 @@ spec: replicas: 1 secret: osp-secret nova: + apiOverride: + route: {} template: apiServiceTemplate: - externalEndpoints: - - endpoint: internal - ipAddressPool: internalapi - loadBalancerIPs: - - 172.17.0.80 - secret: osp-secret + override: + service: + internal: + metadata: + annotations: + metallb.universe.tf/address-pool: internalapi + metallb.universe.tf/allow-shared-ip: internalapi + metallb.universe.tf/loadBalancerIPs: 172.17.0.80 + spec: + type: LoadBalancer metadataServiceTemplate: - externalEndpoints: - - endpoint: internal - ipAddressPool: internalapi - loadBalancerIPs: - - 172.17.0.80 + override: + service: + internal: + metadata: + annotations: + metallb.universe.tf/address-pool: internalapi + metallb.universe.tf/allow-shared-ip: internalapi + metallb.universe.tf/loadBalancerIPs: 172.17.0.80 + spec: + type: LoadBalancer + secret: osp-secret manila: template: manilaAPI: diff --git a/config/samples/core_v1beta1_openstackcontrolplane_network_isolation.yaml b/config/samples/core_v1beta1_openstackcontrolplane_network_isolation.yaml index 2e1fc808b..bc3f6fc7e 100644 --- a/config/samples/core_v1beta1_openstackcontrolplane_network_isolation.yaml +++ b/config/samples/core_v1beta1_openstackcontrolplane_network_isolation.yaml @@ -115,20 +115,32 @@ spec: replicas: 1 secret: osp-secret nova: + apiOverride: + route: {} template: apiServiceTemplate: - externalEndpoints: - - endpoint: internal - ipAddressPool: internalapi - loadBalancerIPs: - - 172.17.0.80 - secret: osp-secret + override: + service: + internal: + metadata: + annotations: + metallb.universe.tf/address-pool: internalapi + metallb.universe.tf/allow-shared-ip: internalapi + metallb.universe.tf/loadBalancerIPs: 172.17.0.80 + spec: + type: LoadBalancer metadataServiceTemplate: - externalEndpoints: - - endpoint: internal - ipAddressPool: internalapi - loadBalancerIPs: - - 172.17.0.80 + override: + service: + internal: + metadata: + annotations: + metallb.universe.tf/address-pool: internalapi + metallb.universe.tf/allow-shared-ip: internalapi + metallb.universe.tf/loadBalancerIPs: 172.17.0.80 + spec: + type: LoadBalancer + secret: osp-secret manila: template: manilaAPI: diff --git a/config/samples/core_v1beta1_openstackcontrolplane_network_isolation_ceph.yaml b/config/samples/core_v1beta1_openstackcontrolplane_network_isolation_ceph.yaml index 9fe24e020..1b3b90d0c 100644 --- a/config/samples/core_v1beta1_openstackcontrolplane_network_isolation_ceph.yaml +++ b/config/samples/core_v1beta1_openstackcontrolplane_network_isolation_ceph.yaml @@ -159,20 +159,32 @@ spec: replicas: 1 secret: osp-secret nova: + apiOverride: + route: {} template: apiServiceTemplate: - externalEndpoints: - - endpoint: internal - ipAddressPool: internalapi - loadBalancerIPs: - - 172.17.0.80 - secret: osp-secret + override: + service: + internal: + metadata: + annotations: + metallb.universe.tf/address-pool: internalapi + metallb.universe.tf/allow-shared-ip: internalapi + metallb.universe.tf/loadBalancerIPs: 172.17.0.80 + spec: + type: LoadBalancer metadataServiceTemplate: - externalEndpoints: - - endpoint: internal - ipAddressPool: internalapi - loadBalancerIPs: - - 172.17.0.80 + override: + service: + internal: + metadata: + annotations: + metallb.universe.tf/address-pool: internalapi + metallb.universe.tf/allow-shared-ip: internalapi + metallb.universe.tf/loadBalancerIPs: 172.17.0.80 + spec: + type: LoadBalancer + secret: osp-secret manila: template: manilaAPI: diff --git a/pkg/openstack/nova.go b/pkg/openstack/nova.go index 6ff791b9d..3d89f09d5 100644 --- a/pkg/openstack/nova.go +++ b/pkg/openstack/nova.go @@ -20,14 +20,20 @@ import ( "context" "fmt" + "github.com/openstack-k8s-operators/lib-common/modules/common" "github.com/openstack-k8s-operators/lib-common/modules/common/condition" "github.com/openstack-k8s-operators/lib-common/modules/common/helper" + "github.com/openstack-k8s-operators/lib-common/modules/common/service" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" + "sigs.k8s.io/controller-runtime/pkg/reconcile" novav1 "github.com/openstack-k8s-operators/nova-operator/api/v1beta1" corev1beta1 "github.com/openstack-k8s-operators/openstack-operator/apis/core/v1beta1" + k8s_errors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + "k8s.io/utils/ptr" ctrl "sigs.k8s.io/controller-runtime" ) @@ -45,9 +51,110 @@ func ReconcileNova(ctx context.Context, instance *corev1beta1.OpenStackControlPl return res, err } instance.Status.Conditions.Remove(corev1beta1.OpenStackControlPlaneNovaReadyCondition) + instance.Status.Conditions.Remove(corev1beta1.OpenStackControlPlaneExposeNovaReadyCondition) return ctrl.Result{}, nil } + // add selector to service overrides + for _, endpointType := range []service.Endpoint{service.EndpointPublic, service.EndpointInternal} { + // NovaAPI + if instance.Spec.Nova.Template.APIServiceTemplate.Override.Service == nil { + instance.Spec.Nova.Template.APIServiceTemplate.Override.Service = map[string]service.OverrideSpec{} + } + instance.Spec.Nova.Template.APIServiceTemplate.Override.Service[string(endpointType)] = + AddServiceComponentLabel( + ptr.To(instance.Spec.Nova.Template.APIServiceTemplate.Override.Service[string(endpointType)]), + nova.Name+"-api") + + // cell NoVNCProxy service override + for cellName := range instance.Spec.Nova.Template.CellTemplates { + cellTemplate := instance.Spec.Nova.Template.CellTemplates[cellName] + if cellTemplate.NoVNCProxyServiceTemplate.Override.Service == nil { + cellTemplate.NoVNCProxyServiceTemplate.Override.Service = map[string]service.OverrideSpec{} + } + cellTemplate.NoVNCProxyServiceTemplate.Override.Service[string(endpointType)] = + AddServiceComponentLabel( + ptr.To(cellTemplate.NoVNCProxyServiceTemplate.Override.Service[string(endpointType)]), + nova.Name+"-"+cellName+"-novnc") + instance.Spec.Nova.Template.CellTemplates[cellName] = cellTemplate + } + } + + // When component services got created check if there is the need to create a route + if err := helper.GetClient().Get(ctx, types.NamespacedName{Name: "nova", Namespace: instance.Namespace}, nova); err != nil { + if !k8s_errors.IsNotFound(err) { + return ctrl.Result{}, err + } + } + + // Nova API + if nova.Status.Conditions.IsTrue(novav1.NovaAPIReadyCondition) { + svcs, err := service.GetServicesListWithLabel( + ctx, + helper, + instance.Namespace, + map[string]string{common.AppSelector: nova.Name + "-api"}, + ) + if err != nil { + return ctrl.Result{}, err + } + + var ctrlResult reconcile.Result + instance.Spec.Nova.Template.APIServiceTemplate.Override.Service, ctrlResult, err = EnsureRoute( + ctx, + instance, + helper, + nova, + svcs, + instance.Spec.Nova.Template.APIServiceTemplate.Override.Service, + instance.Spec.Nova.APIOverride.Route, + corev1beta1.OpenStackControlPlaneExposeNovaReadyCondition, + ) + if err != nil { + return ctrlResult, err + } else if (ctrlResult != ctrl.Result{}) { + return ctrlResult, nil + } + } + + if nova.Status.Conditions.IsTrue(novav1.NovaAllCellsDBReadyCondition) { + // cell NoVNCProxy + for cellName := range instance.Spec.Nova.Template.CellTemplates { + labelValue := nova.Name + "-" + cellName + "-novnc" + cellTemplate := instance.Spec.Nova.Template.CellTemplates[cellName] + + svcs, err := service.GetServicesListWithLabel( + ctx, + helper, + instance.Namespace, + map[string]string{common.AppSelector: labelValue}, + ) + if err != nil { + return ctrl.Result{}, err + } + + var ctrlResult reconcile.Result + cellTemplate.NoVNCProxyServiceTemplate.Override.Service, ctrlResult, err = EnsureRoute( + ctx, + instance, + helper, + nova, + svcs, + cellTemplate.NoVNCProxyServiceTemplate.Override.Service, + instance.Spec.Nova.CellOverride[cellName].NoVNCProxy.Route, + corev1beta1.OpenStackControlPlaneExposeNovaReadyCondition, + ) + if err != nil { + return ctrlResult, err + } else if (ctrlResult != ctrl.Result{}) { + return ctrlResult, nil + } + instance.Spec.Nova.Template.CellTemplates[cellName] = cellTemplate + + } + } + //instance.Status.Conditions.MarkTrue(corev1beta1.OpenStackControlPlaneServiceOverrideReadyCondition, corev1beta1.OpenStackControlPlaneServiceOverrideReadyMessage) + helper.GetLogger().Info("Reconciling Nova", "Nova.Namespace", instance.Namespace, "Nova.Name", nova.Name) op, err := controllerutil.CreateOrPatch(ctx, helper.GetClient(), nova, func() error { // 1)