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

Fix /proc/net/route requirement that causes errors on FreeBSD #1638

Merged
merged 31 commits into from
Oct 23, 2019

Conversation

kawaiivoldemort
Copy link
Contributor

@kawaiivoldemort kawaiivoldemort commented Sep 18, 2019

Description

This is a fix for Issue #1479).

What it does is:

  • Instead of searching the linux specific /proc/net/route in wireserver_route_exists in dhcp.py, it calls the osutil.get_list_of_routes API and checks if the route destination matches the KNOWN_WIRESERVER_IP
  • It then defines various route related functions in osutil/freebsd.py so that this works on FreeBSD
  • One of these functions parses netstat -rn and creates RouteEntry objects that look similar enough to the Linux ones for the rest of the code to work

Issue #1479


PR information

  • The title of the PR is clear and informative.
  • There are a small number of commits, each of which has an informative message. This means that previously merged commits do not appear in the history of the PR. For information on cleaning up the commits in your pull request, see this page.
  • Except for special cases involving multiple contributors, the PR is started from a fork of the main repository, not a branch.
  • If applicable, the PR references the bug/issue that it fixes in the description.
  • New Unit tests were added for the changes made and Travis.CI is passing.

Quality of Code and Contribution Guidelines


This change is Reviewable

@msftclas
Copy link

msftclas commented Sep 18, 2019

CLA assistant check
All CLA requirements met.

@kawaiivoldemort kawaiivoldemort changed the title Fix /proc/net/route requirement on FreeBSD (to fix https://github.com/Azure/WALinuxAgent/issues/1479) Fix /proc/net/route requirement that causes errors on FreeBSD Sep 18, 2019
@codecov
Copy link

codecov bot commented Sep 19, 2019

Codecov Report

❗ No coverage uploaded for pull request base (develop@0105f5f). Click here to learn what that means.
The diff coverage is 65.78%.

Impacted file tree graph

@@            Coverage Diff             @@
##             develop    #1638   +/-   ##
==========================================
  Coverage           ?   67.19%           
==========================================
  Files              ?       80           
  Lines              ?    11440           
  Branches           ?     1608           
==========================================
  Hits               ?     7687           
  Misses             ?     3420           
  Partials           ?      333
Impacted Files Coverage Δ
azurelinuxagent/common/dhcp.py 30.37% <100%> (ø)
azurelinuxagent/common/osutil/freebsd.py 42.67% <65.33%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 0105f5f...08ba686. Read the comment docs.

Nachiketa Ramesh added 4 commits September 19, 2019 17:20
- Moved route conversion code from read_route_table
to build_route_list

- Fixed some typos

- Fixed some routes being ignored
@kawaiivoldemort
Copy link
Contributor Author

kawaiivoldemort commented Sep 19, 2019

1ee6e01 is just a squish of all the other commits. It has all the changes.

Copy link
Contributor

@larohra larohra left a comment

Choose a reason for hiding this comment

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

Thank you for your contribution @onenachi. Could you please add some test cases for the changes in freebsd.py file? We have a test file \tests\common\osutil\test_freebsd.py where you can add the specific tests for your changes to improve the code coverage.

I've also initiated a run from our automated end-to-end testing just to ensure the changes are not breaking anything.

Apart from that the changes look good to me.

# Add the route
linux_style_route_file.append("{0}\t{1}\t{2}\t{3}\t{4}\t{5}\t{6}\t{7}\t{8}\t{9}\t{10}".format(
netif, dest, gw, flags, refcount, use, metric, mask, mtu, window, irtt))
return linux_style_route_file
Copy link
Contributor

Choose a reason for hiding this comment

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

The original implementation of this function handles all errors in function and doesn't propagate any exception further.

 try:
            with open('/proc/net/route') as routing_table:
                return list(map(str.strip, routing_table.readlines()))
        except Exception as e:
            logger.error("Cannot read route table [{0}]", ustr(e))

        return []

After you refactor this function, could you please ensure that the read_route_table function doesn't raise any exception so as to not break the agent

Copy link
Contributor Author

@kawaiivoldemort kawaiivoldemort Oct 4, 2019

Choose a reason for hiding this comment

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

done with 515b672

@@ -29,6 +31,103 @@ def tearDown(self):
def test_get_dhcp_pid_should_return_a_list_of_pids(self):
osutil_get_dhcp_pid_should_return_a_list_of_pids(self, FreeBSDOSUtil())

def test_empty_proc_net_route(self):
Copy link
Contributor

Choose a reason for hiding this comment

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

Thank you for adding the tests 👍

Copy link
Contributor

@larohra larohra left a comment

Choose a reason for hiding this comment

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

Left some comments around refactoring and exception handling.

return linux_style_route_file
netstat_output = netstat_output[3:]
# Parse the Netstat -RN header line
n_columns = 0
Copy link
Contributor

Choose a reason for hiding this comment

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

Could you add a comment with a sample output of netstat -rn is to make it easier for the reader to understand the parsing logic

Copy link
Contributor Author

@kawaiivoldemort kawaiivoldemort Oct 7, 2019

Choose a reason for hiding this comment

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

Exmples added as requested in 10819af


:return: Entries in the route priority table from `netstat -rn`
:rtype: list(str)
"""
Copy link
Contributor

Choose a reason for hiding this comment

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

Could you please add an example of how the netstat -rn output differs with the linux based proc/net/route header just to make sure what this function is parsing

Copy link
Contributor Author

@kawaiivoldemort kawaiivoldemort Oct 7, 2019

Choose a reason for hiding this comment

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

Exmples added as requested in 10819af

Nachiketa Ramesh added 2 commits October 7, 2019 16:58
- refactored it into meaningful subfunctions
- modified the function documentation to make it more understandable
- added examples to the function documentation
Copy link
Contributor

@larohra larohra left a comment

Choose a reason for hiding this comment

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

@narrieta this LGTM, can you please take a look

if os.path.exists(route_file) and \
KNOWN_WIRESERVER_IP_ENTRY in open(route_file).read():
route_table = self.osutil.read_route_table()
if any([(KNOWN_WIRESERVER_IP_ENTRY in route) for route in route_table]):
Copy link
Member

Choose a reason for hiding this comment

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

In the original code there was a check for exists(route_file); if it was false, we would output a warning.
In the new code this would be reported as an error.

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 how to work around this. read_route_table will log an error by default and then return an empty list if /proc/net/route doesn't exist.

The only thing it guarantees is not to raise an exception.

Im not sure changing that function would be appropriate. I do think using that function would be appropriate since checking route is clearly a platform specific task.

Copy link
Contributor Author

@kawaiivoldemort kawaiivoldemort Oct 9, 2019

Choose a reason for hiding this comment

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

I also do think that this is an edge case and not really an issue as it will only log an error on systems without /proc/net/route (non Linux systems) which have not overridden that function with their own osutil (so now, neither Linux nor FreeBSD).

Copy link
Member

Choose a reason for hiding this comment

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

ok

Copy link
Member

@narrieta narrieta left a comment

Choose a reason for hiding this comment

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

requestion 1 small change, otherwise looks good

:rtype: list(dict)
"""
cmd = "netstat -rn -f inet"
ret, output = shellutil.run_get_output(cmd)
Copy link
Member

Choose a reason for hiding this comment

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

we are deprecating shellutil.run_get_output in favor of shellutil.run_command, could you change this?

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 with a0112e2 and 72bddb7

:rtype: list(dict)
"""
cmd = "netstat -rn -f inet"
output = shellutil.run_command(cmd, log_error=True)
Copy link
Member

@narrieta narrieta Oct 16, 2019

Choose a reason for hiding this comment

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

thank you for the update.

run_command sets shell=False when invoking subprocess.Popen, so the command needs to be passed as an array of strings; see, for example https://github.com/Azure/WALinuxAgent/blob/develop/azurelinuxagent/common/utils/cryptutil.py#L55

Also, please be sure to tests this end-to-end on your side. Our test infrastructure does not validate FreeBSD.

Thanks

Copy link
Contributor Author

@kawaiivoldemort kawaiivoldemort Oct 21, 2019

Choose a reason for hiding this comment

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

Fixed in 08ba686

Tested in FreeBSD 11.2 on Azure:
image
Route table is read successfully.

Sorry about that.

@narrieta
Copy link
Member

LGTM; running automation - will approve and merge after that

@narrieta
Copy link
Member

Automation OK

Copy link
Member

@narrieta narrieta left a comment

Choose a reason for hiding this comment

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

Thank you!

@narrieta narrieta merged commit f2af566 into Azure:develop Oct 23, 2019
uqs pushed a commit to freebsd/freebsd-ports that referenced this pull request Nov 13, 2019
  Azure/WALinuxAgent#1638
- Update WWW to where the code exists
- Switch to use Python 3 to match the ports' default to avoid some subprocess
  invoking issues

Approved by:	Wei Hu <weh@microsoft.com> (maintainer, implicitly)
Sponsored by:	The FreeBSD Foundation


git-svn-id: svn+ssh://svn.freebsd.org/ports/head@517374 35697150-7ecd-e111-bb59-0022644237b5
uqs pushed a commit to freebsd/freebsd-ports that referenced this pull request Nov 13, 2019
  Azure/WALinuxAgent#1638
- Update WWW to where the code exists
- Switch to use Python 3 to match the ports' default to avoid some subprocess
  invoking issues

Approved by:	Wei Hu <weh@microsoft.com> (maintainer, implicitly)
Sponsored by:	The FreeBSD Foundation
Jehops pushed a commit to Jehops/freebsd-ports-legacy that referenced this pull request Nov 13, 2019
  Azure/WALinuxAgent#1638
- Update WWW to where the code exists
- Switch to use Python 3 to match the ports' default to avoid some subprocess
  invoking issues

Approved by:	Wei Hu <weh@microsoft.com> (maintainer, implicitly)
Sponsored by:	The FreeBSD Foundation


git-svn-id: svn+ssh://svn.freebsd.org/ports/head@517374 35697150-7ecd-e111-bb59-0022644237b5
ericbsd pushed a commit to ghostbsd/ghostbsd-ports that referenced this pull request Nov 20, 2019
  Azure/WALinuxAgent#1638
- Update WWW to where the code exists
- Switch to use Python 3 to match the ports' default to avoid some subprocess
  invoking issues

Approved by:	Wei Hu <weh@microsoft.com> (maintainer, implicitly)
Sponsored by:	The FreeBSD Foundation
uqs pushed a commit to freebsd/freebsd-ports that referenced this pull request Dec 4, 2019
- Update to 2.2.45 (pre-release) to pull in the requried fix
  Azure/WALinuxAgent#1638
- Update WWW to where the code exists
- Switch to use Python 3 to match the ports' default to avoid some subprocess
  invoking issues

Approved by:	Wei Hu <weh@microsoft.com> (maintainer, implicitly)
Sponsored by:	The FreeBSD Foundation

Approved by:	ports-secteam (blanket(s): bugfix release)
uqs pushed a commit to freebsd/freebsd-ports that referenced this pull request Apr 1, 2021
- Update to 2.2.45 (pre-release) to pull in the requried fix
  Azure/WALinuxAgent#1638
- Update WWW to where the code exists
- Switch to use Python 3 to match the ports' default to avoid some subprocess
  invoking issues

Approved by:	Wei Hu <weh@microsoft.com> (maintainer, implicitly)
Sponsored by:	The FreeBSD Foundation

Approved by:	ports-secteam (blanket(s): bugfix release)
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.

4 participants