Skip to content

Commit

Permalink
Reconcile MTQ CR according to an HCO FeatureGate (#2473)
Browse files Browse the repository at this point in the history
If hco's .spec.featureGates.enableManagedTenantQuota=true, the MTQ CustomResource will be deployed in the installation namespace.
When the feature gate is changed to 'false', the CR is deleted.

Signed-off-by: Oren Cohen <[email protected]>
  • Loading branch information
orenc1 authored Aug 14, 2023
1 parent 10bb4f5 commit 998e0f9
Show file tree
Hide file tree
Showing 54 changed files with 2,090 additions and 41 deletions.
8 changes: 8 additions & 0 deletions api/v1beta1/hyperconverged_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,14 @@ type HyperConvergedFeatureGates struct {
// +kubebuilder:default=false
// +default=false
PersistentReservation *bool `json:"persistentReservation,omitempty"`

// Enable the Managed Tenant Quota operator (MTQ) on the cluster.
// MTQ streamlines the VirtualMachines migration process in namespaces where resource quotas are applied.
// Note: this feature is in Developer Preview.
// +optional
// +kubebuilder:default=false
// +default=false
EnableManagedTenantQuota *bool `json:"enableManagedTenantQuota,omitempty"`
}

// PermittedHostDevices holds information about devices allowed for passthrough
Expand Down
5 changes: 5 additions & 0 deletions api/v1beta1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions api/v1beta1/zz_generated.defaults.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions api/v1beta1/zz_generated.openapi.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions cmd/hyperconverged-cluster-operator/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ import (
hcoutil "github.com/kubevirt/hyperconverged-cluster-operator/pkg/util"
kubevirtcorev1 "kubevirt.io/api/core/v1"
cdiv1beta1 "kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1"
mtqv1alpha1 "kubevirt.io/managed-tenant-quota/staging/src/kubevirt.io/managed-tenant-quota-api/pkg/apis/core/v1alpha1"
sspv1beta2 "kubevirt.io/ssp-operator/api/v1beta2"
)

Expand Down Expand Up @@ -75,6 +76,7 @@ var (
coordinationv1.AddToScheme,
operatorsapiv2.AddToScheme,
imagev1.Install,
mtqv1alpha1.AddToScheme,
}
)

Expand Down Expand Up @@ -189,6 +191,7 @@ func getCacheOption(operatorNamespace string) cache.Options {
&cdiv1beta1.CDI{}: {},
&networkaddonsv1.NetworkAddonsConfig{}: {},
&sspv1beta2.SSP{}: {},
&mtqv1alpha1.MTQ{}: {},
&schedulingv1.PriorityClass{}: {
Label: labels.SelectorFromSet(labels.Set{hcoutil.AppLabel: hcoutil.HyperConvergedName}),
},
Expand Down
7 changes: 7 additions & 0 deletions config/crd/bases/hco.kubevirt.io_hyperconvergeds.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1097,6 +1097,13 @@ spec:
It is possible to use custom templates by adding them to the
dataImportCronTemplates field.'
type: boolean
enableManagedTenantQuota:
default: false
description: 'Enable the Managed Tenant Quota operator (MTQ) on
the cluster. MTQ streamlines the VirtualMachines migration process
in namespaces where resource quotas are applied. Note: this
feature is in Developer Preview.'
type: boolean
nonRoot:
default: true
description: "Enables rootless virt-launcher. \n Deprecated: please
Expand Down
3 changes: 3 additions & 0 deletions controllers/commontestutils/testUtils.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
"context"
"fmt"

mtqv1alpha1 "kubevirt.io/managed-tenant-quota/staging/src/kubevirt.io/managed-tenant-quota-api/pkg/apis/core/v1alpha1"

"github.com/go-logr/logr"
. "github.com/onsi/ginkgo/v2" //nolint dot-imports
. "github.com/onsi/gomega" //nolint dot-imports
Expand Down Expand Up @@ -159,6 +161,7 @@ func GetScheme() *runtime.Scheme {
consolev1.Install,
operatorv1.Install,
openshiftconfigv1.Install,
mtqv1alpha1.AddToScheme,
} {
Expect(f(testScheme)).ToNot(HaveOccurred())
}
Expand Down
2 changes: 2 additions & 0 deletions controllers/hyperconverged/hyperconverged_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ import (
"github.com/kubevirt/hyperconverged-cluster-operator/version"
kubevirtcorev1 "kubevirt.io/api/core/v1"
cdiv1beta1 "kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1"
mtqv1alpha1 "kubevirt.io/managed-tenant-quota/staging/src/kubevirt.io/managed-tenant-quota-api/pkg/apis/core/v1alpha1"
sspv1beta2 "kubevirt.io/ssp-operator/api/v1beta2"
)

Expand Down Expand Up @@ -179,6 +180,7 @@ func add(mgr manager.Manager, r reconcile.Reconciler, ci hcoutil.ClusterInfo) er
&kubevirtcorev1.KubeVirt{},
&cdiv1beta1.CDI{},
&networkaddonsv1.NetworkAddonsConfig{},
&mtqv1alpha1.MTQ{},
&schedulingv1.PriorityClass{},
&corev1.ConfigMap{},
&corev1.Service{},
Expand Down
87 changes: 86 additions & 1 deletion controllers/hyperconverged/hyperconverged_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,91 @@ var _ = Describe("HyperconvergedController", func() {
Expect(foundResource.Status.RelatedObjects).To(ContainElement(expectedRef))
})

It("should create all managed resources + MTQ", func() {

hco := commontestutils.NewHco()
hco.Spec.FeatureGates = hcov1beta1.HyperConvergedFeatureGates{
WithHostPassthroughCPU: pointer.Bool(true),
DeployTektonTaskResources: pointer.Bool(true),
EnableManagedTenantQuota: pointer.Bool(true),
}

cl := commontestutils.InitClient([]client.Object{hcoNamespace, hco})
monitoringReconciler := alerts.NewMonitoringReconciler(hcoutil.GetClusterInfo(), cl, commontestutils.NewEventEmitterMock(), commontestutils.GetScheme())

r := initReconciler(cl, nil)
r.monitoringReconciler = monitoringReconciler

// Do the reconcile
res, err := r.Reconcile(context.TODO(), request)
Expect(err).ToNot(HaveOccurred())
Expect(res).Should(Equal(reconcile.Result{Requeue: true}))
validateOperatorCondition(r, metav1.ConditionTrue, hcoutil.UpgradeableAllowReason, hcoutil.UpgradeableAllowMessage)

// Get the HCO
foundResource := &hcov1beta1.HyperConverged{}
Expect(
cl.Get(context.TODO(),
types.NamespacedName{Name: hco.Name, Namespace: hco.Namespace},
foundResource),
).ToNot(HaveOccurred())
// Check conditions
Expect(foundResource.Status.Conditions).To(ContainElement(commontestutils.RepresentCondition(metav1.Condition{
Type: hcov1beta1.ConditionReconcileComplete,
Status: metav1.ConditionUnknown,
Reason: reconcileInit,
Message: reconcileInitMessage,
})))
Expect(foundResource.Status.Conditions).To(ContainElement(commontestutils.RepresentCondition(metav1.Condition{
Type: hcov1beta1.ConditionAvailable,
Status: metav1.ConditionFalse,
Reason: reconcileInit,
Message: "Initializing HyperConverged cluster",
})))
Expect(foundResource.Status.Conditions).To(ContainElement(commontestutils.RepresentCondition(metav1.Condition{
Type: hcov1beta1.ConditionProgressing,
Status: metav1.ConditionTrue,
Reason: reconcileInit,
Message: "Initializing HyperConverged cluster",
})))
Expect(foundResource.Status.Conditions).To(ContainElement(commontestutils.RepresentCondition(metav1.Condition{
Type: hcov1beta1.ConditionDegraded,
Status: metav1.ConditionFalse,
Reason: reconcileInit,
Message: "Initializing HyperConverged cluster",
})))
Expect(foundResource.Status.Conditions).To(ContainElement(commontestutils.RepresentCondition(metav1.Condition{
Type: hcov1beta1.ConditionUpgradeable,
Status: metav1.ConditionUnknown,
Reason: reconcileInit,
Message: "Initializing HyperConverged cluster",
})))

verifySystemHealthStatusError(foundResource)

res, err = r.Reconcile(context.TODO(), request)
Expect(err).ToNot(HaveOccurred())
Expect(res).Should(Equal(reconcile.Result{Requeue: false}))
validateOperatorCondition(r, metav1.ConditionTrue, hcoutil.UpgradeableAllowReason, hcoutil.UpgradeableAllowMessage)

// Get the HCO
foundResource = &hcov1beta1.HyperConverged{}
Expect(
cl.Get(context.TODO(),
types.NamespacedName{Name: hco.Name, Namespace: hco.Namespace},
foundResource),
).ToNot(HaveOccurred())
// Check conditions
Expect(foundResource.Status.RelatedObjects).To(HaveLen(23))
expectedRef := corev1.ObjectReference{
Kind: "MTQ",
Name: "mtq-kubevirt-hyperconverged",
APIVersion: "mtq.kubevirt.io/v1alpha1",
ResourceVersion: "1",
}
Expect(foundResource.Status.RelatedObjects).To(ContainElement(expectedRef))
})

It("should find all managed resources", func() {

expected := getBasicDeployment()
Expand Down Expand Up @@ -1301,7 +1386,7 @@ var _ = Describe("HyperconvergedController", func() {
expected.ssp.Status.ObservedVersion = newComponentVersion

expected.hco.Status.Conditions = origConditions

_ = os.Setenv(hcoutil.MtqVersionEnvV, newComponentVersion)
})

It("Should update OperatorCondition Upgradeable to False", func() {
Expand Down
6 changes: 2 additions & 4 deletions controllers/operands/kubevirt.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,8 @@ import (
"strconv"
"strings"

"github.com/openshift/library-go/pkg/crypto"

openshiftconfigv1 "github.com/openshift/api/config/v1"

"github.com/openshift/library-go/pkg/crypto"
corev1 "k8s.io/api/core/v1"
schedulingv1 "k8s.io/api/scheduling/v1"
"k8s.io/apimachinery/pkg/api/resource"
Expand Down Expand Up @@ -800,7 +798,7 @@ func NewKubeVirtPriorityClass(hc *hcov1beta1.HyperConverged) *schedulingv1.Prior
Kind: "PriorityClass",
},
ObjectMeta: metav1.ObjectMeta{
Name: "kubevirt-cluster-critical",
Name: kvPriorityClass,
Labels: getLabels(hc, hcoutil.AppComponentCompute),
},
// 1 billion is the highest value we can set
Expand Down
2 changes: 1 addition & 1 deletion controllers/operands/kubevirtConsolePlugin.go
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ func getKvUIDeployment(hc *hcov1beta1.HyperConverged, deploymentName string, ima
},
},
},
PriorityClassName: "kubevirt-cluster-critical",
PriorityClassName: kvPriorityClass,
Volumes: []corev1.Volume{
{
Name: servingCertName,
Expand Down
6 changes: 3 additions & 3 deletions controllers/operands/kubevirt_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ var _ = Describe("KubeVirt Operand", func() {
Kind: "PriorityClass",
},
ObjectMeta: metav1.ObjectMeta{
Name: "kubevirt-cluster-critical",
Name: kvPriorityClass,
},
Value: 1,
GlobalDefault: false,
Expand All @@ -112,7 +112,7 @@ var _ = Describe("KubeVirt Operand", func() {
Kind: "PriorityClass",
},
ObjectMeta: metav1.ObjectMeta{
Name: "kubevirt-cluster-critical",
Name: kvPriorityClass,
},
Value: 1000000000,
GlobalDefault: true,
Expand Down Expand Up @@ -156,7 +156,7 @@ var _ = Describe("KubeVirt Operand", func() {
Entry("get error", func(testClient *commontestutils.HcoTestClient) error {
expectedError := fmt.Errorf("fake PriorityClass get error")
testClient.InitiateGetErrors(func(key client.ObjectKey) error {
if key.Name == "kubevirt-cluster-critical" {
if key.Name == kvPriorityClass {
return expectedError
}
return nil
Expand Down
Loading

0 comments on commit 998e0f9

Please sign in to comment.