diff --git a/ros2doctor/package.xml b/ros2doctor/package.xml
index 90f3b5810..47101106f 100644
--- a/ros2doctor/package.xml
+++ b/ros2doctor/package.xml
@@ -9,7 +9,7 @@
ros2cli
- python3-numpy
+ ifcfg_vendor
python3-rosdistro-modules
ament_copyright
diff --git a/ros2doctor/ros2doctor/api/format.py b/ros2doctor/ros2doctor/api/format.py
new file mode 100644
index 000000000..7241fca7b
--- /dev/null
+++ b/ros2doctor/ros2doctor/api/format.py
@@ -0,0 +1,20 @@
+# Copyright 2019 Open Source Robotics Foundation, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+
+def print_term(k, v):
+ """Print term only if it exists."""
+ if v:
+ # TODO(clairewang): 20 padding needs to be dynamically set
+ print('{:20}: {}'.format(k, v))
diff --git a/ros2doctor/ros2doctor/api/network.py b/ros2doctor/ros2doctor/api/network.py
new file mode 100644
index 000000000..682671fc6
--- /dev/null
+++ b/ros2doctor/ros2doctor/api/network.py
@@ -0,0 +1,60 @@
+# Copyright 2019 Open Source Robotics Foundation, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import os
+import sys
+
+import ifcfg
+
+from ros2doctor.api.format import print_term
+
+
+def _is_unix_like_platform():
+ """Return True if conforms to UNIX/POSIX-style APIs."""
+ return os.name == 'posix'
+
+
+def check_network_config_helper():
+ """Check if loopback and multicast IP addresses are found."""
+ has_loopback, has_non_loopback, has_multicast = False, False, False
+ for name, iface in ifcfg.interfaces().items():
+ flags = iface.get('flags')
+ if 'LOOPBACK' in flags:
+ has_loopback = True
+ else:
+ has_non_loopback = True
+ if 'MULTICAST' in flags:
+ has_multicast = True
+ return has_loopback, has_non_loopback, has_multicast
+
+
+def check_network_config():
+ """Conduct network checks and output error/warning messages."""
+ has_loopback, has_non_loopback, has_multicast = check_network_config_helper()
+ if not has_loopback:
+ sys.stderr.write('ERROR: No loopback IP address is found.\n')
+ if not has_non_loopback:
+ sys.stderr.write('WARNING: Only loopback IP address is found.\n')
+ if not has_multicast:
+ sys.stderr.write('WARNING: No multicast IP address is found.\n')
+ return has_loopback and has_non_loopback and has_multicast
+
+
+def print_network():
+ """Print all system and ROS network information."""
+ print('NETWORK CONFIGURATION')
+ for name, iface in ifcfg.interfaces().items():
+ for k, v in iface.items():
+ print_term(k, v)
+ print('\n')
diff --git a/ros2doctor/ros2doctor/api/platform.py b/ros2doctor/ros2doctor/api/platform.py
index 02d879fb7..cd31b5a53 100644
--- a/ros2doctor/ros2doctor/api/platform.py
+++ b/ros2doctor/ros2doctor/api/platform.py
@@ -16,6 +16,8 @@
import platform
import sys
+from ros2doctor.api.format import print_term
+
import rosdistro
@@ -24,37 +26,38 @@ def print_platform_info():
platform_name = platform.system()
# platform info
print('PLATFORM INFORMATION')
- print('system : ', platform_name)
- print('Platform Info : ', platform.platform())
+ print_term('system', platform_name)
+ print_term('platform info', platform.platform())
if platform_name == 'Darwin':
- print('Mac OS version : ', platform.mac_ver())
- print('release : ', platform.release())
- print('processor : ', platform.processor())
+ print_term('mac OS version', platform.mac_ver())
+ print_term('release', platform.release())
+ print_term('processor', platform.processor())
# python info
print('PYTHON INFORMATION')
- print('version : ', platform.python_version())
- print('compiler : ', platform.python_compiler())
- print('build : ', platform.python_build())
+ print_term('version', platform.python_version())
+ print_term('compiler', platform.python_compiler())
+ print_term('build', platform.python_build())
+ print('\n')
def check_platform_helper():
"""Check ROS_DISTRO related environment variables and distribution name."""
distro_name = os.environ.get('ROS_DISTRO')
if not distro_name:
- sys.stderr.write('WARNING: ROS_DISTRO is not set.')
+ sys.stderr.write('WARNING: ROS_DISTRO is not set.\n')
return
else:
distro_name = distro_name.lower()
u = rosdistro.get_index_url()
if not u:
- sys.stderr.write('WARNING: Unable to access ROSDISTRO_INDEX_URL\
- or DEFAULT_INDEX_URL.')
+ sys.stderr.write('WARNING: Unable to access ROSDISTRO_INDEX_URL '
+ 'or DEFAULT_INDEX_URL.\n')
return
i = rosdistro.get_index(u)
distro_info = i.distributions.get(distro_name)
if not distro_info:
- sys.stderr.write("WARNING: Distribution name '%s' is not found" % distro_name)
+ sys.stderr.write("WARNING: Distribution name '%s' is not found\n" % distro_name)
return
distro_data = rosdistro.get_distribution(i, distro_name).get_data()
return distro_name, distro_info, distro_data
@@ -68,10 +71,11 @@ def print_ros2_info():
distro_name, distro_info, distro_data = distros
print('ROS INFORMATION')
- print('distribution name : ', distro_name)
- print('distribution type : ', distro_info.get('distribution_type'))
- print('distribution status : ', distro_info.get('distribution_status'))
- print('release platforms : ', distro_data.get('release_platforms'))
+ print_term('distribution name', distro_name)
+ print_term('distribution type', distro_info.get('distribution_type'))
+ print_term('distribution status', distro_info.get('distribution_status'))
+ print_term('release platforms', distro_data.get('release_platforms'))
+ print('\n')
def check_platform():
@@ -84,15 +88,13 @@ def check_platform():
# check distro status
if distro_info.get('distribution_status') == 'prerelease':
- sys.stderr.write('WARNING: Distribution is not fully supported or tested.\
- To get more stable features,\
- Download a stable version at\
- https://index.ros.org/doc/ros2/Installation/')
+ sys.stderr.write('WARNING: Distribution is not fully supported or tested. '
+ 'To get more stable features, download a stable version at '
+ 'https://index.ros.org/doc/ros2/Installation/\n')
elif distro_info.get('distribution_status') == 'end-of-life':
- sys.stderr.write('WARNING: Distribution is no longer supported or deprecated.\
- To get the latest features,\
- Download the latest version at\
- https://index.ros.org/doc/ros2/Installation/')
+ sys.stderr.write('WARNING: Distribution is no longer supported or deprecated. '
+ 'To get the latest features, download the latest version at '
+ 'https://index.ros.org/doc/ros2/Installation/')
else:
passed = True
return passed
diff --git a/ros2doctor/ros2doctor/command/doctor.py b/ros2doctor/ros2doctor/command/doctor.py
index 43f01b3e8..3cbf00551 100644
--- a/ros2doctor/ros2doctor/command/doctor.py
+++ b/ros2doctor/ros2doctor/command/doctor.py
@@ -41,6 +41,6 @@ def main(self, *, parser, args):
class WtfCommand(DoctorCommand):
- """Add `wtf` as alias to `doctor`."""
+ """Use `wtf` as alias to `doctor`."""
pass
diff --git a/ros2doctor/setup.py b/ros2doctor/setup.py
index 41efa6b03..200842c48 100644
--- a/ros2doctor/setup.py
+++ b/ros2doctor/setup.py
@@ -32,10 +32,12 @@
],
'ros2doctor.checks': [
'check_platform = ros2doctor.api.platform:check_platform',
+ 'check_network_config = ros2doctor.api.network:check_network_config',
],
'ros2doctor.report': [
'report_platform = ros2doctor.api.platform:print_platform_info',
'report_ros_distro = ros2doctor.api.platform:print_ros2_info',
+ 'report_network_config = ros2doctor.api.network:print_network',
],
}
)