Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

improve interface filtering when iscsi session is detected #891

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
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
}
Loading