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

Allow to install an host with IPv6 management interface #2

Open
wants to merge 19 commits into
base: master
Choose a base branch
from

Conversation

benjamreis
Copy link
Contributor

Adds a screen to choose between IPv4, IPv6
and dual stack (with IPv4 as primary address type for management).

Write network conf file for IPv6 so that netinstall work in IPv6's modes

Configure the host with an IPv6 management interface

Signed-off-by: BenjiReis benjamin.reis@vates.fr

@benjamreis
Copy link
Contributor Author

Hi, any comments on this? :)

Copy link

@lindig lindig left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this looks good in general but I'm not familiar with this area; since it involves a UI change, could you include screenshots?

backend.py Outdated Show resolved Hide resolved
netutil.py Outdated
if int(el) > 255:
return False
return True
ipv4_re = '^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}'
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both regexp are constructed from the same patterns repeatedly. I'd like to see the patterns bound to names and the final regexp (which is just a string) composed from the names.

https://stackoverflow.com/questions/6930982/how-to-use-a-variable-inside-a-regular-expression

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are we not using the ipaddress library here, is it just because we don't include it in the install image?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is indeed not included. Should it be and used?
Since this code is kind of a small ip lib i assumed it was by design not included.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code doesn't use ipaddress because it long predates its introduction in Python 3.3.

We could use one of the unofficial Python 2 backports but I'd probably prefer that we move to Python 3 first and then do further improvements.

In the meantime, I think using a regex here would be OK if the repeated patterns were condensed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed the use of regex to instead use socket.inet_pton. Is that okay with you?

upgrade.py Outdated Show resolved Hide resolved
netinterface.py Outdated
@@ -32,8 +32,8 @@ class NetInterface:
Autoconf = 3

def __init__(self, mode, hwaddr, ipaddr=None, netmask=None, gateway=None,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

all of the conditionals in this make this scream out for some heavy refactoring, splitting into different classes with static/dhcp helpers

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, but I'd wager that this PR adds a new feature, to add refactoring on top of that would make it even more complex.
IMHO, a new PR (or several) should be created to refactor the code and perhaps adds some GH actions to enforce coding style and such.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typically the process is to refactor before adding the new feature and refactor after all changes to remove duplication and complexity.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just realising: a netintrface can be configured for both IPv4 and IPv6 so splitting in 2 classes is not possible.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've created a NetinterfaceV6 class, inheriting from Netinterface, to split the __init__ codes between the 2 classes.

netutil.py Outdated
if int(el) > 255:
return False
return True
ipv4_re = '^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are we not using the ipaddress library here, is it just because we don't include it in the install image?

@@ -941,7 +942,7 @@ def nsvalue(answers, id):
answers['manual-nameservers'][1].append(ns2_entry.value())
if ns3_entry.value() != '':
answers['manual-nameservers'][1].append(ns3_entry.value())
if 'net-admin-configuration' in answers and answers['net-admin-configuration'].isStatic():
if 'net-admin-configuration' in answers and answers['net-admin-configuration'].valid() and not answers['net-admin-configuration'].isDHCP():
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This check is now complex enough to warrant pulling it out as a well named method.

tui/network.py Outdated Show resolved Hide resolved
tui/network.py Outdated
dns_field.value(), vlan=vlan_value)
return RIGHT_FORWARDS, answers

def get_ipv6_configuration(nic, txt, defaults, include_dns):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

far too long and far too complicated

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure how to do better than a subfunction per screen.
TUI in code is very verbose.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'v mutualized the codes for both IPv4 and IPv6 interface configuration form

backend.py Outdated Show resolved Hide resolved
tui/network.py Outdated Show resolved Hide resolved
upgrade.py Outdated
@@ -487,6 +487,11 @@ def completeUpgrade(self, mounts, prev_install, target_disk, backup_partnum, log
nfd.write("NETWORKING_IPV6=no\n")
nfd.close()
netutil.disable_ipv6_module(mounts["root"])
else:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't you need to write NETWORKING_IPV6=yes here to sysconfig/network?

Although since sysconfig/network is preserved across upgrades, I think it would be better to change the above if statement so that it only runs if sysconfig/network doesn't exist or if it exists but doesn't contain NETWORKING_IPV6 (i.e. to handle upgrades from old installations that didn't write it out).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NETWORKING_IPV6 is written here.

upgrade.py Outdated
@@ -487,6 +487,11 @@ def completeUpgrade(self, mounts, prev_install, target_disk, backup_partnum, log
nfd.write("NETWORKING_IPV6=no\n")
nfd.close()
netutil.disable_ipv6_module(mounts["root"])
else:
# Enable IPV6
with open("%s/etc/sysctl.d/91-net-ipv6.conf" % mounts["root"], "w") as ipv6_conf:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could add this to the restore list instead.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure to understand this comment. Could you point me towards this restore list?
I assume it allows to keep a config file upon an host upgrade.
Since this would be a new file is there something else to do?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done! :)

upgrade.py Outdated
# Enable IPV6
with open("%s/etc/sysctl.d/91-net-ipv6.conf" % mounts["root"], "w") as ipv6_conf:
for i in ['all', 'default']:
ipv6_conf.write('net.ipv6.conf.%s.disable_ipv6=0\n' % i)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you need to enable ip6tables here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think so, the IPv6 is working without doing it.

@@ -811,7 +811,8 @@ def ns_callback((enabled, )):
for entry in [ns1_entry, ns2_entry, ns3_entry]:
entry.setFlags(FLAG_DISABLED, enabled)

hide_rb = answers['net-admin-configuration'].isStatic()
admin_config = answers['net-admin-configuration']
hide_rb = admin_config.valid() and not admin_config.isDHCP()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had the same comment earlier but setting nameservers shouldn't be conditional on DHCP should it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here it's to hide the radio button to select the auto DHCP nameservers so I think this is correct.
The code before my PR was already making a condition on the config being static.

tui/network.py Outdated Show resolved Hide resolved
netutil.py Outdated
if int(el) > 255:
return False
return True
ipv4_re = '^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}'
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The code doesn't use ipaddress because it long predates its introduction in Python 3.3.

We could use one of the unofficial Python 2 backports but I'd probably prefer that we move to Python 3 first and then do further improvements.

In the meantime, I think using a regex here would be OK if the repeated patterns were condensed.

@rosslagerwall
Copy link
Collaborator

Aside from the small comments above, I wonder if it would be possible to have a config option (or just a variable in constants.py) that controls whether the new configuration screens are shown? At least at this point, I don't think we'd want to expose this option to our users so it would be nice to have an easy way of hiding it.

@benjamreis
Copy link
Contributor Author

@rosslagerwall a quick question about the config option for enabling/disabling IPv6 support in the installer.
Is it still something wanted since it's now in the pipes to support IPv6 for XenServer as well AFAIK?

@benjamreis
Copy link
Contributor Author

I fixed a few things, refactored the code to mutualize as much as possible.
Remains the questions of the restore list for 91-net-ipv6.conf for which I need directions and if the param to enable the IPv6 config is still needed.

For the rest this is good to review, it has been tested.

@benjamreis
Copy link
Contributor Author

I've splitted the PR in several independant to commits to ease the review.
The Debstyle interfaces file no longer supports IPv6 since it seems to me it's dead code and I proposer a PR to remove it. I can add it back if needed.
The 91-net-ipv6.conf had been added to the restore list instead of manually rewriting it upon upgrade.

I can add a settings to enable/disable the IPv6 configuration in TUI as discussed above if this is still wanted, i'm not sure it is though so i'm waiting for your feedback.

lindig
lindig previously approved these changes Jun 13, 2023
netutil.py Outdated
return True

inet6s = filter(lambda x: x.startswith(" inet6 "), out.split("\n"))
return len(inet6s) > 1 # Not just the fe80:: address
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This condition could be moved into the filter; this code is duplicated - so would it be worth to put it into a function?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You mean having 1 filter for both IPv4 and IPv6?
The thing is, having one IPv4 is enough but having only one IPv6 is not fecause of the link local addresses.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking to filter the output such that only inet6 that are not localhost remain. That would make it more explicit which ones you are looking for rather than assuming fe80:: is in the list or results.

Copy link
Contributor Author

@benjamreis benjamreis Jun 16, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So something like:

inet6s = filter(lambda x: x.startswith("    inet6 ") and not x.startswith("    inet6 fe80::"), out.split("\n"))

?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. Is there a risk that the formatting of the input changes such that it would be better to use x.strip().find("inet6") or similar?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think so. More recent versions of ipaddr still use this format.

Comment on lines +226 to +229
if self.isStatic6() and self.ipv6_gateway and util.runCmd2(
['/usr/sbin/ndisc6', '-1', '-w', '120', self.ipv6_gateway, iface_name]
):
return False
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This code is equivalent to the arping code above but for IPv6 as arping only supports IPv4.
Please note this requires to have ndisc6 installed in host-installer image.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this reflected in the corresponding RPM spec file?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as I know your installer spec file repository is not public so I can't provide a PR to add ndisc6 which is why I commented my code for someone with access to reflect the change. :)

Signed-off-by: BenjiReis <benjamin.reis@vates.fr>
Add family specific validator as well

Signed-off-by: BenjiReis <benjamin.reis@vates.fr>
Signed-off-by: BenjiReis <benjamin.reis@vates.fr>
Signed-off-by: BenjiReis <benjamin.reis@vates.fr>
Signed-off-by: BenjiReis <benjamin.reis@vates.fr>
Only static configuration should allow a user
to fill the fields

Signed-off-by: BenjiReis <benjamin.reis@vates.fr>
In case of error return directly

Signed-off-by: BenjiReis <benjamin.reis@vates.fr>
Signed-off-by: BenjiReis <benjamin.reis@vates.fr>
Signed-off-by: BenjiReis <benjamin.reis@vates.fr>
@benjamreis benjamreis force-pushed the allow-ipv6-install branch 4 times, most recently from 1bf7d15 to 0f18e5d Compare June 19, 2023 13:17
Signed-off-by: BenjiReis <benjamin.reis@vates.fr>
IPv4 for IPv4 only
IPv6 for IPv6 only
Dual for both (IPv4 will be primary in XAPI)

Signed-off-by: BenjiReis <benjamin.reis@vates.fr>
Need to add `ndisc6` to the install.img

Signed-off-by: BenjiReis <benjamin.reis@vates.fr>
Add `isDynamic` helper to `NetInterface`

Signed-off-by: BenjiReis <benjamin.reis@vates.fr>
Add `etc/sysctl.d/91-net-ipv6.conf` in the restore list

Signed-off-by: BenjiReis <benjamin.reis@vates.fr>
The file should always be written if the fileds have
been filled.

Signed-off-by: BenjiReis <benjamin.reis@vates.fr>
Signed-off-by: BenjiReis <benjamin.reis@vates.fr>
@benjamreis
Copy link
Contributor Author

Screens of the modified TUI:
Capture d’écran du 2023-06-21 09-34-19
management-ip-family-selector

@lindig
Copy link

lindig commented Jun 21, 2023

I don't know if this is pre-existing: the blue background for the text inside the pop-up make it really busy; I don't think these input elements need to be highlighted at all or a more subtle method should be used: text colouring or bold text but not changing background colour.

@lindig
Copy link

lindig commented Jun 21, 2023

@MarkSymsCtx commented that he would have liked to see a refactoring to avoid the heavy branching introduced by IPv6. While I think this is valid, I do like the counted work on this feature.

@benjamreis
Copy link
Contributor Author

benjamreis commented Jun 21, 2023

@MarkSymsCtx commented that he would have liked to see a refactoring to avoid the heavy branching introduced by IPv6. While I think this is valid, I do like the counted work on this feature.

I have splitted the PR in several commits to discriminate the refactorings and the changes of behavior to support IPv6 so reviewing commit per commit should allow to see what's what. 👍

@benjamreis
Copy link
Contributor Author

I don't know if this is pre-existing: the blue background for the text inside the pop-up make it really busy; I don't think these input elements need to be highlighted at all or a more subtle method should be used: text colouring or bold text but not changing background colour.

AFAIK this was already like this

Copy link
Collaborator

@bernhardkaindl bernhardkaindl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I reviewed the "backend" changes. I did not review the frontend changes, but I guess that IPv6 for xsconsole should be merged/integrated first and then both can be tested together.

I'll be away until about 16 August.

Not reviewed: tui/network.py

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants