Skip to content

Commit

Permalink
Add ovirt system version to validate
Browse files Browse the repository at this point in the history
This patch will check the source provider version when it's oVirt
provider and we have a direct LUN/FC to migrate. It will make sure we
can support direct LUN/FC migration with enough API details from ovirt
to do so. The minimal required version of ovirt is ovirt-engine-4.5.2.1
based on the PR:
oVirt/ovirt-engine@e7c1f58

Signed-off-by: Liran Rotenberg <[email protected]>
  • Loading branch information
liranr23 committed Nov 20, 2023
1 parent ecf7900 commit 5145e5e
Show file tree
Hide file tree
Showing 17 changed files with 206 additions and 11 deletions.
2 changes: 2 additions & 0 deletions pkg/controller/plan/adapter/base/doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,8 @@ type Client interface {
type Validator interface {
// Validate that a VM's disk backing storage has been mapped.
StorageMapped(vmRef ref.Ref) (bool, error)
// Validate that a VM's direct LUN/FC has the details (oVirt only)
DirectStorage(vmRef ref.Ref) (bool, error)
// Validate that a VM's networks have been mapped.
NetworksMapped(vmRef ref.Ref) (bool, error)
// Validate that a VM's Host isn't in maintenance mode.
Expand Down
5 changes: 5 additions & 0 deletions pkg/controller/plan/adapter/ocp/validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -179,3 +179,8 @@ func (r *Validator) NetworksMapped(vmRef ref.Ref) (ok bool, err error) {

return true, nil
}

// NO-OP
func (r *Validator) DirectStorage(vmRef ref.Ref) (bool, error) {
return true, nil
}
5 changes: 5 additions & 0 deletions pkg/controller/plan/adapter/openstack/validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,3 +110,8 @@ func (r *Validator) PodNetwork(vmRef ref.Ref) (ok bool, err error) {
ok = podMapped <= 1
return
}

// NO-OP
func (r *Validator) DirectStorage(vmRef ref.Ref) (bool, error) {
return true, nil
}
5 changes: 5 additions & 0 deletions pkg/controller/plan/adapter/ova/validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,3 +108,8 @@ func (r *Validator) MaintenanceMode(vmRef ref.Ref) (ok bool, err error) {
ok = true
return
}

// NO-OP
func (r *Validator) DirectStorage(vmRef ref.Ref) (bool, error) {
return true, nil
}
1 change: 1 addition & 0 deletions pkg/controller/plan/adapter/ovirt/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ go_library(
"//pkg/controller/plan/adapter/base",
"//pkg/controller/plan/context",
"//pkg/controller/plan/util",
"//pkg/controller/provider/container",
"//pkg/controller/provider/container/ovirt",
"//pkg/controller/provider/web",
"//pkg/controller/provider/web/base",
Expand Down
16 changes: 16 additions & 0 deletions pkg/controller/plan/adapter/ovirt/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,22 @@ func (r *Client) getVM(vmRef ref.Ref) (ovirtVm *ovirtsdk.Vm, vmService *ovirtsdk
vmRef.String())
return
}
//system, err := r.connection.SystemService().Get().Send()
//product_info
/*
// <product_info>
// <name>oVirt Engine</name>
// <vendor>ovirt.org</vendor>
// <version>
// <build>4</build>
// <full_version>4.0.4</full_version>
// <major>4</major>
// <minor>0</minor>
// <revision>0</revision>
// </version>
// </product_info>
*/

vmService = r.connection.SystemService().VmsService().VmService(vm.ID)
vmResponse, err := vmService.Get().Query("correlation_id", r.Migration.Name).Send()
if err != nil {
Expand Down
88 changes: 83 additions & 5 deletions pkg/controller/plan/adapter/ovirt/validator.go
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
package ovirt

import (
"strconv"

api "github.com/konveyor/forklift-controller/pkg/apis/forklift/v1beta1"
"github.com/konveyor/forklift-controller/pkg/apis/forklift/v1beta1/ref"
"github.com/konveyor/forklift-controller/pkg/controller/provider/container"
"github.com/konveyor/forklift-controller/pkg/controller/provider/web"
model "github.com/konveyor/forklift-controller/pkg/controller/provider/web/ovirt"
liberr "github.com/konveyor/forklift-controller/pkg/lib/error"
"github.com/konveyor/forklift-controller/pkg/settings"
)

// vSphere validator.
// oVirt validator.
type Validator struct {
plan *api.Plan
inventory web.Client
Expand Down Expand Up @@ -92,7 +95,6 @@ func (r *Validator) PodNetwork(vmRef ref.Ref) (ok bool, err error) {

// Validate that a VM's disk backing storage has been mapped.
func (r *Validator) StorageMapped(vmRef ref.Ref) (ok bool, err error) {
// TODO validate ovirt version > ovirt-engine-4.5.2.1 (https://github.com/oVirt/ovirt-engine/commit/e7c1f585863a332bcecfc8c3d909c9a3a56eb922)
if r.plan.Referenced.Map.Storage == nil {
return
}
Expand All @@ -106,20 +108,96 @@ func (r *Validator) StorageMapped(vmRef ref.Ref) (ok bool, err error) {
vmRef.String())
return
}

for _, da := range vm.DiskAttachments {
if da.Disk.StorageType != "lun" {
if !r.plan.Referenced.Map.Storage.Status.Refs.Find(ref.Ref{ID: da.Disk.StorageDomain}) {
return
}
} else if len(da.Disk.Lun.LogicalUnits.LogicalUnit) > 0 {
// Have LUN disk but without the relevant data. This might happen with older oVirt versions.
return
}
}
ok = true
return
}

// Validates oVirt version in case we use direct LUN/FC storage
func (r *Validator) DirectStorage(vmRef ref.Ref) (ok bool, err error) {
if r.plan.Referenced.Map.Storage == nil {
return
}
vm := &model.Workload{}
err = r.inventory.Find(vm, vmRef)
if err != nil {
err = liberr.Wrap(
err,
"VM not found in inventory.",
"vm",
vmRef.String())
return
}

for _, da := range vm.DiskAttachments {
if da.Disk.StorageType == "lun" {
if len(da.Disk.Lun.LogicalUnits.LogicalUnit) > 0 {
if ok, err := r.checkOvirtVersion(); err != nil || !ok {
return ok, err
}
}
}
}
ok = true
return
}

// Checks the version for ovirt direct LUN/FC
func (r *Validator) checkOvirtVersion() (ok bool, err error) {
// validate ovirt version > ovirt-engine-4.5.2.1 (https://github.com/oVirt/ovirt-engine/commit/e7c1f585863a332bcecfc8c3d909c9a3a56eb922)
rl := container.Build(nil, r.plan.Referenced.Provider.Source, r.plan.Referenced.Secret)
major, minor, build, revision, err := rl.Version()
if err != nil {
return false, err
}
val, err := strconv.Atoi(major)
if err != nil {
return false, err
}
if val != 4 {
if val > 4 {
return true, nil
}
return false, nil
}
val, err = strconv.Atoi(minor)
if err != nil {
return false, err
}
if val != 5 {
if val > 5 {
return true, nil
}
return false, nil
}
val, err = strconv.Atoi(build)
if err != nil {
return false, err
}
if val != 2 {
if val > 2 {
return true, nil
}
return false, nil
}
val, err = strconv.Atoi(revision)
if err != nil {
return false, err
}
if val < 1 {
return false, nil
}
ok = true
return
}

// Validate that a VM's Host isn't in maintenance mode. No-op for oVirt.
func (r *Validator) MaintenanceMode(_ ref.Ref) (ok bool, err error) {
ok = true
Expand Down
5 changes: 5 additions & 0 deletions pkg/controller/plan/adapter/vsphere/validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,3 +144,8 @@ func (r *Validator) MaintenanceMode(vmRef ref.Ref) (ok bool, err error) {
ok = !host.InMaintenanceMode
return
}

// NO-OP
func (r *Validator) DirectStorage(vmRef ref.Ref) (bool, error) {
return true, nil
}
40 changes: 40 additions & 0 deletions pkg/controller/plan/validation.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
libcnd "github.com/konveyor/forklift-controller/pkg/lib/condition"
liberr "github.com/konveyor/forklift-controller/pkg/lib/error"
libref "github.com/konveyor/forklift-controller/pkg/lib/ref"
v1 "k8s.io/api/core/v1"
k8serr "k8s.io/apimachinery/pkg/api/errors"
k8svalidation "k8s.io/apimachinery/pkg/util/validation"
"sigs.k8s.io/controller-runtime/pkg/client"
Expand All @@ -34,6 +35,7 @@ const (
VMAlreadyExists = "VMAlreadyExists"
VMNetworksNotMapped = "VMNetworksNotMapped"
VMStorageNotMapped = "VMStorageNotMapped"
VMStorageNotSupported = "VMStorageNotSupported"
VMMultiplePodNetworkMappings = "VMMultiplePodNetworkMappings"
HostNotReady = "HostNotReady"
DuplicateVM = "DuplicateVM"
Expand Down Expand Up @@ -342,6 +344,14 @@ func (r *Reconciler) validateVM(plan *api.Plan) error {
Message: "VM has unmapped storage.",
Items: []string{},
}
unsupportedStorage := libcnd.Condition{
Type: VMStorageNotSupported,
Status: True,
Reason: NotValid,
Category: Critical,
Message: "VM has unsupported storage. Direct LUN/FC in oVirt requires version 4.5.2.1",
Items: []string{},
}
maintenanceMode := libcnd.Condition{
Type: HostNotReady,
Status: True,
Expand Down Expand Up @@ -411,6 +421,12 @@ func (r *Reconciler) validateVM(plan *api.Plan) error {
if err != nil {
return err
}
if plan.Referenced.Secret == nil {
err = r.setupSecret(plan)
if err != nil {
return err
}
}
if plan.Referenced.Map.Network != nil {
ok, err := validator.NetworksMapped(*ref)
if err != nil {
Expand All @@ -435,6 +451,13 @@ func (r *Reconciler) validateVM(plan *api.Plan) error {
if !ok {
unmappedStorage.Items = append(unmappedStorage.Items, ref.String())
}
ok, err = validator.DirectStorage(*ref)
if err != nil {
return err
}
if !ok {
unsupportedStorage.Items = append(unsupportedStorage.Items, ref.String())
}
}
ok, err := validator.MaintenanceMode(*ref)
if err != nil {
Expand Down Expand Up @@ -491,6 +514,9 @@ func (r *Reconciler) validateVM(plan *api.Plan) error {
if len(unmappedStorage.Items) > 0 {
plan.Status.SetCondition(unmappedStorage)
}
if len(unsupportedStorage.Items) > 0 {
plan.Status.SetCondition(unsupportedStorage)
}
if len(maintenanceMode.Items) > 0 {
plan.Status.SetCondition(maintenanceMode)
}
Expand Down Expand Up @@ -670,3 +696,17 @@ func (r *Reconciler) validateVddkImage(plan *api.Plan) (err error) {
}
return nil
}

func (r *Reconciler) setupSecret(plan *api.Plan) (err error) {
key := client.ObjectKey{
Namespace: plan.Referenced.Provider.Source.Spec.Secret.Namespace,
Name: plan.Referenced.Provider.Source.Spec.Secret.Name,
}
secret := v1.Secret{}
err = r.Get(context.TODO(), key, &secret)
if err != nil {
return
}
plan.Referenced.Secret = &secret
return
}
5 changes: 5 additions & 0 deletions pkg/controller/provider/container/ocp/collector.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,11 @@ func New(db libmodel.DB, provider *api.Provider, secret *core.Secret) libcontain
}
}

// NO-OP
func (r *Collector) Version() (_, _, _, _ string, err error) {
return
}

// OCP collector.
type Collector struct {
*libocp.Collector
Expand Down
5 changes: 5 additions & 0 deletions pkg/controller/provider/container/openstack/collector.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,11 @@ func (r *Collector) Test() (_ int, err error) {
return
}

// NO-OP
func (r *Collector) Version() (_ , _, _, _ string, err error) {
return
}

// Start the collector.
func (r *Collector) Start() error {
ctx := Context{
Expand Down
5 changes: 5 additions & 0 deletions pkg/controller/provider/container/ova/collector.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,11 @@ func (r *Collector) Test() (_ int, err error) {
return
}

// NO-OP
func (r *Collector) Version() (_, _, _, _ string, err error) {
return
}

// Start the collector.
func (r *Collector) Start() error {
ctx := Context{
Expand Down
4 changes: 2 additions & 2 deletions pkg/controller/provider/container/ovirt/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -189,12 +189,12 @@ func (r *Client) get(path string, object interface{}, param ...libweb.Param) (er
}

// Get system.
func (r *Client) system() (s *System, status int, err error) {
func (r *Client) system() (system *System, status int, err error) {
status, err = r.connect()
if err != nil {
return
}
system := &System{}
system = &System{}
status, err = r.client.Get(r.url, system)
if err != nil {
return
Expand Down
15 changes: 15 additions & 0 deletions pkg/controller/provider/container/ovirt/collector.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,21 @@ func (r *Collector) Test() (status int, err error) {
return
}

func (r *Collector) Version() (major, minor, build, revision string, err error) {
system, _, err := r.client.system()
if err != nil {
return
}
version := strings.Split(system.Product.Version.FullVersion, ".")
major = version[0]
minor = version[1]
build = version[2]
if len(version) > 3 {
revision = strings.Split(version[3], "-")[0]
}
return
}

// Start the collector.
func (r *Collector) Start() error {
ctx := Context{
Expand Down
9 changes: 5 additions & 4 deletions pkg/controller/provider/container/ovirt/resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,11 @@ type System struct {
Name string `json:"name"`
Vendor string `json:"vendor"`
Version struct {
Build string `json:"build"`
Major string `json:"major"`
Minor string `json:"minor"`
Revision string `json:"revision"`
Build string `json:"build"`
Major string `json:"major"`
Minor string `json:"minor"`
Revision string `json:"revision"`
FullVersion string `json:"full_version"`
} `json:"version"`
} `json:"product_info"`
}
Expand Down
5 changes: 5 additions & 0 deletions pkg/controller/provider/container/vsphere/collector.go
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,11 @@ func (r *Collector) Test() (status int, err error) {
return
}

// NO-OP
func (r *Collector) Version() (_, _, _, _ string, err error) {
return
}

// Start the collector.
func (r *Collector) Start() error {
ctx := context.Background()
Expand Down
2 changes: 2 additions & 0 deletions pkg/lib/inventory/container/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -148,4 +148,6 @@ type Collector interface {
Test() (int, error)
// Reset
Reset()
// Get the system verion - only ovirt
Version() (string, string, string, string, error)
}

0 comments on commit 5145e5e

Please sign in to comment.