From 2a5b0f77e520fc1cd1f116d43cc92c1ae1796796 Mon Sep 17 00:00:00 2001 From: David Murphy Date: Tue, 21 Nov 2023 14:43:27 -0700 Subject: [PATCH] Update pre-commit, py 3.10 support and support for vmotion work-in-progress (#392) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Initial updates to pre-commit and test * Added vmotion_disable, vmotion_enable and updated get_vmotion_enabled * Added changelog entry for issue 350 * Updated 3.10 to "3.10" so last 0 gets recognized * Updated tests for formatting issues with new pre-commit * Added Python 3.10 and updated version of pytest-salt-factories * Updated pre-commit for recent versions of utilities * Updated bandit in pre-commit to allow for weak MD4, MD5 or SHA1 hash * Changed test version from Salt 3005.1 to 3006.4 * Updated creation of url with f-strings * Updated coverage in noxfile * Updated coverage to 6.5 * Updated to need 3006 and disabled Sphinx coverage till 7.3.0 which has fix for divide by zero * Updated pytest-salt-factories version per reviewer comments --------- Co-authored-by: David Murphy < dmurphy@saltstack.com> --- .github/workflows/test.yml | 15 +- .pre-commit-config.yaml | 114 +++++++--- changelog/350.added | 1 + noxfile.py | 27 ++- setup.cfg | 5 +- src/saltext/vmware/modules/esxi.py | 206 +++++++++++++++++- .../modules/nsxt_transport_node_profiles.py | 10 +- src/saltext/vmware/states/esxi.py | 107 +++++++++ .../unit/modules/test_nsxt_compute_manager.py | 34 ++- tests/unit/modules/test_nsxt_ip_pools.py | 17 +- tests/unit/modules/test_nsxt_policy_tier0.py | 17 +- .../unit/modules/test_nsxt_uplink_profiles.py | 34 ++- .../modules/test_transport_node_profiles.py | 34 ++- tests/unit/modules/test_vmc_vpn_statistics.py | 4 +- 14 files changed, 489 insertions(+), 136 deletions(-) create mode 100644 changelog/350.added diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e87f6ead..833ec304 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -11,7 +11,7 @@ jobs: - name: Set up Python uses: actions/setup-python@v4 with: - python-version: 3.7 + python-version: "3.10" - name: Set Cache Key run: echo "PY=$(python --version --version | sha256sum | cut -d' ' -f1)" >> $GITHUB_ENV - name: Install System Deps @@ -36,7 +36,7 @@ jobs: - name: Set up Python 3.7 For Nox uses: actions/setup-python@v4 with: - python-version: 3.7 + python-version: "3.10" - name: Install Nox run: | @@ -67,8 +67,9 @@ jobs: - 3.7 - 3.8 - 3.9 + - "3.10" salt-version: - - 3005.1 + - 3006.4 steps: - uses: actions/checkout@v2 @@ -184,9 +185,9 @@ jobs: max-parallel: 3 matrix: python-version: - - 3.7 + - "3.10" salt-version: - - 3005.1 + - 3006.4 steps: - uses: actions/checkout@v2 @@ -307,9 +308,9 @@ jobs: max-parallel: 3 matrix: python-version: - - 3.9 + - "3.10" salt-version: - - 3005.1 + - 3006.4 steps: - uses: actions/checkout@v2 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index a8527e92..a71e983e 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,20 +1,59 @@ --- -minimum_pre_commit_version: 1.15.2 +default_language_version: + python: python3 + +exclude: ^(doc/_static/.*|doc/_themes/.*)$ +minimum_pre_commit_version: 2.4.0 repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v2.1.0 + rev: v4.4.0 hooks: - id: check-merge-conflict # Check for files that contain merge conflict strings. - id: trailing-whitespace # Trims trailing whitespace. args: [--markdown-linebreak-ext=md] + exclude: > + (?x)^( + pkg/macos/pkg-resources/.*\.rtf + )$ + - id: mixed-line-ending # Replaces or checks mixed line ending. args: [--fix=auto] - id: end-of-file-fixer # Makes sure files end in a newline and only a newline. exclude: changelog/.* - id: check-merge-conflict # Check for files that contain merge conflict strings. - id: check-ast # Simply check whether files parse as valid python. + exclude: > + (?x)^( + templates/.* + )$ + - id: check-case-conflict # Check for files with names that would conflict on a + # case-insensitive filesystem like MacOS HFS+ or Windows FAT. + - id: check-json # Attempts to load all json files to verify syntax. + - id: check-symlinks # Checks for symlinks which do not point to anything. + - id: debug-statements # Check for debugger imports and py37+ breakpoint() calls in python source. + exclude: > + (?x)^( + templates/.* + )$ + - id: fix-byte-order-marker # removes UTF-8 byte order marker + - id: forbid-submodules # forbids any submodules in the repository. + - id: fix-encoding-pragma # Remove `# -*- coding: utf-8 -*-` from the top of python files. + args: + - --remove + exclude: > + (?x)^( + salt/ext/.* + )$ # ----- Formatting ----------------------------------------------------------------------------> + - repo: https://github.com/asottile/pyupgrade + rev: v2.37.2 + hooks: + - id: pyupgrade + name: Rewrite Code to be Py3.7+, drop six usage and Py2 support + args: [--py3-plus, --keep-mock] + exclude: src/saltext/vcenter/version.py + - repo: https://github.com/saltstack/pre-commit-remove-import-headers rev: 1.1.0 hooks: @@ -38,36 +77,22 @@ repos: - repo: https://github.com/s0undt3ch/salt-rewrite # Automatically rewrite code with known rules - rev: 1.3.2 + rev: "2.2.0" hooks: - id: salt-rewrite alias: rewrite-docstrings name: Salt extensions docstrings auto-fixes files: ^src/saltext/vcenter/.*\.py$ - args: [--silent] + args: [--silent, -F, fix_docstrings] - - repo: https://github.com/s0undt3ch/salt-rewrite - # Automatically rewrite code with known rules - rev: 1.3.2 - hooks: - id: salt-rewrite alias: rewrite-tests - name: Rewrite the test suite + name: Rewrite Salt's Test Suite files: ^tests/.*\.py$ - args: [--silent, -E, fix_docstrings] - - - repo: https://github.com/asottile/pyupgrade - rev: v2.10.0 - hooks: - - id: pyupgrade - name: Rewrite Code to be Py3.7+ - args: [ - --py3-plus - ] - exclude: src/saltext/vcenter/version.py + args: [--silent, -E, fix_asserts, -E, fix_docstrings] - repo: https://github.com/asottile/reorder_python_imports - rev: v2.4.0 + rev: v3.10.0 hooks: - id: reorder-python-imports args: [ @@ -76,7 +101,7 @@ repos: exclude: src/saltext/vcenter/version.py - repo: https://github.com/psf/black - rev: 20.8b1 + rev: 22.6.0 hooks: - id: black args: [-l 100] @@ -103,21 +128,21 @@ repos: # ----- Security ------------------------------------------------------------------------------> - repo: https://github.com/PyCQA/bandit - rev: "1.7.0" + rev: "1.7.4" hooks: - id: bandit alias: bandit-salt name: Run bandit against the code base - args: [--silent, -lll, --skip, B701] + args: [--silent, -lll, --skip, "B701,B324"] exclude: src/saltext/vcenter/version.py additional_dependencies: ['importlib_metadata<5'] - repo: https://github.com/PyCQA/bandit - rev: "1.7.0" + rev: "1.7.4" hooks: - id: bandit alias: bandit-tests name: Run bandit against the test suite - args: [--silent, -lll, --skip, B701] + args: [--silent, -lll, --skip, "B701,B324"] files: ^tests/.* additional_dependencies: ['importlib_metadata<5'] # <---- Security ------------------------------------------------------------------------------- @@ -131,6 +156,7 @@ repos: # alias: lint-src # name: Lint Source Code # files: ^((setup|noxfile)|src/.*)\.py$ +# require_serial: True # args: # - -e # - lint-code-pre-commit @@ -143,6 +169,7 @@ repos: # alias: lint-tests # name: Lint Tests # files: ^tests/.*\.py$ +# require_serial: True # args: # - -e # - lint-tests-pre-commit @@ -151,7 +178,7 @@ repos: # ----- Static Test Requirements --------------------------------------------------------------> - repo: https://github.com/saltstack/pip-tools-compile-impersonate - rev: dff9089c1003af49665064067ff63c75b9b69dcd + rev: '4.8' hooks: - id: pip-tools-compile alias: compile-3.7-test-requirements @@ -185,6 +212,17 @@ repos: - --py-version=3.9 - --platform=linux - requirements/tests.in + + - id: pip-tools-compile + alias: compile-3.10-test-requirements + name: Py3.10 Test Requirements + files: ^requirements/tests.in$ + pass_filenames: false + args: + - -v + - --py-version=3.10 + - --platform=linux + - requirements/tests.in # <---- Static Test Requirements --------------------------------------------------------------- # ----- Static Lint Requirements --------------------------------------------------------------> @@ -220,6 +258,17 @@ repos: - --py-version=3.9 - --platform=linux - requirements/lint.in + + - id: pip-tools-compile + alias: compile-3.10-test-requirements + name: Py3.10 Lint Requirements + files: ^requirements/lint.in$ + pass_filenames: false + args: + - -v + - --py-version=3.10 + - --platform=linux + - requirements/lint.in # <---- Static Lint Requirements --------------------------------------------------------------- # ----- Static Docs Requirements --------------------------------------------------------------> @@ -255,4 +304,15 @@ repos: - --py-version=3.9 - --platform=linux - requirements/docs.in + + - id: pip-tools-compile + alias: compile-3.10-test-requirements + name: Py3.10 Docs Requirements + files: ^requirements/docs.in$ + pass_filenames: false + args: + - -v + - --py-version=3.10 + - --platform=linux + - requirements/docs.in # <---- Static Docs Requirements --------------------------------------------------------------- diff --git a/changelog/350.added b/changelog/350.added new file mode 100644 index 00000000..9511a6a9 --- /dev/null +++ b/changelog/350.added @@ -0,0 +1 @@ +Added support for vmotion_configured and its supporting functionality diff --git a/noxfile.py b/noxfile.py index 9422bb8d..06c1c59e 100644 --- a/noxfile.py +++ b/noxfile.py @@ -1,3 +1,9 @@ +""" +noxfile +~~~~~~~ + +Nox configuration script +""" # pylint: disable=missing-module-docstring,import-error,protected-access,missing-function-docstring import datetime import json @@ -7,6 +13,15 @@ import sys import tempfile +# fmt: off +if __name__ == "__main__": + sys.stderr.write( + "Do not execute this file directly. Use nox instead, it will know how to handle this file\n" + ) + sys.stderr.flush() + exit(1) +# fmt: on + import nox from nox.command import CommandFailed from nox.virtualenv import VirtualEnv @@ -24,11 +39,11 @@ os.environ.get("JENKINS_URL") or os.environ.get("CI") or os.environ.get("DRONE") is not None ) PIP_INSTALL_SILENT = CI_RUN is False -SKIP_REQUIREMENTS_INSTALL = "SKIP_REQUIREMENTS_INSTALL" in os.environ +SKIP_REQUIREMENTS_INSTALL = os.environ.get("SKIP_REQUIREMENTS_INSTALL", "0") == "1" EXTRA_REQUIREMENTS_INSTALL = os.environ.get("EXTRA_REQUIREMENTS_INSTALL") +COVERAGE_VERSION_REQUIREMENT = "coverage==6.5" # 7.x dropped support for Py 3.7 -COVERAGE_VERSION_REQUIREMENT = "coverage==5.2" -SALT_REQUIREMENT = os.environ.get("SALT_REQUIREMENT") or "salt>=3005" +SALT_REQUIREMENT = os.environ.get("SALT_REQUIREMENT") or "salt>=3006" if SALT_REQUIREMENT == "salt==master": SALT_REQUIREMENT = "git+https://github.com/saltstack/salt.git@master" @@ -355,7 +370,11 @@ def docs(session): os.chdir("docs/") session.run("make", "clean", external=True) session.run("make", "linkcheck", "SPHINXOPTS=-Wn --keep-going", external=True) - session.run("make", "coverage", "SPHINXOPTS=-Wn --keep-going", external=True) + + ## Disabling till sphinx 7.3.0 is released with fix for divide by zero, i + ## see Sphinx https://github.com/sphinx-doc/sphinx/commit/bb74aec2b6aa1179868d83134013450c9ff9d4d6 + ## session.run("make", "coverage", "SPHINXOPTS=-Wn --keep-going", external=True) + docs_coverage_file = os.path.join("_build", "html", "python.txt") if os.path.exists(docs_coverage_file): with open(docs_coverage_file) as rfh: diff --git a/setup.cfg b/setup.cfg index b93bac68..33cceb9c 100644 --- a/setup.cfg +++ b/setup.cfg @@ -21,6 +21,7 @@ classifiers = Programming Language :: Python :: 3.7 Programming Language :: Python :: 3.8 Programming Language :: Python :: 3.9 + Programming Language :: Python :: 3.10 Development Status :: 4 - Beta Intended Audience :: Developers License :: OSI Approved :: Apache Software License @@ -38,7 +39,7 @@ setup_requires = setuptools>=50.3.2 setuptools-declarative-requirements install_requires = - salt>=3005 + salt>=3006 pyvmomi==7.0.3 importlib_metadata; python_version < "3.8" jinja2>=3.1.0 @@ -47,7 +48,7 @@ install_requires = tests = pytest>=6.1.0 pytest-cov - pytest-salt-factories>=0.121.1 + pytest-salt-factories>=1.0.0rc27 dev = nox towncrier==21.9.0rc1 diff --git a/src/saltext/vmware/modules/esxi.py b/src/saltext/vmware/modules/esxi.py index 87ab4ab7..805655ae 100644 --- a/src/saltext/vmware/modules/esxi.py +++ b/src/saltext/vmware/modules/esxi.py @@ -3967,6 +3967,7 @@ def get_vmotion_enabled( cluster_name=None, service_instance=None, profile=None, + host_names=None, ): """ .. versionadded:: 23.4.4.0rc1 @@ -3989,13 +3990,22 @@ def get_vmotion_enabled( profile Profile to use (optional) + host_names + List of ESXi host names provided for a vCenter Server, the host_names argument + is required to tell vCenter which hosts to check if VMotion is enabled. + + If host_names is not provided, the VMotion status will be retrieved for the + ``host`` location instead. This is useful for when service instance + connection information is used for a single ESXi host. + + CLI Example: .. code-block:: bash salt '*' vmware_esxi.get_vmotion_enabled """ - log.debug("Running vmware_esxi.get_host_datetime") + log.debug("Running vmware_esxi.get_vmotion_enabled") ret = {} service_instance = service_instance or utils_connect.get_service_instance( config=__opts__, profile=profile @@ -4007,11 +4017,191 @@ def get_vmotion_enabled( datacenter_name=datacenter_name, get_all_hosts=host_name is None, ) - for host in hosts: - vmotion_vnic = host.configManager.vmotionSystem.netConfig.selectedVnic - if vmotion_vnic: - ret.update({host.name: {"VMotion Enabled": True}}) - else: - ret.update({host.name: {"VMotion Enabled": False}}) - return ret + if not host_names: + host_names = host + + try: + for host in hosts: + if host in host_names: + vmotion_vnic = host.configManager.vmotionSystem.netConfig.selectedVnic + if vmotion_vnic: + ret.update({host.name: {"VMotion Enabled": True}}) + else: + ret.update({host.name: {"VMotion Enabled": False}}) + return ret + except DEFAULT_EXCEPTIONS as exc: + raise salt.exceptions.SaltException(str(exc)) + + +def vmotion_disable( + host_name=None, + datacenter_name=None, + cluster_name=None, + service_instance=None, + profile=None, + host_names=None, +): + """ + .. versionadded:: 23.6.29.0rc1 + + Disable vMotion for a given host or list of host_names. + + host_name + Filter by this ESXi hostname (optional) + + datacenter_name + Filter by this datacenter name (required when cluster is specified) + + cluster_name + Filter by this cluster name (optional) + + service_instance + Use this vCenter service connection instance instead of creating a new one. (optional). + + profile + Profile to use (optional) + + host_names + List of ESXi host names provided for a vCenter Server, the host_names argument + is required to tell vCenter which hosts should disable VMotion. + + If host_names is not provided, VMotion will be disabled for the ``host`` + location instead. This is useful for when service instance connection + information is used for a single ESXi host. + + CLI Example: + + .. code-block:: bash + + salt '*' vmware_esxi.vmotion_disable + """ + log.debug("Running vmware_esxi.vmotion_disable") + ret = {} + service_instance = service_instance or utils_connect.get_service_instance( + config=__opts__, profile=profile + ) + hosts = utils_esxi.get_hosts( + service_instance=service_instance, + host_names=[host_name] if host_name else None, + cluster_name=cluster_name, + datacenter_name=datacenter_name, + get_all_hosts=host_name is None, + ) + + ## host_names = _check_hosts(service_instance, host, host_names) + if not host_names: + host_names = host + + try: + ## for host_name in host_names: + ## host_ref = _get_host_ref(service_instance, host, host_name=host_name) + ## vmotion_system = host_ref.configManager.vmotionSystem + + for host in hosts: + if host in host_names: + vmotion_system = host.configManager.vmotionSystem + + # Disable VMotion for the host by removing the VNic selected to use for VMotion. + try: + vmotion_system.DeselectVnic() + except vim.fault.HostConfigFault as err: + msg = f"vsphere.vmotion_disable failed: {err}" + log.debug(msg) + ret.update({host_name: {"Error": msg, "VMotion Disabled": False}}) + continue + + ret.update({host_name: {"VMotion Disabled": True}}) + + return ret + except DEFAULT_EXCEPTIONS as exc: + raise salt.exceptions.SaltException(str(exc)) + + +def vmotion_enable( + host_name=None, + datacenter_name=None, + cluster_name=None, + service_instance=None, + profile=None, + host_names=None, + device="vmk0", +): + """ + .. versionadded:: 23.6.29.0rc1 + + Enable vMotion for a given host or list of host_names. + + host_name + Filter by this ESXi hostname (optional) + + datacenter_name + Filter by this datacenter name (required when cluster is specified) + + cluster_name + Filter by this cluster name (optional) + + service_instance + Use this vCenter service connection instance instead of creating a new one. (optional). + + profile + Profile to use (optional) + + host_names + List of ESXi host names provided for a vCenter Server, the host_names argument + is required to tell vCenter which hosts should enable VMotion. + + If host_names is not provided, VMotion will be enabled for the ``host`` + location instead. This is useful for when service instance connection + information is used for a single ESXi host. + + device + The device that uniquely identifies the VirtualNic that will be used for + VMotion for each host. Defaults to ``vmk0``. + + CLI Example: + + .. code-block:: bash + + salt '*' vmware_esxi.vmotion_disable + """ + log.debug("Running vmware_esxi.vmotion_disable") + ret = {} + service_instance = service_instance or utils_connect.get_service_instance( + config=__opts__, profile=profile + ) + hosts = utils_esxi.get_hosts( + service_instance=service_instance, + host_names=[host_name] if host_name else None, + cluster_name=cluster_name, + datacenter_name=datacenter_name, + get_all_hosts=host_name is None, + ) + + ## host_names = _check_hosts(service_instance, host, host_names) + if not host_names: + host_names = host + + try: + ## for host_name in host_names: + ## host_ref = _get_host_ref(service_instance, host, host_name=host_name) + ## vmotion_system = host_ref.configManager.vmotionSystem + + for host in hosts: + if host in host_names: + vmotion_system = host.configManager.vmotionSystem + + # Enable VMotion for the host by setting the given device to provide the VNic to use for VMotion. + try: + vmotion_system.SelectVnic(device) + except vim.fault.HostConfigFault as err: + msg = f"vsphere.vmotion_disable failed: {err}" + log.debug(msg) + ret.update({host_name: {"Error": msg, "VMotion Enabled": False}}) + continue + + ret.update({host_name: {"VMotion Enabled": True}}) + + return ret + except DEFAULT_EXCEPTIONS as exc: + raise salt.exceptions.SaltException(str(exc)) diff --git a/src/saltext/vmware/modules/nsxt_transport_node_profiles.py b/src/saltext/vmware/modules/nsxt_transport_node_profiles.py index 90cafe23..65556113 100644 --- a/src/saltext/vmware/modules/nsxt_transport_node_profiles.py +++ b/src/saltext/vmware/modules/nsxt_transport_node_profiles.py @@ -15,8 +15,6 @@ def __virtual__(): return __virtual_name__ -TRANSPORT_NODE_PROFILE_BASE_URL = "https://{0}/api/v1/transport-node-profiles" - create_params_for_transport_profiles = [ "transport_zone_endpoints", "description", @@ -89,7 +87,7 @@ def get( """ log.info("Fetching NSX-T transport node profiles") - url = TRANSPORT_NODE_PROFILE_BASE_URL.format(hostname) + url = f"https://{hostname}/api/v1/transport-node-profiles" params = common._filter_kwargs( allowed_kwargs=["cursor", "included_fields", "page_size", "sort_ascending", "sort_by"], default_dict=None, @@ -268,7 +266,7 @@ def create( """ log.info("Creating nsxt transport node profile") - url = TRANSPORT_NODE_PROFILE_BASE_URL.format(hostname) + url = f"https://{hostname}/api/v1/transport-node-profiles" req_data = common._filter_kwargs( allowed_kwargs=create_params_for_transport_profiles, default_dict={}, @@ -396,7 +394,7 @@ def update( """ log.info("Updating nsxt transport node profile") - url = TRANSPORT_NODE_PROFILE_BASE_URL.format(hostname) + "/{}".format(transport_node_profile_id) + url = f"https://{hostname}/api/v1/transport-node-profiles/{transport_node_profile_id}" req_data = common._filter_kwargs( allowed_kwargs=create_params_for_transport_profiles, default_dict={}, @@ -468,7 +466,7 @@ def delete( """ log.info("Deleting transport node profile with id %s", transport_node_profile_id) - url = TRANSPORT_NODE_PROFILE_BASE_URL.format(hostname) + "/{}".format(transport_node_profile_id) + url = f"https://{hostname}/api/v1/transport-node-profiles/{transport_node_profile_id}" result = nsxt_request.call_api( method="delete", url=url, diff --git a/src/saltext/vmware/states/esxi.py b/src/saltext/vmware/states/esxi.py index e2969d9f..32ecb9ac 100644 --- a/src/saltext/vmware/states/esxi.py +++ b/src/saltext/vmware/states/esxi.py @@ -1680,3 +1680,110 @@ def vsan_config( ret["comment"] = "VSAN configuration will change." return ret + + +def vmotion_configured( + name, + enabled, + device="vmk0", + datacenter_name=None, + cluster_name=None, + host_name=None, + service_instance=None, +): + """ + Configures a host's VMotion properties such as enabling VMotion and setting + the device VirtualNic that VMotion will use. + + name + Name of the state. (DGM this could have been returned from name of function) + + enabled + Ensures whether or not VMotion should be enabled on a host as a boolean + value where ``True`` indicates that VMotion should be enabled and ``False`` + indicates that VMotion should be disabled. + + device + The device that uniquely identifies the VirtualNic that will be used for + VMotion for the host. Defaults to ``vmk0``. + + datacenter_name + Filter by this datacenter name (required when cluster is specified) + + cluster_name + Filter by this cluster name (optional) + + host_name + Filter by this ESXi hostname (optional) + + service_instance + Use this vCenter service connection instance instead of creating a new one. (optional). + + Example: + + .. code-block:: yaml + + configure-vmotion: + esxi.vmotion_configured: + - enabled: True + - device: sample-device + + """ + log.debug("Running vmware_esxi.firewall_config") + ret = {"name": name, "result": None, "comment": "", "changes": {}} + try: + response_list = __salt__["vmware_esxi.get_vmotion_enabled"]( + datacenter_name=datacenter_name, + cluster_name=cluster_name, + host_name=host_name, + service_instance=service_instance, + ) + + # returns a list of host names with enabled or nota + log.debug(f"DGM vmotion_configured response_list '{response_list}'") + for host in response_list: + current_vmotion_enabled = host.get("VMotion_Enabled") + + # DGM work in progress - pausing while helping with 3006 RC1 + + # Configure VMotion Enabled state, if changed. + if enabled != current_vmotion_enabled: + # Only run the command if not using test=True + if not __opts__["test"]: + # Enable VMotion if enabled=True + if enabled is True: + ## response = __salt__[esxi_cmd]("vmotion_enable", device=device).get(host) + # DGM work to be done for set_vmotion + response = __salt__["vmware_esxi.vmotion_enable"](device=device).get(host) + error = response.get("Error") + if error: + ret["comment"] = "Error: {}".format(error) + return ret + # Disable VMotion if enabled=False + else: + ## response = __salt__[esxi_cmd]("vmotion_disable").get(host) + # DGM work to be done for set_vmotion + response = __salt__["vmware_esxi.vmotion_disable"]().get(host) + error = response.get("Error") + if error: + ret["comment"] = "Error: {}".format(error) + return ret + ret["changes"].update( + {host: {"enabled": {"old": current_vmotion_enabled, "new": enabled}}} + ) + + ret["result"] = True + if ret["changes"] == {}: + ret["comment"] = "VMotion configuration is already in the desired state." + return ret + + if __opts__["test"]: + ret["result"] = None + ret["comment"] = "VMotion configuration will change." + + except salt.exceptions.CommandExecutionError as err: + ret["result"] = False + ret["comment"] = "Error: {}".format(err) + return ret + + return ret diff --git a/tests/unit/modules/test_nsxt_compute_manager.py b/tests/unit/modules/test_nsxt_compute_manager.py index 7a4cde05..58df1f38 100644 --- a/tests/unit/modules/test_nsxt_compute_manager.py +++ b/tests/unit/modules/test_nsxt_compute_manager.py @@ -140,16 +140,13 @@ def test_get_by_display_name(api_mock): "sort_ascending": "true", } api_mock.return_value = response - assert ( - nsxt_compute_manager.get_by_display_name( - hostname="hostname", - username="username", - password="pass", - display_name=_mocked_compute_manager["display_name"], - verify_ssl=False, - ) - == {"results": [_mocked_compute_manager]} - ) + assert nsxt_compute_manager.get_by_display_name( + hostname="hostname", + username="username", + password="pass", + display_name=_mocked_compute_manager["display_name"], + verify_ssl=False, + ) == {"results": [_mocked_compute_manager]} @patch.object(nsxt_request, "call_api") @@ -186,13 +183,10 @@ def test_get_by_display_name_paginated(api_mock): "sort_ascending": "true", } api_mock.side_effect = [response_with_cursor, response_without_cursor] - assert ( - nsxt_compute_manager.get_by_display_name( - hostname="hostname", - username="username", - password="pass", - display_name=_mocked_compute_manager["display_name"], - verify_ssl=False, - ) - == {"results": [_mocked_compute_manager]} - ) + assert nsxt_compute_manager.get_by_display_name( + hostname="hostname", + username="username", + password="pass", + display_name=_mocked_compute_manager["display_name"], + verify_ssl=False, + ) == {"results": [_mocked_compute_manager]} diff --git a/tests/unit/modules/test_nsxt_ip_pools.py b/tests/unit/modules/test_nsxt_ip_pools.py index c4bf7327..54d72bfe 100644 --- a/tests/unit/modules/test_nsxt_ip_pools.py +++ b/tests/unit/modules/test_nsxt_ip_pools.py @@ -80,16 +80,13 @@ def test_nsxt_ip_pools_get_by_display_name_when_multiple_pages_exists_in_api_res response = [response_with_cursor, response_without_cursor] mock_call_api.side_effect = response - assert ( - nsxt_ip_pools.get_by_display_name( - hostname="sample.nsxt-hostname.vmware", - username="username", - password="password", - verify_ssl=False, - display_name=_mock_ip_pool["display_name"], - ) - == {"results": [_mock_ip_pool]} - ) + assert nsxt_ip_pools.get_by_display_name( + hostname="sample.nsxt-hostname.vmware", + username="username", + password="password", + verify_ssl=False, + display_name=_mock_ip_pool["display_name"], + ) == {"results": [_mock_ip_pool]} @patch.object(nsxt_request, "call_api") diff --git a/tests/unit/modules/test_nsxt_policy_tier0.py b/tests/unit/modules/test_nsxt_policy_tier0.py index 1d4fe6c3..1bcec3e3 100644 --- a/tests/unit/modules/test_nsxt_policy_tier0.py +++ b/tests/unit/modules/test_nsxt_policy_tier0.py @@ -929,16 +929,13 @@ def test_get_hierarchy_with_error_while_getting_list_response(api_mock): err_msg = "Generic error" static_routes_list_response = {"error": err_msg} api_mock.side_effect = [tier0_obj, static_routes_list_response] - assert ( - nsxt_policy_tier0.get_hierarchy( - hostname="hostname", - username="username", - password="pass", - tier0_id=tier0_obj["id"], - verify_ssl=False, - )["error"] - == "Failure while querying static_routes: {}".format(err_msg) - ) + assert nsxt_policy_tier0.get_hierarchy( + hostname="hostname", + username="username", + password="pass", + tier0_id=tier0_obj["id"], + verify_ssl=False, + )["error"] == "Failure while querying static_routes: {}".format(err_msg) @patch.object(nsxt_request, "call_api") diff --git a/tests/unit/modules/test_nsxt_uplink_profiles.py b/tests/unit/modules/test_nsxt_uplink_profiles.py index 1594a0ed..d0fdf610 100644 --- a/tests/unit/modules/test_nsxt_uplink_profiles.py +++ b/tests/unit/modules/test_nsxt_uplink_profiles.py @@ -74,16 +74,13 @@ def test_get_by_display_name(api_mock): "sort_ascending": "true", } api_mock.return_value = response - assert ( - nsxt_uplink_profiles.get_by_display_name( - hostname="hostname", - username="username", - password="pass", - display_name=_mock_uplink_profile["display_name"], - verify_ssl=False, - ) - == {"results": [_mock_uplink_profile]} - ) + assert nsxt_uplink_profiles.get_by_display_name( + hostname="hostname", + username="username", + password="pass", + display_name=_mock_uplink_profile["display_name"], + verify_ssl=False, + ) == {"results": [_mock_uplink_profile]} @patch.object(nsxt_request, "call_api") @@ -120,16 +117,13 @@ def test_get_by_display_name_paginated(api_mock): "sort_ascending": "true", } api_mock.side_effect = [response_with_cursor, response_without_cursor] - assert ( - nsxt_uplink_profiles.get_by_display_name( - hostname="hostname", - username="username", - password="pass", - display_name=_mock_uplink_profile["display_name"], - verify_ssl=False, - ) - == {"results": [_mock_uplink_profile]} - ) + assert nsxt_uplink_profiles.get_by_display_name( + hostname="hostname", + username="username", + password="pass", + display_name=_mock_uplink_profile["display_name"], + verify_ssl=False, + ) == {"results": [_mock_uplink_profile]} @patch.object(nsxt_request, "call_api") diff --git a/tests/unit/modules/test_transport_node_profiles.py b/tests/unit/modules/test_transport_node_profiles.py index 6437af8e..ea124edd 100644 --- a/tests/unit/modules/test_transport_node_profiles.py +++ b/tests/unit/modules/test_transport_node_profiles.py @@ -88,16 +88,13 @@ def test_get_by_display_name(api_mock): "sort_ascending": "true", } api_mock.return_value = response - assert ( - nsxt_transport_node_profiles.get_by_display_name( - hostname="hostname", - username="username", - password="pass", - verify_ssl=False, - display_name=_mock_transport_node_profile["display_name"], - ) - == {"results": [_mock_transport_node_profile]} - ) + assert nsxt_transport_node_profiles.get_by_display_name( + hostname="hostname", + username="username", + password="pass", + verify_ssl=False, + display_name=_mock_transport_node_profile["display_name"], + ) == {"results": [_mock_transport_node_profile]} @patch.object(nsxt_request, "call_api") @@ -134,16 +131,13 @@ def test_get_by_display_name_paginated(api_mock): "sort_ascending": "true", } api_mock.side_effect = [response_with_cursor, response_without_cursor] - assert ( - nsxt_transport_node_profiles.get_by_display_name( - hostname="hostname", - username="username", - password="pass", - display_name=_mock_transport_node_profile["display_name"], - verify_ssl=False, - ) - == {"results": [_mock_transport_node_profile]} - ) + assert nsxt_transport_node_profiles.get_by_display_name( + hostname="hostname", + username="username", + password="pass", + display_name=_mock_transport_node_profile["display_name"], + verify_ssl=False, + ) == {"results": [_mock_transport_node_profile]} @patch.object(nsxt_request, "call_api") diff --git a/tests/unit/modules/test_vmc_vpn_statistics.py b/tests/unit/modules/test_vmc_vpn_statistics.py index dce7768a..ad4f2d7a 100644 --- a/tests/unit/modules/test_vmc_vpn_statistics.py +++ b/tests/unit/modules/test_vmc_vpn_statistics.py @@ -362,7 +362,7 @@ def test_get_ipsec_statistics_called_with_url(): def test_get_ipsec_statistics_fail_with_error_1(ipsec_statistics_data): - """ Error when tier0_id or tier1_id is not specified """ + """Error when tier0_id or tier1_id is not specified""" result = vmc_vpn_statistics.get_ipsec_statistics( hostname="hostname", refresh_key="refresh_key", @@ -379,7 +379,7 @@ def test_get_ipsec_statistics_fail_with_error_1(ipsec_statistics_data): def test_get_ipsec_statistics_fail_with_error_2(ipsec_statistics_data): - """ Error when both tier0_id and tier1_id are specified """ + """Error when both tier0_id and tier1_id are specified""" result = vmc_vpn_statistics.get_ipsec_statistics( hostname="hostname", refresh_key="refresh_key",