summaryrefslogtreecommitdiffstats
path: root/ansible_collections/openvswitch
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-13 12:04:41 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-13 12:04:41 +0000
commit975f66f2eebe9dadba04f275774d4ab83f74cf25 (patch)
tree89bd26a93aaae6a25749145b7e4bca4a1e75b2be /ansible_collections/openvswitch
parentInitial commit. (diff)
downloadansible-975f66f2eebe9dadba04f275774d4ab83f74cf25.tar.xz
ansible-975f66f2eebe9dadba04f275774d4ab83f74cf25.zip
Adding upstream version 7.7.0+dfsg.upstream/7.7.0+dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'ansible_collections/openvswitch')
-rw-r--r--ansible_collections/openvswitch/openvswitch/.github/workflows/codecoverage.yml15
-rw-r--r--ansible_collections/openvswitch/openvswitch/.github/workflows/test.yml32
-rw-r--r--ansible_collections/openvswitch/openvswitch/.gitignore1
-rw-r--r--ansible_collections/openvswitch/openvswitch/.isort.cfg4
-rw-r--r--ansible_collections/openvswitch/openvswitch/.pre-commit-config.yaml35
-rw-r--r--ansible_collections/openvswitch/openvswitch/.prettierignore17
-rw-r--r--ansible_collections/openvswitch/openvswitch/.yamllint15
-rw-r--r--ansible_collections/openvswitch/openvswitch/CHANGELOG.rst129
-rw-r--r--ansible_collections/openvswitch/openvswitch/FILES.json782
-rw-r--r--ansible_collections/openvswitch/openvswitch/LICENSE674
-rw-r--r--ansible_collections/openvswitch/openvswitch/MANIFEST.json33
-rw-r--r--ansible_collections/openvswitch/openvswitch/README.md109
-rw-r--r--ansible_collections/openvswitch/openvswitch/bindep.txt9
-rw-r--r--ansible_collections/openvswitch/openvswitch/changelogs/.plugin-cache.yaml39
-rw-r--r--ansible_collections/openvswitch/openvswitch/changelogs/changelog.yaml114
-rw-r--r--ansible_collections/openvswitch/openvswitch/changelogs/config.yaml32
-rw-r--r--ansible_collections/openvswitch/openvswitch/codecov.yml10
-rw-r--r--ansible_collections/openvswitch/openvswitch/docs/openvswitch.openvswitch.openvswitch_bond_module.rst341
-rw-r--r--ansible_collections/openvswitch/openvswitch/docs/openvswitch.openvswitch.openvswitch_bridge_module.rst232
-rw-r--r--ansible_collections/openvswitch/openvswitch/docs/openvswitch.openvswitch.openvswitch_db_module.rst305
-rw-r--r--ansible_collections/openvswitch/openvswitch/docs/openvswitch.openvswitch.openvswitch_port_module.rst236
-rw-r--r--ansible_collections/openvswitch/openvswitch/meta/runtime.yml12
-rw-r--r--ansible_collections/openvswitch/openvswitch/plugins/modules/__init__.py0
-rw-r--r--ansible_collections/openvswitch/openvswitch/plugins/modules/openvswitch_bond.py391
-rw-r--r--ansible_collections/openvswitch/openvswitch/plugins/modules/openvswitch_bridge.py286
-rw-r--r--ansible_collections/openvswitch/openvswitch/plugins/modules/openvswitch_db.py314
-rw-r--r--ansible_collections/openvswitch/openvswitch/plugins/modules/openvswitch_port.py282
-rw-r--r--ansible_collections/openvswitch/openvswitch/pyproject.toml7
-rw-r--r--ansible_collections/openvswitch/openvswitch/requirements.txt0
-rw-r--r--ansible_collections/openvswitch/openvswitch/test-requirements.txt7
-rw-r--r--ansible_collections/openvswitch/openvswitch/tests/.gitignore1
-rw-r--r--ansible_collections/openvswitch/openvswitch/tests/integration/network-integration.cfg4
-rw-r--r--ansible_collections/openvswitch/openvswitch/tests/integration/target-prefixes.network1
-rw-r--r--ansible_collections/openvswitch/openvswitch/tests/integration/targets/openvswitch_bridge/aliases1
-rw-r--r--ansible_collections/openvswitch/openvswitch/tests/integration/targets/openvswitch_bridge/defaults/main.yaml3
-rw-r--r--ansible_collections/openvswitch/openvswitch/tests/integration/targets/openvswitch_bridge/meta/main.yaml3
-rw-r--r--ansible_collections/openvswitch/openvswitch/tests/integration/targets/openvswitch_bridge/tasks/main.yml16
-rw-r--r--ansible_collections/openvswitch/openvswitch/tests/integration/targets/openvswitch_bridge/tests/basic.yaml65
-rw-r--r--ansible_collections/openvswitch/openvswitch/tests/integration/targets/openvswitch_db/aliases1
-rw-r--r--ansible_collections/openvswitch/openvswitch/tests/integration/targets/openvswitch_db/defaults/main.yaml3
-rw-r--r--ansible_collections/openvswitch/openvswitch/tests/integration/targets/openvswitch_db/meta/main.yaml3
-rw-r--r--ansible_collections/openvswitch/openvswitch/tests/integration/targets/openvswitch_db/tasks/main.yml16
-rw-r--r--ansible_collections/openvswitch/openvswitch/tests/integration/targets/openvswitch_db/tests/basic.yaml182
-rw-r--r--ansible_collections/openvswitch/openvswitch/tests/integration/targets/prepare_ovs_tests/tasks/main.yml37
-rw-r--r--ansible_collections/openvswitch/openvswitch/tests/sanity/ignore-2.10.txt0
-rw-r--r--ansible_collections/openvswitch/openvswitch/tests/sanity/ignore-2.9.txt0
-rw-r--r--ansible_collections/openvswitch/openvswitch/tests/unit/__init__.py0
-rw-r--r--ansible_collections/openvswitch/openvswitch/tests/unit/compat/__init__.py0
-rw-r--r--ansible_collections/openvswitch/openvswitch/tests/unit/compat/mock.py125
-rw-r--r--ansible_collections/openvswitch/openvswitch/tests/unit/compat/unittest.py39
-rw-r--r--ansible_collections/openvswitch/openvswitch/tests/unit/mock/__init__.py0
-rw-r--r--ansible_collections/openvswitch/openvswitch/tests/unit/mock/loader.py116
-rw-r--r--ansible_collections/openvswitch/openvswitch/tests/unit/mock/path.py9
-rw-r--r--ansible_collections/openvswitch/openvswitch/tests/unit/mock/procenv.py95
-rw-r--r--ansible_collections/openvswitch/openvswitch/tests/unit/mock/vault_helper.py39
-rw-r--r--ansible_collections/openvswitch/openvswitch/tests/unit/mock/yaml_helper.py152
-rw-r--r--ansible_collections/openvswitch/openvswitch/tests/unit/modules/__init__.py0
-rw-r--r--ansible_collections/openvswitch/openvswitch/tests/unit/modules/conftest.py31
-rw-r--r--ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/__init__.py0
-rw-r--r--ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/__init__.py0
-rw-r--r--ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/__init__.py0
-rw-r--r--ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/br_get_external_id_foo_bar.cfg1
-rw-r--r--ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/br_to_parent_test_br.cfg1
-rw-r--r--ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/br_to_vlan_zero.cfg1
-rw-r--r--ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/get_fail_mode_secure.cfg1
-rw-r--r--ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/get_port_bond0_external_ids.cfg1
-rw-r--r--ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/get_port_bond0_other_config.cfg1
-rw-r--r--ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/get_port_eth2_external_ids.cfg1
-rw-r--r--ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/get_port_eth2_tag.cfg1
-rw-r--r--ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/list_br_test_br.cfg1
-rw-r--r--ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/list_ports_bond_br.cfg1
-rw-r--r--ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/list_ports_test_br.cfg1
-rw-r--r--ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/openvswitch_db_disable_in_band_missing.cfg23
-rw-r--r--ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/openvswitch_db_disable_in_band_true.cfg23
-rw-r--r--ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/ovs_module.py87
-rw-r--r--ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/test_openvswitch_bond.py175
-rw-r--r--ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/test_openvswitch_bridge.py299
-rw-r--r--ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/test_openvswitch_db.py328
-rw-r--r--ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/test_openvswitch_port.py289
-rw-r--r--ansible_collections/openvswitch/openvswitch/tests/unit/modules/utils.py53
-rw-r--r--ansible_collections/openvswitch/openvswitch/tests/unit/requirements.txt42
-rw-r--r--ansible_collections/openvswitch/openvswitch/tox.ini31
82 files changed, 6766 insertions, 0 deletions
diff --git a/ansible_collections/openvswitch/openvswitch/.github/workflows/codecoverage.yml b/ansible_collections/openvswitch/openvswitch/.github/workflows/codecoverage.yml
new file mode 100644
index 000000000..b425edcc2
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/.github/workflows/codecoverage.yml
@@ -0,0 +1,15 @@
+---
+name: Code Coverage
+
+on: # yamllint disable-line rule:truthy
+ push:
+ pull_request:
+ branches: [ main ]
+
+jobs:
+ codecoverage:
+ uses: ansible-network/github_actions/.github/workflows/coverage_network_devices.yml@main
+ with:
+ collection_pre_install: >-
+ git+https://github.com/ansible-collections/ansible.utils.git
+ git+https://github.com/ansible-collections/ansible.netcommon.git
diff --git a/ansible_collections/openvswitch/openvswitch/.github/workflows/test.yml b/ansible_collections/openvswitch/openvswitch/.github/workflows/test.yml
new file mode 100644
index 000000000..428b1cf36
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/.github/workflows/test.yml
@@ -0,0 +1,32 @@
+name: Test collection
+
+concurrency:
+ group: ${{ github.head_ref }}
+ cancel-in-progress: true
+
+on:
+ pull_request:
+ branches: [main]
+ workflow_dispatch:
+
+jobs:
+ changelog:
+ uses: ansible-network/github_actions/.github/workflows/changelog.yml@main
+ sanity:
+ uses: ansible-network/github_actions/.github/workflows/sanity.yml@main
+ unit-galaxy:
+ uses: ansible-network/github_actions/.github/workflows/unit_galaxy.yml@main
+ all_green:
+ if: ${{ always() }}
+ needs:
+ - changelog
+ - sanity
+ - unit-galaxy
+ runs-on: ubuntu-latest
+ steps:
+ - run: >-
+ python -c "assert set([
+ '${{ needs.changelog.result }}',
+ '${{ needs.sanity.result }}',
+ '${{ needs.unit-galaxy.result }}',
+ ]) == {'success'}"
diff --git a/ansible_collections/openvswitch/openvswitch/.gitignore b/ansible_collections/openvswitch/openvswitch/.gitignore
new file mode 100644
index 000000000..172bf5786
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/.gitignore
@@ -0,0 +1 @@
+.tox
diff --git a/ansible_collections/openvswitch/openvswitch/.isort.cfg b/ansible_collections/openvswitch/openvswitch/.isort.cfg
new file mode 100644
index 000000000..a39e55e19
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/.isort.cfg
@@ -0,0 +1,4 @@
+[settings]
+known_first_party=ansible_collections.openvswitch.openvswitch
+line_length=100
+profile=black
diff --git a/ansible_collections/openvswitch/openvswitch/.pre-commit-config.yaml b/ansible_collections/openvswitch/openvswitch/.pre-commit-config.yaml
new file mode 100644
index 000000000..6ca2ad731
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/.pre-commit-config.yaml
@@ -0,0 +1,35 @@
+---
+repos:
+ - repo: https://github.com/ansible-network/collection_prep
+ rev: 1.1.1
+ hooks:
+ - id: autoversion
+ - id: update-docs
+
+ - repo: https://github.com/pre-commit/pre-commit-hooks
+ rev: v4.4.0
+ hooks:
+ - id: check-merge-conflict
+ - id: debug-statements
+ - id: end-of-file-fixer
+ - id: no-commit-to-branch
+ - id: trailing-whitespace
+
+ - repo: https://github.com/pre-commit/mirrors-prettier
+ rev: "v3.0.0-alpha.9-for-vscode"
+ hooks:
+ - id: prettier
+ additional_dependencies:
+ - prettier
+ - prettier-plugin-toml
+
+ - repo: https://github.com/PyCQA/isort
+ rev: 5.12.0
+ hooks:
+ - id: isort
+ args: ["--filter-files"]
+
+ - repo: https://github.com/psf/black
+ rev: 23.3.0
+ hooks:
+ - id: black
diff --git a/ansible_collections/openvswitch/openvswitch/.prettierignore b/ansible_collections/openvswitch/openvswitch/.prettierignore
new file mode 100644
index 000000000..5fbc1b8c8
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/.prettierignore
@@ -0,0 +1,17 @@
+# Stuff we don't want prettier to ever to look into
+.*/
+coverage/
+
+# Environments
+.env
+.venv
+env/
+venv/
+ENV/
+env.bak/
+venv.bak/
+
+# A linked collection directory created by pytest-ansible-units
+collections/
+
+README.md
diff --git a/ansible_collections/openvswitch/openvswitch/.yamllint b/ansible_collections/openvswitch/openvswitch/.yamllint
new file mode 100644
index 000000000..3adaf90cf
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/.yamllint
@@ -0,0 +1,15 @@
+---
+extends: default
+
+ignore: |
+ .tox
+ changelogs/*
+
+rules:
+ braces:
+ max-spaces-inside: 1
+ level: error
+ brackets:
+ max-spaces-inside: 1
+ level: error
+ line-length: disable
diff --git a/ansible_collections/openvswitch/openvswitch/CHANGELOG.rst b/ansible_collections/openvswitch/openvswitch/CHANGELOG.rst
new file mode 100644
index 000000000..a8e230d83
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/CHANGELOG.rst
@@ -0,0 +1,129 @@
+====================================
+Openvswitch Collection Release Notes
+====================================
+
+.. contents:: Topics
+
+
+v2.1.1
+======
+
+Bugfixes
+--------
+
+- Fix galaxy version issue when installing this collection.
+
+Documentation Changes
+---------------------
+
+- Update module documentation and examples.
+
+v2.1.0
+======
+
+Minor Changes
+-------------
+
+- Allows read operation in openvswitch_db module(https://github.com/ansible-collections/openvswitch.openvswitch/pull/88)
+- openvswitch modules got support for database socket parameter.
+
+v2.0.2
+======
+
+Bugfixes
+--------
+
+- `openvswitch_bridge` - Fix idempotency for VLAN bridges
+
+v2.0.1
+======
+
+Major Changes
+-------------
+
+- By mistake we tagged the repo to 2.0.0 and as it wasn't intended and cannot be reverted we're releasing 2.0.1 to make the community aware of the major version update.
+
+v2.0.0
+======
+
+Major Changes
+-------------
+
+- There is no major changes for this particular release and it was tagged by mistake and cannot be reverted.
+
+v1.2.0
+======
+
+Minor Changes
+-------------
+
+- Allow setting multiple properties on a port (https://github.com/ansible-collections/openvswitch.openvswitch/issues/63).
+
+Bugfixes
+--------
+
+- Allow deleting key from table without specifying value (https://github.com/ansible-collections/openvswitch.openvswitch/issues/64).
+
+v1.1.0
+======
+
+Minor Changes
+-------------
+
+- openvswitch_bond - New module for managing Open vSwitch bonds (https://github.com/ansible-collections/openvswitch.openvswitch/pull/58).
+
+Bugfixes
+--------
+
+- Add version key to galaxy.yaml to work around ansible-galaxy bug (https://github.com/ansible-collections/openvswitch.openvswitch/issues/59)
+
+v1.0.5
+======
+
+Minor Changes
+-------------
+
+- Regenerated docs, add description to galaxy.yml and linked changelog to README (https://github.com/ansible-collections/openvswitch.openvswitch/pull/53).
+
+v1.0.4
+======
+
+Release Summary
+---------------
+
+Rereleased 1.0.3 with updated changelog.
+
+v1.0.3
+======
+
+Release Summary
+---------------
+
+Released for testing.
+
+v1.0.2
+======
+
+Release Summary
+---------------
+
+Rereleased 1.0.1 with updated changelog.
+
+v1.0.1
+======
+
+Bugfixes
+--------
+
+- Makes sure that docstring and argspec are in sync and removes sanity ignores (https://github.com/ansible-collections/openvswitch.openvswitch/pull/46).
+- Update docs after sanity fixes to modules.
+
+v1.0.0
+======
+
+New Modules
+-----------
+
+- openvswitch_bridge - Manage Open vSwitch bridges
+- openvswitch_db - Configure open vswitch database.
+- openvswitch_port - Manage Open vSwitch ports
diff --git a/ansible_collections/openvswitch/openvswitch/FILES.json b/ansible_collections/openvswitch/openvswitch/FILES.json
new file mode 100644
index 000000000..d1f5faaad
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/FILES.json
@@ -0,0 +1,782 @@
+{
+ "files": [
+ {
+ "name": ".",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": ".github",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": ".github/workflows",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": ".github/workflows/codecoverage.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "a56c8aba05b81d2e1d6575b37963f40df663387030de5eaac6f5c9dfd7af54f1",
+ "format": 1
+ },
+ {
+ "name": ".github/workflows/test.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "68f1dab3d706336656fd2e69665f0f0baea7952aeb9ec88c04efb828c5a1e748",
+ "format": 1
+ },
+ {
+ "name": "changelogs",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "changelogs/.plugin-cache.yaml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "7ed118736237c922e32159f3adb4035237ca8e56271197d4fa49e9baa2b6f408",
+ "format": 1
+ },
+ {
+ "name": "changelogs/changelog.yaml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "3b58f26fb5ec8dd709538fc569fd66d3409e31a9ee0daaece218cf9b0ee9dd4b",
+ "format": 1
+ },
+ {
+ "name": "changelogs/config.yaml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "2adb276dfb7fe5754f0ed71a5678bf5fe38cfb7faf137f8087d7cd7be9ab0968",
+ "format": 1
+ },
+ {
+ "name": "docs",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "docs/openvswitch.openvswitch.openvswitch_bond_module.rst",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "eebe22da580707acab765f0a37fea28dd24740594a9efaa3b754474b45c9dd7a",
+ "format": 1
+ },
+ {
+ "name": "docs/openvswitch.openvswitch.openvswitch_bridge_module.rst",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "8b49055378c201a883f16920e2e589ea5af5b6b95a1ec8376bf1b79324699e9e",
+ "format": 1
+ },
+ {
+ "name": "docs/openvswitch.openvswitch.openvswitch_db_module.rst",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "f04f4804f09779c06564557974dcf9fb764d86f23a83fbeaa8b00f1b996bbd28",
+ "format": 1
+ },
+ {
+ "name": "docs/openvswitch.openvswitch.openvswitch_port_module.rst",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "f9dfacacb82c5411193085bbcec480593612c9c5b2ca6ef2d3c26fbd8edc862e",
+ "format": 1
+ },
+ {
+ "name": "meta",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "meta/runtime.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "6eaf1c23aa84c677ad9d7b9bfb1033a07ebc7ce3ea2f693e79e844ef1bc86574",
+ "format": 1
+ },
+ {
+ "name": "plugins",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "plugins/modules",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/__init__.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/openvswitch_bond.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "da013d93cbd467a08ea02429a3a2289eac85c5b10dc51caab94d046597aa9fa1",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/openvswitch_bridge.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "38952dd15bbfa23f45c406dc81c79ad83d8bb972aa88922b833809f4b21a8ce8",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/openvswitch_db.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "8ff4334f056b584d937a1de01a754953bd25ad07365914bcd71e9dab8e810233",
+ "format": 1
+ },
+ {
+ "name": "plugins/modules/openvswitch_port.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "5b69b48f8a1fd003ed76ac6a32701a050a6f07b24aea8f3dc3469f74f0d14c64",
+ "format": 1
+ },
+ {
+ "name": "tests",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/openvswitch_bridge",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/openvswitch_bridge/defaults",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/openvswitch_bridge/defaults/main.yaml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "665288590cd4226da42511817f09ccdfc92df36c9621583cd2c82919af295c5a",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/openvswitch_bridge/meta",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/openvswitch_bridge/meta/main.yaml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "8030d202f0d4ed045738a0be23a2b00abca712f250fd05504f67f4083806e70d",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/openvswitch_bridge/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/openvswitch_bridge/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "864fdb64c38a190f819cfdcb18fd2bd93910347d8afc0e50bebf376aa0405800",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/openvswitch_bridge/tests",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/openvswitch_bridge/tests/basic.yaml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "71355de14b7606ddc4150315db87f07d85febb47a92b9414e5a538d9adc9941a",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/openvswitch_bridge/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "796f43c1ce3f6a1461bdb8ff0f62ddecd2ab76d2131364d58279a9e066119006",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/openvswitch_db",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/openvswitch_db/defaults",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/openvswitch_db/defaults/main.yaml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "665288590cd4226da42511817f09ccdfc92df36c9621583cd2c82919af295c5a",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/openvswitch_db/meta",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/openvswitch_db/meta/main.yaml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "8030d202f0d4ed045738a0be23a2b00abca712f250fd05504f67f4083806e70d",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/openvswitch_db/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/openvswitch_db/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "864fdb64c38a190f819cfdcb18fd2bd93910347d8afc0e50bebf376aa0405800",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/openvswitch_db/tests",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/openvswitch_db/tests/basic.yaml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "1df8b2b57b13c7ad3e6f65e9d77e4c8ebeeec19c3543f76cb4b95dc29b5fc7bc",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/openvswitch_db/aliases",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "796f43c1ce3f6a1461bdb8ff0f62ddecd2ab76d2131364d58279a9e066119006",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/prepare_ovs_tests",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/prepare_ovs_tests/tasks",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/integration/targets/prepare_ovs_tests/tasks/main.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "1bab35091b1edea841526465500fa96b65e5ac8dd0edd3efd4a8e8fe2a6ae42b",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/network-integration.cfg",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "d67b11263a8f50b30bf43c7c2b4bdd8dc4f173f0b5dd22761311360dfbd56a1d",
+ "format": 1
+ },
+ {
+ "name": "tests/integration/target-prefixes.network",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "2a60524cedd48d85c64c8a6be73270ec86302fcde54829a94c5240577af9cd29",
+ "format": 1
+ },
+ {
+ "name": "tests/sanity",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/sanity/ignore-2.10.txt",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "format": 1
+ },
+ {
+ "name": "tests/sanity/ignore-2.9.txt",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "format": 1
+ },
+ {
+ "name": "tests/unit",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/unit/compat",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/unit/compat/__init__.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "format": 1
+ },
+ {
+ "name": "tests/unit/compat/mock.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "c1027e053a21d6e19f021cd022137ac984433b9066fabaa5abe1cd67b842d880",
+ "format": 1
+ },
+ {
+ "name": "tests/unit/compat/unittest.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "3ed698b1faec43d87a2c1ebcb15a2aae48b09ff355bb9a598e5f5a1c928dbb30",
+ "format": 1
+ },
+ {
+ "name": "tests/unit/mock",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/unit/mock/__init__.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "format": 1
+ },
+ {
+ "name": "tests/unit/mock/loader.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "2a3719aed31d2c5f5392c699a49f2ac3e93e499394d7cfdf7e92cbcb5fbda199",
+ "format": 1
+ },
+ {
+ "name": "tests/unit/mock/path.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "c225b58b136e2043c7f7b6e8f1fe236826de312e8e776157c35ffa95f33ac19d",
+ "format": 1
+ },
+ {
+ "name": "tests/unit/mock/procenv.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "ee2694a844ac94a6ca0ff89f4201799e6130140dafaa7c160e0d8a18867dfb93",
+ "format": 1
+ },
+ {
+ "name": "tests/unit/mock/vault_helper.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "f9e3bd3e1a1cb27f74017fedc58266ba5958e1dfaf1e1a83d2d36176f22c4308",
+ "format": 1
+ },
+ {
+ "name": "tests/unit/mock/yaml_helper.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "8e16dc5bf20c7fcd862f3c30b2752954ccc65c6bae3066ff048a338f57e19901",
+ "format": 1
+ },
+ {
+ "name": "tests/unit/modules",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/unit/modules/network",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/unit/modules/network/ovs",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/unit/modules/network/ovs/fixtures",
+ "ftype": "dir",
+ "chksum_type": null,
+ "chksum_sha256": null,
+ "format": 1
+ },
+ {
+ "name": "tests/unit/modules/network/ovs/fixtures/__init__.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "format": 1
+ },
+ {
+ "name": "tests/unit/modules/network/ovs/fixtures/br_get_external_id_foo_bar.cfg",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "fb4d8c7a525630ab89af2b8f6b3b51f65877f20a569a87fc33bdbe1c3922f929",
+ "format": 1
+ },
+ {
+ "name": "tests/unit/modules/network/ovs/fixtures/br_to_parent_test_br.cfg",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "c645f32418aa5d29ef2019dc8d3a86dd3d8d728b20525e06f1e8f0b77f453a8a",
+ "format": 1
+ },
+ {
+ "name": "tests/unit/modules/network/ovs/fixtures/br_to_vlan_zero.cfg",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "9a271f2a916b0b6ee6cecb2426f0b3206ef074578be55d9bc94f6f3fe3ab86aa",
+ "format": 1
+ },
+ {
+ "name": "tests/unit/modules/network/ovs/fixtures/get_fail_mode_secure.cfg",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "64f8590dc1c153a7569418973e62755013551bcf78b624ed4c6f766005a55a36",
+ "format": 1
+ },
+ {
+ "name": "tests/unit/modules/network/ovs/fixtures/get_port_bond0_external_ids.cfg",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "c0dac1db3bfc4b4dbf889edb777f280d8f3f8e0d11f500fde7bf387645386d4a",
+ "format": 1
+ },
+ {
+ "name": "tests/unit/modules/network/ovs/fixtures/get_port_bond0_other_config.cfg",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "b9fe20d613e9e0e526b6044cd92d2b9766922a50cf722bb0766c7375d472942c",
+ "format": 1
+ },
+ {
+ "name": "tests/unit/modules/network/ovs/fixtures/get_port_eth2_external_ids.cfg",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "c0dac1db3bfc4b4dbf889edb777f280d8f3f8e0d11f500fde7bf387645386d4a",
+ "format": 1
+ },
+ {
+ "name": "tests/unit/modules/network/ovs/fixtures/get_port_eth2_tag.cfg",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "917df3320d778ddbaa5c5c7742bc4046bf803c36ed2b050f30844ed206783469",
+ "format": 1
+ },
+ {
+ "name": "tests/unit/modules/network/ovs/fixtures/list_br_test_br.cfg",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "c645f32418aa5d29ef2019dc8d3a86dd3d8d728b20525e06f1e8f0b77f453a8a",
+ "format": 1
+ },
+ {
+ "name": "tests/unit/modules/network/ovs/fixtures/list_ports_bond_br.cfg",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "2968b4d67997fded3a924b3ad98d983facfe51861d738bc9928aa687e9340a86",
+ "format": 1
+ },
+ {
+ "name": "tests/unit/modules/network/ovs/fixtures/list_ports_test_br.cfg",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "4dd854aba69453d0c5d442b39eebde7036f3834ed1c126f1cfad223c58a872d4",
+ "format": 1
+ },
+ {
+ "name": "tests/unit/modules/network/ovs/fixtures/openvswitch_db_disable_in_band_missing.cfg",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "074e61c3d4ff7f1666fe08b48b30a75b071a0b7b014a8d619dfdab48c974d43e",
+ "format": 1
+ },
+ {
+ "name": "tests/unit/modules/network/ovs/fixtures/openvswitch_db_disable_in_band_true.cfg",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "86bfabba396d54e82162037801585a124cc7c9a19489a974b01f1cb2ee0a39db",
+ "format": 1
+ },
+ {
+ "name": "tests/unit/modules/network/ovs/__init__.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "format": 1
+ },
+ {
+ "name": "tests/unit/modules/network/ovs/ovs_module.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "857ad60b3cc7654fc20888fdde42271493cfc3db5728fd8b8572ce282ee82a81",
+ "format": 1
+ },
+ {
+ "name": "tests/unit/modules/network/ovs/test_openvswitch_bond.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "4e3dea7c472eda27beab0be4c8421e3bb75a75f63edd537dcfbf3d35d3de2f18",
+ "format": 1
+ },
+ {
+ "name": "tests/unit/modules/network/ovs/test_openvswitch_bridge.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "4f6544a71b2b596a96be66a8ca017c57c7d24560a06146058694a5112717f2fd",
+ "format": 1
+ },
+ {
+ "name": "tests/unit/modules/network/ovs/test_openvswitch_db.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "54f7be5c873c58a17b2e3d1b5d9bc3b89a7e8364826dae9087148617350ca2eb",
+ "format": 1
+ },
+ {
+ "name": "tests/unit/modules/network/ovs/test_openvswitch_port.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "1c4082f545ccd3f977d30305be413463fb3027275173d806294ae033e14e20d8",
+ "format": 1
+ },
+ {
+ "name": "tests/unit/modules/network/__init__.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "format": 1
+ },
+ {
+ "name": "tests/unit/modules/__init__.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "format": 1
+ },
+ {
+ "name": "tests/unit/modules/conftest.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "91a7af4f26197c9c55a48ad00d004a56f8ba43604cb83ff8d1da857a99526a75",
+ "format": 1
+ },
+ {
+ "name": "tests/unit/modules/utils.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "fa8c30c6423b5a307d4d47f818dd037cecb9781a15fb26543fd2125b0ab8fa29",
+ "format": 1
+ },
+ {
+ "name": "tests/unit/__init__.py",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "format": 1
+ },
+ {
+ "name": "tests/unit/requirements.txt",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "49ba996dc4735c3463e9af561344346dfae14bcc1a68096ce78364b377f0df1f",
+ "format": 1
+ },
+ {
+ "name": "tests/.gitignore",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "b5726d3ec9335a09c124469eca039523847a6b0f08a083efaefd002b83326600",
+ "format": 1
+ },
+ {
+ "name": ".gitignore",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "ddc61d479977d318682280fa2b18bcb6cb9a1b0e0e7897cea3d14d5c8d222e68",
+ "format": 1
+ },
+ {
+ "name": ".isort.cfg",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "5a1cbc1860f66ffbd0601a7d3f09d0d05c7c204260e34b00b5a3fc3c9c66dcc4",
+ "format": 1
+ },
+ {
+ "name": ".pre-commit-config.yaml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "51b246b858aab8696cbf5cfca18dc0dc223351bc919d8cb595695f5edbd70f62",
+ "format": 1
+ },
+ {
+ "name": ".prettierignore",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "d4794efd30dbced939a50b3dd436b231470bc09e7e69ed28713aa1867b184fd7",
+ "format": 1
+ },
+ {
+ "name": ".yamllint",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "827ef9e031ecdcaf137be239d33ef93fcbbc3611cbb6b30b0e507d0e03373d0e",
+ "format": 1
+ },
+ {
+ "name": "CHANGELOG.rst",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "f9fccb4667a56127bc19dede309674e6d5534839f1c7a93aef2aaba09e9d3063",
+ "format": 1
+ },
+ {
+ "name": "LICENSE",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "3972dc9744f6499f0f9b2dbf76696f2ae7ad8af9b23dde66d6af86c9dfb36986",
+ "format": 1
+ },
+ {
+ "name": "README.md",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "91272b3132e10b4e6ce93e00ee5fea0fd97ee72338913d7c2dbf84bec8270981",
+ "format": 1
+ },
+ {
+ "name": "bindep.txt",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "bc4c11f2eaa67b38574c8ab4052deee3644c88b1a45fd9c1153cc6c447daac7b",
+ "format": 1
+ },
+ {
+ "name": "codecov.yml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "d7119b3a96ece7bcd2df6e851e7e19783049f280918a801344d502c6ada4e582",
+ "format": 1
+ },
+ {
+ "name": "pyproject.toml",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "1cb6a45dfa2625123890b93ad7fdc156b063c16e8ae6dba11511a1d1986b0fcc",
+ "format": 1
+ },
+ {
+ "name": "requirements.txt",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855",
+ "format": 1
+ },
+ {
+ "name": "test-requirements.txt",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "6bc12fd99094693035494ca012b5acac80bbbbb2824f0a60a3b2c2d94dd048cc",
+ "format": 1
+ },
+ {
+ "name": "tox.ini",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "76b579ff04d1b4f49495fccbd86b2f682a3050b7092c7f92af3be1b9396d76e7",
+ "format": 1
+ }
+ ],
+ "format": 1
+} \ No newline at end of file
diff --git a/ansible_collections/openvswitch/openvswitch/LICENSE b/ansible_collections/openvswitch/openvswitch/LICENSE
new file mode 100644
index 000000000..f288702d2
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/LICENSE
@@ -0,0 +1,674 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+ The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users. We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors. You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+ To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights. Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received. You must make sure that they, too, receive
+or can get the source code. And you must show them these terms so they
+know their rights.
+
+ Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+ For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software. For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+ Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so. This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software. The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable. Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products. If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+ Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary. To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ TERMS AND CONDITIONS
+
+ 0. Definitions.
+
+ "This License" refers to version 3 of the GNU General Public License.
+
+ "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+ "The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+ To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy. The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+ A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+ To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+ To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+ An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+ 1. Source Code.
+
+ The "source code" for a work means the preferred form of the work
+for making modifications to it. "Object code" means any non-source
+form of a work.
+
+ A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+ The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+ The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+ The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+ The Corresponding Source for a work in source code form is that
+same work.
+
+ 2. Basic Permissions.
+
+ All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+ You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force. You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright. Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+ Conveying under any other circumstances is permitted solely under
+the conditions stated below. Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+ 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+ No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+ When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+ 4. Conveying Verbatim Copies.
+
+ You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+ You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+ 5. Conveying Modified Source Versions.
+
+ You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+ a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+
+ b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under section
+ 7. This requirement modifies the requirement in section 4 to
+ "keep intact all notices".
+
+ c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+
+ d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+ A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+ 6. Conveying Non-Source Forms.
+
+ You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+ a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+
+ b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the
+ Corresponding Source from a network server at no charge.
+
+ c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+
+ d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+
+ e) Convey the object code using peer-to-peer transmission, provided
+ you inform other peers where the object code and Corresponding
+ Source of the work are being offered to the general public at no
+ charge under subsection 6d.
+
+ A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+ A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling. In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage. For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product. A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+ "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source. The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+ If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+ The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed. Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+ Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+ 7. Additional Terms.
+
+ "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+ When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+ Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+ a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+
+ b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+
+ c) Prohibiting misrepresentation of the origin of that material, or
+ requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+
+ d) Limiting the use for publicity purposes of names of licensors or
+ authors of the material; or
+
+ e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+
+ f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions of
+ it) with contractual assumptions of liability to the recipient, for
+ any liability that these contractual assumptions directly impose on
+ those licensors and authors.
+
+ All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+ If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+ Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+ 8. Termination.
+
+ You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+ However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+ Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+ 9. Acceptance Not Required for Having Copies.
+
+ You are not required to accept this License in order to receive or
+run a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+ 10. Automatic Licensing of Downstream Recipients.
+
+ Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+ An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+ You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+ 11. Patents.
+
+ A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+ A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+ Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+ In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+ If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+ If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+ A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License. You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+ Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+ 12. No Surrender of Others' Freedom.
+
+ If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all. For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+ 13. Use with the GNU Affero General Public License.
+
+ Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+ 14. Revised Versions of this License.
+
+ The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+ Each version is given a distinguishing version number. If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+ If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+ Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+ 15. Disclaimer of Warranty.
+
+ THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. Limitation of Liability.
+
+ IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+ 17. Interpretation of Sections 15 and 16.
+
+ If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+ If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+ <program> Copyright (C) <year> <name of author>
+ This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+ You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<https://www.gnu.org/licenses/>.
+
+ The GNU General Public License does not permit incorporating your program
+into proprietary programs. If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License. But first, please read
+<https://www.gnu.org/licenses/why-not-lgpl.html>.
diff --git a/ansible_collections/openvswitch/openvswitch/MANIFEST.json b/ansible_collections/openvswitch/openvswitch/MANIFEST.json
new file mode 100644
index 000000000..a4a039a20
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/MANIFEST.json
@@ -0,0 +1,33 @@
+{
+ "collection_info": {
+ "namespace": "openvswitch",
+ "name": "openvswitch",
+ "version": "2.1.1",
+ "authors": [
+ "Ansible Network Community (ansible-network)"
+ ],
+ "readme": "README.md",
+ "tags": [
+ "networking",
+ "vswitch",
+ "bridge",
+ "vlan"
+ ],
+ "description": "Ansible Network Collection for Open vSwitch",
+ "license": [],
+ "license_file": "LICENSE",
+ "dependencies": {},
+ "repository": "https://github.com/ansible-collections/openvswitch.openvswitch",
+ "documentation": null,
+ "homepage": null,
+ "issues": "https://github.com/ansible-collections/openvswitch.openvswitch/issues"
+ },
+ "file_manifest_file": {
+ "name": "FILES.json",
+ "ftype": "file",
+ "chksum_type": "sha256",
+ "chksum_sha256": "a3c4f61b8611e8f26f8749b1408367e4142def8d001e13858d1c36414f54d47d",
+ "format": 1
+ },
+ "format": 1
+} \ No newline at end of file
diff --git a/ansible_collections/openvswitch/openvswitch/README.md b/ansible_collections/openvswitch/openvswitch/README.md
new file mode 100644
index 000000000..1687293a0
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/README.md
@@ -0,0 +1,109 @@
+
+
+# Open vSwitch Collection
+[![CI](https://zuul-ci.org/gated.svg)](https://dashboard.zuul.ansible.com/t/ansible/project/github.com/ansible-collections/openvswitch.openvswitch) <!--[![Codecov](https://img.shields.io/codecov/c/github/ansible-collections/vyos)](https://codecov.io/gh/ansible-collections/openvswitch.openvswitch)-->
+
+The Open vSwitch collection includes a variety of Ansible content to help automate the management of Open vSwitch.
+
+<!--start requires_ansible-->
+## Ansible version compatibility
+
+This collection has been tested against following Ansible versions: **>=2.9.10**.
+
+For collections that support Ansible 2.9, please ensure you update your `network_os` to use the
+fully qualified collection name (for example, `cisco.ios.ios`).
+Plugins and modules within a collection may be tested with only specific Ansible versions.
+A collection may contain metadata that identifies these versions.
+PEP440 is the schema used to describe the versions of Ansible.
+<!--end requires_ansible-->
+
+### Supported connections
+The Open vSwitch collection supports local connections only.
+
+## Included content
+
+Click the ``Content`` button to see the list of content included in this collection.
+
+<!--start collection content-->
+### Modules
+Name | Description
+--- | ---
+[openvswitch.openvswitch.openvswitch_bond](https://github.com/ansible-collections/openvswitch.openvswitch/blob/main/docs/openvswitch.openvswitch.openvswitch_bond_module.rst)|Manage Open vSwitch bonds
+[openvswitch.openvswitch.openvswitch_bridge](https://github.com/ansible-collections/openvswitch.openvswitch/blob/main/docs/openvswitch.openvswitch.openvswitch_bridge_module.rst)|Manage Open vSwitch bridges
+[openvswitch.openvswitch.openvswitch_db](https://github.com/ansible-collections/openvswitch.openvswitch/blob/main/docs/openvswitch.openvswitch.openvswitch_db_module.rst)|Configure open vswitch database.
+[openvswitch.openvswitch.openvswitch_port](https://github.com/ansible-collections/openvswitch.openvswitch/blob/main/docs/openvswitch.openvswitch.openvswitch_port_module.rst)|Manage Open vSwitch ports
+
+<!--end collection content-->
+
+## Installing this collection
+
+You can install the Open vSwitch collection with the Ansible Galaxy CLI:
+
+ ansible-galaxy collection install openvswitch.openvswitch
+
+You can also include it in a `requirements.yml` file and install it with `ansible-galaxy collection install -r requirements.yml`, using the format:
+
+```yaml
+---
+collections:
+ - name: openvswitch.openvswitch
+```
+## Using this collection
+
+You can call modules by their Fully Qualified Collection Namespace (FQCN), such as `openvswitch.openvswitch.openvswitch_port`.
+The following example task replaces configuration changes in the existing configuration on a Open vSwitch network device, using the FQCN:
+
+```yaml
+---
+ - name: Creates port eth2 on bridge br-ex
+ openvswitch.openvswitch.openvswitch_port:
+ bridge: br-ex
+ port: eth2
+ state: present
+```
+
+**NOTE**: For Ansible 2.9, you may not see deprecation warnings when you run your playbooks with this collection. Use this documentation to track when a module is deprecated.
+
+
+### See Also:
+
+* [Ansible Using collections](https://docs.ansible.com/ansible/latest/user_guide/collections_using.html) for more details.
+
+## Contributing to this collection
+
+We welcome community contributions to this collection. If you find problems, please open an issue or create a PR against the [Open vSwitch collection repository](https://github.com/ansible-collections/openvswitch.openvswitch). See [Contributing to Ansible-maintained collections](https://docs.ansible.com/ansible/devel/community/contributing_maintained_collections.html#contributing-maintained-collections) for complete details.
+
+You can also join us on:
+
+- IRC - the ``#ansible-network`` [irc.libera.chat](https://libera.chat/) channel
+- Slack - https://ansiblenetwork.slack.com
+
+See the [Ansible Community Guide](https://docs.ansible.com/ansible/latest/community/index.html) for details on contributing to Ansible.
+
+### Code of Conduct
+This collection follows the Ansible project's
+[Code of Conduct](https://docs.ansible.com/ansible/devel/community/code_of_conduct.html).
+Please read and familiarize yourself with this document.
+
+
+## Changelogs
+
+Release notes are available [here](https://github.com/ansible-collections/openvswitch.openvswitch/blob/main/changelogs/CHANGELOG.rst).
+
+## Roadmap
+
+<!-- Optional. Include the roadmap for this collection, and the proposed release/versioning strategy so users can anticipate the upgrade/update cycle. -->
+
+## More information
+
+- [Ansible network resources](https://docs.ansible.com/ansible/latest/network/getting_started/network_resources.html)
+- [Ansible Collection overview](https://github.com/ansible-collections/overview)
+- [Ansible User guide](https://docs.ansible.com/ansible/latest/user_guide/index.html)
+- [Ansible Developer guide](https://docs.ansible.com/ansible/latest/dev_guide/index.html)
+- [Ansible Community code of conduct](https://docs.ansible.com/ansible/latest/community/code_of_conduct.html)
+
+## Licensing
+
+GNU General Public License v3.0 or later.
+
+See [LICENSE](https://www.gnu.org/licenses/gpl-3.0.txt) to see the full text.
diff --git a/ansible_collections/openvswitch/openvswitch/bindep.txt b/ansible_collections/openvswitch/openvswitch/bindep.txt
new file mode 100644
index 000000000..a8b2ccc40
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/bindep.txt
@@ -0,0 +1,9 @@
+# This is a cross-platform list tracking distribution packages needed by tests;
+# see https://docs.openstack.org/infra/bindep/ for additional information.
+
+gcc-c++ [doc test platform:rpm]
+libyaml-devel [test platform:rpm]
+libyaml-dev [test platform:dpkg]
+libssh-devel [test platform:rpm]
+libffi-devel [test platform:rpm]
+openssl-devel [test platform:rpm]
diff --git a/ansible_collections/openvswitch/openvswitch/changelogs/.plugin-cache.yaml b/ansible_collections/openvswitch/openvswitch/changelogs/.plugin-cache.yaml
new file mode 100644
index 000000000..f7b35680d
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/changelogs/.plugin-cache.yaml
@@ -0,0 +1,39 @@
+objects:
+ role: {}
+plugins:
+ become: {}
+ cache: {}
+ callback: {}
+ cliconf: {}
+ connection: {}
+ filter: {}
+ httpapi: {}
+ inventory: {}
+ lookup: {}
+ module:
+ openvswitch_bond:
+ description: Manage Open vSwitch bonds
+ name: openvswitch_bond
+ namespace: ""
+ version_added: 1.0.0
+ openvswitch_bridge:
+ description: Manage Open vSwitch bridges
+ name: openvswitch_bridge
+ namespace: ""
+ version_added: 1.0.0
+ openvswitch_db:
+ description: Configure open vswitch database.
+ name: openvswitch_db
+ namespace: ""
+ version_added: 1.0.0
+ openvswitch_port:
+ description: Manage Open vSwitch ports
+ name: openvswitch_port
+ namespace: ""
+ version_added: 1.0.0
+ netconf: {}
+ shell: {}
+ strategy: {}
+ test: {}
+ vars: {}
+version: 2.1.1
diff --git a/ansible_collections/openvswitch/openvswitch/changelogs/changelog.yaml b/ansible_collections/openvswitch/openvswitch/changelogs/changelog.yaml
new file mode 100644
index 000000000..17f610e11
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/changelogs/changelog.yaml
@@ -0,0 +1,114 @@
+ancestor: null
+releases:
+ 1.0.0:
+ modules:
+ - description: Manage Open vSwitch bridges
+ name: openvswitch_bridge
+ namespace: ""
+ - description: Configure open vswitch database.
+ name: openvswitch_db
+ namespace: ""
+ - description: Manage Open vSwitch ports
+ name: openvswitch_port
+ namespace: ""
+ release_date: "2020-06-23"
+ 1.0.1:
+ changes:
+ bugfixes:
+ - Makes sure that docstring and argspec are in sync and removes sanity ignores
+ (https://github.com/ansible-collections/openvswitch.openvswitch/pull/46).
+ - Update docs after sanity fixes to modules.
+ fragments:
+ - remove_ignores.yaml
+ - update_docs.yaml
+ release_date: "2020-08-03"
+ 1.0.2:
+ changes:
+ release_summary: Rereleased 1.0.1 with updated changelog.
+ fragments:
+ - 1.0.2.yaml
+ release_date: "2020-08-07"
+ 1.0.3:
+ changes:
+ release_summary: Released for testing.
+ fragments:
+ - 1.0.3.yaml
+ release_date: "2020-08-07"
+ 1.0.4:
+ changes:
+ release_summary: Rereleased 1.0.3 with updated changelog.
+ fragments:
+ - 1.0.4.yaml
+ release_date: "2020-08-08"
+ 1.0.5:
+ changes:
+ minor_changes:
+ - Regenerated docs, add description to galaxy.yml and linked changelog to README
+ (https://github.com/ansible-collections/openvswitch.openvswitch/pull/53).
+ fragments:
+ - fixes_to_readme_and_doc.yaml
+ release_date: "2020-08-28"
+ 1.1.0:
+ changes:
+ bugfixes:
+ - Add version key to galaxy.yaml to work around ansible-galaxy bug (https://github.com/ansible-collections/openvswitch.openvswitch/issues/59)
+ minor_changes:
+ - openvswitch_bond - New module for managing Open vSwitch bonds (https://github.com/ansible-collections/openvswitch.openvswitch/pull/58).
+ fragments:
+ - 1-openvswitch_bond-new-module.yaml
+ - fix_download_git.yaml
+ release_date: "2020-11-26"
+ 1.2.0:
+ changes:
+ bugfixes:
+ - Allow deleting key from table without specifying value (https://github.com/ansible-collections/openvswitch.openvswitch/issues/64).
+ minor_changes:
+ - Allow setting multiple properties on a port (https://github.com/ansible-collections/openvswitch.openvswitch/issues/63).
+ fragments:
+ - fix_openvswitch_db.yaml
+ - fix_openvswitch_port.yaml
+ release_date: "2021-02-24"
+ 2.0.0:
+ changes:
+ major_changes:
+ - There is no major changes for this particular release and it was tagged by
+ mistake and cannot be reverted.
+ release_date: "2021-02-24"
+ 2.0.1:
+ changes:
+ major_changes:
+ - By mistake we tagged the repo to 2.0.0 and as it wasn't intended and cannot
+ be reverted we're releasing 2.0.1 to make the community aware of the major
+ version update.
+ release_date: "2021-03-03"
+ 2.0.2:
+ changes:
+ bugfixes:
+ - "`openvswitch_bridge` - Fix idempotency for VLAN bridges"
+ fragments:
+ - 69-remove_tests_sanity_requirements.yml
+ - fix_validate_modules.yaml
+ - fix_vlan_bridge_idempotency.yaml
+ - pylint_fixes.yaml
+ release_date: "2021-09-24"
+ 2.1.0:
+ changes:
+ minor_changes:
+ - Allows read operation in openvswitch_db module(https://github.com/ansible-collections/openvswitch.openvswitch/pull/88)
+ - openvswitch modules got support for database socket parameter.
+ fragments:
+ - 84-ovs-modules-database-socket.yaml
+ - openvswitch_db_read.yaml
+ release_date: "2021-12-07"
+ 2.1.1:
+ changes:
+ bugfixes:
+ - Fix galaxy version issue when installing this collection.
+ doc_changes:
+ - Update module documentation and examples.
+ fragments:
+ - black.yaml
+ - fix.yaml
+ - galaxy.yml
+ - gha.yaml
+ release_date: "2023-04-27"
diff --git a/ansible_collections/openvswitch/openvswitch/changelogs/config.yaml b/ansible_collections/openvswitch/openvswitch/changelogs/config.yaml
new file mode 100644
index 000000000..f6f3c1fa9
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/changelogs/config.yaml
@@ -0,0 +1,32 @@
+changelog_filename_template: ../CHANGELOG.rst
+changelog_filename_version_depth: 0
+changes_file: changelog.yaml
+changes_format: combined
+keep_fragments: false
+mention_ancestor: true
+new_plugins_after_name: removed_features
+notesdir: fragments
+prelude_section_name: release_summary
+prelude_section_title: Release Summary
+flatmap: true
+sections:
+ - - major_changes
+ - Major Changes
+ - - minor_changes
+ - Minor Changes
+ - - breaking_changes
+ - Breaking Changes / Porting Guide
+ - - deprecated_features
+ - Deprecated Features
+ - - removed_features
+ - Removed Features (previously deprecated)
+ - - security_fixes
+ - Security Fixes
+ - - bugfixes
+ - Bugfixes
+ - - known_issues
+ - Known Issues
+ - - doc_changes
+ - Documentation Changes
+title: Openvswitch Collection
+trivial_section_name: trivial
diff --git a/ansible_collections/openvswitch/openvswitch/codecov.yml b/ansible_collections/openvswitch/openvswitch/codecov.yml
new file mode 100644
index 000000000..816cb4409
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/codecov.yml
@@ -0,0 +1,10 @@
+---
+codecov:
+ require_ci_to_pass: true
+comment: false
+coverage:
+ status:
+ patch: false
+ project:
+ default:
+ threshold: 0.3%
diff --git a/ansible_collections/openvswitch/openvswitch/docs/openvswitch.openvswitch.openvswitch_bond_module.rst b/ansible_collections/openvswitch/openvswitch/docs/openvswitch.openvswitch.openvswitch_bond_module.rst
new file mode 100644
index 000000000..5ebc2edfa
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/docs/openvswitch.openvswitch.openvswitch_bond_module.rst
@@ -0,0 +1,341 @@
+.. _openvswitch.openvswitch.openvswitch_bond_module:
+
+
+****************************************
+openvswitch.openvswitch.openvswitch_bond
+****************************************
+
+**Manage Open vSwitch bonds**
+
+
+Version added: 1.0.0
+
+.. contents::
+ :local:
+ :depth: 1
+
+
+Synopsis
+--------
+- Manage Open vSwitch bonds and associated options.
+
+
+
+Requirements
+------------
+The below requirements are needed on the host that executes this module.
+
+- ovs-vsctl
+
+
+Parameters
+----------
+
+.. raw:: html
+
+ <table border=0 cellpadding=0 class="documentation-table">
+ <tr>
+ <th colspan="1">Parameter</th>
+ <th>Choices/<font color="blue">Defaults</font></th>
+ <th width="100%">Comments</th>
+ </tr>
+ <tr>
+ <td colspan="1">
+ <div class="ansibleOptionAnchor" id="parameter-"></div>
+ <b>bond_downdelay</b>
+ <a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
+ <div style="font-size: small">
+ <span style="color: purple">integer</span>
+ </div>
+ </td>
+ <td>
+ </td>
+ <td>
+ <div>Number of milliseconds a link must be down to be deactivated to prevent flapping.</div>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="1">
+ <div class="ansibleOptionAnchor" id="parameter-"></div>
+ <b>bond_mode</b>
+ <a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
+ <div style="font-size: small">
+ <span style="color: purple">string</span>
+ </div>
+ </td>
+ <td>
+ <ul style="margin: 0; padding: 0"><b>Choices:</b>
+ <li>active-backup</li>
+ <li>balance-tcp</li>
+ <li>balance-slb</li>
+ </ul>
+ </td>
+ <td>
+ <div>Sets the bond mode</div>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="1">
+ <div class="ansibleOptionAnchor" id="parameter-"></div>
+ <b>bond_updelay</b>
+ <a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
+ <div style="font-size: small">
+ <span style="color: purple">integer</span>
+ </div>
+ </td>
+ <td>
+ </td>
+ <td>
+ <div>Number of milliseconds a link must be up to be activated to prevent flapping.</div>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="1">
+ <div class="ansibleOptionAnchor" id="parameter-"></div>
+ <b>bridge</b>
+ <a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
+ <div style="font-size: small">
+ <span style="color: purple">string</span>
+ / <span style="color: red">required</span>
+ </div>
+ </td>
+ <td>
+ </td>
+ <td>
+ <div>Name of bridge to manage</div>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="1">
+ <div class="ansibleOptionAnchor" id="parameter-"></div>
+ <b>database_socket</b>
+ <a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
+ <div style="font-size: small">
+ <span style="color: purple">string</span>
+ </div>
+ </td>
+ <td>
+ </td>
+ <td>
+ <div>Path/ip to datbase socket to use</div>
+ <div>Default path is used if not specified</div>
+ <div>Path should start with &#x27;unix:&#x27; prefix</div>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="1">
+ <div class="ansibleOptionAnchor" id="parameter-"></div>
+ <b>external_ids</b>
+ <a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
+ <div style="font-size: small">
+ <span style="color: purple">dictionary</span>
+ </div>
+ </td>
+ <td>
+ <b>Default:</b><br/><div style="color: blue">{}</div>
+ </td>
+ <td>
+ <div>Dictionary of external_ids applied to a port.</div>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="1">
+ <div class="ansibleOptionAnchor" id="parameter-"></div>
+ <b>interfaces</b>
+ <a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
+ <div style="font-size: small">
+ <span style="color: purple">list</span>
+ / <span style="color: purple">elements=string</span>
+ </div>
+ </td>
+ <td>
+ </td>
+ <td>
+ <div>List of interfaces to add to the bond</div>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="1">
+ <div class="ansibleOptionAnchor" id="parameter-"></div>
+ <b>lacp</b>
+ <a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
+ <div style="font-size: small">
+ <span style="color: purple">string</span>
+ </div>
+ </td>
+ <td>
+ <ul style="margin: 0; padding: 0"><b>Choices:</b>
+ <li>active</li>
+ <li>passive</li>
+ <li>off</li>
+ </ul>
+ </td>
+ <td>
+ <div>Sets LACP mode</div>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="1">
+ <div class="ansibleOptionAnchor" id="parameter-"></div>
+ <b>other_config</b>
+ <a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
+ <div style="font-size: small">
+ <span style="color: purple">dictionary</span>
+ </div>
+ </td>
+ <td>
+ <b>Default:</b><br/><div style="color: blue">{}</div>
+ </td>
+ <td>
+ <div>Dictionary of other_config applied to a port.</div>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="1">
+ <div class="ansibleOptionAnchor" id="parameter-"></div>
+ <b>port</b>
+ <a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
+ <div style="font-size: small">
+ <span style="color: purple">string</span>
+ / <span style="color: red">required</span>
+ </div>
+ </td>
+ <td>
+ </td>
+ <td>
+ <div>Name of port to manage on the bridge</div>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="1">
+ <div class="ansibleOptionAnchor" id="parameter-"></div>
+ <b>set</b>
+ <a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
+ <div style="font-size: small">
+ <span style="color: purple">list</span>
+ / <span style="color: purple">elements=string</span>
+ </div>
+ </td>
+ <td>
+ </td>
+ <td>
+ <div>Sets one or more properties on a port.</div>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="1">
+ <div class="ansibleOptionAnchor" id="parameter-"></div>
+ <b>state</b>
+ <a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
+ <div style="font-size: small">
+ <span style="color: purple">string</span>
+ </div>
+ </td>
+ <td>
+ <ul style="margin: 0; padding: 0"><b>Choices:</b>
+ <li><div style="color: blue"><b>present</b>&nbsp;&larr;</div></li>
+ <li>absent</li>
+ </ul>
+ </td>
+ <td>
+ <div>Whether the port should exist</div>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="1">
+ <div class="ansibleOptionAnchor" id="parameter-"></div>
+ <b>timeout</b>
+ <a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
+ <div style="font-size: small">
+ <span style="color: purple">integer</span>
+ </div>
+ </td>
+ <td>
+ <b>Default:</b><br/><div style="color: blue">5</div>
+ </td>
+ <td>
+ <div>How long to wait for ovs-vswitchd to respond in seconds</div>
+ </td>
+ </tr>
+ </table>
+ <br/>
+
+
+
+
+Examples
+--------
+
+.. code-block:: yaml
+
+ - name: Create an active-backup bond using eth4 and eth5 on bridge br-ex
+ openvswitch.openvswitch.openvswitch_bond:
+ bridge: br-ex
+ port: bond1
+ interfaces:
+ - eth4
+ - eth5
+ state: present
+ - name: Delete the bond from bridge br-ex
+ openvswitch.openvswitch.openvswitch_bond:
+ bridge: br-ex
+ port: bond1
+ state: absent
+ - name: Create an active LACP bond using eth4 and eth5 on bridge br-ex
+ openvswitch.openvswitch.openvswitch_bond:
+ bridge: br-ex
+ port: bond1
+ interfaces:
+ - eth4
+ - eth5
+ lacp: active
+ state: present
+ # NOTE: other_config values of integer type must be represented
+ # as literal strings
+ - name: Configure bond with miimon link monitoring at 100 millisecond intervals
+ openvswitch.openvswitch.openvswitch_bond:
+ bridge: br-ex
+ port: bond1
+ interfaces:
+ - eth4
+ - eth5
+ bond_updelay: 100
+ bond_downdelay: 100
+ state: present
+ args:
+ other_config:
+ bond-detect-mode: miimon
+ bond-miimon-interval: '"100"'
+ - name: Create an active LACP bond using DPDK interfaces
+ openvswitch.openvswitch.openvswitch_bond:
+ bridge: br-provider
+ port: dpdkbond
+ interfaces:
+ - "0000:04:00.0"
+ - "0000:04:00.1"
+ lacp: active
+ set:
+ - "interface 0000:04:00.0 type=dpdk options:dpdk-devargs=0000:04:00.0"
+ - "interface 0000:04:00.1 type=dpdk options:dpdk-devargs=0000:04:00.1"
+ state: present
+ - name: Create an active-backup bond using eth4 and eth5 on bridge br-ex in second OVS database
+ openvswitch.openvswitch.openvswitch_bond:
+ bridge: br-ex
+ port: bond1
+ interfaces:
+ - eth4
+ - eth5
+ state: present
+ database_socket: unix:/opt/second.sock
+
+
+
+
+Status
+------
+
+
+Authors
+~~~~~~~
+
+- James Denton (@busterswt)
diff --git a/ansible_collections/openvswitch/openvswitch/docs/openvswitch.openvswitch.openvswitch_bridge_module.rst b/ansible_collections/openvswitch/openvswitch/docs/openvswitch.openvswitch.openvswitch_bridge_module.rst
new file mode 100644
index 000000000..6432d61f1
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/docs/openvswitch.openvswitch.openvswitch_bridge_module.rst
@@ -0,0 +1,232 @@
+.. _openvswitch.openvswitch.openvswitch_bridge_module:
+
+
+******************************************
+openvswitch.openvswitch.openvswitch_bridge
+******************************************
+
+**Manage Open vSwitch bridges**
+
+
+Version added: 1.0.0
+
+.. contents::
+ :local:
+ :depth: 1
+
+
+Synopsis
+--------
+- Manage Open vSwitch bridges
+
+
+
+Requirements
+------------
+The below requirements are needed on the host that executes this module.
+
+- ovs-vsctl
+
+
+Parameters
+----------
+
+.. raw:: html
+
+ <table border=0 cellpadding=0 class="documentation-table">
+ <tr>
+ <th colspan="1">Parameter</th>
+ <th>Choices/<font color="blue">Defaults</font></th>
+ <th width="100%">Comments</th>
+ </tr>
+ <tr>
+ <td colspan="1">
+ <div class="ansibleOptionAnchor" id="parameter-"></div>
+ <b>bridge</b>
+ <a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
+ <div style="font-size: small">
+ <span style="color: purple">string</span>
+ / <span style="color: red">required</span>
+ </div>
+ </td>
+ <td>
+ </td>
+ <td>
+ <div>Name of bridge or fake bridge to manage</div>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="1">
+ <div class="ansibleOptionAnchor" id="parameter-"></div>
+ <b>database_socket</b>
+ <a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
+ <div style="font-size: small">
+ <span style="color: purple">string</span>
+ </div>
+ </td>
+ <td>
+ </td>
+ <td>
+ <div>Path/ip to datbase socket to use</div>
+ <div>Default path is used if not specified</div>
+ <div>Path should start with &#x27;unix:&#x27; prefix</div>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="1">
+ <div class="ansibleOptionAnchor" id="parameter-"></div>
+ <b>external_ids</b>
+ <a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
+ <div style="font-size: small">
+ <span style="color: purple">dictionary</span>
+ </div>
+ </td>
+ <td>
+ </td>
+ <td>
+ <div>A dictionary of external-ids. Omitting this parameter is a No-op. To clear all external-ids pass an empty value.</div>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="1">
+ <div class="ansibleOptionAnchor" id="parameter-"></div>
+ <b>fail_mode</b>
+ <a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
+ <div style="font-size: small">
+ <span style="color: purple">string</span>
+ </div>
+ </td>
+ <td>
+ </td>
+ <td>
+ <div>Set bridge fail-mode. The default value (None) is a No-op.</div>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="1">
+ <div class="ansibleOptionAnchor" id="parameter-"></div>
+ <b>parent</b>
+ <a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
+ <div style="font-size: small">
+ <span style="color: purple">string</span>
+ </div>
+ </td>
+ <td>
+ </td>
+ <td>
+ <div>Bridge parent of the fake bridge to manage</div>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="1">
+ <div class="ansibleOptionAnchor" id="parameter-"></div>
+ <b>set</b>
+ <a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
+ <div style="font-size: small">
+ <span style="color: purple">string</span>
+ </div>
+ </td>
+ <td>
+ </td>
+ <td>
+ <div>Run set command after bridge configuration. This parameter is non-idempotent, play will always return <em>changed</em> state if present</div>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="1">
+ <div class="ansibleOptionAnchor" id="parameter-"></div>
+ <b>state</b>
+ <a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
+ <div style="font-size: small">
+ <span style="color: purple">string</span>
+ </div>
+ </td>
+ <td>
+ <ul style="margin: 0; padding: 0"><b>Choices:</b>
+ <li><div style="color: blue"><b>present</b>&nbsp;&larr;</div></li>
+ <li>absent</li>
+ </ul>
+ </td>
+ <td>
+ <div>Whether the bridge should exist</div>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="1">
+ <div class="ansibleOptionAnchor" id="parameter-"></div>
+ <b>timeout</b>
+ <a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
+ <div style="font-size: small">
+ <span style="color: purple">integer</span>
+ </div>
+ </td>
+ <td>
+ <b>Default:</b><br/><div style="color: blue">5</div>
+ </td>
+ <td>
+ <div>How long to wait for ovs-vswitchd to respond</div>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="1">
+ <div class="ansibleOptionAnchor" id="parameter-"></div>
+ <b>vlan</b>
+ <a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
+ <div style="font-size: small">
+ <span style="color: purple">integer</span>
+ </div>
+ </td>
+ <td>
+ </td>
+ <td>
+ <div>The VLAN id of the fake bridge to manage (must be between 0 and 4095). This parameter is required if <em>parent</em> parameter is set.</div>
+ </td>
+ </tr>
+ </table>
+ <br/>
+
+
+
+
+Examples
+--------
+
+.. code-block:: yaml
+
+ # Create a bridge named br-int
+ - openvswitch.openvswitch.openvswitch_bridge:
+ bridge: br-int
+ state: present
+
+ # Create a fake bridge named br-int within br-parent on the VLAN 405
+ - openvswitch.openvswitch.openvswitch_bridge:
+ bridge: br-int
+ parent: br-parent
+ vlan: 405
+ state: present
+
+ # Create an integration bridge
+ - openvswitch.openvswitch.openvswitch_bridge:
+ bridge: br-int
+ state: present
+ fail_mode: secure
+ args:
+ external_ids:
+ bridge-id: br-int
+ # Create a bridge named br0 in database with socket at /opt/second.sock
+ - openvswitch.openvswitch.openvswitch_bridge:
+ bridge: br0
+ state: present
+ database_socket: unix:/opt/second.sock
+
+
+
+
+Status
+------
+
+
+Authors
+~~~~~~~
+
+- David Stygstra (@stygstra)
diff --git a/ansible_collections/openvswitch/openvswitch/docs/openvswitch.openvswitch.openvswitch_db_module.rst b/ansible_collections/openvswitch/openvswitch/docs/openvswitch.openvswitch.openvswitch_db_module.rst
new file mode 100644
index 000000000..d8bf4ae72
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/docs/openvswitch.openvswitch.openvswitch_db_module.rst
@@ -0,0 +1,305 @@
+.. _openvswitch.openvswitch.openvswitch_db_module:
+
+
+**************************************
+openvswitch.openvswitch.openvswitch_db
+**************************************
+
+**Configure open vswitch database.**
+
+
+Version added: 1.0.0
+
+.. contents::
+ :local:
+ :depth: 1
+
+
+Synopsis
+--------
+- Set column values in record in database table.
+
+
+
+Requirements
+------------
+The below requirements are needed on the host that executes this module.
+
+- ovs-vsctl >= 2.3.3
+
+
+Parameters
+----------
+
+.. raw:: html
+
+ <table border=0 cellpadding=0 class="documentation-table">
+ <tr>
+ <th colspan="1">Parameter</th>
+ <th>Choices/<font color="blue">Defaults</font></th>
+ <th width="100%">Comments</th>
+ </tr>
+ <tr>
+ <td colspan="1">
+ <div class="ansibleOptionAnchor" id="parameter-"></div>
+ <b>col</b>
+ <a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
+ <div style="font-size: small">
+ <span style="color: purple">string</span>
+ / <span style="color: red">required</span>
+ </div>
+ </td>
+ <td>
+ </td>
+ <td>
+ <div>Identifies the column in the record.</div>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="1">
+ <div class="ansibleOptionAnchor" id="parameter-"></div>
+ <b>database_socket</b>
+ <a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
+ <div style="font-size: small">
+ <span style="color: purple">string</span>
+ </div>
+ </td>
+ <td>
+ </td>
+ <td>
+ <div>Path/ip to datbase socket to use</div>
+ <div>Default path is used if not specified</div>
+ <div>Path should start with &#x27;unix:&#x27; prefix</div>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="1">
+ <div class="ansibleOptionAnchor" id="parameter-"></div>
+ <b>key</b>
+ <a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
+ <div style="font-size: small">
+ <span style="color: purple">string</span>
+ </div>
+ </td>
+ <td>
+ </td>
+ <td>
+ <div>Identifies the key in the record column, when the column is a map type.</div>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="1">
+ <div class="ansibleOptionAnchor" id="parameter-"></div>
+ <b>record</b>
+ <a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
+ <div style="font-size: small">
+ <span style="color: purple">string</span>
+ / <span style="color: red">required</span>
+ </div>
+ </td>
+ <td>
+ </td>
+ <td>
+ <div>Identifies the record in the table.</div>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="1">
+ <div class="ansibleOptionAnchor" id="parameter-"></div>
+ <b>state</b>
+ <a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
+ <div style="font-size: small">
+ <span style="color: purple">string</span>
+ </div>
+ </td>
+ <td>
+ <ul style="margin: 0; padding: 0"><b>Choices:</b>
+ <li><div style="color: blue"><b>present</b>&nbsp;&larr;</div></li>
+ <li>absent</li>
+ <li>read</li>
+ </ul>
+ </td>
+ <td>
+ <div>Configures the state of the key. When set to <em>present</em>, the <em>key</em> and <em>value</em> pair will be set on the <em>record</em> and when set to <em>absent</em> the <em>key</em> will not be set.</div>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="1">
+ <div class="ansibleOptionAnchor" id="parameter-"></div>
+ <b>table</b>
+ <a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
+ <div style="font-size: small">
+ <span style="color: purple">string</span>
+ / <span style="color: red">required</span>
+ </div>
+ </td>
+ <td>
+ </td>
+ <td>
+ <div>Identifies the table in the database.</div>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="1">
+ <div class="ansibleOptionAnchor" id="parameter-"></div>
+ <b>timeout</b>
+ <a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
+ <div style="font-size: small">
+ <span style="color: purple">integer</span>
+ </div>
+ </td>
+ <td>
+ <b>Default:</b><br/><div style="color: blue">5</div>
+ </td>
+ <td>
+ <div>How long to wait for ovs-vswitchd to respond</div>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="1">
+ <div class="ansibleOptionAnchor" id="parameter-"></div>
+ <b>value</b>
+ <a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
+ <div style="font-size: small">
+ <span style="color: purple">string</span>
+ </div>
+ </td>
+ <td>
+ </td>
+ <td>
+ <div>Expected value for the table, record, column and key.</div>
+ </td>
+ </tr>
+ </table>
+ <br/>
+
+
+
+
+Examples
+--------
+
+.. code-block:: yaml
+
+ # Increase the maximum idle time to 50 seconds before pruning unused kernel
+ # rules.
+ - openvswitch.openvswitch.openvswitch_db:
+ table: open_vswitch
+ record: .
+ col: other_config
+ key: max-idle
+ value: 50000
+
+ # Disable in band copy
+ - openvswitch.openvswitch.openvswitch_db:
+ table: Bridge
+ record: br-int
+ col: other_config
+ key: disable-in-band
+ value: true
+
+ # Remove in band key
+ - openvswitch.openvswitch.openvswitch_db:
+ state: present
+ table: Bridge
+ record: br-int
+ col: other_config
+ key: disable-in-band
+
+ # Mark port with tag 10
+ - openvswitch.openvswitch.openvswitch_db:
+ table: Port
+ record: port0
+ col: tag
+ value: 10
+
+ # Mark port with tag 10 for OVSDB with socket in /opt/second.sock
+ - openvswitch.openvswitch.openvswitch_db:
+ table: Port
+ record: port0
+ col: tag
+ value: 10
+ database_socket: unix:/opt/second.sock
+
+ # Get interface statistics
+ - openvswitch.openvswitch.openvswitch_db:
+ state: read
+ table: interface
+ record: ifname
+ col: statistics
+
+ # Get tx_packets value
+ - openvswitch.openvswitch.openvswitch_db:
+ state: read
+ table: interface
+ record: ifname
+ col: statistics
+ key: tx_packets
+
+ # Get mtu value
+ - openvswitch.openvswitch.openvswitch_db:
+ state: read
+ table: interface
+ record: ifname
+ col: mtu
+
+
+
+Return Values
+-------------
+Common return values are documented `here <https://docs.ansible.com/ansible/latest/reference_appendices/common_return_values.html#common-return-values>`_, the following are the fields unique to this module:
+
+.. raw:: html
+
+ <table border=0 cellpadding=0 class="documentation-table">
+ <tr>
+ <th colspan="1">Key</th>
+ <th>Returned</th>
+ <th width="100%">Description</th>
+ </tr>
+ <tr>
+ <td colspan="1">
+ <div class="ansibleOptionAnchor" id="return-"></div>
+ <b>commands</b>
+ <a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
+ <div style="font-size: small">
+ <span style="color: purple">list</span>
+ </div>
+ </td>
+ <td>when state is read</td>
+ <td>
+ <div>List of commands sent</div>
+ <br/>
+ <div style="font-size: smaller"><b>Sample:</b></div>
+ <div style="font-size: smaller; color: blue; word-wrap: break-word; word-break: break-all;">[&#x27;/usr/local/bin/ovs-vsctl -t 5 get interface vhuclient1 statistics:tx_packets&#x27;]</div>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="1">
+ <div class="ansibleOptionAnchor" id="return-"></div>
+ <b>output</b>
+ <a class="ansibleOptionLink" href="#return-" title="Permalink to this return value"></a>
+ <div style="font-size: small">
+ <span style="color: purple">dictionary</span>
+ </div>
+ </td>
+ <td>when state is read</td>
+ <td>
+ <div>Output of the commands</div>
+ <br/>
+ <div style="font-size: smaller"><b>Sample:</b></div>
+ <div style="font-size: smaller; color: blue; word-wrap: break-word; word-break: break-all;">{&#x27;tx_packets&#x27;: &#x27;0&#x27;}</div>
+ </td>
+ </tr>
+ </table>
+ <br/><br/>
+
+
+Status
+------
+
+
+Authors
+~~~~~~~
+
+- Mark Hamilton (@markleehamilton) <mhamilton@vmware.com>
diff --git a/ansible_collections/openvswitch/openvswitch/docs/openvswitch.openvswitch.openvswitch_port_module.rst b/ansible_collections/openvswitch/openvswitch/docs/openvswitch.openvswitch.openvswitch_port_module.rst
new file mode 100644
index 000000000..b5248a975
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/docs/openvswitch.openvswitch.openvswitch_port_module.rst
@@ -0,0 +1,236 @@
+.. _openvswitch.openvswitch.openvswitch_port_module:
+
+
+****************************************
+openvswitch.openvswitch.openvswitch_port
+****************************************
+
+**Manage Open vSwitch ports**
+
+
+Version added: 1.0.0
+
+.. contents::
+ :local:
+ :depth: 1
+
+
+Synopsis
+--------
+- Manage Open vSwitch ports
+
+
+
+Requirements
+------------
+The below requirements are needed on the host that executes this module.
+
+- ovs-vsctl
+
+
+Parameters
+----------
+
+.. raw:: html
+
+ <table border=0 cellpadding=0 class="documentation-table">
+ <tr>
+ <th colspan="1">Parameter</th>
+ <th>Choices/<font color="blue">Defaults</font></th>
+ <th width="100%">Comments</th>
+ </tr>
+ <tr>
+ <td colspan="1">
+ <div class="ansibleOptionAnchor" id="parameter-"></div>
+ <b>bridge</b>
+ <a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
+ <div style="font-size: small">
+ <span style="color: purple">string</span>
+ / <span style="color: red">required</span>
+ </div>
+ </td>
+ <td>
+ </td>
+ <td>
+ <div>Name of bridge to manage</div>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="1">
+ <div class="ansibleOptionAnchor" id="parameter-"></div>
+ <b>database_socket</b>
+ <a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
+ <div style="font-size: small">
+ <span style="color: purple">string</span>
+ </div>
+ </td>
+ <td>
+ </td>
+ <td>
+ <div>Path/ip to datbase socket to use</div>
+ <div>Default path is used if not specified</div>
+ <div>Path should start with &#x27;unix:&#x27; prefix</div>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="1">
+ <div class="ansibleOptionAnchor" id="parameter-"></div>
+ <b>external_ids</b>
+ <a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
+ <div style="font-size: small">
+ <span style="color: purple">dictionary</span>
+ </div>
+ </td>
+ <td>
+ <b>Default:</b><br/><div style="color: blue">{}</div>
+ </td>
+ <td>
+ <div>Dictionary of external_ids applied to a port.</div>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="1">
+ <div class="ansibleOptionAnchor" id="parameter-"></div>
+ <b>port</b>
+ <a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
+ <div style="font-size: small">
+ <span style="color: purple">string</span>
+ / <span style="color: red">required</span>
+ </div>
+ </td>
+ <td>
+ </td>
+ <td>
+ <div>Name of port to manage on the bridge</div>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="1">
+ <div class="ansibleOptionAnchor" id="parameter-"></div>
+ <b>set</b>
+ <a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
+ <div style="font-size: small">
+ <span style="color: purple">list</span>
+ / <span style="color: purple">elements=string</span>
+ </div>
+ </td>
+ <td>
+ </td>
+ <td>
+ <div>Set multiple properties on a port.</div>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="1">
+ <div class="ansibleOptionAnchor" id="parameter-"></div>
+ <b>state</b>
+ <a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
+ <div style="font-size: small">
+ <span style="color: purple">string</span>
+ </div>
+ </td>
+ <td>
+ <ul style="margin: 0; padding: 0"><b>Choices:</b>
+ <li><div style="color: blue"><b>present</b>&nbsp;&larr;</div></li>
+ <li>absent</li>
+ </ul>
+ </td>
+ <td>
+ <div>Whether the port should exist</div>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="1">
+ <div class="ansibleOptionAnchor" id="parameter-"></div>
+ <b>tag</b>
+ <a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
+ <div style="font-size: small">
+ <span style="color: purple">string</span>
+ </div>
+ </td>
+ <td>
+ </td>
+ <td>
+ <div>VLAN tag for this port. Must be a value between 0 and 4095.</div>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="1">
+ <div class="ansibleOptionAnchor" id="parameter-"></div>
+ <b>timeout</b>
+ <a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
+ <div style="font-size: small">
+ <span style="color: purple">integer</span>
+ </div>
+ </td>
+ <td>
+ <b>Default:</b><br/><div style="color: blue">5</div>
+ </td>
+ <td>
+ <div>How long to wait for ovs-vswitchd to respond</div>
+ </td>
+ </tr>
+ </table>
+ <br/>
+
+
+
+
+Examples
+--------
+
+.. code-block:: yaml
+
+ # Creates port eth2 on bridge br-ex
+ - openvswitch.openvswitch.openvswitch_port:
+ bridge: br-ex
+ port: eth2
+ state: present
+
+ # Creates port eth6
+ - openvswitch.openvswitch.openvswitch_port:
+ bridge: bridge-loop
+ port: eth6
+ state: present
+ set: Interface eth6
+
+ # Creates port vlan10 with tag 10 on bridge br-ex
+ - openvswitch.openvswitch.openvswitch_port:
+ bridge: br-ex
+ port: vlan10
+ tag: 10
+ state: present
+ set: Interface vlan10
+
+ # Assign interface id server1-vifeth6 and mac address 00:00:5E:00:53:23
+ # to port vifeth6 and setup port to be managed by a controller.
+ - openvswitch.openvswitch.openvswitch_port:
+ bridge: br-int
+ port: vifeth6
+ state: present
+ args:
+ external_ids:
+ iface-id: '{{ inventory_hostname }}-vifeth6'
+ attached-mac: 00:00:5E:00:53:23
+ vm-id: '{{ inventory_hostname }}'
+ iface-status: active
+
+ # Plugs port veth0 into brdige br0 for database for OVSDB instance
+ # with socket unix:/opt/second_ovsdb.sock
+ - openvswitch.openvswitch.openvswitch_port:
+ bridge: br0
+ port: veth0
+ state: present
+ database_socket: unix:/opt/second_ovsdb.sock
+
+
+
+
+Status
+------
+
+
+Authors
+~~~~~~~
+
+- David Stygstra (@stygstra)
diff --git a/ansible_collections/openvswitch/openvswitch/meta/runtime.yml b/ansible_collections/openvswitch/openvswitch/meta/runtime.yml
new file mode 100644
index 000000000..c3911995d
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/meta/runtime.yml
@@ -0,0 +1,12 @@
+---
+requires_ansible: ">=2.9.10"
+plugin_routing:
+ modules:
+ bridge:
+ redirect: openvswitch.openvswitch.openvswitch_bridge
+ db:
+ redirect: openvswitch.openvswitch.openvswitch_db
+ port:
+ redirect: openvswitch.openvswitch.openvswitch_port
+ bond:
+ redirect: openvswitch.openvswitch.openvswitch_bond
diff --git a/ansible_collections/openvswitch/openvswitch/plugins/modules/__init__.py b/ansible_collections/openvswitch/openvswitch/plugins/modules/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/plugins/modules/__init__.py
diff --git a/ansible_collections/openvswitch/openvswitch/plugins/modules/openvswitch_bond.py b/ansible_collections/openvswitch/openvswitch/plugins/modules/openvswitch_bond.py
new file mode 100644
index 000000000..ece20811f
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/plugins/modules/openvswitch_bond.py
@@ -0,0 +1,391 @@
+#!/usr/bin/python
+# coding: utf-8 -*-
+
+# (c) 2020, James Denton <james.denton@outlook.com>
+# Portions copyright @ 2013 David Stygstra <david.stygstra@gmail.com>
+# Portions copyright @ 2015 VMware, Inc.
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+DOCUMENTATION = """
+---
+module: openvswitch_bond
+author: "James Denton (@busterswt)"
+short_description: Manage Open vSwitch bonds
+requirements:
+- ovs-vsctl
+description:
+- Manage Open vSwitch bonds and associated options.
+version_added: '1.0.0'
+options:
+ bridge:
+ required: true
+ description:
+ - Name of bridge to manage
+ type: str
+ port:
+ required: true
+ description:
+ - Name of port to manage on the bridge
+ type: str
+ interfaces:
+ description:
+ - List of interfaces to add to the bond
+ type: list
+ elements: str
+ bond_mode:
+ choices: [ active-backup, balance-tcp, balance-slb ]
+ description:
+ - Sets the bond mode
+ type: str
+ lacp:
+ choices: [ 'active', 'passive', 'off' ]
+ description:
+ - Sets LACP mode
+ type: str
+ bond_updelay:
+ description:
+ - Number of milliseconds a link must be up to be activated
+ to prevent flapping.
+ type: int
+ bond_downdelay:
+ description:
+ - Number of milliseconds a link must be down to be deactivated
+ to prevent flapping.
+ type: int
+ state:
+ default: 'present'
+ choices: [ 'present', 'absent' ]
+ description:
+ - Whether the port should exist
+ type: str
+ timeout:
+ default: 5
+ description:
+ - How long to wait for ovs-vswitchd to respond in seconds
+ type: int
+ external_ids:
+ default: {}
+ description:
+ - Dictionary of external_ids applied to a port.
+ type: dict
+ other_config:
+ default: {}
+ description:
+ - Dictionary of other_config applied to a port.
+ type: dict
+ set:
+ description:
+ - Sets one or more properties on a port.
+ type: list
+ elements: str
+ database_socket:
+ description:
+ - Path/ip to datbase socket to use
+ - Default path is used if not specified
+ - Path should start with 'unix:' prefix
+ type: str
+"""
+
+EXAMPLES = """
+- name: Create an active-backup bond using eth4 and eth5 on bridge br-ex
+ openvswitch.openvswitch.openvswitch_bond:
+ bridge: br-ex
+ port: bond1
+ interfaces:
+ - eth4
+ - eth5
+ state: present
+- name: Delete the bond from bridge br-ex
+ openvswitch.openvswitch.openvswitch_bond:
+ bridge: br-ex
+ port: bond1
+ state: absent
+- name: Create an active LACP bond using eth4 and eth5 on bridge br-ex
+ openvswitch.openvswitch.openvswitch_bond:
+ bridge: br-ex
+ port: bond1
+ interfaces:
+ - eth4
+ - eth5
+ lacp: active
+ state: present
+# NOTE: other_config values of integer type must be represented
+# as literal strings
+- name: Configure bond with miimon link monitoring at 100 millisecond intervals
+ openvswitch.openvswitch.openvswitch_bond:
+ bridge: br-ex
+ port: bond1
+ interfaces:
+ - eth4
+ - eth5
+ bond_updelay: 100
+ bond_downdelay: 100
+ state: present
+ args:
+ other_config:
+ bond-detect-mode: miimon
+ bond-miimon-interval: '"100"'
+- name: Create an active LACP bond using DPDK interfaces
+ openvswitch.openvswitch.openvswitch_bond:
+ bridge: br-provider
+ port: dpdkbond
+ interfaces:
+ - "0000:04:00.0"
+ - "0000:04:00.1"
+ lacp: active
+ set:
+ - "interface 0000:04:00.0 type=dpdk options:dpdk-devargs=0000:04:00.0"
+ - "interface 0000:04:00.1 type=dpdk options:dpdk-devargs=0000:04:00.1"
+ state: present
+- name: Create an active-backup bond using eth4 and eth5 on bridge br-ex in second OVS database
+ openvswitch.openvswitch.openvswitch_bond:
+ bridge: br-ex
+ port: bond1
+ interfaces:
+ - eth4
+ - eth5
+ state: present
+ database_socket: unix:/opt/second.sock
+"""
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible.module_utils.six import iteritems
+
+
+def _external_ids_to_dict(text):
+ text = text.strip()
+
+ if text == "{}":
+ return None
+
+ else:
+ d = {}
+
+ for kv in text[1:-1].split(","):
+ kv = kv.strip()
+ k, v = kv.split("=")
+ d[k] = v
+
+ return d
+
+
+def _other_config_to_dict(text):
+ text = text.strip()
+
+ if text == "{}":
+ return None
+ else:
+ d = {}
+
+ for kv in text[1:-1].split(","):
+ kv = kv.strip()
+ k, v = kv.split("=")
+ d[k] = v
+
+ return d
+
+
+def map_obj_to_commands(want, have, module):
+ commands = list()
+
+ if module.params["state"] == "absent":
+ if have:
+ templatized_command = "%(ovs-vsctl)s -t %(timeout)s del-port %(bridge)s %(port)s"
+ command = templatized_command % module.params
+ commands.append(command)
+ else:
+ if have:
+ if want["other_config"] != have["other_config"]:
+ for k, v in iteritems(want["other_config"]):
+ if (
+ not have["other_config"]
+ or k not in have["other_config"]
+ or want["other_config"][k] != have["other_config"][k]
+ ):
+ if v is None:
+ templatized_command = (
+ "%(ovs-vsctl)s -t %(timeout)s remove port %(port)s other_config "
+ + k
+ )
+ command = templatized_command % module.params
+ commands.append(command)
+ else:
+ templatized_command = (
+ "%(ovs-vsctl)s -t %(timeout)s set port %(port)s other_config:"
+ )
+ command = templatized_command % module.params
+ command += k + "=" + v
+ commands.append(command)
+
+ if want["external_ids"] != have["external_ids"]:
+ for k, v in iteritems(want["external_ids"]):
+ if (
+ not have["external_ids"]
+ or k not in have["external_ids"]
+ or want["external_ids"][k] != have["external_ids"][k]
+ ):
+ if v is None:
+ templatized_command = (
+ "%(ovs-vsctl)s -t %(timeout)s remove port %(port)s external_ids "
+ + k
+ )
+ command = templatized_command % module.params
+ commands.append(command)
+ else:
+ templatized_command = (
+ "%(ovs-vsctl)s -t %(timeout)s set port %(port)s external_ids:"
+ )
+ command = templatized_command % module.params
+ command += k + "=" + v
+ commands.append(command)
+
+ else:
+ templatized_command = "%(ovs-vsctl)s -t %(timeout)s add-bond %(bridge)s %(port)s"
+ command = templatized_command % module.params
+
+ if want["interfaces"]:
+ for interface in want["interfaces"]:
+ command += " " + interface
+
+ if want["bond_mode"]:
+ templatized_command = " bond_mode=%(bond_mode)s"
+ command += templatized_command % module.params
+
+ if want["lacp"]:
+ templatized_command = " lacp=%(lacp)s"
+ command += templatized_command % module.params
+
+ if want["bond_updelay"]:
+ templatized_command = " bond_updelay=%(bond_updelay)s"
+ command += templatized_command % module.params
+
+ if want["bond_downdelay"]:
+ templatized_command = " bond_downdelay=%(bond_downdelay)s"
+ command += templatized_command % module.params
+
+ if want["set"]:
+ for set in want["set"]:
+ command += " -- set " + set
+
+ commands.append(command)
+
+ if want["other_config"]:
+ for k, v in iteritems(want["other_config"]):
+ templatized_command = (
+ "%(ovs-vsctl)s -t %(timeout)s set port %(port)s other_config:"
+ )
+ command = templatized_command % module.params
+ command += k + "=" + v
+ commands.append(command)
+
+ if want["external_ids"]:
+ for k, v in iteritems(want["external_ids"]):
+ templatized_command = (
+ "%(ovs-vsctl)s -t %(timeout)s set port %(port)s external_ids:"
+ )
+ command = templatized_command % module.params
+ command += k + "=" + v
+ commands.append(command)
+
+ return commands
+
+
+def map_config_to_obj(module):
+ templatized_command = "%(ovs-vsctl)s -t %(timeout)s list-ports %(bridge)s"
+ command = templatized_command % module.params
+ rc, out, err = module.run_command(command, check_rc=True)
+ if rc != 0:
+ module.fail_json(msg=err)
+
+ obj = {}
+
+ if module.params["port"] in out.splitlines():
+ obj["bridge"] = module.params["bridge"]
+ obj["port"] = module.params["port"]
+
+ templatized_command = "%(ovs-vsctl)s -t %(timeout)s get Port %(port)s other_config"
+ command = templatized_command % module.params
+ rc, out, err = module.run_command(command, check_rc=True)
+ obj["other_config"] = _other_config_to_dict(out)
+
+ templatized_command = "%(ovs-vsctl)s -t %(timeout)s get Port %(port)s external_ids"
+ command = templatized_command % module.params
+ rc, out, err = module.run_command(command, check_rc=True)
+ obj["external_ids"] = _external_ids_to_dict(out)
+
+ return obj
+
+
+def map_params_to_obj(module):
+ obj = {
+ "bridge": module.params["bridge"],
+ "port": module.params["port"],
+ "interfaces": module.params["interfaces"],
+ "bond_mode": module.params["bond_mode"],
+ "lacp": module.params["lacp"],
+ "bond_updelay": module.params["bond_updelay"],
+ "bond_downdelay": module.params["bond_downdelay"],
+ "external_ids": module.params["external_ids"],
+ "other_config": module.params["other_config"],
+ "set": module.params["set"],
+ }
+
+ return obj
+
+
+def main():
+ """Entry point."""
+ argument_spec = {
+ "bridge": {"required": True},
+ "port": {"required": True},
+ "interfaces": {"type": "list", "elements": "str"},
+ "bond_mode": {
+ "default": None,
+ "choices": ["active-backup", "balance-tcp", "balance-slb"],
+ },
+ "lacp": {"default": None, "choices": ["active", "passive", "off"]},
+ "bond_updelay": {"default": None, "type": "int"},
+ "bond_downdelay": {"default": None, "type": "int"},
+ "state": {"default": "present", "choices": ["present", "absent"]},
+ "timeout": {"default": 5, "type": "int"},
+ "external_ids": {"default": {}, "type": "dict"},
+ "other_config": {"default": {}, "type": "dict"},
+ "set": {
+ "required": False,
+ "type": "list",
+ "default": None,
+ "elements": "str",
+ },
+ "database_socket": {"default": None},
+ }
+
+ module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True)
+
+ result = {"changed": False}
+
+ # We add ovs-vsctl to module_params to later build up templatized commands
+ module.params["ovs-vsctl"] = module.get_bin_path("ovs-vsctl", True)
+ if module.params.get("database_socket"):
+ module.params["ovs-vsctl"] += " --db=" + module.params.get("database_socket")
+
+ want = map_params_to_obj(module)
+ have = map_config_to_obj(module)
+
+ commands = map_obj_to_commands(want, have, module)
+ result["commands"] = commands
+
+ if commands:
+ if not module.check_mode:
+ for c in commands:
+ module.run_command(c, check_rc=True)
+ result["changed"] = True
+
+ module.exit_json(**result)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/ansible_collections/openvswitch/openvswitch/plugins/modules/openvswitch_bridge.py b/ansible_collections/openvswitch/openvswitch/plugins/modules/openvswitch_bridge.py
new file mode 100644
index 000000000..0aed44d79
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/plugins/modules/openvswitch_bridge.py
@@ -0,0 +1,286 @@
+#!/usr/bin/python
+
+# (c) 2013, David Stygstra <david.stygstra@gmail.com>
+# Portions copyright @ 2015 VMware, Inc.
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+
+DOCUMENTATION = """
+module: openvswitch_bridge
+author: David Stygstra (@stygstra)
+short_description: Manage Open vSwitch bridges
+requirements:
+- ovs-vsctl
+description:
+- Manage Open vSwitch bridges
+version_added: 1.0.0
+options:
+ bridge:
+ required: true
+ description:
+ - Name of bridge or fake bridge to manage
+ type: str
+ parent:
+ description:
+ - Bridge parent of the fake bridge to manage
+ type: str
+ vlan:
+ description:
+ - The VLAN id of the fake bridge to manage (must be between 0 and 4095). This
+ parameter is required if I(parent) parameter is set.
+ type: int
+ state:
+ default: present
+ choices:
+ - present
+ - absent
+ description:
+ - Whether the bridge should exist
+ type: str
+ timeout:
+ default: 5
+ description:
+ - How long to wait for ovs-vswitchd to respond
+ type: int
+ external_ids:
+ description:
+ - A dictionary of external-ids. Omitting this parameter is a No-op. To clear
+ all external-ids pass an empty value.
+ type: dict
+ fail_mode:
+ description:
+ - Set bridge fail-mode. The default value (None) is a No-op.
+ type: str
+ set:
+ description:
+ - Run set command after bridge configuration. This parameter is non-idempotent,
+ play will always return I(changed) state if present
+ type: str
+ database_socket:
+ description:
+ - Path/ip to datbase socket to use
+ - Default path is used if not specified
+ - Path should start with 'unix:' prefix
+ type: str
+"""
+
+EXAMPLES = """
+# Create a bridge named br-int
+- openvswitch.openvswitch.openvswitch_bridge:
+ bridge: br-int
+ state: present
+
+# Create a fake bridge named br-int within br-parent on the VLAN 405
+- openvswitch.openvswitch.openvswitch_bridge:
+ bridge: br-int
+ parent: br-parent
+ vlan: 405
+ state: present
+
+# Create an integration bridge
+- openvswitch.openvswitch.openvswitch_bridge:
+ bridge: br-int
+ state: present
+ fail_mode: secure
+ args:
+ external_ids:
+ bridge-id: br-int
+# Create a bridge named br0 in database with socket at /opt/second.sock
+- openvswitch.openvswitch.openvswitch_bridge:
+ bridge: br0
+ state: present
+ database_socket: unix:/opt/second.sock
+"""
+
+from ansible.module_utils._text import to_text
+from ansible.module_utils.basic import AnsibleModule
+from ansible.module_utils.six import iteritems
+
+
+def _fail_mode_to_str(text):
+ if not text:
+ return None
+ else:
+ return text.strip()
+
+
+def _external_ids_to_dict(text):
+ if not text:
+ return None
+ else:
+ d = {}
+
+ for l in text.splitlines():
+ if l:
+ k, v = l.split("=")
+ d[k] = v
+
+ return d
+
+
+def map_obj_to_commands(want, have, module):
+ commands = list()
+
+ if module.params["state"] == "absent":
+ if have:
+ templatized_command = "%(ovs-vsctl)s -t %(timeout)s del-br %(bridge)s"
+ command = templatized_command % module.params
+ commands.append(command)
+ else:
+ if have:
+ if want["fail_mode"] != have["fail_mode"]:
+ templatized_command = (
+ "%(ovs-vsctl)s -t %(timeout)s set-fail-mode %(bridge)s %(fail_mode)s"
+ )
+ command = templatized_command % module.params
+ commands.append(command)
+
+ if want["external_ids"] != have["external_ids"]:
+ templatized_command = "%(ovs-vsctl)s -t %(timeout)s br-set-external-id %(bridge)s"
+ command = templatized_command % module.params
+ if want["external_ids"]:
+ for k, v in iteritems(want["external_ids"]):
+ if (
+ k not in have["external_ids"]
+ or want["external_ids"][k] != have["external_ids"][k]
+ ):
+ command += " " + k + " " + v
+ commands.append(command)
+
+ if want["vlan"] and to_text(want["vlan"]) != have["vlan"]:
+ templatized_command = (
+ "%(ovs-vsctl)s -t %(timeout)s set port %(bridge)s tag=%(vlan)s"
+ )
+ command = templatized_command % module.params
+ commands.append(command)
+ else:
+ templatized_command = "%(ovs-vsctl)s -t %(timeout)s add-br %(bridge)s"
+ command = templatized_command % module.params
+
+ if want["parent"]:
+ templatized_command = "%(parent)s %(vlan)s"
+ command += " " + templatized_command % module.params
+
+ if want["set"]:
+ templatized_command = " -- set %(set)s"
+ command += templatized_command % module.params
+
+ commands.append(command)
+
+ if want["fail_mode"]:
+ templatized_command = (
+ "%(ovs-vsctl)s -t %(timeout)s set-fail-mode %(bridge)s %(fail_mode)s"
+ )
+ command = templatized_command % module.params
+ commands.append(command)
+
+ if want["external_ids"]:
+ for k, v in iteritems(want["external_ids"]):
+ templatized_command = (
+ "%(ovs-vsctl)s -t %(timeout)s br-set-external-id %(bridge)s"
+ )
+ command = templatized_command % module.params
+ command += " " + k + " " + v
+ commands.append(command)
+
+ return commands
+
+
+def map_config_to_obj(module):
+ templatized_command = "%(ovs-vsctl)s -t %(timeout)s list-br"
+ command = templatized_command % module.params
+ rc, out, err = module.run_command(command, check_rc=True)
+ if rc != 0:
+ module.fail_json(msg=err)
+
+ obj = {}
+
+ if module.params["bridge"] in out.splitlines():
+ obj["bridge"] = module.params["bridge"]
+
+ templatized_command = "%(ovs-vsctl)s -t %(timeout)s br-to-parent %(bridge)s"
+ command = templatized_command % module.params
+ rc, out, err = module.run_command(command, check_rc=True)
+ obj["parent"] = out.strip()
+
+ templatized_command = "%(ovs-vsctl)s -t %(timeout)s br-to-vlan %(bridge)s"
+ command = templatized_command % module.params
+ rc, out, err = module.run_command(command, check_rc=True)
+ obj["vlan"] = out.strip()
+
+ templatized_command = "%(ovs-vsctl)s -t %(timeout)s get-fail-mode %(bridge)s"
+ command = templatized_command % module.params
+ rc, out, err = module.run_command(command, check_rc=True)
+ obj["fail_mode"] = _fail_mode_to_str(out)
+
+ templatized_command = "%(ovs-vsctl)s -t %(timeout)s br-get-external-id %(bridge)s"
+ command = templatized_command % module.params
+ rc, out, err = module.run_command(command, check_rc=True)
+ obj["external_ids"] = _external_ids_to_dict(out)
+
+ return obj
+
+
+def map_params_to_obj(module):
+ obj = {
+ "bridge": module.params["bridge"],
+ "parent": module.params["parent"],
+ "vlan": module.params["vlan"],
+ "fail_mode": module.params["fail_mode"],
+ "external_ids": module.params["external_ids"],
+ "set": module.params["set"],
+ }
+
+ return obj
+
+
+def main():
+ """Entry point."""
+ argument_spec = {
+ "bridge": {"required": True},
+ "parent": {"default": None},
+ "vlan": {"default": None, "type": "int"},
+ "state": {"default": "present", "choices": ["present", "absent"]},
+ "timeout": {"default": 5, "type": "int"},
+ "external_ids": {"default": None, "type": "dict"},
+ "fail_mode": {"default": None},
+ "set": {"required": False, "default": None},
+ "database_socket": {"default": None},
+ }
+
+ required_if = [("parent", not None, ("vlan",))]
+
+ module = AnsibleModule(
+ argument_spec=argument_spec,
+ required_if=required_if,
+ supports_check_mode=True,
+ )
+
+ result = {"changed": False}
+
+ # We add ovs-vsctl to module_params to later build up templatized commands
+ module.params["ovs-vsctl"] = module.get_bin_path("ovs-vsctl", True)
+ if module.params.get("database_socket"):
+ module.params["ovs-vsctl"] += " --db=" + module.params.get("database_socket")
+
+ want = map_params_to_obj(module)
+ have = map_config_to_obj(module)
+
+ commands = map_obj_to_commands(want, have, module)
+ result["commands"] = commands
+
+ if commands:
+ if not module.check_mode:
+ for c in commands:
+ module.run_command(c, check_rc=True)
+ result["changed"] = True
+
+ module.exit_json(**result)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/ansible_collections/openvswitch/openvswitch/plugins/modules/openvswitch_db.py b/ansible_collections/openvswitch/openvswitch/plugins/modules/openvswitch_db.py
new file mode 100644
index 000000000..b4928704a
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/plugins/modules/openvswitch_db.py
@@ -0,0 +1,314 @@
+#!/usr/bin/python
+
+#
+# (c) 2015, Mark Hamilton <mhamilton@vmware.com>
+# Portions copyright @ 2015 VMware, Inc.
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+
+DOCUMENTATION = """
+module: openvswitch_db
+author: Mark Hamilton (@markleehamilton) <mhamilton@vmware.com>
+short_description: Configure open vswitch database.
+requirements:
+- ovs-vsctl >= 2.3.3
+description:
+- Set column values in record in database table.
+version_added: 1.0.0
+options:
+ state:
+ required: false
+ description:
+ - Configures the state of the key. When set to I(present), the I(key) and I(value)
+ pair will be set on the I(record) and when set to I(absent) the I(key) will
+ not be set.
+ default: present
+ choices:
+ - present
+ - absent
+ - read
+ type: str
+ table:
+ required: true
+ description:
+ - Identifies the table in the database.
+ type: str
+ record:
+ required: true
+ description:
+ - Identifies the record in the table.
+ type: str
+ col:
+ required: true
+ description:
+ - Identifies the column in the record.
+ type: str
+ key:
+ required: false
+ description:
+ - Identifies the key in the record column, when the column is a map type.
+ type: str
+ value:
+ description:
+ - Expected value for the table, record, column and key.
+ type: str
+ timeout:
+ required: false
+ default: 5
+ description:
+ - How long to wait for ovs-vswitchd to respond
+ type: int
+ database_socket:
+ description:
+ - Path/ip to datbase socket to use
+ - Default path is used if not specified
+ - Path should start with 'unix:' prefix
+ type: str
+"""
+
+EXAMPLES = """
+# Increase the maximum idle time to 50 seconds before pruning unused kernel
+# rules.
+- openvswitch.openvswitch.openvswitch_db:
+ table: open_vswitch
+ record: .
+ col: other_config
+ key: max-idle
+ value: 50000
+
+# Disable in band copy
+- openvswitch.openvswitch.openvswitch_db:
+ table: Bridge
+ record: br-int
+ col: other_config
+ key: disable-in-band
+ value: true
+
+# Remove in band key
+- openvswitch.openvswitch.openvswitch_db:
+ state: present
+ table: Bridge
+ record: br-int
+ col: other_config
+ key: disable-in-band
+
+# Mark port with tag 10
+- openvswitch.openvswitch.openvswitch_db:
+ table: Port
+ record: port0
+ col: tag
+ value: 10
+
+# Mark port with tag 10 for OVSDB with socket in /opt/second.sock
+- openvswitch.openvswitch.openvswitch_db:
+ table: Port
+ record: port0
+ col: tag
+ value: 10
+ database_socket: unix:/opt/second.sock
+
+# Get interface statistics
+- openvswitch.openvswitch.openvswitch_db:
+ state: read
+ table: interface
+ record: ifname
+ col: statistics
+
+# Get tx_packets value
+- openvswitch.openvswitch.openvswitch_db:
+ state: read
+ table: interface
+ record: ifname
+ col: statistics
+ key: tx_packets
+
+# Get mtu value
+- openvswitch.openvswitch.openvswitch_db:
+ state: read
+ table: interface
+ record: ifname
+ col: mtu
+"""
+
+RETURN = """
+commands:
+ description: List of commands sent
+ returned: when state is read
+ type: list
+ sample: ["/usr/local/bin/ovs-vsctl -t 5 get interface vhuclient1 statistics:tx_packets"]
+output:
+ description: Output of the commands
+ returned: when state is read
+ type: dict
+ sample: {"tx_packets": "0"}
+"""
+import re
+
+from ansible.module_utils.basic import AnsibleModule
+
+# Regular expression for map type, must not be empty
+NON_EMPTY_MAP_RE = re.compile(r"{.+}")
+# Regular expression for a map column type
+MAP_RE = re.compile(r"{.*}")
+
+
+def map_obj_to_commands(want, have, module):
+ """Define ovs-vsctl command to meet desired state"""
+ commands = list()
+
+ if module.params["state"] == "absent":
+ if "key" in have.keys():
+ templatized_command = (
+ "%(ovs-vsctl)s -t %(timeout)s remove %(table)s %(record)s %(col)s %(key)s"
+ )
+ if module.params.get("value"):
+ templatized_command += "=%(value)s"
+ commands.append(templatized_command % module.params)
+ elif module.params["key"] is None:
+ templatized_command = "%(ovs-vsctl)s -t %(timeout)s remove %(table)s %(record)s %(col)s"
+ commands.append(templatized_command % module.params)
+ elif module.params["state"] == "read":
+ if module.params["key"] is None:
+ templatized_command = "%(ovs-vsctl)s -t %(timeout)s get %(table)s %(record)s %(col)s"
+ commands.append(templatized_command % module.params)
+ else:
+ templatized_command = (
+ "%(ovs-vsctl)s -t %(timeout)s get %(table)s %(record)s %(col)s:%(key)s"
+ )
+ commands.append(templatized_command % module.params)
+ else:
+ if want == have:
+ # Nothing to commit
+ return commands
+ if module.params["key"] is None:
+ templatized_command = (
+ "%(ovs-vsctl)s -t %(timeout)s set %(table)s %(record)s %(col)s=%(value)s"
+ )
+ commands.append(templatized_command % module.params)
+ else:
+ templatized_command = (
+ "%(ovs-vsctl)s -t %(timeout)s set %(table)s %(record)s %(col)s:%(key)s=%(value)s"
+ )
+ commands.append(templatized_command % module.params)
+
+ return commands
+
+
+def map_config_to_obj(module):
+ templatized_command = "%(ovs-vsctl)s -t %(timeout)s list %(table)s %(record)s"
+ command = templatized_command % module.params
+ rc, out, err = module.run_command(command, check_rc=True)
+ if rc != 0:
+ module.fail_json(msg=err)
+
+ match = re.search(r"^" + module.params["col"] + r"(\s+):(\s+)(.*)$", out, re.M)
+
+ col_value = match.group(3)
+
+ # Map types require key argument
+ has_key = module.params["key"] is not None
+ is_map = MAP_RE.match(col_value)
+ if is_map and not has_key and module.params["state"] != "read":
+ module.fail_json(msg="missing required arguments: key for map type of column")
+
+ col_value_to_dict = {}
+ if NON_EMPTY_MAP_RE.match(col_value):
+ for kv in col_value[1:-1].split(", "):
+ k, v = kv.split("=", 1)
+ col_value_to_dict[k.strip()] = v.strip('"')
+
+ obj = {
+ "table": module.params["table"],
+ "record": module.params["record"],
+ "col": module.params["col"],
+ }
+
+ if has_key and is_map:
+ if module.params["key"] in col_value_to_dict:
+ obj["key"] = module.params["key"]
+ obj["value"] = col_value_to_dict[module.params["key"]]
+ else:
+ obj["value"] = str(col_value.strip())
+
+ return obj
+
+
+def map_params_to_obj(module):
+ if module.params["value"] in ["True", "False"]:
+ module.params["value"] = module.params["value"].lower()
+ obj = {
+ "table": module.params["table"],
+ "record": module.params["record"],
+ "col": module.params["col"],
+ "value": module.params["value"],
+ }
+
+ key = module.params["key"]
+ if key is not None:
+ obj["key"] = key
+
+ return obj
+
+
+def main():
+ """Entry point for ansible module."""
+ argument_spec = {
+ "state": {
+ "default": "present",
+ "choices": ["present", "absent", "read"],
+ },
+ "table": {"required": True},
+ "record": {"required": True},
+ "col": {"required": True},
+ "key": {"required": False, "no_log": False},
+ "value": {"type": "str"},
+ "timeout": {"default": 5, "type": "int"},
+ "database_socket": {"default": None},
+ }
+
+ module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True)
+
+ result = {"changed": False}
+
+ # We add ovs-vsctl to module_params to later build up templatized commands
+ module.params["ovs-vsctl"] = module.get_bin_path("ovs-vsctl", True)
+ if module.params.get("database_socket"):
+ module.params["ovs-vsctl"] += " --db=" + module.params.get("database_socket")
+
+ if module.params["state"] == "present" and not module.params["value"]:
+ module.fail_json(msg="missing required argument value for state: present")
+
+ want = map_params_to_obj(module)
+ have = map_config_to_obj(module)
+
+ commands = map_obj_to_commands(want, have, module)
+ result["commands"] = commands
+
+ if commands:
+ if not module.check_mode:
+ for c in commands:
+ rc, out, err = module.run_command(c, check_rc=True)
+ result["changed"] = True
+
+ string_to_dict = {}
+
+ if NON_EMPTY_MAP_RE.match(str(out)):
+ for kv in re.split(r", ", out[1:-1]):
+ k, v = re.split(r"=", kv, 1)
+ string_to_dict[re.search("\\w*", k).group(0)] = re.search("\\d*", v).group(0)
+ else:
+ if module.params["key"] is not None:
+ string_to_dict[module.params["key"]] = re.search("\\w*", str(out)).group(0)
+ else:
+ string_to_dict[module.params["col"]] = re.search("\\w*", str(out)).group(0)
+ result["output"] = string_to_dict
+
+ module.exit_json(**result)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/ansible_collections/openvswitch/openvswitch/plugins/modules/openvswitch_port.py b/ansible_collections/openvswitch/openvswitch/plugins/modules/openvswitch_port.py
new file mode 100644
index 000000000..ba1f9daa2
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/plugins/modules/openvswitch_port.py
@@ -0,0 +1,282 @@
+#!/usr/bin/python
+
+# (c) 2013, David Stygstra <david.stygstra@gmail.com>
+# Portions copyright @ 2015 VMware, Inc.
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+
+DOCUMENTATION = """
+module: openvswitch_port
+author: David Stygstra (@stygstra)
+short_description: Manage Open vSwitch ports
+requirements:
+- ovs-vsctl
+description:
+- Manage Open vSwitch ports
+version_added: 1.0.0
+options:
+ bridge:
+ required: true
+ description:
+ - Name of bridge to manage
+ type: str
+ port:
+ required: true
+ description:
+ - Name of port to manage on the bridge
+ type: str
+ tag:
+ description:
+ - VLAN tag for this port. Must be a value between 0 and 4095.
+ type: str
+ state:
+ default: present
+ choices:
+ - present
+ - absent
+ description:
+ - Whether the port should exist
+ type: str
+ timeout:
+ default: 5
+ description:
+ - How long to wait for ovs-vswitchd to respond
+ type: int
+ external_ids:
+ default: {}
+ description:
+ - Dictionary of external_ids applied to a port.
+ type: dict
+ set:
+ description:
+ - Set multiple properties on a port.
+ type: list
+ elements: str
+ database_socket:
+ description:
+ - Path/ip to datbase socket to use
+ - Default path is used if not specified
+ - Path should start with 'unix:' prefix
+ type: str
+"""
+
+EXAMPLES = """
+# Creates port eth2 on bridge br-ex
+- openvswitch.openvswitch.openvswitch_port:
+ bridge: br-ex
+ port: eth2
+ state: present
+
+# Creates port eth6
+- openvswitch.openvswitch.openvswitch_port:
+ bridge: bridge-loop
+ port: eth6
+ state: present
+ set: Interface eth6
+
+# Creates port vlan10 with tag 10 on bridge br-ex
+- openvswitch.openvswitch.openvswitch_port:
+ bridge: br-ex
+ port: vlan10
+ tag: 10
+ state: present
+ set: Interface vlan10
+
+# Assign interface id server1-vifeth6 and mac address 00:00:5E:00:53:23
+# to port vifeth6 and setup port to be managed by a controller.
+- openvswitch.openvswitch.openvswitch_port:
+ bridge: br-int
+ port: vifeth6
+ state: present
+ args:
+ external_ids:
+ iface-id: '{{ inventory_hostname }}-vifeth6'
+ attached-mac: 00:00:5E:00:53:23
+ vm-id: '{{ inventory_hostname }}'
+ iface-status: active
+
+# Plugs port veth0 into brdige br0 for database for OVSDB instance
+# with socket unix:/opt/second_ovsdb.sock
+- openvswitch.openvswitch.openvswitch_port:
+ bridge: br0
+ port: veth0
+ state: present
+ database_socket: unix:/opt/second_ovsdb.sock
+
+"""
+
+from ansible.module_utils.basic import AnsibleModule
+from ansible.module_utils.six import iteritems
+
+
+def _external_ids_to_dict(text):
+ text = text.strip()
+
+ if text == "{}":
+ return None
+ else:
+ d = {}
+
+ for kv in text[1:-1].split(","):
+ kv = kv.strip()
+ k, v = kv.split("=")
+ d[k] = v
+
+ return d
+
+
+def _tag_to_str(text):
+ text = text.strip()
+
+ if text == "[]":
+ return None
+ else:
+ return text
+
+
+def map_obj_to_commands(want, have, module):
+ commands = list()
+
+ if module.params["state"] == "absent":
+ if have:
+ templatized_command = "%(ovs-vsctl)s -t %(timeout)s del-port %(bridge)s %(port)s"
+ command = templatized_command % module.params
+ commands.append(command)
+ else:
+ if have:
+ if want["tag"] != have["tag"]:
+ templatized_command = "%(ovs-vsctl)s -t %(timeout)s set port %(port)s tag=%(tag)s"
+ command = templatized_command % module.params
+ commands.append(command)
+
+ if want["external_ids"] != have["external_ids"]:
+ for k, v in iteritems(want["external_ids"]):
+ if (
+ not have["external_ids"]
+ or k not in have["external_ids"]
+ or want["external_ids"][k] != have["external_ids"][k]
+ ):
+ if v is None:
+ templatized_command = (
+ "%(ovs-vsctl)s -t %(timeout)s"
+ " remove port %(port)s"
+ " external_ids " + k
+ )
+ command = templatized_command % module.params
+ commands.append(command)
+ else:
+ templatized_command = (
+ "%(ovs-vsctl)s -t %(timeout)s set port %(port)s external_ids:"
+ )
+ command = templatized_command % module.params
+ command += k + "=" + v
+ commands.append(command)
+ else:
+ templatized_command = "%(ovs-vsctl)s -t %(timeout)s add-port %(bridge)s %(port)s"
+ command = templatized_command % module.params
+
+ if want["tag"]:
+ templatized_command = " tag=%(tag)s"
+ command += templatized_command % module.params
+
+ if want["set"]:
+ set_command = ""
+ for x in want["set"]:
+ set_command += " -- set {0}".format(x)
+ command += set_command
+
+ commands.append(command)
+
+ if want["external_ids"]:
+ for k, v in iteritems(want["external_ids"]):
+ templatized_command = (
+ "%(ovs-vsctl)s -t %(timeout)s set port %(port)s external_ids:"
+ )
+ command = templatized_command % module.params
+ command += k + "=" + v
+ commands.append(command)
+
+ return commands
+
+
+def map_config_to_obj(module):
+ templatized_command = "%(ovs-vsctl)s -t %(timeout)s list-ports %(bridge)s"
+ command = templatized_command % module.params
+ rc, out, err = module.run_command(command, check_rc=True)
+ if rc != 0:
+ module.fail_json(msg=err)
+
+ obj = {}
+
+ if module.params["port"] in out.splitlines():
+ obj["bridge"] = module.params["bridge"]
+ obj["port"] = module.params["port"]
+
+ templatized_command = "%(ovs-vsctl)s -t %(timeout)s get Port %(port)s tag"
+ command = templatized_command % module.params
+ rc, out, err = module.run_command(command, check_rc=True)
+ obj["tag"] = _tag_to_str(out)
+
+ templatized_command = "%(ovs-vsctl)s -t %(timeout)s get Port %(port)s external_ids"
+ command = templatized_command % module.params
+ rc, out, err = module.run_command(command, check_rc=True)
+ obj["external_ids"] = _external_ids_to_dict(out)
+
+ return obj
+
+
+def map_params_to_obj(module):
+ obj = {
+ "bridge": module.params["bridge"],
+ "port": module.params["port"],
+ "tag": module.params["tag"],
+ "external_ids": module.params["external_ids"],
+ "set": module.params["set"],
+ }
+
+ return obj
+
+
+def main():
+ """Entry point."""
+ argument_spec = {
+ "bridge": {"required": True},
+ "port": {"required": True},
+ "state": {"default": "present", "choices": ["present", "absent"]},
+ "timeout": {"default": 5, "type": "int"},
+ "external_ids": {"default": {}, "type": "dict"},
+ "tag": {"default": None},
+ "database_socket": {"default": None},
+ "set": {"required": False, "type": "list", "elements": "str"},
+ }
+
+ module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=True)
+
+ result = {"changed": False}
+
+ # We add ovs-vsctl to module_params to later build up templatized commands
+ module.params["ovs-vsctl"] = module.get_bin_path("ovs-vsctl", True)
+ if module.params.get("database_socket"):
+ module.params["ovs-vsctl"] += " --db=" + module.params.get("database_socket")
+
+ want = map_params_to_obj(module)
+ have = map_config_to_obj(module)
+
+ commands = map_obj_to_commands(want, have, module)
+ result["commands"] = commands
+
+ if commands:
+ if not module.check_mode:
+ for c in commands:
+ module.run_command(c, check_rc=True)
+ result["changed"] = True
+
+ module.exit_json(**result)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/ansible_collections/openvswitch/openvswitch/pyproject.toml b/ansible_collections/openvswitch/openvswitch/pyproject.toml
new file mode 100644
index 000000000..fa4225f3e
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/pyproject.toml
@@ -0,0 +1,7 @@
+[tool.black]
+line-length = 100
+
+[tool.pytest.ini_options]
+addopts = ["-vvv", "-n", "2", "--log-level", "WARNING", "--color", "yes"]
+testpaths = ["tests"]
+filterwarnings = ['ignore:AnsibleCollectionFinder has already been configured']
diff --git a/ansible_collections/openvswitch/openvswitch/requirements.txt b/ansible_collections/openvswitch/openvswitch/requirements.txt
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/requirements.txt
diff --git a/ansible_collections/openvswitch/openvswitch/test-requirements.txt b/ansible_collections/openvswitch/openvswitch/test-requirements.txt
new file mode 100644
index 000000000..2a8e6fb7e
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/test-requirements.txt
@@ -0,0 +1,7 @@
+black==22.3.0 ; python_version > '3.5'
+coverage==4.5.4
+flake8
+git+https://github.com/ansible-community/pytest-ansible-units.git
+mock ; python_version < '3.5'
+pytest-xdist
+yamllint
diff --git a/ansible_collections/openvswitch/openvswitch/tests/.gitignore b/ansible_collections/openvswitch/openvswitch/tests/.gitignore
new file mode 100644
index 000000000..ea1472ec1
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/tests/.gitignore
@@ -0,0 +1 @@
+output/
diff --git a/ansible_collections/openvswitch/openvswitch/tests/integration/network-integration.cfg b/ansible_collections/openvswitch/openvswitch/tests/integration/network-integration.cfg
new file mode 100644
index 000000000..d12c1efe2
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/tests/integration/network-integration.cfg
@@ -0,0 +1,4 @@
+[persistent_connection]
+command_timeout = 100
+connect_timeout = 100
+connect_retry_timeout = 100
diff --git a/ansible_collections/openvswitch/openvswitch/tests/integration/target-prefixes.network b/ansible_collections/openvswitch/openvswitch/tests/integration/target-prefixes.network
new file mode 100644
index 000000000..64796f72c
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/tests/integration/target-prefixes.network
@@ -0,0 +1 @@
+openvswitch
diff --git a/ansible_collections/openvswitch/openvswitch/tests/integration/targets/openvswitch_bridge/aliases b/ansible_collections/openvswitch/openvswitch/tests/integration/targets/openvswitch_bridge/aliases
new file mode 100644
index 000000000..a51f9c505
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/tests/integration/targets/openvswitch_bridge/aliases
@@ -0,0 +1 @@
+non_local
diff --git a/ansible_collections/openvswitch/openvswitch/tests/integration/targets/openvswitch_bridge/defaults/main.yaml b/ansible_collections/openvswitch/openvswitch/tests/integration/targets/openvswitch_bridge/defaults/main.yaml
new file mode 100644
index 000000000..9ef5ba516
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/tests/integration/targets/openvswitch_bridge/defaults/main.yaml
@@ -0,0 +1,3 @@
+---
+testcase: "*"
+test_items: []
diff --git a/ansible_collections/openvswitch/openvswitch/tests/integration/targets/openvswitch_bridge/meta/main.yaml b/ansible_collections/openvswitch/openvswitch/tests/integration/targets/openvswitch_bridge/meta/main.yaml
new file mode 100644
index 000000000..846a02ba2
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/tests/integration/targets/openvswitch_bridge/meta/main.yaml
@@ -0,0 +1,3 @@
+---
+dependencies:
+ - prepare_ovs_tests
diff --git a/ansible_collections/openvswitch/openvswitch/tests/integration/targets/openvswitch_bridge/tasks/main.yml b/ansible_collections/openvswitch/openvswitch/tests/integration/targets/openvswitch_bridge/tasks/main.yml
new file mode 100644
index 000000000..3eaedab1e
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/tests/integration/targets/openvswitch_bridge/tasks/main.yml
@@ -0,0 +1,16 @@
+---
+- name: collect all test cases
+ find:
+ paths: "{{ role_path }}/tests"
+ patterns: "{{ testcase }}.yaml"
+ delegate_to: localhost
+ register: test_cases
+
+- name: set test_items
+ set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}"
+
+- name: run test case
+ include: "{{ test_case_to_run }}"
+ with_items: "{{ test_items }}"
+ loop_control:
+ loop_var: test_case_to_run
diff --git a/ansible_collections/openvswitch/openvswitch/tests/integration/targets/openvswitch_bridge/tests/basic.yaml b/ansible_collections/openvswitch/openvswitch/tests/integration/targets/openvswitch_bridge/tests/basic.yaml
new file mode 100644
index 000000000..6ea2a2f3e
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/tests/integration/targets/openvswitch_bridge/tests/basic.yaml
@@ -0,0 +1,65 @@
+---
+- name: Make sure test bridge does not exist before tests
+ command: ovs-vsctl del-br br-test
+ become: true
+ ignore_errors: true
+
+- name: Create bridge
+ register: result
+ become: true
+ openvswitch.openvswitch.openvswitch_bridge:
+ bridge: br-test
+
+- assert:
+ that:
+ - result is changed
+
+- name: Create bridge again (idempotent)
+ register: result
+ become: true
+ openvswitch.openvswitch.openvswitch_bridge:
+ bridge: br-test
+
+- assert:
+ that:
+ - result is not changed
+
+- name: Add fake bridge
+ register: result
+ become: true
+ openvswitch.openvswitch.openvswitch_bridge:
+ bridge: fake-br-test
+ parent: br-test
+ vlan: 100
+
+- assert:
+ that:
+ - result is changed
+
+- name: Change fake bridge vlan
+ register: result
+ become: true
+ openvswitch.openvswitch.openvswitch_bridge:
+ bridge: fake-br-test
+ parent: br-test
+ vlan: 300
+
+- assert:
+ that:
+ - result is changed
+
+- name: Change fake bridge vlan again (idempotent)
+ register: result
+ become: true
+ openvswitch.openvswitch.openvswitch_bridge:
+ bridge: fake-br-test
+ parent: br-test
+ vlan: 300
+
+- assert:
+ that:
+ - result is not changed
+
+- name: Tear down test bridges
+ become: true
+ command: ovs-vsctl del-br br-test
diff --git a/ansible_collections/openvswitch/openvswitch/tests/integration/targets/openvswitch_db/aliases b/ansible_collections/openvswitch/openvswitch/tests/integration/targets/openvswitch_db/aliases
new file mode 100644
index 000000000..a51f9c505
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/tests/integration/targets/openvswitch_db/aliases
@@ -0,0 +1 @@
+non_local
diff --git a/ansible_collections/openvswitch/openvswitch/tests/integration/targets/openvswitch_db/defaults/main.yaml b/ansible_collections/openvswitch/openvswitch/tests/integration/targets/openvswitch_db/defaults/main.yaml
new file mode 100644
index 000000000..9ef5ba516
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/tests/integration/targets/openvswitch_db/defaults/main.yaml
@@ -0,0 +1,3 @@
+---
+testcase: "*"
+test_items: []
diff --git a/ansible_collections/openvswitch/openvswitch/tests/integration/targets/openvswitch_db/meta/main.yaml b/ansible_collections/openvswitch/openvswitch/tests/integration/targets/openvswitch_db/meta/main.yaml
new file mode 100644
index 000000000..846a02ba2
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/tests/integration/targets/openvswitch_db/meta/main.yaml
@@ -0,0 +1,3 @@
+---
+dependencies:
+ - prepare_ovs_tests
diff --git a/ansible_collections/openvswitch/openvswitch/tests/integration/targets/openvswitch_db/tasks/main.yml b/ansible_collections/openvswitch/openvswitch/tests/integration/targets/openvswitch_db/tasks/main.yml
new file mode 100644
index 000000000..3eaedab1e
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/tests/integration/targets/openvswitch_db/tasks/main.yml
@@ -0,0 +1,16 @@
+---
+- name: collect all test cases
+ find:
+ paths: "{{ role_path }}/tests"
+ patterns: "{{ testcase }}.yaml"
+ delegate_to: localhost
+ register: test_cases
+
+- name: set test_items
+ set_fact: test_items="{{ test_cases.files | map(attribute='path') | list }}"
+
+- name: run test case
+ include: "{{ test_case_to_run }}"
+ with_items: "{{ test_items }}"
+ loop_control:
+ loop_var: test_case_to_run
diff --git a/ansible_collections/openvswitch/openvswitch/tests/integration/targets/openvswitch_db/tests/basic.yaml b/ansible_collections/openvswitch/openvswitch/tests/integration/targets/openvswitch_db/tests/basic.yaml
new file mode 100644
index 000000000..b20413565
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/tests/integration/targets/openvswitch_db/tests/basic.yaml
@@ -0,0 +1,182 @@
+---
+- name: Make sure test bridge does not exist before tests
+ command: ovs-vsctl del-br br-test
+ become: true
+ ignore_errors: true
+
+- name: Create test bridge
+ command: ovs-vsctl add-br br-test
+ become: true
+
+- name: Create bridge
+ become: true
+ register: result
+ openvswitch.openvswitch.openvswitch_db:
+ table: Bridge
+ record: br-test
+ col: other_config
+ key: disable-in-band
+ value: true
+
+- assert:
+ that:
+ - result is changed
+
+- name: Create bridge again (idempotent)
+ become: true
+ register: result
+ openvswitch.openvswitch.openvswitch_db:
+ table: Bridge
+ record: br-test
+ col: other_config
+ key: disable-in-band
+ value: true
+
+- assert:
+ that:
+ - result is not changed
+
+- name: Change key value with quotes
+ become: true
+ register: result
+ openvswitch.openvswitch.openvswitch_db:
+ table: open_vswitch
+ record: .
+ col: other_config
+ key: pmd-cpu-mask
+ value: "0xaaa00000000"
+
+- assert:
+ that:
+ - result is changed
+
+- name: Change keyvalue with quotes(idempotent)
+ become: true
+ register: result
+ openvswitch.openvswitch.openvswitch_db:
+ table: open_vswitch
+ record: .
+ col: other_config
+ key: pmd-cpu-mask
+ value: "0xaaa00000000"
+
+- assert:
+ that:
+ - result is not changed
+
+- name: Remove key value with quotes
+ become: true
+ register: result
+ openvswitch.openvswitch.openvswitch_db:
+ table: open_vswitch
+ record: .
+ col: other_config
+ key: pmd-cpu-mask
+ value: "0xaaa00000000"
+ state: absent
+
+- assert:
+ that:
+ - result is changed
+
+- name: Change column value in a map
+ become: true
+ register: result
+ openvswitch.openvswitch.openvswitch_db:
+ table: Bridge
+ record: br-test
+ col: other_config
+ key: disable-in-band
+ value: false
+
+- assert:
+ that:
+ - result is changed
+
+- name: Change column value in a map again (idempotent)
+ become: true
+ register: result
+ openvswitch.openvswitch.openvswitch_db:
+ table: Bridge
+ record: br-test
+ col: other_config
+ key: disable-in-band
+ value: false
+
+- assert:
+ that:
+ - result is not changed
+
+- name: Change column value
+ become: true
+ register: result
+ openvswitch.openvswitch.openvswitch_db:
+ table: Bridge
+ record: br-test
+ col: stp_enable
+ value: true
+
+- assert:
+ that:
+ - result is changed
+
+- name: Change column value again (idempotent)
+ become: true
+ register: result
+ openvswitch.openvswitch.openvswitch_db:
+ table: Bridge
+ record: br-test
+ col: stp_enable
+ value: true
+
+- assert:
+ that:
+ - result is not changed
+
+- name: Try to set value on a map type without a key (negative)
+ ignore_errors: true
+ become: true
+ register: result
+ openvswitch.openvswitch.openvswitch_db:
+ table: Bridge
+ record: br-test
+ col: other_config
+ value: true
+
+- assert:
+ that:
+ - result is failed
+
+- name: Remove bridge
+ become: true
+ register: result
+ openvswitch.openvswitch.openvswitch_db:
+ table: Bridge
+ record: br-test
+ col: other_config
+ key: disable-in-band
+ value: false
+ state: absent
+
+- assert:
+ that:
+ - result is changed
+
+- name: Remove bridge again (idempotent)
+ become: true
+ register: result
+ openvswitch.openvswitch.openvswitch_db:
+ table: Bridge
+ record: br-test
+ col: other_config
+ key: disable-in-band
+ value: false
+ state: absent
+
+- assert:
+ that:
+ - result is not changed
+
+- name: Tear down test bridge
+ command: ovs-vsctl del-br br-test
+ become: true
diff --git a/ansible_collections/openvswitch/openvswitch/tests/integration/targets/prepare_ovs_tests/tasks/main.yml b/ansible_collections/openvswitch/openvswitch/tests/integration/targets/prepare_ovs_tests/tasks/main.yml
new file mode 100644
index 000000000..924dbd3a4
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/tests/integration/targets/prepare_ovs_tests/tasks/main.yml
@@ -0,0 +1,37 @@
+---
+# No easy way to know OS type without python or without ansible facts.
+# Run below raw commands and one would succeed with apt/yum on debian/centos
+- block:
+ - name: Install python
+ raw: test -e /usr/bin/python || (apt-get -y update && apt-get install -y python-minimal)
+ become: yes
+ ignore_errors: yes
+
+ - name: Install python
+ raw: test -e /usr/bin/python || (yum -y update && yum install -y python)
+ become: yes
+ ignore_errors: yes
+
+ # network-integration test are ran with gather_facts: no
+ # We need to explicitly call setup so ansible_distribution is set
+
+ - name: Gather facts
+ setup:
+ become: yes
+
+ - name: Install openvswitch-switch package if we are on Ubuntu
+ apt:
+ name: openvswitch-switch
+ state: present
+ update_cache: yes
+ become: yes
+ when: ansible_distribution == 'Ubuntu'
+
+ - name: Install openvswitch package if we are on Fedora
+ yum:
+ name: openvswitch
+ state: installed
+ update_cache: yes
+ become: yes
+ when: ansible_distribution == 'Fedora'
+ when: prepare_ovs_tests_task | default(False) | bool
diff --git a/ansible_collections/openvswitch/openvswitch/tests/sanity/ignore-2.10.txt b/ansible_collections/openvswitch/openvswitch/tests/sanity/ignore-2.10.txt
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/tests/sanity/ignore-2.10.txt
diff --git a/ansible_collections/openvswitch/openvswitch/tests/sanity/ignore-2.9.txt b/ansible_collections/openvswitch/openvswitch/tests/sanity/ignore-2.9.txt
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/tests/sanity/ignore-2.9.txt
diff --git a/ansible_collections/openvswitch/openvswitch/tests/unit/__init__.py b/ansible_collections/openvswitch/openvswitch/tests/unit/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/tests/unit/__init__.py
diff --git a/ansible_collections/openvswitch/openvswitch/tests/unit/compat/__init__.py b/ansible_collections/openvswitch/openvswitch/tests/unit/compat/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/tests/unit/compat/__init__.py
diff --git a/ansible_collections/openvswitch/openvswitch/tests/unit/compat/mock.py b/ansible_collections/openvswitch/openvswitch/tests/unit/compat/mock.py
new file mode 100644
index 000000000..54c1d20e7
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/tests/unit/compat/mock.py
@@ -0,0 +1,125 @@
+# (c) 2014, Toshio Kuratomi <tkuratomi@ansible.com>
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+"""
+Compat module for Python3.x's unittest.mock module
+"""
+import sys
+
+# Python 2.7
+
+# Note: Could use the pypi mock library on python3.x as well as python2.x. It
+# is the same as the python3 stdlib mock library
+
+try:
+ # Allow wildcard import because we really do want to import all of mock's
+ # symbols into this compat shim
+ # pylint: disable=wildcard-import,unused-wildcard-import
+ from unittest.mock import *
+except ImportError:
+ # Python 2
+ # pylint: disable=wildcard-import,unused-wildcard-import
+ try:
+ from mock import *
+ except ImportError:
+ print("You need the mock library installed on python2.x to run tests")
+
+
+# Prior to 3.4.4, mock_open cannot handle binary read_data
+if sys.version_info >= (3,) and sys.version_info < (3, 4, 4):
+ file_spec = None
+
+ def _iterate_read_data(read_data):
+ # Helper for mock_open:
+ # Retrieve lines from read_data via a generator so that separate calls to
+ # readline, read, and readlines are properly interleaved
+ sep = b"\n" if isinstance(read_data, bytes) else "\n"
+ data_as_list = [l + sep for l in read_data.split(sep)]
+
+ if data_as_list[-1] == sep:
+ # If the last line ended in a newline, the list comprehension will have an
+ # extra entry that's just a newline. Remove this.
+ data_as_list = data_as_list[:-1]
+ else:
+ # If there wasn't an extra newline by itself, then the file being
+ # emulated doesn't have a newline to end the last line remove the
+ # newline that our naive format() added
+ data_as_list[-1] = data_as_list[-1][:-1]
+
+ for line in data_as_list:
+ yield line
+
+ def mock_open(mock=None, read_data=""):
+ """
+ A helper function to create a mock to replace the use of `open`. It works
+ for `open` called directly or used as a context manager.
+
+ The `mock` argument is the mock object to configure. If `None` (the
+ default) then a `MagicMock` will be created for you, with the API limited
+ to methods or attributes available on standard file handles.
+
+ `read_data` is a string for the `read` methoddline`, and `readlines` of the
+ file handle to return. This is an empty string by default.
+ """
+
+ def _readlines_side_effect(*args, **kwargs):
+ if handle.readlines.return_value is not None:
+ return handle.readlines.return_value
+ return list(_data)
+
+ def _read_side_effect(*args, **kwargs):
+ if handle.read.return_value is not None:
+ return handle.read.return_value
+ return type(read_data)().join(_data)
+
+ def _readline_side_effect():
+ if handle.readline.return_value is not None:
+ while True:
+ yield handle.readline.return_value
+ for line in _data:
+ yield line
+
+ global file_spec
+ if file_spec is None:
+ import _io
+
+ file_spec = list(set(dir(_io.TextIOWrapper)).union(set(dir(_io.BytesIO))))
+
+ if mock is None:
+ mock = MagicMock(name="open", spec=open)
+
+ handle = MagicMock(spec=file_spec)
+ handle.__enter__.return_value = handle
+
+ _data = _iterate_read_data(read_data)
+
+ handle.write.return_value = None
+ handle.read.return_value = None
+ handle.readline.return_value = None
+ handle.readlines.return_value = None
+
+ handle.read.side_effect = _read_side_effect
+ handle.readline.side_effect = _readline_side_effect()
+ handle.readlines.side_effect = _readlines_side_effect
+
+ mock.return_value = handle
+ return mock
diff --git a/ansible_collections/openvswitch/openvswitch/tests/unit/compat/unittest.py b/ansible_collections/openvswitch/openvswitch/tests/unit/compat/unittest.py
new file mode 100644
index 000000000..df3379b82
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/tests/unit/compat/unittest.py
@@ -0,0 +1,39 @@
+# (c) 2014, Toshio Kuratomi <tkuratomi@ansible.com>
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+"""
+Compat module for Python2.7's unittest module
+"""
+
+import sys
+
+# Allow wildcard import because we really do want to import all of
+# unittests's symbols into this compat shim
+# pylint: disable=wildcard-import,unused-wildcard-import
+if sys.version_info < (2, 7):
+ try:
+ # Need unittest2 on python2.6
+ from unittest2 import *
+ except ImportError:
+ print("You need unittest2 installed on python2.6.x to run tests")
+else:
+ from unittest import *
diff --git a/ansible_collections/openvswitch/openvswitch/tests/unit/mock/__init__.py b/ansible_collections/openvswitch/openvswitch/tests/unit/mock/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/tests/unit/mock/__init__.py
diff --git a/ansible_collections/openvswitch/openvswitch/tests/unit/mock/loader.py b/ansible_collections/openvswitch/openvswitch/tests/unit/mock/loader.py
new file mode 100644
index 000000000..c141e66e5
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/tests/unit/mock/loader.py
@@ -0,0 +1,116 @@
+# (c) 2012-2014, Michael DeHaan <michael.dehaan@gmail.com>
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+import os
+
+from ansible.errors import AnsibleParserError
+from ansible.module_utils._text import to_bytes, to_text
+from ansible.parsing.dataloader import DataLoader
+
+
+class DictDataLoader(DataLoader):
+ def __init__(self, file_mapping=None):
+ file_mapping = {} if file_mapping is None else file_mapping
+ assert type(file_mapping) == dict
+
+ super(DictDataLoader, self).__init__()
+
+ self._file_mapping = file_mapping
+ self._build_known_directories()
+ self._vault_secrets = None
+
+ def load_from_file(self, path, cache=True, unsafe=False):
+ path = to_text(path)
+ if path in self._file_mapping:
+ return self.load(self._file_mapping[path], path)
+ return None
+
+ # TODO: the real _get_file_contents returns a bytestring, so we actually convert the
+ # unicode/text it's created with to utf-8
+ def _get_file_contents(self, file_name):
+ file_name = to_text(file_name)
+ if file_name in self._file_mapping:
+ return (to_bytes(self._file_mapping[file_name]), False)
+ else:
+ raise AnsibleParserError("file not found: %s" % file_name)
+
+ def path_exists(self, path):
+ path = to_text(path)
+ return path in self._file_mapping or path in self._known_directories
+
+ def is_file(self, path):
+ path = to_text(path)
+ return path in self._file_mapping
+
+ def is_directory(self, path):
+ path = to_text(path)
+ return path in self._known_directories
+
+ def list_directory(self, path):
+ ret = []
+ path = to_text(path)
+ for x in list(self._file_mapping.keys()) + self._known_directories:
+ if x.startswith(path):
+ if os.path.dirname(x) == path:
+ ret.append(os.path.basename(x))
+ return ret
+
+ def is_executable(self, path):
+ # FIXME: figure out a way to make paths return true for this
+ return False
+
+ def _add_known_directory(self, directory):
+ if directory not in self._known_directories:
+ self._known_directories.append(directory)
+
+ def _build_known_directories(self):
+ self._known_directories = []
+ for path in self._file_mapping:
+ dirname = os.path.dirname(path)
+ while dirname not in ("/", ""):
+ self._add_known_directory(dirname)
+ dirname = os.path.dirname(dirname)
+
+ def push(self, path, content):
+ rebuild_dirs = False
+ if path not in self._file_mapping:
+ rebuild_dirs = True
+
+ self._file_mapping[path] = content
+
+ if rebuild_dirs:
+ self._build_known_directories()
+
+ def pop(self, path):
+ if path in self._file_mapping:
+ del self._file_mapping[path]
+ self._build_known_directories()
+
+ def clear(self):
+ self._file_mapping = dict()
+ self._known_directories = []
+
+ def get_basedir(self):
+ return os.getcwd()
+
+ def set_vault_secrets(self, vault_secrets):
+ self._vault_secrets = vault_secrets
diff --git a/ansible_collections/openvswitch/openvswitch/tests/unit/mock/path.py b/ansible_collections/openvswitch/openvswitch/tests/unit/mock/path.py
new file mode 100644
index 000000000..2bc9ddea0
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/tests/unit/mock/path.py
@@ -0,0 +1,9 @@
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+from ansible.utils.path import unfrackpath
+
+from ansible_collections.openvswitch.openvswitch.tests.unit.compat.mock import MagicMock
+
+mock_unfrackpath_noop = MagicMock(spec_set=unfrackpath, side_effect=lambda x, *args, **kwargs: x)
diff --git a/ansible_collections/openvswitch/openvswitch/tests/unit/mock/procenv.py b/ansible_collections/openvswitch/openvswitch/tests/unit/mock/procenv.py
new file mode 100644
index 000000000..f3f0e3935
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/tests/unit/mock/procenv.py
@@ -0,0 +1,95 @@
+# (c) 2016, Matt Davis <mdavis@ansible.com>
+# (c) 2016, Toshio Kuratomi <tkuratomi@ansible.com>
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+import json
+import sys
+from contextlib import contextmanager
+from io import BytesIO, StringIO
+
+from ansible.module_utils._text import to_bytes
+from ansible.module_utils.six import PY3
+
+from ansible_collections.openvswitch.openvswitch.tests.unit.compat import unittest
+
+
+@contextmanager
+def swap_stdin_and_argv(stdin_data="", argv_data=tuple()):
+ """
+ context manager that temporarily masks the test runner's values for stdin and argv
+ """
+ real_stdin = sys.stdin
+ real_argv = sys.argv
+
+ if PY3:
+ fake_stream = StringIO(stdin_data)
+ fake_stream.buffer = BytesIO(to_bytes(stdin_data))
+ else:
+ fake_stream = BytesIO(to_bytes(stdin_data))
+
+ try:
+ sys.stdin = fake_stream
+ sys.argv = argv_data
+
+ yield
+ finally:
+ sys.stdin = real_stdin
+ sys.argv = real_argv
+
+
+@contextmanager
+def swap_stdout():
+ """
+ context manager that temporarily replaces stdout for tests that need to verify output
+ """
+ old_stdout = sys.stdout
+
+ if PY3:
+ fake_stream = StringIO()
+ else:
+ fake_stream = BytesIO()
+
+ try:
+ sys.stdout = fake_stream
+
+ yield fake_stream
+ finally:
+ sys.stdout = old_stdout
+
+
+class ModuleTestCase(unittest.TestCase):
+ def setUp(self, module_args=None):
+ if module_args is None:
+ module_args = {
+ "_ansible_remote_tmp": "/tmp",
+ "_ansible_keep_remote_files": False,
+ }
+
+ args = json.dumps(dict(ANSIBLE_MODULE_ARGS=module_args))
+
+ # unittest doesn't have a clean place to use a context manager, so we have to enter/exit manually
+ self.stdin_swap = swap_stdin_and_argv(stdin_data=args)
+ self.stdin_swap.__enter__()
+
+ def tearDown(self):
+ # unittest doesn't have a clean place to use a context manager, so we have to enter/exit manually
+ self.stdin_swap.__exit__(None, None, None)
diff --git a/ansible_collections/openvswitch/openvswitch/tests/unit/mock/vault_helper.py b/ansible_collections/openvswitch/openvswitch/tests/unit/mock/vault_helper.py
new file mode 100644
index 000000000..4c6c890c1
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/tests/unit/mock/vault_helper.py
@@ -0,0 +1,39 @@
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+from ansible.module_utils._text import to_bytes
+from ansible.parsing.vault import VaultSecret
+
+
+class TextVaultSecret(VaultSecret):
+ """A secret piece of text. ie, a password. Tracks text encoding.
+
+ The text encoding of the text may not be the default text encoding so
+ we keep track of the encoding so we encode it to the same bytes."""
+
+ def __init__(self, text, encoding=None, errors=None, _bytes=None):
+ super(TextVaultSecret, self).__init__()
+ self.text = text
+ self.encoding = encoding or "utf-8"
+ self._bytes = _bytes
+ self.errors = errors or "strict"
+
+ @property
+ def bytes(self):
+ """The text encoded with encoding, unless we specifically set _bytes."""
+ return self._bytes or to_bytes(self.text, encoding=self.encoding, errors=self.errors)
diff --git a/ansible_collections/openvswitch/openvswitch/tests/unit/mock/yaml_helper.py b/ansible_collections/openvswitch/openvswitch/tests/unit/mock/yaml_helper.py
new file mode 100644
index 000000000..c5b29fcaf
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/tests/unit/mock/yaml_helper.py
@@ -0,0 +1,152 @@
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+import io
+
+import yaml
+from ansible.module_utils.six import PY3
+from ansible.parsing.yaml.dumper import AnsibleDumper
+from ansible.parsing.yaml.loader import AnsibleLoader
+
+
+class YamlTestUtils(object):
+ """Mixin class to combine with a unittest.TestCase subclass."""
+
+ def _loader(self, stream):
+ """Vault related tests will want to override this.
+
+ Vault cases should setup a AnsibleLoader that has the vault password."""
+ return AnsibleLoader(stream)
+
+ def _dump_stream(self, obj, stream, dumper=None):
+ """Dump to a py2-unicode or py3-string stream."""
+ if PY3:
+ return yaml.dump(obj, stream, Dumper=dumper)
+ else:
+ return yaml.dump(obj, stream, Dumper=dumper, encoding=None)
+
+ def _dump_string(self, obj, dumper=None):
+ """Dump to a py2-unicode or py3-string"""
+ if PY3:
+ return yaml.dump(obj, Dumper=dumper)
+ else:
+ return yaml.dump(obj, Dumper=dumper, encoding=None)
+
+ def _dump_load_cycle(self, obj):
+ # Each pass though a dump or load revs the 'generation'
+ # obj to yaml string
+ string_from_object_dump = self._dump_string(obj, dumper=AnsibleDumper)
+
+ # wrap a stream/file like StringIO around that yaml
+ stream_from_object_dump = io.StringIO(string_from_object_dump)
+ loader = self._loader(stream_from_object_dump)
+ # load the yaml stream to create a new instance of the object (gen 2)
+ obj_2 = loader.get_data()
+
+ # dump the gen 2 objects directory to strings
+ string_from_object_dump_2 = self._dump_string(obj_2, dumper=AnsibleDumper)
+
+ # The gen 1 and gen 2 yaml strings
+ self.assertEqual(string_from_object_dump, string_from_object_dump_2)
+ # the gen 1 (orig) and gen 2 py object
+ self.assertEqual(obj, obj_2)
+
+ # again! gen 3... load strings into py objects
+ stream_3 = io.StringIO(string_from_object_dump_2)
+ loader_3 = self._loader(stream_3)
+ obj_3 = loader_3.get_data()
+
+ string_from_object_dump_3 = self._dump_string(obj_3, dumper=AnsibleDumper)
+
+ self.assertEqual(obj, obj_3)
+ # should be transitive, but...
+ self.assertEqual(obj_2, obj_3)
+ self.assertEqual(string_from_object_dump, string_from_object_dump_3)
+
+ def _old_dump_load_cycle(self, obj):
+ """Dump the passed in object to yaml, load it back up, dump again, compare."""
+ stream = io.StringIO()
+
+ yaml_string = self._dump_string(obj, dumper=AnsibleDumper)
+ self._dump_stream(obj, stream, dumper=AnsibleDumper)
+
+ yaml_string_from_stream = stream.getvalue()
+
+ # reset stream
+ stream.seek(0)
+
+ loader = self._loader(stream)
+ # loader = AnsibleLoader(stream, vault_password=self.vault_password)
+ obj_from_stream = loader.get_data()
+
+ stream_from_string = io.StringIO(yaml_string)
+ loader2 = self._loader(stream_from_string)
+ # loader2 = AnsibleLoader(stream_from_string, vault_password=self.vault_password)
+ obj_from_string = loader2.get_data()
+
+ stream_obj_from_stream = io.StringIO()
+ stream_obj_from_string = io.StringIO()
+
+ if PY3:
+ yaml.dump(obj_from_stream, stream_obj_from_stream, Dumper=AnsibleDumper)
+ yaml.dump(obj_from_stream, stream_obj_from_string, Dumper=AnsibleDumper)
+ else:
+ yaml.dump(
+ obj_from_stream,
+ stream_obj_from_stream,
+ Dumper=AnsibleDumper,
+ encoding=None,
+ )
+ yaml.dump(
+ obj_from_stream,
+ stream_obj_from_string,
+ Dumper=AnsibleDumper,
+ encoding=None,
+ )
+
+ yaml_string_stream_obj_from_stream = stream_obj_from_stream.getvalue()
+ yaml_string_stream_obj_from_string = stream_obj_from_string.getvalue()
+
+ stream_obj_from_stream.seek(0)
+ stream_obj_from_string.seek(0)
+
+ if PY3:
+ yaml_string_obj_from_stream = yaml.dump(obj_from_stream, Dumper=AnsibleDumper)
+ yaml_string_obj_from_string = yaml.dump(obj_from_string, Dumper=AnsibleDumper)
+ else:
+ yaml_string_obj_from_stream = yaml.dump(
+ obj_from_stream, Dumper=AnsibleDumper, encoding=None
+ )
+ yaml_string_obj_from_string = yaml.dump(
+ obj_from_string, Dumper=AnsibleDumper, encoding=None
+ )
+
+ assert yaml_string == yaml_string_obj_from_stream
+ assert yaml_string == yaml_string_obj_from_stream == yaml_string_obj_from_string
+ assert (
+ yaml_string
+ == yaml_string_obj_from_stream
+ == yaml_string_obj_from_string
+ == yaml_string_stream_obj_from_stream
+ == yaml_string_stream_obj_from_string
+ )
+ assert obj == obj_from_stream
+ assert obj == obj_from_string
+ assert obj == yaml_string_obj_from_stream
+ assert obj == yaml_string_obj_from_string
+ assert (
+ obj
+ == obj_from_stream
+ == obj_from_string
+ == yaml_string_obj_from_stream
+ == yaml_string_obj_from_string
+ )
+ return {
+ "obj": obj,
+ "yaml_string": yaml_string,
+ "yaml_string_from_stream": yaml_string_from_stream,
+ "obj_from_stream": obj_from_stream,
+ "obj_from_string": obj_from_string,
+ "yaml_string_obj_from_string": yaml_string_obj_from_string,
+ }
diff --git a/ansible_collections/openvswitch/openvswitch/tests/unit/modules/__init__.py b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/__init__.py
diff --git a/ansible_collections/openvswitch/openvswitch/tests/unit/modules/conftest.py b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/conftest.py
new file mode 100644
index 000000000..01a0adc3f
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/conftest.py
@@ -0,0 +1,31 @@
+# Copyright (c) 2017 Ansible Project
+# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+import json
+
+import pytest
+from ansible.module_utils._text import to_bytes
+from ansible.module_utils.common._collections_compat import MutableMapping
+from ansible.module_utils.six import string_types
+
+
+@pytest.fixture
+def patch_ansible_module(request, mocker):
+ if isinstance(request.param, string_types):
+ args = request.param
+ elif isinstance(request.param, MutableMapping):
+ if "ANSIBLE_MODULE_ARGS" not in request.param:
+ request.param = {"ANSIBLE_MODULE_ARGS": request.param}
+ if "_ansible_remote_tmp" not in request.param["ANSIBLE_MODULE_ARGS"]:
+ request.param["ANSIBLE_MODULE_ARGS"]["_ansible_remote_tmp"] = "/tmp"
+ if "_ansible_keep_remote_files" not in request.param["ANSIBLE_MODULE_ARGS"]:
+ request.param["ANSIBLE_MODULE_ARGS"]["_ansible_keep_remote_files"] = False
+ args = json.dumps(request.param)
+ else:
+ raise Exception("Malformed data to the patch_ansible_module pytest fixture")
+
+ mocker.patch("ansible.module_utils.basic._ANSIBLE_ARGS", to_bytes(args))
diff --git a/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/__init__.py b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/__init__.py
diff --git a/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/__init__.py b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/__init__.py
diff --git a/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/__init__.py b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/__init__.py
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/__init__.py
diff --git a/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/br_get_external_id_foo_bar.cfg b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/br_get_external_id_foo_bar.cfg
new file mode 100644
index 000000000..74d0a43fc
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/br_get_external_id_foo_bar.cfg
@@ -0,0 +1 @@
+foo=bar
diff --git a/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/br_to_parent_test_br.cfg b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/br_to_parent_test_br.cfg
new file mode 100644
index 000000000..482c59adb
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/br_to_parent_test_br.cfg
@@ -0,0 +1 @@
+test-br
diff --git a/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/br_to_vlan_zero.cfg b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/br_to_vlan_zero.cfg
new file mode 100644
index 000000000..573541ac9
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/br_to_vlan_zero.cfg
@@ -0,0 +1 @@
+0
diff --git a/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/get_fail_mode_secure.cfg b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/get_fail_mode_secure.cfg
new file mode 100644
index 000000000..38bf3dc0e
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/get_fail_mode_secure.cfg
@@ -0,0 +1 @@
+secure
diff --git a/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/get_port_bond0_external_ids.cfg b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/get_port_bond0_external_ids.cfg
new file mode 100644
index 000000000..660fa5ae1
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/get_port_bond0_external_ids.cfg
@@ -0,0 +1 @@
+{foo=bar}
diff --git a/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/get_port_bond0_other_config.cfg b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/get_port_bond0_other_config.cfg
new file mode 100644
index 000000000..ef62fb5bd
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/get_port_bond0_other_config.cfg
@@ -0,0 +1 @@
+{bond-detect-mode=miimon}
diff --git a/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/get_port_eth2_external_ids.cfg b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/get_port_eth2_external_ids.cfg
new file mode 100644
index 000000000..660fa5ae1
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/get_port_eth2_external_ids.cfg
@@ -0,0 +1 @@
+{foo=bar}
diff --git a/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/get_port_eth2_tag.cfg b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/get_port_eth2_tag.cfg
new file mode 100644
index 000000000..f599e28b8
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/get_port_eth2_tag.cfg
@@ -0,0 +1 @@
+10
diff --git a/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/list_br_test_br.cfg b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/list_br_test_br.cfg
new file mode 100644
index 000000000..482c59adb
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/list_br_test_br.cfg
@@ -0,0 +1 @@
+test-br
diff --git a/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/list_ports_bond_br.cfg b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/list_ports_bond_br.cfg
new file mode 100644
index 000000000..306379d4e
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/list_ports_bond_br.cfg
@@ -0,0 +1 @@
+bond0
diff --git a/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/list_ports_test_br.cfg b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/list_ports_test_br.cfg
new file mode 100644
index 000000000..a908f0da4
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/list_ports_test_br.cfg
@@ -0,0 +1 @@
+eth2
diff --git a/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/openvswitch_db_disable_in_band_missing.cfg b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/openvswitch_db_disable_in_band_missing.cfg
new file mode 100644
index 000000000..3c9dafc69
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/openvswitch_db_disable_in_band_missing.cfg
@@ -0,0 +1,23 @@
+_uuid : 64f04422-d510-4258-9648-ee0a982f58c1
+auto_attach : []
+controller : []
+datapath_id : "00002244f0645842"
+datapath_type : ""
+datapath_version : "<unknown>"
+external_ids : {}
+fail_mode : []
+flood_vlans : []
+flow_tables : {}
+ipfix : []
+mcast_snooping_enable: false
+mirrors : []
+name : test-br
+netflow : []
+other_config : {}
+ports : [2c9c1b35-a304-4dee-bb7a-092d656543c7]
+protocols : []
+rstp_enable : false
+rstp_status : {}
+sflow : []
+status : {}
+stp_enable : false
diff --git a/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/openvswitch_db_disable_in_band_true.cfg b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/openvswitch_db_disable_in_band_true.cfg
new file mode 100644
index 000000000..4b9f3a799
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/fixtures/openvswitch_db_disable_in_band_true.cfg
@@ -0,0 +1,23 @@
+_uuid : 64f04422-d510-4258-9648-ee0a982f58c1
+auto_attach : []
+controller : []
+datapath_id : "00002244f0645842"
+datapath_type : ""
+datapath_version : "<unknown>"
+external_ids : {}
+fail_mode : []
+flood_vlans : []
+flow_tables : {}
+ipfix : []
+mcast_snooping_enable: false
+mirrors : []
+name : test-br
+netflow : []
+other_config : {disable-in-band=true}
+ports : [2c9c1b35-a304-4dee-bb7a-092d656543c7]
+protocols : []
+rstp_enable : false
+rstp_status : {}
+sflow : []
+status : {}
+stp_enable : false
diff --git a/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/ovs_module.py b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/ovs_module.py
new file mode 100644
index 000000000..92a5e11d1
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/ovs_module.py
@@ -0,0 +1,87 @@
+# (c) 2017 Red Hat Inc.
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+import json
+import os
+
+from ansible_collections.openvswitch.openvswitch.tests.unit.modules.utils import (
+ AnsibleExitJson,
+ AnsibleFailJson,
+ ModuleTestCase,
+)
+
+fixture_path = os.path.join(os.path.dirname(__file__), "fixtures")
+fixture_data = {}
+
+
+def load_fixture(name):
+ path = os.path.join(fixture_path, name)
+
+ if path in fixture_data:
+ return fixture_data[path]
+
+ with open(path) as f:
+ data = f.read()
+
+ try:
+ data = json.loads(data)
+ except Exception:
+ pass
+
+ fixture_data[path] = data
+ return data
+
+
+class TestOpenVSwitchModule(ModuleTestCase):
+ def execute_module(self, failed=False, changed=False, commands=None, test_name=None):
+ self.load_fixtures(test_name)
+
+ if failed:
+ result = self.failed()
+ self.assertTrue(result["failed"], result)
+ else:
+ result = self.changed(changed)
+ self.assertEqual(result["changed"], changed, result)
+
+ if commands is not None:
+ self.assertEqual(commands, result["commands"], result["commands"])
+
+ return result
+
+ def failed(self):
+ with self.assertRaises(AnsibleFailJson) as exc:
+ self.module.main()
+
+ result = exc.exception.args[0]
+ self.assertTrue(result["failed"], result)
+ return result
+
+ def changed(self, changed=False):
+ with self.assertRaises(AnsibleExitJson) as exc:
+ self.module.main()
+
+ result = exc.exception.args[0]
+ self.assertEqual(result["changed"], changed, result)
+ return result
+
+ def load_fixtures(self, test_name):
+ pass
diff --git a/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/test_openvswitch_bond.py b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/test_openvswitch_bond.py
new file mode 100644
index 000000000..29f3eba4e
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/test_openvswitch_bond.py
@@ -0,0 +1,175 @@
+#
+# (c) 2020, James Denton <james.denton@outlook.com>
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+from ansible_collections.openvswitch.openvswitch.plugins.modules import openvswitch_bond
+from ansible_collections.openvswitch.openvswitch.tests.unit.compat.mock import patch
+from ansible_collections.openvswitch.openvswitch.tests.unit.modules.utils import set_module_args
+
+from .ovs_module import TestOpenVSwitchModule, load_fixture
+
+test_name_side_effect_matrix = {
+ "test_openvswitch_bond_absent_idempotent": [(0, "", "")],
+ "test_openvswitch_bond_absent_removes_bond": [
+ (0, "list_ports_bond_br.cfg", ""),
+ (0, "get_port_bond0_other_config.cfg", ""),
+ (0, "get_port_bond0_external_ids.cfg", ""),
+ (0, "", ""),
+ (0, "", ""),
+ ],
+ "test_openvswitch_bond_present_idempotent": [
+ (0, "list_ports_bond_br.cfg", ""),
+ (0, "get_port_bond0_other_config.cfg", ""),
+ (0, "get_port_bond0_external_ids.cfg", ""),
+ (0, "", ""),
+ (0, "", ""),
+ ],
+ "test_openvswitch_bond_present_creates_bond": [
+ (0, "", ""),
+ (0, "", ""),
+ (0, "", ""),
+ (0, "", ""),
+ (0, "", ""),
+ ],
+ "test_openvswitch_bond_present_creates_lacp_bond": [
+ (0, "", ""),
+ (0, "", ""),
+ (0, "", ""),
+ (0, "", ""),
+ (0, "", ""),
+ ],
+}
+
+
+class TestOpenVSwitchBondModule(TestOpenVSwitchModule):
+ module = openvswitch_bond
+
+ def setUp(self):
+ super(TestOpenVSwitchBondModule, self).setUp()
+
+ self.mock_run_command = patch("ansible.module_utils.basic.AnsibleModule.run_command")
+ self.run_command = self.mock_run_command.start()
+ self.mock_get_bin_path = patch("ansible.module_utils.basic.AnsibleModule.get_bin_path")
+ self.get_bin_path = self.mock_get_bin_path.start()
+
+ def tearDown(self):
+ super(TestOpenVSwitchBondModule, self).tearDown()
+
+ self.mock_run_command.stop()
+ self.mock_get_bin_path.stop()
+
+ def load_fixtures(self, test_name):
+ test_side_effects = []
+ for s in test_name_side_effect_matrix[test_name]:
+ rc = s[0]
+ out = s[1] if s[1] == "" else str(load_fixture(s[1]))
+ err = s[2]
+ side_effect_with_fixture_loaded = (rc, out, err)
+ test_side_effects.append(side_effect_with_fixture_loaded)
+ self.run_command.side_effect = test_side_effects
+
+ self.get_bin_path.return_value = "/usr/bin/ovs-vsctl"
+
+ def test_openvswitch_bond_absent_idempotent(self):
+ set_module_args(dict(state="absent", bridge="bond-br", port="bond0"))
+ self.execute_module(commands=[], test_name="test_openvswitch_bond_absent_idempotent")
+
+ def test_openvswitch_bond_absent_removes_bond(self):
+ set_module_args(dict(state="absent", bridge="bond-br", port="bond0"))
+ commands = ["/usr/bin/ovs-vsctl -t 5 del-port bond-br bond0"]
+ self.execute_module(
+ changed=True,
+ commands=commands,
+ test_name="test_openvswitch_bond_absent_removes_bond",
+ )
+
+ def test_openvswitch_bond_database_socket(self):
+ set_module_args(
+ dict(
+ state="absent",
+ bridge="bond-br",
+ port="bond0",
+ database_socket="unix:/opt/second.sock",
+ )
+ )
+ commands = ["/usr/bin/ovs-vsctl --db=unix:/opt/second.sock -t 5 del-port bond-br bond0"]
+ self.execute_module(
+ changed=True,
+ commands=commands,
+ test_name="test_openvswitch_bond_absent_removes_bond",
+ )
+
+ def test_openvswitch_bond_present_idempotent(self):
+ set_module_args(
+ dict(
+ state="present",
+ bridge="bond-br",
+ port="bond0",
+ external_ids={"foo": "bar"},
+ other_config={"bond-detect-mode": "miimon"},
+ )
+ )
+ self.execute_module(commands=[], test_name="test_openvswitch_bond_present_idempotent")
+
+ def test_openvswitch_bond_present_creates_bond(self):
+ set_module_args(
+ dict(
+ state="present",
+ bridge="bond-br",
+ port="bond0",
+ bond_updelay="100",
+ bond_downdelay="100",
+ interfaces=["eth3", "eth4"],
+ other_config={"bond-detect-mode": "miimon"},
+ )
+ )
+ commands = [
+ "/usr/bin/ovs-vsctl -t 5 add-bond bond-br bond0 eth3 eth4"
+ + " bond_updelay=100 bond_downdelay=100",
+ "/usr/bin/ovs-vsctl -t 5 set port bond0 other_config:bond-detect-mode=miimon",
+ ]
+ self.execute_module(
+ changed=True,
+ commands=commands,
+ test_name="test_openvswitch_bond_present_creates_bond",
+ )
+
+ def test_openvswitch_bond_present_creates_lacp_bond(self):
+ set_module_args(
+ dict(
+ state="present",
+ lacp="active",
+ bridge="bond-br",
+ port="bond0",
+ interfaces=["eth3", "eth4"],
+ other_config={"bond-detect-mode": "miimon"},
+ )
+ )
+ commands = [
+ "/usr/bin/ovs-vsctl -t 5 add-bond bond-br bond0 eth3 eth4 lacp=active",
+ "/usr/bin/ovs-vsctl -t 5 set port bond0 other_config:bond-detect-mode=miimon",
+ ]
+ self.execute_module(
+ changed=True,
+ commands=commands,
+ test_name="test_openvswitch_bond_present_creates_bond",
+ )
diff --git a/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/test_openvswitch_bridge.py b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/test_openvswitch_bridge.py
new file mode 100644
index 000000000..bd620e84c
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/test_openvswitch_bridge.py
@@ -0,0 +1,299 @@
+#
+# (c) 2016 Red Hat Inc.
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+import pytest
+
+from ansible_collections.openvswitch.openvswitch.plugins.modules import openvswitch_bridge
+from ansible_collections.openvswitch.openvswitch.tests.unit.compat.mock import MagicMock, patch
+from ansible_collections.openvswitch.openvswitch.tests.unit.modules.utils import set_module_args
+
+from .ovs_module import TestOpenVSwitchModule, load_fixture
+
+
+@pytest.fixture
+def patched_openvswitch_bridge(monkeypatch):
+ mocked_bridge = MagicMock()
+ mocked_bridge.return_value = {
+ "bridge": "test-br2",
+ "parent": "test-br",
+ "vlan": 200,
+ "fail_mode": None,
+ "external_ids": None,
+ "set": None,
+ }
+ monkeypatch.setattr(openvswitch_bridge, "map_config_to_obj", mocked_bridge)
+ return openvswitch_bridge
+
+
+test_name_side_effect_matrix = {
+ "test_openvswitch_bridge_absent_idempotent": [(0, "", "")],
+ "test_openvswitch_bridge_absent_removes_bridge": [
+ (0, "list_br_test_br.cfg", ""),
+ (0, "", ""),
+ (0, "", ""),
+ (0, "", ""),
+ (0, "", ""),
+ (0, "", ""),
+ ],
+ "test_openvswitch_bridge_present_idempotent": [
+ (0, "list_br_test_br.cfg", ""),
+ (0, "br_to_parent_test_br.cfg", ""),
+ (0, "br_to_vlan_zero.cfg", ""),
+ (0, "get_fail_mode_secure.cfg", ""),
+ (0, "br_get_external_id_foo_bar.cfg", ""),
+ ],
+ "test_openvswitch_bridge_present_creates_bridge": [
+ (0, "", ""),
+ (0, "", ""),
+ (0, "", ""),
+ (0, "", ""),
+ ],
+ "test_openvswitch_bridge_present_creates_fake_bridge": [
+ (0, "", ""),
+ (0, "", ""),
+ (0, "", ""),
+ (0, "", ""),
+ ],
+ "test_openvswitch_bridge_updates_vlan": [
+ (0, "", ""),
+ (0, "", ""),
+ (0, "", ""),
+ (0, "", ""),
+ ],
+ "test_openvswitch_bridge_present_adds_external_id": [
+ (0, "list_br_test_br.cfg", ""),
+ (0, "br_to_parent_test_br.cfg", ""),
+ (0, "br_to_vlan_zero.cfg", ""),
+ (0, "get_fail_mode_secure.cfg", ""),
+ (0, "br_get_external_id_foo_bar.cfg", ""),
+ (0, "", ""),
+ ],
+ "test_openvswitch_bridge_present_clears_external_id": [
+ (0, "list_br_test_br.cfg", ""),
+ (0, "br_to_parent_test_br.cfg", ""),
+ (0, "br_to_vlan_zero.cfg", ""),
+ (0, "get_fail_mode_secure.cfg", ""),
+ (0, "br_get_external_id_foo_bar.cfg", ""),
+ (0, "", ""),
+ ],
+ "test_openvswitch_bridge_present_changes_fail_mode": [
+ (0, "list_br_test_br.cfg", ""),
+ (0, "br_to_parent_test_br.cfg", ""),
+ (0, "br_to_vlan_zero.cfg", ""),
+ (0, "get_fail_mode_secure.cfg", ""),
+ (0, "br_get_external_id_foo_bar.cfg", ""),
+ (0, "", ""),
+ ],
+ "test_openvswitch_bridge_present_runs_set_mode": [
+ (0, "", ""),
+ (0, "", ""),
+ (0, "", ""),
+ (0, "", ""),
+ ],
+}
+
+
+class TestOpenVSwitchBridgeModule(TestOpenVSwitchModule):
+ module = openvswitch_bridge
+
+ def setUp(self):
+ super(TestOpenVSwitchBridgeModule, self).setUp()
+
+ self.mock_run_command = patch("ansible.module_utils.basic.AnsibleModule.run_command")
+ self.run_command = self.mock_run_command.start()
+ self.mock_get_bin_path = patch("ansible.module_utils.basic.AnsibleModule.get_bin_path")
+ self.get_bin_path = self.mock_get_bin_path.start()
+
+ def tearDown(self):
+ super(TestOpenVSwitchBridgeModule, self).tearDown()
+
+ self.mock_run_command.stop()
+ self.mock_get_bin_path.stop()
+
+ def load_fixtures(self, test_name):
+ test_side_effects = []
+ for s in test_name_side_effect_matrix[test_name]:
+ rc = s[0]
+ out = s[1] if s[1] == "" else str(load_fixture(s[1]))
+ err = s[2]
+ side_effect_with_fixture_loaded = (rc, out, err)
+ test_side_effects.append(side_effect_with_fixture_loaded)
+ self.run_command.side_effect = test_side_effects
+
+ self.get_bin_path.return_value = "/usr/bin/ovs-vsctl"
+
+ def test_openvswitch_bridge_absent_idempotent(self):
+ set_module_args(dict(state="absent", bridge="test-br"))
+ self.execute_module(test_name="test_openvswitch_bridge_absent_idempotent")
+
+ def test_openvswitch_bridge_absent_removes_bridge(self):
+ set_module_args(dict(state="absent", bridge="test-br"))
+ commands = ["/usr/bin/ovs-vsctl -t 5 del-br test-br"]
+ self.execute_module(
+ changed=True,
+ commands=commands,
+ test_name="test_openvswitch_bridge_absent_removes_bridge",
+ )
+
+ def test_openvswitch_bridge_present_idempotent(self):
+ set_module_args(
+ dict(
+ state="present",
+ bridge="test-br",
+ fail_mode="secure",
+ external_ids={"foo": "bar"},
+ )
+ )
+ self.execute_module(test_name="test_openvswitch_bridge_present_idempotent")
+
+ def test_openvswitch_bridge_present_creates_bridge(self):
+ set_module_args(
+ dict(
+ state="present",
+ bridge="test-br",
+ fail_mode="secure",
+ external_ids={"foo": "bar"},
+ )
+ )
+ commands = [
+ "/usr/bin/ovs-vsctl -t 5 add-br test-br",
+ "/usr/bin/ovs-vsctl -t 5 set-fail-mode test-br secure",
+ "/usr/bin/ovs-vsctl -t 5 br-set-external-id test-br foo bar",
+ ]
+ self.execute_module(
+ changed=True,
+ commands=commands,
+ test_name="test_openvswitch_bridge_present_creates_bridge",
+ )
+
+ def test_openvswitch_bridge_present_creates_fake_bridge(self):
+ set_module_args(dict(state="present", bridge="test-br2", parent="test-br", vlan=10))
+ commands = ["/usr/bin/ovs-vsctl -t 5 add-br test-br2 test-br 10"]
+ self.execute_module(
+ changed=True,
+ commands=commands,
+ test_name="test_openvswitch_bridge_present_creates_fake_bridge",
+ )
+
+ def test_openvswitch_bridge_uses_database_socket(self):
+ set_module_args(
+ dict(
+ state="present",
+ bridge="test-br2",
+ parent="test-br",
+ database_socket="unix:/opt/second.sock",
+ vlan=10,
+ )
+ )
+ commands = ["/usr/bin/ovs-vsctl --db=unix:/opt/second.sock -t 5 add-br test-br2 test-br 10"]
+ self.execute_module(
+ changed=True,
+ commands=commands,
+ test_name="test_openvswitch_bridge_present_creates_fake_bridge",
+ )
+
+ @pytest.mark.usefixtures("patched_openvswitch_bridge")
+ def test_openvswitch_bridge_updates_vlan(self):
+ set_module_args(
+ {
+ "state": "present",
+ "bridge": "test-br2",
+ "parent": "test-br",
+ "vlan": 300,
+ }
+ )
+ commands = ["/usr/bin/ovs-vsctl -t 5 set port test-br2 tag=300"]
+ self.execute_module(
+ changed=True,
+ commands=commands,
+ test_name="test_openvswitch_bridge_updates_vlan",
+ )
+
+ def test_openvswitch_bridge_present_adds_external_id(self):
+ set_module_args(
+ dict(
+ state="present",
+ bridge="test-br",
+ fail_mode="secure",
+ external_ids={"bip": "bop"},
+ )
+ )
+ commands = ["/usr/bin/ovs-vsctl -t 5 br-set-external-id test-br bip bop"]
+ self.execute_module(
+ changed=True,
+ commands=commands,
+ test_name="test_openvswitch_bridge_present_adds_external_id",
+ )
+
+ def test_openvswitch_bridge_present_clears_external_id(self):
+ set_module_args(
+ dict(
+ state="present",
+ bridge="test-br",
+ fail_mode="secure",
+ external_ids={"foo": ""},
+ )
+ )
+ commands = ["/usr/bin/ovs-vsctl -t 5 br-set-external-id test-br foo "]
+ self.execute_module(
+ changed=True,
+ commands=commands,
+ test_name="test_openvswitch_bridge_present_clears_external_id",
+ )
+
+ def test_openvswitch_bridge_present_changes_fail_mode(self):
+ set_module_args(
+ dict(
+ state="present",
+ bridge="test-br",
+ fail_mode="standalone",
+ external_ids={"foo": "bar"},
+ )
+ )
+ commands = ["/usr/bin/ovs-vsctl -t 5 set-fail-mode test-br standalone"]
+ self.execute_module(
+ changed=True,
+ commands=commands,
+ test_name="test_openvswitch_bridge_present_changes_fail_mode",
+ )
+
+ def test_openvswitch_bridge_present_runs_set_mode(self):
+ set_module_args(
+ dict(
+ state="present",
+ bridge="test-br",
+ fail_mode="secure",
+ external_ids={"foo": "bar"},
+ set="bridge test-br datapath_type=netdev",
+ )
+ )
+ commands = [
+ "/usr/bin/ovs-vsctl -t 5 add-br test-br -- set bridge test-br datapath_type=netdev",
+ "/usr/bin/ovs-vsctl -t 5 set-fail-mode test-br secure",
+ "/usr/bin/ovs-vsctl -t 5 br-set-external-id test-br foo bar",
+ ]
+ self.execute_module(
+ changed=True,
+ commands=commands,
+ test_name="test_openvswitch_bridge_present_runs_set_mode",
+ )
diff --git a/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/test_openvswitch_db.py b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/test_openvswitch_db.py
new file mode 100644
index 000000000..6d2db5565
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/test_openvswitch_db.py
@@ -0,0 +1,328 @@
+#
+# (c) 2016 Red Hat Inc.
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+import pytest
+
+from ansible_collections.openvswitch.openvswitch.plugins.modules import openvswitch_db
+from ansible_collections.openvswitch.openvswitch.tests.unit.compat.mock import MagicMock, patch
+from ansible_collections.openvswitch.openvswitch.tests.unit.modules.utils import set_module_args
+
+from .ovs_module import TestOpenVSwitchModule, load_fixture
+
+
+@pytest.fixture
+def patched_openvswitch_db(monkeypatch):
+ mocked_ovs_db = MagicMock()
+ mocked_ovs_db.return_value = {
+ "table": "open_vswitch",
+ "record": ".",
+ "col": "other_config",
+ "key": "pmd-cpu-mask",
+ "value": "0xaaa00000000",
+ }
+ monkeypatch.setattr(openvswitch_db, "map_config_to_obj", mocked_ovs_db)
+ return openvswitch_db
+
+
+test_name_side_effect_matrix = {
+ "test_openvswitch_db_absent_idempotent": [
+ (0, "openvswitch_db_disable_in_band_missing.cfg", None),
+ (0, None, None),
+ ],
+ "test_openvswitch_db_absent_removes_key": [
+ (0, "openvswitch_db_disable_in_band_true.cfg", None),
+ (0, None, None),
+ ],
+ "test_openvswitch_db_present_idempotent": [
+ (0, "openvswitch_db_disable_in_band_true.cfg", None),
+ (0, None, None),
+ ],
+ "test_openvswitch_db_present_idempotent_value": [(0, None, None)],
+ "test_openvswitch_db_present_adds_key": [
+ (0, "openvswitch_db_disable_in_band_missing.cfg", None),
+ (0, None, None),
+ ],
+ "test_openvswitch_db_present_updates_key": [
+ (0, "openvswitch_db_disable_in_band_true.cfg", None),
+ (0, None, None),
+ ],
+ "test_openvswitch_db_present_missing_key_on_map": [
+ (0, "openvswitch_db_disable_in_band_true.cfg", None),
+ (0, None, None),
+ ],
+ "test_openvswitch_db_present_stp_enable": [
+ (0, "openvswitch_db_disable_in_band_true.cfg", None),
+ (0, None, None),
+ ],
+ "test_openvswitch_db_get_with_key": [
+ (0, "openvswitch_db_disable_in_band_true.cfg", None),
+ (0, None, None),
+ ],
+ "test_openvswitch_db_get_without_key": [
+ (0, "openvswitch_db_disable_in_band_true.cfg", None),
+ (0, None, None),
+ ],
+ "test_openvswitch_db_get_non_dict": [
+ (0, "openvswitch_db_disable_in_band_true.cfg", None),
+ (0, None, None),
+ ],
+}
+
+
+class TestOpenVSwitchDBModule(TestOpenVSwitchModule):
+ module = openvswitch_db
+
+ def setUp(self):
+ super(TestOpenVSwitchDBModule, self).setUp()
+
+ self.mock_run_command = patch("ansible.module_utils.basic.AnsibleModule.run_command")
+ self.run_command = self.mock_run_command.start()
+ self.mock_get_bin_path = patch("ansible.module_utils.basic.AnsibleModule.get_bin_path")
+ self.get_bin_path = self.mock_get_bin_path.start()
+
+ def tearDown(self):
+ super(TestOpenVSwitchDBModule, self).tearDown()
+
+ self.mock_run_command.stop()
+ self.mock_get_bin_path.stop()
+
+ def load_fixtures(self, test_name):
+ test_side_effects = []
+ for s in test_name_side_effect_matrix[test_name]:
+ rc = s[0]
+ out = load_fixture(s[1]) if s[1] else None
+ err = s[2]
+ side_effect_with_fixture_loaded = (rc, out, err)
+ test_side_effects.append(side_effect_with_fixture_loaded)
+ self.run_command.side_effect = test_side_effects
+
+ self.get_bin_path.return_value = "/usr/bin/ovs-vsctl"
+
+ def test_openvswitch_db_absent_idempotent(self):
+ set_module_args(
+ dict(
+ state="absent",
+ table="Bridge",
+ record="test-br",
+ col="other_config",
+ key="disable-in-band",
+ value="true",
+ )
+ )
+ self.execute_module(test_name="test_openvswitch_db_absent_idempotent")
+
+ def test_openvswitch_db_absent_removes_key(self):
+ set_module_args(
+ dict(
+ state="absent",
+ table="Bridge",
+ record="test-br",
+ col="other_config",
+ key="disable-in-band",
+ value="true",
+ )
+ )
+ self.execute_module(
+ changed=True,
+ commands=[
+ "/usr/bin/ovs-vsctl -t 5 remove Bridge test-br other_config disable-in-band=true"
+ ],
+ test_name="test_openvswitch_db_absent_removes_key",
+ )
+
+ def test_openvswitch_db_absent_removes_key_no_value(self):
+ set_module_args(
+ dict(
+ state="absent",
+ table="Bridge",
+ record="test-br",
+ col="other_config",
+ key="disable-in-band",
+ )
+ )
+ self.execute_module(
+ changed=True,
+ commands=["/usr/bin/ovs-vsctl -t 5 remove Bridge test-br other_config disable-in-band"],
+ test_name="test_openvswitch_db_absent_removes_key",
+ )
+
+ def test_openvswitch_db_present_idempotent(self):
+ set_module_args(
+ dict(
+ state="present",
+ table="Bridge",
+ record="test-br",
+ col="other_config",
+ key="disable-in-band",
+ value="true",
+ )
+ )
+ self.execute_module(test_name="test_openvswitch_db_present_idempotent")
+
+ @pytest.mark.usefixtures("patched_openvswitch_db")
+ def test_openvswitch_db_present_idempotent_value(self):
+ set_module_args(
+ {
+ "col": "other_config",
+ "key": "pmd-cpu-mask",
+ "record": ".",
+ "table": "open_vswitch",
+ "value": "0xaaa00000000",
+ }
+ )
+ self.execute_module(test_name="test_openvswitch_db_present_idempotent_value")
+
+ def test_openvswitch_db_present_adds_key(self):
+ set_module_args(
+ dict(
+ state="present",
+ table="Bridge",
+ record="test-br",
+ col="other_config",
+ key="disable-in-band",
+ value="true",
+ )
+ )
+ self.execute_module(
+ changed=True,
+ commands=[
+ "/usr/bin/ovs-vsctl -t 5 set Bridge test-br other_config:disable-in-band=true"
+ ],
+ test_name="test_openvswitch_db_present_adds_key",
+ )
+
+ def test_openvswitch_db_present_updates_key(self):
+ set_module_args(
+ dict(
+ state="present",
+ table="Bridge",
+ record="test-br",
+ col="other_config",
+ key="disable-in-band",
+ value="false",
+ )
+ )
+ self.execute_module(
+ changed=True,
+ commands=[
+ "/usr/bin/ovs-vsctl -t 5 set Bridge test-br other_config:disable-in-band=false"
+ ],
+ test_name="test_openvswitch_db_present_updates_key",
+ )
+
+ def test_openvswitch_uses_database_socket(self):
+ set_module_args(
+ dict(
+ state="present",
+ table="Bridge",
+ record="test-br",
+ col="other_config",
+ key="disable-in-band",
+ database_socket="unix:/opt/second.sock",
+ value="false",
+ )
+ )
+ self.execute_module(
+ changed=True,
+ commands=[
+ "/usr/bin/ovs-vsctl --db=unix:/opt/second.sock -t 5 set Bridge test-br other_config"
+ ":disable-in-band=false"
+ ],
+ test_name="test_openvswitch_db_present_updates_key",
+ )
+
+ def test_openvswitch_db_present_missing_key_on_map(self):
+ set_module_args(
+ dict(
+ state="present",
+ table="Bridge",
+ record="test-br",
+ col="other_config",
+ value="false",
+ )
+ )
+ self.execute_module(
+ failed=True,
+ test_name="test_openvswitch_db_present_missing_key_on_map",
+ )
+
+ def test_openvswitch_db_present_stp_enable(self):
+ set_module_args(
+ dict(
+ state="present",
+ table="Bridge",
+ record="test-br",
+ col="stp_enable",
+ value="true",
+ )
+ )
+ self.execute_module(changed=True, test_name="test_openvswitch_db_present_stp_enable")
+
+ def test_openvswitch_db_get_with_key(self):
+ set_module_args(
+ dict(
+ state="read",
+ table="Bridge",
+ record="test-br",
+ col="other_config",
+ key="disable-in-band",
+ value="true",
+ )
+ )
+ self.execute_module(
+ changed=True,
+ commands=["/usr/bin/ovs-vsctl -t 5 get Bridge test-br other_config:disable-in-band"],
+ test_name="test_openvswitch_db_get_with_key",
+ )
+
+ def test_openvswitch_db_get_without_key(self):
+ set_module_args(
+ dict(
+ state="read",
+ table="Bridge",
+ record="test-br",
+ col="other_config",
+ value="true",
+ )
+ )
+ self.execute_module(
+ changed=True,
+ commands=["/usr/bin/ovs-vsctl -t 5 get Bridge test-br other_config"],
+ test_name="test_openvswitch_db_get_without_key",
+ )
+
+ def test_openvswitch_db_get_non_dict(self):
+ set_module_args(
+ dict(
+ state="read",
+ table="Bridge",
+ record="test-br",
+ col="name",
+ value="true",
+ )
+ )
+ self.execute_module(
+ changed=True,
+ commands=["/usr/bin/ovs-vsctl -t 5 get Bridge test-br name"],
+ test_name="test_openvswitch_db_get_non_dict",
+ )
diff --git a/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/test_openvswitch_port.py b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/test_openvswitch_port.py
new file mode 100644
index 000000000..9817228be
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/network/ovs/test_openvswitch_port.py
@@ -0,0 +1,289 @@
+#
+# (c) 2016 Red Hat Inc.
+#
+# This file is part of Ansible
+#
+# Ansible is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Ansible is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+from ansible_collections.openvswitch.openvswitch.plugins.modules import openvswitch_port
+from ansible_collections.openvswitch.openvswitch.tests.unit.compat.mock import patch
+from ansible_collections.openvswitch.openvswitch.tests.unit.modules.utils import set_module_args
+
+from .ovs_module import TestOpenVSwitchModule, load_fixture
+
+test_name_side_effect_matrix = {
+ "test_openvswitch_port_absent_idempotent": [(0, "", "")],
+ "test_openvswitch_port_absent_removes_port": [
+ (0, "list_ports_test_br.cfg", ""),
+ (0, "get_port_eth2_tag.cfg", ""),
+ (0, "get_port_eth2_external_ids.cfg", ""),
+ (0, "", ""),
+ ],
+ "test_openvswitch_port_present_idempotent": [
+ (0, "list_ports_test_br.cfg", ""),
+ (0, "get_port_eth2_tag.cfg", ""),
+ (0, "get_port_eth2_external_ids.cfg", ""),
+ (0, "", ""),
+ ],
+ "test_openvswitch_port_present_creates_port": [
+ (0, "", ""),
+ (0, "", ""),
+ (0, "", ""),
+ ],
+ "test_openvswitch_port_present_changes_tag": [
+ (0, "list_ports_test_br.cfg", ""),
+ (0, "get_port_eth2_tag.cfg", ""),
+ (0, "get_port_eth2_external_ids.cfg", ""),
+ (0, "", ""),
+ ],
+ "test_openvswitch_port_present_changes_external_id": [
+ (0, "list_ports_test_br.cfg", ""),
+ (0, "get_port_eth2_tag.cfg", ""),
+ (0, "get_port_eth2_external_ids.cfg", ""),
+ (0, "", ""),
+ ],
+ "test_openvswitch_port_present_adds_external_id": [
+ (0, "list_ports_test_br.cfg", ""),
+ (0, "get_port_eth2_tag.cfg", ""),
+ (0, "get_port_eth2_external_ids.cfg", ""),
+ (0, "", ""),
+ ],
+ "test_openvswitch_port_present_clears_external_id": [
+ (0, "list_ports_test_br.cfg", ""),
+ (0, "get_port_eth2_tag.cfg", ""),
+ (0, "get_port_eth2_external_ids.cfg", ""),
+ (0, "", ""),
+ ],
+ "test_openvswitch_port_present_runs_set_mode": [
+ (0, "", ""),
+ (0, "", ""),
+ (0, "", ""),
+ ],
+}
+
+
+class TestOpenVSwitchPortModule(TestOpenVSwitchModule):
+ module = openvswitch_port
+
+ def setUp(self):
+ super(TestOpenVSwitchPortModule, self).setUp()
+
+ self.mock_run_command = patch("ansible.module_utils.basic.AnsibleModule.run_command")
+ self.run_command = self.mock_run_command.start()
+ self.mock_get_bin_path = patch("ansible.module_utils.basic.AnsibleModule.get_bin_path")
+ self.get_bin_path = self.mock_get_bin_path.start()
+
+ def tearDown(self):
+ super(TestOpenVSwitchPortModule, self).tearDown()
+
+ self.mock_run_command.stop()
+ self.mock_get_bin_path.stop()
+
+ def load_fixtures(self, test_name):
+ test_side_effects = []
+ for s in test_name_side_effect_matrix[test_name]:
+ rc = s[0]
+ out = s[1] if s[1] == "" else str(load_fixture(s[1]))
+ err = s[2]
+ side_effect_with_fixture_loaded = (rc, out, err)
+ test_side_effects.append(side_effect_with_fixture_loaded)
+ self.run_command.side_effect = test_side_effects
+
+ self.get_bin_path.return_value = "/usr/bin/ovs-vsctl"
+
+ def test_openvswitch_port_absent_idempotent(self):
+ set_module_args(dict(state="absent", bridge="test-br", port="eth2"))
+ self.execute_module(test_name="test_openvswitch_port_absent_idempotent")
+
+ def test_openvswitch_port_absent_removes_port(self):
+ set_module_args(dict(state="absent", bridge="test-br", port="eth2"))
+ commands = ["/usr/bin/ovs-vsctl -t 5 del-port test-br eth2"]
+ self.execute_module(
+ changed=True,
+ commands=commands,
+ test_name="test_openvswitch_port_absent_removes_port",
+ )
+
+ def test_openvswitch_port_present_idempotent(self):
+ set_module_args(
+ dict(
+ state="present",
+ bridge="test-br",
+ port="eth2",
+ tag=10,
+ external_ids={"foo": "bar"},
+ )
+ )
+ self.execute_module(test_name="test_openvswitch_port_present_idempotent")
+
+ def test_openvswitch_port_present_creates_port(self):
+ set_module_args(
+ dict(
+ state="present",
+ bridge="test-br",
+ port="eth2",
+ tag=10,
+ external_ids={"foo": "bar"},
+ )
+ )
+ commands = [
+ "/usr/bin/ovs-vsctl -t 5 add-port test-br eth2 tag=10",
+ "/usr/bin/ovs-vsctl -t 5 set port eth2 external_ids:foo=bar",
+ ]
+ self.execute_module(
+ changed=True,
+ commands=commands,
+ test_name="test_openvswitch_port_present_creates_port",
+ )
+
+ def test_openvswitch_port_present_changes_tag(self):
+ set_module_args(
+ dict(
+ state="present",
+ bridge="test-br",
+ port="eth2",
+ tag=20,
+ external_ids={"foo": "bar"},
+ )
+ )
+ commands = ["/usr/bin/ovs-vsctl -t 5 set port eth2 tag=20"]
+ self.execute_module(
+ changed=True,
+ commands=commands,
+ test_name="test_openvswitch_port_present_changes_tag",
+ )
+
+ def test_openvswitch_port_present_changes_external_id(self):
+ set_module_args(
+ dict(
+ state="present",
+ bridge="test-br",
+ port="eth2",
+ tag=10,
+ external_ids={"foo": "baz"},
+ )
+ )
+ commands = ["/usr/bin/ovs-vsctl -t 5 set port eth2 external_ids:foo=baz"]
+ self.execute_module(
+ changed=True,
+ commands=commands,
+ test_name="test_openvswitch_port_present_changes_external_id",
+ )
+
+ def test_openvswitch_port_present_adds_external_id(self):
+ set_module_args(
+ dict(
+ state="present",
+ bridge="test-br",
+ port="eth2",
+ tag=10,
+ external_ids={"foo2": "bar2"},
+ )
+ )
+ commands = ["/usr/bin/ovs-vsctl -t 5 set port eth2 external_ids:foo2=bar2"]
+ self.execute_module(
+ changed=True,
+ commands=commands,
+ test_name="test_openvswitch_port_present_adds_external_id",
+ )
+
+ def test_openvswitch_port_present_clears_external_id(self):
+ set_module_args(
+ dict(
+ state="present",
+ bridge="test-br",
+ port="eth2",
+ tag=10,
+ external_ids={"foo": None},
+ )
+ )
+ commands = ["/usr/bin/ovs-vsctl -t 5 remove port eth2 external_ids foo"]
+ self.execute_module(
+ changed=True,
+ commands=commands,
+ test_name="test_openvswitch_port_present_clears_external_id",
+ )
+
+ def test_openvswitch_port_present_runs_set_mode(self):
+ set_module_args(
+ dict(
+ state="present",
+ bridge="test-br",
+ port="eth2",
+ tag=10,
+ external_ids={"foo": "bar"},
+ set="port eth2 other_config:stp-path-cost=10",
+ )
+ )
+ commands = [
+ "/usr/bin/ovs-vsctl -t 5 add-port test-br eth2 tag=10 -- set"
+ " port eth2 other_config:stp-path-cost=10",
+ "/usr/bin/ovs-vsctl -t 5 set port eth2 external_ids:foo=bar",
+ ]
+ self.execute_module(
+ changed=True,
+ commands=commands,
+ test_name="test_openvswitch_port_present_runs_set_mode",
+ )
+
+ def test_openvswitch_port_present_runs_set_mode_multiple(self):
+ set_module_args(
+ dict(
+ state="present",
+ bridge="test-br",
+ port="eth2",
+ tag=10,
+ external_ids={"foo": "bar"},
+ set=[
+ "port eth2 other_config:stp-path-cost=10",
+ "port eth2 type=patch",
+ ],
+ )
+ )
+ commands = [
+ "/usr/bin/ovs-vsctl -t 5 add-port test-br eth2 tag=10 -- set"
+ " port eth2 other_config:stp-path-cost=10 -- set port eth2 type=patch",
+ "/usr/bin/ovs-vsctl -t 5 set port eth2 external_ids:foo=bar",
+ ]
+ self.execute_module(
+ changed=True,
+ commands=commands,
+ test_name="test_openvswitch_port_present_runs_set_mode",
+ )
+
+ def test_openvswitch_database_socket(self):
+ set_module_args(
+ dict(
+ state="present",
+ bridge="test-br",
+ port="eth2",
+ database_socket="unix:/opt/second.sock",
+ tag=10,
+ external_ids={"foo": "bar"},
+ )
+ )
+ commands = [
+ "/usr/bin/ovs-vsctl --db=unix:/opt/second.sock -t 5 add-port test-br eth2 tag=10",
+ "/usr/bin/ovs-vsctl --db=unix:/opt/second.sock -t 5 set port eth2 external_ids:foo=bar",
+ ]
+ self.execute_module(
+ changed=True,
+ commands=commands,
+ test_name="test_openvswitch_port_present_creates_port",
+ )
diff --git a/ansible_collections/openvswitch/openvswitch/tests/unit/modules/utils.py b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/utils.py
new file mode 100644
index 000000000..3c63aaecd
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/tests/unit/modules/utils.py
@@ -0,0 +1,53 @@
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+import json
+
+from ansible.module_utils import basic
+from ansible.module_utils._text import to_bytes
+
+from ansible_collections.openvswitch.openvswitch.tests.unit.compat import unittest
+from ansible_collections.openvswitch.openvswitch.tests.unit.compat.mock import patch
+
+
+def set_module_args(args):
+ if "_ansible_remote_tmp" not in args:
+ args["_ansible_remote_tmp"] = "/tmp"
+ if "_ansible_keep_remote_files" not in args:
+ args["_ansible_keep_remote_files"] = False
+
+ args = json.dumps({"ANSIBLE_MODULE_ARGS": args})
+ basic._ANSIBLE_ARGS = to_bytes(args)
+
+
+class AnsibleExitJson(Exception):
+ pass
+
+
+class AnsibleFailJson(Exception):
+ pass
+
+
+def exit_json(*args, **kwargs):
+ if "changed" not in kwargs:
+ kwargs["changed"] = False
+ raise AnsibleExitJson(kwargs)
+
+
+def fail_json(*args, **kwargs):
+ kwargs["failed"] = True
+ raise AnsibleFailJson(kwargs)
+
+
+class ModuleTestCase(unittest.TestCase):
+ def setUp(self):
+ self.mock_module = patch.multiple(
+ basic.AnsibleModule, exit_json=exit_json, fail_json=fail_json
+ )
+ self.mock_module.start()
+ self.mock_sleep = patch("time.sleep")
+ self.mock_sleep.start()
+ set_module_args({})
+ self.addCleanup(self.mock_module.stop)
+ self.addCleanup(self.mock_sleep.stop)
diff --git a/ansible_collections/openvswitch/openvswitch/tests/unit/requirements.txt b/ansible_collections/openvswitch/openvswitch/tests/unit/requirements.txt
new file mode 100644
index 000000000..a9772bea1
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/tests/unit/requirements.txt
@@ -0,0 +1,42 @@
+boto3
+placebo
+pycrypto
+passlib
+pypsrp
+python-memcached
+pytz
+pyvmomi
+redis
+requests
+setuptools > 0.6 # pytest-xdist installed via requirements does not work with very old setuptools (sanity_ok)
+unittest2 ; python_version < '2.7'
+importlib ; python_version < '2.7'
+netaddr
+ipaddress
+netapp-lib
+solidfire-sdk-python
+
+# requirements for F5 specific modules
+f5-sdk ; python_version >= '2.7'
+f5-icontrol-rest ; python_version >= '2.7'
+deepdiff
+
+# requirement for Fortinet specific modules
+pyFMG
+
+# requirement for aci_rest module
+xmljson
+
+# requirement for winrm connection plugin tests
+pexpect
+
+# requirement for the linode module
+linode-python # APIv3
+linode_api4 ; python_version > '2.6' # APIv4
+
+# requirement for the gitlab module
+python-gitlab
+httmock
+
+# requirment for kubevirt modules
+openshift ; python_version >= '2.7'
diff --git a/ansible_collections/openvswitch/openvswitch/tox.ini b/ansible_collections/openvswitch/openvswitch/tox.ini
new file mode 100644
index 000000000..0610ef989
--- /dev/null
+++ b/ansible_collections/openvswitch/openvswitch/tox.ini
@@ -0,0 +1,31 @@
+[tox]
+minversion = 1.4.2
+envlist = linters
+skipsdist = True
+
+[testenv]
+deps = -r{toxinidir}/requirements.txt
+ -r{toxinidir}/test-requirements.txt
+
+[testenv:black]
+install_command = pip install {opts} {packages}
+commands =
+ black -v {toxinidir}
+
+[testenv:linters]
+install_command = pip install {opts} {packages}
+commands =
+ black -v --diff --check {toxinidir}
+ flake8 {posargs}
+
+[testenv:venv]
+commands = {posargs}
+
+[flake8]
+# E123, E125 skipped as they are invalid PEP-8.
+
+show-source = True
+ignore = E123,E125,E402,E501,E741,W503
+max-line-length = 160
+builtins = _
+exclude = .git,.tox,tests/unit/compat/