mirror of
https://opendev.org/openstack/ansible-collections-openstack.git
synced 2026-03-27 14:03:03 +00:00
Compare commits
47 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
617e8fb552 | ||
|
|
5abf89d805 | ||
|
|
0599d05103 | ||
|
|
9c28af7d12 | ||
|
|
bcb5d18492 | ||
|
|
7aa626377b | ||
|
|
0a7889b9a2 | ||
|
|
a1b920742f | ||
|
|
bd55e1f905 | ||
|
|
20329c0329 | ||
|
|
bdf472a53f | ||
|
|
b7fb23b097 | ||
|
|
6ed02eff2d | ||
|
|
cb396cf03d | ||
|
|
20c2633ea3 | ||
|
|
6569e07023 | ||
|
|
031475d42e | ||
|
|
5e2ab3d8c3 | ||
|
|
f3b12fed68 | ||
|
|
39a627d4a0 | ||
|
|
4eb7c43539 | ||
|
|
8c6d1041fa | ||
|
|
26530ac97b | ||
|
|
b3e07a1864 | ||
|
|
94933250e8 | ||
|
|
1582956dcd | ||
|
|
b1952e0c4b | ||
|
|
9cd6d2f69a | ||
|
|
86a57498e8 | ||
|
|
15f73aa72e | ||
|
|
22a7f516f3 | ||
|
|
de54be5ecd | ||
|
|
3f1a693bd6 | ||
|
|
8e87ad651f | ||
|
|
b2f3cf3210 | ||
|
|
11c7cd23f8 | ||
|
|
59d0e4c3a4 | ||
|
|
014665ddac | ||
|
|
21b70f6b9b | ||
|
|
ecaff2a798 | ||
|
|
02e9e87964 | ||
|
|
980536c32e | ||
|
|
a9a0d23441 | ||
|
|
011515de2d | ||
|
|
4292a00f75 | ||
|
|
bbefa8c156 | ||
|
|
b023aa337a |
238
.zuul.yaml
238
.zuul.yaml
@@ -3,6 +3,7 @@
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack
|
||||
parent: openstacksdk-functional-devstack
|
||||
post-run: ci/playbooks/postlog.yaml
|
||||
description: |
|
||||
Run openstack collections functional tests against a master devstack
|
||||
using master of openstacksdk with latest ansible release
|
||||
@@ -11,6 +12,7 @@
|
||||
- openstack/designate
|
||||
irrelevant-files: &ignore_files
|
||||
- changelogs/.*
|
||||
- galaxy.*
|
||||
- COPYING
|
||||
- docs/.*
|
||||
- .*\.md
|
||||
@@ -22,12 +24,17 @@
|
||||
vars:
|
||||
zuul_work_dir: src/opendev.org/openstack/ansible-collections-openstack
|
||||
tox_envlist: ansible
|
||||
tox_install_siblings: true
|
||||
tox_install_siblings: false
|
||||
fetch_subunit: false
|
||||
devstack_plugins:
|
||||
designate: https://opendev.org/openstack/designate
|
||||
devstack_services:
|
||||
designate: true
|
||||
neutron-dns: true
|
||||
zuul_copy_output:
|
||||
'{{ devstack_log_dir }}/test_output.log': 'logs'
|
||||
extensions_to_txt:
|
||||
log: true
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-octavia
|
||||
@@ -40,7 +47,7 @@
|
||||
required-projects:
|
||||
- openstack/octavia
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: stable-2.11
|
||||
override-checkout: stable-2.12
|
||||
files:
|
||||
- ^ci/roles/loadbalancer/.*$
|
||||
- ^plugins/modules/lb_health_monitor.py
|
||||
@@ -56,6 +63,7 @@
|
||||
octavia: https://opendev.org/openstack/octavia
|
||||
devstack_services:
|
||||
designate: true
|
||||
neutron-dns: true
|
||||
octavia: true
|
||||
o-api: true
|
||||
o-cw: true
|
||||
@@ -94,13 +102,32 @@
|
||||
parent: ansible-collections-openstack-functional-devstack
|
||||
description: |
|
||||
Run openstack collections functional tests against a master devstack
|
||||
using master of openstacksdk and stable 2.11 branch of ansible
|
||||
using master of openstacksdk and stable 2.12 branch of ansible
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: stable-2.11
|
||||
vars:
|
||||
tox_envlist: ansible
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-ansible-2.12
|
||||
parent: ansible-collections-openstack-functional-devstack
|
||||
description: |
|
||||
Run openstack collections functional tests against a master devstack
|
||||
using master of openstacksdk and stable 2.12 branch of ansible
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: stable-2.12
|
||||
vars:
|
||||
tox_envlist: ansible
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-ansible-new_sdk
|
||||
parent: ansible-collections-openstack-functional-devstack-ansible-2.12
|
||||
voting: false
|
||||
vars:
|
||||
tox_install_siblings: true
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-ansible-devel
|
||||
parent: ansible-collections-openstack-functional-devstack
|
||||
@@ -112,36 +139,53 @@
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: devel
|
||||
vars:
|
||||
tox_envlist: ansible-2.11
|
||||
tox_envlist: ansible-2.12
|
||||
|
||||
# Stable branches tests
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-wallaby-ansible-2.11
|
||||
name: ansible-collections-openstack-functional-devstack-xena-ansible-2.12
|
||||
parent: ansible-collections-openstack-functional-devstack-ansible-devel
|
||||
description: |
|
||||
Run openstack collections functional tests against a xena devstack
|
||||
using xena brach of openstacksdk and stable 2.12 branch of ansible
|
||||
voting: true
|
||||
override-checkout: stable/xena
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: stable-2.12
|
||||
- name: openstack/openstacksdk
|
||||
override-checkout: stable/xena
|
||||
vars:
|
||||
tox_envlist: ansible
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-wallaby-ansible-2.12
|
||||
parent: ansible-collections-openstack-functional-devstack-ansible-devel
|
||||
description: |
|
||||
Run openstack collections functional tests against a wallaby devstack
|
||||
using wallaby brach of openstacksdk and stable 2.11 branch of ansible
|
||||
using wallaby brach of openstacksdk and stable 2.12 branch of ansible
|
||||
voting: true
|
||||
override-checkout: stable/wallaby
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: stable-2.11
|
||||
override-checkout: stable-2.12
|
||||
- name: openstack/openstacksdk
|
||||
override-checkout: stable/wallaby
|
||||
vars:
|
||||
tox_envlist: ansible
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-victoria-ansible-2.11
|
||||
name: ansible-collections-openstack-functional-devstack-victoria-ansible-2.12
|
||||
parent: ansible-collections-openstack-functional-devstack-ansible-devel
|
||||
description: |
|
||||
Run openstack collections functional tests against a victoria devstack
|
||||
using victoria brach of openstacksdk and stable 2.11 branch of ansible
|
||||
using victoria brach of openstacksdk and stable 2.12 branch of ansible
|
||||
voting: true
|
||||
override-checkout: stable/victoria
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: stable-2.11
|
||||
override-checkout: stable-2.12
|
||||
- name: openstack/openstacksdk
|
||||
override-checkout: stable/victoria
|
||||
vars:
|
||||
@@ -172,6 +216,7 @@
|
||||
description: |
|
||||
Run openstack collections functional tests against a train devstack
|
||||
using train brach of openstacksdk and stable 2.11 branch of ansible
|
||||
voting: true
|
||||
override-checkout: stable/train
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
@@ -200,63 +245,6 @@
|
||||
vars:
|
||||
tox_envlist: ansible
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-queens-ansible-devel
|
||||
parent: ansible-collections-openstack-functional-devstack-ansible-devel
|
||||
description: |
|
||||
Run openstack collections functional tests against a queens devstack
|
||||
using master branch of openstacksdk and devel branch of ansible
|
||||
voting: false
|
||||
override-checkout: stable/queens
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: devel
|
||||
- name: openstack/openstacksdk
|
||||
# Run queens with highest possible py2 version of SDK
|
||||
override-checkout: stable/train
|
||||
vars:
|
||||
tox_envlist: ansible-2.11
|
||||
|
||||
# Experimental pipeline jobs
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-stein-ansible-2.11
|
||||
parent: ansible-collections-openstack-functional-devstack-ansible-devel
|
||||
description: |
|
||||
Run openstack collections functional tests against a stein devstack
|
||||
using stein brach of openstacksdk and stable 2.11 branch of ansible
|
||||
voting: true
|
||||
override-checkout: stable/stein
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: stable-2.11
|
||||
- name: openstack/openstacksdk
|
||||
override-checkout: stable/stein
|
||||
- name: openstack/os-client-config
|
||||
override-checkout: stable/stein
|
||||
vars:
|
||||
tox_envlist: ansible
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-functional-devstack-rocky-ansible-2.11
|
||||
parent: ansible-collections-openstack-functional-devstack-ansible-devel
|
||||
description: |
|
||||
Run openstack collections functional tests against a rocky devstack
|
||||
using rocky brach of openstacksdk and stable 2.11 branch of ansible
|
||||
voting: true
|
||||
override-checkout: stable/rocky
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: stable-2.11
|
||||
- name: openstack/openstacksdk
|
||||
override-checkout: stable/rocky
|
||||
- name: openstack/os-client-config
|
||||
override-checkout: stable/rocky
|
||||
- name: openstack/shade
|
||||
override-checkout: stable/rocky
|
||||
|
||||
vars:
|
||||
tox_envlist: ansible
|
||||
|
||||
# Linters
|
||||
- job:
|
||||
name: openstack-tox-linters-ansible-devel
|
||||
@@ -270,22 +258,22 @@
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: devel
|
||||
vars:
|
||||
tox_envlist: linters-2.11
|
||||
tox_envlist: linters-2.12
|
||||
python_version: 3.8
|
||||
bindep_profile: test py38
|
||||
|
||||
- job:
|
||||
name: openstack-tox-linters-ansible-2.11
|
||||
name: openstack-tox-linters-ansible-2.12
|
||||
parent: openstack-tox-linters
|
||||
nodeset: ubuntu-focal
|
||||
description: |
|
||||
Run openstack collections linter tests using the 2.11 branch of ansible
|
||||
Run openstack collections linter tests using the 2.12 branch of ansible
|
||||
voting: true
|
||||
required-projects:
|
||||
- name: github.com/ansible/ansible
|
||||
override-checkout: stable-2.11
|
||||
override-checkout: stable-2.12
|
||||
vars:
|
||||
tox_envlist: linters-2.11
|
||||
tox_envlist: linters-2.12
|
||||
python_version: 3.8
|
||||
bindep_profile: test py38
|
||||
|
||||
@@ -318,10 +306,25 @@
|
||||
# TripleO jobs
|
||||
- job:
|
||||
name: tripleo-ci-centos-8-standalone-osa
|
||||
parent: tripleo-ci-centos-8-standalone
|
||||
parent: tripleo-ci-base-standalone-centos-8
|
||||
vars:
|
||||
featureset: '052'
|
||||
consumer_job: false
|
||||
build_container_images: true
|
||||
irrelevant-files: &irr_files
|
||||
- .*molecule.*
|
||||
- ^.*\.md$
|
||||
- ^.*\.rst$
|
||||
- ^docs/.*$
|
||||
- ^contrib/.*$
|
||||
- ^changelogs/.*$
|
||||
- ^meta/.*$
|
||||
- ^tests/.*$
|
||||
- ^tools/.*$
|
||||
- ^requirements.*$
|
||||
- ^test-requirements.*$
|
||||
- ^setup.*$
|
||||
- tox.ini
|
||||
# Run only on files used in TripleO
|
||||
files: &ooo_files
|
||||
- ^plugins/modules/catalog_service.*$
|
||||
@@ -336,14 +339,40 @@
|
||||
- ^plugins/modules/stack.*$
|
||||
- ^plugins/module_utils/openstack.*$
|
||||
|
||||
- job:
|
||||
name: tripleo-ci-centos-9-standalone-osa
|
||||
parent: tripleo-ci-centos-8-standalone-osa
|
||||
nodeset: single-centos-9-node
|
||||
branches: master
|
||||
vars:
|
||||
containers_base_image: quay.io/centos/centos:stream9
|
||||
consumer_job: false
|
||||
build_container_images: true
|
||||
files: *ooo_files
|
||||
irrelevant-files: *irr_files
|
||||
|
||||
- job:
|
||||
name: tripleo-ci-centos-8-standalone-train-osa
|
||||
parent: tripleo-ci-centos-8-standalone-osa
|
||||
voting: false
|
||||
override-checkout: stable/train
|
||||
vars:
|
||||
branch_override: stable/train
|
||||
|
||||
- job:
|
||||
name: tripleo-ci-centos-8-standalone-wallaby-osa
|
||||
parent: tripleo-ci-centos-8-standalone-osa
|
||||
override-checkout: stable/wallaby
|
||||
vars:
|
||||
branch_override: stable/wallaby
|
||||
|
||||
- job:
|
||||
name: tripleo-ci-centos-9-standalone-wallaby-osa
|
||||
parent: tripleo-ci-centos-9-standalone-osa
|
||||
branches: master
|
||||
override-checkout: stable/wallaby
|
||||
vars:
|
||||
branch_override: stable/wallaby
|
||||
|
||||
- job:
|
||||
name: ansible-collections-openstack-release
|
||||
parent: base
|
||||
@@ -372,33 +401,30 @@
|
||||
jobs:
|
||||
- tox-pep8
|
||||
- openstack-tox-linters-ansible-devel
|
||||
- openstack-tox-linters-ansible-2.11
|
||||
- openstack-tox-linters-ansible-2.12
|
||||
- openstack-tox-linters-ansible-2.9
|
||||
- ansible-collections-openstack-functional-devstack:
|
||||
dependencies: &deps_unit_lint
|
||||
- tox-pep8
|
||||
- openstack-tox-linters-ansible-2.9
|
||||
- openstack-tox-linters-ansible-2.11
|
||||
- openstack-tox-linters-ansible-2.12
|
||||
|
||||
- ansible-collections-openstack-functional-devstack-ansible-new_sdk:
|
||||
dependencies: *deps_unit_lint
|
||||
- ansible-collections-openstack-functional-devstack-releases:
|
||||
dependencies: *deps_unit_lint
|
||||
- ansible-collections-openstack-functional-devstack-ansible-2.9:
|
||||
dependencies: *deps_unit_lint
|
||||
- ansible-collections-openstack-functional-devstack-ansible-2.11:
|
||||
- ansible-collections-openstack-functional-devstack-ansible-2.12:
|
||||
dependencies: *deps_unit_lint
|
||||
- ansible-collections-openstack-functional-devstack-ansible-devel:
|
||||
dependencies: *deps_unit_lint
|
||||
- ansible-collections-openstack-functional-devstack-wallaby-ansible-2.11:
|
||||
- ansible-collections-openstack-functional-devstack-xena-ansible-2.12:
|
||||
dependencies: *deps_unit_lint
|
||||
- ansible-collections-openstack-functional-devstack-victoria-ansible-2.11:
|
||||
dependencies: *deps_unit_lint
|
||||
- ansible-collections-openstack-functional-devstack-ussuri-ansible-2.11:
|
||||
- ansible-collections-openstack-functional-devstack-wallaby-ansible-2.12:
|
||||
dependencies: *deps_unit_lint
|
||||
- ansible-collections-openstack-functional-devstack-train-ansible-2.11:
|
||||
dependencies: *deps_unit_lint
|
||||
- ansible-collections-openstack-functional-devstack-queens-ansible-2.11:
|
||||
dependencies: *deps_unit_lint
|
||||
voting: false
|
||||
- ansible-collections-openstack-functional-devstack-octavia:
|
||||
dependencies: *deps_unit_lint
|
||||
|
||||
@@ -411,55 +437,65 @@
|
||||
dependencies: *deps_unit_lint
|
||||
irrelevant-files: *ignore_files
|
||||
|
||||
- tripleo-ci-centos-8-standalone-osa:
|
||||
- tripleo-ci-centos-8-standalone-wallaby-osa:
|
||||
dependencies: *deps_unit_lint
|
||||
|
||||
- tripleo-ci-centos-8-standalone-train-osa:
|
||||
voting: false
|
||||
dependencies: *deps_unit_lint
|
||||
|
||||
- tripleo-ci-centos-9-standalone-osa:
|
||||
voting: false
|
||||
dependencies: *deps_unit_lint
|
||||
|
||||
- tripleo-ci-centos-9-standalone-wallaby-osa:
|
||||
voting: false
|
||||
dependencies: *deps_unit_lint
|
||||
|
||||
gate:
|
||||
jobs:
|
||||
- tox-pep8
|
||||
- openstack-tox-linters-ansible-2.11
|
||||
- openstack-tox-linters-ansible-2.12
|
||||
- openstack-tox-linters-ansible-2.9
|
||||
- ansible-collections-openstack-functional-devstack
|
||||
- ansible-collections-openstack-functional-devstack-releases
|
||||
- ansible-collections-openstack-functional-devstack-ansible-2.9
|
||||
- ansible-collections-openstack-functional-devstack-ansible-2.11
|
||||
- ansible-collections-openstack-functional-devstack-wallaby-ansible-2.11
|
||||
- ansible-collections-openstack-functional-devstack-victoria-ansible-2.11
|
||||
- ansible-collections-openstack-functional-devstack-ussuri-ansible-2.11
|
||||
- ansible-collections-openstack-functional-devstack-ansible-2.12
|
||||
- ansible-collections-openstack-functional-devstack-wallaby-ansible-2.12
|
||||
- ansible-collections-openstack-functional-devstack-xena-ansible-2.12
|
||||
- ansible-collections-openstack-functional-devstack-train-ansible-2.11
|
||||
- ansible-collections-openstack-functional-devstack-queens-ansible-2.11
|
||||
- ansible-collections-openstack-functional-devstack-octavia
|
||||
- tripleo-ci-centos-8-standalone-osa
|
||||
- tripleo-ci-centos-8-standalone-wallaby-osa
|
||||
|
||||
periodic:
|
||||
jobs:
|
||||
- openstack-tox-linters-ansible-devel
|
||||
- openstack-tox-linters-ansible-2.11
|
||||
- openstack-tox-linters-ansible-2.12
|
||||
- openstack-tox-linters-ansible-2.9
|
||||
- ansible-collections-openstack-functional-devstack
|
||||
- ansible-collections-openstack-functional-devstack-releases
|
||||
- ansible-collections-openstack-functional-devstack-ansible-2.9
|
||||
- ansible-collections-openstack-functional-devstack-ansible-2.11
|
||||
- ansible-collections-openstack-functional-devstack-ansible-2.12
|
||||
- ansible-collections-openstack-functional-devstack-ansible-devel
|
||||
- ansible-collections-openstack-functional-devstack-wallaby-ansible-2.11
|
||||
- ansible-collections-openstack-functional-devstack-victoria-ansible-2.11
|
||||
- ansible-collections-openstack-functional-devstack-ussuri-ansible-2.11
|
||||
- ansible-collections-openstack-functional-devstack-xena-ansible-2.12
|
||||
- ansible-collections-openstack-functional-devstack-wallaby-ansible-2.12
|
||||
- ansible-collections-openstack-functional-devstack-victoria-ansible-2.12
|
||||
- ansible-collections-openstack-functional-devstack-train-ansible-2.11
|
||||
- ansible-collections-openstack-functional-devstack-queens-ansible-2.11
|
||||
- ansible-collections-openstack-functional-devstack-queens-ansible-devel
|
||||
- bifrost-collections-src
|
||||
- bifrost-keystone-collections-src
|
||||
- ansible-collections-openstack-functional-devstack-octavia
|
||||
- tripleo-ci-centos-9-standalone-wallaby-osa
|
||||
- tripleo-ci-centos-9-standalone-osa
|
||||
- tripleo-ci-centos-8-standalone-train-osa
|
||||
- tripleo-ci-centos-8-standalone-wallaby-osa
|
||||
|
||||
experimental:
|
||||
jobs:
|
||||
- ansible-collections-openstack-functional-devstack-stein-ansible-2.11
|
||||
- ansible-collections-openstack-functional-devstack-rocky-ansible-2.11
|
||||
- ansible-collections-openstack-functional-devstack-queens-ansible-devel
|
||||
- ansible-collections-openstack-functional-devstack-ansible-2.11
|
||||
- ansible-collections-openstack-functional-devstack-victoria-ansible-2.12
|
||||
- ansible-collections-openstack-functional-devstack-ussuri-ansible-2.11
|
||||
- ansible-collections-openstack-functional-devstack-queens-ansible-2.11
|
||||
|
||||
tag:
|
||||
jobs:
|
||||
|
||||
@@ -5,6 +5,91 @@ Openstack Cloud Ansilbe modules Release Notes
|
||||
.. contents:: Topics
|
||||
|
||||
|
||||
v1.7.0
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
New modules for Ironic and bugfixes
|
||||
|
||||
Minor Changes
|
||||
-------------
|
||||
|
||||
- openstack_inventory - Adds use_name variable
|
||||
- port - Add dns_[name,domain] to the port module
|
||||
- project - Remove project properties tests and support
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- identity_user_info - Fix identity user lookup with a domain
|
||||
- keystone_domain - Move identity domain to use proxy layer
|
||||
|
||||
New Modules
|
||||
-----------
|
||||
|
||||
- openstack.cloud.baremetal_node_info - Retrieve information about Bare Metal nodes from OpenStack an object.
|
||||
- openstack.cloud.baremetal_port - Create, Update, Remove ironic ports from OpenStack
|
||||
- openstack.cloud.baremetal_port_info - Retrieve information about Bare Metal ports from OpenStack an object.
|
||||
|
||||
v1.6.0
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
New modules for RBAC and Nova services
|
||||
|
||||
Minor Changes
|
||||
-------------
|
||||
|
||||
- quota - Adds metadata_items parameter
|
||||
|
||||
New Modules
|
||||
-----------
|
||||
|
||||
- openstack.cloud.compute_service_info - Retrieve information about one or more OpenStack compute services
|
||||
- openstack.cloud.neutron_rbac_policies_info - Fetch Neutron policies.
|
||||
- openstack.cloud.neutron_rbac_policy - Create or delete a Neutron policy to apply a RBAC rule against an object.
|
||||
|
||||
v1.5.3
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
Bugfixes
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- Don't require allowed_address_pairs for port
|
||||
- server_volume - check specified server is found
|
||||
|
||||
v1.5.2
|
||||
======
|
||||
|
||||
Release Summary
|
||||
---------------
|
||||
|
||||
Bugfixes
|
||||
|
||||
Minor Changes
|
||||
-------------
|
||||
|
||||
- Add documentation links to README.md
|
||||
- Don't run functional jobs on galaxy.yml change
|
||||
- Move CI to use Ansible 2.12 version as main
|
||||
|
||||
Bugfixes
|
||||
--------
|
||||
|
||||
- Add client and member listener timeouts for persistence (Ex. SSH)
|
||||
- Added missing warn() used in cloud.openstack.quota
|
||||
- Fix issue with same host and group names
|
||||
- Flavor properties are not deleted on changes and id will stay
|
||||
|
||||
v1.5.1
|
||||
======
|
||||
|
||||
|
||||
@@ -83,6 +83,14 @@ Or you can add the full namespace and collection name in the `collections` eleme
|
||||
device: /dev/vdb
|
||||
```
|
||||
|
||||
### Usage
|
||||
|
||||
See the collection docs at Ansible site:
|
||||
|
||||
* [openstack.cloud collection docs (version released in Ansible package)](https://docs.ansible.com/ansible/latest/collections/openstack/cloud/index.html)
|
||||
|
||||
* [openstack.cloud collection docs (devel version)](https://docs.ansible.com/ansible/devel/collections/openstack/cloud/index.html)
|
||||
|
||||
## Contributing
|
||||
|
||||
For information on contributing, please see [CONTRIBUTING](https://opendev.org/openstack/ansible-collections-openstack/src/branch/master/CONTRIBUTING.rst)
|
||||
|
||||
@@ -246,3 +246,61 @@ releases:
|
||||
- Update IRC server in README
|
||||
release_summary: Bugfixes for networking modules
|
||||
release_date: '2021-09-02'
|
||||
1.5.2:
|
||||
changes:
|
||||
bugfixes:
|
||||
- Add client and member listener timeouts for persistence (Ex. SSH)
|
||||
- Added missing warn() used in cloud.openstack.quota
|
||||
- Fix issue with same host and group names
|
||||
- Flavor properties are not deleted on changes and id will stay
|
||||
minor_changes:
|
||||
- Add documentation links to README.md
|
||||
- Don't run functional jobs on galaxy.yml change
|
||||
- Move CI to use Ansible 2.12 version as main
|
||||
release_summary: Bugfixes
|
||||
release_date: '2021-11-09'
|
||||
1.5.3:
|
||||
changes:
|
||||
bugfixes:
|
||||
- Don't require allowed_address_pairs for port
|
||||
- server_volume - check specified server is found
|
||||
release_summary: Bugfixes
|
||||
release_date: '2021-11-11'
|
||||
1.6.0:
|
||||
changes:
|
||||
minor_changes:
|
||||
- quota - Adds metadata_items parameter
|
||||
release_summary: New modules for RBAC and Nova services
|
||||
modules:
|
||||
- description: Retrieve information about one or more OpenStack compute services
|
||||
name: compute_service_info
|
||||
namespace: ''
|
||||
- description: Fetch Neutron policies.
|
||||
name: neutron_rbac_policies_info
|
||||
namespace: ''
|
||||
- description: Create or delete a Neutron policy to apply a RBAC rule against
|
||||
an object.
|
||||
name: neutron_rbac_policy
|
||||
namespace: ''
|
||||
release_date: '2022-01-13'
|
||||
1.7.0:
|
||||
changes:
|
||||
bugfixes:
|
||||
- identity_user_info - Fix identity user lookup with a domain
|
||||
- keystone_domain - Move identity domain to use proxy layer
|
||||
minor_changes:
|
||||
- openstack_inventory - Adds use_name variable
|
||||
- port - Add dns_[name,domain] to the port module
|
||||
- project - Remove project properties tests and support
|
||||
release_summary: New modules for Ironic and bugfixes
|
||||
modules:
|
||||
- description: Retrieve information about Bare Metal nodes from OpenStack an object.
|
||||
name: baremetal_node_info
|
||||
namespace: ''
|
||||
- description: Create, Update, Remove ironic ports from OpenStack
|
||||
name: baremetal_port
|
||||
namespace: ''
|
||||
- description: Retrieve information about Bare Metal ports from OpenStack an object.
|
||||
name: baremetal_port_info
|
||||
namespace: ''
|
||||
release_date: '2022-02-15'
|
||||
|
||||
8
ci/playbooks/postlog.yaml
Normal file
8
ci/playbooks/postlog.yaml
Normal file
@@ -0,0 +1,8 @@
|
||||
- hosts: all
|
||||
tasks:
|
||||
- zuul_return:
|
||||
data:
|
||||
zuul:
|
||||
artifacts:
|
||||
- name: Test log
|
||||
url: controller/logs/test_output_log.txt
|
||||
@@ -1,19 +1,36 @@
|
||||
---
|
||||
- name: Create keystone domain
|
||||
openstack.cloud.identity_domain:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ domain_name }}"
|
||||
description: "test description"
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ domain_name }}"
|
||||
description: "test description"
|
||||
register: os_domain
|
||||
|
||||
- name: Test output
|
||||
assert:
|
||||
that:
|
||||
- "'domain' in os_domain"
|
||||
- os_domain.domain.name == "{{ domain_name }}"
|
||||
- >-
|
||||
('enabled' in os_domain.domain.keys() and os_domain.domain['enabled']|bool) or
|
||||
('is_enabled' in os_domain.domain and os_domain.domain['is_enabled']|bool)
|
||||
- os_domain.domain.description == "test description"
|
||||
|
||||
- name: Update keystone domain
|
||||
openstack.cloud.identity_domain:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ domain_name }}"
|
||||
description: "updated description"
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ domain_name }}"
|
||||
description: "updated description"
|
||||
register: os_domain_updated
|
||||
|
||||
- name: Test output
|
||||
assert:
|
||||
that:
|
||||
- os_domain_updated.domain.description == "updated description"
|
||||
|
||||
- name: Delete keystone domain
|
||||
openstack.cloud.identity_domain:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: "{{ domain_name }}"
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: "{{ domain_name }}"
|
||||
|
||||
85
ci/roles/neutron_rbac/tasks/main.yml
Normal file
85
ci/roles/neutron_rbac/tasks/main.yml
Normal file
@@ -0,0 +1,85 @@
|
||||
---
|
||||
# General run of tests
|
||||
# - Prepare projects/network objects
|
||||
# - Create rbac object
|
||||
# - Get rbac object info
|
||||
# - Verify RBAC object match
|
||||
# - Delete rbac object
|
||||
# - Get rbac object info
|
||||
# - Verify RBAC object deleted
|
||||
|
||||
- name: Create source project
|
||||
openstack.cloud.project:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: source_project
|
||||
description: Source project for network RBAC test
|
||||
domain_id: default
|
||||
enabled: True
|
||||
register: source_project
|
||||
|
||||
- name: Create network - generic
|
||||
openstack.cloud.network:
|
||||
cloud: "{{ cloud }}"
|
||||
name: "{{ network_name }}"
|
||||
state: present
|
||||
project: "{{ source_project.project.id }}"
|
||||
shared: false
|
||||
external: "{{ network_external }}"
|
||||
register: network
|
||||
|
||||
- name: Create target project
|
||||
openstack.cloud.project:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_project
|
||||
description: Target project for network RBAC test
|
||||
domain_id: default
|
||||
enabled: True
|
||||
register: target_project
|
||||
|
||||
- name: Create a new network RBAC policy
|
||||
openstack.cloud.neutron_rbac_policy:
|
||||
cloud: "{{ cloud }}"
|
||||
object_id: "{{ network.network.id }}"
|
||||
object_type: 'network'
|
||||
action: 'access_as_shared'
|
||||
target_project_id: "{{ target_project.project.id }}"
|
||||
project_id: "{{ source_project.project.id }}"
|
||||
register: rbac_policy
|
||||
|
||||
- name: Get all rbac policies for {{ source_project.project.name }} - after creation
|
||||
openstack.cloud.neutron_rbac_policies_info:
|
||||
cloud: "{{ cloud }}"
|
||||
project_id: "{{ source_project.project.id }}"
|
||||
register: rbac_policies
|
||||
|
||||
- name: Capture all existing policy IDs
|
||||
set_fact:
|
||||
rbac_policy_ids: "{{ rbac_policies.policies | map(attribute='id') | list }}"
|
||||
|
||||
- name: Verify policy exists - after creation
|
||||
assert:
|
||||
that:
|
||||
- rbac_policy.policy.id in rbac_policy_ids
|
||||
|
||||
- name: Delete RBAC policy
|
||||
openstack.cloud.neutron_rbac_policy:
|
||||
cloud: "{{ cloud }}"
|
||||
policy_id: "{{ rbac_policy.policy.id }}"
|
||||
state: absent
|
||||
|
||||
- name: Get all rbac policies for {{ source_project.project.name }} - after deletion
|
||||
openstack.cloud.neutron_rbac_policies_info:
|
||||
cloud: "{{ cloud }}"
|
||||
project_id: "{{ source_project.project.id }}"
|
||||
register: rbac_policies_remaining
|
||||
|
||||
- name: Capture all remaining policy IDs
|
||||
set_fact:
|
||||
remaining_rbac_policy_ids: "{{ rbac_policies_remaining.policies | map(attribute='id') | list }}"
|
||||
|
||||
- name: Verify policy does not exist - after deletion
|
||||
assert:
|
||||
that:
|
||||
- not rbac_policy.policy.id in remaining_rbac_policy_ids
|
||||
15
ci/roles/nova_services/tasks/main.yml
Normal file
15
ci/roles/nova_services/tasks/main.yml
Normal file
@@ -0,0 +1,15 @@
|
||||
---
|
||||
|
||||
- name: Get nova compute services info
|
||||
openstack.cloud.compute_service_info:
|
||||
cloud: "{{ cloud }}"
|
||||
binary: "nova-compute"
|
||||
register: result
|
||||
failed_when: "result.openstack_compute_services | length <= 0"
|
||||
|
||||
- name: Get nova conductor services info
|
||||
openstack.cloud.compute_service_info:
|
||||
cloud: "{{ cloud }}"
|
||||
binary: "nova-conductor"
|
||||
register: result
|
||||
failed_when: "result.openstack_compute_services | length <= 0"
|
||||
@@ -60,6 +60,26 @@
|
||||
state: absent
|
||||
name: "{{ port_name }}"
|
||||
|
||||
- name: Create port (with dns_name, dns_domain)
|
||||
openstack.cloud.port:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: "{{ port_name }}"
|
||||
network: "{{ network_name }}"
|
||||
fixed_ips:
|
||||
- ip_address: 10.5.5.69
|
||||
dns_name: "dns-port-name"
|
||||
dns_domain: "example.com."
|
||||
register: port
|
||||
|
||||
- debug: var=port
|
||||
|
||||
- name: Delete port (with dns name,domain)
|
||||
openstack.cloud.port:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: "{{ port_name }}"
|
||||
|
||||
- name: Create port (with allowed_address_pairs and extra_dhcp_opts)
|
||||
openstack.cloud.port:
|
||||
cloud: "{{ cloud }}"
|
||||
@@ -101,7 +121,7 @@
|
||||
|
||||
- name: Assert binding:profile exists in created port
|
||||
assert:
|
||||
that: "port.port['binding:profile']"
|
||||
that: "port.port['binding_profile']"
|
||||
|
||||
- debug: var=port
|
||||
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
dummy_value: 'test-value'
|
||||
dummy_value_updated: 'test-value-updated'
|
||||
@@ -1,142 +0,0 @@
|
||||
---
|
||||
- name: 'Create project with properties - CHECK_MODE'
|
||||
check_mode: yes
|
||||
openstack.cloud.project:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_project
|
||||
description: dummy description
|
||||
domain_id: default
|
||||
enabled: True
|
||||
properties:
|
||||
dummy_key: '{{ dummy_value }}'
|
||||
register: create_project_cm
|
||||
- assert:
|
||||
that:
|
||||
- create_project_cm is successful
|
||||
- create_project_cm is changed
|
||||
|
||||
- name: 'Create project with properties'
|
||||
openstack.cloud.project:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_project
|
||||
description: dummy description
|
||||
domain_id: default
|
||||
enabled: True
|
||||
properties:
|
||||
dummy_key: '{{ dummy_value }}'
|
||||
register: create_project
|
||||
- assert:
|
||||
that:
|
||||
- create_project is successful
|
||||
- create_project is changed
|
||||
- '"project" in create_project'
|
||||
- '"dummy_key" in create_project["project"]'
|
||||
- create_project["project"].dummy_key == dummy_value
|
||||
|
||||
- name: 'Create project with properties (retry - no change) - CHECK_MODE'
|
||||
check_mode: yes
|
||||
openstack.cloud.project:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_project
|
||||
description: dummy description
|
||||
domain_id: default
|
||||
enabled: True
|
||||
properties:
|
||||
dummy_key: '{{ dummy_value }}'
|
||||
register: create_project_retry_cm
|
||||
- assert:
|
||||
that:
|
||||
- create_project_retry_cm is successful
|
||||
- create_project_retry_cm is not changed
|
||||
|
||||
- name: 'Create project with properties (retry - no change)'
|
||||
openstack.cloud.project:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_project
|
||||
description: dummy description
|
||||
domain_id: default
|
||||
enabled: True
|
||||
properties:
|
||||
dummy_key: '{{ dummy_value }}'
|
||||
register: create_project_retry
|
||||
- assert:
|
||||
that:
|
||||
- create_project_retry is successful
|
||||
- create_project_retry is not changed
|
||||
- '"project" in create_project_retry'
|
||||
- '"dummy_key" in create_project_retry["project"]'
|
||||
- create_project_retry["project"].dummy_key == dummy_value
|
||||
|
||||
- name: 'Update project with properties - CHECK_MODE'
|
||||
check_mode: yes
|
||||
openstack.cloud.project:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_project
|
||||
description: new description
|
||||
properties:
|
||||
dummy_key: '{{ dummy_value_updated }}'
|
||||
register: updated_project_cm
|
||||
- assert:
|
||||
that:
|
||||
- updated_project_cm is successful
|
||||
- updated_project_cm is changed
|
||||
|
||||
- name: 'Update project with properties'
|
||||
openstack.cloud.project:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_project
|
||||
description: new description
|
||||
properties:
|
||||
dummy_key: '{{ dummy_value_updated }}'
|
||||
register: updated_project
|
||||
- assert:
|
||||
that:
|
||||
- updated_project is successful
|
||||
- updated_project is changed
|
||||
- '"project" in updated_project'
|
||||
- '"dummy_key" in updated_project["project"]'
|
||||
- updated_project["project"].dummy_key == dummy_value_updated
|
||||
|
||||
- name: 'Update project with properties (retry - no change) - CHECK_MODE'
|
||||
check_mode: yes
|
||||
openstack.cloud.project:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_project
|
||||
description: new description
|
||||
properties:
|
||||
dummy_key: '{{ dummy_value_updated }}'
|
||||
register: updated_project_retry_cm
|
||||
- assert:
|
||||
that:
|
||||
- updated_project_retry_cm is successful
|
||||
- updated_project_retry_cm is not changed
|
||||
|
||||
- name: 'Update project with properties (retry - no change)'
|
||||
openstack.cloud.project:
|
||||
cloud: "{{ cloud }}"
|
||||
state: present
|
||||
name: ansible_project
|
||||
description: new description
|
||||
properties:
|
||||
dummy_key: '{{ dummy_value_updated }}'
|
||||
register: updated_project_retry
|
||||
- assert:
|
||||
that:
|
||||
- updated_project_retry is successful
|
||||
- updated_project_retry is not changed
|
||||
- '"project" in updated_project_retry'
|
||||
- '"dummy_key" in updated_project_retry["project"]'
|
||||
- updated_project_retry["project"].dummy_key == dummy_value_updated
|
||||
|
||||
- name: Delete project with properties
|
||||
openstack.cloud.project:
|
||||
cloud: "{{ cloud }}"
|
||||
state: absent
|
||||
name: ansible_project
|
||||
@@ -131,8 +131,9 @@ fi
|
||||
SDK_VER=$(python -c "import openstack; print(openstack.version.__version__)")
|
||||
pushd ci/
|
||||
# run tests
|
||||
set -o pipefail
|
||||
ANSIBLE_COLLECTIONS_PATHS=$TEST_COLLECTIONS_PATHS ansible-playbook \
|
||||
-vvv ./run-collection.yml \
|
||||
-e "sdk_version=${SDK_VER} cloud=${CLOUD} image=${IMAGE} ${ANSIBLE_VARS}" \
|
||||
${tag_opt}
|
||||
${tag_opt} 2>&1 | sudo tee /opt/stack/logs/test_output.log
|
||||
popd
|
||||
|
||||
@@ -30,13 +30,17 @@
|
||||
when: sdk_version is version(0.44, '>=')
|
||||
- { role: keystone_role, tags: keystone_role }
|
||||
- { role: network, tags: network }
|
||||
- role: neutron_rbac
|
||||
tags:
|
||||
- rbac
|
||||
- neutron_rbac
|
||||
- { role: nova_flavor, tags: nova_flavor }
|
||||
- role: nova_services
|
||||
tags: nova_services
|
||||
when: sdk_version is version(0.44, '>=')
|
||||
- { role: object, tags: object }
|
||||
- { role: port, tags: port }
|
||||
- { role: project, tags: project }
|
||||
- role: project_properties
|
||||
tags: project_properties
|
||||
when: sdk_version is version("0.45.01", '>')
|
||||
- { role: router, tags: router }
|
||||
- { role: security_group, tags: security_group }
|
||||
- { role: server, tags: server }
|
||||
|
||||
@@ -33,4 +33,4 @@ build_ignore:
|
||||
- ansible_collections_openstack.egg-info
|
||||
- contrib
|
||||
- changelogs
|
||||
version: 1.5.1
|
||||
version: 1.7.0
|
||||
|
||||
@@ -9,6 +9,9 @@ action_groups:
|
||||
- baremetal_node
|
||||
- baremetal_node_action
|
||||
- baremetal_node_action
|
||||
- baremetal_node_info
|
||||
- baremetal_port_info
|
||||
- baremetal_port
|
||||
- catalog_endpoint
|
||||
- catalog_service
|
||||
- catalog_service
|
||||
@@ -19,6 +22,8 @@ action_groups:
|
||||
- compute_flavor
|
||||
- compute_flavor_info
|
||||
- compute_flavor_info
|
||||
- compute_service_info
|
||||
- compute_service_info
|
||||
- config
|
||||
- config
|
||||
- dns_zone
|
||||
|
||||
@@ -42,6 +42,13 @@ options:
|
||||
- name
|
||||
- uuid
|
||||
default: "name"
|
||||
use_names:
|
||||
description: |
|
||||
Use the host's 'name' instead of 'interface_ip' for the 'ansible_host' and
|
||||
'ansible_ssh_host' facts. This might be desired when using jump or
|
||||
bastion hosts and the name is the FQDN of the host.
|
||||
type: bool
|
||||
default: 'no'
|
||||
expand_hostvars:
|
||||
description: |
|
||||
Run extra commands on each host to fill in additional
|
||||
@@ -237,6 +244,7 @@ class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable):
|
||||
expand_hostvars = self._config_data.get('expand_hostvars', False)
|
||||
fail_on_errors = self._config_data.get('fail_on_errors', False)
|
||||
all_projects = self._config_data.get('all_projects', False)
|
||||
self.use_names = self._config_data.get('use_names', False)
|
||||
|
||||
source_data = []
|
||||
try:
|
||||
@@ -311,7 +319,11 @@ class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable):
|
||||
for group_name, group_hosts in groups.items():
|
||||
gname = self.inventory.add_group(group_name)
|
||||
for host in group_hosts:
|
||||
self.inventory.add_child(gname, host)
|
||||
if gname == host:
|
||||
display.vvvv("Same name for host %s and group %s" % (host, gname))
|
||||
self.inventory.add_host(host, gname)
|
||||
else:
|
||||
self.inventory.add_child(gname, host)
|
||||
|
||||
def _get_groups_from_server(self, server_vars, namegroup=True):
|
||||
groups = []
|
||||
@@ -359,10 +371,20 @@ class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable):
|
||||
|
||||
def _append_hostvars(self, hostvars, groups, current_host,
|
||||
server, namegroup=False):
|
||||
hostvars[current_host] = dict(
|
||||
ansible_ssh_host=server['interface_ip'],
|
||||
ansible_host=server['interface_ip'],
|
||||
openstack=server)
|
||||
if not self.use_names:
|
||||
hostvars[current_host] = dict(
|
||||
ansible_ssh_host=server['interface_ip'],
|
||||
ansible_host=server['interface_ip'],
|
||||
openstack=server,
|
||||
)
|
||||
|
||||
if self.use_names:
|
||||
hostvars[current_host] = dict(
|
||||
ansible_ssh_host=server['name'],
|
||||
ansible_host=server['name'],
|
||||
openstack=server,
|
||||
)
|
||||
|
||||
self.inventory.add_host(current_host)
|
||||
|
||||
if self.get_option('legacy_groups'):
|
||||
|
||||
@@ -261,6 +261,7 @@ class OpenStackModule:
|
||||
self.results = {'changed': False}
|
||||
self.exit = self.exit_json = self.ansible.exit_json
|
||||
self.fail = self.fail_json = self.ansible.fail_json
|
||||
self.warn = self.ansible.warn
|
||||
self.sdk, self.conn = self.openstack_cloud_from_module()
|
||||
self.check_deprecated_names()
|
||||
|
||||
|
||||
555
plugins/modules/baremetal_node_info.py
Normal file
555
plugins/modules/baremetal_node_info.py
Normal file
@@ -0,0 +1,555 @@
|
||||
#!/usr/bin/python
|
||||
# coding: utf-8 -*-
|
||||
|
||||
# Copyright (c) 2021 by Red Hat, Inc.
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
|
||||
DOCUMENTATION = '''
|
||||
module: baremetal_node_info
|
||||
short_description: Retrieve information about Bare Metal nodes from OpenStack
|
||||
author: OpenStack Ansible SIG
|
||||
description:
|
||||
- Retrieve information about Bare Metal nodes from OpenStack.
|
||||
options:
|
||||
node:
|
||||
description:
|
||||
- Name or globally unique identifier (UUID) to identify the host.
|
||||
type: str
|
||||
mac:
|
||||
description:
|
||||
- Unique mac address that is used to attempt to identify the host.
|
||||
type: str
|
||||
ironic_url:
|
||||
description:
|
||||
- If noauth mode is utilized, this is required to be set to the
|
||||
endpoint URL for the Ironic API. Use with "auth" and "auth_type"
|
||||
settings set to None.
|
||||
type: str
|
||||
requirements:
|
||||
- "python >= 3.6"
|
||||
- "openstacksdk"
|
||||
|
||||
extends_documentation_fragment:
|
||||
- openstack.cloud.openstack
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
# Gather information about all baremeal nodes
|
||||
- openstack.cloud.baremetal_node_info:
|
||||
cloud: "devstack"
|
||||
register: result
|
||||
- debug:
|
||||
msg: "{{ result.baremetal_nodes }}"
|
||||
# Gather information about a baremeal node
|
||||
- openstack.cloud.baremetal_node_info:
|
||||
cloud: "devstack"
|
||||
node: "00000000-0000-0000-0000-000000000002"
|
||||
register: result
|
||||
- debug:
|
||||
msg: "{{ result.baremetal_nodes }}"
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
baremetal_nodes:
|
||||
description: Bare Metal node list. A subset of the dictionary keys
|
||||
listed below may be returned, depending on your cloud
|
||||
provider.
|
||||
returned: always, but can be null
|
||||
type: complex
|
||||
contains:
|
||||
allocation_uuid:
|
||||
description: The UUID of the allocation associated with the node.
|
||||
If not null, will be the same as instance_uuid (the
|
||||
opposite is not always true). Unlike instance_uuid,
|
||||
this field is read-only. Please use the Allocation API
|
||||
to remove allocations.
|
||||
returned: success
|
||||
type: str
|
||||
automated_clean:
|
||||
description: Indicates whether the node will perform automated
|
||||
clean or not.
|
||||
returned: success
|
||||
type: bool
|
||||
bios_interface:
|
||||
description: The bios interface to be used for this node.
|
||||
returned: success
|
||||
type: str
|
||||
boot_interface:
|
||||
description: The boot interface for a Node, e.g. "pxe".
|
||||
returned: success
|
||||
type: str
|
||||
boot_mode:
|
||||
description: The boot mode for a node, either "uefi" or "bios"
|
||||
returned: success
|
||||
type: str
|
||||
chassis_uuid:
|
||||
description: UUID of the chassis associated with this Node. May be
|
||||
empty or None.
|
||||
returned: success
|
||||
type: str
|
||||
clean_step:
|
||||
description: The current clean step.
|
||||
returned: success
|
||||
type: str
|
||||
conductor:
|
||||
description: The conductor currently servicing a node. This field
|
||||
is read-only.
|
||||
returned: success
|
||||
type: str
|
||||
conductor_group:
|
||||
description: The conductor group for a node. Case-insensitive
|
||||
string up to 255 characters, containing a-z, 0-9, _,
|
||||
-, and ..
|
||||
returned: success
|
||||
type: str
|
||||
console_enabled:
|
||||
description: Indicates whether console access is enabled or
|
||||
disabled on this node.
|
||||
returned: success
|
||||
type: bool
|
||||
console_interface:
|
||||
description: The console interface for a node, e.g. "no-console".
|
||||
returned: success
|
||||
type: str
|
||||
created_at:
|
||||
description: Bare Metal node created at timestamp.
|
||||
returned: success
|
||||
type: str
|
||||
deploy_interface:
|
||||
description: The deploy interface for a node, e.g. "direct".
|
||||
returned: success
|
||||
type: str
|
||||
deploy_step:
|
||||
description: The current deploy step.
|
||||
returned: success
|
||||
type: str
|
||||
driver:
|
||||
description: The name of the driver.
|
||||
returned: success
|
||||
type: str
|
||||
driver_info:
|
||||
description: All the metadata required by the driver to manage this
|
||||
Node. List of fields varies between drivers, and can
|
||||
be retrieved from the
|
||||
/v1/drivers/<DRIVER_NAME>/properties resource.
|
||||
returned: success
|
||||
type: dict
|
||||
driver_internal_info:
|
||||
description: Internal metadata set and stored by the Node's driver.
|
||||
returned: success
|
||||
type: dict
|
||||
extra:
|
||||
description: A set of one or more arbitrary metadata key and value
|
||||
pairs.
|
||||
returned: success
|
||||
type: dict
|
||||
fault:
|
||||
description: The fault indicates the active fault detected by
|
||||
ironic, typically the Node is in "maintenance mode".
|
||||
None means no fault has been detected by ironic.
|
||||
"power failure" indicates ironic failed to retrieve
|
||||
power state from this node. There are other possible
|
||||
types, e.g., "clean failure" and "rescue abort
|
||||
failure".
|
||||
returned: success
|
||||
type: str
|
||||
id:
|
||||
description: The UUID for the resource.
|
||||
returned: success
|
||||
type: str
|
||||
inspect_interface:
|
||||
description: The interface used for node inspection.
|
||||
returned: success
|
||||
type: str
|
||||
instance_info:
|
||||
description: Information used to customize the deployed image. May
|
||||
include root partition size, a base 64 encoded config
|
||||
drive, and other metadata. Note that this field is
|
||||
erased automatically when the instance is deleted
|
||||
(this is done by requesting the Node provision state
|
||||
be changed to DELETED).
|
||||
returned: success
|
||||
type: dict
|
||||
instance_uuid:
|
||||
description: UUID of the Nova instance associated with this Node.
|
||||
returned: success
|
||||
type: str
|
||||
last_error:
|
||||
description: Any error from the most recent (last) transaction that
|
||||
started but failed to finish.
|
||||
returned: success
|
||||
type: str
|
||||
maintenance:
|
||||
description: Whether or not this Node is currently in "maintenance
|
||||
mode". Setting a Node into maintenance mode removes it
|
||||
from the available resource pool and halts some
|
||||
internal automation. This can happen manually (eg, via
|
||||
an API request) or automatically when Ironic detects a
|
||||
hardware fault that prevents communication with the
|
||||
machine.
|
||||
returned: success
|
||||
type: bool
|
||||
maintenance_reason:
|
||||
description: User-settable description of the reason why this Node
|
||||
was placed into maintenance mode
|
||||
returned: success
|
||||
type: str
|
||||
management_interface:
|
||||
description: Interface for out-of-band node management.
|
||||
returned: success
|
||||
type: str
|
||||
name:
|
||||
description: Human-readable identifier for the Node resource. May
|
||||
be undefined. Certain words are reserved.
|
||||
returned: success
|
||||
type: str
|
||||
network_interface:
|
||||
description: Which Network Interface provider to use when plumbing
|
||||
the network connections for this Node.
|
||||
returned: success
|
||||
type: str
|
||||
owner:
|
||||
description: A string or UUID of the tenant who owns the object.
|
||||
returned: success
|
||||
type: str
|
||||
portgroups:
|
||||
description: List of ironic portgroups on this node.
|
||||
returned: success
|
||||
type: list
|
||||
elements: dict
|
||||
contains:
|
||||
address:
|
||||
description: Physical hardware address of this Portgroup,
|
||||
typically the hardware MAC address.
|
||||
returned: success
|
||||
type: str
|
||||
created_at:
|
||||
description: The UTC date and time when the resource was
|
||||
created, ISO 8601 format.
|
||||
returned: success
|
||||
type: str
|
||||
extra:
|
||||
description: A set of one or more arbitrary metadata key and
|
||||
value pairs.
|
||||
returned: success
|
||||
type: dict
|
||||
id:
|
||||
description: The UUID for the resource.
|
||||
returned: success
|
||||
type: str
|
||||
internal_info:
|
||||
description: Internal metadata set and stored by the Portgroup.
|
||||
This field is read-only.
|
||||
returned: success
|
||||
type: dict
|
||||
is_standalone_ports_supported:
|
||||
description: Indicates whether ports that are members of this
|
||||
portgroup can be used as stand-alone ports.
|
||||
returned: success
|
||||
type: bool
|
||||
mode:
|
||||
description: Mode of the port group. For possible values, refer
|
||||
to https://www.kernel.org/doc/Documentation/networking/bonding.txt.
|
||||
If not specified in a request to create a port
|
||||
group, it will be set to the value of the
|
||||
[DEFAULT]default_portgroup_mode configuration
|
||||
option. When set, can not be removed from the port
|
||||
group.
|
||||
returned: success
|
||||
type: str
|
||||
name:
|
||||
description: Human-readable identifier for the Portgroup
|
||||
resource. May be undefined.
|
||||
returned: success
|
||||
type: str
|
||||
node_id:
|
||||
description: UUID of the Node this resource belongs to.
|
||||
returned: success
|
||||
type: str
|
||||
ports:
|
||||
description: List of port UUID's of ports belonging to this
|
||||
portgroup.
|
||||
returned: success
|
||||
type: list
|
||||
properties:
|
||||
description: Key/value properties related to the port group's
|
||||
configuration.
|
||||
returned: success
|
||||
type: dict
|
||||
updated_at:
|
||||
description: The UTC date and time when the resource was
|
||||
updated, ISO 8601 format. May be "null".
|
||||
returned: success
|
||||
type: str
|
||||
ports:
|
||||
description: List of ironic ports on this node.
|
||||
returned: success
|
||||
type: list
|
||||
elements: dict
|
||||
contains:
|
||||
address:
|
||||
description: Physical hardware address of this network Port,
|
||||
typically the hardware MAC address.
|
||||
returned: success
|
||||
type: str
|
||||
created_at:
|
||||
description: The UTC date and time when the resource was
|
||||
created, ISO 8601 format.
|
||||
returned: success
|
||||
type: str
|
||||
extra:
|
||||
description: A set of one or more arbitrary metadata key and
|
||||
value pairs.
|
||||
returned: success
|
||||
type: dict
|
||||
id:
|
||||
description: The UUID for the resource.
|
||||
returned: success
|
||||
type: str
|
||||
internal_info:
|
||||
description: Internal metadata set and stored by the Port. This
|
||||
field is read-only.
|
||||
returned: success
|
||||
type: dict
|
||||
local_link_connection:
|
||||
description: The Port binding profile. If specified, must
|
||||
contain switch_id (only a MAC address or an
|
||||
OpenFlow based datapath_id of the switch are
|
||||
accepted in this field) and port_id (identifier of
|
||||
the physical port on the switch to which node's
|
||||
port is connected to) fields. switch_info is an
|
||||
optional string field to be used to store any
|
||||
vendor-specific information.
|
||||
returned: success
|
||||
type: dict
|
||||
name:
|
||||
description: The name of the resource.
|
||||
returned: success
|
||||
type: str
|
||||
node_uuid:
|
||||
description: UUID of the Node this resource belongs to.
|
||||
returned: success
|
||||
type: str
|
||||
physical_network:
|
||||
description: The name of the physical network to which a port
|
||||
is connected. May be empty.
|
||||
returned: success
|
||||
type: str
|
||||
portgroup_uuid:
|
||||
description: UUID of the Portgroup this resource belongs to.
|
||||
returned: success
|
||||
type: str
|
||||
pxe_enabled:
|
||||
description: Indicates whether PXE is enabled or disabled on
|
||||
the Port.
|
||||
returned: success
|
||||
type: str
|
||||
updated_at:
|
||||
description: The UTC date and time when the resource was
|
||||
updated, ISO 8601 format. May be "null".
|
||||
returned: success
|
||||
type: str
|
||||
uuid:
|
||||
description: The UUID for the resource.
|
||||
returned: success
|
||||
type: str
|
||||
power_interface:
|
||||
description: Interface used for performing power actions on the
|
||||
node, e.g. "ipmitool".
|
||||
returned: success
|
||||
type: str
|
||||
power_state:
|
||||
description: The current power state of this Node. Usually, "power
|
||||
on" or "power off", but may be "None" if Ironic is
|
||||
unable to determine the power state (eg, due to
|
||||
hardware failure).
|
||||
returned: success
|
||||
type: str
|
||||
properties:
|
||||
description: Physical characteristics of this Node. Populated by
|
||||
ironic-inspector during inspection. May be edited via
|
||||
the REST API at any time.
|
||||
returned: success
|
||||
type: dict
|
||||
protected:
|
||||
description: Whether the node is protected from undeploying,
|
||||
rebuilding and deletion.
|
||||
returned: success
|
||||
type: bool
|
||||
protected_reason:
|
||||
description: The reason the node is marked as protected.
|
||||
returned: success
|
||||
type: str
|
||||
provision_state:
|
||||
description: The current provisioning state of this Node.
|
||||
returned: success
|
||||
type: str
|
||||
raid_config:
|
||||
description: Represents the current RAID configuration of the node.
|
||||
Introduced with the cleaning feature.
|
||||
returned: success
|
||||
type: dict
|
||||
raid_interface:
|
||||
description: Interface used for configuring RAID on this node.
|
||||
returned: success
|
||||
type: str
|
||||
rescue_interface:
|
||||
description: The interface used for node rescue, e.g. "no-rescue".
|
||||
returned: success
|
||||
type: str
|
||||
reservation:
|
||||
description: The name of an Ironic Conductor host which is holding
|
||||
a lock on this node, if a lock is held. Usually
|
||||
"null", but this field can be useful for debugging.
|
||||
returned: success
|
||||
type: str
|
||||
resource_class:
|
||||
description: A string which can be used by external schedulers to
|
||||
identify this Node as a unit of a specific type of
|
||||
resource. For more details, see
|
||||
https://docs.openstack.org/ironic/latest/install/configure-nova-flavors.html
|
||||
returned: success
|
||||
type: str
|
||||
retired:
|
||||
description: Whether the node is retired and can hence no longer be
|
||||
provided, i.e. move from manageable to available, and
|
||||
will end up in manageable after cleaning (rather than
|
||||
available).
|
||||
returned: success
|
||||
type: bool
|
||||
retired_reason:
|
||||
description: The reason the node is marked as retired.
|
||||
returned: success
|
||||
type: str
|
||||
secure_boot:
|
||||
description: Indicates whether node is currently booted with
|
||||
secure_boot turned on.
|
||||
returned: success
|
||||
type: bool
|
||||
storage_interface:
|
||||
description: Interface used for attaching and detaching volumes on
|
||||
this node, e.g. "cinder".
|
||||
returned: success
|
||||
type: str
|
||||
target_power_state:
|
||||
description: If a power state transition has been requested, this
|
||||
field represents the requested (ie, "target") state,
|
||||
either "power on" or "power off".
|
||||
returned: success
|
||||
type: str
|
||||
target_provision_state:
|
||||
description: If a provisioning action has been requested, this
|
||||
field represents the requested (ie, "target") state.
|
||||
Note that a Node may go through several states during
|
||||
its transition to this target state. For instance,
|
||||
when requesting an instance be deployed to an
|
||||
AVAILABLE Node, the Node may go through the following
|
||||
state change progression, AVAILABLE -> DEPLOYING ->
|
||||
DEPLOYWAIT -> DEPLOYING -> ACTIVE
|
||||
returned: success
|
||||
type: str
|
||||
target_raid_config:
|
||||
description: Represents the requested RAID configuration of the
|
||||
node, which will be applied when the Node next
|
||||
transitions through the CLEANING state. Introduced
|
||||
with the cleaning feature.
|
||||
returned: success
|
||||
type: dict
|
||||
traits:
|
||||
description: List of traits for this node.
|
||||
returned: success
|
||||
type: list
|
||||
updated_at:
|
||||
description: Bare Metal node updated at timestamp.
|
||||
returned: success
|
||||
type: str
|
||||
uuid:
|
||||
description: The UUID for the resource.
|
||||
returned: success
|
||||
type: str
|
||||
vendor_interface:
|
||||
description: Interface for vendor-specific functionality on this
|
||||
node, e.g. "no-vendor".
|
||||
returned: success
|
||||
type: str
|
||||
'''
|
||||
|
||||
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.ironic import (
|
||||
IronicModule,
|
||||
ironic_argument_spec,
|
||||
)
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import (
|
||||
openstack_module_kwargs,
|
||||
openstack_cloud_from_module
|
||||
)
|
||||
|
||||
|
||||
def cleanup_node_properties(machine, cloud):
|
||||
# states are links, not useful
|
||||
machine.pop('states', None)
|
||||
|
||||
for port in machine.ports:
|
||||
# links are not useful
|
||||
port.pop('links', None)
|
||||
# redundant, location is in on machine as well
|
||||
port.pop('location', None)
|
||||
|
||||
for portgroup in machine.portgroups:
|
||||
# links are not useful
|
||||
portgroup.pop('links', None)
|
||||
# redundant, location is in on machine as well
|
||||
portgroup.pop('location', None)
|
||||
# links to ports are not useful, replace with list of port uuid's
|
||||
portgroup['ports'] = [x.id for x in list(
|
||||
cloud.baremetal.ports(portgroup=portgroup['id']))]
|
||||
|
||||
|
||||
def get_ports_and_portgroups(cloud, machine):
|
||||
machine.ports = cloud.list_nics_for_machine(machine.uuid)
|
||||
machine.portgroups = [dict(x) for x in
|
||||
list(cloud.baremetal.port_groups(node=machine.uuid,
|
||||
details=True))]
|
||||
|
||||
|
||||
def main():
|
||||
argument_spec = ironic_argument_spec(
|
||||
node=dict(required=False),
|
||||
mac=dict(required=False),
|
||||
)
|
||||
module_kwargs = openstack_module_kwargs()
|
||||
module_kwargs['supports_check_mode'] = True
|
||||
|
||||
module = IronicModule(argument_spec, **module_kwargs)
|
||||
|
||||
machine = None
|
||||
machines = list()
|
||||
|
||||
sdk, cloud = openstack_cloud_from_module(module)
|
||||
try:
|
||||
if module.params['node']:
|
||||
machine = cloud.get_machine(module.params['node'])
|
||||
elif module.params['mac']:
|
||||
machine = cloud.get_machine_by_mac(module.params['mac'])
|
||||
|
||||
# Fail if node not found
|
||||
if (module.params['node'] or module.params['mac']) and not machine:
|
||||
module.fail_json(msg='The baremetal node was not found')
|
||||
|
||||
if machine:
|
||||
machines.append(machine)
|
||||
else:
|
||||
machines = cloud.list_machines()
|
||||
|
||||
for machine in machines:
|
||||
get_ports_and_portgroups(cloud, machine)
|
||||
cleanup_node_properties(machine, cloud)
|
||||
|
||||
module.exit_json(changed=False, baremetal_nodes=machines)
|
||||
except sdk.exceptions.OpenStackCloudException as e:
|
||||
module.fail_json(msg=str(e))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
373
plugins/modules/baremetal_port.py
Normal file
373
plugins/modules/baremetal_port.py
Normal file
@@ -0,0 +1,373 @@
|
||||
#!/usr/bin/python
|
||||
# coding: utf-8 -*-
|
||||
# Copyright (c) 2021 by Red Hat, Inc.
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
DOCUMENTATION = '''
|
||||
module: baremetal_port
|
||||
short_description: Create/Delete Bare Metal port Resources from OpenStack
|
||||
author: OpenStack Ansible SIG
|
||||
description:
|
||||
- Create, Update and Remove ironic ports from OpenStack.
|
||||
options:
|
||||
state:
|
||||
description:
|
||||
- Indicates desired state of the resource
|
||||
choices: ['present', 'absent']
|
||||
default: present
|
||||
type: str
|
||||
uuid:
|
||||
description:
|
||||
- globally unique identifier (UUID) to be given to the resource. Will
|
||||
be auto-generated if not specified.
|
||||
type: str
|
||||
node:
|
||||
description:
|
||||
- UUID or Name of the Node this resource belongs to.
|
||||
type: str
|
||||
address:
|
||||
description:
|
||||
- Physical hardware address of this network Port, typically the
|
||||
hardware MAC address.
|
||||
type: str
|
||||
portgroup:
|
||||
description:
|
||||
- UUID or Name of the Portgroup this resource belongs to.
|
||||
type: str
|
||||
local_link_connection:
|
||||
description:
|
||||
- The Port binding profile.
|
||||
type: dict
|
||||
suboptions:
|
||||
switch_id:
|
||||
description:
|
||||
- A MAC address or an OpenFlow based datapath_id of the switch.
|
||||
type: str
|
||||
port_id:
|
||||
description:
|
||||
- Identifier of the physical port on the switch to which node's
|
||||
port is connected to.
|
||||
type: str
|
||||
switch_info:
|
||||
description:
|
||||
- An optional string field to be used to store any vendor-specific
|
||||
information.
|
||||
type: str
|
||||
is_pxe_enabled:
|
||||
description:
|
||||
- Whether PXE should be enabled or disabled on the Port.
|
||||
type: bool
|
||||
physical_network:
|
||||
description:
|
||||
- The name of the physical network to which a port is connected.
|
||||
type: str
|
||||
extra:
|
||||
description:
|
||||
- A set of one or more arbitrary metadata key and value pairs.
|
||||
type: dict
|
||||
ironic_url:
|
||||
description:
|
||||
- If noauth mode is utilized, this is required to be set to the
|
||||
endpoint URL for the Ironic API. Use with "auth" and "auth_type"
|
||||
settings set to None.
|
||||
type: str
|
||||
|
||||
requirements:
|
||||
- "python >= 3.6"
|
||||
- "openstacksdk"
|
||||
extends_documentation_fragment:
|
||||
- openstack.cloud.openstack
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
# Create Bare Metal port
|
||||
- name: Create Bare Metal port
|
||||
openstack.cloud.baremetal_port:
|
||||
cloud: devstack
|
||||
state: present
|
||||
node: bm-0
|
||||
address: fa:16:3e:aa:aa:aa
|
||||
pxe_enabled: True
|
||||
local_link_connection:
|
||||
switch_id: 0a:1b:2c:3d:4e:5f
|
||||
port_id: Ethernet3/1
|
||||
switch_info: switch1
|
||||
extra:
|
||||
something: extra
|
||||
physical_network: datacenter
|
||||
register: result
|
||||
# Delete Bare Metal port
|
||||
- name: Delete Bare Metal port
|
||||
openstack.cloud.baremetal_port:
|
||||
cloud: devstack
|
||||
state: absent
|
||||
address: fa:16:3e:aa:aa:aa
|
||||
register: result
|
||||
# Update Bare Metal port
|
||||
- name: Update Bare Metal port
|
||||
openstack.cloud.baremetal_port:
|
||||
cloud: devstack
|
||||
state: present
|
||||
uuid: 1a85ebca-22bf-42eb-ad9e-f640789b8098
|
||||
pxe_enabled: False
|
||||
local_link_connection:
|
||||
switch_id: a0:b1:c2:d3:e4:f5
|
||||
port_id: Ethernet4/12
|
||||
switch_info: switch2
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
id:
|
||||
description: Unique UUID of the port.
|
||||
returned: always, but can be null
|
||||
type: str
|
||||
result:
|
||||
description: A short text describing the result.
|
||||
returned: success
|
||||
type: str
|
||||
changes:
|
||||
description: Map showing from -> to values for properties that was changed
|
||||
after port update.
|
||||
returned: success
|
||||
type: dict
|
||||
port:
|
||||
description: A port dictionary, subset of the dictionary keys listed below
|
||||
may be returned, depending on your cloud provider.
|
||||
returned: success
|
||||
type: complex
|
||||
contains:
|
||||
address:
|
||||
description: Physical hardware address of this network Port,
|
||||
typically the hardware MAC address.
|
||||
returned: success
|
||||
type: str
|
||||
created_at:
|
||||
description: Bare Metal port created at timestamp.
|
||||
returned: success
|
||||
type: str
|
||||
extra:
|
||||
description: A set of one or more arbitrary metadata key and value
|
||||
pairs.
|
||||
returned: success
|
||||
type: dict
|
||||
id:
|
||||
description: The UUID for the Baremetal Port resource.
|
||||
returned: success
|
||||
type: str
|
||||
internal_info:
|
||||
description: Internal metadata set and stored by the Port. This
|
||||
field is read-only.
|
||||
returned: success
|
||||
type: dict
|
||||
is_pxe_enabled:
|
||||
description: Whether PXE is enabled or disabled on the Port.
|
||||
returned: success
|
||||
type: bool
|
||||
local_link_connection:
|
||||
description: The Port binding profile. If specified, must contain
|
||||
switch_id (only a MAC address or an OpenFlow based
|
||||
datapath_id of the switch are accepted in this field
|
||||
and port_id (identifier of the physical port on the
|
||||
switch to which node's port is connected to) fields.
|
||||
switch_info is an optional string field to be used to
|
||||
store any vendor-specific information.
|
||||
returned: success
|
||||
type: dict
|
||||
location:
|
||||
description: Cloud location of this resource (cloud, project,
|
||||
region, zone)
|
||||
returned: success
|
||||
type: dict
|
||||
name:
|
||||
description: Bare Metal port name.
|
||||
returned: success
|
||||
type: str
|
||||
node_id:
|
||||
description: UUID of the Bare Metal Node this resource belongs to.
|
||||
returned: success
|
||||
type: str
|
||||
physical_network:
|
||||
description: The name of the physical network to which a port is
|
||||
connected.
|
||||
returned: success
|
||||
type: str
|
||||
port_group_id:
|
||||
description: UUID of the Portgroup this resource belongs to.
|
||||
returned: success
|
||||
type: str
|
||||
updated_at:
|
||||
description: Bare Metal port updated at timestamp.
|
||||
returned: success
|
||||
type: str
|
||||
'''
|
||||
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.ironic import (
|
||||
IronicModule,
|
||||
ironic_argument_spec,
|
||||
)
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import (
|
||||
openstack_module_kwargs,
|
||||
openstack_cloud_from_module
|
||||
)
|
||||
|
||||
_PROP_TO_ATTR_MAP = {
|
||||
'pxe_enabled': 'is_pxe_enabled',
|
||||
'address': 'address',
|
||||
'extra': 'extra',
|
||||
'local_link_connection': 'local_link_connection',
|
||||
'physical_network': 'physical_network',
|
||||
'node_uuid': 'node_id',
|
||||
'portgroup_uuid': 'port_group_id',
|
||||
'uuid': 'id',
|
||||
}
|
||||
|
||||
|
||||
def find_port(module, cloud):
|
||||
port = None
|
||||
if module.params['uuid']:
|
||||
port = cloud.baremetal.find_port(module.params['uuid'])
|
||||
elif module.params['address']:
|
||||
ports = list(cloud.baremetal.ports(address=module.params['address'],
|
||||
details=True))
|
||||
if ports and len(ports) == 1:
|
||||
port = ports[0]
|
||||
elif len(ports) > 1:
|
||||
module.fail_json(
|
||||
msg="Multiple ports with address {address} found. A uuid must "
|
||||
"be defined in order to identify the correct port"
|
||||
.format(address=module.params['address']))
|
||||
|
||||
return port
|
||||
|
||||
|
||||
def add_port(module, cloud):
|
||||
port = find_port(module, cloud)
|
||||
if port:
|
||||
update_port(module, cloud, port=port)
|
||||
|
||||
if not module.params['node'] or not module.params['address']:
|
||||
module.fail_json(
|
||||
msg="A Bare Metal node (name or uuid) and an address is required "
|
||||
"to create a port")
|
||||
|
||||
machine = cloud.get_machine(module.params['node'])
|
||||
if not machine:
|
||||
module.fail_json(
|
||||
msg="Bare Metal node {node} could not be found".format(
|
||||
node=module.params['node']))
|
||||
|
||||
module.params['node_uuid'] = machine.id
|
||||
props = {k: module.params[k] for k in _PROP_TO_ATTR_MAP.keys()
|
||||
if k in module.params}
|
||||
port = cloud.baremetal.create_port(**props)
|
||||
port_dict = port.to_dict()
|
||||
port_dict.pop('links', None)
|
||||
module.exit_json(
|
||||
changed=True,
|
||||
result="Port successfully created",
|
||||
changes=None,
|
||||
port=port_dict,
|
||||
id=port_dict['id'])
|
||||
|
||||
|
||||
def update_port(module, cloud, port=None):
|
||||
if not port:
|
||||
port = find_port(module, cloud)
|
||||
|
||||
if module.params['node']:
|
||||
machine = cloud.get_machine(module.params['node'])
|
||||
if machine:
|
||||
module.params['node_uuid'] = machine.id
|
||||
|
||||
old_props = {k: port[v] for k, v in _PROP_TO_ATTR_MAP.items()}
|
||||
new_props = {k: module.params[k] for k in _PROP_TO_ATTR_MAP.keys()
|
||||
if k in module.params and module.params[k] is not None}
|
||||
prop_diff = {k: new_props[k] for k in _PROP_TO_ATTR_MAP.keys()
|
||||
if k in new_props and old_props[k] != new_props[k]}
|
||||
|
||||
if not prop_diff:
|
||||
port_dict = port.to_dict()
|
||||
port_dict.pop('links', None)
|
||||
module.exit_json(
|
||||
changed=False,
|
||||
result="No port update required",
|
||||
changes=None,
|
||||
port=port_dict,
|
||||
id=port_dict['id'])
|
||||
|
||||
port = cloud.baremetal.update_port(port.id, **prop_diff)
|
||||
port_dict = port.to_dict()
|
||||
port_dict.pop('links', None)
|
||||
module.exit_json(
|
||||
changed=True,
|
||||
result="Port successfully updated",
|
||||
changes={k: {'to': new_props[k], 'from': old_props[k]}
|
||||
for k in prop_diff},
|
||||
port=port_dict,
|
||||
id=port_dict['id'])
|
||||
|
||||
|
||||
def remove_port(module, cloud):
|
||||
if not module.params['uuid'] and not module.params['address']:
|
||||
module.fail_json(
|
||||
msg="A uuid or an address value must be defined in order to "
|
||||
"remove a port.")
|
||||
if module.params['uuid']:
|
||||
port = cloud.baremetal.delete_port(module.params['uuid'])
|
||||
if not port:
|
||||
module.exit_json(
|
||||
changed=False,
|
||||
result="Port not found",
|
||||
changes=None,
|
||||
id=module.params['uuid'])
|
||||
else:
|
||||
port = find_port(module, cloud)
|
||||
if not port:
|
||||
module.exit_json(
|
||||
changed=False,
|
||||
result="Port not found",
|
||||
changes=None,
|
||||
id=None)
|
||||
port = cloud.baremetal.delete_port(port.id)
|
||||
|
||||
module.exit_json(
|
||||
changed=True,
|
||||
result="Port successfully removed",
|
||||
changes=None,
|
||||
id=port.id)
|
||||
|
||||
|
||||
def main():
|
||||
argument_spec = ironic_argument_spec(
|
||||
uuid=dict(required=False),
|
||||
node=dict(required=False),
|
||||
address=dict(required=False),
|
||||
portgroup=dict(required=False),
|
||||
local_link_connection=dict(required=False, type='dict'),
|
||||
is_pxe_enabled=dict(required=False, type='bool'),
|
||||
physical_network=dict(required=False),
|
||||
extra=dict(required=False, type='dict'),
|
||||
state=dict(required=False,
|
||||
default='present',
|
||||
choices=['present', 'absent'])
|
||||
)
|
||||
|
||||
module_kwargs = openstack_module_kwargs()
|
||||
module = IronicModule(argument_spec, **module_kwargs)
|
||||
|
||||
module.params['pxe_enabled'] = module.params.pop('is_pxe_enabled', None)
|
||||
|
||||
sdk, cloud = openstack_cloud_from_module(module)
|
||||
try:
|
||||
if module.params['state'] == 'present':
|
||||
add_port(module, cloud)
|
||||
|
||||
if module.params['state'] == 'absent':
|
||||
remove_port(module, cloud)
|
||||
|
||||
except sdk.exceptions.OpenStackCloudException as e:
|
||||
module.fail_json(msg=str(e))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
208
plugins/modules/baremetal_port_info.py
Normal file
208
plugins/modules/baremetal_port_info.py
Normal file
@@ -0,0 +1,208 @@
|
||||
#!/usr/bin/python
|
||||
# coding: utf-8 -*-
|
||||
# Copyright (c) 2021 by Red Hat, Inc.
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
DOCUMENTATION = '''
|
||||
module: baremetal_port_info
|
||||
short_description: Retrieve information about Bare Metal ports from OpenStack
|
||||
author: OpenStack Ansible SIG
|
||||
description:
|
||||
- Retrieve information about Bare Metal ports from OpenStack.
|
||||
options:
|
||||
uuid:
|
||||
description:
|
||||
- Name or globally unique identifier (UUID) to identify the port.
|
||||
type: str
|
||||
address:
|
||||
description:
|
||||
- Physical hardware address of this network Port, typically the
|
||||
hardware MAC address.
|
||||
type: str
|
||||
node:
|
||||
description:
|
||||
- Name or globally unique identifier (UUID) to identify a Baremetal
|
||||
Node.
|
||||
type: str
|
||||
ironic_url:
|
||||
description:
|
||||
- If noauth mode is utilized, this is required to be set to the
|
||||
endpoint URL for the Ironic API. Use with "auth" and "auth_type"
|
||||
settings set to None.
|
||||
type: str
|
||||
requirements:
|
||||
- "python >= 3.6"
|
||||
- "openstacksdk"
|
||||
extends_documentation_fragment:
|
||||
- openstack.cloud.openstack
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
# Gather information about all baremetal ports
|
||||
- openstack.cloud.baremetal_port_info:
|
||||
cloud: devstack
|
||||
register: result
|
||||
# Gather information about a baremetal port by address
|
||||
- openstack.cloud.baremetal_port_info:
|
||||
cloud: devstack
|
||||
address: fa:16:3e:aa:aa:aa
|
||||
register: result
|
||||
# Gather information about a baremetal port by address
|
||||
- openstack.cloud.baremetal_port_info:
|
||||
cloud: devstack
|
||||
uuid: a2b6bd99-77b9-43f0-9ddc-826568e68dec
|
||||
register: result
|
||||
# Gather information about a baremetal ports associated with a baremetal node
|
||||
- openstack.cloud.baremetal_port_info:
|
||||
cloud: devstack
|
||||
node: bm-0
|
||||
register: result
|
||||
'''
|
||||
|
||||
RETURN = '''
|
||||
baremetal_ports:
|
||||
description: Bare Metal port list. A subset of the dictionary keys
|
||||
listed below may be returned, depending on your cloud
|
||||
provider.
|
||||
returned: always, but can be null
|
||||
type: list
|
||||
elements: dict
|
||||
contains:
|
||||
address:
|
||||
description: Physical hardware address of this network Port,
|
||||
typically the hardware MAC address.
|
||||
returned: success
|
||||
type: str
|
||||
created_at:
|
||||
description: Bare Metal port created at timestamp.
|
||||
returned: success
|
||||
type: str
|
||||
extra:
|
||||
description: A set of one or more arbitrary metadata key and
|
||||
value pairs.
|
||||
returned: success
|
||||
type: dict
|
||||
id:
|
||||
description: The UUID for the Baremetal Port resource.
|
||||
returned: success
|
||||
type: str
|
||||
internal_info:
|
||||
description: Internal metadata set and stored by the Port. This
|
||||
field is read-only.
|
||||
returned: success
|
||||
type: dict
|
||||
is_pxe_enabled:
|
||||
description: Whether PXE is enabled or disabled on the Port.
|
||||
returned: success
|
||||
type: bool
|
||||
local_link_connection:
|
||||
description: The Port binding profile.
|
||||
returned: success
|
||||
type: dict
|
||||
contains:
|
||||
switch_id:
|
||||
description: A MAC address or an OpenFlow based datapath_id of
|
||||
the switch.
|
||||
type: str
|
||||
port_id:
|
||||
description: Identifier of the physical port on the switch to
|
||||
which node's port is connected to.
|
||||
type: str
|
||||
switch_info:
|
||||
description: An optional string field to be used to store any
|
||||
vendor-specific information.
|
||||
type: str
|
||||
location:
|
||||
description: Cloud location of this resource (cloud, project,
|
||||
region, zone)
|
||||
returned: success
|
||||
type: dict
|
||||
name:
|
||||
description: Bare Metal port name.
|
||||
returned: success
|
||||
type: str
|
||||
node_id:
|
||||
description: UUID of the Bare Metal Node this resource belongs to.
|
||||
returned: success
|
||||
type: str
|
||||
physical_network:
|
||||
description: The name of the physical network to which a port is
|
||||
connected.
|
||||
returned: success
|
||||
type: str
|
||||
port_group_id:
|
||||
description: UUID of the Portgroup this resource belongs to.
|
||||
returned: success
|
||||
type: str
|
||||
updated_at:
|
||||
description: Bare Metal port updated at timestamp.
|
||||
returned: success
|
||||
type: str
|
||||
'''
|
||||
|
||||
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.ironic import (
|
||||
IronicModule,
|
||||
ironic_argument_spec,
|
||||
)
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import (
|
||||
openstack_module_kwargs,
|
||||
openstack_cloud_from_module
|
||||
)
|
||||
|
||||
|
||||
def main():
|
||||
argument_spec = ironic_argument_spec(
|
||||
uuid=dict(required=False),
|
||||
address=dict(required=False),
|
||||
node=dict(required=False),
|
||||
)
|
||||
module_kwargs = openstack_module_kwargs()
|
||||
module_kwargs['supports_check_mode'] = True
|
||||
module = IronicModule(argument_spec, **module_kwargs)
|
||||
|
||||
ports = list()
|
||||
sdk, cloud = openstack_cloud_from_module(module)
|
||||
try:
|
||||
if module.params['uuid']:
|
||||
port = cloud.baremetal.find_port(module.params['uuid'])
|
||||
if not port:
|
||||
module.fail_json(
|
||||
msg='Baremetal port with uuid {uuid} was not found'
|
||||
.format(uuid=module.params['uuid']))
|
||||
ports.append(port)
|
||||
|
||||
elif module.params['address']:
|
||||
ports = list(
|
||||
cloud.baremetal.ports(address=module.params['address'],
|
||||
details=True))
|
||||
if not ports:
|
||||
module.fail_json(
|
||||
msg='Baremetal port with address {address} was not found'
|
||||
.format(address=module.params['address']))
|
||||
|
||||
elif module.params['node']:
|
||||
machine = cloud.get_machine(module.params['node'])
|
||||
if not machine:
|
||||
module.fail_json(
|
||||
msg='Baremetal node {node} was not found'
|
||||
.format(node=module.params['node']))
|
||||
ports = list(
|
||||
cloud.baremetal.ports(node_uuid=machine.uuid, details=True))
|
||||
|
||||
else:
|
||||
ports = list(cloud.baremetal.ports(details=True))
|
||||
|
||||
# Convert ports to dictionaries and cleanup properties
|
||||
ports = [port.to_dict() for port in ports]
|
||||
for port in ports:
|
||||
# links are not useful
|
||||
port.pop('links', None)
|
||||
|
||||
module.exit_json(changed=False, baremetal_ports=ports)
|
||||
except sdk.exceptions.OpenStackCloudException as e:
|
||||
module.fail_json(msg=str(e))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -220,9 +220,12 @@ class ComputeFlavorModule(OpenStackModule):
|
||||
if self.params[param_key] != flavor[param_key]:
|
||||
require_update = True
|
||||
break
|
||||
|
||||
flavorid = self.params['flavorid']
|
||||
if flavor and require_update:
|
||||
self.conn.delete_flavor(name)
|
||||
old_extra_specs = {}
|
||||
if flavorid == 'auto':
|
||||
flavorid = flavor['id']
|
||||
flavor = None
|
||||
|
||||
if not flavor:
|
||||
@@ -231,7 +234,7 @@ class ComputeFlavorModule(OpenStackModule):
|
||||
ram=self.params['ram'],
|
||||
vcpus=self.params['vcpus'],
|
||||
disk=self.params['disk'],
|
||||
flavorid=self.params['flavorid'],
|
||||
flavorid=flavorid,
|
||||
ephemeral=self.params['ephemeral'],
|
||||
swap=self.params['swap'],
|
||||
rxtx_factor=self.params['rxtx_factor'],
|
||||
|
||||
111
plugins/modules/compute_service_info.py
Normal file
111
plugins/modules/compute_service_info.py
Normal file
@@ -0,0 +1,111 @@
|
||||
#!/usr/bin/python
|
||||
# Copyright (c) 2016 Hewlett-Packard Enterprise Corporation
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
DOCUMENTATION = '''
|
||||
---
|
||||
module: compute_service_info
|
||||
short_description: Retrieve information about one or more OpenStack compute services
|
||||
author: OpenStack Ansible SIG
|
||||
description:
|
||||
- Retrieve information about nova compute services
|
||||
options:
|
||||
binary:
|
||||
description:
|
||||
- Filter by service binary type
|
||||
type: str
|
||||
host:
|
||||
description:
|
||||
- Filter by service host
|
||||
type: str
|
||||
requirements:
|
||||
- "python >= 3.6"
|
||||
- "openstacksdk"
|
||||
|
||||
extends_documentation_fragment:
|
||||
- openstack.cloud.openstack
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
# Gather information about compute services
|
||||
- openstack.cloud.compute_service_info:
|
||||
cloud: awesomecloud
|
||||
binary: "nova-compute"
|
||||
host: "localhost"
|
||||
register: result
|
||||
- openstack.cloud.compute_service_info:
|
||||
cloud: awesomecloud
|
||||
register: result
|
||||
- debug:
|
||||
msg: "{{ result.openstack_compute_services }}"
|
||||
'''
|
||||
|
||||
|
||||
RETURN = '''
|
||||
openstack_compute_services:
|
||||
description: has all the OpenStack information about compute services
|
||||
returned: always, but can be null
|
||||
type: complex
|
||||
contains:
|
||||
id:
|
||||
description: Unique UUID.
|
||||
returned: success
|
||||
type: str
|
||||
binary:
|
||||
description: The binary name of the service.
|
||||
returned: success
|
||||
type: str
|
||||
host:
|
||||
description: The name of the host.
|
||||
returned: success
|
||||
type: str
|
||||
zone:
|
||||
description: The availability zone name.
|
||||
returned: success
|
||||
type: str
|
||||
status:
|
||||
description: The status of the service. One of enabled or disabled.
|
||||
returned: success
|
||||
type: str
|
||||
state:
|
||||
description: The state of the service. One of up or down.
|
||||
returned: success
|
||||
type: str
|
||||
update:
|
||||
description: The date and time when the resource was updated
|
||||
returned: success
|
||||
type: str
|
||||
'''
|
||||
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import OpenStackModule
|
||||
|
||||
|
||||
class ComputeServiceInfoModule(OpenStackModule):
|
||||
argument_spec = dict(
|
||||
binary=dict(required=False, default=None),
|
||||
host=dict(required=False, default=None),
|
||||
)
|
||||
module_kwargs = dict(
|
||||
supports_check_mode=True
|
||||
)
|
||||
|
||||
def run(self):
|
||||
binary = self.params['binary']
|
||||
host = self.params['host']
|
||||
filters = {}
|
||||
if binary:
|
||||
filters['binary'] = binary
|
||||
if host:
|
||||
filters['host'] = host
|
||||
services = self.conn.compute.services(**filters)
|
||||
services = list(services)
|
||||
self.exit_json(changed=False, openstack_compute_services=services)
|
||||
|
||||
|
||||
def main():
|
||||
module = ComputeServiceInfoModule()
|
||||
module()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -104,7 +104,8 @@ class IdentityDomainModule(OpenStackModule):
|
||||
if self.params['description'] is not None and \
|
||||
domain.description != self.params['description']:
|
||||
return True
|
||||
if domain.enabled != self.params['enabled']:
|
||||
if domain.get(
|
||||
"is_enabled", domain.get("enabled")) != self.params['enabled']:
|
||||
return True
|
||||
return False
|
||||
|
||||
@@ -126,7 +127,7 @@ class IdentityDomainModule(OpenStackModule):
|
||||
enabled = self.params['enabled']
|
||||
state = self.params['state']
|
||||
|
||||
domains = self.conn.search_domains(filters=dict(name=name))
|
||||
domains = list(self.conn.identity.domains(name=name))
|
||||
|
||||
if len(domains) > 1:
|
||||
self.fail_json(msg='Domain name %s is not unique' % name)
|
||||
@@ -151,7 +152,10 @@ class IdentityDomainModule(OpenStackModule):
|
||||
changed = True
|
||||
else:
|
||||
changed = False
|
||||
self.exit_json(changed=changed, domain=domain, id=domain.id)
|
||||
if hasattr(domain, "to_dict"):
|
||||
domain = domain.to_dict()
|
||||
domain.pop("location")
|
||||
self.exit_json(changed=changed, domain=domain, id=domain['id'])
|
||||
|
||||
elif state == 'absent':
|
||||
if domain is None:
|
||||
|
||||
@@ -141,12 +141,7 @@ class IdentityUserInfoModule(OpenStackModule):
|
||||
else:
|
||||
self.fail_json(msg='Domain name or ID does not exist')
|
||||
|
||||
if not filters:
|
||||
filters = {}
|
||||
|
||||
filters['domain_id'] = domain
|
||||
|
||||
users = self.conn.search_users(name, filters)
|
||||
users = self.conn.search_users(name, filters, domain_id=domain)
|
||||
self.exit_json(changed=False, openstack_users=users)
|
||||
|
||||
|
||||
|
||||
@@ -38,6 +38,16 @@ options:
|
||||
- The protocol port number for the listener.
|
||||
default: 80
|
||||
type: int
|
||||
timeout_client_data:
|
||||
description:
|
||||
- Client inactivity timeout in milliseconds.
|
||||
default: 50000
|
||||
type: int
|
||||
timeout_member_data:
|
||||
description:
|
||||
- Member inactivity timeout in milliseconds.
|
||||
default: 50000
|
||||
type: int
|
||||
wait:
|
||||
description:
|
||||
- If the module should wait for the load balancer to be ACTIVE.
|
||||
@@ -108,6 +118,14 @@ listener:
|
||||
description: The protocol port number for the listener.
|
||||
type: int
|
||||
sample: 80
|
||||
timeout_client_data:
|
||||
description: Client inactivity timeout in milliseconds.
|
||||
type: int
|
||||
sample: 50000
|
||||
timeout_member_data:
|
||||
description: Member inactivity timeout in milliseconds.
|
||||
type: int
|
||||
sample: 50000
|
||||
'''
|
||||
|
||||
EXAMPLES = '''
|
||||
@@ -139,6 +157,18 @@ EXAMPLES = '''
|
||||
state: absent
|
||||
name: test-listener
|
||||
loadbalancer: test-loadbalancer
|
||||
|
||||
# Create a listener, increase timeouts for connection persistence (for SSH for example).
|
||||
- openstack.cloud.lb_listener:
|
||||
cloud: mycloud
|
||||
endpoint_type: admin
|
||||
state: present
|
||||
name: test-listener
|
||||
loadbalancer: test-loadbalancer
|
||||
protocol: TCP
|
||||
protocol_port: 22
|
||||
timeout_client_data: 1800000
|
||||
timeout_member_data: 1800000
|
||||
'''
|
||||
|
||||
import time
|
||||
@@ -154,6 +184,8 @@ class LoadbalancerListenerModule(OpenStackModule):
|
||||
protocol=dict(default='HTTP',
|
||||
choices=['HTTP', 'HTTPS', 'TCP', 'TERMINATED_HTTPS', 'UDP', 'SCTP']),
|
||||
protocol_port=dict(default=80, type='int', required=False),
|
||||
timeout_client_data=dict(default=50000, type='int', required=False),
|
||||
timeout_member_data=dict(default=50000, type='int', required=False),
|
||||
)
|
||||
module_kwargs = dict()
|
||||
|
||||
@@ -205,6 +237,8 @@ class LoadbalancerListenerModule(OpenStackModule):
|
||||
loadbalancer_id=loadbalancer_id,
|
||||
protocol=self.params['protocol'],
|
||||
protocol_port=self.params['protocol_port'],
|
||||
timeout_client_data=self.params['timeout_client_data'],
|
||||
timeout_member_data=self.params['timeout_member_data'],
|
||||
)
|
||||
changed = True
|
||||
|
||||
|
||||
237
plugins/modules/neutron_rbac_policies_info.py
Normal file
237
plugins/modules/neutron_rbac_policies_info.py
Normal file
@@ -0,0 +1,237 @@
|
||||
#!/usr/bin/python
|
||||
# coding: utf-8 -*-
|
||||
|
||||
# Copyright: Ansible Project
|
||||
# (c) 2021, Ashraf Hasson <ahasson@redhat.com>
|
||||
# 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 = r'''
|
||||
---
|
||||
module: neutron_rbac_policies_info
|
||||
short_description: Fetch Neutron policies.
|
||||
author: OpenStack Ansible SIG
|
||||
description:
|
||||
- Get RBAC policies against a network, security group or a QoS Policy for one or more projects.
|
||||
- If a C(policy_id) was not provided, this module will attempt to fetch all available policies.
|
||||
- Accepts same arguments as OpenStackSDK network proxy C(find_rbac_policy) and C(rbac_policies) functions which are ultimately passed over to C(RBACPolicy)
|
||||
- All parameters passed in to this module act as a filter for when no C(policy_id) was provided, otherwise they're ignored.
|
||||
- Returns None if no matching policy was found as opposed to failing.
|
||||
|
||||
options:
|
||||
policy_id:
|
||||
description:
|
||||
- The RBAC policy ID
|
||||
- If provided, all other filters are ignored
|
||||
type: str
|
||||
object_id:
|
||||
description:
|
||||
- The object ID (the subject of the policy) to which the RBAC rules applies
|
||||
- This would be the ID of a network, security group or a qos policy
|
||||
- Mutually exclusive with the C(object_type)
|
||||
type: str
|
||||
object_type:
|
||||
description:
|
||||
- Can be one of the following object types C(network), C(security_group) or C(qos_policy)
|
||||
- Mutually exclusive with the C(object_id)
|
||||
choices: ['network', 'security_group', 'qos_policy']
|
||||
type: str
|
||||
target_project_id:
|
||||
description:
|
||||
- Filters the RBAC rules based on the target project id
|
||||
- Logically AND'ed with other filters
|
||||
- Mutually exclusive with C(project_id)
|
||||
type: str
|
||||
project_id:
|
||||
description:
|
||||
- Filters the RBAC rules based on the project id to which the object belongs to
|
||||
- Logically AND'ed with other filters
|
||||
- Mutually exclusive with C(target_project_id)
|
||||
type: str
|
||||
project:
|
||||
description:
|
||||
- Filters the RBAC rules based on the project name
|
||||
- Logically AND'ed with other filters
|
||||
type: str
|
||||
action:
|
||||
description:
|
||||
- Can be either of the following options C(access_as_shared) | C(access_as_external)
|
||||
- Logically AND'ed with other filters
|
||||
choices: ['access_as_shared', 'access_as_external']
|
||||
type: str
|
||||
|
||||
extends_documentation_fragment:
|
||||
- openstack.cloud.openstack
|
||||
'''
|
||||
|
||||
EXAMPLES = r'''
|
||||
# Gather all rbac policies for a project
|
||||
- name: Get all rbac policies for {{ project }}
|
||||
openstack.cloud.neutron_rbac_policies_info:
|
||||
project_id: "{{ project.id }}"
|
||||
'''
|
||||
|
||||
RETURN = r'''
|
||||
# return value can either be plural or signular depending on what was passed in as parameters
|
||||
policies:
|
||||
description:
|
||||
- List of rbac policies, this could also be returned as a singular element, i.e., 'policy'
|
||||
type: complex
|
||||
returned: always
|
||||
contains:
|
||||
object_id:
|
||||
description:
|
||||
- The UUID of the object to which the RBAC rules apply
|
||||
type: str
|
||||
sample: "7422172b-2961-475c-ac68-bd0f2a9960ad"
|
||||
target_project_id:
|
||||
description:
|
||||
- The UUID of the target project
|
||||
type: str
|
||||
sample: "c201a689c016435c8037977166f77368"
|
||||
project_id:
|
||||
description:
|
||||
- The UUID of the project to which access is granted
|
||||
type: str
|
||||
sample: "84b8774d595b41e89f3dfaa1fd76932c"
|
||||
object_type:
|
||||
description:
|
||||
- The object type to which the RBACs apply
|
||||
type: str
|
||||
sample: "network"
|
||||
action:
|
||||
description:
|
||||
- The access model specified by the RBAC rules
|
||||
type: str
|
||||
sample: "access_as_shared"
|
||||
id:
|
||||
description:
|
||||
- The ID of the RBAC rule/policy
|
||||
type: str
|
||||
sample: "4154ce0c-71a7-4d87-a905-09762098ddb9"
|
||||
name:
|
||||
description:
|
||||
- The name of the RBAC rule; usually null
|
||||
type: str
|
||||
sample: null
|
||||
location:
|
||||
description:
|
||||
- A dictionary of the project details to which access is granted
|
||||
type: dict
|
||||
sample: >-
|
||||
{
|
||||
"cloud": "devstack",
|
||||
"region_name": "",
|
||||
"zone": null,
|
||||
"project": {
|
||||
"id": "84b8774d595b41e89f3dfaa1fd76932c",
|
||||
"name": null,
|
||||
"domain_id": null,
|
||||
"domain_name": null
|
||||
}
|
||||
}
|
||||
'''
|
||||
|
||||
import re
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import OpenStackModule
|
||||
|
||||
|
||||
class NeutronRbacPoliciesInfo(OpenStackModule):
|
||||
argument_spec = dict(
|
||||
policy_id=dict(),
|
||||
object_id=dict(), # ID of the object that this RBAC policy affects.
|
||||
object_type=dict(choices=['security_group', 'qos_policy', 'network']), # Type of the object that this RBAC policy affects.
|
||||
target_project_id=dict(), # The ID of the project this RBAC will be enforced.
|
||||
project_id=dict(), # The owner project ID.
|
||||
project=dict(),
|
||||
action=dict(choices=['access_as_external', 'access_as_shared']), # Action for the RBAC policy.
|
||||
)
|
||||
|
||||
module_kwargs = dict(
|
||||
supports_check_mode=True,
|
||||
)
|
||||
|
||||
def _filter_policies_by(self, policies, key, value):
|
||||
filtered = []
|
||||
regexp = re.compile(r"location\.project\.([A-Za-z]+)")
|
||||
if regexp.match(key):
|
||||
attribute = key.split('.')[-1]
|
||||
for p in policies:
|
||||
if p['location']['project'][attribute] == value:
|
||||
filtered.append(p)
|
||||
else:
|
||||
for p in policies:
|
||||
if getattr(p, key) == value:
|
||||
filtered.append(p)
|
||||
|
||||
return filtered
|
||||
|
||||
def _get_rbac_policies(self):
|
||||
object_type = self.params.get('object_type')
|
||||
project_id = self.params.get('project_id')
|
||||
action = self.params.get('action')
|
||||
|
||||
search_attributes = {}
|
||||
if object_type is not None:
|
||||
search_attributes['object_type'] = object_type
|
||||
if project_id is not None:
|
||||
search_attributes['project_id'] = project_id
|
||||
if action is not None:
|
||||
search_attributes['action'] = action
|
||||
|
||||
try:
|
||||
policies = []
|
||||
generator = self.conn.network.rbac_policies(**search_attributes)
|
||||
for p in generator:
|
||||
policies.append(p)
|
||||
except self.sdk.exceptions.OpenStackCloudException as ex:
|
||||
self.fail_json(msg='Failed to get RBAC policies: {0}'.format(str(ex)))
|
||||
|
||||
return policies
|
||||
|
||||
def run(self):
|
||||
policy_id = self.params.get('policy_id')
|
||||
object_id = self.params.get('object_id')
|
||||
object_type = self.params.get('object_type')
|
||||
project_id = self.params.get('project_id')
|
||||
project = self.params.get('project')
|
||||
target_project_id = self.params.get('target_project_id')
|
||||
|
||||
if self.ansible.check_mode:
|
||||
self.exit_json(changed=False)
|
||||
|
||||
if policy_id is not None:
|
||||
try:
|
||||
policy = self.conn.network.get_rbac_policy(policy_id)
|
||||
self.exit_json(changed=False, policy=policy)
|
||||
except self.sdk.exceptions.ResourceNotFound:
|
||||
self.exit_json(changed=False, policy=None)
|
||||
except self.sdk.exceptions.OpenStackCloudException as ex:
|
||||
self.fail_json(msg='Failed to get RBAC policy: {0}'.format(str(ex)))
|
||||
else:
|
||||
if object_id is not None and object_type is not None:
|
||||
self.fail_json(msg='object_id and object_type are mutually exclusive, please specify one of the two.')
|
||||
if project_id is not None and target_project_id is not None:
|
||||
self.fail_json(msg='project_id and target_project_id are mutually exclusive, please specify one of the two.')
|
||||
|
||||
filtered_policies = self._get_rbac_policies()
|
||||
|
||||
if project is not None:
|
||||
filtered_policies = self._filter_policies_by(filtered_policies, 'location.project.name', project)
|
||||
if object_id is not None:
|
||||
filtered_policies = self._filter_policies_by(filtered_policies, 'object_id', object_id)
|
||||
if target_project_id is not None:
|
||||
filtered_policies = self._filter_policies_by(filtered_policies, 'target_project_id', target_project_id)
|
||||
|
||||
self.exit_json(policies=filtered_policies, changed=False)
|
||||
|
||||
|
||||
def main():
|
||||
module = NeutronRbacPoliciesInfo()
|
||||
module()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
308
plugins/modules/neutron_rbac_policy.py
Normal file
308
plugins/modules/neutron_rbac_policy.py
Normal file
@@ -0,0 +1,308 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
# Copyright: Ansible Project
|
||||
# (c) 2021, Ashraf Hasson <ahasson@redhat.com>
|
||||
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||
|
||||
DOCUMENTATION = r'''
|
||||
---
|
||||
module: neutron_rbac_policy
|
||||
short_description: Create or delete a Neutron policy to apply a RBAC rule against an object.
|
||||
author: OpenStack Ansible SIG
|
||||
description:
|
||||
- Create a policy to apply a RBAC rule against a network, security group or a QoS Policy or update/delete an existing policy.
|
||||
- If a C(policy_id) was provided but not found, this module will attempt to create a new policy rather than error out when updating an existing rule.
|
||||
- Accepts same arguments as OpenStackSDK network proxy C(find_rbac_policy) and C(rbac_policies) functions which are ultimately passed over to C(RBACPolicy)
|
||||
|
||||
options:
|
||||
policy_id:
|
||||
description:
|
||||
- The RBAC policy ID
|
||||
- Required when deleting or updating an existing RBAC policy rule, ignored otherwise
|
||||
type: str
|
||||
object_id:
|
||||
description:
|
||||
- The object ID (the subject of the policy) to which the RBAC rule applies
|
||||
- Cannot be changed when updating an existing policy
|
||||
- Required when creating a RBAC policy rule, ignored when deleting a policy
|
||||
type: str
|
||||
object_type:
|
||||
description:
|
||||
- Can be one of the following object types C(network), C(security_group) or C(qos_policy)
|
||||
- Cannot be changed when updating an existing policy
|
||||
- Required when creating a RBAC policy rule, ignored when deleting a policy
|
||||
choices: ['network', 'security_group', 'qos_policy']
|
||||
type: str
|
||||
target_project_id:
|
||||
description:
|
||||
- The project to which access to be allowed or revoked/disallowed
|
||||
- Can be specified/changed when updating an existing policy
|
||||
- Required when creating or updating a RBAC policy rule, ignored when deleting a policy
|
||||
type: str
|
||||
project_id:
|
||||
description:
|
||||
- The project to which the object_id belongs
|
||||
- Cannot be changed when updating an existing policy
|
||||
- Required when creating a RBAC policy rule, ignored when deleting a policy
|
||||
type: str
|
||||
action:
|
||||
description:
|
||||
- Can be either of the following options C(access_as_shared) | C(access_as_external)
|
||||
- Cannot be changed when updating an existing policy
|
||||
- Required when creating a RBAC policy rule, ignored when deleting a policy
|
||||
choices: ['access_as_shared', 'access_as_external']
|
||||
type: str
|
||||
state:
|
||||
description:
|
||||
- Whether the RBAC rule should be C(present) or C(absent).
|
||||
choices: ['present', 'absent']
|
||||
default: present
|
||||
type: str
|
||||
|
||||
extends_documentation_fragment:
|
||||
- openstack.cloud.openstack
|
||||
'''
|
||||
|
||||
EXAMPLES = r'''
|
||||
# Ensure network RBAC policy exists
|
||||
- name: Create a new network RBAC policy
|
||||
neutron_rbac_policy:
|
||||
object_id: '7422172b-2961-475c-ac68-bd0f2a9960ad'
|
||||
object_type: 'network'
|
||||
target_project_id: 'a12f9ce1de0645e0a0b01c2e679f69ec'
|
||||
project_id: '84b8774d595b41e89f3dfaa1fd76932d'
|
||||
|
||||
# Update network RBAC policy
|
||||
- name: Update an existing network RBAC policy
|
||||
neutron_rbac_policy:
|
||||
policy_id: 'f625242a-6a73-47ac-8d1f-91440b2c617f'
|
||||
target_project_id: '163c89e065a94e069064e551e15daf0e'
|
||||
|
||||
# Delete an existing RBAC policy
|
||||
- name: Delete RBAC policy
|
||||
openstack.cloud.openstack.neutron_rbac_policy:
|
||||
policy_id: 'f625242a-6a73-47ac-8d1f-91440b2c617f'
|
||||
state: absent
|
||||
'''
|
||||
|
||||
RETURN = r'''
|
||||
policy:
|
||||
description:
|
||||
- A hash representing the policy
|
||||
type: complex
|
||||
returned: always
|
||||
contains:
|
||||
object_id:
|
||||
description:
|
||||
- The UUID of the object to which the RBAC rules apply
|
||||
type: str
|
||||
sample: "7422172b-2961-475c-ac68-bd0f2a9960ad"
|
||||
target_project_id:
|
||||
description:
|
||||
- The UUID of the target project
|
||||
type: str
|
||||
sample: "c201a689c016435c8037977166f77368"
|
||||
project_id:
|
||||
description:
|
||||
- The UUID of the project to which access is granted
|
||||
type: str
|
||||
sample: "84b8774d595b41e89f3dfaa1fd76932c"
|
||||
object_type:
|
||||
description:
|
||||
- The object type to which the RBACs apply
|
||||
type: str
|
||||
sample: "network"
|
||||
action:
|
||||
description:
|
||||
- The access model specified by the RBAC rules
|
||||
type: str
|
||||
sample: "access_as_shared"
|
||||
id:
|
||||
description:
|
||||
- The ID of the RBAC rule/policy
|
||||
type: str
|
||||
sample: "4154ce0c-71a7-4d87-a905-09762098ddb9"
|
||||
name:
|
||||
description:
|
||||
- The name of the RBAC rule; usually null
|
||||
type: str
|
||||
sample: null
|
||||
location:
|
||||
description:
|
||||
- A dictionary of the project details to which access is granted
|
||||
type: dict
|
||||
sample: >-
|
||||
{
|
||||
"cloud": "devstack",
|
||||
"region_name": "",
|
||||
"zone": null,
|
||||
"project": {
|
||||
"id": "84b8774d595b41e89f3dfaa1fd76932c",
|
||||
"name": null,
|
||||
"domain_id": null,
|
||||
"domain_name": null
|
||||
}
|
||||
}
|
||||
'''
|
||||
|
||||
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import OpenStackModule
|
||||
|
||||
|
||||
class NeutronRbacPolicy(OpenStackModule):
|
||||
argument_spec = dict(
|
||||
policy_id=dict(),
|
||||
object_id=dict(), # ID of the object that this RBAC policy affects.
|
||||
object_type=dict(choices=['security_group', 'qos_policy', 'network']), # Type of the object that this RBAC policy affects.
|
||||
target_project_id=dict(), # The ID of the project this RBAC will be enforced.
|
||||
project_id=dict(), # The owner project ID.
|
||||
action=dict(choices=['access_as_external', 'access_as_shared']), # Action for the RBAC policy.
|
||||
state=dict(default='present', choices=['absent', 'present'])
|
||||
)
|
||||
|
||||
module_kwargs = dict(
|
||||
supports_check_mode=True,
|
||||
)
|
||||
|
||||
def _delete_rbac_policy(self, policy):
|
||||
"""
|
||||
Delete an existing RBAC policy
|
||||
returns: the "Changed" state
|
||||
"""
|
||||
|
||||
if policy is None:
|
||||
self.fail_json(msg='Must specify policy_id for delete')
|
||||
|
||||
try:
|
||||
self.conn.network.delete_rbac_policy(policy.id)
|
||||
except self.sdk.exceptions.OpenStackCloudException as ex:
|
||||
self.fail_json(msg='Failed to delete RBAC policy: {0}'.format(str(ex)))
|
||||
|
||||
return True
|
||||
|
||||
def _create_rbac_policy(self):
|
||||
"""
|
||||
Creates a new RBAC policy
|
||||
returns: the "Changed" state of the RBAC policy
|
||||
"""
|
||||
|
||||
object_id = self.params.get('object_id')
|
||||
object_type = self.params.get('object_type')
|
||||
target_project_id = self.params.get('target_project_id')
|
||||
project_id = self.params.get('project_id')
|
||||
action = self.params.get('action')
|
||||
|
||||
attributes = {
|
||||
'object_id': object_id,
|
||||
'object_type': object_type,
|
||||
'target_project_id': target_project_id,
|
||||
'project_id': project_id,
|
||||
'action': action
|
||||
}
|
||||
|
||||
if not all(attributes.values()):
|
||||
self.fail_json(msg='Missing one or more required parameter for creating a RBAC policy')
|
||||
|
||||
try:
|
||||
search_attributes = dict(attributes)
|
||||
del search_attributes['object_id']
|
||||
del search_attributes['target_project_id']
|
||||
policies = self.conn.network.rbac_policies(**search_attributes)
|
||||
for p in policies:
|
||||
if p.object_id == object_id and p.target_project_id == target_project_id:
|
||||
return (False, p)
|
||||
|
||||
# if no matching policy exists, attempt to create one
|
||||
policy = self.conn.network.create_rbac_policy(**attributes)
|
||||
except self.sdk.exceptions.OpenStackCloudException as ex:
|
||||
self.fail_json(msg='Failed to create RBAC policy: {0}'.format(str(ex)))
|
||||
|
||||
return (True, policy)
|
||||
|
||||
def _update_rbac_policy(self, policy):
|
||||
"""
|
||||
Updates an existing RBAC policy
|
||||
returns: the "Changed" state of the RBAC policy
|
||||
"""
|
||||
|
||||
object_id = self.params.get('object_id')
|
||||
object_type = self.params.get('object_type')
|
||||
target_project_id = self.params.get('target_project_id')
|
||||
project_id = self.params.get('project_id')
|
||||
action = self.params.get('action')
|
||||
|
||||
allowed_attributes = {
|
||||
'rbac_policy': policy.id,
|
||||
'target_project_id': target_project_id
|
||||
}
|
||||
|
||||
disallowed_attributes = {
|
||||
'object_id': object_id,
|
||||
'object_type': object_type,
|
||||
'project_id': project_id,
|
||||
'action': action
|
||||
}
|
||||
|
||||
if not all(allowed_attributes.values()):
|
||||
self.fail_json(msg='Missing one or more required parameter for updating a RBAC policy')
|
||||
|
||||
if any(disallowed_attributes.values()):
|
||||
self.fail_json(msg='Cannot change disallowed parameters while updating a RBAC policy: ["object_id", "object_type", "project_id", "action"]')
|
||||
|
||||
try:
|
||||
policy = self.conn.network.update_rbac_policy(**allowed_attributes)
|
||||
except self.sdk.exceptions.OpenStackCloudException as ex:
|
||||
self.fail_json(msg='Failed to update the RBAC policy: {0}'.format(str(ex)))
|
||||
|
||||
return (True, policy)
|
||||
|
||||
def _policy_state_change(self, policy):
|
||||
state = self.params['state']
|
||||
if state == 'present':
|
||||
if not policy:
|
||||
return True
|
||||
if state == 'absent' and policy:
|
||||
return True
|
||||
return False
|
||||
|
||||
def run(self):
|
||||
policy_id = self.params.get('policy_id')
|
||||
state = self.params.get('state')
|
||||
|
||||
if policy_id is not None:
|
||||
try:
|
||||
policy = self.conn.network.get_rbac_policy(policy_id)
|
||||
except self.sdk.exceptions.ResourceNotFound:
|
||||
policy = None
|
||||
except self.sdk.exceptions.OpenStackCloudException as ex:
|
||||
self.fail_json(msg='Failed to get RBAC policy: {0}'.format(str(ex)))
|
||||
else:
|
||||
policy = None
|
||||
|
||||
if self.ansible.check_mode:
|
||||
self.exit_json(changed=self._policy_state_change(policy), policy=policy)
|
||||
|
||||
if state == 'absent':
|
||||
if policy is None and policy_id:
|
||||
self.exit_json(changed=False)
|
||||
if policy_id is None:
|
||||
self.fail_json(msg='Must specify policy_id when state is absent')
|
||||
if policy is not None:
|
||||
changed = self._delete_rbac_policy(policy)
|
||||
self.exit_json(changed=changed)
|
||||
# state == 'present'
|
||||
else:
|
||||
if policy is None:
|
||||
(changed, new_policy) = self._create_rbac_policy()
|
||||
else:
|
||||
(changed, new_policy) = self._update_rbac_policy(policy)
|
||||
|
||||
self.exit_json(changed=changed, policy=new_policy)
|
||||
|
||||
|
||||
def main():
|
||||
module = NeutronRbacPolicy()
|
||||
module()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -123,6 +123,14 @@ options:
|
||||
description:
|
||||
- Binding profile dict that the port should be created with.
|
||||
type: dict
|
||||
dns_name:
|
||||
description:
|
||||
- The dns name of the port ( only with dns-integration enabled )
|
||||
type: str
|
||||
dns_domain:
|
||||
description:
|
||||
- The dns domain of the port ( only with dns-integration enabled )
|
||||
type: str
|
||||
requirements:
|
||||
- "python >= 3.6"
|
||||
- "openstacksdk"
|
||||
@@ -302,7 +310,9 @@ class NetworkPortModule(OpenStackModule):
|
||||
choices=['normal', 'direct', 'direct-physical',
|
||||
'macvtap', 'baremetal', 'virtio-forwarder']),
|
||||
port_security_enabled=dict(default=None, type='bool'),
|
||||
binding_profile=dict(default=None, type='dict')
|
||||
binding_profile=dict(default=None, type='dict'),
|
||||
dns_name=dict(type='str', default=None),
|
||||
dns_domain=dict(type='str', default=None)
|
||||
)
|
||||
|
||||
module_kwargs = dict(
|
||||
@@ -312,6 +322,13 @@ class NetworkPortModule(OpenStackModule):
|
||||
supports_check_mode=True
|
||||
)
|
||||
|
||||
def _is_dns_integration_enabled(self):
|
||||
""" Check if dns-integraton is enabled """
|
||||
for ext in self.conn.network.extensions():
|
||||
if ext.alias == 'dns-integration':
|
||||
return True
|
||||
return False
|
||||
|
||||
def _needs_update(self, port):
|
||||
"""Check for differences in the updatable values.
|
||||
|
||||
@@ -324,10 +341,18 @@ class NetworkPortModule(OpenStackModule):
|
||||
'binding:vnic_type',
|
||||
'port_security_enabled',
|
||||
'binding:profile']
|
||||
compare_dns = ['dns_name', 'dns_domain']
|
||||
compare_list_dict = ['allowed_address_pairs',
|
||||
'extra_dhcp_opts']
|
||||
compare_list = ['security_groups']
|
||||
|
||||
if self.conn.has_service('dns') and \
|
||||
self._is_dns_integration_enabled():
|
||||
for key in compare_dns:
|
||||
if self.params[key] is not None and \
|
||||
self.params[key] != port[key]:
|
||||
return True
|
||||
|
||||
for key in compare_simple:
|
||||
if self.params[key] is not None and self.params[key] != port[key]:
|
||||
return True
|
||||
@@ -340,11 +365,11 @@ class NetworkPortModule(OpenStackModule):
|
||||
|
||||
for key in compare_list_dict:
|
||||
if not self.params[key]:
|
||||
if port[key]:
|
||||
if port.get(key):
|
||||
return True
|
||||
|
||||
if self.params[key]:
|
||||
if not port[key]:
|
||||
if not port.get(key):
|
||||
return True
|
||||
|
||||
# sort dicts in list
|
||||
@@ -410,6 +435,11 @@ class NetworkPortModule(OpenStackModule):
|
||||
'binding:vnic_type',
|
||||
'port_security_enabled',
|
||||
'binding:profile']
|
||||
|
||||
if self.conn.has_service('dns') and \
|
||||
self._is_dns_integration_enabled():
|
||||
optional_parameters.extend(['dns_name', 'dns_domain'])
|
||||
|
||||
for optional_param in optional_parameters:
|
||||
if self.params[optional_param] is not None:
|
||||
port_kwargs[optional_param] = self.params[optional_param]
|
||||
@@ -473,12 +503,14 @@ class NetworkPortModule(OpenStackModule):
|
||||
msg="Specified network was not found."
|
||||
)
|
||||
|
||||
port = self.conn.create_port(network_id, **port_kwargs)
|
||||
port_kwargs['network_id'] = network_id
|
||||
port = self.conn.network.create_port(**port_kwargs)
|
||||
changed = True
|
||||
else:
|
||||
if self._needs_update(port):
|
||||
port_kwargs = self._compose_port_args()
|
||||
port = self.conn.update_port(port['id'], **port_kwargs)
|
||||
port = self.conn.network.update_port(port['id'],
|
||||
**port_kwargs)
|
||||
changed = True
|
||||
self.exit_json(changed=changed, id=port['id'], port=port)
|
||||
|
||||
|
||||
@@ -69,6 +69,9 @@ options:
|
||||
loadbalancer:
|
||||
description: Number of load balancers to allow.
|
||||
type: int
|
||||
metadata_items:
|
||||
description: Number of metadata items allowed per instance.
|
||||
type: int
|
||||
network:
|
||||
description: Number of networks to allow.
|
||||
type: int
|
||||
@@ -183,6 +186,7 @@ EXAMPLES = '''
|
||||
instances: "{{ item.instances }}"
|
||||
key_pairs: "{{ item.key_pairs }}"
|
||||
loadbalancer: "{{ item.loadbalancer }}"
|
||||
metadata_items: "{{ item.metadata_items }}"
|
||||
per_volume_gigabytes: "{{ item.per_volume_gigabytes }}"
|
||||
pool: "{{ item.pool }}"
|
||||
port: "{{ item.port }}"
|
||||
@@ -277,6 +281,7 @@ class QuotaModule(OpenStackModule):
|
||||
instances=dict(required=False, type='int', default=None),
|
||||
key_pairs=dict(required=False, type='int', default=None, no_log=False),
|
||||
loadbalancer=dict(required=False, type='int', default=None),
|
||||
metadata_items=dict(required=False, type='int', default=None),
|
||||
network=dict(required=False, type='int', default=None),
|
||||
per_volume_gigabytes=dict(required=False, type='int', default=None),
|
||||
pool=dict(required=False, type='int', default=None),
|
||||
|
||||
@@ -89,6 +89,9 @@ class ServerVolumeModule(OpenStackModule):
|
||||
server = self.conn.get_server(self.params['server'])
|
||||
volume = self.conn.get_volume(self.params['volume'])
|
||||
|
||||
if not server:
|
||||
self.fail(msg='server %s is not found' % self.params['server'])
|
||||
|
||||
if not volume:
|
||||
self.fail(msg='volume %s is not found' % self.params['volume'])
|
||||
|
||||
|
||||
11
test-requirements-2.12.txt
Normal file
11
test-requirements-2.12.txt
Normal file
@@ -0,0 +1,11 @@
|
||||
openstacksdk
|
||||
ansible-core
|
||||
pycodestyle
|
||||
flake8
|
||||
pylint
|
||||
voluptuous
|
||||
yamllint
|
||||
rstcheck
|
||||
ruamel.yaml
|
||||
#galaxy-importer # see https://review.opendev.org/#/c/743054
|
||||
tox
|
||||
0
tests/sanity/ignore-2.13.txt
Normal file
0
tests/sanity/ignore-2.13.txt
Normal file
12
tox.ini
12
tox.ini
@@ -65,6 +65,12 @@ commands = {[testenv:linters]commands}
|
||||
deps =
|
||||
-r{toxinidir}/test-requirements-2.11.txt
|
||||
|
||||
[testenv:linters-2.12]
|
||||
passenv = {[testenv:linters]passenv}
|
||||
commands = {[testenv:linters]commands}
|
||||
deps =
|
||||
-r{toxinidir}/test-requirements-2.12.txt
|
||||
|
||||
[testenv:venv]
|
||||
deps =
|
||||
-r{toxinidir}/test-requirements.txt
|
||||
@@ -112,6 +118,12 @@ deps =
|
||||
passenv = {[testenv:ansible]passenv}
|
||||
commands = {[testenv:ansible]commands}
|
||||
|
||||
[testenv:ansible-2.12]
|
||||
deps =
|
||||
-r{toxinidir}/test-requirements-2.12.txt
|
||||
passenv = {[testenv:ansible]passenv}
|
||||
commands = {[testenv:ansible]commands}
|
||||
|
||||
[testenv:galaxy-release]
|
||||
deps =
|
||||
ansible-core
|
||||
|
||||
Reference in New Issue
Block a user