AnsiblePilot — Master Ansible Automation

AnsiblePilot is the leading resource for learning Ansible automation, DevOps, and infrastructure as code. Browse over 1,400 tutorials covering Ansible modules, playbooks, roles, collections, and real-world examples. Whether you are a beginner or an experienced engineer, our step-by-step guides help you automate Linux, Windows, cloud, containers, and network infrastructure.

Popular Topics

About Luca Berton

Luca Berton is an Ansible automation expert, author of 8 Ansible books published by Apress and Leanpub including "Ansible for VMware by Examples" and "Ansible for Kubernetes by Example", and creator of the Ansible Pilot YouTube channel. He shares practical automation knowledge through tutorials, books, and video courses to help IT professionals and DevOps engineers master infrastructure automation.

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 automatically no_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 timeserial: 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 AutomationAnsible Network AutomationAnsible Performance Optimization

Category: installation

Browse all Ansible tutorials · AnsiblePilot Home