Files
toallab-automation/collections/ansible_collections/davidban77/gns3/plugins/modules/gns3_node.py

273 lines
7.8 KiB
Python

#!/usr/bin/env python
ANSIBLE_METADATA = {
"metadata_version": "1.2",
"status": ["preview"],
"supported_by": "community",
}
DOCUMENTATION = """
---
module: gns3_node
short_description: Module to operate a node in a GNS3 server project
version_added: '2.8'
description:
- Module to operate a node in a GNS3 server project.
- It starts/stops/suspend/reloads a node.
requirements: [ gns3fy ]
author:
- David Flores (@davidban77)
options:
url:
description:
- URL target of the GNS3 server
required: true
type: str
port:
description:
- TCP port to connect to server REST API
type: int
default: 3080
user:
description:
- User to connect to GNS3 server
type: str
password:
description:
- Password to connect to GNS3 server
type: str
project_name:
description:
- Project name
type: str
project_id:
description:
- Project ID
type: str
node_name:
description:
- Node name
type: str
node_id:
description:
- Node ID
type: str
state:
description:
- State of the node, it can be:
- '- C(started): Starts a node'
- '- C(stopped): Stops a node'
- '- C(suspended): Suspends a node'
- '- C(reload): Special non-idempotent action that reloads a node'
type: str
choices: ['started', 'stopped', 'suspended', 'reload']
retry:
description:
- Retries an action based on the state, if true and state is set to reload
- it will reload the device and try to start it again if the status was not
- changed
type: bool
default: false
poll_wait_time:
description:
- Delay in seconds to wait to poll nodes when they are started/stopped.
- Used when I(nodes_state) is C(started)/C(stopped)
type: int
default: 5
force_project_open:
description:
- It will open the project (if closed) to interact with the device.
- Otherwise it will throw out an error
type: bool
default: false
"""
EXAMPLES = """
# Open a GNS3 project and start router01 node
- name: Start node
gns3_node:
url: http://localhost
project_name: lab_example
node_name: router01
node_state: started
force_project_open: true
# Stop a node and wait 10 seconds to poll for status
- name: Stop node
gns3_node:
url: http://localhost
project_name: lab_example
node_name: router01
state: stopped
# Suspend a node based on UUID
- name: Suspend node
gns3_node:
url: http://localhost
project_name: lab_example
node_id: 'ROUTER-UUID-SOMETHING-1234567'
state: suspended
# Reload a node and apply a retry to start if needed
- name: Stop lab
gns3_node:
url: http://localhost
project_id: 'PROJECT-UUID-SOMETHING-1234567'
node_name: router01
state: reload
retry: true
poll_wait_time: 30
"""
RETURN = """
name:
description: Project name
type: str
project_id:
description: Project UUID
type: str
node_id:
description: Node UUID
type: str
status:
description: Project status. Possible values: opened, closed
type: str
node_directory:
description: Path of the node on the server (works only with compute=local)
type: str
node_type:
description: Network node type
type: str
"""
import time
import traceback
from ansible.module_utils.basic import AnsibleModule, missing_required_lib
GNS3FY_IMP_ERR = None
try:
from gns3fy import Gns3Connector, Project
HAS_GNS3FY = True
except Exception:
HAS_GNS3FY = False
GNS3FY_IMP_ERR = traceback.format_exc()
def return_node_data(node):
"Returns the node main attributes"
return dict(
name=node.name,
project_id=node.project_id,
node_id=node.node_id,
status=node.status,
node_directory=node.node_directory,
node_type=node.node_type,
)
def state_verification(expected_state, node, retry=False, poll_wait_time=5):
"Verifies node state and returns a changed attribute"
if expected_state == "started" and node.status != "started":
node.start()
if node.status != "started" and retry:
node.start()
return True
elif expected_state == "stopped" and node.status != "stopped":
node.stop()
if node.status != "stopped" and retry:
node.stop()
return True
elif expected_state == "suspended" and node.status != "suspended":
node.suspend()
if node.status != "suspended" and retry:
node.suspend()
return True
elif expected_state == "reload":
node.reload()
time.sleep(poll_wait_time)
node.get()
if node.status != "started" and retry:
node.start()
return True
return False
def main():
module = AnsibleModule(
argument_spec=dict(
url=dict(type="str", required=True),
port=dict(type="int", default=3080),
user=dict(type="str", default=None),
password=dict(type="str", default=None, no_log=True),
state=dict(
type="str",
required=True,
choices=["started", "stopped", "suspended", "reload"],
),
project_name=dict(type="str", default=None),
project_id=dict(type="str", default=None),
node_name=dict(type="str", default=None),
node_id=dict(type="str", default=None),
retry=dict(type="bool", default=False),
poll_wait_time=dict(type="int", default=5),
force_project_open=dict(type="bool", default=False),
),
required_one_of=[["project_name", "project_id"], ["node_name", "node_id"]],
)
result = dict(changed=False)
if not HAS_GNS3FY:
module.fail_json(msg=missing_required_lib("gns3fy"), exception=GNS3FY_IMP_ERR)
server_url = module.params["url"]
server_port = module.params["port"]
server_user = module.params["user"]
server_password = module.params["password"]
state = module.params["state"]
project_name = module.params["project_name"]
project_id = module.params["project_id"]
node_name = module.params["node_name"]
node_id = module.params["node_id"]
retry = module.params["retry"]
poll_wait_time = module.params["poll_wait_time"]
force_project_open = module.params["force_project_open"]
try:
# Create server session
server = Gns3Connector(
url=f"{server_url}:{server_port}", user=server_user, cred=server_password
)
# Define the project
if project_name is not None:
project = Project(name=project_name, connector=server)
elif project_id is not None:
project = Project(project_id=project_id, connector=server)
if project is None:
module.fail_json(msg="Could not retrieve project. Check name", **result)
project.get()
if project.status != "opened" and force_project_open:
project.open()
# Retrieve node
if node_name is not None:
node = project.get_node(name=node_name)
elif node_id is not None:
node = project.get_node(node_id=node_id)
if node is None:
module.fail_json(msg="Could not retrieve node. Check name", **result)
except Exception as err:
module.fail_json(msg=str(err), **result)
# Apply state change
result["changed"] = state_verification(
expected_state=state, node=node, retry=retry, poll_wait_time=poll_wait_time
)
# Return the node data
result["node"] = return_node_data(node)
module.exit_json(**result)
if __name__ == "__main__":
main()