Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
177 changes: 130 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,113 @@ 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"),
)

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:
wait_until_configured_seconds = module.params.get("wait_until_configured_seconds")
if wait_until_configured_seconds:
# wait for manager to restart
time.sleep(60)
module.session.wait_server_ready(timeout=(wait_until_configured_seconds))
result.msg = "Successfully updated requested vManage configuration. vManage was restarted"
else:
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