github.com/openshift/installer@v1.4.17/pkg/types/baremetal/validation/libvirt.go (about)

     1  package validation
     2  
     3  import (
     4  	"fmt"
     5  	"net/url"
     6  	"strings"
     7  
     8  	libvirt "github.com/digitalocean/go-libvirt"
     9  	"github.com/sirupsen/logrus"
    10  )
    11  
    12  // libvirtInterfaceValidator fetches the valid interface names from a particular libvirt instance, and returns a closure
    13  // to validate if an interface is found among them
    14  func libvirtInterfaceValidator(libvirtURI string) (func(string) error, error) {
    15  	// Connect to libvirt and obtain a list of interface names
    16  	interfaces := make(map[string]struct{})
    17  	var exists = struct{}{}
    18  
    19  	uri, err := url.Parse(libvirtURI)
    20  	if err != nil {
    21  		return nil, err
    22  	}
    23  
    24  	virt, err := libvirt.ConnectToURI(uri)
    25  	if err != nil {
    26  		return nil, err
    27  	}
    28  	defer func() {
    29  		if err := virt.Disconnect(); err != nil {
    30  			logrus.Errorln("error disconnecting from libvirt:", err)
    31  		}
    32  	}()
    33  
    34  	networks, _, err := virt.ConnectListAllNetworks(1, libvirt.ConnectListNetworksActive)
    35  	if err != nil {
    36  		return nil, fmt.Errorf("could not list libvirt networks: %w", err)
    37  	}
    38  	for _, network := range networks {
    39  		bridgeName, err := virt.NetworkGetBridgeName(network)
    40  		if err == nil && bridgeName == network.Name {
    41  			interfaces[network.Name] = exists
    42  		}
    43  	}
    44  	bridges, _, err := virt.ConnectListAllInterfaces(1, libvirt.ConnectListInterfacesActive)
    45  	if err != nil {
    46  		return nil, fmt.Errorf("could not list libvirt interfaces: %w", err)
    47  	}
    48  
    49  	for _, bridge := range bridges {
    50  		interfaces[bridge.Name] = exists
    51  	}
    52  	interfaceNames := make([]string, len(interfaces))
    53  	idx := 0
    54  	for key := range interfaces {
    55  		interfaceNames[idx] = key
    56  		idx++
    57  	}
    58  
    59  	// Return a closure to validate if any particular interface is found among interfaceNames
    60  	return func(interfaceName string) error {
    61  		if len(interfaceNames) == 0 {
    62  			return fmt.Errorf("no interfaces found")
    63  		} else {
    64  			for _, foundInterface := range interfaceNames {
    65  				if foundInterface == interfaceName {
    66  					return nil
    67  				}
    68  			}
    69  
    70  			return fmt.Errorf("could not find interface %q, valid interfaces are %s", interfaceName, strings.Join(interfaceNames, ", "))
    71  		}
    72  	}, nil
    73  }