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

Supporting launching MAPDL from WSL #2324

Merged
merged 19 commits into from
Sep 12, 2023
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
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
88 changes: 71 additions & 17 deletions doc/source/getting_started/wsl.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,37 +15,42 @@
This page walk you through the installation of WSL on Windows and then
show how to use it together with MAPDL, PyMAPDL, and `Docker <https://www.docker.com/>`_.

.. caution::
This approach hasn't been fully tested with a VPN connection. If you
experience any problems connecting WSL to the internet, try to
disconnect from the VPN.

.. note::
Updating this guide is doing a best effort basis. Due to WSL being under constant
development this guide might be outdated without any notice.
If you find any issue or problem, feel free to
`open an issue in the GitHub repository <pymapdl_issues>`_.
germa89 marked this conversation as resolved.
Show resolved Hide resolved

Run PyMAPDL on WSL
##################
There are two versions of WSL: WSL1 and WSL2. Because WSL2 provides many improvements
over WSL1, you should upgrade to and use WSL2.

Install WSL
============
###########

There are two versions of WSL: WSL1 and WSL2. Because WSL2 provides many improvements
over WSL1, you should upgrade to and use WSL2.

Install WSL by following Microsoft's directions at
`Microsoft: Install WSL <install_wsl_microsoft_>`_.

Install the CentOS7 WSL distribution
====================================
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

When working with PyAnsys libraries, you should use the CentOS7 WSL distribution.

You can install this distribution using an unofficial WSL distribution from
`CentOS-WSL <gh_centos_wsl_1_>`_ package or the
`CentOS WSL <gh_centos_wsl_2_>`_ package.

Optionally, you can try Ubuntu, but it has not been tested yet in the context of WSL.

Using Ubuntu WSL distribution

Check warning on line 45 in doc/source/getting_started/wsl.rst

View workflow job for this annotation

GitHub Actions / vale

[vale] doc/source/getting_started/wsl.rst#L45

[Google.Headings] 'Using Ubuntu WSL distribution' should use sentence-style capitalization.
Raw output
{"message": "[Google.Headings] 'Using Ubuntu WSL distribution' should use sentence-style capitalization.", "location": {"path": "doc/source/getting_started/wsl.rst", "range": {"start": {"line": 45, "column": 1}}}, "severity": "WARNING"}
germa89 marked this conversation as resolved.
Show resolved Hide resolved
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
germa89 marked this conversation as resolved.
Show resolved Hide resolved

Ubuntu is a supported operative system for Ansys products. However it has not been
tested yet in the context of WSL. We recommend to proceed with caution.

Check warning on line 49 in doc/source/getting_started/wsl.rst

View workflow job for this annotation

GitHub Actions / vale

[vale] doc/source/getting_started/wsl.rst#L49

[Google.We] Try to avoid using first-person plural like 'We'.
Raw output
{"message": "[Google.We] Try to avoid using first-person plural like 'We'.", "location": {"path": "doc/source/getting_started/wsl.rst", "range": {"start": {"line": 49, "column": 35}}}, "severity": "WARNING"}
germa89 marked this conversation as resolved.
Show resolved Hide resolved

Install Ansys products in WSL CentOS 7
======================================

Install Ansys products in WSL
#############################

Prerequisites
~~~~~~~~~~~~~
Expand Down Expand Up @@ -119,7 +124,7 @@


Post-installation setup
=======================
#######################

Open ports for license server communication
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Expand Down Expand Up @@ -187,7 +192,7 @@
You can add the next lines to your WSL ``~/.bashrc`` file to create an
environment variable with this IP address:

.. _ref_bash_win_ip:

Check failure on line 195 in doc/source/getting_started/wsl.rst

View workflow job for this annotation

GitHub Actions / vale

[vale] doc/source/getting_started/wsl.rst#L195

[Vale.Spelling] Did you really mean 'ip'?
Raw output
{"message": "[Vale.Spelling] Did you really mean 'ip'?", "location": {"path": "doc/source/getting_started/wsl.rst", "range": {"start": {"line": 195, "column": 18}}}, "severity": "ERROR"}

.. code:: console

Expand All @@ -196,7 +201,7 @@


Launch MAPDL in WSL
===================
###################

To launch MAPDL in WSL, you must launch MAPDL process.
germa89 marked this conversation as resolved.
Show resolved Hide resolved
An example follows.
Expand All @@ -213,8 +218,48 @@
/ansys_inc/v222/ansys/bin/ansys222 -grpc -dir /tmp/ansys_jobs/myjob


Launch MAPDL in the Windows host OS
###################################

You can launch an instance of MAPDL using the MAPDL installation from the
Windows host OS.
To do that, you can just run the following code.
germa89 marked this conversation as resolved.
Show resolved Hide resolved

.. code:: python

from ansys.mapdl.core import launch_mapdl

mapdl = launch_mapdl(
exec_file="/mnt/c/Program Files/ANSYS Inc/v231/ANSYS/bin/winx64/ANSYS231.exe",
)

As mentioned in `Open ports for license server communication`_, the Windows host OS
and WSL are connected with a virtual network where they have both different IPs.

Check failure on line 237 in doc/source/getting_started/wsl.rst

View workflow job for this annotation

GitHub Actions / vale

[vale] doc/source/getting_started/wsl.rst#L237

[Vale.Spelling] Did you really mean 'IPs'?
Raw output
{"message": "[Vale.Spelling] Did you really mean 'IPs'?", "location": {"path": "doc/source/getting_started/wsl.rst", "range": {"start": {"line": 237, "column": 77}}}, "severity": "ERROR"}
germa89 marked this conversation as resolved.
Show resolved Hide resolved
PyMAPDL does its best to detect the IP of the Windows host OS. For that, it parses
the output given by the command `ip route` in WSL.
However, if you find that this IP is not correct, you can specify the IP to connect
to using:
germa89 marked this conversation as resolved.
Show resolved Hide resolved

.. code:: python

from ansys.mapdl.core import launch_mapdl

mapdl = launch_mapdl(
exec_file="/mnt/c/Program Files/ANSYS Inc/v231/ANSYS/bin/winx64/ANSYS231.exe",
ip="172.23.112.1",
)

You might need to disable the Microsoft Firewall completely or at least

Check warning on line 252 in doc/source/getting_started/wsl.rst

View workflow job for this annotation

GitHub Actions / vale

[vale] doc/source/getting_started/wsl.rst#L252

[Google.WordList] Use 'turn off' or 'off' instead of 'disable'.
Raw output
{"message": "[Google.WordList] Use 'turn off' or 'off' instead of 'disable'.", "location": {"path": "doc/source/getting_started/wsl.rst", "range": {"start": {"line": 252, "column": 19}}}, "severity": "WARNING"}
germa89 marked this conversation as resolved.
Show resolved Hide resolved
germa89 marked this conversation as resolved.
Show resolved Hide resolved
for the WSL network connection.
To do so, follow `this link <disable_firewall_on_wsl_ethernet_section_>`_.
germa89 marked this conversation as resolved.
Show resolved Hide resolved


For more information and troubleshooting visit `this issue <wsl_launching_mapdl_>`_
or open a new issue in the `GitHub repository <pymapdl_issues_>`_.
germa89 marked this conversation as resolved.
Show resolved Hide resolved


Connect to an MAPDL instance running in WSL
===========================================
###########################################

To connect to the WSL instance that is running the MAPDL instance,
you need to specify the IP address of the WSL instance:
Expand All @@ -225,6 +270,7 @@
>>> mapdl = Mapdl(ip="127.0.0.1", port=50053)



Additional information
######################

Expand Down Expand Up @@ -430,12 +476,20 @@
yum install xorg-x11-server-Xvfb


.. note::
If you want to replicate the CICD behaviour or develop from inside a docker container,
it is highly recommended to use Ubuntu as base operative system. You can find instructions
to `create your own MAPDL Ubuntu container in here <ref_make_container_>`_ and how to use it to
`develop on containers in here <ref_devcontainer_>`_.
germa89 marked this conversation as resolved.
Show resolved Hide resolved

Notes
=====

- PyMAPDL only works for shared-memory parallel (SMP) when running on WSL. This
is why the flag ``-smp`` should be included.

- Because there are some incompatibilities between VPN and INTEL MPI, use the
flag ``-mpi msmpi`` when calling MAPDL.
flag ``-mpi msmpi`` when calling MAPDL. This guide has not been written or tested
under VPN. If you are experiencing issues connecting to the Windows host maachine,
your license server or an MAPDL instance please disconnect the VPN.
germa89 marked this conversation as resolved.
Show resolved Hide resolved

1 change: 1 addition & 0 deletions doc/source/links.rst
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@
.. _pymapdl_docker_compose_license_server: https://github.com/ansys/pymapdl/blob/main/docker/docker-compose.license_server.yml
.. _pymapdl_discussion_differences_mapdl_pymapdl: https://github.com/ansys/pymapdl-reader/issues/185
.. _cartpole_example_notebook: https://cartpole.mapdl.docs.pyansys.com/ml-rl-notebook.html
.. _wsl_launching_mapdl: https://github.com/ansys/pymapdl/issues/2315

.. #Python
.. _using_venv: https://docs.python.org/3/library/venv.html
Expand Down
64 changes: 59 additions & 5 deletions src/ansys/mapdl/core/launcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,18 @@
CONFIG_FILE = os.path.join(SETTINGS_DIR, "config.txt")
ALLOWABLE_MODES = ["corba", "console", "grpc"]

ON_WSL = os.name == "posix" and (
bool(os.environ.get("WSL_DISTRO_NAME", None))
or bool(os.environ.get("WSL_INTEROP", None))
)

if ON_WSL:
LOG.info("On WSL: Running on WSL detected.")

Check warning on line 69 in src/ansys/mapdl/core/launcher.py

View check run for this annotation

Codecov / codecov/patch

src/ansys/mapdl/core/launcher.py#L69

Added line #L69 was not covered by tests

LOCALHOST = "127.0.0.1"
MAPDL_DEFAULT_PORT = 50052

INTEL_MSG = """Due to incompatibilities between 'DMP', Windows and VPN connections,
INTEL_MSG = """Due to incompatibilities between this MAPDL version, Windows and VPN connections,
germa89 marked this conversation as resolved.
Show resolved Hide resolved
the flat '-mpi INTELMPI' is overwritten by '-mpi msmpi'.

If you still want to use 'INTEL', set:
Expand Down Expand Up @@ -524,7 +531,7 @@
LOG.debug("Checking file error is created")
_check_file_error_created(run_location, timeout)

if os.name == "posix":
if os.name == "posix" and not ON_WSL:
LOG.debug("Checking if gRPC server is alive.")
_check_server_is_alive(stdout_queue, run_location, timeout)

Expand Down Expand Up @@ -1353,12 +1360,31 @@
raise ValueError(f"The following arguments are not recognaised: {ms_}")
germa89 marked this conversation as resolved.
Show resolved Hide resolved

if ip is None:
ip = os.environ.get("PYMAPDL_IP", LOCALHOST)
ip = os.environ.get("PYMAPDL_IP", None)

if not ip and ON_WSL:
ip = _get_windows_host_ip()
if ip:
LOG.debug(

Check warning on line 1368 in src/ansys/mapdl/core/launcher.py

View check run for this annotation

Codecov / codecov/patch

src/ansys/mapdl/core/launcher.py#L1366-L1368

Added lines #L1366 - L1368 were not covered by tests
f"On WSL: Using the following IP for the Windows OS host: {ip}"
germa89 marked this conversation as resolved.
Show resolved Hide resolved
)
else:
LOG.debug("PyMAPDL could not find the IP of the Windows Host Machine.")

Check warning on line 1372 in src/ansys/mapdl/core/launcher.py

View check run for this annotation

Codecov / codecov/patch

src/ansys/mapdl/core/launcher.py#L1372

Added line #L1372 was not covered by tests
germa89 marked this conversation as resolved.
Show resolved Hide resolved

if not ip:
LOG.debug(f"No IP supplied, using default IP: {LOCALHOST}")
germa89 marked this conversation as resolved.
Show resolved Hide resolved
ip = LOCALHOST

else:
LOG.debug(
"Because ``PYMAPDL_IP is not None, an attempt is made to connect to a remote session. ('START_INSTANCE' is set to False.`)"
"Because ``PYMAPDL_IP is not None, an attempt is made to connect to"
germa89 marked this conversation as resolved.
Show resolved Hide resolved
" a remote session. ('START_INSTANCE' is set to False.`)"
germa89 marked this conversation as resolved.
Show resolved Hide resolved
)
start_instance = False
if not ON_WSL:
germa89 marked this conversation as resolved.
Show resolved Hide resolved
start_instance = False

Check warning on line 1384 in src/ansys/mapdl/core/launcher.py

View check run for this annotation

Codecov / codecov/patch

src/ansys/mapdl/core/launcher.py#L1383-L1384

Added lines #L1383 - L1384 were not covered by tests
else:
LOG.debug("On WSL: Allowing 'start_instance' and 'ip' arguments together.")

Check warning on line 1386 in src/ansys/mapdl/core/launcher.py

View check run for this annotation

Codecov / codecov/patch

src/ansys/mapdl/core/launcher.py#L1386

Added line #L1386 was not covered by tests

ip = socket.gethostbyname(ip) # Converting ip or hostname to ip

check_valid_ip(ip) # double check
Expand Down Expand Up @@ -1822,3 +1848,31 @@
)

return version


def _get_windows_host_ip():
output = _run_ip_route()
if output:
return _parse_ip_route(output)

Check warning on line 1856 in src/ansys/mapdl/core/launcher.py

View check run for this annotation

Codecov / codecov/patch

src/ansys/mapdl/core/launcher.py#L1854-L1856

Added lines #L1854 - L1856 were not covered by tests


def _run_ip_route():
from subprocess import run

Check warning on line 1860 in src/ansys/mapdl/core/launcher.py

View check run for this annotation

Codecov / codecov/patch

src/ansys/mapdl/core/launcher.py#L1860

Added line #L1860 was not covered by tests

try:
p = run(["ip", "route"], capture_output=True)
except Exception:
LOG.debug(

Check warning on line 1865 in src/ansys/mapdl/core/launcher.py

View check run for this annotation

Codecov / codecov/patch

src/ansys/mapdl/core/launcher.py#L1862-L1865

Added lines #L1862 - L1865 were not covered by tests
"Detecting the IP of the host Windows machine requires to be able to execute the command 'ip route'."
germa89 marked this conversation as resolved.
Show resolved Hide resolved
)
return None

Check warning on line 1868 in src/ansys/mapdl/core/launcher.py

View check run for this annotation

Codecov / codecov/patch

src/ansys/mapdl/core/launcher.py#L1868

Added line #L1868 was not covered by tests

if p and p.stdout and isinstance(p.stdout, bytes):
return p.stdout.decode()

Check warning on line 1871 in src/ansys/mapdl/core/launcher.py

View check run for this annotation

Codecov / codecov/patch

src/ansys/mapdl/core/launcher.py#L1870-L1871

Added lines #L1870 - L1871 were not covered by tests


def _parse_ip_route(output):
match = re.findall(r"(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}).*", output)

if match:
return match[0]
14 changes: 14 additions & 0 deletions tests/test_launcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
_check_license_argument,
_force_smp_student_version,
_is_ubuntu,
_parse_ip_route,
_validate_MPI,
_verify_version,
find_ansys,
Expand Down Expand Up @@ -410,3 +411,16 @@ def test_launch_mapdl_non_recognaised_arguments():
def test_mapdl_non_recognaised_arguments():
with pytest.raises(ValueError, match="my_fake_argument"):
pymapdl.Mapdl(my_fake_argument="my_fake_value")


def test__parse_ip_route():
output = """default via 172.25.192.1 dev eth0 proto kernel <<<=== this
172.25.192.0/20 dev eth0 proto kernel scope link src 172.25.195.101 <<<=== not this"""

assert "172.25.192.1" == _parse_ip_route(output)

output = """
default via 172.23.112.1 dev eth0 proto kernel
172.23.112.0/20 dev eth0 proto kernel scope link src 172.23.121.145"""

assert "172.23.112.1" == _parse_ip_route(output)
Loading