Skip to content

Commit

Permalink
The PR improves nic filtering when iscsi sessions are detected.
Browse files Browse the repository at this point in the history
With this change, in case a vlan interface is used for an iscsi session,
then the parent interface is filtered from the list of interfaces and
is no longer visible in the list of interfaces

If there is no iscsi session then the behaviour of the installer remains
unchanged.

(cherry picked from commit f748284)
  • Loading branch information
ibrokethecloud authored and mergify[bot] committed Mar 3, 2025
1 parent 04bc862 commit 30ffa40
Showing 1 changed file with 54 additions and 20 deletions.
74 changes: 54 additions & 20 deletions pkg/console/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ func upAllLinks() error {
}

func getNICs() ([]netlink.Link, error) {
var nics []netlink.Link
var nics, vlanNics []netlink.Link

links, err := netlink.LinkList()
if err != nil {
Expand All @@ -138,9 +138,24 @@ func getNICs() ([]netlink.Link, error) {
if l.Type() == "device" && l.Attrs().EncapType != "loopback" {
nics = append(nics, l)
}
if l.Type() == "vlan" {
vlanNics = append(vlanNics, l)
}
}

iscsi := goiscsi.NewLinuxISCSI(nil)
sessions, err := iscsi.GetSessions()
if err != nil {
return nil, fmt.Errorf("error querying iscsi sessions: %v", err)
}

return filterISCSIInterfaces(nics)
// no iscsi sessions detected so no additional filtering based on usage for iscsi device
// access is needed and we can break here
if len(sessions) == 0 {
return nics, nil
}

return filterISCSIInterfaces(nics, vlanNics, sessions)
}

func getNICState(name string) int {
Expand Down Expand Up @@ -196,44 +211,63 @@ func getManagementInterfaceName(mgmtInterface config.Network) string {

// filterISCSIInterfaces will query the host to identify iscsi sessions, and skip interfaces
// used by the existing iscsi session.
func filterISCSIInterfaces(links []netlink.Link) ([]netlink.Link, error) {
iscsi := goiscsi.NewLinuxISCSI(nil)
sessions, err := iscsi.GetSessions()
if err != nil {
return nil, fmt.Errorf("error querying iscsi sessions: %v", err)
func filterISCSIInterfaces(nics, vlanNics []netlink.Link, sessions []goiscsi.ISCSISession) ([]netlink.Link, error) {
hwDeviceMap := make(map[string]netlink.Link)
for _, v := range nics {
hwDeviceMap[v.Attrs().HardwareAddr.String()] = v
}

var returnLinks []netlink.Link
// temporary sessionMap to make it easy to correlate interface addressses with session ip address
// should speed up identification of interfaces in use with iscsi sessions
sessionMap := make(map[string]string)
for _, session := range sessions {
sessionMap[session.IfaceIPaddress] = ""
}

if err := filterNICSBySession(hwDeviceMap, nics, sessionMap); err != nil {
return nil, err
}

if err := filterNICSBySession(hwDeviceMap, vlanNics, sessionMap); err != nil {
return nil, err
}
logrus.Debugf("identified following iscsi sessions: %v", sessionMap)
// we need to filter the filteredNics to also isolate parent nics if a vlan if is in use
returnedNics := make([]netlink.Link, 0, len(hwDeviceMap))
for _, v := range hwDeviceMap {
returnedNics = append(returnedNics, v)
}
return returnedNics, nil
}

func filterNICSBySession(hwDeviceMap map[string]netlink.Link, links []netlink.Link, sessionMap map[string]string) error {
for _, link := range links {
var inuse bool
logrus.Debugf("checking if link %s is in use", link.Attrs().Name)
if getNICState(link.Attrs().Name) == NICStateUP {
iface, err := net.InterfaceByName(link.Attrs().Name)
if err != nil {
return nil, fmt.Errorf("error fetching interface details: %v", err)
return fmt.Errorf("error fetching interface details: %v", err)
}

addresses, err := iface.Addrs()
if err != nil {
return nil, fmt.Errorf("error fetching addresses from interface: %v", err)
return fmt.Errorf("error fetching addresses from interface: %v", err)
}

for _, address := range addresses {
// interface addresses are in cidr format, and need to be converted before comparison
// since iscsi session contains just the ip address
ipAddress, _, err := net.ParseCIDR(address.String())
if err != nil {
return nil, fmt.Errorf("error parsing ip address: %v", err)
return fmt.Errorf("error parsing ip address: %v", err)
}
for _, session := range sessions {
if session.IfaceIPaddress == ipAddress.String() {
inuse = true
}
if _, ok := sessionMap[ipAddress.String()]; ok {
logrus.Debugf("filtering interface %s", link.Attrs().Name)
delete(hwDeviceMap, link.Attrs().HardwareAddr.String())
break //device is already removed, no point checking for other addresses
}
}
}
if !inuse {
returnLinks = append(returnLinks, link)
}
}
return returnLinks, nil
return nil
}

0 comments on commit 30ffa40

Please sign in to comment.