Skip to content

Commit 56856dd

Browse files
germa89akaszynski
andauthored
Feat/adding license selection to launcher (#659)
* Added dict with license names and descriptions. * Added license_type functionality * Added tests for the 'license_type' optional keyword. * Added mapping in 'license_type' keyword to being able to use the license description. Added test to reflect that new capability. * Removed unused import. * Update ansys/mapdl/core/launcher.py Using rst style instead of markdown for docstrings. Co-authored-by: Alex Kaszynski <[email protected]> * Apply suggestions from code review Co-authored-by: Alex Kaszynski <[email protected]> * Apply suggestions from code review * minor changes Co-authored-by: Alex Kaszynski <[email protected]>
1 parent e5cc214 commit 56856dd

File tree

3 files changed

+137
-3
lines changed

3 files changed

+137
-3
lines changed

ansys/mapdl/core/launcher.py

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
)
2020
from ansys.mapdl.core.mapdl_grpc import MapdlGrpc
2121
from ansys.mapdl.core.licensing import LicenseChecker
22+
from ansys.mapdl.core.licensing import ALLOWABLE_LICENSES
23+
from ansys.mapdl.core import LOG
2224

2325
# settings directory
2426
SETTINGS_DIR = appdirs.user_data_dir("ansys_mapdl_core")
@@ -751,6 +753,7 @@ def launch_mapdl(
751753
log_apdl=False,
752754
verbose_mapdl=False,
753755
license_server_check=True,
756+
license_type=None,
754757
**kwargs,
755758
):
756759
"""Start MAPDL locally in gRPC mode.
@@ -864,7 +867,16 @@ def launch_mapdl(
864867
865868
license_server_check : bool, optional
866869
Check if the license server is available if MAPDL fails to
867-
start. Only available on ``mode='grpc'``. Defaults to True
870+
start. Only available on ``mode='grpc'``. Defaults ``True``.
871+
872+
license_type : str, optional
873+
Enable license type selection. You can input a string for its
874+
license name (for example ``'meba'`` or ``'ansys'``) or its description
875+
("enterprise solver" or "enterprise" respectively).
876+
You can also use legacy licenses (for example ``'aa_t_a'``) but it will
877+
also raise a warning. If it is not used (``None``), no specific license
878+
will be requested, being up to the license server to provide a specific
879+
license type. Default is ``None``.
868880
869881
Notes
870882
-----
@@ -1041,6 +1053,59 @@ def launch_mapdl(
10411053
additional_switches = _validate_add_sw(
10421054
additional_switches, exec_file, kwargs.pop("force_intel", False)
10431055
)
1056+
1057+
if isinstance(license_type, str):
1058+
# In newer license server versions an invalid license name just get discarded and produces no effect or warning.
1059+
# For example:
1060+
# ```bash
1061+
# mapdl.exe -p meba # works fine because 'meba' is a valid license in ALLOWABLE_LICENSES.
1062+
# mapdl.exe -p yoyoyo # The -p flag is ignored and it run the default license.
1063+
# ```
1064+
#
1065+
# In older versions probably it might raise an error. But not sure.
1066+
license_type = license_type.lower().strip()
1067+
1068+
if 'enterprise' in license_type and 'solver' not in license_type:
1069+
license_type = 'ansys'
1070+
1071+
elif 'enterprise' in license_type and 'solver' in license_type:
1072+
license_type = 'meba'
1073+
1074+
elif 'premium' in license_type:
1075+
license_type = 'mech_2'
1076+
1077+
elif 'pro' in license_type:
1078+
license_type = 'mech_1'
1079+
1080+
elif license_type not in ALLOWABLE_LICENSES:
1081+
allow_lics = [f"'{each}'" for each in ALLOWABLE_LICENSES]
1082+
warn_text = \
1083+
f"The keyword argument 'license_type' value ('{license_type}') is not a recognized license name or has been deprecated.\n" + \
1084+
"Still PyMAPDL will try to use it but in older versions you might experience problems connecting to the server.\n" + \
1085+
f"Recognized license names: {' '.join(allow_lics)}"
1086+
warnings.warn(warn_text, UserWarning)
1087+
1088+
additional_switches += ' -p ' + license_type
1089+
LOG.debug(f"Using specified license name '{license_type}' in the 'license_type' keyword argument.")
1090+
1091+
elif '-p ' in additional_switches:
1092+
# There is already a license request in additional switches.
1093+
license_type = re.findall(r'-p \b(\w*)', additional_switches)[0] # getting only the first product license.
1094+
1095+
if license_type not in ALLOWABLE_LICENSES:
1096+
allow_lics = [f"'{each}'" for each in ALLOWABLE_LICENSES]
1097+
warn_text = \
1098+
f"The additional switch product value ('-p {license_type}') is not a recognized license name or has been deprecated.\n" + \
1099+
"Still PyMAPDL will try to use it but in older versions you might experience problems connecting to the server.\n" + \
1100+
f"Recognized license names: {' '.join(allow_lics)}"
1101+
warnings.warn(warn_text, UserWarning)
1102+
LOG.warning(warn_text)
1103+
1104+
LOG.debug(f"Using specified license name '{license_type}' in the additional switches parameter.")
1105+
1106+
elif license_type is not None:
1107+
raise TypeError("The argument 'license_type' does only accept str or None.")
1108+
10441109
start_parm = {
10451110
"exec_file": exec_file,
10461111
"run_location": run_location,

ansys/mapdl/core/licensing.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,14 @@
1414
LIC_FILE_ENVAR = "ANSYSLMD_LICENSE_FILE"
1515
APP_NAME = "FEAT_ANSYS" # TODO: We need to make sure this is the type of feature we need to checkout.
1616
LIC_TO_CHECK = ["mech_1"]
17-
ALLOWABLE_LICENSES = ["ansys", "meba", "mech_2", "mech_1"]
17+
18+
LICENSES = {
19+
"ansys": "Ansys Mechanical Enterprise",
20+
"meba": "Ansys Mechanical Enterprise Solver",
21+
"mech_2": "Ansys Mechanical Premium",
22+
"mech_1": "Ansys Mechanical Pro"
23+
}
24+
ALLOWABLE_LICENSES = list(LICENSES)
1825

1926
## Regarding license checking.
2027
# The available licenses we can check against are (in order of

tests/test_launcher.py

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@
44

55
import pytest
66
from ansys.mapdl import core as pymapdl
7-
from ansys.mapdl.core.launcher import _version_from_path, get_start_instance, _validate_add_sw
7+
from ansys.mapdl.core.launcher import _version_from_path, get_start_instance, _validate_add_sw, launch_mapdl
88
from ansys.mapdl.core.misc import get_ansys_bin
9+
from ansys.mapdl.core.licensing import LICENSES
910

1011
try:
1112
import ansys_corba # noqa: F401
@@ -124,3 +125,64 @@ def test_launch_corba(version):
124125
mapdl_ref = weakref.ref(mapdl)
125126
del mapdl
126127
assert mapdl_ref() is None
128+
129+
130+
def test_license_type_keyword():
131+
# This test might became a way to check available licenses, which is not the purpose.
132+
133+
checks = []
134+
for license_name, license_description in LICENSES.items():
135+
mapdl = launch_mapdl(license_type=license_name)
136+
137+
#Using first line to ensure not picking up other stuff.
138+
checks.append(license_description in mapdl.__str__().split('\n')[0])
139+
mapdl.exit()
140+
141+
breakpoint()
142+
assert any(checks)
143+
144+
dummy_license_name = 'dummy'
145+
# I had to scape the parenthesis because the match argument uses regex.
146+
expected_warn = f"The keyword argument 'license_type' value \('{dummy_license_name}'\) is not a recognized license name or has been deprecated"
147+
with pytest.warns(UserWarning, match=expected_warn):
148+
mapdl = launch_mapdl(license_type=dummy_license_name)
149+
# regardless the license specification, it should lunch.
150+
assert mapdl.is_alive
151+
mapdl.exit()
152+
153+
154+
def test_license_type_keyword_names():
155+
# This test might became a way to check available licenses, which is not the purpose.
156+
157+
successful_check = False
158+
for license_description, each_keyword in zip(LICENSES.values(), keywords):
159+
mapdl = launch_mapdl(license_type=each_keyword)
160+
161+
#Using first line to ensure not picking up other stuff.
162+
successful_check = license_description in mapdl.__str__().split('\n')[0] or successful_check
163+
assert license_description in mapdl.__str__().split('\n')[0]
164+
mapdl.exit()
165+
166+
assert successful_check # if at least one license is ok, this should be true.
167+
168+
169+
def test_license_type_additional_switch():
170+
# This test might became a way to check available licenses, which is not the purpose.
171+
successful_check = False
172+
for license_name, license_description in LICENSES.items():
173+
mapdl = launch_mapdl(additional_switches=' -p' + license_name)
174+
175+
#Using first line to ensure not picking up other stuff.
176+
successful_check = license_description in mapdl.__str__().split('\n')[0] or successful_check
177+
mapdl.exit()
178+
179+
assert successful_check # if at least one license is ok, this should be true.
180+
181+
dummy_license_name = 'dummy'
182+
# I had to scape the parenthesis because the match argument uses regex.
183+
expected_warn = f"The additional switch product value \('-p {dummy_license_name}'\) is not a recognized license name or has been deprecated"
184+
with pytest.warns(UserWarning, match=expected_warn):
185+
mapdl = launch_mapdl(additional_switches=f' -p {dummy_license_name}')
186+
# regardless the license specification, it should lunch.
187+
assert mapdl.is_alive
188+
mapdl.exit()

0 commit comments

Comments
 (0)