BMC Ansible/Automation Module
Version: 0.4.3
This is an Ansible module for automating BMCs, e.g. iDRACs.
This was driven out of the need for a reliable and repeatable way to drive BMCs. As such it uses CLI tools like SSH/racadm rather than web based APIs such as redshift. I found redshift APIs to be totally unreliable (for example different versions of iDRAC support different subsets of capability, whereas racadm supported the capability even if it wasn't exposed by redfish) and thus results were not repeatable.
There are other modules built by others available with similar features e.g.:
https://github.com/1NoOne1/ansible-racadm
This module is based somewhat on the ideas of other modules, and on my previous generic virtualisation ansible module:
https://github.com/lateralblast/vamp
This is Ansible module is designed to be generic and extensible. Other platforms can be relatively easily added if needed, for example ILOMs, ILOs etc.
I'll added support for Intel IME/AMT via web calls like I've done here:
https://github.com/lateralblast/goat
To use the racadm method, racadm is required.
For x86 based Linux, racadm can be installed from the packages provided by Dell:
https://linux.dell.com/repo/community/openmanage/
For non x86 based Linux and MacOS, you can run racadm via docker using the platform flag.
I've written a script to do this:
https://github.com/lateralblast/dracadm/
The goal of this module is to expose an Ansible based DSL that is more easily translated to and from the racadm command set allowing for more easy implementation and debugging.
For example the command from the iDRAC manual to convert a disk reset a controller config is:
racadm --nocertwarn -r IDRAC-HOSTNAME -u IDRAC-USERNAME -p IDRAC-PASSWORD storage resetconfig:RAID.Integrated.1-1
The Ansible stanza for this would be:
- name: Reset RAID Config
bam:
bmctype: idrac
method: racadm
bmchostname: "{{ bmc_admin_hostname }}"
bmcusername: "{{ bmc_admin_username }}"
bmcpassword: "{{ bmc_admin_password }}"
nocertwarn: true
function: storage
resetconfig: RAID.Integrated.1-1
Add path where module is to ---module-path in anisble-playbook command line.
This software is licensed as CC-BA (Creative Commons By Attrbution)
http://creativecommons.org/licenses/by/4.0/legalcode
The following components are required:
- ansible
- python
In the case of iDRACs the script tries to support the older and newer implementations of iDRAC and racadm.
For example the older method of enabling IPMI over LAN uses the following method, with a group and an object:
racadm config -g cfgIpmiLan -o cfgIpmiLanEnable 1
The newer method of enabling IPMI over LAN uses the following method:
racadm get iDRAC.IPMILan.Enable Enabled
To address this, if the objectgroup tag is used, it will assume the older method.
For example an Ansible stanza that would force/use the first method:
- name: Enable IPMI over LAN via SSH using old method
bam:
bmctype: idrac
method: ssh
bmchostname: "{{ bmc_admin_hostname }}"
bmcusername: "{{ bmc_admin_username }}"
bmcpassword: "{{ bmc_admin_password }}"
function: set
objectgroup: cfgIpmiLan
object: cfgIpmiLanEnable
value: 1
An example Ansible stanza that would force/use the newer method:
- name: Enable IPMI over LAN via SSH using new method
bam:
bmctype: idrac
method: ssh
bmchostname: "{{ bmc_admin_hostname }}"
bmcusername: "{{ bmc_admin_username }}"
bmcpassword: "{{ bmc_admin_password }}"
function: set
objectgroup: iDRAC.IPMILan.Enable
value: Enabled
Support for SSH also exists allowing the use of keys. When using SSH as the method, if no password is given, it will be assumed SSH keys are being used.
In addition to the usual Ansible module features, this module has the following features:
- Where a commnd is run it can return the command run making it useful for debugging
- This can be discovered via the register function and calling the command property
- Can search output for a value which is useful for debugging and doing conditional actions
- This can be called for in two ways
- A search function which will return the line the string is found in
- A searchforvalue function which will try to return just the value in search result rather than the entire line
- This can be called for in two ways
- Return the value of a get function which is also useful for debugging and doing conditional actions
- This can be discovered via the register function and calling the value property
- Sylinking to the BMC type to the module file can be used to call the BMC type directly in a stanza
To help with processing information, I've added a couple of search function tags.
The "search" tag with return any references to a term.
For example to return any reference to Gateway from the getniccfg command:
- name: Get Gateway references from iDRAC Network config via ssh using newer method
bam:
bmctype: idrac
method: ssh
bmchostname: "{{ ansible_host }}"
bmcusername: "{{ idrac_username }}"
usesshkey: true
sshkeyfile: "{{idrac_sshkey_file}}"
function: getniccfg
search: "Gateway"
execute: "{{ execute_get }}"
This will return the line with Gateway in it, e.g.:
Gateway = 192.168.11.254
In order to assist with processing, I've added a "searchforvalue" tag with will attempt to clean up the ouput and only return the value.
For example
- name: Get Gateway references from iDRAC Network config via ssh using newer method
bam:
bmctype: idrac
method: ssh
bmchostname: "{{ ansible_host }}"
bmcusername: "{{ idrac_username }}"
usesshkey: true
sshkeyfile: "{{idrac_sshkey_file}}"
function: getniccfg
searchforvalue: "Gateway"
execute: "{{ execute_get }}"
This will return:
192.168.11.254
You can verify this with a debug statement, e.g.:
- name: Output Gateway
debug:
msg: "{{ output.stdout }}"
This would produce the following output:
TASK [Output Gateway] ***************************
ok: [HOSTNAME] => {
"msg": "192.168.11.254"
}
You can also use the value property which will try to extract the value from the output, for example:
- name: Get Gateway references from iDRAC Network config via ssh using newer method
bam:
bmctype: idrac
method: ssh
bmchostname: "{{ ansible_host }}"
bmcusername: "{{ idrac_username }}"
usesshkey: true
sshkeyfile: "{{idrac_sshkey_file}}"
function: getniccfg
search: "Gateway"
execute: "{{ execute_get }}"
- name: Output Gateway
debug:
msg: "{{ output.value }}"
This would produce the following output:
TASK [Output Gateway] ***************************
ok: [HOSTNAME] => {
"msg": "192.168.11.254"
}
This is more useful with the newer racadm command/object structure, where you would follow the following method:
- name: Get Gateway references from iDRAC Network config via ssh using newer method
bam:
bmctype: idrac
method: ssh
bmchostname: "{{ ansible_host }}"
bmcusername: "{{ idrac_username }}"
usesshkey: true
sshkeyfile: "{{idrac_sshkey_file}}"
function: get
object: "iDRAC.IPv4.Gateway"
execute: "{{ execute_get }}"
I've added some additional modularity/flexible and debugging to the module.
For example, if you want to run in debug mode without running the actual command, set the execute object to no:
- name: Get iDRAC object but don't execute function
bam:
bmctype: idrac
method: racadm
bmchostname: "{{ bmc_admin_hostname }}"
bmcusername: "{{ bmc_admin_username }}"
bmcpassword: "{{ bmc_admin_password }}"
function: get
object: iDRAC.OS-BMC.AdminState
execute: no
Otherwise, to get the value of a object:
- name: Get iDRAC object
bam:
bmctype: idrac
method: racadm
bmchostname: "{{ bmc_admin_hostname }}"
bmcusername: "{{ bmc_admin_username }}"
bmcpassword: "{{ bmc_admin_password }}"
function: get
object: iDRAC.OS-BMC.AdminState
If you want to know what command was actually run to get the information you can use debug, e.g.:
- name: Get Virtual Disk Information
bam:
bmctype: idrac
method: racadm
bmchostname: "{{ bmc_admin_hostname }}"
bmcusername: "{{ bmc_admin_username }}"
bmcpassword: "{{ bmc_admin_password }}"
function: raid
subfunction: get
object: vdisks
verbose: true
register: pdisks
- name: Output pdisks
debug:
msg: "{{ vdisks.command }}"
This will produce the following output:
TASK [Print Virtual Disk Information] *****************************************************************************************
ok: [ BMC_HOSTNAME ] => {
"msg": "racadm --nocertwarn -r IDRAC-HOSTNAME -u IDRAC-USERNAME -p IDRAC-PASSWORD raid get vdisks -o"
}
An example of iterating through physical disks and convert them to raid capable disks and output the commands that would be run:
- name: Convert physical disks to RAID capable devices
bam:
bmctype: idrac
method: racadm
bmchostname: "{{ bmc_admin_hostname }}"
bmcusername: "{{ bmc_admin_username }}"
bmcpassword: "{{ bmc_admin_password }}"
function: raid
converttoraid: "Disk.Bay.{{ item }}:Enclosure.Internal.0-1:RAID.Integrated.1-1"
execute: false
with_items:
- 0
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
register: output
- name: Print job command
debug:
msg: "{{ item.command }}"
with_items: "{{ output.results }}"
loop_control:
label: "{{ item.command }}"
The output from this example:
TASK [Print job command] *************************************************************
ok: [ BMC_HOSTNAME ] => (item=racadm --nocertwarn -r IDRAC-HOSTNAME -u IDRAC-USERNAME -p IDRAC-PASSWORD raid converttoraid:Disk.Bay.0:Enclosure.Internal.0-1:RAID.Integrated.1-1) => {
"msg": "racadm --nocertwarn -r IDRAC-HOSTNAME -u IDRAC-USERNAME -p IDRAC-PASSWORD raid converttoraid:Disk.Bay.0:Enclosure.Internal.0-1:RAID.Integrated.1-1"
}
ok: [ BMC_HOSTNAME ] => (item=racadm --nocertwarn -r IDRAC-HOSTNAME -u IDRAC-USERNAME -p IDRAC-PASSWORD raid converttoraid:Disk.Bay.1:Enclosure.Internal.0-1:RAID.Integrated.1-1) => {
"msg": "racadm --nocertwarn -r IDRAC-HOSTNAME -u IDRAC-USERNAME -p IDRAC-PASSWORD raid converttoraid:Disk.Bay.1:Enclosure.Internal.0-1:RAID.Integrated.1-1"
}
ok: [ BMC_HOSTNAME ] => (item=racadm --nocertwarn -r IDRAC-HOSTNAME -u IDRAC-USERNAME -p IDRAC-PASSWORD raid converttoraid:Disk.Bay.2:Enclosure.Internal.0-1:RAID.Integrated.1-1) => {
"msg": "racadm --nocertwarn -r IDRAC-HOSTNAME -u IDRAC-USERNAME -p IDRAC-PASSWORD raid converttoraid:Disk.Bay.2:Enclosure.Internal.0-1:RAID.Integrated.1-1"
}
ok: [ BMC_HOSTNAME ] => (item=racadm --nocertwarn -r IDRAC-HOSTNAME -u IDRAC-USERNAME -p IDRAC-PASSWORD raid converttoraid:Disk.Bay.3:Enclosure.Internal.0-1:RAID.Integrated.1-1) => {
"msg": "racadm --nocertwarn -r IDRAC-HOSTNAME -u IDRAC-USERNAME -p IDRAC-PASSWORD raid converttoraid:Disk.Bay.3:Enclosure.Internal.0-1:RAID.Integrated.1-1"
}
ok: [ BMC_HOSTNAME ] => (item=racadm --nocertwarn -r IDRAC-HOSTNAME -u IDRAC-USERNAME -p IDRAC-PASSWORD raid converttoraid:Disk.Bay.4:Enclosure.Internal.0-1:RAID.Integrated.1-1) => {
"msg": "racadm --nocertwarn -r IDRAC-HOSTNAME -u IDRAC-USERNAME -p IDRAC-PASSWORD raid converttoraid:Disk.Bay.4:Enclosure.Internal.0-1:RAID.Integrated.1-1"
}
ok: [ BMC_HOSTNAME ] => (item=racadm --nocertwarn -r IDRAC-HOSTNAME -u IDRAC-USERNAME -p IDRAC-PASSWORD raid converttoraid:Disk.Bay.5:Enclosure.Internal.0-1:RAID.Integrated.1-1) => {
"msg": "racadm --nocertwarn -r IDRAC-HOSTNAME -u IDRAC-USERNAME -p IDRAC-PASSWORD raid converttoraid:Disk.Bay.5:Enclosure.Internal.0-1:RAID.Integrated.1-1"
}
ok: [ BMC_HOSTNAME ] => (item=racadm --nocertwarn -r IDRAC-HOSTNAME -u IDRAC-USERNAME -p IDRAC-PASSWORD raid converttoraid:Disk.Bay.6:Enclosure.Internal.0-1:RAID.Integrated.1-1) => {
"msg": "racadm --nocertwarn -r IDRAC-HOSTNAME -u IDRAC-USERNAME -p IDRAC-PASSWORD raid converttoraid:Disk.Bay.6:Enclosure.Internal.0-1:RAID.Integrated.1-1"
}
ok: [ BMC_HOSTNAME ] => (item=racadm --nocertwarn -r IDRAC-HOSTNAME -u IDRAC-USERNAME -p IDRAC-PASSWORD raid converttoraid:Disk.Bay.7:Enclosure.Internal.0-1:RAID.Integrated.1-1) => {
"msg": "racadm --nocertwarn -r IDRAC-HOSTNAME -u IDRAC-USERNAME -p IDRAC-PASSWORD raid converttoraid:Disk.Bay.7:Enclosure.Internal.0-1:RAID.Integrated.1-1"
}
ok: [ BMC_HOSTNAME ] => (item=racadm --nocertwarn -r IDRAC-HOSTNAME -u IDRAC-USERNAME -p IDRAC-PASSWORD raid converttoraid:Disk.Bay.8:Enclosure.Internal.0-1:RAID.Integrated.1-1) => {
"msg": "racadm --nocertwarn -r IDRAC-HOSTNAME -u IDRAC-USERNAME -p IDRAC-PASSWORD raid converttoraid:Disk.Bay.8:Enclosure.Internal.0-1:RAID.Integrated.1-1"
}
ok: [ BMC_HOSTNAME ] => (item=racadm --nocertwarn -r IDRAC-HOSTNAME -u IDRAC-USERNAME -p IDRAC-PASSWORD raid converttoraid:Disk.Bay.9:Enclosure.Internal.0-1:RAID.Integrated.1-1) => {
"msg": "racadm --nocertwarn -r IDRAC-HOSTNAME -u IDRAC-USERNAME -p IDRAC-PASSWORD raid converttoraid:Disk.Bay.9:Enclosure.Internal.0-1:RAID.Integrated.1-1"
}
The engine (virtualisation platform) can be automatically determined from the file name.
To do this symlink the type to bam:
ln -s bam idrac
Then do the following:
- name: Example with symlinked file to set engine
idrac:
method: racadm
bmchostname: "{{ bmc_admin_hostname }}"
bmcusername: "{{ bmc_admin_username }}"
bmcpassword: "{{ bmc_admin_password }}"
function: get
object: iDRAC.OS-BMC.AdminState
The engine and function can be automatically determined from the file name.
To do this symlink the type and function to bam in the following method:
ln -s bam bam_get
Then do the following:
- name: Example with symlinked file to set engine
bam_get:
bmctype: idrac
method: racadm
bmchostname: "{{ bmc_admin_hostname }}"
bmcusername: "{{ bmc_admin_username }}"
bmcpassword: "{{ bmc_admin_password }}"
object: iDRAC.OS-BMC.AdminState
There is support for legacy racadm commands. The legacy mode can be enabled by setting the function to config or getconfig.
For example, the legacy racadm command to set the boot once device to VCD-DVD:
racadm config -g cfgServerInfo -o cfgServerFirstBootDevice VCD-DVD
Has the following ansible stanza:
- name: Set the first once device to VCD-DVD using legacy racadm format
bam:
bmctype: idrac
method: racadm
bmchostname: "{{ bmc_admin_hostname }}"
bmcusername: "{{ bmc_admin_username }}"
bmcpassword: "{{ bmc_admin_password }}"
function: config
group: cfgServerInfo
object: cfgServerFirstBootDevice
value: VCD-DVD
The newer command for this is:
racadm set iDRAC.serverboot.FirstBootDevice VCD-DV
The ansible stanze for using he newer method is:
- name: Set the first once device to VCD-DVD using newer racadm format
bam:
bmctype: idrac
method: racadm
bmchostname: "{{ bmc_admin_hostname }}"
bmcusername: "{{ bmc_admin_username }}"
bmcpassword: "{{ bmc_admin_password }}"
function: set
object: cfgServerFirstBootDevice
value: VCD-DVD
Get physical disk infomation:
- name: Get Physical Disk Information
bam:
bmctype: idrac
method: racadm
bmchostname: "{{ bmc_admin_hostname }}"
bmcusername: "{{ bmc_admin_username }}"
bmcpassword: "{{ bmc_admin_password }}"
function: raid
subfunction: get
object: pdisks
register: pdisks
- name: Output Physical Disk Information
debug:
msg: "{{ pdisks.stdout_lines }}"
Example output:
TASK [Ouput Physical Disks] *************************************
ok: [ BMC_HOSTNAME ] => {
"msg": [
"Disk.Bay.0:Enclosure.Internal.0-1:RAID.Integrated.1-1",
"Disk.Bay.1:Enclosure.Internal.0-1:RAID.Integrated.1-1",
"Disk.Bay.2:Enclosure.Internal.0-1:RAID.Integrated.1-1",
"Disk.Bay.3:Enclosure.Internal.0-1:RAID.Integrated.1-1",
"Disk.Bay.4:Enclosure.Internal.0-1:RAID.Integrated.1-1",
"Disk.Bay.5:Enclosure.Internal.0-1:RAID.Integrated.1-1",
"Disk.Bay.6:Enclosure.Internal.0-1:RAID.Integrated.1-1",
"Disk.Bay.7:Enclosure.Internal.0-1:RAID.Integrated.1-1",
"Disk.Bay.8:Enclosure.Internal.0-1:RAID.Integrated.1-1",
"Disk.Bay.9:Enclosure.Internal.0-1:RAID.Integrated.1-1"
]
}
Get virtual disk information:
- name: Get Virtual Disk Information
bam:
bmctype: idrac
method: racadm
bmchostname: "{{ bmc_admin_hostname }}"
bmcusername: "{{ bmc_admin_username }}"
bmcpassword: "{{ bmc_admin_password }}"
function: raid
subfunction: get
object: vdisks
register: pdisks
- name: Output pdisks
debug:
msg: "{{ vdisks.stdout_lines }}"
Example output:
TASK [Print Virtual Disk Information] ********
ok: [ BMC_HOSTNAME ] => {
"msg": [
"Disk.Virtual.0:RAID.Integrated.1-1",
"Disk.Virtual.1:RAID.Integrated.1-1",
"Disk.Virtual.2:RAID.Integrated.1-1"
]
}
Get verbose virtual disk information:
- name: Get Virtual Disk Information
bam:
bmctype: idrac
method: racadm
bmchostname: "{{ bmc_admin_hostname }}"
bmcusername: "{{ bmc_admin_username }}"
bmcpassword: "{{ bmc_admin_password }}"
function: raid
subfunction: get
object: vdisks
details: true
register: pdisks
- name: Output pdisks
debug:
msg: "{{ vdisks.stdout_lines }}"
Example verbose output:
TASK [Print Virtual Disk Information] ***********************************************************************************************
ok: [ BMC_HOSTNAME ] => {
"msg": [
"Disk.Virtual.0:RAID.Integrated.1-1",
" Status = Unknown ",
" DeviceDescription = Virtual Disk 0 on Integrated RAID Controller 1",
" Name = boot ",
" RollupStatus = Unknown ",
" State = Online ",
" OperationalState = Not applicable ",
" Layout = Raid-1 ",
" Size = 893.75 GB ",
" SpanDepth = 1 ",
" AvailableProtocols = SATA ",
" MediaType = SSD ",
" ReadPolicy = Read Ahead ",
" WritePolicy = Write Back ",
" StripeSize = 64K ",
" DiskCachePolicy = Default ",
" BadBlocksFound = NO ",
" Secured = NO ",
" RemainingRedundancy = 1 ",
" EnhancedCache = Not Applicable ",
" T10PIStatus = Disabled ",
" BlockSizeInBytes = 512 ",
"Disk.Virtual.1:RAID.Integrated.1-1",
" Status = Unknown ",
" DeviceDescription = Virtual Disk 1 on Integrated RAID Controller 1",
" Name = data ",
" RollupStatus = Unknown ",
" State = Online ",
" OperationalState = Not applicable ",
" Layout = Raid-10 ",
" Size = 2681.25 GB ",
" SpanDepth = 1 ",
" AvailableProtocols = SATA ",
" MediaType = SSD ",
" ReadPolicy = Read Ahead ",
" WritePolicy = Write Back ",
" StripeSize = 64K ",
" DiskCachePolicy = Default ",
" BadBlocksFound = NO ",
" Secured = NO ",
" RemainingRedundancy = 1 ",
" EnhancedCache = Not Applicable ",
" T10PIStatus = Disabled ",
" BlockSizeInBytes = 512 ",
"Disk.Virtual.2:RAID.Integrated.1-1",
" Status = Unknown ",
" DeviceDescription = Virtual Disk 2 on Integrated RAID Controller 1",
" Name = backup ",
" RollupStatus = Unknown ",
" State = Online ",
" OperationalState = Not applicable ",
" Layout = Raid-1 ",
" Size = 3576.38 GB ",
" SpanDepth = 1 ",
" AvailableProtocols = SATA ",
" MediaType = SSD ",
" ReadPolicy = Read Ahead ",
" WritePolicy = Write Back ",
" StripeSize = 64K ",
" DiskCachePolicy = Default ",
" BadBlocksFound = NO ",
" Secured = NO ",
" RemainingRedundancy = 1 ",
" EnhancedCache = Not Applicable ",
" T10PIStatus = Disabled ",
" BlockSizeInBytes = 512 "
]
}
Set the Lifecyle Controller to collect system inventory on reset using SSH:
- name: Set the Lifecyle Controller to collect system inventory on reset
bam:
bmctype: idrac
method: ssh
bmchostname: "{{ bmc_admin_hostname }}"
bmcusername: "{{ bmc_admin_username }}"
bmcpassword: "{{ bmc_admin_password }}"
function: get
objectgroup: LifecycleController.Embedded.1
object: LCAttributes.1#CollectSystemInventoryOnRestart
value: Enabled
Get the AMT system Model name from the System information:
- name: Get AMT object value via http(s)
bam:
bmctype: amt
method: http
bmchostname: "{{ ansible_host }}"
bmcusername: "{{ amt_username }}"
bmcpassword: "{{ amt_password }}"
objectgroup: "system"
object: "model"
function: get
execute: "{{ execute_get }}"
Execute a command directly:
- name: Set one time boot device to BIOS
bam:
bmctype: idrac
method: ssh
bmchostname: "{{ bmc_admin_hostname }}"
bmcusername: "{{ bmc_admin_username }}"
bmcpassword: "{{ bmc_admin_password }}"
function: execute
bmccommand: racadm set iDRAC.serverboot.FirstBootDevice BIOS
Module version of previous command:
- name: Set one time boot device to BIOS
bam:
bmctype: idrac
method: ssh
bmchostname: "{{ bmc_admin_hostname }}"
bmcusername: "{{ bmc_admin_username }}"
bmcpassword: "{{ bmc_admin_password }}"
function: set
object: iDRAC.serverboot.FirstBootDevice
value: BIOS
This example steps through the set up of a RAID controller and virtual disks
Reset RAID config:
- name: Reset RAID config
bam:
bmctype: idrac
method: racadm
bmchostname: "{{ bmc_admin_hostname }}"
bmcusername: "{{ bmc_admin_username }}"
bmcpassword: "{{ bmc_admin_password }}"
function: raid
resetconfig: RAID.Integrated.1-1
register: raidreset_status
- name: Create variable for RAID reset status
debug:
var: raidreset_status
- name: Create a job for RAID reset
bam:
bmctype: idrac
method: racadm
bmchostname: "{{ bmc_admin_hostname }}"
bmcusername: "{{ bmc_admin_username }}"
bmcpassword: "{{ bmc_admin_password }}"
function: raid
subfunction: jobqueue
create: RAID.Integrated.1-1
register: raidreset_job
- name: Create variable for RAID reset job
debug:
var: raidreset_job
- name: Powercycle server to execute RAID controller reset job
bam:
bmctype: idrac
method: racadm
bmchostname: "{{ bmc_admin_hostname }}"
bmcusername: "{{ bmc_admin_username }}"
bmcpassword: "{{ bmc_admin_password }}"
function: serveraction
subfunction: powercycle
register: raidreset_reboot
when: raidreset_job != ''
- name: Create a variable for RAID reset reboot
debug:
var: raidreset_reboot
- name: Wait for RAID Reset job to be completed
bam:
bmctype: idrac
method: racadm
bmchostname: "{{ bmc_admin_hostname }}"
bmcusername: "{{ bmc_admin_username }}"
bmcpassword: "{{ bmc_admin_password }}"
function: jobqueue
subfunction: view
register: raidreset_jobstatus
until: raidreset_jobstatus.stdout.find("Running") <= 0 and raidreset_jobstatus.stdout.find("Scheduled") <= 0 and raidreset_jobstatus.stdout.find("New") <= 0
retries: 20
delay: 30
when: '"Server power operation successful" in raidreset_reboot.stdout_lines'
Create virtual disks:
- name: Create a variable for RAID reset job status
debug: var=raidreset_jobstatus
- name: Check whether RAID reset deleted all the Virtual Disks
bam:
bmctype: idrac
method: racadm
bmchostname: "{{ bmc_admin_hostname }}"
bmcusername: "{{ bmc_admin_username }}"
bmcpassword: "{{ bmc_admin_password }}"
function: raid
subfunction: get
object: vdisks
register: vdisk_status
- name: Create a variable for vdisk status
debug:
var: vdisks_status
- name: Setup Hardware RAID-1 across first two disks
bam:
bmctype: idrac
method: racadm
bmchostname: "{{ bmc_admin_hostname }}"
bmcusername: "{{ bmc_admin_username }}"
bmcpassword: "{{ bmc_admin_password }}"
function: raid
createvd: RAID.Integrated.1-1
name: boot
raidlevel: r1
writepolicy: wt
readpolicy: ra
diskcachepolicy: default
stripesize: 64
pdkey: Disk.Bay.0:Enclosure.Internal.0-1:RAID.Integrated.1-1,Disk.Bay.1:Enclosure.Internal.0-1:RAID.Integrated.1-1
register: vdisk1_raid_status
when: vdisks_status is search("No virtual disks")
- name: Create a variable for RAID status
debug:
var: vdisk1_raid_status
- name: Setup Hardware RAID-10 across next six disks
bam:
bmctype: idrac
method: racadm
bmchostname: "{{ bmc_admin_hostname }}"
bmcusername: "{{ bmc_admin_username }}"
bmcpassword: "{{ bmc_admin_password }}"
function: raid
createvd: RAID.Integrated.1-1
name: data
raidlevel: r10
writepolicy: wt
readpolicy: ra
diskcachepolicy: default
stripesize: 64
pdkey: Disk.Bay.2:Enclosure.Internal.0-1:RAID.Integrated.1-1,Disk.Bay.3:Enclosure.Internal.0-1:RAID.Integrated.1-1,Disk.Bay.4:Enclosure.Internal.0-1:RAID.Integrated.1-1,Disk.Bay.5:Enclosure.Internal.0-1:RAID.Integrated.1-1,Disk.Bay.6:Enclosure.Internal.0-1:RAID.Integrated.1-1,Disk.Bay.7:Enclosure.Internal.0-1:RAID.Integrated.1-1
register: vdisk2_raid_status
when: vdisks_status is search("No virtual disks")
- name: Create a variable for RAID status
debug:
var: vdisk2_raid_status
- name: Setup Hardware RAID-1 across last two disks
bam:
bmctype: idrac
method: racadm
bmchostname: "{{ bmc_admin_hostname }}"
bmcusername: "{{ bmc_admin_username }}"
bmcpassword: "{{ bmc_admin_password }}"
function: raid
createvd: RAID.Integrated.1-1
name: boot
raidlevel: r1
writepolicy: wt
readpolicy: ra
diskcachepolicy: backup
stripesize: 64
pdkey: Disk.Bay.8:Enclosure.Internal.0-1:RAID.Integrated.1-1,Disk.Bay.9:Enclosure.Internal.0-1:RAID.Integrated.1-1
register: vdisk3_raid_status
when: vdisks_status is search("No virtual disks")
- name: Create a variable for RAID status
debug:
var: vdisk3_raid1_status
- name: Create a job for RAID-1 configuration
bam:
bam:
bmctype: idrac
method: racadm
bmchostname: "{{ bmc_admin_hostname }}"
bmcusername: "{{ bmc_admin_username }}"
bmcpassword: "{{ bmc_admin_password }}"
function: raid
subfunction: jobqueue
queue: RAID.Integrated.1-1
register: register: vdisks_raid_job
failed_when: disks_raid_job.stdout is seach("ERROR")
when: vdisks_status is search("No virtual disks")
- name: Create a variable for RAID configuration job
debug:
var: vdisks_raid_job
This is an example to update firmware using a bootable ISO:
- name: Power off server
bam:
bmctype: idrac
method: racadm
bmchostname: "{{ bmc_hostname }}"
bmcusername: "{{ bmc_username }}"
bmcpassword: "{{ bmc_password }}"
function: serveraction
subfunction: powerdown
- name: Disconnect remote ISO
bam:
bmctype: idrac
method: racadm
bmchostname: "{{ bmc_hostname }}"
bmcusername: "{{ bmc_username }}"
bmcpassword: "{{ bmc_password }}"
function: remoteimage
disconnect: true
- name: Connect remote ISO
bam:
bmctype: idrac
method: racadm
bmchostname: "{{ bmc_hostname }}"
bmcusername: "{{ bmc_username }}"
bmcpassword: "{{ bmc_password }}"
function: remoteimage
connect: true
location: "{{ nfs_server }}/{{ firmware_iso }}"
- name: Set one time boot to enabled
bam:
bmctype: idrac
method: racadm
bmchostname: "{{ bmc_hostname }}"
bmcusername: "{{ bmc_username }}"
bmcpassword: "{{ bmc_password }}"
function: set
object: iDRAC.serverboot.BootOnce
value: 1
- name: Set one time boot device to VCD-DVD
bam:
bmctype: idrac
method: racadm
bmchostname: "{{ bmc_hostname }}"
bmcusername: "{{ bmc_username }}"
bmcpassword: "{{ bmc_password }}"
function: set
object: iDRAC.serverboot.FirstBootDevice
value: VCD-DVD
- name: Power on server
bam:
bmctype: idrac
method: racadm
bmchostname: "{{ bmc_hostname }}"
bmcusername: "{{ bmc_username }}"
bmcpassword: "{{ bmc_password }}"
function: serveraction
subfunction: powerup
This example sets up an Admin user:
- name: Get User 4 Name
bam:
bmctype: idrac
method: racadm
bmchostname: "{{ bmc_hostname }}"
bmcusername: "{{ bmc_username }}"
bmcpassword: "{{ bmc_password }}"
function: get
object: iDRAC.Users.4.UserName
register: get_user4_name
- name: Set User 4 Name if not correct
bam:
bmctype: idrac
method: racadm
bmchostname: "{{ bmc_hostname }}"
bmcusername: "{{ bmc_username }}"
bmcpassword: "{{ bmc_password }}"
function: set
object: iDRAC.Users.4.UserName
value: "{{ bmc_sysadmin }}"
register: set_user4_name
when: get_user4_name != bmc_sysadmin
- name: Get User 4 Name
bam:
bmctype: idrac
method: racadm
bmchostname: "{{ bmc_hostname }}"
bmcusername: "{{ bmc_username }}"
bmcpassword: "{{ bmc_password }}"
function: get
object: iDRAC.Users.4.UserName
searchforvalue: UserName
register: get_user4_name
when: get_user4_name != bmc_sysadmin
- name: Output command
debug:
msg: "{{ get_user4_name.value }}"
- name: Get User 4 Enabled status
bam:
bmctype: idrac
method: racadm
bmchostname: "{{ bmc_hostname }}"
bmcusername: "{{ bmc_username }}"
bmcpassword: "{{ bmc_password }}"
function: get
object: iDRAC.Users.4.Enable
register: get_user4_enable
- name: Get User 4 SHA256Password key to check if password is set
bam:
bmctype: idrac
method: racadm
bmchostname: "{{ bmc_hostname }}"
bmcusername: "{{ bmc_username }}"
bmcpassword: "{{ bmc_password }}"
function: get
object: iDRAC.Users.4.SHA256Password
register: get_user4_password
- name: Output command
debug:
msg: "{{ get_user4_password.command }}"
- name: Output command
debug:
msg: "{{ get_user4_password.value }}"
- name: Output command
debug:
msg: "{{ get_user4_name.value }}"
- name: Set User 4 Password
bam:
bmctype: idrac
method: racadm
bmchostname: "{{ bmc_hostname }}"
bmcusername: "{{ bmc_username }}"
bmcpassword: "{{ bmc_password }}"
function: set
object: iDRAC.Users.4.Password
value: "{{ bmc_password }}"
register: set_user4_password
when: get_user4_name.value == bmc_sysadmin and get_user4_enable.value == "Disabled" and get_user4_password.value == ""
- name: Set User 4 Enabled status
bam:
bmctype: idrac
method: racadm
bmchostname: "{{ bmc_hostname }}"
bmcusername: "{{ bmc_username }}"
bmcpassword: "{{ bmc_password }}"
function: set
object: iDRAC.Users.4.Enable
value: 1
register: set_user4_enable
when: get_user4_name.value == bmc_sysadmin and get_user4_enable.value == "Disabled"
- name: Get User 4 IPMI LAN Privilege
bam:
bmctype: idrac
method: racadm
bmchostname: "{{ bmc_hostname }}"
bmcusername: "{{ bmc_username }}"
bmcpassword: "{{ bmc_password }}"
function: get
object: iDRAC.Users.4.IpmiLanPrivilege
register: get_user4_ipmi_lan_privilege
when: get_user4_name.value == bmc_sysadmin
- name: Set User 4 IPMI LAN Privilege if required
bam:
bmctype: idrac
method: racadm
bmchostname: "{{ bmc_hostname }}"
bmcusername: "{{ bmc_username }}"
bmcpassword: "{{ bmc_password }}"
function: set
object: iDRAC.Users.4.IpmiLanPrivilege
value: 4
register: set_user4_ipmi_lan_privilege
when: get_user4_name.value == bmc_sysadmin and not get_user4_ipmi_lan_privilege.value == "4"
- name: Get User 4 IPMI Serial Privilege
bam:
bmctype: idrac
method: racadm
bmchostname: "{{ bmc_hostname }}"
bmcusername: "{{ bmc_username }}"
bmcpassword: "{{ bmc_password }}"
function: get
object: iDRAC.Users.4.IpmiSerialPrivilege
register: get_user4_ipmi_serial_privilege
when: get_user4_name.value == bmc_sysadmin
- name: Set User 4 IPMI Serial Privilege
bam:
bmctype: idrac
method: racadm
bmchostname: "{{ bmc_hostname }}"
bmcusername: "{{ bmc_username }}"
bmcpassword: "{{ bmc_password }}"
function: set
object: iDRAC.Users.4.IpmiSerialPrivilege
value: 4
register: set_user4_ipmi_serial_privilege
when: get_user4_name.value == bmc_sysadmin and not get_user4_ipmi_serial_privilege.value == "4"
- name: Get User 4 Privilege
bam:
bmctype: idrac
method: racadm
bmchostname: "{{ bmc_hostname }}"
bmcusername: "{{ bmc_username }}"
bmcpassword: "{{ bmc_password }}"
function: get
object: iDRAC.Users.4.Privilege
register: get_user4_privilege
when: get_user4_name.value == bmc_sysadmin
- name: Set User 4 Privilege
bam:
bmctype: idrac
method: racadm
bmchostname: "{{ bmc_hostname }}"
bmcusername: "{{ bmc_username }}"
bmcpassword: "{{ bmc_password }}"
function: set
object: iDRAC.Users.4.Privilege
value: 0x1ff
register: set_user4_privilege
when: get_user4_name.value == bmc_sysadmin and not get_user4_ipmi_serial_privilege.value == "0x1ff"
- name: Get User 4 SOL Enabled status
bam:
bmctype: idrac
method: racadm
bmchostname: "{{ bmc_hostname }}"
bmcusername: "{{ bmc_username }}"
bmcpassword: "{{ bmc_password }}"
function: get
object: iDRAC.Users.4.SolEnable
register: get_user4_sol_enable
when: get_user4_name.value == bmc_sysadmin
- name: Output command
debug:
msg: "{{ get_user4_sol_enable.command }}"
when: get_user4_name.value == bmc_sysadmin
- name: Set User 4 SOL Enable
bam:
bmctype: idrac
method: racadm
bmchostname: "{{ bmc_hostname }}"
bmcusername: "{{ bmc_username }}"
bmcpassword: "{{ bmc_password }}"
function: set
object: iDRAC.Users.4.SolEnable
value: Enabled
register: set_user4_sol_enable
when: get_user4_name.value == bmc_sysadmin and not get_user4_sol_enable.value == "Disabled"
- name: Get User 4 SNMP Enabled status
bam:
bmctype: idrac
method: racadm
bmchostname: "{{ bmc_hostname }}"
bmcusername: "{{ bmc_username }}"
bmcpassword: "{{ bmc_password }}"
function: get
object: iDRAC.Users.4.SNMPv3Enable
register: get_user4_snmp_enable
when: get_user4_name.value == bmc_sysadmin
- name: Set User 4 SNMP Enable
bam:
bmctype: idrac
method: racadm
bmchostname: "{{ bmc_hostname }}"
bmcusername: "{{ bmc_username }}"
bmcpassword: "{{ bmc_password }}"
function: set
object: iDRAC.Users.4.SolEnable
value: Enabled
register: set_user4_snmp_enable
when: get_user4_name.value == bmc_sysadmin and not get_user4_snmp_enable.value == "Disabled"
This example sets up SSH keys:
- name: Get User 4 Name
bam:
bmctype: idrac
method: racadm
bmchostname: "{{ bmc_hostname }}"
bmcusername: "{{ bmc_username }}"
bmcpassword: "{{ bmc_password }}"
function: get
object: iDRAC.Users.4.UserName
register: get_user4_name
- name: Get User 4 SSH key
bam:
bmctype: idrac
method: racadm
bmchostname: "{{ bmc_hostname }}"
bmcusername: "{{ bmc_username }}"
bmcpassword: "{{ bmc_password }}"
function: sshpkauth
subfunction: view
userindex: 4
keyindex: 1
register: get_user4_sshkey
when: get_user4_name.value == bmc_sysadmin
- name: Get SSH key if user 4 is sysadmin
bam:
bmctype: idrac
method: racadm
bmchostname: "{{ bmc_hostname }}"
bmcusername: "{{ bmc_username }}"
bmcpassword: "{{ bmc_password }}"
function: sshpkauth
userindex: 4
keyindex: 1
text: "{{ bmc_sshkey_text }}"
execute: false
register: set_user4_sshkey
when: get_user4_name.value == bmc_sysadmin and not get_user4_sshkey.value == bmc_sshkey_text