Ansible Cisco UCS Automation: Manage UCS Manager Server Profiles, VLANs, and Policies
By Luca Berton · Published 2024-01-01 · Category: installation
Automate Cisco UCS Manager with Ansible. Configure server profiles, VLANs, service profiles, boot policies, and firmware upgrades using the cisco.ucs.
Introduction
Cisco Unified Computing System (UCS) combines compute, networking, storage, and virtualization into a single managed platform. Manually configuring UCS domains through the UCS Manager GUI is slow, error-prone, and impossible to reproduce consistently across multiple domains. Ansible's cisco.ucs collection automates the entire UCS lifecycle — from initial setup through day-2 operations — using the same playbook-based approach you use for everything else.
See also: Ansible Network Automation: Configure Cisco, Arista, and Juniper at Scale
Prerequisites
Install the Collection and SDK
# Install the Ansible collection
ansible-galaxy collection install cisco.ucs
# Install the Python SDK (required by all cisco.ucs modules)
pip install ucsmsdk
Verify Connectivity
# Quick test — verify UCS Manager API access
from ucsmsdk.ucshandle import UcsHandle
handle = UcsHandle("ucs-mgr.example.com", "admin", "password")
handle.login()
print("Connected:", handle.ucs)
handle.logout()
Inventory Setup
# inventory/ucs.ini
[ucs]
ucs-domain-01 ucs_hostname=10.1.1.100
ucs-domain-02 ucs_hostname=10.1.2.100
[ucs:vars]
ucs_username=admin
ucs_password={{ vault_ucs_password }}
VLAN Configuration
---
- name: Configure VLANs on UCS domain
hosts: ucs
connection: local
gather_facts: false
collections:
- cisco.ucs
tasks:
- name: Create production VLANs
cisco.ucs.ucs_vlans:
hostname: "{{ ucs_hostname }}"
username: "{{ ucs_username }}"
password: "{{ ucs_password }}"
name: "{{ item.name }}"
id: "{{ item.id }}"
native: "{{ item.native | default('no') }}"
state: present
loop:
- { name: mgmt-vlan, id: '10', native: 'yes' }
- { name: prod-app, id: '100' }
- { name: prod-db, id: '101' }
- { name: prod-web, id: '102' }
- { name: dmz, id: '200' }
- { name: backup, id: '300' }
no_log: true
- name: Remove deprecated VLANs
cisco.ucs.ucs_vlans:
hostname: "{{ ucs_hostname }}"
username: "{{ ucs_username }}"
password: "{{ ucs_password }}"
name: "{{ item }}"
state: absent
loop:
- old-test-vlan
- legacy-vlan-50
no_log: true
See also: Using the AAP 2.6 Self-Service Portal for Network Automation
vNIC and vHBA Templates
- name: Configure vNIC templates
hosts: ucs
connection: local
gather_facts: false
collections:
- cisco.ucs
tasks:
- name: Create vNIC template for production
cisco.ucs.ucs_vnic_template:
hostname: "{{ ucs_hostname }}"
username: "{{ ucs_username }}"
password: "{{ ucs_password }}"
name: prod-vnic-a
fabric: A
redundancy_type: primary
peer_redundancy_template: prod-vnic-b
template_type: updating-template
vlans_list:
- name: prod-app
native: 'no'
- name: prod-db
native: 'no'
- name: mgmt-vlan
native: 'yes'
mtu: '9000'
mac_pool: prod-mac-pool-a
network_control_policy: enable-cdp-lldp
state: present
no_log: true
- name: Create vNIC template for fabric B
cisco.ucs.ucs_vnic_template:
hostname: "{{ ucs_hostname }}"
username: "{{ ucs_username }}"
password: "{{ ucs_password }}"
name: prod-vnic-b
fabric: B
redundancy_type: secondary
peer_redundancy_template: prod-vnic-a
template_type: updating-template
vlans_list:
- name: prod-app
native: 'no'
- name: prod-db
native: 'no'
- name: mgmt-vlan
native: 'yes'
mtu: '9000'
mac_pool: prod-mac-pool-b
state: present
no_log: true
- name: Create vHBA templates for SAN boot
cisco.ucs.ucs_vhba_template:
hostname: "{{ ucs_hostname }}"
username: "{{ ucs_username }}"
password: "{{ ucs_password }}"
name: "{{ item.name }}"
fabric: "{{ item.fabric }}"
vsan: "{{ item.vsan }}"
template_type: updating-template
wwpn_pool: "{{ item.wwpn_pool }}"
state: present
loop:
- { name: prod-vhba-a, fabric: A, vsan: vsan-100, wwpn_pool: wwpn-pool-a }
- { name: prod-vhba-b, fabric: B, vsan: vsan-200, wwpn_pool: wwpn-pool-b }
no_log: true
MAC, WWPN, and UUID Pools
- name: Configure identity pools
hosts: ucs
connection: local
gather_facts: false
collections:
- cisco.ucs
tasks:
- name: Create MAC address pools
cisco.ucs.ucs_mac_pool:
hostname: "{{ ucs_hostname }}"
username: "{{ ucs_username }}"
password: "{{ ucs_password }}"
name: "{{ item.name }}"
first_addr: "{{ item.first }}"
last_addr: "{{ item.last }}"
order: sequential
state: present
loop:
- { name: prod-mac-pool-a, first: '00:25:B5:A0:00:00', last: '00:25:B5:A0:00:FF' }
- { name: prod-mac-pool-b, first: '00:25:B5:B0:00:00', last: '00:25:B5:B0:00:FF' }
no_log: true
- name: Create UUID suffix pool
cisco.ucs.ucs_uuid_pool:
hostname: "{{ ucs_hostname }}"
username: "{{ ucs_username }}"
password: "{{ ucs_password }}"
name: prod-uuid-pool
prefix: derived
first_uuid: '0000-000000000001'
last_uuid: '0000-0000000000FF'
order: sequential
state: present
no_log: true
See also: AAP 2.6 Network Automation: Cisco, Arista, Juniper, and Multi-Vendor Management
Service Profile Templates
- name: Configure service profile templates
hosts: ucs
connection: local
gather_facts: false
collections:
- cisco.ucs
tasks:
- name: Create service profile template
cisco.ucs.ucs_service_profile_template:
hostname: "{{ ucs_hostname }}"
username: "{{ ucs_username }}"
password: "{{ ucs_password }}"
name: prod-spt-esxi
template_type: updating-template
uuid_pool: prod-uuid-pool
storage_profile: prod-storage
local_disk_policy: any-configuration
boot_policy: prod-san-boot
bios_policy: prod-performance
maintenance_policy: user-ack
server_pool: prod-server-pool
host_firmware_package: prod-firmware
mgmt_ip_pool: prod-ext-mgmt
power_control_policy: no-power-cap
vnic_list:
- name: eth0
vnic_template: prod-vnic-a
adapter_policy: VMWare
- name: eth1
vnic_template: prod-vnic-b
adapter_policy: VMWare
vhba_list:
- name: fc0
vhba_template: prod-vhba-a
adapter_policy: VMWare
- name: fc1
vhba_template: prod-vhba-b
adapter_policy: VMWare
state: present
no_log: true
- name: Create service profiles from template
cisco.ucs.ucs_service_profile_from_template:
hostname: "{{ ucs_hostname }}"
username: "{{ ucs_username }}"
password: "{{ ucs_password }}"
name: "prod-esxi-{{ '%02d' | format(item) }}"
source_template: prod-spt-esxi
state: present
loop: "{{ range(1, 17) | list }}"
no_log: true
Boot Policies
- name: Create SAN boot policy
cisco.ucs.ucs_managed_objects:
hostname: "{{ ucs_hostname }}"
username: "{{ ucs_username }}"
password: "{{ ucs_password }}"
objects:
- module: ucsmsdk.mometa.lsboot.LsbootPolicy
class: LsbootPolicy
properties:
parent_mo_or_dn: org-root
name: prod-san-boot
purpose: operational
reboot_on_update: 'no'
enforce_vnic_name: 'yes'
children:
- module: ucsmsdk.mometa.lsboot.LsbootVirtualMedia
class: LsbootVirtualMedia
properties:
access: read-only-remote-cimc
lun_id: '0'
order: '1'
- module: ucsmsdk.mometa.lsboot.LsbootStorage
class: LsbootStorage
properties:
order: '2'
no_log: true
Firmware Management
- name: Manage UCS firmware
hosts: ucs
connection: local
gather_facts: false
collections:
- cisco.ucs
tasks:
- name: Create host firmware package
cisco.ucs.ucs_managed_objects:
hostname: "{{ ucs_hostname }}"
username: "{{ ucs_username }}"
password: "{{ ucs_password }}"
objects:
- module: ucsmsdk.mometa.firmware.FirmwareComputeHostPack
class: FirmwareComputeHostPack
properties:
parent_mo_or_dn: org-root
name: prod-firmware
blade_bundle_version: "{{ ucs_firmware_version }}"
rack_bundle_version: "{{ ucs_firmware_version }}"
no_log: true
NTP and DNS Configuration
- name: Configure UCS infrastructure services
hosts: ucs
connection: local
gather_facts: false
collections:
- cisco.ucs
tasks:
- name: Configure NTP servers
cisco.ucs.ucs_ntp_server:
hostname: "{{ ucs_hostname }}"
username: "{{ ucs_username }}"
password: "{{ ucs_password }}"
ntp_server: "{{ item }}"
state: present
loop:
- 10.1.1.1
- 10.1.1.2
no_log: true
- name: Configure DNS servers
cisco.ucs.ucs_dns_server:
hostname: "{{ ucs_hostname }}"
username: "{{ ucs_username }}"
password: "{{ ucs_password }}"
dns_server: "{{ item }}"
state: present
loop:
- 10.1.1.10
- 10.1.1.11
no_log: true
- name: Set timezone
cisco.ucs.ucs_timezone:
hostname: "{{ ucs_hostname }}"
username: "{{ ucs_username }}"
password: "{{ ucs_password }}"
timezone: America/New_York
state: present
no_log: true
Multi-Domain Management
- name: Standardize configuration across all UCS domains
hosts: ucs
connection: local
gather_facts: false
serial: 1 # One domain at a time
tasks:
- name: Import standard configuration
ansible.builtin.include_role:
name: ucs_baseline
vars:
ucs_host: "{{ ucs_hostname }}"
ucs_user: "{{ ucs_username }}"
ucs_pass: "{{ ucs_password }}"
- name: Verify configuration
cisco.ucs.ucs_query:
hostname: "{{ ucs_hostname }}"
username: "{{ ucs_username }}"
password: "{{ ucs_password }}"
class_ids: fabricVlan
register: vlan_check
no_log: true
- name: Report domain status
ansible.builtin.debug:
msg: "{{ ucs_hostname }}: {{ vlan_check.objects | length }} VLANs configured"
Cisco UCS + VMware Integration
- name: End-to-end UCS + VMware provisioning
hosts: localhost
connection: local
tasks:
# Step 1: Create UCS service profile
- name: Create bare-metal server profile
cisco.ucs.ucs_service_profile_from_template:
hostname: "{{ ucs_hostname }}"
username: "{{ ucs_username }}"
password: "{{ ucs_password }}"
name: "esxi-{{ new_host_id }}"
source_template: prod-spt-esxi
no_log: true
# Step 2: Wait for server association
- name: Wait for server to associate
cisco.ucs.ucs_query:
hostname: "{{ ucs_hostname }}"
username: "{{ ucs_username }}"
password: "{{ ucs_password }}"
distinguished_names: "org-root/ls-esxi-{{ new_host_id }}"
register: sp_status
until: sp_status.objects[0].assoc_state == 'associated'
retries: 30
delay: 60
no_log: true
# Step 3: Add to vCenter
- name: Add ESXi host to vCenter
community.vmware.vmware_host:
hostname: "{{ vcenter_hostname }}"
username: "{{ vcenter_username }}"
password: "{{ vcenter_password }}"
datacenter: "{{ vcenter_datacenter }}"
cluster: "{{ vcenter_cluster }}"
esxi_hostname: "esxi-{{ new_host_id }}.example.com"
esxi_username: root
esxi_password: "{{ vault_esxi_password }}"
state: present
no_log: true
Best Practices
Use updating templates — Changes propagate to all service profiles automaticallyno_log: true always — UCS credentials appear in every task
Sequential pools — MAC, WWPN, UUID pools should use sequential assignment for predictability
Maintenance policies — Use user-ack for production to prevent unexpected reboots
One domain at a time — serial: 1 for cross-domain changes
Firmware staging — Stage firmware first, then schedule activation during maintenance windows
Backup before changes — Export UCS configuration before any automation run
AAP credential type — Create a custom credential type for UCS Manager credentials
FAQ
cisco.ucs vs cisco.intersight collection?
cisco.ucs manages on-premises UCS Manager directly via the XML API. cisco.intersight manages UCS through Cisco's cloud-based Intersight platform. Choose based on your management model.
Can Ansible handle UCS firmware upgrades?
Yes — create firmware packages, assign to service profile templates, and let the maintenance policy control when blades reboot. Always stage firmware to both fabric interconnects before activating.
What about UCS Central?
For multi-domain management, UCS Central provides centralized policies. Ansible can complement it by automating domain-specific configurations and cross-platform workflows (UCS + VMware + network).
Conclusion
The cisco.ucs collection brings infrastructure-as-code to Cisco UCS — automating VLANs, service profiles, firmware, identity pools, and boot policies. Combined with VMware and network automation, Ansible provides end-to-end datacenter automation from bare metal to running workloads.
Related Articles
• Ansible VMware Automation • Ansible Network Automation • Ansible Performance OptimizationCategory: installation