12 Commits
2.0.0 ... 2.1.0

Author SHA1 Message Date
Jakob Meng
c30e4db77c Publish 2.1.0 release
Change-Id: I142f14dd35720557539b9cf3489a3c12c31f342a
2023-04-18 08:46:14 +02:00
Jakob Meng
ab6f2e45c6 Change security group rules only when instructed to do so
Security group rules in module openstack.cloud.security_group
are changed/updated only when option 'security_group_rules' was
defined explicitly. This follows our policy of "apply no change"
when module options in our Ansible modules have not been set.

Story: 2010691
Task: 47795
Change-Id: I4a0cda46cb160b5321913b63ff1123d8b8a19705
2023-04-18 08:39:57 +02:00
Zuul
568adcb890 Merge "Add baremetal_deploy_template module" 2023-04-17 23:37:52 +00:00
Jakob Meng
18cf839db4 Highlight our mode of operation more prominently
Change-Id: I23d9f390ffbe2c67ebca4e114c9d417a8bd2065e
2023-03-30 10:02:46 +02:00
Mark Goddard
454a05452b Add baremetal_deploy_template module
This module supports managing deploy template resources in OpenStack
Ironic.

https: //docs.openstack.org/ironic/latest/admin/node-deployment.html#deploy-templates

Change-Id: I2d1b89e7cbd1a7e847f54ffd62778f953ba65863
2023-03-28 12:05:38 +00:00
Dmitriy Rabotyagov
ad9594dcd7 Fix mistake in compute_flavor_access notes
In order to execute addTenantAccess or removeTenantAccess
a flavor should have have is_public set to false, which means it must
be private.

Change-Id: Iea1c4e7167b7134a4f70a4fb44fc0a8676265419
2023-03-14 18:43:35 +01:00
Jakob Meng
62c0169e64 Fixed private option in inventory plugin
Story: 2010614
Task: 47538
Change-Id: I64e1b3ce5323ca8e351ee9faef4bddbef53dfd5d
2023-03-06 21:07:23 +01:00
Christian Kueppers
497f020100 Fix for AttributeError: 'dict' object has no attribute 'status'.
Story: 2010610
Task: 47505
Change-Id: I9e138d8f282de9adfb3d7e1142c10ab77c22578e
2023-03-05 09:41:42 +00:00
Jakob Meng
92c3e87467 Respect description option and delete security group rules first
The description option of security group rules will now be used properly
when creating new rules.

Security group rules have to be deleted first before new ones get
created, because if one changes one rule attribute such as its
description, then the old rule must be deleted before recreating it,
as rules cannot be updated.

Story: 2010605
Task: 47486

Change-Id: I75b900e6675f7ec33532089738a6c2bfc10a898b
2023-02-23 21:20:51 +01:00
Jakob Meng
f73a0e385e Use true and false instead of yes and no for boolean values
Story: 2010586
Task: 47380
Change-Id: I1b88aa925d823d74b2d012153dfe26d35c93dfd5
2023-02-21 13:07:29 +01:00
Jakob Meng
b6b5f63877 Do not hardcode image name and properly delete mock images in CI tests
Change-Id: I2962dd1d1c27989cbd135b051cfb3e9f8c9e3823
2023-02-21 13:06:44 +01:00
Sagi Shnaidman
edd4e1b2e9 Fix issue with multiple records in recordset
Story: #2010527
Task: #47136

Sort records in recordset so it can be compared to existing ones
and not to trigger update in case of a different order.

Change-Id: Ib5d2af56616532174c29ec2be86827ccd0a17940
2023-02-01 21:26:26 +02:00
41 changed files with 484 additions and 103 deletions

View File

@@ -5,6 +5,31 @@ Ansible OpenStack Collection Release Notes
.. contents:: Topics
v2.1.0
======
Release Summary
---------------
New module for Ironic and bugfixes
Minor Changes
-------------
- Add baremetal_deploy_template module
- Highlight our mode of operation more prominently
Bugfixes
--------
- Change security group rules only when instructed to do so
- Fix for AttributeError: 'dict' object has no attribute 'status'
- Fix issue with multiple records in recordset
- Fix mistake in compute_flavor_access notes
- Fixed private option in inventory plugin
- Respect description option and delete security group rules first
- Use true and false instead of yes and no for boolean values
v2.0.0
======

View File

@@ -6,6 +6,12 @@ http://zuul.opendev.org/t/openstack/builds?project=openstack%2Fansible-collectio
Ansible OpenStack collection aka `openstack.cloud` provides Ansible modules and Ansible plugins for managing OpenStack
clouds. It is supported and maintained by the OpenStack community.
**NOTE:** We need and value your contributions! Maintaining this collection is a community effort. We are all both users
and developers of this collection at the same time. If you find a bug, please report it. If you have fixed a bug, please
submit a patch. If you need new functionality which is not covered by this collection yet, please extend an existing
module or submit a new one. Our [Contributing](#contributing) section below has tons of docs to check out. Please get in
touch!
## Branches and Non Backward Compatibility ⚠️
Our codebase has been split into two separate release series, `2.x.x` and `1.x.x`:
@@ -216,8 +222,7 @@ docs/reviewing.md) (⚠️) before sending your first patch. Pull requests submi
## Communication
We have a Special Interest Group for the Ansible OpenStack collection. Join us in `#openstack-ansible-sig` on
[OFTC IRC](https://www.oftc.net/) and ping Artem Goncharov <artem.goncharov@gmail.com> (gtema), Jakob Meng
<mail@jakobmeng.de> (jm1) or Sagi Shnaidman <sshnaidm@redhat.com> (sshnaidm) 🍪
[OFTC IRC](https://www.oftc.net/) 🍪
## License

View File

@@ -500,3 +500,18 @@ releases:
directory which could be used to generate and develop new Ansible modules
for this collection have been removed.
release_date: '2023-01-31'
2.1.0:
changes:
bugfixes:
- Change security group rules only when instructed to do so
- 'Fix for AttributeError: ''dict'' object has no attribute ''status'''
- Fix issue with multiple records in recordset
- Fix mistake in compute_flavor_access notes
- Fixed private option in inventory plugin
- Respect description option and delete security group rules first
- Use true and false instead of yes and no for boolean values
minor_changes:
- Add baremetal_deploy_template module
- Highlight our mode of operation more prominently
release_summary: New module for Ironic and bugfixes
release_date: '2023-04-19'

View File

@@ -0,0 +1,7 @@
expected_fields:
- created_at
- extra
- id
- name
- steps
- updated_at

View File

@@ -0,0 +1,58 @@
---
# TODO: Actually run this role in CI. Atm we do not have DevStack's ironic plugin enabled.
- name: Create baremetal deploy template
openstack.cloud.baremetal_deploy_template:
cloud: "{{ cloud }}"
state: present
name: CUSTOM_ANSIBLE_DEPLOY_TEMPLATE
steps:
- interface: bios
step: apply_configuration
args:
settings:
- name: some-setting
value: some-value
priority: 110
register: template
- debug: var=template
- name: Assert return values of baremetal_deploy_template module
assert:
that:
# allow new fields to be introduced but prevent fields from being removed
- expected_fields|difference(template.template.keys())|length == 0
- name: Update baremetal deploy template
openstack.cloud.baremetal_deploy_template:
cloud: "{{ cloud }}"
state: present
id: "{{ template.template.id }}"
extra:
foo: bar
register: updated_template
- name: Assert return values of updated baremetal deploy template
assert:
that:
- updated_template is changed
- updated_template.template.id == template.template.id
- name: Update baremetal deploy template again
openstack.cloud.baremetal_deploy_template:
cloud: "{{ cloud }}"
state: present
id: "{{ template.template.id }}"
register: updated_template
- name: Assert return values of updated baremetal deploy template
assert:
that:
- updated_template is not changed
- updated_template.template.id == template.template.id
- name: Delete Bare Metal deploy template
openstack.cloud.baremetal_deploy_template:
cloud: "{{ cloud }}"
state: absent
id: "{{ template.template.id }}"

View File

@@ -19,7 +19,7 @@
name: '{{ mapping_name }}'
rules: '{{ mapping_rules_1 }}'
register: create_mapping
check_mode: yes
check_mode: true
- assert:
that:
@@ -91,7 +91,7 @@
name: '{{ mapping_name }}'
rules: '{{ mapping_rules_1 }}'
register: create_mapping
check_mode: yes
check_mode: true
- assert:
that:
@@ -117,7 +117,7 @@
name: '{{ mapping_name }}'
rules: '{{ mapping_rules_2 }}'
register: update_mapping
check_mode: yes
check_mode: true
- assert:
that:
@@ -196,7 +196,7 @@
state: 'absent'
name: '{{ mapping_name }}'
register: delete_mapping
check_mode: yes
check_mode: true
- assert:
that:
@@ -217,7 +217,7 @@
state: 'absent'
name: '{{ mapping_name }}'
register: delete_mapping
check_mode: yes
check_mode: true
- assert:
that:
@@ -257,10 +257,10 @@
openstack.cloud.federation_mapping:
state: 'absent'
name: '{{ mapping_name }}'
ignore_errors: yes
ignore_errors: true
- name: 'Delete second mapping'
openstack.cloud.federation_mapping:
state: 'absent'
name: '{{ mapping_name_2 }}'
ignore_errors: yes
ignore_errors: true

View File

@@ -214,7 +214,7 @@
cloud: "{{ cloud }}"
state: present
server: ansible_server1
wait: yes
wait: true
- name: Get floating ip attached to server 1
openstack.cloud.floating_ip_info:
@@ -302,7 +302,7 @@
openstack.cloud.floating_ip:
cloud: "{{ cloud }}"
state: present
reuse: no # else fixed_address will be ignored
reuse: false # else fixed_address will be ignored
server: ansible_server2
network: public
fixed_address: "{{ port2.port.fixed_ips[0].ip_address }}"
@@ -347,12 +347,12 @@
openstack.cloud.floating_ip:
cloud: "{{ cloud }}"
state: present
reuse: no # else fixed_address will be ignored
reuse: false # else fixed_address will be ignored
server: ansible_server2
network: ansible_external
fixed_address: "{{ port3.port.fixed_ips[0].ip_address }}"
floating_ip_address: "10.6.6.150"
wait: no # does not work anyway and causes issues in local testing
wait: false # does not work anyway and causes issues in local testing
- name: Get floating ip attached to server 2
openstack.cloud.floating_ip_info:

View File

@@ -28,7 +28,7 @@
domain: default
default_project: demo
register: user
ignore_errors: yes
ignore_errors: true
- name: Assert that update failed
assert:
@@ -93,7 +93,7 @@
update_password: always
email: updated.ansible.user@nowhere.net
register: user
ignore_errors: yes
ignore_errors: true
- name: Assert user update failed
assert:

View File

@@ -318,6 +318,15 @@
name: ansible_project
domain: default
- name: Delete mock kernel and ramdisk images
openstack.cloud.image:
cloud: "{{ cloud }}"
state: absent
name: "{{ item }}"
loop:
- cirros-vmlinuz
- cirros-initrd
- name: Delete test image file
file:
name: "{{ tmp_file.path }}"

View File

@@ -78,7 +78,7 @@
- name: Generate test key file
user:
name: "{{ ansible_env.USER }}"
generate_ssh_key: yes
generate_ssh_key: true
ssh_key_file: .ssh/shade_id_rsa
- name: Create keypair (file)

View File

@@ -78,7 +78,7 @@
# Creation
- name: Create protocol - CHECK MODE
check_mode: yes
check_mode: true
openstack.cloud.keystone_federation_protocol:
state: present
name: ansible_protocol1
@@ -119,7 +119,7 @@
- expected_fields|difference(protocol.protocol.keys())|length == 0
- name: Create protocol (retry - no change) - CHECK MODE
check_mode: yes
check_mode: true
openstack.cloud.keystone_federation_protocol:
state: present
name: ansible_protocol1
@@ -148,7 +148,7 @@
# Update
- name: Update protocol - CHECK MODE
check_mode: yes
check_mode: true
openstack.cloud.keystone_federation_protocol:
state: present
name: ansible_protocol1
@@ -174,7 +174,7 @@
- protocol.protocol.mapping_id == 'ansible_mapping2'
- name: Update protocol (retry - no change) - CHECK MODE
check_mode: yes
check_mode: true
openstack.cloud.keystone_federation_protocol:
state: present
name: ansible_protocol1
@@ -258,7 +258,7 @@
# Deletion
- name: Delete protocol - CHECK MODE
check_mode: yes
check_mode: true
openstack.cloud.keystone_federation_protocol:
state: absent
name: ansible_protocol1
@@ -279,7 +279,7 @@
- protocol is changed
- name: Delete protocol (retry - no change) - CHECK MODE
check_mode: yes
check_mode: true
openstack.cloud.keystone_federation_protocol:
state: absent
name: ansible_protocol1
@@ -307,35 +307,35 @@
state: absent
name: ansible_protocol1
idp_id: ansible_idp
ignore_errors: yes
ignore_errors: true
- name: Delete protocol (2)
openstack.cloud.keystone_federation_protocol:
state: absent
name: ansible_protocol2
idp_id: ansible_idp
ignore_errors: yes
ignore_errors: true
- name: Delete mapping 1
openstack.cloud.federation_mapping:
state: absent
name: ansible_mapping1
ignore_errors: yes
ignore_errors: true
- name: Delete mapping 2
openstack.cloud.federation_mapping:
state: absent
name: ansible_mapping2
ignore_errors: yes
ignore_errors: true
- name: Delete idp
openstack.cloud.federation_idp:
state: absent
name: ansible_idp
ignore_errors: yes
ignore_errors: true
- name: Delete domain
openstack.cloud.identity_domain:
state: absent
name: ansible_domain
ignore_errors: yes
ignore_errors: true

View File

@@ -116,7 +116,7 @@
_idps: '{{ idps.identity_providers }}'
- name: 'Create identity_provider (retry - no change) - CHECK_MODE'
check_mode: yes
check_mode: true
openstack.cloud.federation_idp:
state: present
name: 'ansible_identity_provider'
@@ -150,7 +150,7 @@
# Update (simple cases)
- name: 'Update IDP set description - CHECK_MODE'
check_mode: yes
check_mode: true
openstack.cloud.federation_idp:
state: present
name: 'ansible_identity_provider'
@@ -181,7 +181,7 @@
_idp: '{{ idp.identity_provider }}'
- name: 'Update IDP set description (retry - no change) - CHECK_MODE'
check_mode: yes
check_mode: true
openstack.cloud.federation_idp:
state: present
name: 'ansible_identity_provider'
@@ -213,7 +213,7 @@
- name: 'Update IDP set Remote IDs - CHECK_MODE'
check_mode: yes
check_mode: true
openstack.cloud.federation_idp:
state: present
name: 'ansible_identity_provider'
@@ -244,7 +244,7 @@
_idp: '{{ idp.identity_provider }}'
- name: 'Update IDP set Remote IDs (retry - no change) - CHECK_MODE'
check_mode: yes
check_mode: true
openstack.cloud.federation_idp:
state: present
name: 'ansible_identity_provider'
@@ -275,7 +275,7 @@
_idp: '{{ idp.identity_provider }}'
- name: 'Update IDP set Enabled - CHECK_MODE'
check_mode: yes
check_mode: true
openstack.cloud.federation_idp:
state: present
name: 'ansible_identity_provider'
@@ -306,7 +306,7 @@
_idp: '{{ idp.identity_provider }}'
- name: 'Update IDP set Enabled (retry - no change) - CHECK_MODE'
check_mode: yes
check_mode: true
openstack.cloud.federation_idp:
state: present
name: 'ansible_identity_provider'
@@ -338,7 +338,7 @@
# If we don't specify anything to change, then nothing should change...
- name: 'Minimal call to IDP (no change) - CHECK_MODE'
check_mode: yes
check_mode: true
openstack.cloud.federation_idp:
state: present
name: 'ansible_identity_provider'
@@ -371,7 +371,7 @@
# Update (mass-update)
- name: 'Update all updatable IDP parameters - CHECK_MODE'
check_mode: yes
check_mode: true
openstack.cloud.federation_idp:
state: present
name: 'ansible_identity_provider'
@@ -406,7 +406,7 @@
_idp: '{{ idp.identity_provider }}'
- name: 'Update all updatable IDP parameters (no change) - CHECK_MODE'
check_mode: yes
check_mode: true
openstack.cloud.federation_idp:
state: present
name: 'ansible_identity_provider'
@@ -444,7 +444,7 @@
# Create complex IDP
- name: 'Create complex IDP - CHECK_MODE'
check_mode: yes
check_mode: true
openstack.cloud.federation_idp:
state: present
name: 'ansible_identity_provider2'
@@ -481,7 +481,7 @@
_idp: '{{ idp.identity_provider }}'
- name: 'Create complex IDP (retry - no change) - CHECK_MODE'
check_mode: yes
check_mode: true
openstack.cloud.federation_idp:
state: present
name: 'ansible_identity_provider2'
@@ -558,7 +558,7 @@
- False in (idps.identity_providers | map(attribute='is_enabled'))
- name: 'Delete identity_provider - CHECK_MODE'
check_mode: yes
check_mode: true
openstack.cloud.federation_idp:
state: absent
name: 'ansible_identity_provider'
@@ -579,7 +579,7 @@
- idp is changed
- name: 'Delete identity_provider (retry - no change) - CHECK_MODE'
check_mode: yes
check_mode: true
openstack.cloud.federation_idp:
state: absent
name: 'ansible_identity_provider'

View File

@@ -23,7 +23,7 @@
- name: Check output of network info
# TODO: Remove ignore_errors once SDK's search_networks() (re)implemented searching by id
ignore_errors: yes
ignore_errors: true
assert:
that:
- result.networks|length == 1

View File

@@ -90,4 +90,4 @@
cloud: "{{ cloud }}"
state: absent
name: ansible_container2
delete_with_all_objects: yes
delete_with_all_objects: true

View File

@@ -169,7 +169,7 @@
- ip_address: 10.5.5.69
name: "{{ port_name }}"
network: "{{ network_name }}"
no_security_groups: yes
no_security_groups: true
state: present
register: port
@@ -192,7 +192,7 @@
subnet_id: "{{ subnet.subnet.id }}"
name: "{{ port_name }}"
network: "{{ network_name }}"
no_security_groups: yes
no_security_groups: true
state: present
register: port_again

View File

@@ -1,7 +1,7 @@
dns_zone_name: test.dns.zone.
recordset_name: testrecordset.test.dns.zone.
records: ['10.0.0.0']
updated_records: ['10.1.1.1']
records: ['10.0.0.0', '10.0.0.2']
updated_records: ['10.1.1.1', '10.0.0.2']
recordset_fields:
- action

View File

@@ -29,7 +29,7 @@
- recordset is changed
- recordset["recordset"].name == recordset_name
- recordset["recordset"].zone_name == dns_zone.zone.name
- recordset["recordset"].records == records
- recordset["recordset"].records | list | sort == records | list | sort
- name: Assert recordset fields
assert:
@@ -71,7 +71,7 @@
- recordset is changed
- recordset["recordset"].zone_name == dns_zone.zone.name
- recordset["recordset"].name == recordset_name
- recordset["recordset"].records == updated_records
- recordset["recordset"].records | list | sort == updated_records | list | sort
- name: Assert recordset fields
assert:

View File

@@ -32,7 +32,9 @@
- name: Assert return values of security_group_rule_info module
assert:
that:
- security_group_rules.security_group_rules | length == 0
- security_group_rules.security_group_rules | length in [1, 2]
- security_group_rules.security_group_rules | map(attribute='ether_type') | list | sort in
[['IPv4'], ['IPv6'], ['IPv4', 'IPv6']]
- name: Delete security group
openstack.cloud.security_group:
@@ -58,6 +60,47 @@
that:
- security_group is not changed
- name: Create security group without security group rules
openstack.cloud.security_group:
cloud: "{{ cloud }}"
name: ansible_security_group
security_group_rules: []
register: security_group
- name: Assert return values of security_group module
assert:
that:
- security_group is changed
- name: Create security group without security group rules again
openstack.cloud.security_group:
cloud: "{{ cloud }}"
name: ansible_security_group
security_group_rules: []
register: security_group
- name: Assert return values of security_group module
assert:
that:
- security_group is not changed
- name: Fetch security group rules
openstack.cloud.security_group_rule_info:
cloud: "{{ cloud }}"
security_group: ansible_security_group
register: security_group_rules
- name: Assert return values of security_group_rule_info module
assert:
that:
- security_group_rules.security_group_rules | length == 0
- name: Delete security group without security group rules
openstack.cloud.security_group:
cloud: "{{ cloud }}"
name: ansible_security_group
state: absent
- name: Create security group including security group rules
openstack.cloud.security_group:
cloud: "{{ cloud }}"
@@ -263,10 +306,11 @@
name: ansible_security_group
state: absent
- name: Create security group
- name: Create security group without security group rules
openstack.cloud.security_group:
cloud: "{{ cloud }}"
name: ansible_security_group
security_group_rules: []
state: present
register: security_group

View File

@@ -224,7 +224,7 @@
register: info
# TODO: Drop ignore_errors once openstacksdk's bug #2010135 has been solved.
# Ref.: https://storyboard.openstack.org/#!/story/2010135
ignore_errors: yes
ignore_errors: true
- name: Check info about server image name
assert:
@@ -232,7 +232,7 @@
- info.servers[0].image.name == image_name
# TODO: Drop ignore_errors once openstacksdk's bug #2010135 has been solved.
# Ref.: https://storyboard.openstack.org/#!/story/2010135
ignore_errors: yes
ignore_errors: true
- name: Delete server (FIP from pool/network)
openstack.cloud.server:
@@ -375,7 +375,7 @@
state: present
name: "{{ server_port }}"
network: "{{ server_network }}"
no_security_groups: yes
no_security_groups: true
fixed_ips:
- ip_address: 192.168.0.42
register: port
@@ -555,7 +555,7 @@
- name: Delete updated server
openstack.cloud.server:
cloud: "{{ cloud }}"
delete_ips: yes
delete_ips: true
name: "{{ server_name }}"
state: absent
wait: true

View File

@@ -1,9 +1,21 @@
---
- name: List all images
openstack.cloud.image_info:
cloud: "{{ cloud }}"
register: images
- name: Identify CirrOS image name
set_fact:
image_name: "{{ images.images|community.general.json_query(query)|first }}"
vars:
query: "[?starts_with(name, 'cirros')].name"
- name: Create server
openstack.cloud.server:
cloud: "{{ cloud }}"
state: present
name: "{{ server_name }}"
image: "cirros-0.5.2-x86_64-disk"
image: "{{ image_name }}"
flavor: "{{ flavor_name }}"
network: "{{ server_network }}"
auto_ip: false

View File

@@ -32,4 +32,4 @@ build_ignore:
- .vscode
- ansible_collections_openstack.egg-info
- changelogs
version: 2.0.0
version: 2.1.0

View File

@@ -3,6 +3,7 @@ action_groups:
openstack:
- address_scope
- auth
- baremetal_deploy_template
- baremetal_inspect
- baremetal_node
- baremetal_node_action

View File

@@ -46,7 +46,7 @@ options:
description:
- Should ansible wait until the requested resource is complete.
type: bool
default: yes
default: true
timeout:
description:
- How long should ansible wait for the requested resource.
@@ -60,7 +60,7 @@ options:
validate_certs:
description:
- Whether or not SSL API requests should be verified.
- Before Ansible 2.3 this defaulted to C(yes).
- Before Ansible 2.3 this defaulted to C(true).
type: bool
aliases: [ verify ]
ca_cert:

View File

@@ -293,10 +293,6 @@ class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable):
clouds = [openstack.connection.Connection(config=cloud_region)
for cloud_region in cloud_regions]
if self.get_option('private'):
for cloud in self.clouds:
cloud.private = True
self.display.vvvv(
'Found {0} OpenStack cloud(s)'
.format(len(clouds)))
@@ -393,7 +389,7 @@ class InventoryModule(BaseInventoryPlugin, Constructable, Cacheable):
if address['OS-EXT-IPS:type'] == 'fixed'),
None)
ip = floating_ip if floating_ip is not None else fixed_ip
ip = floating_ip if floating_ip is not None and not self.get_option('private') else fixed_ip
if ip is not None:
host_vars['ansible_ssh_host'] = ip

View File

@@ -40,7 +40,7 @@ options:
description:
- Whether this address scope is shared or not.
type: bool
default: 'no'
default: 'false'
aliases: ['shared']
extra_specs:
description:

View File

@@ -0,0 +1,198 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
# Copyright (c) 2023 StackHPC Ltd.
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
DOCUMENTATION = r'''
module: baremetal_deploy_template
short_description: Create/Delete Bare Metal deploy template Resources from OpenStack
author: OpenStack Ansible SIG
description:
- Create, Update and Remove ironic deploy templates from OpenStack.
options:
extra:
description:
- A set of one or more arbitrary metadata key and value pairs.
type: dict
id:
description:
- ID of the deploy template.
- Will be auto-generated if not specified.
type: str
aliases: ['uuid']
name:
description:
- Name of the deploy template.
- Must be formatted as a trait name (see API reference).
- Required when the deploy template is created, after which the
name or ID may be used.
type: str
steps:
description:
- List of deploy steps to apply.
- Required when the deploy template is created.
type: list
elements: dict
state:
description:
- Indicates desired state of the resource
choices: ['present', 'absent']
default: present
type: str
extends_documentation_fragment:
- openstack.cloud.openstack
'''
EXAMPLES = r'''
- name: Create Bare Metal deploy template
openstack.cloud.baremetal_deploy_template:
cloud: devstack
state: present
name: CUSTOM_FOO
steps:
- interface: bios
step: apply_configuration
args:
settings:
- name: LogicalProc
value: Enabled
priority: 110
extra:
something: extra
register: result
- name: Delete Bare Metal deploy template
openstack.cloud.baremetal_deploy_template:
cloud: devstack
state: absent
id: 1a85ebca-22bf-42eb-ad9e-f640789b8098
register: result
- name: Update Bare Metal deploy template
openstack.cloud.baremetal_deploy_template:
cloud: devstack
state: present
id: 1a85ebca-22bf-42eb-ad9e-f640789b8098
extra:
something: new
'''
RETURN = r'''
template:
description: A deploy template dictionary, subset of the dictionary keys
listed below may be returned, depending on your cloud
provider.
returned: success
type: dict
contains:
created_at:
description: Bare Metal deploy template 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 Deploy Template resource.
returned: success
type: str
links:
description: A list of relative links, including the self and
bookmark links.
returned: success
type: list
location:
description: Cloud location of this resource (cloud, project,
region, zone)
returned: success
type: dict
name:
description: Bare Metal deploy template name.
returned: success
type: str
steps:
description: A list of deploy steps.
returned: success
type: list
elements: dict
updated_at:
description: Bare Metal deploy template updated at timestamp.
returned: success
type: str
'''
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import (
OpenStackModule
)
class BaremetalDeployTemplateModule(OpenStackModule):
argument_spec = dict(
extra=dict(type='dict'),
id=dict(aliases=['uuid']),
name=dict(),
steps=dict(type='list', elements='dict'),
state=dict(default='present', choices=['present', 'absent']),
)
module_kwargs = dict(
required_one_of=[
('id', 'name'),
],
)
def run(self):
template = self._find_deploy_template()
state = self.params['state']
if state == 'present':
# create or update deploy template
kwargs = {}
for k in ['extra', 'id', 'name', 'steps']:
if self.params[k] is not None:
kwargs[k] = self.params[k]
changed = True
if not template:
# create deploy template
template = self.conn.baremetal.create_deploy_template(**kwargs)
else:
# update deploy template
updates = dict((k, v)
for k, v in kwargs.items()
if v != template[k])
if updates:
template = \
self.conn.baremetal.update_deploy_template(template['id'], **updates)
else:
changed = False
self.exit_json(changed=changed, template=template.to_dict(computed=False))
if state == 'absent':
# remove deploy template
if not template:
self.exit_json(changed=False)
template = self.conn.baremetal.delete_deploy_template(template['id'])
self.exit_json(changed=True)
def _find_deploy_template(self):
id_or_name = self.params['id'] if self.params['id'] else self.params['name']
try:
return self.conn.baremetal.get_deploy_template(id_or_name)
except self.sdk.exceptions.ResourceNotFound:
return None
def main():
module = BaremetalDeployTemplateModule()
module()
if __name__ == "__main__":
main()

View File

@@ -93,10 +93,10 @@ EXAMPLES = r'''
image_checksum: "356a6b55ecc511a20c33c946c4e678af"
image_disk_format: "qcow"
delegate_to: localhost
deploy: yes
deploy: true
cloud: "openstack"
config_drive: "http://192.168.1.1/host-configdrive.iso"
maintenance: no
maintenance: false
power: present
uuid: "d44666e1-35b3-4f6b-acb0-88ab7052da69"
state: present

View File

@@ -317,7 +317,7 @@ EXAMPLES = r'''
image_id: 2a8c9888-9054-4b06-a1ca-2bb61f9adb72
keypair_id: mykey
name: k8s
is_public: no
is_public: false
'''
from ansible_collections.openstack.cloud.plugins.module_utils.openstack import OpenStackModule

View File

@@ -34,7 +34,7 @@ options:
type: str
choices: ['present', 'absent']
notes:
- A compute flavor must not be private to manage project access.
- A compute flavor must be private to manage project access.
extends_documentation_fragment:
- openstack.cloud.openstack
'''

View File

@@ -42,7 +42,7 @@ options:
floating IP completely, or only detach it from the server.
Default is to detach only.
type: bool
default: 'no'
default: 'false'
reuse:
description:
- When I(state) is present, and I(floating_ip_address) is not present,
@@ -52,7 +52,7 @@ options:
I(floating_ip_address) is undefined, then C(nat_destination) and
C(fixed_address) will be ignored.
type: bool
default: 'no'
default: 'false'
server:
description:
- The name or ID of the server to which the IP address
@@ -83,7 +83,7 @@ EXAMPLES = '''
- openstack.cloud.floating_ip:
cloud: dguerri
state: present
reuse: yes
reuse: true
server: cattle001
network: ext_net
fixed_address: 192.0.2.3
@@ -244,7 +244,7 @@ class NetworkingFloatingIPModule(OpenStackModule):
else: # ip
# Requested floating ip address exists already
if ip.port_details and (ip.port_details.status == 'ACTIVE') \
if ip.port_details and (ip.port_details['status'] == 'ACTIVE') \
and (floating_ip_address not in self._filter_ips(
self.server)):
# Floating ip address exists and has been attached

View File

@@ -32,7 +32,7 @@ options:
description:
- Whether the user is enabled or not.
type: bool
default: 'yes'
default: 'true'
aliases: ['enabled']
name:
description:

View File

@@ -258,7 +258,7 @@ EXAMPLES = r'''
- name: Delete a load balancer, its related resources and its floating ip
openstack.cloud.loadbalancer:
cloud: devstack
delete_floating_ip: yes
delete_floating_ip: true
name: my_lb
state: absent
'''

View File

@@ -135,9 +135,9 @@ options:
description:
- Do not associate a security group with this port.
- "Deprecated. Use I(security_groups): C([]) instead
of I(no_security_groups): C(yes)."
of I(no_security_groups): C(true)."
type: bool
default: 'no'
default: 'false'
port_security_enabled:
description:
- Whether to enable or disable the port security on the network.

View File

@@ -181,6 +181,10 @@ class DnsRecordsetModule(OpenStackModule):
module_min_sdk_version = '0.28.0'
def _needs_update(self, params, recordset):
if params['records'] is not None:
params['records'] = sorted(params['records'])
if recordset['records'] is not None:
recordset['records'] = sorted(recordset['records'])
for k in ('description', 'records', 'ttl', 'type'):
if k not in params:
continue

View File

@@ -87,7 +87,7 @@ options:
description:
- Desired admin state of the created or existing router.
type: bool
default: 'yes'
default: 'true'
aliases: ['admin_state_up']
name:
description:

View File

@@ -34,8 +34,8 @@ options:
security group with a default set of rules.
- Security group rules which are listed in I(security_group_rules)
but not defined in this security group will be created.
- Existing security group rules which are not listed in
I(security_group_rules) will be deleted.
- When I(security_group_rules) is not set, existing security group rules
which are not listed in I(security_group_rules) will be deleted.
- When updating a security group, one has to explicitly list rules from
Neutron's defaults in I(security_group_rules) if those rules should be
kept. Rules which are not listed in I(security_group_rules) will be
@@ -331,6 +331,12 @@ class SecurityGroupModule(OpenStackModule):
def _build_update_security_group_rules(self, security_group):
if self.params['security_group_rules'] is None:
# Consider a change of security group rules only when option
# 'security_group_rules' was defined explicitly, because undefined
# options in our Ansible modules denote "apply no change"
return {}
def find_security_group_rule_match(prototype, security_group_rules):
matches = [r for r in security_group_rules
if is_security_group_rule_match(prototype, r)]
@@ -439,7 +445,7 @@ class SecurityGroupModule(OpenStackModule):
def _generate_security_group_rule(params):
prototype = dict(
(k, params[k])
for k in ['direction', 'remote_ip_prefix']
for k in ['description', 'direction', 'remote_ip_prefix']
if params[k] is not None)
# When remote_ip_prefix is missing a netmask, then Neutron will add
@@ -521,17 +527,17 @@ class SecurityGroupModule(OpenStackModule):
return security_group
def _update_security_group_rules(self, security_group, update):
create_security_group_rules = update.get('create_security_group_rules')
if create_security_group_rules:
self.conn.network.\
create_security_group_rules(create_security_group_rules)
delete_security_group_rules = update.get('delete_security_group_rules')
if delete_security_group_rules:
for security_group_rule in delete_security_group_rules:
self.conn.network.\
delete_security_group_rule(security_group_rule['id'])
create_security_group_rules = update.get('create_security_group_rules')
if create_security_group_rules:
self.conn.network.\
create_security_group_rules(create_security_group_rules)
if create_security_group_rules or delete_security_group_rules:
# Update security group with created and deleted rules
return self.conn.network.get_security_group(security_group.id)

View File

@@ -308,7 +308,8 @@ class SecurityGroupRuleModule(OpenStackModule):
def _define_prototype(self):
filters = {}
prototype = dict((k, self.params[k])
for k in ['direction', 'remote_ip_prefix']
for k in ['description', 'direction',
'remote_ip_prefix']
if self.params[k] is not None)
# When remote_ip_prefix is missing a netmask, then Neutron will add

View File

@@ -27,7 +27,7 @@ options:
attaching and detaching of floating ip addresses use module
I(openstack.cloud.resource) instead.
type: bool
default: 'yes'
default: 'true'
aliases: ['auto_floating_ip', 'public_ip']
availability_zone:
description:
@@ -40,7 +40,7 @@ options:
the image given. Mutually exclusive with boot_volume.
- This server attribute cannot be updated.
type: bool
default: 'no'
default: 'false'
boot_volume:
description:
- Volume name or id to use as the volume to boot from. Implies
@@ -53,7 +53,7 @@ options:
- Whether to boot the server with config drive enabled.
- This server attribute cannot be updated.
type: bool
default: 'no'
default: 'false'
delete_ips:
description:
- When I(state) is C(absent) and this option is true, any floating IP
@@ -61,7 +61,7 @@ options:
- Floating IP support is unstable in this module, use with caution.
type: bool
aliases: ['delete_fip']
default: 'no'
default: 'false'
description:
description:
- Description of the server.
@@ -183,7 +183,7 @@ options:
- Floating IP support is unstable in this module, use with caution.
- This server attribute cannot be updated.
type: bool
default: 'yes'
default: 'true'
scheduler_hints:
description:
- Arbitrary key/value pairs to the scheduler for custom use.
@@ -207,11 +207,11 @@ options:
type: str
terminate_volume:
description:
- If C(yes), delete volume when deleting the instance and if it has
- If C(true), delete volume when deleting the instance and if it has
been booted from volume(s).
- This server attribute cannot be updated.
type: bool
default: 'no'
default: 'false'
timeout:
description:
- The amount of time the module should wait for the instance to get
@@ -240,7 +240,7 @@ options:
description:
- If the module should wait for the instance to be created.
type: bool
default: 'yes'
default: 'true'
extends_documentation_fragment:
- openstack.cloud.openstack
'''
@@ -288,7 +288,7 @@ EXAMPLES = '''
flavor: 101
security_groups:
- default
auto_ip: yes
auto_ip: true
# Create a new instance in named cloud mordred availability zone az2
# and assigns a pre-known floating IP
@@ -1038,7 +1038,7 @@ class ServerModule(OpenStackModule):
# we wait until the server has been created
# Ref.: https://opendev.org/openstack/openstacksdk/src/commit/3f81d0001dd994cde990d38f6e2671ee0694d7d5/openstack/cloud/_compute.py#L945
self.fail_json(
msg="Option '{0}' requires 'wait: yes'".format(k))
msg="Option '{0}' requires 'wait: true'".format(k))
flavor_name_or_id = self.params['flavor']

View File

@@ -25,7 +25,7 @@ options:
- when true, return additional detail about servers at the expense
of additional API calls.
type: bool
default: 'no'
default: 'false'
filters:
description: |
Used for further filtering of results. Either a string containing a
@@ -37,7 +37,7 @@ options:
- Whether to list servers from all projects or just the current auth
scoped project.
type: bool
default: 'no'
default: 'false'
extends_documentation_fragment:
- openstack.cloud.openstack
'''

View File

@@ -43,7 +43,7 @@ options:
- The gateway IP would not be assigned for this subnet
type: bool
aliases: ['no_gateway_ip']
default: 'no'
default: 'false'
dns_nameservers:
description:
- List of DNS nameservers for this subnet.
@@ -85,7 +85,7 @@ options:
- Whether DHCP should be enabled for this subnet.
type: bool
aliases: ['enable_dhcp']
default: 'yes'
default: 'true'
ipv6_ra_mode:
description:
- IPv6 router advertisement mode

View File

@@ -22,7 +22,7 @@ options:
- Allows or disallows snapshot of a volume to be created,
when the volume is attached to an instance.
type: bool
default: 'no'
default: 'false'
name:
description:
- Name of the snapshot