Skip to content
Closed
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
1 change: 1 addition & 0 deletions data/data/ovirt/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ module "template" {
ovirt_template_mem = var.ovirt_template_mem
disk_size_gib = var.ovirt_template_disk_size_gib
ovirt_network_name = var.ovirt_network_name
ovirt_vnic_profile_id = var.ovirt_vnic_profile_id
}

module "bootstrap" {
Expand Down
8 changes: 1 addition & 7 deletions data/data/ovirt/template/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,6 @@ data "ovirt_clusters" "clusters" {
}
}

// default vnic profile of ovirt's cluster network
data "ovirt_vnic_profiles" "vnic_profiles" {
name_regex = var.ovirt_network_name
network_id = local.network_id
}

// work around the missing regexall in terraform < 0.12.9
// if length(regexall("^Blank.*$", t.name)
locals {
Expand Down Expand Up @@ -59,7 +53,7 @@ resource "ovirt_vm" "tmp_import_vm" {
}
nics {
name = "nic1"
vnic_profile_id = data.ovirt_vnic_profiles.vnic_profiles.vnic_profiles.0.id
vnic_profile_id = var.ovirt_vnic_profile_id
}
depends_on = [ovirt_image_transfer.releaseimage]
}
Expand Down
6 changes: 5 additions & 1 deletion data/data/ovirt/template/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,14 @@ variable "openstack_base_image_local_file_path" {

variable "ovirt_network_name" {
type = string
default = "ovirtmgmt"
description = "The name of ovirt's logical network for the selected ovirt cluster."
}

variable "ovirt_vnic_profile_id" {
type = string
description = "The ID of the vnic profile of ovirt's logical network."
}

variable "ovirt_template_mem" {
type = string
}
Expand Down
5 changes: 5 additions & 0 deletions data/data/ovirt/variables-ovirt.tf
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@ variable "ovirt_network_name" {
description = "The name of ovirt's logical network for the selected ovirt cluster."
}

variable "ovirt_vnic_profile_id" {
type = string
description = "The ID of the vnic profile of ovirt's logical network."
}

variable "ovirt_master_mem" {
type = string
default = "8192"
Expand Down
20 changes: 20 additions & 0 deletions pkg/asset/cluster/tfvars.go
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,25 @@ func (t *TerraformVariables) Generate(parents asset.Parents) error {
if err != nil {
return err
}
con, err := ovirtconfig.NewConnection()
if err != nil {
return err
}
defer con.Close()

if installConfig.Config.Platform.Ovirt.VNICProfileID == "" {
profiles, err := ovirtconfig.FetchVNICProfileByClusterNetwork(
con,
installConfig.Config.Platform.Ovirt.ClusterID,
installConfig.Config.Platform.Ovirt.NetworkName)
if err != nil {
return errors.Wrapf(err, "failed to compute values for oVirt platform")
}
if len(profiles) != 1 {
return errors.Wrapf(err, "failed to compute values for oVirt platform, there are multiple vNic profiles.")
}
installConfig.Config.Platform.Ovirt.VNICProfileID = profiles[0].MustId()
}

data, err := ovirttfvars.TFVars(
config.URL,
Expand All @@ -423,6 +442,7 @@ func (t *TerraformVariables) Generate(parents asset.Parents) error {
installConfig.Config.Platform.Ovirt.ClusterID,
installConfig.Config.Platform.Ovirt.StorageDomainID,
installConfig.Config.Platform.Ovirt.NetworkName,
installConfig.Config.Platform.Ovirt.VNICProfileID,
string(*rhcosImage),
clusterID.InfraID,
)
Expand Down
4 changes: 4 additions & 0 deletions pkg/asset/installconfig/installconfig.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
icazure "github.com/openshift/installer/pkg/asset/installconfig/azure"
icgcp "github.com/openshift/installer/pkg/asset/installconfig/gcp"
icopenstack "github.com/openshift/installer/pkg/asset/installconfig/openstack"
icovirt "github.com/openshift/installer/pkg/asset/installconfig/ovirt"
"github.com/openshift/installer/pkg/types"
"github.com/openshift/installer/pkg/types/conversion"
"github.com/openshift/installer/pkg/types/defaults"
Expand Down Expand Up @@ -173,5 +174,8 @@ func (a *InstallConfig) platformValidation() error {
if a.Config.Platform.AWS != nil {
return aws.Validate(context.TODO(), a.AWS, a.Config)
}
if a.Config.Platform.Ovirt != nil {
return icovirt.Validate(a.Config)
}
return field.ErrorList{}.ToAggregate()
}
53 changes: 51 additions & 2 deletions pkg/asset/installconfig/ovirt/client.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
package ovirt

import (
"fmt"

ovirtsdk "github.com/ovirt/go-ovirt"
"github.com/pkg/errors"
)

// GetConnection is a convenience method to get a connection to ovirt api
// getConnection is a convenience method to get a connection to ovirt api
// form a Config Object.
func GetConnection(ovirtConfig Config) (*ovirtsdk.Connection, error) {
func getConnection(ovirtConfig Config) (*ovirtsdk.Connection, error) {
con, err := ovirtsdk.NewConnectionBuilder().
URL(ovirtConfig.URL).
Username(ovirtConfig.Username).
Expand All @@ -19,3 +22,49 @@ func GetConnection(ovirtConfig Config) (*ovirtsdk.Connection, error) {
}
return con, nil
}

// NewConnection returns a new client connection to oVirt's API endpoint.
// It is the responsibility of the caller to close the connection.
func NewConnection() (*ovirtsdk.Connection, error) {
ovirtConfig, err := NewConfig()
if err != nil {
return nil, errors.Wrap(err, "getting ovirt configuration")
}
con, err := getConnection(ovirtConfig)
if err != nil {
return nil, errors.Wrap(err, "establishing ovirt connection")
}
return con, nil
}

// FetchVNICProfileByClusterNetwork returns a list of profiles for the given cluster and network name.
func FetchVNICProfileByClusterNetwork(con *ovirtsdk.Connection, clusterID string, networkName string) ([]*ovirtsdk.VnicProfile, error) {
clusterResponse, err := con.SystemService().ClustersService().ClusterService(clusterID).Get().Follow("networks").Send()
if err != nil {
return nil, err
}

cluster, ok := clusterResponse.Cluster()
if !ok {
return nil, fmt.Errorf("failed to find cluster with id %s", clusterID)
}

networks, ok := cluster.Networks()
if !ok {
return nil, fmt.Errorf("no cluster networks for cluster %s [%s]", cluster.MustName(), clusterID)
}

for _, n := range networks.Slice() {
if n.MustName() != networkName {
continue
}

profilesGet, err := con.SystemService().NetworksService().NetworkService(n.MustId()).VnicProfilesService().List().Send()
if err != nil {
return nil, fmt.Errorf("failed to fetch vNic profiles")
}

return profilesGet.MustProfiles().Slice(), nil
}
return nil, fmt.Errorf("there are no vNic profiles for the given cluster ID %s and network name %s", clusterID, networkName)
}
43 changes: 43 additions & 0 deletions pkg/asset/installconfig/ovirt/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,46 @@ func askNetwork(c *ovirtsdk4.Connection, p *ovirt.Platform) error {
})
return err
}

func askVNICProfileID(c *ovirtsdk4.Connection, p *ovirt.Platform) error {
var profileID string
var profilesByNames = make(map[string]*ovirtsdk4.VnicProfile)
var profileNames []string
profiles, err := FetchVNICProfileByClusterNetwork(c, p.ClusterID, p.NetworkName)
if err != nil {
return err
}

for _, profile := range profiles {
profilesByNames[profile.MustName()] = profile
profileNames = append(profileNames, profile.MustName())
}

if len(profilesByNames) == 1 {
p.VNICProfileID = profilesByNames[profileNames[0]].MustId()
return nil
}

// we have multiple vnic profile for the selected network
err = survey.AskOne(&survey.Select{
Message: "VNIC Profile",
Help: "The oVirt VNIC profile of the VMs.",
Options: profileNames,
},
&profileID,
func(ans interface{}) error {
choice := ans.(string)
sort.Strings(profileNames)
i := sort.SearchStrings(profileNames, choice)
if i == len(profileNames) || profileNames[i] != choice {
return fmt.Errorf("invalid VNIC profile %s", choice)
}
profile, ok := profilesByNames[choice]
if !ok {
return fmt.Errorf("cannot find a VNIC profile id by the name %s", choice)
}
p.VNICProfileID = profile.MustId()
return nil
})
return err
}
5 changes: 5 additions & 0 deletions pkg/asset/installconfig/ovirt/ovirt.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,11 @@ func Platform() (*ovirt.Platform, error) {
return &p, err
}

err = askVNICProfileID(c, &p)
if err != nil {
return &p, err
}

err = survey.Ask([]*survey.Question{
{
Prompt: &survey.Input{
Expand Down
96 changes: 96 additions & 0 deletions pkg/asset/installconfig/ovirt/validaton.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package ovirt

import (
"fmt"

ovirtsdk "github.com/ovirt/go-ovirt"
"github.com/pkg/errors"
"gopkg.in/AlecAivazis/survey.v1"
"k8s.io/apimachinery/pkg/util/validation/field"

"github.com/openshift/installer/pkg/types"
"github.com/openshift/installer/pkg/types/ovirt"
"github.com/openshift/installer/pkg/types/ovirt/validation"
)

// Validate executes ovirt specific validation
func Validate(ic *types.InstallConfig) error {
allErrs := field.ErrorList{}
ovirtPlatformPath := field.NewPath("platform", "ovirt")

if ic.Platform.Ovirt == nil {
return errors.New(field.Required(
ovirtPlatformPath,
"oVirt validation requires a oVirt platform configuration").Error())
}

allErrs = append(
allErrs,
validation.ValidatePlatform(ic.Platform.Ovirt, ovirtPlatformPath)...)

con, err := NewConnection()
if err != nil {
return err
}
defer con.Close()

if err := validateVNICProfile(*ic.Ovirt, con); err != nil {
allErrs = append(
allErrs,
field.Invalid(ovirtPlatformPath.Child("vnicProfileID"), ic.Ovirt.VNICProfileID, err.Error()))
}

return allErrs.ToAggregate()
}

// authenticated takes an ovirt platform and validates
// its connection to the API by establishing
// the connection and authenticating successfully.
// The API connection is closed in the end and must leak
// or be reused in any way.
func authenticated(c *Config) survey.Validator {
return func(val interface{}) error {
connection, err := ovirtsdk.NewConnectionBuilder().
URL(c.URL).
Username(c.Username).
Password(fmt.Sprint(val)).
CAFile(c.CAFile).
Insecure(c.Insecure).
Build()

if err != nil {
return errors.Errorf("failed to construct connection to oVirt platform %s", err)
}

defer connection.Close()

err = connection.Test()
if err != nil {
return errors.Errorf("failed to connect to oVirt platform %s", err)
}
return nil
}

}

// validate the provided vnic profile exists and belongs the the cluster network
func validateVNICProfile(platform ovirt.Platform, con *ovirtsdk.Connection) error {
if platform.VNICProfileID != "" {
profiles, err := FetchVNICProfileByClusterNetwork(con, platform.ClusterID, platform.NetworkName)
if err != nil {
return err
}

for _, p := range profiles {
if platform.VNICProfileID == p.MustId() {
return nil
}
}

return fmt.Errorf(
"vNic profile ID %s does not belong to cluster network %s",
platform.VNICProfileID,
platform.NetworkName)
}
return nil
}
39 changes: 0 additions & 39 deletions pkg/asset/installconfig/ovirt/validators.go

This file was deleted.

8 changes: 2 additions & 6 deletions pkg/asset/installconfig/platformcredscheck.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,13 +65,9 @@ func (a *PlatformCredsCheck) Generate(dependencies asset.Parents) error {
return errors.Wrap(err, "creating Azure session")
}
case ovirt.Name:
ovirtConfig, err := ovirtconfig.NewConfig()
con, err := ovirtconfig.NewConnection()
if err != nil {
return errors.Wrap(err, "getting ovirt configuration")
}
con, err := ovirtconfig.GetConnection(ovirtConfig)
if err != nil {
return errors.Wrap(err, "establishing ovirt connection")
return errors.Wrap(err, "creating oVirt connection")
}
err = con.Test()
if err != nil {
Expand Down
Loading