Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 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
2 changes: 2 additions & 0 deletions .ansible-lint
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ mock_modules:
- cisco.catalystwan.config_group_deployment
- cisco.catalystwan.feature_profile_builder
- cisco.catalystwan.policy
- cisco.catalystwan.tenants
- cisco.catalystwan.tenants_info
# - zuul_return
# # note the foo.bar is invalid as being neither a module or a collection
# - fake_namespace.fake_collection.fake_module
Expand Down
6 changes: 5 additions & 1 deletion plugins/module_utils/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from catalystwan.endpoints.monitoring.device_details import DeviceData
from catalystwan.session import ManagerHTTPError
from catalystwan.typed_list import DataSequence
from catalystwan.utils.session_type import SessionType

from ..module_utils.vmanage_module import AnsibleCatalystwanModule

Expand Down Expand Up @@ -41,7 +42,10 @@ def get_target_device(

module.logger.info(f"Device Category: {device_category} \nAll devices response: {devices}")
if module.params.get("device_ip"):
target_device = devices.filter(device_ip=module.params["device_ip"]).single_or_default()
if module.session.session_type == SessionType.PROVIDER:
target_device = devices.filter(local_system_ip=module.params["device_ip"]).single_or_default()
else:
target_device = devices.filter(device_ip=module.params["device_ip"]).single_or_default()
if module.params.get("hostname"):
target_device = devices.filter(host_name=module.params["hostname"]).single_or_default()
if module.params.get("uuid"):
Expand Down
2 changes: 2 additions & 0 deletions plugins/module_utils/vmanage_module.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ class AnsibleCatalystwanModule:
username=dict(type="str", required=True, fallback=(env_fallback, ["VMANAGE_USERNAME"])),
password=dict(type="str", required=True, fallback=(env_fallback, ["VMANAGE_PASSWORD"]), no_log=True),
port=dict(type="str", required=False, fallback=(env_fallback, ["VMANAGE_PORT"])),
subdomain=dict(type="str", required=False, fallback=(env_fallback, ["VMANAGE_SUBDOMAIN"])),
),
),
catalystwan_log_dir=dict(type="str", required=False, fallback=(env_fallback, ["CATALYSTWAN_LOG_DIR"])),
Expand Down Expand Up @@ -136,6 +137,7 @@ def session(self) -> ManagerSession:
username=self.module.params["manager_credentials"]["username"],
password=self.module.params["manager_credentials"]["password"],
port=self.module.params["manager_credentials"]["port"],
subdomain=self.module.params["manager_credentials"]["subdomain"],
logger=self._vmanage_logger,
)
break
Expand Down
171 changes: 124 additions & 47 deletions plugins/modules/cluster_management.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,26 @@
- A dict containing the services of cluster device,
such as Cisco Software-Defined Application Visibility and Control.
type: dict
tenancy:
description:
- Dictionary to configure tenancy settings.
type: dict
required: false
suboptions:
mode:
description:
- Tenancy mode for the cluster.
choices: ['single', 'multi']
type: str
clusterid:
description:
- Unique identifier for the cluster in tenancy context.
type: str
domain:
description:
- Domain name associated with the tenancy.
type: str

author:
- Przemyslaw Susko ([email protected])
extends_documentation_fragment:
Expand Down Expand Up @@ -105,12 +125,18 @@
services:
sd-avc:
server: false

- name: Create a cluster with tenancy configuration
cluster_management:
tenancy:
mode: multi
domain: "domain"
"""

import time
from typing import List, Optional

from catalystwan.endpoints.cluster_management import ConnectedDevice, VManageSetup
from catalystwan.endpoints.cluster_management import ConnectedDevice, TenancyMode, VManageSetup
from catalystwan.exceptions import ManagerRequestException

from ..module_utils.result import ModuleResult
Expand Down Expand Up @@ -160,12 +186,12 @@ def run_module():
module_args = dict(
wait_until_configured_seconds=dict(type="int", default=0),
vmanage_id=dict(type=str),
system_ip=dict(type=str, required=True),
cluster_ip=dict(type=str, required=True),
username=dict(type=str, required=True),
password=dict(type=str, no_log=True, required=True),
system_ip=dict(type=str),
cluster_ip=dict(type=str),
username=dict(type=str),
password=dict(type=str, no_log=True),
gen_csr=dict(type=bool, aliases=["genCSR"]),
persona=dict(type=str, choices=["COMPUTE_AND_DATA", "COMPUTE", "DATA"], required=True),
persona=dict(type=str, choices=["COMPUTE_AND_DATA", "COMPUTE", "DATA"]),
services=dict(
type="dict",
options=dict(
Expand All @@ -178,56 +204,107 @@ def run_module():
),
),
),
tenancy=dict(
type="dict",
options=dict(
mode=dict(type="str", choices=["single", "multi"]),
clusterid=dict(type="str"),
domain=dict(type="str"),
),
required=False,
),
)

module = AnsibleCatalystwanModule(argument_spec=module_args, session_reconnect_retries=180)
required_together = [("system_ip", "cluster_ip", "username", "password", "persona")]

mutually_exclusive = [("tenancy", ("system_ip", "cluster_ip", "username", "password", "persona"))]

required_one_of = mutually_exclusive

module = AnsibleCatalystwanModule(
argument_spec=module_args,
session_reconnect_retries=180,
required_together=required_together,
mutually_exclusive=mutually_exclusive,
required_one_of=required_one_of,
)
module.session.request_timeout = 60
result = ModuleResult()

vmanage_id = module.params.get("vmanage_id")
system_ip = module.params.get("system_ip")
cluster_ip = module.params.get("cluster_ip")

if is_device_connected_to_cluster(module, system_ip, cluster_ip):
result.changed = False
result.msg = f"Device {cluster_ip} already configured"
module.exit_json(**result.model_dump(mode="json"))

payload = VManageSetup(
vmanage_id=vmanage_id,
device_ip=cluster_ip,
username=module.params.get("username"),
password=module.params.get("password"),
persona=module.params.get("persona"),
services=module.params.get("services"),
)
if module.params.get("vmanage_id"):
vmanage_id = module.params.get("vmanage_id")
system_ip = module.params.get("system_ip")
cluster_ip = module.params.get("cluster_ip")

if vmanage_id:
module.send_request_safely(
result,
action_name="Cluster Management: Edit vManage",
send_func=module.session.endpoints.cluster_management.edit_vmanage,
payload=payload,
response_key="edit_vmanage",
if is_device_connected_to_cluster(module, system_ip, cluster_ip):
result.changed = False
result.msg = f"Device {cluster_ip} already configured"
module.exit_json(**result.model_dump(mode="json"))

payload = VManageSetup(
vmanage_id=vmanage_id,
device_ip=cluster_ip,
username=module.params.get("username"),
password=module.params.get("password"),
persona=module.params.get("persona"),
services=module.params.get("services"),
)
else:
module.send_request_safely(
result,
action_name="Cluster Management: Add vManage",
send_func=module.session.endpoints.cluster_management.add_vmanage,
payload=payload,
response_key="add_vmanage",

if vmanage_id:
module.send_request_safely(
result,
action_name="Cluster Management: Edit vManage",
send_func=module.session.endpoints.cluster_management.edit_vmanage,
payload=payload,
response_key="edit_vmanage",
)
else:
module.send_request_safely(
result,
action_name="Cluster Management: Add vManage",
send_func=module.session.endpoints.cluster_management.add_vmanage,
payload=payload,
response_key="add_vmanage",
)

if result.changed:
wait_until_configured_seconds = module.params.get("wait_until_configured_seconds")
if wait_until_configured_seconds:
error_msg = wait_for_connected_device(module, system_ip, cluster_ip, wait_until_configured_seconds)
if error_msg:
module.fail_json(msg=f"Error during vManage configuration: {error_msg}")
result.msg = "Successfully updated requested vManage configuration."
else:
result.msg = "No changes to vManage configuration applied."

if module.params.get("tenancy"):
tenancy_mode: TenancyMode = module.get_response_safely(
module.session.endpoints.cluster_management.get_tenancy_mode
)

if result.changed:
wait_until_configured_seconds = module.params.get("wait_until_configured_seconds")
if wait_until_configured_seconds:
error_msg = wait_for_connected_device(module, system_ip, cluster_ip, wait_until_configured_seconds)
if error_msg:
module.fail_json(msg=f"Error during vManage configuration: {error_msg}")
result.msg = "Successfully updated requested vManage configuration."
else:
result.msg = "No changes to vManage configuration applied."
if tenancy_mode.mode == "MultiTenant" and module.params.get("tenancy").get("mode") != "multi":
module.fail_json(msg="Switching from MultiTenancy to SingleTenancy is forbidden")

elif tenancy_mode.mode == "SingleTenant" and module.params.get("tenancy").get("mode") != "single":
new_tennacy = TenancyMode(
mode="MultiTenant",
domain=module.params.get("tenancy").get("domain"),
clusterid=module.params.get("tenancy").get("clusterid"),
)

result.changed = True
module.send_request_safely(
result,
action_name="Cluster Management: Tenancy Mode",
send_func=module.session.endpoints.cluster_management.set_tenancy_mode,
payload=new_tennacy,
response_key=tenancy_mode,
)

if result.changed:
result.msg = "Successfully updated requested vManage configuration. vManage will be restarted"
else:
result.msg = "No changes to vManage configuration applied."

module.exit_json(**result.model_dump(mode="json"))

Expand Down
2 changes: 1 addition & 1 deletion plugins/modules/devices_certificates.py
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ def run_module():
result.changed = False
module.exit_json(**result.model_dump(mode="json"))

payload = TargetDevice(deviceIP=module.params.get("device_ip"))
payload = TargetDevice(deviceIP=target_device_details.device_ip)
module.send_request_safely(
result=result,
action_name="Generate CSR for vManage",
Expand Down
Loading