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 #37

Open
wants to merge 23 commits into
base: master
Choose a base branch
from
Open
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
595ace0
init/configureNetworking: improve readability
ydirson Jan 11, 2023
09d6f41
writeRHStyleInterface: split writeIface()
benjamreis Jan 9, 2023
a9c2d68
writeIface: use "with" statement
ydirson Jan 17, 2023
89b419e
writeIface: split writing IP configuration for reuse
ydirson Jan 17, 2023
ae86cfa
ifup: remove extraneous assert
ydirson Jan 12, 2023
249e336
getNetifList: remove eth hardcoding in interface sorting
ydirson Jan 12, 2023
2d982af
netutil.scanConfiguration: rework for extensibility
ydirson Jan 12, 2023
127f63e
doc: make it clear where we expect URLs
ydirson Jan 11, 2023
99ef0a9
doc: fix description of --network_device default
ydirson Jan 11, 2023
34c28ac
doc: make --network_device no less visible than its deprecated counte…
ydirson Jan 11, 2023
9fffa2d
net*: cleanups around vlan-interface
ydirson Jan 17, 2023
04b4413
[CHERRYPICKED] NetInterface: remove dead code
ydirson Jan 13, 2023
3b16aad
answerfile: improve handling of admin-interface selection (xenserver#33)
ydirson Jan 13, 2023
90fbfba
NetInterface: pass a NIC not just a hwaddr to ctor
ydirson Jan 20, 2023
595e17d
NIC,NetInterface: add support for bonding interfaces
ydirson Jan 20, 2023
ced0ea1
init: add support for LACP bonding in --network_device (xcp-ng/xcp#350)
ydirson Jan 13, 2023
69a5a43
netutil.scanConfiguration: allow reuse of commandline config
ydirson Jan 12, 2023
92d7c71
configureNetworking: write bond configuration to firstboot.d
benjamreis Jan 13, 2023
7191d0d
tui.network: make lentry() and iface_details() more accessible
benjamreis Jan 9, 2023
f8b2565
tui: don't hide NIC selection when there is only one
ydirson Jan 13, 2023
5926670
tui: let user configure a bonding interface interactively
ydirson Jan 13, 2023
5028d8b
answerfile: remove useless statement
ydirson Jan 18, 2023
e3d5504
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 @@ -1514,6 +1514,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 @@ -198,6 +198,14 @@ Format of 'source' and 'driver-source'
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 @@ -126,29 +126,37 @@ Startup
Installer
---------

--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