diff --git a/build_ansible.yml b/build_ansible.yml index e09fc6d..7756232 100644 --- a/build_ansible.yml +++ b/build_ansible.yml @@ -23,6 +23,10 @@ name: "{{ inventory_hostname }}_disk0" state: present + - name: VM Created + + + - name: Add NIC to VM ovirt_nic: state: present diff --git a/collections/ansible_collections/davidban77/gns3/.gitignore b/collections/ansible_collections/davidban77/gns3/.gitignore deleted file mode 100644 index 9b9bbd1..0000000 --- a/collections/ansible_collections/davidban77/gns3/.gitignore +++ /dev/null @@ -1,93 +0,0 @@ -# Compiled source # -################### -*.com -*.class -*.dll -*.exe -*.o -*.so -__pycache__/ -*.py[cod] -*$py.class - -# Packages # -############ -# it's better to unpack these files and commit the raw source -# git has its own built in compression methods -*.7z -*.dmg -*.gz -*.iso -*.jar -*.rar -*.tar -*.zip -.Python -build/ -develop-eggs/ -dist/ -downloads/ -eggs/ -.eggs/ -lib/ -lib64/ -parts/ -sdist/ -var/ -wheels/ -pip-wheel-metadata/ -share/python-wheels/ -*.egg-info/ -.installed.cfg -*.egg -MANIFEST - -# Logs and databases # -###################### -*.log -*.sql -*.sqlite - -# OS generated files # -###################### -.DS_Store -.DS_Store? -._* -.Spotlight-V100 -.Trashes -ehthumbs.db -Thumbs.db -*.retry -.vscode -.mypy_cache -.pytest_cache -__pycache__ -prof -.envFile -.env -.eapi.conf -.idea - -# Unit test / coverage reports -htmlcov/ -.tox/ -.nox/ -.coverage -.coverage.* -.cache -nosetests.xml -coverage.xml -*.cover -.hypothesis/ -.pytest_cache/ - -# Sphinx documentation -docs/_build/ - -# MkDocs -site/ - -# mypy -.mypy_cache/ -.dmypy.json -dmypy.json diff --git a/collections/ansible_collections/davidban77/gns3/CHANGELOG.md b/collections/ansible_collections/davidban77/gns3/CHANGELOG.md deleted file mode 100644 index 80731d4..0000000 --- a/collections/ansible_collections/davidban77/gns3/CHANGELOG.md +++ /dev/null @@ -1,69 +0,0 @@ -# Releases - -## 1.5.0 - -**Enhancements:** - -- Added `gns3_facts` to retrieve the compute information like: console ports, server version, available emulators, available images, etc.. -- Added `gns3_snapshot` to manipulate the snapshot creation/deletion and restoration of a project. - -**Fixes:** - -- Added the needed `user` and `password` arguments to all the modules, when interacting with a GNS3 server with authentication. -- Refactored the modules a little to be more standard with each other. - -## 1.4.0 - -**Enhacements:** - -- Added `gns3_node` to interact with the node inside a project. Provides the following: - - `start/stop/suspend/reload`: Actions to be applied on the node. These are idempotent with the exception of `reload`. - - Special flags like `retry` for an action to be applied a second time just in case... And a `force_project_open` to interact with a device if the project is closed -- Refactored `gns3_project` to be more pythonic - -## 1.3.0 - -**Enhancements:** - -- Added `gns3_node_file` and `gns3_project_file` modules. -- Improved the Makefile -- Added alpine node to the tests - -## 1.2.2. - -**Fixes:** - -- Upgrading to `gns3fy ^0.4.0` - -## 1.2.1 - -**Enhancements:** - -- No more `node_type` needed when creating nodes in a project. - -## 1.2.0 - -**Enhancements:** - -- Modules: - - `gns3_nodes_inventory`: Returns inventory-style dictionary of the nodes. - -**Fixes:** - -- Modules: - - Error when using the `gns3_version` module when `gns3fy` is not installed - -- Tests: - - Added check for `gns3_version` - -## 1.1.0 - -**Enhancements:** - -- Roles: - - `create_lab`: Create a GNS3 Lab by creating a project and starting up the nodes - - `delete_lab`: Deletes a GNS3 Lab by stopping nodes and deleting the project - -## 1.0.1 - -Initial push of the ansible collections. Released focused on the `gns3` module diff --git a/collections/ansible_collections/davidban77/gns3/FILES.json b/collections/ansible_collections/davidban77/gns3/FILES.json deleted file mode 100644 index af5dc35..0000000 --- a/collections/ansible_collections/davidban77/gns3/FILES.json +++ /dev/null @@ -1,299 +0,0 @@ -{ - "files": [ - { - "name": ".", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, - "format": 1 - }, - { - "name": "plugins", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, - "format": 1 - }, - { - "name": "roles", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, - "format": 1 - }, - { - "name": ".DS_Store", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "07d2bba37d01224569c017d4c7a1279b25034e29466d550ed965f82ed0aaa357", - "format": 1 - }, - { - "name": "LICENSE", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "ecec1ee81897773f92976da30c1fbb4414107ef182511644e86945d74e1a986f", - "format": 1 - }, - { - "name": "requirements.txt", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "59e53d1f4cae821cf5701a9d35babccae916321df53376fa3aa9aaced4134071", - "format": 1 - }, - { - "name": "CHANGELOG.md", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "8274d3baedce15723f01977a4bbf351b5b3d0773fdecb31e67fd33f4a219d866", - "format": 1 - }, - { - "name": "dev-requirements.txt", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "c1f58a2e2e6ad1c44048e835ebc329fb1d8b4e3e65da997defeeac119c22f44c", - "format": 1 - }, - { - "name": "Makefile", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "293c346df21e6637e8bc604cdd5dc7757acdace716eec4a8917be922d821e4aa", - "format": 1 - }, - { - "name": "README.md", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "b2b255969f71c789635f478015538bad0da15af127521fb5d98580617ae5f368", - "format": 1 - }, - { - "name": ".gitignore", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "2282d3966f03871ec05c50da914155bf8d715beebb8027b559a8870116fc5651", - "format": 1 - }, - { - "name": "galaxy.yml", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "11fdd35c3e074f92599a16e94a4425db14b0c2a741020c41cac4b15538a717f5", - "format": 1 - }, - { - "name": "test/playbooks", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, - "format": 1 - }, - { - "name": "test/playbooks/group_vars", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, - "format": 1 - }, - { - "name": "test/playbooks/create_files.yml", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "633a5a2b3c11c27c7264a5444da7249843490349bc9704e73828e58c75822bc4", - "format": 1 - }, - { - "name": "test/playbooks/node_interaction.yml", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "4d30f6988337e9be5777106bd65357b7064dcfe2345e9672fb184b909c831dff", - "format": 1 - }, - { - "name": "test/playbooks/delete_files.yml", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "2cc8b222450116e3ac24c959a7e9c36f4ad36073c3f9213bf81dbca769080da5", - "format": 1 - }, - { - "name": "test/playbooks/snapshots.yml", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "4d659f0381a8ae4130081b62ce11f25518a3881cf1f164dd7c078dc70a284d00", - "format": 1 - }, - { - "name": "test/playbooks/ansible.cfg", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "27762b4172718c13f2abb4b8180678875717a465e497eeae3f546e2f24556421", - "format": 1 - }, - { - "name": "test/playbooks/facts.yml", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "781170433cc129bb49ec0b215f280f73f35634afac0d397dda3da38bcd03da4c", - "format": 1 - }, - { - "name": "test/playbooks/main.yml", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "e66b08210468e91df3c15ef46169a2064bc26b18bf28465f1f42d464321b05a1", - "format": 1 - }, - { - "name": "test/playbooks/group_vars/all.yml", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "fa9871fb705af3de74be241428233020ff7d02322f5b58c0b32d05df17990e6a", - "format": 1 - }, - { - "name": "plugins/modules", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, - "format": 1 - }, - { - "name": "plugins/modules/gns3_facts.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "b47b546f9bcbd38128dbb7d4d24a4f1ec4a329a52cd0b2cb6acd37797bbb944a", - "format": 1 - }, - { - "name": "plugins/modules/gns3_project.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "857080b1b5f6b9c1e04aa6e51501f2edae3a9d4fd63a1eecbffb214cc57e12c4", - "format": 1 - }, - { - "name": "plugins/modules/gns3_node_file.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "83eb69764b268fee6d67decdb1fc01f915f47882b4dfcb885599d6d475ce5e47", - "format": 1 - }, - { - "name": "plugins/modules/gns3_node.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "03d49fac0ef8191c620929deb82d1ef2b2dcb0fe28e78d5ab1ff868b516d4e44", - "format": 1 - }, - { - "name": "plugins/modules/gns3_snapshot.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "f25e7a9bfdd07abea77971dbf6126238c8d870036cb9beb8668aa74698accdb4", - "format": 1 - }, - { - "name": "plugins/modules/gns3_version.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "470c19c7e60aed0fc7b318fa8b4433e87c0b66f5f5c6ddda0050e27e85b4abb9", - "format": 1 - }, - { - "name": "plugins/modules/gns3_nodes_inventory.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "7b021e9ef803a03dfe4b975a47d27bfb558b910feee4e31249bf4a8f702846ba", - "format": 1 - }, - { - "name": "plugins/modules/gns3_project_file.py", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "e85dac29bd330c67214038eb1a9098e67ce3e3e16ae62ffb447dfdaea14c7ef3", - "format": 1 - }, - { - "name": "roles/delete_lab", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, - "format": 1 - }, - { - "name": "roles/create_lab", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, - "format": 1 - }, - { - "name": "roles/delete_lab/tasks", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, - "format": 1 - }, - { - "name": "roles/delete_lab/meta", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, - "format": 1 - }, - { - "name": "roles/delete_lab/tasks/main.yml", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "95ac2ba013e97795a2e86623b6cbce9d5e432d9a6b58216be475d1d92ebe56b4", - "format": 1 - }, - { - "name": "roles/delete_lab/meta/main.yml", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "9d92ea65373c0af69fd88e95f63fec9f4001e04128277f340a75932e0500eade", - "format": 1 - }, - { - "name": "roles/create_lab/tasks", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, - "format": 1 - }, - { - "name": "roles/create_lab/meta", - "ftype": "dir", - "chksum_type": null, - "chksum_sha256": null, - "format": 1 - }, - { - "name": "roles/create_lab/tasks/main.yml", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "ed0bd1a5303442348d549b2aa5cc046abdc675be5d4dc8f4fa1d87f3fe44b621", - "format": 1 - }, - { - "name": "roles/create_lab/meta/main.yml", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "14579b38e8cee8b07fe7b2cd337ee0611e949864ff84b1d8a1bc61ffb54e06c4", - "format": 1 - }, - { - "name": ".vscode/settings.json", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "4d5e35cc829fff24f9d120ef957b2ce72fbcc854577ae11ae7534f79bc21ad10", - "format": 1 - } - ], - "format": 1 -} \ No newline at end of file diff --git a/collections/ansible_collections/davidban77/gns3/LICENSE b/collections/ansible_collections/davidban77/gns3/LICENSE deleted file mode 100644 index 2732caa..0000000 --- a/collections/ansible_collections/davidban77/gns3/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2019 David Flores - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/collections/ansible_collections/davidban77/gns3/MANIFEST.json b/collections/ansible_collections/davidban77/gns3/MANIFEST.json deleted file mode 100644 index 8abaf27..0000000 --- a/collections/ansible_collections/davidban77/gns3/MANIFEST.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "collection_info": { - "namespace": "davidban77", - "name": "gns3", - "version": "1.5.0", - "license": [ - "MIT" - ], - "description": "Module to interact with GNS3 server REST API based on gns3fy", - "repository": "https://github.com/davidban77/ansible-collection-gns3", - "documentation": "https://github.com/davidban77/ansible-collection-gns3/blob/master/README.md", - "homepage": "https://github.com/davidban77/ansible-collection-gns3", - "issues": "https://github.com/davidban77/ansible-collection-gns3/issues", - "authors": [ - "David Flores " - ], - "tags": [ - "gns3", - "gns3fy", - "networking", - "rest", - "system", - "netops" - ], - "license_file": null, - "readme": "README.md", - "dependencies": {} - }, - "file_manifest_file": { - "name": "FILES.json", - "ftype": "file", - "chksum_type": "sha256", - "chksum_sha256": "f4608d42f56cf93d10743fa414e9a358810137998c8a7129f0aa9a378344aa50", - "format": 1 - }, - "format": 1 -} \ No newline at end of file diff --git a/collections/ansible_collections/davidban77/gns3/Makefile b/collections/ansible_collections/davidban77/gns3/Makefile deleted file mode 100644 index a856985..0000000 --- a/collections/ansible_collections/davidban77/gns3/Makefile +++ /dev/null @@ -1,30 +0,0 @@ -VERSION=1.5.0 - -build: - rm -rf releases/ - mazer build - -publish: build - mazer publish releases/davidban77-gns3-${VERSION}.tar.gz - -test-create-lab: - cd test/playbooks; ansible-playbook main.yml -e execute=create - -test-node-interaction: - cd test/playbooks; ansible-playbook node_interaction.yml - -test-create-files: - cd test/playbooks; ansible-playbook create_files.yml - -test-snapshots: - cd test/playbooks; ansible-playbook snapshots.yml - -test-delete-files: - cd test/playbooks; ansible-playbook delete_files.yml - -test-delete-lab: - cd test/playbooks; ansible-playbook main.yml -e execute=delete - -test-create-all: test-create-lab test-create-files test-node-interaction test-snapshots - -test-delete-all: test-delete-files test-delete-lab diff --git a/collections/ansible_collections/davidban77/gns3/README.md b/collections/ansible_collections/davidban77/gns3/README.md deleted file mode 100644 index d4b2d24..0000000 --- a/collections/ansible_collections/davidban77/gns3/README.md +++ /dev/null @@ -1,207 +0,0 @@ -# Ansible Module for GNS3 -[Ansible-Galaxy collections](https://galaxy.ansible.com/davidban77/gns3) repository for GNS3 Server REST API using [gns3fy - see the docs](https://davidban77.github.io/gns3fy/). - -## Installation - -For the module to be used you need to have installed [gns3fy](https://github.com/davidban77/gns3fy) - -``` -pip install gns3fy -``` - -This collections is packaged under ansible-galaxy, so to install it you need [mazer from Ansible Projects](https://galaxy.ansible.com/docs/mazer/index.html): - -``` -mazer install davidban77.gns3 -``` - -## Features - -- Open/closes projects. -- Starts/stops all nodes inside a project, or it can be done sequentially with a delay factor. -- Creates/Updates projects with nodes and links specified as variables in a playbook. -- Deletes projects safely by stopping nodes, if there are any, then closing the project and finally deleting it. -- Creates/Deletes/Restores snapshots of projects. -- Retrieves information about available emulators on the GNS3 server compute, as well as available images, console ports, version, etc.. -- Idempotency is present in all actions. An example could be reflected in a playbook that creates a project with nodes and links, these settings will not be executed again on a rerun (and by settings I mean projects settings, nodes and links)/ - - -## Modules - -These are the modules provided with this collection: - -- `gns3_version`: Retrieves GNS3 server version. (**TO BE DEPRECATED** with the `gns3_facts` module) -- `gns3_facts`: Retrieves the compute(s) information of a GNS3 server -- `gns3_project`: Module to interact with GNS3 server projects - - It opens/closes projects and performs basic turnup/teradown operations on nodes. - - It creates/updates or deletes projects, with the respective nodes and links specified -- `gns3_project_file`: Updates/creates a file on a project directory. -- `gns3_snapshot`: Module that interacts with snapshots of a project on GNS3 server. -- `gns3_node`: Module to operate a node in a GNS3 server project. -- `gns3_node_file`: Updates/creates a file on a node directory. -- `gns3_nodes_inventory`: Retrieves GNS3 a project nodes console information. - -## Examples: using the module - -Here are some examples of how to use the module. - -#### Get server version - -```yaml ---- -- host: localhost - # Call the collections to use the respective modules - collections: - - davidban77.gns3 - vars: - gns3_url: http://localhost - tasks: - - name: Get the server facts - gns3_facts: - url: "{{ gns3_url }}" - port: 3080 - get_images: all - get_compute_ports: yes - register: result - - - debug: var=result -``` -#### Get nodes_inventory information from a project - -```yaml ---- -- host: localhost - # Call the collections to use the respective modules - collections: - - davidban77.gns3 - vars: - gns3_url: http://localhost - tasks: - - name: Get the server version - gns3_nodes_inventory: - url: "{{ gns3_url }}" - project_name: lab_example - register: result - - - debug: var=result -``` - -#### Manipulate GNS3 projects - -```yaml ---- -# Open a GNS3 project -- name: Start lab - gns3_project: - url: "{{ gns3_url }}" - state: opened - project_name: lab_example - -# Stop all nodes inside an open project -- name: Stop nodes - gns3_project: - url: "{{ gns3_url }}" - state: opened - project_name: lab_example - nodes_state: stopped - nodes_strategy: all - poll_wait_time: 5 - -# Open a GNS3 project and start nodes one by one with a delay of 10sec between them -- name: Start nodes one by one - gns3_project: - url: "{{ gns3_url }}" - state: opened - project_name: lab_example - nodes_state: started - nodes_strategy: one_by_one - nodes_delay: 10 - -# Close a GNS3 project -- name: Stop lab - gns3_project: - url: "{{ gns3_url }}" - state: closed - project_id: "UUID-SOMETHING-1234567" -``` - -#### Create and delete projects - -```yaml ---- -# Create a GNS3 project given nodes and links specifications -- name: Create a project - gns3_project: - url: "{{ gns3_url }}" - state: present - project_name: new_lab - nodes_spec: - - name: alpine-1 - template: alpine - - name: alpine-2 - template: alpine - links_spec: - - ['alpine-1', 'eth0', 'alpine-2', 'eth1'] - -# Delete a GNS3 project -- name: Delete project - gns3_project: - url: "{{ gns3_url }}" - state: absent - project_name: new_lab -``` - -## Examples: using the roles - -There are also some convinient roles that you can use to manage your labs. Here is an example playbook: - -`main.yml` -```yaml -- hosts: localhost - tasks: - - import_role: - name: create_lab - when: execute == "create" - - import_role: - name: delete_lab - when: execute == "delete" -``` - -This way you can call and switch the behaviour of the playbook: - -**Create the lab** -``` -ansible-playbook main.yml -e execute=create -``` - -Or **delete the lab** -``` -ansible-playbook main.yml -e execute=delete -``` - -Here is the example variable file which specifies the naming convention used. You can see that the variable names come from the module itself with only `gns3_` - -```yaml ---- -gns3_url: "http://dev_gns3server" -gns3_project_name: test_ansible -gns3_nodes_spec: - - name: veos-1 - template: "vEOS-4.21.5F" - - name: veos-2 - template: "vEOS-4.21.5F" - - name: ios-1 - template: "IOU-15.4" - - name: ios-2 - template: "IOU-15.4" -gns3_nodes_strategy: one_by_one -gns3_links_spec: - - ["veos-1", "Ethernet1", "veos-2", "Ethernet1"] - - ["veos-1", "Ethernet2", "ios-1", "Ethernet1/0"] - - ["veos-2", "Ethernet2", "ios-2", "Ethernet1/0"] - - ["ios-1", "Ethernet1/2", "ios-2", "Ethernet1/2"] -``` - -### More examples - -For more examples like create an `/etc/network/interfaces` file for an `alpine` docker node to configure its network interfaces, or restore a project to an specific snapshot, you can go to the `test/playbooks` directory. diff --git a/collections/ansible_collections/davidban77/gns3/dev-requirements.txt b/collections/ansible_collections/davidban77/gns3/dev-requirements.txt deleted file mode 100644 index 54b944b..0000000 --- a/collections/ansible_collections/davidban77/gns3/dev-requirements.txt +++ /dev/null @@ -1,4 +0,0 @@ --r requirements.txt - -flake8 -black diff --git a/collections/ansible_collections/davidban77/gns3/galaxy.yml b/collections/ansible_collections/davidban77/gns3/galaxy.yml deleted file mode 100644 index 7b81ef3..0000000 --- a/collections/ansible_collections/davidban77/gns3/galaxy.yml +++ /dev/null @@ -1,21 +0,0 @@ -namespace: "davidban77" -name: "gns3" -version: "1.5.0" -readme: "README.md" -description: "Module to interact with GNS3 server REST API based on gns3fy" -authors: - - "David Flores " -dependencies: -license: - - "MIT" -tags: - - gns3 - - gns3fy - - networking - - rest - - system - - netops -repository: "https://github.com/davidban77/ansible-collection-gns3" -documentation: "https://github.com/davidban77/ansible-collection-gns3/blob/master/README.md" -homepage: "https://github.com/davidban77/ansible-collection-gns3" -issues: "https://github.com/davidban77/ansible-collection-gns3/issues" diff --git a/collections/ansible_collections/davidban77/gns3/plugins/modules/gns3_facts.py b/collections/ansible_collections/davidban77/gns3/plugins/modules/gns3_facts.py deleted file mode 100644 index d3581e7..0000000 --- a/collections/ansible_collections/davidban77/gns3/plugins/modules/gns3_facts.py +++ /dev/null @@ -1,187 +0,0 @@ -#!/usr/bin/env python - -ANSIBLE_METADATA = { - "metadata_version": "1.1", - "status": ["preview"], - "supported_by": "community", -} - -DOCUMENTATION = """ ---- -module: gns3_facts -short_description: Module that retrieves the compute(s) information of a GNS3 server -version_added: '2.8' -description: - - Module that retrieves the compute(s) information of a GNS3 server -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 - get_images: - description: - - If set it will also retrieve the images of the specified emulator unless - - is set to 'all', in which case will retrieve from all emulators. For a - - list of available emulators, visit the GNS3 API information - type: str - get_compute_ports: - description: - - If set it will retrieve the console_ports and udp_ports of the compute - type: bool -""" - -EXAMPLES = """ -# Retrieves all the information from the computes of GNS3 server -- name: Retrieve all the facts of a GNS3 server computes - gns3_facts: - url: http://localhost - get_images: all - get_compute_ports: yes - register: computes_info - -- debug: var=computes_info - -# Retrieves only basic facts data of the GNS3 server computes -- gns3_facts: - url: http://localhost - register: computes_info - -- debug: var=computes_info -""" - -RETURN = """ -compute_id: - description: Server identifier - type: str -name: - description: Server name - type: str -host: - description: Server host - type: str -capabilities: - description: Object that describes what the server supports - type: dict -connected: - description: Whether the controller is connected to the compute or not - type: bool -cpu_usage_percent: - description: CPU usage of the compute - type: float -memory_usage_percent: - description: RAM usage of the compute - type: int -port: - description: Server port - type: int -protocol: - description: Protocol used (http, https) - type: str -user: - description: User for authentication - type: str -last_error: - description: Last error on the compute - type: str -images: - description: Images configured on the compute depending on the emulator (optional) - type: dict -compute_ports: - description: Ports used by the compute (console and udp ports) (optional) - type: dict -""" - -import traceback -from ansible.module_utils.basic import AnsibleModule, missing_required_lib - -GNS3FY_IMP_ERR = None -try: - from gns3fy import Gns3Connector - - HAS_GNS3FY = True -except Exception: - HAS_GNS3FY = False - GNS3FY_IMP_ERR = traceback.format_exc() - - -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), - get_images=dict(type="str", default=None), - get_compute_ports=dict(type="bool", default=False), - ) - ) - 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"] - get_images = module.params["get_images"] - get_compute_ports = module.params["get_compute_ports"] - - try: - # Create server session - server = Gns3Connector( - url=f"{server_url}:{server_port}", user=server_user, cred=server_password - ) - - computes = server.get_computes() - for compute in computes: - - # Images - if get_images: - compute["images"] = dict() - - if get_images == "all": - for emulator in compute["capabilities"]["node_types"]: - try: - compute["images"][emulator] = server.get_compute_images( - emulator=emulator, compute_id=compute["compute_id"] - ) - except Exception as err: - if "404" in str(err): - # Contine if no image dir is set for that emulator - continue - else: - compute["images"][get_images] = server.get_compute_images( - emulator=get_images, compute_id=compute["compute_id"] - ) - - # Compute ports - if get_compute_ports: - compute["compute_ports"] = server.get_compute_ports( - compute_id=compute["compute_id"] - ) - - result["facts"] = computes - module.exit_json(**result) - except Exception as err: - module.fail_json(msg=str(err), **result) - - -if __name__ == "__main__": - main() diff --git a/collections/ansible_collections/davidban77/gns3/plugins/modules/gns3_node.py b/collections/ansible_collections/davidban77/gns3/plugins/modules/gns3_node.py deleted file mode 100644 index 5b9e882..0000000 --- a/collections/ansible_collections/davidban77/gns3/plugins/modules/gns3_node.py +++ /dev/null @@ -1,272 +0,0 @@ -#!/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() diff --git a/collections/ansible_collections/davidban77/gns3/plugins/modules/gns3_node_file.py b/collections/ansible_collections/davidban77/gns3/plugins/modules/gns3_node_file.py deleted file mode 100644 index 6d0c305..0000000 --- a/collections/ansible_collections/davidban77/gns3/plugins/modules/gns3_node_file.py +++ /dev/null @@ -1,192 +0,0 @@ -#!/usr/bin/env python - -ANSIBLE_METADATA = { - "metadata_version": "1.2", - "status": ["preview"], - "supported_by": "community", -} - -DOCUMENTATION = """ ---- -module: gns3_node_file -short_description: Updates/creates a file on a node directory -version_added: '2.8' -description: - - "Updates/creates a file on a node directory of a GNS3 project" -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 - data: - description: - - The text to insert. - type: str - dest: - description: - - Node destination path. Like 'etc/network/interfaces' - type: str - required: true - state: - description: - - If the file should present or absent - type: str - choices: ['present', 'absent'] - default: present -""" - -EXAMPLES = """ -# Retrieve the GNS3 server version -- name: Get the server version - gns3_node_file: - url: http://localhost - port: 3080 - project_name: test_lab - node_name: alpine-1 - data: | - auto eth0 - iface eth0 inet dhcp - dest: /etc/network/interfaces -""" -import traceback - -GNS3FY_IMP_ERR = None -try: - from gns3fy import Gns3Connector, Project - - HAS_GNS3FY = True -except ImportError: - GNS3FY_IMP_ERR = traceback.format_exc() - HAS_GNS3FY = False - -from ansible.module_utils.basic import AnsibleModule, missing_required_lib - - -def node_write_file(module, node, path, data): - "Writes text data into specified path of the node" - try: - node.write_file(path=path, data=data) - except Exception as err: - module.fail_json(msg=str(err), exception=traceback.format_exc()) - - -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), - 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), - data=dict(type="str", default=None), - dest=dict(type="str", required=True), - state=dict(type="str", choices=["present", "absent"], default="present"), - ), - required_one_of=[["project_name", "project_id"], ["node_name", "node_id"]], - ) - if not HAS_GNS3FY: - module.fail_json(msg=missing_required_lib("gns3fy"), exception=GNS3FY_IMP_ERR) - result = dict(changed=False) - - server_url = module.params["url"] - server_port = module.params["port"] - server_user = module.params["user"] - server_password = module.params["password"] - project_name = module.params["project_name"] - project_id = module.params["project_id"] - node_name = module.params["node_name"] - node_id = module.params["node_id"] - data = module.params["data"] - dest = module.params["dest"] - state = module.params["state"] - if state == "present" and data is None: - module.fail_json(msg="Parameter needs to be passed: data", **result) - - # 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) - - # Retrieve project info - project.get() - - # Define the 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) - - # Try to get file data - try: - file_data = node.get_file(path=dest) - except Exception as err: - if "not found" in str(err): - file_data = None - else: - module.fail_json(msg=str(err), exception=traceback.format_exc()) - - if state == "absent": - if file_data is None or file_data == "": - result.update(changed=False) - else: - # Delete node file data - # As of now (GNS3 v2.2.rc5) the DELETE method is not allowed - node_write_file(module, node, dest, "") - result.update(changed=True) - elif state == "present": - if file_data == data: - result.update(changed=False) - else: - node_write_file(module, node, dest, data) - result.update(changed=True) - - module.exit_json(**result) - - -if __name__ == "__main__": - main() diff --git a/collections/ansible_collections/davidban77/gns3/plugins/modules/gns3_nodes_inventory.py b/collections/ansible_collections/davidban77/gns3/plugins/modules/gns3_nodes_inventory.py deleted file mode 100644 index 5cd2ebe..0000000 --- a/collections/ansible_collections/davidban77/gns3/plugins/modules/gns3_nodes_inventory.py +++ /dev/null @@ -1,128 +0,0 @@ -#!/usr/bin/env python - -ANSIBLE_METADATA = { - "metadata_version": "1.2", - "status": ["preview"], - "supported_by": "community", -} - -DOCUMENTATION = """ ---- -module: gns3_nodes_inventory -short_description: Retrieves GNS3 a project nodes console information -version_added: '2.8' -description: - - "Retrieves nodes inventory information from a GNS3 project" -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 -""" - -EXAMPLES = """ -# Retrieve the GNS3 server version -- name: Get the server version - gns3_nodes_inventory: - url: http://localhost - port: 3080 - project_name: test_lab - register: nodes_inventory - -- debug: var=nodes_inventory -""" - -RETURN = """ -nodes_inventory: - description: Dictionary that contain: name, server, console_port, console_type, - type and template of each node - type: dict -total_nodes: - description: Total number of nodes - type: int -""" -import traceback - -GNS3FY_IMP_ERR = None -try: - from gns3fy import Gns3Connector, Project - - HAS_GNS3FY = True -except ImportError: - GNS3FY_IMP_ERR = traceback.format_exc() - HAS_GNS3FY = False - -from ansible.module_utils.basic import AnsibleModule, missing_required_lib - - -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), - project_name=dict(type="str", default=None), - project_id=dict(type="str", default=None), - ), - required_one_of=[["project_name", "project_id"]], - ) - if not HAS_GNS3FY: - module.fail_json(msg=missing_required_lib("gns3fy"), exception=GNS3FY_IMP_ERR) - result = dict(changed=False, nodes_inventory=None, total_nodes=None) - - server_url = module.params["url"] - server_port = module.params["port"] - server_user = module.params["user"] - server_password = module.params["password"] - project_name = module.params["project_name"] - project_id = module.params["project_id"] - - # 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) - - # Retrieve project info - project.get() - - nodes_inventory = project.nodes_inventory() - result.update( - nodes_inventory=nodes_inventory, total_nodes=len(nodes_inventory.keys()) - ) - - module.exit_json(**result) - - -if __name__ == "__main__": - main() diff --git a/collections/ansible_collections/davidban77/gns3/plugins/modules/gns3_project.py b/collections/ansible_collections/davidban77/gns3/plugins/modules/gns3_project.py deleted file mode 100644 index 405248a..0000000 --- a/collections/ansible_collections/davidban77/gns3/plugins/modules/gns3_project.py +++ /dev/null @@ -1,434 +0,0 @@ -#!/usr/bin/env python - -ANSIBLE_METADATA = { - "metadata_version": "1.4", - "status": ["preview"], - "supported_by": "community", -} - -DOCUMENTATION = """ ---- -module: gns3_project -short_description: Module to interact with GNS3 server projects -version_added: '2.8' -description: - - 'Module to interact with GNS3 server projects. - - It is using the L(gns3fy library,https://davidban77.github.io/gns3fy/)' - - It opens/closes projects and performs basic turnup/teradown operations on nodes. - - It creates/updates or deletes projects. -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 - state: - description: - - State of the project to be on the GNS3 server - - '- C(opened): Opens a project and turns up nodes' - - '- C(closed): Closes a project and turns down nodes' - - '- C(present): Creates/update a project on the server' - - '- C(absent): Deletes a project on the server' - type: str - choices: ['opened', 'closed', 'present', 'absent'] - project_name: - description: - - Project name - type: str - project_id: - description: - - Project ID - type: str - nodes_state: - description: - - Starts/stops nodes on the project. - - Used when I(state) is C(opened)/C(closed) - type: str - choices: ['started', 'stopped'] - nodes_strategy: - description: - - Start/stop strategy of the devices defined on the project. - - '- C(all): It starts/stops all nodes at once' - - '- C(one_by_one): It starts/stops nodes serialy using I(nodes_delay) time - between each action' - - Used when I(state) is C(opened)/C(closed) - type: str - choices: ['all', 'one_by_one'] - default: 'all' - nodes_delay: - description: - - Delay time in seconds to wait between nodes start/stop - - Used when I(nodes_strategy) is C(one_by_one) - type: int - default: 10 - 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 - nodes_spec: - description: - - List of dictionaries specifying the nodes properties. - - '- Mandatory attributes: C(name), C(node_type) and C(template).' - - '- Optional attributes: C(compute_id). It defaults to C(local)' - type: list - links_spec: - description: - - 'List of lists specifying the links endpoints. Example: C(- ["alpine-1", - "eth0", "alpine-2", "eth0"])' - - 'Mandatory attributes: C(node_a), C(port_a), C(node_b) and C(port_b)' - type: list -""" - -EXAMPLES = """ -# Open a GNS3 project -- name: Start lab - gns3_project: - url: http://localhost - state: opened - project_name: lab_example - -# Stop all nodes inside an open project -- name: Stop nodes - gns3_project: - url: http://localhost - state: opened - project_name: lab_example - nodes_state: stopped - nodes_strategy: all - poll_wait_time: 5 - -# Open a GNS3 project and start nodes one by one with a delay of 10sec between them -- name: Start nodes one by one - gns3_project: - url: http://localhost - state: opened - project_name: lab_example - nodes_state: started - nodes_strategy: one_by_one - nodes_delay: 10 - -# Close a GNS3 project -- name: Stop lab - gns3_project: - url: http://localhost - state: closed - project_id: 'UUID-SOMETHING-1234567' - -# Create a GNS3 project -- name: Create a project given nodes and links specs - gns3_project: - url: http://localhost - state: present - project_name: new_lab - nodes_spec: - - name: alpine-1 - node_type: docker - template: alpine - - name: alpine-2 - node_type: docker - template: alpine - links_spec: - - ('alpine-1', 'eth0', 'alpine-2', 'eth1') - -# Delete a GNS3 project -- name: Delete project - gns3_project: - url: http://localhost - state: absent - project_name: new_lab -""" - -RETURN = """ -name: - description: Project name - type: str -project_id: - description: Project UUID - type: str -status: - description: Project status. Possible values: opened, closed - type: str -path: - description: Path of the project on the server (works only with compute=local) - type: str -auto_close: - description: Project auto close when client cut off the notifications feed - type: bool -auto_open: - description: Project open when GNS3 start - type: bool -auto_start: - description: Project start when opened - type: bool -filename: - description: Project filename - 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_project_data(project): - "Returns the project main attributes" - return dict( - name=project.name, - project_id=project.project_id, - status=project.status, - path=project.path, - auto_close=project.auto_close, - auto_open=project.auto_open, - auto_start=project.auto_start, - filename=project.filename, - ) - - -# def nodes_state_verification(module, project, result): -def nodes_state_verification( - expected_nodes_state, nodes_strategy, nodes_delay, poll_wait_time, project -): - "Verifies each node state and returns a changed attribute" - nodes_statuses = [node.status for node in project.nodes] - - # Verify if nodes do not match expected state - if expected_nodes_state == "started" and any( - status == "stopped" for status in nodes_statuses - ): - # Turnup the nodes based on strategy - if nodes_strategy == "all": - project.start_nodes(poll_wait_time=poll_wait_time) - elif nodes_strategy == "one_by_one": - for node in project.nodes: - if node.status != "started": - node.start() - time.sleep(nodes_delay) - return True - elif expected_nodes_state == "stopped" and any( - status == "started" for status in nodes_statuses - ): - # Shutdown nodes based on strategy - if nodes_strategy == "all": - project.stop_nodes(poll_wait_time=poll_wait_time) - elif nodes_strategy == "one_by_one": - for node in project.nodes: - if node.status != "stopped": - node.stop() - time.sleep(nodes_delay) - return True - return False - - -def create_node(node_spec, project, module): - "Creates the node specified in nodes_spec" - # If exceptions occur then print them out in ansible format - try: - project.create_node(**node_spec) - except Exception as err: - module.fail_json(msg=str(err), exception=traceback.format_exc()) - - -def create_link(link_spec, project, module): - "Creates the node specified in nodes_spec" - # If exceptions occur then print them out in ansible format - try: - project.create_link(*link_spec) - except ValueError as err: - if "At least one port is used" in str(err): - return False - else: - module.fail_json(msg=str(err), exception=traceback.format_exc()) - except Exception as err: - module.fail_json(msg=str(err), exception=traceback.format_exc()) - return True - - -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=["opened", "closed", "present", "absent"], - ), - project_name=dict(type="str", default=None), - project_id=dict(type="str", default=None), - nodes_state=dict(type="str", choices=["started", "stopped"]), - nodes_strategy=dict( - type="str", choices=["all", "one_by_one"], default="all" - ), - nodes_delay=dict(type="int", default=10), - poll_wait_time=dict(type="int", default=5), - nodes_spec=dict(type="list"), - links_spec=dict(type="list"), - ), - supports_check_mode=True, - required_one_of=[["project_name", "project_id"]], - required_if=[["nodes_strategy", "one_by_one", ["nodes_delay"]]], - ) - result = dict(changed=False) - if not HAS_GNS3FY: - module.fail_json(msg=missing_required_lib("gns3fy"), exception=GNS3FY_IMP_ERR) - if module.check_mode: - module.exit_json(**result) - - 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"] - nodes_state = module.params["nodes_state"] - nodes_strategy = module.params["nodes_strategy"] - nodes_delay = module.params["nodes_delay"] - poll_wait_time = module.params["poll_wait_time"] - nodes_spec = module.params["nodes_spec"] - links_spec = module.params["links_spec"] - - 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) - except Exception as err: - module.fail_json(msg=str(err), **result) - - #  Retrieve project information - try: - project.get() - pr_exists = True - except Exception as err: - pr_exists = False - reason = str(err) - - if state == "opened": - if pr_exists: - if project.status != "opened": - # Open project - project.open() - - # Now verify nodes - if nodes_state is not None: - - # Change flag based on the nodes state - result["changed"] = nodes_state_verification( - expected_nodes_state=nodes_state, - nodes_strategy=nodes_strategy, - nodes_delay=nodes_delay, - poll_wait_time=poll_wait_time, - project=project, - ) - else: - # Means that nodes are not taken into account for idempotency - result["changed"] = True - # Even if the project is open if nodes_state has been set, check it - else: - if nodes_state is not None: - result["changed"] = nodes_state_verification( - expected_nodes_state=nodes_state, - nodes_strategy=nodes_strategy, - nodes_delay=nodes_delay, - poll_wait_time=poll_wait_time, - project=project, - ) - - else: - module.fail_json(msg=reason, **result) - - elif state == "closed": - if pr_exists: - if project.status != "closed": - # Close project - project.close() - result["changed"] = True - else: - module.fail_json(msg=reason, **result) - - elif state == "present": - if pr_exists: - if nodes_spec is not None: - # Need to verify if nodes exist - _nodes_already_created = [node.name for node in project.nodes] - for node_spec in nodes_spec: - if node_spec["name"] not in _nodes_already_created: - # Open the project in case it was closed - project.open() - create_node(node_spec, project, module) - result["changed"] = True - if links_spec is not None: - for link_spec in links_spec: - project.open() - # Trigger another get to refresh nodes attributes - project.get() - # Link verification is already built in the library - created = create_link(link_spec, project, module) - if created: - result["changed"] = True - else: - # Create project - project.create() - # Nodes section - if nodes_spec is not None: - for node_spec in nodes_spec: - create_node(node_spec, project, module) - # Links section - if links_spec is not None: - for link_spec in links_spec: - create_link(link_spec, project, module) - result["changed"] = True - elif state == "absent": - if pr_exists: - # Stop nodes and close project to perform delete gracefully - if project.status != "opened": - # Project needs to be opened in order to be deleted... - project.open() - project.stop_nodes(poll_wait_time=0) - project.delete() - result["changed"] = True - else: - module.exit_json(**result) - - # Return the project data - result["project"] = return_project_data(project) - module.exit_json(**result) - - -if __name__ == "__main__": - main() diff --git a/collections/ansible_collections/davidban77/gns3/plugins/modules/gns3_project_file.py b/collections/ansible_collections/davidban77/gns3/plugins/modules/gns3_project_file.py deleted file mode 100644 index f636a8a..0000000 --- a/collections/ansible_collections/davidban77/gns3/plugins/modules/gns3_project_file.py +++ /dev/null @@ -1,170 +0,0 @@ -#!/usr/bin/env python - -ANSIBLE_METADATA = { - "metadata_version": "1.2", - "status": ["preview"], - "supported_by": "community", -} - -DOCUMENTATION = """ ---- -module: gns3_project_file -short_description: Updates/creates a file on a project directory -version_added: '2.8' -description: - - "Updates/creates a file on a project directory on the GNS3 server" -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 - data: - description: - - The text to insert. - type: str - dest: - description: - - Node destination path. Like 'etc/network/interfaces' - type: str - required: true - state: - description: - - If the file should present or absent - type: str - choices: ['present', 'absent'] - default: present -""" - -EXAMPLES = """ -# Retrieve the GNS3 server version -- name: Get the server version - gns3_project_file: - url: http://localhost - port: 3080 - project_name: test_lab - data: | - Hello this is a README! - dest: README.txt -""" -import traceback - -GNS3FY_IMP_ERR = None -try: - from gns3fy import Gns3Connector, Project - - HAS_GNS3FY = True -except ImportError: - GNS3FY_IMP_ERR = traceback.format_exc() - HAS_GNS3FY = False - -from ansible.module_utils.basic import AnsibleModule, missing_required_lib - - -def project_write_file(module, project, path, data): - "Writes text data into specified path of the project" - try: - project.write_file(path=path, data=data) - except Exception as err: - module.fail_json(msg=str(err), exception=traceback.format_exc()) - - -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), - project_name=dict(type="str", default=None), - project_id=dict(type="str", default=None), - data=dict(type="str", default=None), - dest=dict(type="str", required=True), - state=dict(type="str", choices=["present", "absent"], default="present"), - ), - required_one_of=[["project_name", "project_id"]], - ) - if not HAS_GNS3FY: - module.fail_json(msg=missing_required_lib("gns3fy"), exception=GNS3FY_IMP_ERR) - result = dict(changed=False) - - server_url = module.params["url"] - server_port = module.params["port"] - server_user = module.params["user"] - server_password = module.params["password"] - project_name = module.params["project_name"] - project_id = module.params["project_id"] - data = module.params["data"] - dest = module.params["dest"] - state = module.params["state"] - if state == "present" and data is None: - module.fail_json(msg="Parameter needs to be passed: data", **result) - - # 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) - - # Retrieve project info - project.get() - - # Try to get file data - try: - file_data = project.get_file(path=dest) - except Exception as err: - if "Not Found" in str(err): - file_data = None - else: - module.fail_json(msg=str(err), exception=traceback.format_exc()) - - if state == "absent": - if file_data is None or file_data == "": - result.update(changed=False) - else: - # Delete project file data - # As of now (GNS3 v2.2.rc5) the DELETE method is not allowed - project_write_file(module, project, dest, "") - result.update(changed=True) - elif state == "present": - if file_data == data: - result.update(changed=False) - else: - project_write_file(module, project, dest, data) - result.update(changed=True) - - module.exit_json(**result) - - -if __name__ == "__main__": - main() diff --git a/collections/ansible_collections/davidban77/gns3/plugins/modules/gns3_snapshot.py b/collections/ansible_collections/davidban77/gns3/plugins/modules/gns3_snapshot.py deleted file mode 100644 index 75d9895..0000000 --- a/collections/ansible_collections/davidban77/gns3/plugins/modules/gns3_snapshot.py +++ /dev/null @@ -1,203 +0,0 @@ -#!/usr/bin/env python - -ANSIBLE_METADATA = { - "metadata_version": "1.1", - "status": ["preview"], - "supported_by": "community", -} - -DOCUMENTATION = """ ---- -module: gns3_snapshot -short_description: Module that interacts with snapshots of a project on GNS3 server -version_added: '2.8' -description: - - Module that interacts with snapshots of a project on GNS3 server -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 - snapshot_name: - description: - - Snapshot name - type: str - snapshot_id: - description: - - Snapshot ID - type: str - state: - description: - - Creates/deletes/restores a project snapshot. - - NOTE: The restore is not an idempotent task - type: str - choices: ['present', 'absent', 'restore'] - required: true -""" - -EXAMPLES = """ -# Retrieves all the information from the computes of GNS3 server -- name: Retrieve all the facts of a GNS3 server computes - gns3_snapshot: - url: http://localhost - project_name: demo_lab - snapshot_name: snap1 - state: present - register: result - -- debug: var=result - -# Retrieves only basic facts data of the GNS3 server computes -- gns3_snapshot: - url: http://localhost - project_name: demo_lab - snapshot_id: "SOME_UUID" - state: absent - -# Restores the project from a specific snapshot. This is NOT idempotent -- gns3_snapshot: - url: http://localhost - project_name: demo_lab - snapshot_name: snap1 - state: restore -""" - -RETURN = """ -created_at: - description: Unix format datetime - type: int -name: - description: Snapshot name - type: str -project_id: - description: Project UUID - type: str -snapshot_id: - description: Snapshot UUID - type: dict -""" - -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 main(): - module = AnsibleModule( - argument_spec=dict( - url=dict(type="str", required=True), - user=dict(type="str", default=None), - password=dict(type="str", default=None, no_log=True), - port=dict(type="int", default=3080), - state=dict( - type="str", required=True, choices=["present", "absent", "restore"] - ), - project_name=dict(type="str", default=None), - project_id=dict(type="str", default=None), - snapshot_name=dict(type="str", default=None), - snapshot_id=dict(type="str", default=None), - ), - required_one_of=[ - ["project_name", "project_id"], - ["snapshot_name", "snapshot_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"] - project_name = module.params["project_name"] - project_id = module.params["project_id"] - snapshot_name = module.params["snapshot_name"] - snapshot_id = module.params["snapshot_id"] - state = module.params["state"] - - 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) - - # Collect project and snapshots data - project.get() - snapshot = project.get_snapshot(name=snapshot_name, snapshot_id=snapshot_id) - - if state == "present": - if snapshot is None: - # Create the snapshot - if not snapshot_name: - module.fail_json( - msg="Need to specify snapshot name for creation", **result - ) - project.create_snapshot(name=snapshot_name) - result["changed"] = True - result["snapshot"] = project.get_snapshot( - name=snapshot_name, snapshot_id=snapshot_id - ) - else: - result["snapshot"] = snapshot - - elif state == "absent": - if snapshot: - #  Delete snapshot - project.delete_snapshot(name=snapshot_name, snapshot_id=snapshot_id) - result["changed"] = True - - elif state == "restore": - if not snapshot: - module.fail_json(msg="Snapshot not found", **result) - # Restore snapshot - project.restore_snapshot(name=snapshot_name, snapshot_id=snapshot_id) - result["changed"] = True - result["snapshot"] = snapshot - - module.exit_json(**result) - except Exception as err: - module.fail_json(msg=str(err), **result) - - -if __name__ == "__main__": - main() diff --git a/collections/ansible_collections/davidban77/gns3/plugins/modules/gns3_version.py b/collections/ansible_collections/davidban77/gns3/plugins/modules/gns3_version.py deleted file mode 100644 index 6ac8f99..0000000 --- a/collections/ansible_collections/davidban77/gns3/plugins/modules/gns3_version.py +++ /dev/null @@ -1,100 +0,0 @@ -#!/usr/bin/env python - -ANSIBLE_METADATA = { - "metadata_version": "1.3", - "status": ["preview"], - "supported_by": "community", -} - -DOCUMENTATION = """ ---- -module: gns3_version -short_description: Retrieves GNS3 server version -version_added: '2.8' -description: - - 'Retrieves GNS3 server version using gns3fy' -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 -""" - -EXAMPLES = """ -# Retrieve the GNS3 server version -- name: Get the server version - gns3_version: - url: http://localhost - port: 3080 - register: result - -- debug: var=result -""" - -RETURN = """ -local_compute: - description: Whether this is a local server or not - type: bool - returned: always -version: - description: Version number of the server - type: str - returned: always -""" -import traceback -from ansible.module_utils.basic import AnsibleModule, missing_required_lib - -GNS3FY_IMP_ERR = None -try: - from gns3fy import Gns3Connector - - HAS_GNS3FY = True -except Exception: - HAS_GNS3FY = False - GNS3FY_IMP_ERR = traceback.format_exc() - - -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), - ) - ) - if not HAS_GNS3FY: - module.fail_json(msg=missing_required_lib("gns3fy"), exception=GNS3FY_IMP_ERR) - result = dict(changed=False, local_compute=None, version=None) - server_url = module.params["url"] - server_port = module.params["port"] - server_user = module.params["user"] - server_password = module.params["password"] - - server = Gns3Connector( - url=f"{server_url}:{server_port}", user=server_user, cred=server_password - ) - _version = server.get_version() - result.update(local_compute=_version["local"], version=_version["version"]) - module.exit_json(**result) - - -if __name__ == "__main__": - main() diff --git a/collections/ansible_collections/davidban77/gns3/requirements.txt b/collections/ansible_collections/davidban77/gns3/requirements.txt deleted file mode 100644 index 5cd2c06..0000000 --- a/collections/ansible_collections/davidban77/gns3/requirements.txt +++ /dev/null @@ -1,2 +0,0 @@ -ansible>=2.8.0 -gns3fy>=0.5.2 diff --git a/collections/ansible_collections/davidban77/gns3/test/playbooks/ansible.cfg b/collections/ansible_collections/davidban77/gns3/test/playbooks/ansible.cfg deleted file mode 100644 index d65a64c..0000000 --- a/collections/ansible_collections/davidban77/gns3/test/playbooks/ansible.cfg +++ /dev/null @@ -1,6 +0,0 @@ -[defaults] -library = ../../plugins/modules -roles_path = ../../roles -nocows = 1 -retry_files_enabled = False -display_skipped_hosts = no diff --git a/collections/ansible_collections/davidban77/gns3/test/playbooks/create_files.yml b/collections/ansible_collections/davidban77/gns3/test/playbooks/create_files.yml deleted file mode 100644 index f7ff5ce..0000000 --- a/collections/ansible_collections/davidban77/gns3/test/playbooks/create_files.yml +++ /dev/null @@ -1,22 +0,0 @@ -- hosts: localhost - tasks: - - name: Play with a dummy file to node - gns3_node_file: - url: "{{ gns3_url }}" - project_name: "{{ gns3_project_name }}" - node_name: alpine-1 - state: present - dest: /etc/network/dummy_file - data: | - # Some data to insert on the file - auto eth0 - iface eth0 inect dhcp - - - name: Play with a dummy file on project - gns3_project_file: - url: "{{ gns3_url }}" - project_name: "{{ gns3_project_name }}" - state: present - dest: README.txt - data: | - Hello! this is a README diff --git a/collections/ansible_collections/davidban77/gns3/test/playbooks/delete_files.yml b/collections/ansible_collections/davidban77/gns3/test/playbooks/delete_files.yml deleted file mode 100644 index 0b51a33..0000000 --- a/collections/ansible_collections/davidban77/gns3/test/playbooks/delete_files.yml +++ /dev/null @@ -1,16 +0,0 @@ -- hosts: localhost - tasks: - - name: Play with a dummy file to node - gns3_node_file: - url: "{{ gns3_url }}" - project_name: "{{ gns3_project_name }}" - node_name: alpine-1 - state: absent - dest: /etc/network/dummy_file - - - name: Play with a dummy file on project - gns3_project_file: - url: "{{ gns3_url }}" - project_name: "{{ gns3_project_name }}" - state: absent - dest: README.txt diff --git a/collections/ansible_collections/davidban77/gns3/test/playbooks/facts.yml b/collections/ansible_collections/davidban77/gns3/test/playbooks/facts.yml deleted file mode 100644 index c8c0fa0..0000000 --- a/collections/ansible_collections/davidban77/gns3/test/playbooks/facts.yml +++ /dev/null @@ -1,18 +0,0 @@ -- hosts: localhost - gather_facts: no - tasks: - - name: Retrieve computes info all - gns3_facts: - url: "{{ gns3_url }}" - get_images: iou - get_compute_ports: no - register: resultado - - - debug: var=resultado - - # - name: Retrieves basic facts - # gns3_facts: - # url: "{{ gns3_url }}" - # register: resultado - - # - debug: var=resultado diff --git a/collections/ansible_collections/davidban77/gns3/test/playbooks/group_vars/all.yml b/collections/ansible_collections/davidban77/gns3/test/playbooks/group_vars/all.yml deleted file mode 100644 index 7ffbb25..0000000 --- a/collections/ansible_collections/davidban77/gns3/test/playbooks/group_vars/all.yml +++ /dev/null @@ -1,21 +0,0 @@ ---- -gns3_url: "http://dev_gns3server" -gns3_project_name: test_ansible -gns3_nodes_spec: - - name: veos-1 - template: "vEOS-4.21.5F" - - name: veos-2 - template: "vEOS-4.21.5F" - - name: ios-1 - template: "IOU-L2-15.1" - - name: ios-2 - template: "IOU-L3-15.4" - - name: alpine-1 - template: "alpine" -gns3_nodes_strategy: one_by_one -gns3_links_spec: - - ["veos-1", "Ethernet1", "veos-2", "Ethernet1"] - - ["veos-1", "Ethernet2", "ios-1", "Ethernet1/0"] - - ["veos-2", "Ethernet2", "ios-2", "Ethernet1/0"] - - ["ios-1", "Ethernet1/2", "ios-2", "Ethernet1/2"] - - ["ios-1", "Ethernet1/3", "alpine-1", "eth0"] diff --git a/collections/ansible_collections/davidban77/gns3/test/playbooks/main.yml b/collections/ansible_collections/davidban77/gns3/test/playbooks/main.yml deleted file mode 100644 index 48c0ac3..0000000 --- a/collections/ansible_collections/davidban77/gns3/test/playbooks/main.yml +++ /dev/null @@ -1,28 +0,0 @@ -- hosts: localhost - tasks: - - name: Get server version - gns3_facts: - url: "{{ gns3_url }}" - get_images: all - get_compute_ports: yes - register: resultado - - - debug: var=resultado - - - name: Creation/Active section - when: execute == "create" - block: - - import_role: - name: create_lab - - - name: Get nodes inventory - gns3_nodes_inventory: - url: "{{ gns3_url }}" - project_name: "{{ gns3_project_name }}" - register: nodes_inventory - - - debug: var=nodes_inventory - - - import_role: - name: delete_lab - when: execute == "delete" diff --git a/collections/ansible_collections/davidban77/gns3/test/playbooks/node_interaction.yml b/collections/ansible_collections/davidban77/gns3/test/playbooks/node_interaction.yml deleted file mode 100644 index 20828bd..0000000 --- a/collections/ansible_collections/davidban77/gns3/test/playbooks/node_interaction.yml +++ /dev/null @@ -1,28 +0,0 @@ -- hosts: localhost - gather_facts: no - tasks: - - name: Reload a node alpine node which requires a special reload - gns3_node: - url: "{{ gns3_url }}" - project_name: "{{ gns3_project_name }}" - node_name: alpine-1 - state: reload - retry: yes - poll_wait_time: 30 - - - name: Stop ios-1 - gns3_node: - url: "{{ gns3_url }}" - project_name: "{{ gns3_project_name }}" - node_name: ios-1 - state: stopped - - - name: Start ios-1 - gns3_node: - url: "{{ gns3_url }}" - project_name: "{{ gns3_project_name }}" - node_name: ios-1 - state: started - register: node - - - debug: var=node diff --git a/collections/ansible_collections/davidban77/gns3/test/playbooks/snapshots.yml b/collections/ansible_collections/davidban77/gns3/test/playbooks/snapshots.yml deleted file mode 100644 index 7949a03..0000000 --- a/collections/ansible_collections/davidban77/gns3/test/playbooks/snapshots.yml +++ /dev/null @@ -1,39 +0,0 @@ -- hosts: localhost - gather_facts: no - tasks: - - name: Stop nodes on the project - gns3_project: - url: "{{ gns3_url }}" - project_name: "{{ gns3_project_name }}" - state: opened - nodes_state: stopped - - - name: Create snapshot - gns3_snapshot: - url: "{{ gns3_url }}" - project_name: "{{ gns3_project_name }}" - snapshot_name: snap - state: present - register: resultado - - - debug: var=resultado - - - pause: - minutes: 1 - - - name: Restore snapshot - gns3_snapshot: - url: "{{ gns3_url }}" - project_name: "{{ gns3_project_name }}" - snapshot_name: snap - state: restore - - - pause: - minutes: 1 - - - name: Delete snapshot - gns3_snapshot: - url: "{{ gns3_url }}" - project_name: "{{ gns3_project_name }}" - snapshot_name: snap - state: absent diff --git a/collections/requirements.yml b/collections/requirements.yml index 9580d1b..5d42bbb 100644 --- a/collections/requirements.yml +++ b/collections/requirements.yml @@ -17,3 +17,6 @@ collections: - name: redhat.satellite source: https://cloud.redhat.com/api/automation-hub/ + + - name: community.general + source: https://galaxy.ansible.com diff --git a/roles/toal-common/tasks/main.yml b/roles/toal-common/tasks/main.yml index 4f4cbbd..44f3c11 100644 --- a/roles/toal-common/tasks/main.yml +++ b/roles/toal-common/tasks/main.yml @@ -47,12 +47,3 @@ name: insights-client state: present when: ansible_distribution == "RedHat" - -- name: Performance Co-Pilot - yum: - name: - - pcp-system-tools - - pcp-zeroconf - - cockpit-pcp - - pcp-pmda-trace - - pcp-selinux diff --git a/satellite.yml b/satellite.yml index 993fdb7..c596e29 100644 --- a/satellite.yml +++ b/satellite.yml @@ -1,34 +1,32 @@ # Playbook to install Satellite server on RHV -# TODO: Autocreate pxeboot environment on tftp server. This was a partial attempt to create the ks file -# and dump it on the NAS. -# Note for my future self: Don't bother trying to attach a VFD/ISO with the ks file. It will all -# end in tears, because RHV4.2 doesn't have the APIs / functionality. +- name: Prepare RHV for Build + hosts: localhost + gather_facts: no + tasks: + - name: Obtain SSO token from username / password credentials + redhat.rhv.ovirt_auth: + url: "{{ ovirt_url }}" + username: "{{ ovirt_username }}" + password: "{{ ovirt_password }}" -# - name: Prepare Kickstart Files -# hosts: vms -# connection: local -# gather_facts: no - -# tasks: - # - name: Get first nfs server - # set_fact: ks_nfs_server="{{ groups['nfs_server'][0] }}" - # - set_fact: ks_file="{{ hostvars[ks_nfs_server]['nfs_dir'] }}/{{ inventory_hostname }}.cfg" - - # - name: Copy ks file to builddir - # template: - # src: templates/ks.cfg - # dest: "{{ ks_file }}" - # delegate_to: "{{ ks_nfs_server }}" + - name: ISO is uploaded to RHV + redhat.rhv.ovirt_disk: + name: "{{ rhel_iso_filename }}" + upload_image_path: "{{ rhel_iso_path }}/{{ rhel_iso_filename }}" + storage_domain: ssdvdo0 + size: 5 GiB + wait: true + bootable: true + format: raw + content_type: iso + register: iso_disk - name: Create VMs - hosts: vms + hosts: "{{ vm_name }}" connection: local gather_facts: no # Never run this, unless specifically enabled - tags: - - never - - rebuild vars: # Hack to work around virtualenv python interpreter ansible_python_interpreter: "{{ ansible_playbook_python }}" @@ -36,184 +34,196 @@ tasks: - name: Remove known_hosts entry known_hosts: - name: "{{ inventory_hostname }}" + name: "{{ vm_name }}" state: absent - - name: Create VM Disks + - name: Create VM disk ovirt_disk: - auth: "{{ ovirt_auth }}" - name: '{{ item.name }}' - description: '{{ item.descr }}' - interface: '{{ item.interface }}' - size: '{{ item.size }}' - state: '{{ item.state }}' - sparse: '{{ item.sparse }}' + name: "{{ vm_name }}_Disk0" + description: '{{ vm_name }} Primary Disk' + interface: 'virtio_scsi' + size: '{{ disk }}GiB' + state: attached + sparse: yes wait: true - storage_domain: "{{ item.storage_domain }}" + storage_domain: "ssdvdo0" async: 300 poll: 15 - loop: "{{ vm_disks }}" - # If we change the disks, we will PXE Boot the Server for install - notify: PXE Boot - name: Create Satellite VM in RHV ovirt_vm: - auth: "{{ ovirt_auth }}" name: "{{ vm_name }}" state: present - memory: "{{ vm_memory }}" - disks: "{{ vm_disks }}" - cpu_cores: "{{ vm_cpu_cores }}" - cluster: "{{ vm_cluster }}" - operating_system: "{{ vm_os }}" + memory: "{{ memory}}GiB" + disks: + - name: "{{ vm_name }}_Disk0" + activate: yes + bootable: yes + cpu_cores: "{{ vcpus }}" + cluster: "{{ cluster }}" + operating_system: "rhel_7x64" type: server graphical_console: protocol: - - spice - vnc boot_devices: - hd async: 300 poll: 15 + register: vm_result - name: Assign NIC ovirt_nic: - auth: "{{ ovirt_auth }}" interface: virtio - mac_address: "{{ vm_mac_address }}" name: nic1 profile: ovirtmgmt network: ovirtmgmt state: plugged vm: "{{ vm_name }}" + register: nic_result - handlers: - - name: PXE Boot - ovirt_vm: - auth: "{{ ovirt_auth }}" - name: "{{ vm_name }}" - boot_devices: - - network - state: running - register: vm_build_result - -- name: Ensure Satellite is running and reachable - hosts: satellite - gather_facts: no +- name: Prepare First Boot Resources + hosts: "{{ vm_name }}" connection: local + gather_facts: no + + tasks: + - name: Create directory for initial boot files + tempfile: + state: directory + register: kstmpdir + + - name: Extract ISO files + community.general.iso_extract: + image: "{{ rhel_iso_path }}/{{ rhel_iso_filename }}" + dest: "{{ kstmpdir.path }}" + files: + - isolinux/vmlinuz + - isolinux/initrd.img + +# TODO Move out vars +- name: Copy Files to Webserver + hosts: webserver.mgmt.toal.ca + become: yes + tasks: + - name: Generate Kickstart File + template: + src: templates/ks.cfg + dest: "/var/www/ks/{{ vm_name }}.cfg" + +- name: Prepare Hypervisor + hosts: "{{ vm_host }}" + tasks: + - name: Temporary Directory + file: + path: "/tmp/{{ vm_name }}" + state: directory + mode: 0755 + + - name: Transfer files to Hypervisor + copy: + src: "{{ hostvars[vm_name].kstmpdir.path }}/{{ item }}" + dest: "/tmp/{{ vm_name }}/{{ item }}" + loop: + - vmlinuz + - initrd.img + +# NOTE: This is not idempotent +- name: First Boot + hosts: localhost + gather_facts: no vars: # Hack to work around virtualenv python interpreter ansible_python_interpreter: "{{ ansible_playbook_python }}" - - tasks: - - name: VM is running + + tasks: + - block: + - name: Start VM with first-boot parameters + ovirt_vm: + name: "{{ vm_name }}" + host: "{{ vm_host }}" + kernel_params_persist: false + cd_iso: "{{ iso_disk.id }}" + kernel_path: "/tmp/{{ vm_name }}/vmlinuz" + kernel_params: "ks=http://192.168.1.199/ks/{{ vm_name }}.cfg inst.stage2=hd:LABEL=RHEL-7.9\\x20Server.x86_64" + initrd_path: "/tmp/{{ vm_name }}/initrd.img" + state: running + + + - name: Wait for system to shut down after installation + ovirt_vm_info: + pattern: "name={{ vm_name }}" + register: vm_info + until: vm_info['ovirt_vms'][0]['status'] == "down" + delay: 20 + retries: 60 + when: hostvars[vm_name].vm_result.vm.status != 'up' + + - name: Power up VM + ovirt_vm: + name: "{{ vm_name }}" + state: running + + - name: VM is running + connection: local ovirt_vm: - auth: "{{ ovirt_auth }}" name: "{{ vm_name }}" state: running boot_devices: - hd - + +- name: Ensure Satellite is reachable + hosts: "{{ vm_name }}" + gather_facts: no + + tasks: + - name: Set authentication for bootstrap + no_log: True + set_fact: + ansible_ssh_user: "root" + ansible_ssh_pass: "{{ initial_root_pass }}" + - name: Wait for SSH to be ready wait_for_connection: timeout: 1800 sleep: 5 - -- name: Set up ipa-client - hosts: satellite - remote_user: root - vars: - ansible_ssh_pass: "{{ satellite_root_pass }}" - become: no - roles: - - alvaroaleman.freeipa-client - pre_tasks: - - name: Register to RHSM and connect to Satellite Subscription. - tags: rhsm + + - name: Register System to Red Hat redhat_subscription: state: present - auto_attach: yes username: "{{ rhn_username }}" password: "{{ rhn_password }}" - pool: "^Red Hat Satellite Infrastructure Subscription$" + # TODO This shouldn't be hard-coded + pool_ids: 8a85f99c727637ad0172e1ba2856736d + +- name: Set up IPA Client + hosts: "{{ vm_name }}" + become: yes + vars: + ipaclient_realm: IDM.TOAL.CA + ipaclient_mkhomedir: true + ipaclient_domain: "mgmt.toal.ca" + ipasssd_enable_dns_updates: true + collections: + - freeipa.ansible_freeipa + pre_tasks: - name: Set hostname - hostname: - name: "{{ansible_host}}" + hostname: + name: "{{ vm_name }}" + + roles: + - role: debian-freeipa-client + when: ansible_os_family == "Debian" + - role: ipaclient + state: present + when: ansible_os_family == "RedHat" + +- name: Set up Basic Lab Packages + hosts: "{{ vm_name }}" + become: yes + roles: + - role: toal-common - name: Configure Satellite Servers - hosts: satellite + hosts: "{{ vm_name }}" become: true - roles: - - ansible-role-redhat_satellite6_installation - pre_tasks: - # This could take a while, if we are creating the VM from scratch, and installing - # the base software - - # - name: Required Satellite Repos - # tags: rhsm - # rhsm_repository: - # name: "{{ item }}" - # state: present - # with_items: - # - rhel-7-server-rpms - # - rhel-server-rhscl-7-rpms - # - rhel-7-server-satellite-6.4-rpms - # - rhel-7-server-satellite-maintenance-6-rpms - # - rhel-7-server-ansible-2.6-rpms - # - rhel-7-server-rh-common-rpms - - - name: Ensure latest versions of packages - yum: - name: "*" - state: latest - - - name: Chronyd Installed - yum: - name: chrony - state: latest - notify: Restart Chrony - - - name: IdM Client - yum: - name: ipa-client - state: latest - - - name: Latest Version of SOS - yum: - name: sos - state: latest - -# TODO: set this in Administer -> Settings -> Puppet Puppet out of sync disabled = Yes -# Description: Disable host configuration status turning to out of sync for Puppet after report does not arrive within configured interval - -# TODO: Make this work -# For now: -# hammer user-group create --admin yes --name satellite_admins -# hammer user-group external create --name satellite_admins --user-group satellite_admins --auth-source-id 3 - -# - name: Satellite configuration -# hosts: satellite -# gather_facts: no -# connection: local -# vars: -# # Hack to work around virtualenv python interpreter -# ansible_python_interpreter: "{{ ansible_playbook_python }}" - -# tasks: -# - foreman: -# username: admin -# password: "{{satellite_deployment_admin_password}}" -# server_url: "https://{{satellite_deployment_hostname_full}}" -# entity: user-group -# params: -# name: satellite_admins -# admin: yes - -# - foreman: -# username: admin -# password: "{{satellite_deployment_admin_password}}" -# server_url: "https://{{satellite_deployment_hostname_full}}" -# entity: -# params: -# name: satellite_admins -# admin: yes diff --git a/templates/ks.cfg b/templates/ks.cfg index 558fba2..1504847 100644 --- a/templates/ks.cfg +++ b/templates/ks.cfg @@ -1,18 +1,20 @@ lang en_CA keyboard us timezone America/Toronto --isUtc -rootpw $1$3Sx/AUYD$VOS6XPI5U5x3pW4CA6m1y0 --iscrypted +rootpw {{ initial_root_pass|password_hash('sha512') }} --iscrypted sshpw --username=ptoal $1$3Sx/AUYD$VOS6XPI5U5x3pW4CA6m1y0 --iscrypted #platform x86, AMD64, or Intel EM64T -reboot +poweroff text cdrom bootloader --location=mbr --append="rhgb quiet crashkernel=auto" zerombr +{% set ipaddr=hostvars[vm_name].interfaces[0]['ip_addresses'][0]['address']|ansible.netcommon.ipaddr('address') %} +{% set ipmask=hostvars[vm_name].interfaces[0]['ip_addresses'][0]['address']|ansible.netcommon.ipaddr('netmask') %} +network --bootproto=static --ip={{ ipaddr }} --netmask={{ ipmask }} --gateway=192.168.90.1 --nameserver=192.168.90.1 clearpart --none autopart eula --agreed -network --device=eth0 --bootproto=static --ip=192.168.90.2 --netmask=255.255.255.0 --gateway=192.168.90.1 --nameserver=192.168.90.1 auth --passalgo=sha512 --useshadow selinux --enforcing firewall --enabled --ssh