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

LACP support #9

Closed
wants to merge 23 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
9e03602
init/configureNetworking: improve readability
ydirson Jan 11, 2023
af7aa43
writeRHStyleInterface: split writeIface()
benjamreis Jan 9, 2023
0e42c10
writeIface: use "with" statement
ydirson Jan 17, 2023
84c83f2
writeIface: split writing IP configuration for reuse
ydirson Jan 17, 2023
c0246d0
ifup: remove extraneous assert
ydirson Jan 12, 2023
61d5853
getNetifList: remove eth hardcoding in interface sorting
ydirson Jan 12, 2023
c6c3222
netutil.scanConfiguration: rework for extensibility
ydirson Jan 12, 2023
e33094e
doc: make it clear where we expect URLs
ydirson Jan 11, 2023
7380c8b
doc: fix description of --network_device default
ydirson Jan 11, 2023
d01c8a8
doc: make --network_device no less visible than its deprecated counte…
ydirson Jan 11, 2023
fcdd67f
net*: cleanups around vlan-interface
ydirson Jan 17, 2023
fe1cc9b
NetInterface: remove dead code
ydirson Jan 13, 2023
28ed9ce
answerfile: improve handling of admin-interface selection (xenserver#33)
ydirson Jan 13, 2023
aab13c2
NetInterface: pass a NIC not just a hwaddr to ctor
ydirson Jan 20, 2023
40584a4
WIP NIC,NetInterface: add support for bonding interfaces
ydirson Jan 20, 2023
d031042
init: add support for LACP bonding in --network_device (xcp-ng/xcp#350)
ydirson Jan 13, 2023
7b6d851
netutil.scanConfiguration: allow reuse of commandline config
ydirson Jan 12, 2023
858caff
configureNetworking: write bond configuration to firstboot.d
benjamreis Jan 13, 2023
bd386b1
tui.network: make lentry() and iface_details() more accessible
benjamreis Jan 9, 2023
d25513d
tui: don't hide NIC selection when there is only one
ydirson Jan 13, 2023
1af51b6
tui: let user configure a bonding interface interactively
ydirson Jan 13, 2023
53ccffb
answerfile: remove useless statement
ydirson Jan 18, 2023
df5bed0
answerfile: LACP bonding support
ydirson Jan 17, 2023
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
58 changes: 46 additions & 12 deletions answerfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -352,36 +352,70 @@ def parseFCoEInterface(self):

return results

def parseBonding(self, nethw):
nodes = getElementsByTagName(self.top_node, ['bonding'])
if len(nodes) > 1:
raise AnswerfileException("<bonding> must appear only once")
if nodes:
node = nodes[0]
bond_name = getStrAttribute(node, ['name'], mandatory=True)
if bond_name != "bond0":
raise AnswerfileException("<bonding> name must be 'bond0'")

bond_mode = getStrAttribute(node, ['mode'], mandatory=True)
if bond_mode != "lacp":
raise AnswerfileException("<bonding> mode must be 'lacp'")

bond_members_str = getStrAttribute(node, ['members'], mandatory=True)
bond_members = bond_members_str.split(",")
if len(bond_members) < 2:
raise AnswerfileException("<bonding> members must be at least two")
for member in bond_members:
if member not in nethw:
raise AnswerfileException("<bonding> member %r not in detected NICs" % (member,))

netutil.configure_bonding_interface(nethw, bond_name, bond_mode, bond_members)

def parseInterface(self):
results = {}
node = getElementsByTagName(self.top_node, ['admin-interface'], mandatory=True)[0]
nethw = netutil.scanConfiguration()
if_hwaddr = None
self.parseBonding(nethw)

if_name = getStrAttribute(node, ['name'])
if if_name and if_name in nethw:
if_hwaddr = getStrAttribute(node, ['hwaddr'])
if not (bool(if_name) ^ bool(if_hwaddr)):
raise AnswerfileException("<admin-interface> tag must have exactly one of 'name' or 'hwaddr'")

if if_name:
if if_name not in nethw:
raise AnswerfileException('<admin-interface name="%s">: unknown interface, have %s' % (
if_name, ", ".join(nethw.keys())))
if_hwaddr = nethw[if_name].hwaddr
elif if_hwaddr:
matching_list = [x for x in nethw.values() if x.hwaddr == if_hwaddr.lower()]
if len(matching_list) != 1:
raise AnswerfileException('<admin-interface hwaddr="%s">: cannot identify interface, have %s' % (
if_hwaddr, ", ".join(nethw.values())))
if_name = matching_list[0].name
else:
if_hwaddr = getStrAttribute(node, ['hwaddr'])
if if_hwaddr:
matching_list = filter(lambda x: x.hwaddr == if_hwaddr.lower(), nethw.values())
if len(matching_list) == 1:
if_name = matching_list[0].name
if not if_name and not if_hwaddr:
raise AnswerfileException("<admin-interface> tag must have one of 'name' or 'hwaddr'")
assert False # previous test protects us

nic = netutil.NIC({"Kernel name": if_name,
"Assigned MAC": if_hwaddr,
})
results['net-admin-interface'] = if_name

proto = getStrAttribute(node, ['proto'], mandatory=True)
if proto == 'static':
ip = getText(getElementsByTagName(node, ['ip', 'ipaddr'], mandatory=True)[0])
subnet = getText(getElementsByTagName(node, ['subnet-mask', 'subnet'], mandatory=True)[0])
gateway = getText(getElementsByTagName(node, ['gateway'], mandatory=True)[0])
results['net-admin-configuration'] = NetInterface(NetInterface.Static, if_hwaddr, ip, subnet, gateway, dns=None)
results['net-admin-configuration'] = NetInterface(NetInterface.Static, nic, ip, subnet, gateway, dns=None)
elif proto == 'dhcp':
results['net-admin-configuration'] = NetInterface(NetInterface.DHCP, if_hwaddr)
results['net-admin-configuration'] = NetInterface(NetInterface.DHCP, nic)
else:
results['net-admin-configuration'] = NetInterface(None, if_hwaddr)
results['net-admin-configuration'] = NetInterface(None, nic)

protov6 = getStrAttribute(node, ['protov6'])
if protov6 == 'static':
Expand Down
4 changes: 4 additions & 0 deletions backend.py
Original file line number Diff line number Diff line change
Expand Up @@ -1503,6 +1503,10 @@ def configureNetworking(mounts, admin_iface, admin_bridge, admin_config, hn_conf
print >>mc, "IPv6_GATEWAY='%s'" % admin_config.ipv6_gateway
if admin_config.vlan:
print >>mc, "VLAN='%d'" % admin_config.vlan
if admin_config.bond_mode is not None:
print >>mc, "BOND_MODE='%s'" % admin_config.bond_mode
print >>mc, "BOND_MEMBERS='%s'" % ','.join(admin_config.bond_members)

mc.close()

if network_backend == constants.NETWORK_BACKEND_VSWITCH:
Expand Down
8 changes: 8 additions & 0 deletions doc/answerfile.txt
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,14 @@ Common Elements
Specifies additional devices to be included in the local SR.


<bonding name="bond0" mode="lacp" members="eth,eth[,eth]*"/>

Join given ethernet interfaces using LACP bonding. Name of
resulting interface must be "bond0". It can be then be used with

<admin-interface name="bond0"/>


<admin-interface name="eth"/> | <admin-interface hwaddr="mac"/>

Specifies the initial management interface.
Expand Down
18 changes: 13 additions & 5 deletions doc/parameters.txt
Original file line number Diff line number Diff line change
Expand Up @@ -122,29 +122,37 @@ Installer
Proceed with installation/upgrade.


--answerfile=ans
--answerfile=url

Read answerfile and perform a non-interactive installation
reporting status using screens.


--rt_answerfile=ans
--rt_answerfile=url

Read answerfile and perform a non-interactive installation
reporting status to the console as text.


--answerfile_generator=script
--answerfile_generator=url

Retrieve script, run it and use the output of it as an answerfile.


--answerfile_device[D]=eth|mac|all | --network_device=eth|mac|all
--network_device=eth|mac|lacp:members=eth,eth[,eth]*|all
--answerfile_device[D]=...

Bring up networking on the given interface to allow access to
answerfiles.

Default: all
Specification of LACP bonding configures a bond0 interfaces with
given members.

Default: "all" if a non-local URL is specified for any of the above
answerfile parameters, else no device is started

--answerfile_device is a deprecated alias, and accepts the same
parameters as --network_device.


--map_netdev=eth:d|s:mac|pci[[index]]|ppn
Expand Down
28 changes: 19 additions & 9 deletions init
Original file line number Diff line number Diff line change
Expand Up @@ -51,23 +51,33 @@ def configureNetworking(ui, device, config):

nethw = netutil.scanConfiguration()
netcfg = {}
for i in nethw:
if (device == i or device == nethw[i].hwaddr) and mode == 'static':
netcfg[i] = NetInterface(NetInterface.Static, nethw[i].hwaddr,
config_dict['ip'], config_dict['netmask'],
config_dict['gateway'], config_dict['dns'],
config_dict['domain'], config_dict['vlan'])

if device.startswith("lacp:"):
bond_mode, bond_config = device.split(":", 1)
device = "bond0"
assert bond_config.startswith("members=")
k, v = bond_config.split("=", 1)
bond_members = v.split(",")
netutil.configure_bonding_interface(nethw, device, "lacp", bond_members)

for devname, nic in nethw.items():
if (device == devname or device == nic.hwaddr) and mode == 'static':
netcfg[devname] = NetInterface(NetInterface.Static, nic,
config_dict['ip'], config_dict['netmask'],
config_dict['gateway'], config_dict['dns'],
config_dict['domain'], config_dict['vlan'],
bond_mode=nic.bond_mode, bond_members=nic.bond_members)
else:
netcfg[i] = NetInterface(NetInterface.DHCP, nethw[i].hwaddr,
vlan=config_dict['vlan'])
netcfg[devname] = NetInterface(NetInterface.DHCP, nic,
vlan=config_dict['vlan'])

netutil.writeNetInterfaceFiles(netcfg)
netutil.writeResolverFile(netcfg, '/etc/resolv.conf')

iface_to_start = []
if device == 'all':
iface_to_start.extend(netcfg.keys())
elif device.startswith('eth'):
elif device.startswith('eth') or device.startswith('bond'):
if device in nethw:
iface_to_start.append(device)
else:
Expand Down
Loading