Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions images/virtualization-artifact/Taskfile.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ includes:
api:
taskfile: ../../api/Taskfile.dist.yaml
dir: ../../api
config:
taskfile: pkg/config/apis/Taskfile.yaml
dir: pkg/config/apis

vars:
BaseNamespace: d8-virtualization
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
/*
Copyright 2025 Flant JSC

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 app

import (
"fmt"
"runtime"

"github.com/spf13/cobra"
"github.com/spf13/pflag"
apiruntime "k8s.io/apimachinery/pkg/runtime"
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/client/config"
"sigs.k8s.io/controller-runtime/pkg/manager"
metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server"

deckhouselog "github.com/deckhouse/deckhouse/pkg/log"
virtualizationconfig "github.com/deckhouse/virtualization-controller/pkg/config"
"github.com/deckhouse/virtualization-controller/pkg/controller/indexer"
mc "github.com/deckhouse/virtualization-controller/pkg/controller/moduleconfig"
"github.com/deckhouse/virtualization-controller/pkg/logger"
"github.com/deckhouse/virtualization-controller/pkg/migration"
"github.com/deckhouse/virtualization-controller/pkg/version"
"github.com/deckhouse/virtualization/api/client/kubeclient"
)

func NewVirtualizationControllerCommand() *cobra.Command {
opts := &options{}
cmd := &cobra.Command{
Use: "virtualization-controller",
Short: "virtualization-controller",
Long: "virtualization-controller",
Args: cobra.NoArgs,
SilenceErrors: true,
SilenceUsage: true,
RunE: opts.Run,
}

opts.AddFlags(cmd.Flags())
return cmd
}

type options struct {
Config string
PprofBindAddr string
MetricsBindAddr string
LogLevel string
LogOutput string
LogFormat string
LogDebugControllerList []string
LogDebugVerbosity int
LeaderElection bool
}

func (o *options) AddFlags(fs *pflag.FlagSet) {
fs.StringVar(&o.Config, "config", "/etc/virtualization-controller/config.yaml", "path to config file")
fs.StringVar(&o.PprofBindAddr, "pprof-bind-address", "", "enable pprof")
fs.StringVar(&o.MetricsBindAddr, "metrics-bind-address", "8080", "metric bind address")
fs.StringVar(&o.LogLevel, "log-level", "info", "log level")
fs.StringVar(&o.LogOutput, "log-output", "", "log output")
fs.StringVar(&o.LogFormat, "log-format", "json", "log format")
fs.StringSliceVar(&o.LogDebugControllerList, "log-debug-controller-list", nil, "log debug controller list")
fs.IntVar(&o.LogDebugVerbosity, "log-debug-verbosity", 0, "log debug verbosity")
fs.BoolVar(&o.LeaderElection, "leader-election", true, "enable leader election")
}

func (o *options) Run(cmd *cobra.Command, _ []string) error {
log := logger.NewLogger(o.LogLevel, o.LogOutput, o.LogDebugVerbosity)
logger.SetDefaultLogger(log)

printVersion(log)

configuration, err := virtualizationconfig.Load(o.Config)
if err != nil {
return err
}

cfg, err := config.GetConfig()
if err != nil {
return fmt.Errorf("failed to get config: %w", err)
}

// Override content type to JSON so proxy can rewrite payloads.
cfg.ContentType = apiruntime.ContentTypeJSON
cfg.NegotiatedSerializer = clientgoscheme.Codecs.WithoutConversion()

scheme, err := newScheme()
if err != nil {
return err
}

managerOpts := manager.Options{
LeaderElection: o.LeaderElection,
LeaderElectionNamespace: configuration.Spec.Namespace,
LeaderElectionID: "d8-virtualization-controller",
LeaderElectionResourceLock: "leases",
Scheme: scheme,
Metrics: metricsserver.Options{
BindAddress: o.MetricsBindAddr,
},
PprofBindAddress: o.PprofBindAddr,
}

mgr, err := manager.New(cfg, managerOpts)
if err != nil {
return fmt.Errorf("failed to create manager: %w", err)
}

virtualizationClient, err := kubeclient.GetClientFromRESTConfig(cfg)
if err != nil {
return fmt.Errorf("failed to create virtualization kubeclient: %w", err)
}

log.Info("Registering Components.")
onlyMigrationClient, err := client.New(cfg, client.Options{Scheme: scheme})
if err != nil {
return fmt.Errorf("failed to create onlyMigrationClient: %w", err)
}

mCtrl, err := migration.NewController(onlyMigrationClient, log)
if err != nil {
return fmt.Errorf("failed to create migration controller: %w", err)
}
ctx := cmd.Context()
mCtrl.Run(ctx)

if err = indexer.IndexALL(ctx, mgr); err != nil {
return fmt.Errorf("failed to index all resources: %w", err)
}

for controllerName, setupController := range controllers {
loggerForController := logger.NewControllerLogger(controllerName, o.LogLevel, o.LogOutput, o.LogDebugVerbosity, o.LogDebugControllerList)
err = setupController(ctx, mgr, loggerForController, configuration.DeepCopy(), virtualizationClient)
if err != nil {
return fmt.Errorf("failed to setup %s controller: %w", controllerName, err)
}
}

if err = mc.SetupWebhookWithManager(mgr); err != nil {
return fmt.Errorf("failed to setup module config webhook: %w", err)
}

log.Info("Starting the Manager.")

if err = mgr.Start(ctx); err != nil {
return fmt.Errorf("manager exired non-zero: %w", err)
}
return nil
}

func printVersion(log *deckhouselog.Logger) {
log.Info(fmt.Sprintf("Go Version: %s", runtime.Version()))
log.Info(fmt.Sprintf("Go OS/Arch: %s/%s", runtime.GOOS, runtime.GOARCH))
log.Info(fmt.Sprintf("Edition: %s", version.GetEdition()))
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
/*
Copyright 2025 Flant JSC

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 app

import (
"context"

"sigs.k8s.io/controller-runtime/pkg/manager"

"github.com/deckhouse/deckhouse/pkg/log"
"github.com/deckhouse/virtualization-controller/pkg/config"
"github.com/deckhouse/virtualization-controller/pkg/config/apis/componentconfig"
"github.com/deckhouse/virtualization-controller/pkg/controller/cvi"
"github.com/deckhouse/virtualization-controller/pkg/controller/evacuation"
"github.com/deckhouse/virtualization-controller/pkg/controller/livemigration"
"github.com/deckhouse/virtualization-controller/pkg/controller/vd"
"github.com/deckhouse/virtualization-controller/pkg/controller/vdsnapshot"
"github.com/deckhouse/virtualization-controller/pkg/controller/vi"
"github.com/deckhouse/virtualization-controller/pkg/controller/vm"
"github.com/deckhouse/virtualization-controller/pkg/controller/vmbda"
"github.com/deckhouse/virtualization-controller/pkg/controller/vmclass"
"github.com/deckhouse/virtualization-controller/pkg/controller/vmip"
"github.com/deckhouse/virtualization-controller/pkg/controller/vmiplease"
"github.com/deckhouse/virtualization-controller/pkg/controller/vmop"
"github.com/deckhouse/virtualization-controller/pkg/controller/vmrestore"
"github.com/deckhouse/virtualization-controller/pkg/controller/vmsnapshot"
workloadupdater "github.com/deckhouse/virtualization-controller/pkg/controller/workload-updater"
"github.com/deckhouse/virtualization/api/client/kubeclient"
)

var controllers = map[string]func(
ctx context.Context,
mgr manager.Manager,
log *log.Logger,
configuration *componentconfig.VirtualizationControllerConfiguration,
virtualizationClient kubeclient.Client,
) error{
cvi.ControllerName: func(ctx context.Context, mgr manager.Manager, log *log.Logger, configuration *componentconfig.VirtualizationControllerConfiguration, _ kubeclient.Client) error {
_, err := cvi.NewController(ctx,
mgr,
log,
configuration.Spec.ImportSettings.ImporterImage,
configuration.Spec.ImportSettings.UploaderImage,
configuration.Spec.ImportSettings.Requirements,
config.ToLegacyDVCR(configuration),
configuration.Spec.Namespace)
return err
},
vd.ControllerName: func(ctx context.Context, mgr manager.Manager, log *log.Logger, configuration *componentconfig.VirtualizationControllerConfiguration, _ kubeclient.Client) error {
_, err := vd.NewController(
ctx,
mgr,
log,
configuration.Spec.ImportSettings.ImporterImage,
configuration.Spec.ImportSettings.UploaderImage,
configuration.Spec.ImportSettings.Requirements,
config.ToLegacyDVCR(configuration),
config.ToLegacyVirtualDiskStorageClassSettings(configuration))
return err
},
vi.ControllerName: func(ctx context.Context, mgr manager.Manager, log *log.Logger, configuration *componentconfig.VirtualizationControllerConfiguration, _ kubeclient.Client) error {
_, err := vi.NewController(
ctx,
mgr,
log,
configuration.Spec.ImportSettings.ImporterImage,
configuration.Spec.ImportSettings.UploaderImage,
configuration.Spec.ImportSettings.BounderImage,
configuration.Spec.ImportSettings.Requirements,
config.ToLegacyDVCR(configuration),
config.ToLegacyVirtualImageStorageClassSettings(configuration))
return err
},
vm.ControllerName: func(ctx context.Context, mgr manager.Manager, log *log.Logger, configuration *componentconfig.VirtualizationControllerConfiguration, _ kubeclient.Client) error {
return vm.SetupController(
ctx,
mgr,
log,
config.ToLegacyDVCR(configuration),
configuration.Spec.FirmwareImage)
},
vm.GCVMMigrationControllerName: func(_ context.Context, mgr manager.Manager, log *log.Logger, configuration *componentconfig.VirtualizationControllerConfiguration, _ kubeclient.Client) error {
return vm.SetupGC(mgr, log, configuration.Spec.GarbageCollector.VMIMigration)
},
vmbda.ControllerName: func(ctx context.Context, mgr manager.Manager, log *log.Logger, configuration *componentconfig.VirtualizationControllerConfiguration, virtualizationClient kubeclient.Client) error {
_, err := vmbda.NewController(ctx, mgr, virtualizationClient, log, configuration.Spec.Namespace)
return err
},
vmip.ControllerName: func(ctx context.Context, mgr manager.Manager, log *log.Logger, configuration *componentconfig.VirtualizationControllerConfiguration, virtualizationClient kubeclient.Client) error {
_, err := vmip.NewController(ctx, mgr, virtualizationClient, log, configuration.Spec.VirtualMachineCIDRs)
return err
},
vmiplease.ControllerName: func(ctx context.Context, mgr manager.Manager, log *log.Logger, configuration *componentconfig.VirtualizationControllerConfiguration, _ kubeclient.Client) error {
_, err := vmiplease.NewController(ctx, mgr, log, configuration.Spec.VirtualMachineIPLeasesRetentionDuration)
return err
},
vmclass.ControllerName: func(ctx context.Context, mgr manager.Manager, log *log.Logger, configuration *componentconfig.VirtualizationControllerConfiguration, _ kubeclient.Client) error {
_, err := vmclass.NewController(ctx, mgr, configuration.Spec.Namespace, log)
return err
},
vdsnapshot.ControllerName: func(ctx context.Context, mgr manager.Manager, log *log.Logger, _ *componentconfig.VirtualizationControllerConfiguration, virtualizationClient kubeclient.Client) error {
_, err := vdsnapshot.NewController(ctx, mgr, log, virtualizationClient)
return err
},
vmsnapshot.ControllerName: func(ctx context.Context, mgr manager.Manager, log *log.Logger, _ *componentconfig.VirtualizationControllerConfiguration, virtualizationClient kubeclient.Client) error {
return vmsnapshot.NewController(ctx, mgr, log, virtualizationClient)
},
vmrestore.ControllerName: func(ctx context.Context, mgr manager.Manager, log *log.Logger, _ *componentconfig.VirtualizationControllerConfiguration, _ kubeclient.Client) error {
return vmrestore.NewController(ctx, mgr, log)
},
vmop.ControllerName: func(ctx context.Context, mgr manager.Manager, log *log.Logger, _ *componentconfig.VirtualizationControllerConfiguration, _ kubeclient.Client) error {
return vmop.SetupController(ctx, mgr, log)
},
vmop.GCControllerName: func(_ context.Context, mgr manager.Manager, log *log.Logger, configuration *componentconfig.VirtualizationControllerConfiguration, _ kubeclient.Client) error {
return vmop.SetupGC(mgr, log, configuration.Spec.GarbageCollector.VMOP)
},
livemigration.ControllerName: func(ctx context.Context, mgr manager.Manager, log *log.Logger, _ *componentconfig.VirtualizationControllerConfiguration, _ kubeclient.Client) error {
return livemigration.SetupController(ctx, mgr, log)
},
workloadupdater.ControllerName: func(ctx context.Context, mgr manager.Manager, log *log.Logger, configuration *componentconfig.VirtualizationControllerConfiguration, _ kubeclient.Client) error {
return workloadupdater.SetupController(ctx, mgr, log, configuration.Spec.FirmwareImage, configuration.Spec.Namespace, configuration.Spec.VirtControllerName)
},
evacuation.ControllerName: func(ctx context.Context, mgr manager.Manager, log *log.Logger, _ *componentconfig.VirtualizationControllerConfiguration, virtualizationClient kubeclient.Client) error {
return evacuation.SetupController(ctx, mgr, virtualizationClient, log)
},
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
Copyright 2025 Flant JSC

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 app

import (
"fmt"

vsv1 "github.com/kubernetes-csi/external-snapshotter/client/v6/apis/volumesnapshot/v1"
extv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
"k8s.io/apimachinery/pkg/runtime"
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
virtv1 "kubevirt.io/api/core/v1"
cdiv1beta1 "kubevirt.io/containerized-data-importer-api/pkg/apis/core/v1beta1"

mcapi "github.com/deckhouse/virtualization-controller/pkg/controller/moduleconfig/api"
virtv2alpha1 "github.com/deckhouse/virtualization/api/core/v1alpha2"
)

func newScheme() (*runtime.Scheme, error) {
scheme := runtime.NewScheme()
for _, f := range []func(*runtime.Scheme) error{
clientgoscheme.AddToScheme,
extv1.AddToScheme,
virtv2alpha1.AddToScheme,
cdiv1beta1.AddToScheme,
virtv1.AddToScheme,
vsv1.AddToScheme,
mcapi.AddToScheme,
} {
err := f(scheme)
if err != nil {
return nil, fmt.Errorf("failed to add to scheme: %w", err)
}
}
return scheme, nil
}
Loading
Loading