Ansible - ACI configure a range - ansible

I need to create a script that creates multiple AP with one EPG each , for the AP I can find how to build the range using the ap module , this is what I have so far:
---
- name: ACI Link Level Management
hosts: APIC
connection: local
gather_facts: no
vars:
username: admin
password: Admin
ap_list: "{{ lookup('sequence', 'start=11 count=5 format=ap%d', wantlist=True) }}"
tasks:
- name: Create link level policies
cisco.aci.aci_ap:
host: '{{ inventory_hostname }}'
user: '{{ username }}'
password: '{{ password }}'
validate_certs: false
tenant: DC
ap: '{{ ap_list }}'
description: default ap
monitoring_policy: default
state: present ...
But I'm getting the following error:
FAILED! => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python3"}, "changed": false, "msg": "Connection failed for /api/mo/uni/tn-DC/ap-['ap11', 'ap12', 'ap13', 'ap14', 'ap15'].json?rsp-prop-include=config-only&rsp-subtree=full&rsp-subtree-class=fvRsApMonPol. An unknown error occurred: URL can't contain control characters. "/api/mo/uni/tn-DC/ap-['ap11', 'ap12', 'ap13', 'ap14', 'ap15'].json?rsp-prop-include=config-only&rsp-subtree=full&rsp-subtree-class=fvRsApMonPol" (found at least ' ')"}

The parameter ap requires a string. You provided a list instead
ap_list: [ap11, ap12, ap13, ap14, ap15]
See the doc
shell> ansible-doc -t module cisco.aci.aci_ap
Maybe you'd like to iterate the list?
- name: Create link level policies
cisco.aci.aci_ap:
host: '{{ inventory_hostname }}'
user: '{{ username }}'
password: '{{ password }}'
validate_certs: false
tenant: DC
ap: '{{ item }}'
description: default ap
monitoring_policy: default
state: present ...
loop: '{{ ap_list }}'

Related

Set permission for VMWare folders individually

In my vsphere, I am having total 3 DCs with name ABC,PQR and XYZ. Under each DC I have created main folder (TEAM) & subfolder(FOLDERA and FOLDERB) with same name. Here is how the folder structure look like:
I am trying to set individual permission to the subfolders and main folder under each DC using https://docs.ansible.com/ansible/latest/collections/community/vmware/vmware_object_role_permission_module.html . I have used below code for this
- name: Assign access to parent VM folder
community.vmware.vmware_object_role_permission:
hostname: '{{ vcenter_hostname }}'
username: '{{ vcenter_username }}'
password: '{{ vcenter_password }}'
validate_certs : false
object_name: '{{ root_vm_folder }}'
state: present
recursive : false
role: NoAccess
principal: '{{ item.useraccount }}'
delegate_to: localhost
loop: '{{ my-permission }}'
- name: Assign view permission for VM sub folder
community.vmware.vmware_object_role_permission:
hostname: '{{ vcenter_hostname }}'
username: '{{ vcenter_username }}'
password: '{{ vcenter_password }}'
validate_certs : false
object_name: '{{ item.vmfolder }}'
state: present
recursive : false
role: '{{ item.permission }}'
principal: '{{ item.useraccount }}'
loop: '{{ my-permission}}'
delegate_to: localhost
Here are the variables:
root_vm_folder: 'TEAM'
vmfolder:
- 'FOLDERA'
- 'FOLDERB'
my-permission:
- useraccount: 'devops'
permission: 'ViewOnly'
vmfolder: 'FolderA'
- useraccount: 'developer'
permission: 'ViewOnly'
vmfolder: 'FolderB'
But when we run the playbook the permission is only getting effective to the DC:ABC as it is the first one. There is no option to specify the DataCentre name in the module.
As the Folder names are global variable, is there any way we can set the permission for the folders and sub-folders with same name under each DC in a vsphere.

Getting specific ansible facts in a list

I am currently attempting to automatically create anti-affinity rules for deploying various apps in VMware. I've been using the drs_rule module like so:
- name: Create DRS Anti-Affinity Rule for appX
vmware_vm_vm_drs_rule:
hostname: '{{ vcenter_hostname }}'
username: '{{ vcenter_username }}'
password: '{{ vcenter_password }}'
cluster_name: '{{ vsphere_cluster }}'
enabled: True
vms:
-appXa
-appXb
-appXc
drs_rule_name: appX_rule
mandatory: True
affinity_rule: False
delegate_to: localhost
run_once: True
However, the exact number of VMs can vary based on the deployment. Therefore, I need to be able to pull this information dynamically. This is closest I can find to what I need:
- name: Create DRS Anti-Affinity Rule for appX
vmware_vm_vm_drs_rule:
hostname: '{{ vcenter_hostname }}'
username: '{{ vcenter_username }}'
password: '{{ vcenter_password }}'
cluster_name: '{{ vsphere_cluster }}'
enabled: True
vms: "{{ item }}"
drs_rule_name: appX_rule
mandatory: True
affinity_rule: False
loop: "{{ groups['appX'] }}"
delegate_to: localhost
run_once: True
While this does pull the IP addresses from my inventory file for that group, I need to pull the VM names (i.e. hostnames) in order for it to work with this module. Is there a way to make something like this work within the playbook? Basically to have it return a list of hostname strings, so I can plug it into this module.
# ansible appX-i inventory -m setup -a "filter=ansible_hostname"
xxx.xxx.xxx.xxx | SUCCESS => {
"ansible_facts": {
"ansible_hostname": "appXa"
},
"changed": false
}
xxx.xxx.xxx.xxx | SUCCESS => {
"ansible_facts": {
"ansible_hostname": "appXb"
},
"changed": false
}
xxx.xxx.xxx.xxx | SUCCESS => {
"ansible_facts": {
"ansible_hostname": "appXc"
},
"changed": false
}
Much obliged :-)
EDIT: I was able to extract the hostname. Credit goes to mdaniel for that
- name: Create DRS Anti-Affinity Rule for appX
vmware_vm_vm_drs_rule:
hostname: '{{ vcenter_hostname }}'
username: '{{ vcenter_username }}'
password: '{{ vcenter_password }}'
cluster_name: '{{ vsphere_cluster }}'
enabled: True
vms: "{{ item }}"
drs_rule_name: appX_rule
mandatory: True
affinity_rule: False
loop: "{{ groups['appX'] | map('extract', hostvars, 'ansible_hostname') }}"
delegate_to: localhost
run_once: True
However, we actually need the items in the format of "hostname_IP" e.g. "appXa_192.168.1.100". Is there a way to pull the IP address and concatenate an underscore in between them all on the same line?
Also, having some issues pulling the IPs with map/extract since the ansible facts have them in dictionary format. I.e.
"ansible_default_ipv4": {
"address": "192.169.1.100",
I could use ansible_all_ipv4_addresses which is in a list, but that could introduce complications if we ever attach multiple IPs to the same machines.
However, we actually need the items in the format of "hostname_IP" e.g. "appXa_192.168.1.100". Is there a way to pull the IP address and concatenate an underscore in between them all on the same line?
Yes and no; doing it in one shot would be some silliness, since there is no lambda: equivalent in jinja2, but using the with_together: lookup will likely do what you want, since it will give the task access to the hostname, the matching ip, and then allow you to cheaply join them together as needed. The together lookup should be safe to use to pair them up since (as far as I know) groups["appX"] is ordered deterministically and thus each map application will happen to the same list
- debug:
msg: |
the hostname is '{{ item.0 }}'
its IP is '{{ item.1 }}'
composite key is '{{ item.0 ~ "_" ~ item.1 }}'
with_together:
- '{{ groups["appX"] | map("extract", hostvars, "ansible_hostname") | list }}'
- '{{ groups["appX"] | map("extract", hostvars, ["ansible_default_ipv4", "address"]) | list }}'

Launching oVirt Template cannot find data_center

So far I believe I am very close to getting Ansible to launch a VM template in oVirt. I'm able to authenticate without an issue, I believe specify the quota but even though it's launching a template it cannot find its data_center. No examples that I can find define data_center in the ovirt_vm module, this is what I have:
---
# tasks file for ovirt-template-launch
- name: Login to oVirt
ovirt_auth:
hostname: "{{ ovirt_hostname }}"
url: "{{ ovirt_ind_url }}"
username: "{{ ovirt_login_username }}"
password: "{{ ovirt_login_password }}"
insecure: true
- name: Create persistent SSO token
ovirt_vm:
auth: "{{ ovirt_auth }}"
state: absent
name: myvm
# Gather quota/datacenter
- ovirt_quota_info:
data_center: "{{ ovirt_datacenter }}"
name: "{{ ovirt_quota }}"
auth: "{{ ovirt_auth }}"
register: result
- name: Run VM with cloud init
ovirt_vm:
name: "{{ vmname }}"
template: centos7-template1
cluster: Default
memory: 2GiB
high_availability: true
high_availability_priority: 50
disks:
- size: 10GiB
name: data
storage_domain: mydomain
interface: virtio
auth: "{{ ovirt_auth }}"
quota_id: "{{ ovirt_quota_id }}"
cloud_init:
nic_boot_protocol: static
nic_ip_address: 10.0.1.5
nic_netmask: 255.255.254.0
nic_gateway: 10.0.1.1
nic_name: eth0
nic_on_boot: true
host_name: testdomain.com
custom_script: |
write_files:
- content: |
Hello, world!
path: /tmp/greeting.txt
permissions: '0644'
Error is:
An exception occurred during task execution. To see the full traceback, use -vvv. The error was: AttributeError: 'NoneType' object has no attribute 'data_center'
fatal: [localhost]: FAILED! => {"changed": false, "msg": "'NoneType' object has no attribute 'data_center'"}

Ansible how to select a nested list in a attribut of list

Hi I would like to known how I can select a list nested in an attibut of a list. I've done a research on my F5 BIG IP and it give me a list of the attibutes of the virtuals servers like that:
"/Common/vs_portailopal_wi_https_virtual_server": {
"last_hop_pool": "",
"name": "vs_portailopal_wi_https_virtual_server",
"nat64_state": "STATE_DISABLED",
"object_status": {
"availability_status": "AVAILABILITY_STATUS_RED",
"enabled_status": "ENABLED_STATUS_DISABLED",
"status_description": "The children pool member(s) are down"
},
"profile": [
{
"profile_context": "PROFILE_CONTEXT_TYPE_CLIENT",
"profile_name": "/Common/vs_portailopal_wi_clientssl_profile",
"profile_type": "PROFILE_TYPE_CLIENT_SSL"
},
{
"profile_context": "PROFILE_CONTEXT_TYPE_ALL",
"profile_name": "/Common/vs_portailopal_wi_http_profile",
"profile_type": "PROFILE_TYPE_HTTP"
},
{
"profile_context": "PROFILE_CONTEXT_TYPE_ALL",
"profile_name": "/Common/vs_portailopal_wi_http_profile-cache",
"profile_type": "PROFILE_TYPE_WEBACCELERATION"
},]
},
},
So I would like to compare the name of the virtual serveur and the name of each profile. I can select the name of the vitual server but I can't enter in the list of profile to select the name because it's a nested list in an attribute
This is I doing:
---
- name: Search
hosts: F5
gather_facts: no
connection: local
vars:
username: '{{ cpt_username }}'
password: '{{ cpt_password }}'
tasks:
- name: Get virtual-servers
bigip_facts:
include:
- virtual_server
server: '{{ inventory_hostname }}'
user: '{{ username }}'
password: '{{ password }}'
validate_certs: no
- name: filter on VIP_nommage when VIP_partition is OK
lineinfile:
line:
- "{{ inventory_hostname }} Virtual Server : {{ item.key }} => POOL: {{ item.value.profile.name }}"
dest: "xxxxx/file.csv"
state: present
with_dict: "{{ virtual_server }}"
I want to store in file all profiles name per virtual serveur and in other task filter on their names.
I am not familiar with the bigip Ansible modules, and I definitely don't have any F5 kit to test against :) Before saying anything else, a big note is that the docs say that 'bigip_facts' is now deprecated, and you should be using 'bigip_device_facts'. But if you want to use this module, can you do a couple of things:
1) Edit your original question to add the detail you posted in your reply. It is better to keep editing your original question with additional information, rather than add answers, as it makes it easier to understand your entire situation.
2) Create a new playbook that contains:
---
- hosts: F5
gather_facts: no
connection: local
vars:
username: '{{ cpt_username }}'
password: '{{ cpt_password }}'
tasks:
- name: Get virtual-servers
bigip_facts:
include:
- virtual_server
server: '{{ inventory_hostname }}'
user: '{{ username }}'
password: '{{ password }}'
validate_certs: no
register: bigip_facts_data
- name: Display collected data
debug:
var: bigip_facts_data
This will show us the data that Ansible is actually working with. Paste the output into your original reply, in place the of the JSON that you originally pasted. It may look like this:
"/Common/vs_portailopal_wi_https_virtual_server":
last_hop_pool: ''
name: vs_portailopal_wi_https_virtual_server
nat64_state: STATE_DISABLED
object_status:
availability_status: AVAILABILITY_STATUS_RED
enabled_status: ENABLED_STATUS_DISABLED
status_description: The children pool member(s) are down
profile:
- profile_context: PROFILE_CONTEXT_TYPE_CLIENT
profile_name: "/Common/vs_portailopal_wi_clientssl_profile"
profile_type: PROFILE_TYPE_CLIENT_SSL
- profile_context: PROFILE_CONTEXT_TYPE_ALL
profile_name: "/Common/vs_portailopal_wi_http_profile"
profile_type: PROFILE_TYPE_HTTP
- profile_context: PROFILE_CONTEXT_TYPE_ALL
profile_name: "/Common/vs_portailopal_wi_http_profile-cache"
profile_type: PROFILE_TYPE_WEBACCELERATION
If it does, then this may produce the output you need (tho I am still not clear I fully understand what you require - hopefully we are closer):
- name: filter on VIP_nommage when VIP_partition is OK
lineinfile:
line:
- "{{ inventory_hostname }} Virtual Server : {{ item.0.name }} => POOL: {{ item.1.profile_name }}"
dest: "xxxxx/file.csv"
state: present
with_subelements:
- "{{ bigip_fact_data }}"
- profile
Really, 'with_subelements' is deprecated now along with the other 'with_' constructs, but if you are using 'bigip_facts' I guess you are using an older version of Ansible.

Getting UUID of a VMware Virtual Machine using Ansible

We are working on Ansible Environemt. We wanted to connect to a Newly Deployed VM using its UUUID.
How to Get the UUID of a VMware Virtual Machine using Ansible so that i can establish the connection.
Did you check this link: The UUID Location and Format
It can be accessed by standard SMBIOS scanning software — for example
SiSoftware Sandra or the IBM utility smbios2 [...]
You must use the vmware_guest_facts module first, and retrieve the UUID. However, there are two identified as uuid, so I listed them both. I am assuming that the uuid you want is the instance_uuid.
tasks:
- name: get list of facts
vmware_guest_facts:
hostname: '{{ vc_name }}'
username: '{{ vc_user }}'
password: '{{ vc_pwd }}'
datacenter: "{{ dc_name }}"
name: "{{ vm_name }}"
folder: "{{ dc_folder }}"
validate_certs: False
register: vm_facts
- set_fact:
vm_uuid: "{{ vm_facts.instance.instance_uuid }}"
- debug:
msg: "product uuid hw : {{ vm_facts.instance.hw_product_uuid }}\n instance: {{ vm_facts.instance.instance_uuid }}"
Now continue on in your script and use {{ vm_uuid }} where you need the uuid to the VM.
Ansible module vmware_guest_facts has been deprecated. This will not run in Ansible 2.9. You need to use the vmware_guest_info module instead.
- name: Getting VMWARE UUID
hosts: localhost
gather_facts: false
connection: local
tasks:
- name: Get Virtual Machine info
vmware_guest_info:
validate_certs: no
hostname: "{{ vcenter_hostname }}"
username: "{{ Password }}"
password: "{{ pass }}"
validate_certs: no
datacenter: "{{ datacenter_name }}"
name: "{{ VM_Name }}"
schema: "vsphere"
properties:
delegate_to: localhost
register: vminfo
- debug:
var: vminfo.instance.config.uuid
The above code assumes you know the datacenter the VM is sitting on. If unsure of such you can also run the following code:
- name: Get UUID from given VM Name
block:
- name: Get virtual machine info
vmware_vm_info:
hostname: '{{ vcenter_hostname }}'
username: '{{ vcenter_username }}'
password: '{{ vcenter_password }}'
folder: "/datacenter/vm/folder"
delegate_to: localhost
register: vm_info
- debug:
msg: "{{ item.uuid }}"
with_items:
- "{{ vm_info.virtual_machines | json_query(query) }}"
vars:
query: "[?guest_name=='DC0_H0_VM0']"

Resources