mirror of
https://opendev.org/openstack/ansible-collections-openstack.git
synced 2026-03-27 14:03:03 +00:00
Compare commits
18 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
617e8fb552 | ||
|
|
5abf89d805 | ||
|
|
0599d05103 | ||
|
|
9c28af7d12 | ||
|
|
bcb5d18492 | ||
|
|
7aa626377b | ||
|
|
0a7889b9a2 | ||
|
|
a1b920742f | ||
|
|
bd55e1f905 | ||
|
|
20329c0329 | ||
|
|
bdf472a53f | ||
|
|
b7fb23b097 | ||
|
|
6ed02eff2d | ||
|
|
cb396cf03d | ||
|
|
20c2633ea3 | ||
|
|
6569e07023 | ||
|
|
031475d42e | ||
|
|
5e2ab3d8c3 |
79
.zuul.yaml
79
.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
|
||||
@@ -23,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
|
||||
@@ -57,6 +63,7 @@
|
||||
octavia: https://opendev.org/openstack/octavia
|
||||
devstack_services:
|
||||
designate: true
|
||||
neutron-dns: true
|
||||
octavia: true
|
||||
o-api: true
|
||||
o-cw: true
|
||||
@@ -114,6 +121,13 @@
|
||||
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
|
||||
@@ -292,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.*$
|
||||
@@ -310,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
|
||||
@@ -354,6 +409,8 @@
|
||||
- openstack-tox-linters-ansible-2.9
|
||||
- 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:
|
||||
@@ -380,13 +437,21 @@
|
||||
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
|
||||
@@ -400,7 +465,7 @@
|
||||
- ansible-collections-openstack-functional-devstack-xena-ansible-2.12
|
||||
- ansible-collections-openstack-functional-devstack-train-ansible-2.11
|
||||
- ansible-collections-openstack-functional-devstack-octavia
|
||||
- tripleo-ci-centos-8-standalone-osa
|
||||
- tripleo-ci-centos-8-standalone-wallaby-osa
|
||||
|
||||
periodic:
|
||||
jobs:
|
||||
@@ -420,6 +485,10 @@
|
||||
- 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:
|
||||
|
||||
@@ -5,6 +5,34 @@ 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
|
||||
======
|
||||
|
||||
|
||||
@@ -283,3 +283,24 @@ releases:
|
||||
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 }}"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -41,9 +41,6 @@
|
||||
- { 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.6.0
|
||||
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
|
||||
|
||||
@@ -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:
|
||||
@@ -363,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'):
|
||||
|
||||
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()
|
||||
@@ -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)
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user