]> git.apps.os.sepia.ceph.com Git - ceph-cm-ansible.git/commitdiff
firmware: New role. Adding BIOS and BMC support for mira
authorDavid Galloway <dgallowa@redhat.com>
Fri, 14 Oct 2016 17:05:27 +0000 (13:05 -0400)
committerDavid Galloway <dgallowa@redhat.com>
Fri, 4 Nov 2016 18:48:56 +0000 (14:48 -0400)
Signed-off-by: David Galloway <dgallowa@redhat.com>
firmware.yml [new file with mode: 0644]
roles/firmware/defaults/main.yml [new file with mode: 0644]
roles/firmware/tasks/main.yml [new file with mode: 0644]
roles/firmware/tasks/mira/bios-update.yml [new file with mode: 0644]
roles/firmware/tasks/mira/bios.yml [new file with mode: 0644]
roles/firmware/tasks/mira/bmc-update.yml [new file with mode: 0644]
roles/firmware/tasks/mira/bmc.yml [new file with mode: 0644]

diff --git a/firmware.yml b/firmware.yml
new file mode 100644 (file)
index 0000000..a1e9124
--- /dev/null
@@ -0,0 +1,12 @@
+---
+# "any_errors_fatal: true" makes sure the run stops if any problems happen.
+# This gives you the ability to flash backed up firmwares or diagnose
+# problems without the playbook cleaning up after itself or causing more damage.
+
+- hosts: all
+  any_errors_fatal: true
+  strategy: free
+  roles:
+    - secrets
+    - firmware
+  become: true
diff --git a/roles/firmware/defaults/main.yml b/roles/firmware/defaults/main.yml
new file mode 100644 (file)
index 0000000..5897fbf
--- /dev/null
@@ -0,0 +1,9 @@
+---
+# Defaults should be overridden in the secrets repo in each machine type's
+# group_vars file
+latest_bios_version: null
+latest_bmc_version: null
+
+flashrom_location: "http://download.flashrom.org/releases/flashrom-0.9.9.tar.bz2"
+
+firmware_update_path: "/home/{{ ansible_user }}/firmware-update"
diff --git a/roles/firmware/tasks/main.yml b/roles/firmware/tasks/main.yml
new file mode 100644 (file)
index 0000000..a3bb2e8
--- /dev/null
@@ -0,0 +1,19 @@
+---
+- include: mira/bios.yml
+  tags:
+    - bios
+  when: '"mira" in ansible_hostname'
+
+- include: mira/bmc.yml
+  tags:
+    - bmc
+  when: '"mira" in ansible_hostname'
+
+# This won't get run if a previous playbook fails.  So if a backup of a BIOS is
+# needed to restore, it'll still be there
+- name: Clean up firmware update directory
+  file:
+    path: "{{ firmware_update_path }}"
+    state: absent
+  tags:
+    - always
diff --git a/roles/firmware/tasks/mira/bios-update.yml b/roles/firmware/tasks/mira/bios-update.yml
new file mode 100644 (file)
index 0000000..bcee809
--- /dev/null
@@ -0,0 +1,75 @@
+---
+# This file is only called when current_bios_version
+# and latest_bios_version do not match
+
+- name: Install packages for CentOS/RHEL
+  yum:
+    name: "{{ item }}"
+    state: latest
+  with_items:
+    - pciutils-devel
+    - zlib-devel
+    - libftdi-devel
+    - libusb-devel
+    - make
+    - gcc
+  when: ansible_pkg_mgr == "yum"
+
+- name: Install packages for Ubuntu
+  apt:
+    name: "{{ item }}"
+    state: latest
+  with_items:
+    - flashrom
+  when: ansible_pkg_mgr == "apt"
+
+# Flashrom has to be built on CentOS so we add an extra dir for it
+# This is equivalent to 'mkdir -p'
+- name: Create BIOS update working directory structure
+  file:
+    path: "{{ firmware_update_path }}/bios-update/flashrom"
+    state: directory
+
+# This file must be the already-extracted binary blob from the Supermicro
+# firmware archive.  Naming scheme is PPPPPY.MDD
+# PPPPP = Project name; Y = Year; M = Month; DD = Day
+# We rename it to 'new-bios' here so the playbook can consume a universal name
+- name: Download BIOS binary
+  get_url:
+    url: "{{ bios_location }}"
+    dest: "{{ firmware_update_path }}/bios-update/new-bios"
+
+# There is flashrom RPM in any trusted repositories so we have to compile it
+- name: Download flashrom archive (CentOS)
+  get_url:
+    url: "{{ flashrom_location }}"
+    dest: "{{ firmware_update_path }}/bios-update/flashrom.tar.bz2"
+    validate_certs: no
+  when: ansible_pkg_mgr == "yum"
+
+# The flashrom tarballs extract to a directory with its version number by default
+# '--strip-components 1' gets rid of that dir so the playbook can run with any
+# flashrom version
+- name: Extract flashrom (CentOS)
+  shell: "tar -xjf {{ firmware_update_path }}/bios-update/flashrom.tar.bz2 --directory {{ firmware_update_path }}/bios-update/flashrom --strip-components 1"
+  when: ansible_pkg_mgr == "yum"
+
+- name: Compile flashrom (CentOS)
+  shell: "cd {{ firmware_update_path }}/bios-update/flashrom && make"
+  when: ansible_pkg_mgr == "yum"
+
+- name: Back up existing BIOS (CentOS)
+  shell: "cd {{ firmware_update_path }}/bios-update && flashrom/flashrom --programmer internal --read BIOS.bak"
+  when: ansible_pkg_mgr == "yum"
+
+- name: Flash new BIOS (CentOS)
+  shell: "cd {{ firmware_update_path }}/bios-update && flashrom/flashrom --programmer internal --write new-bios"
+  when: ansible_pkg_mgr == "yum"
+
+- name: Back up existing BIOS (Ubuntu)
+  shell: "flashrom -p internal:Supermicro:X8SIL --read {{ firmware_update_path }}/bios-update/BIOS.bak"
+  when: ansible_pkg_mgr == "apt"
+
+- name: Flash new BIOS (Ubuntu)
+  shell: "flashrom -p internal:Supermicro:X8SIL --write {{ firmware_update_path }}/bios-update/new-bios"
+  when: ansible_pkg_mgr == "apt"
diff --git a/roles/firmware/tasks/mira/bios.yml b/roles/firmware/tasks/mira/bios.yml
new file mode 100644 (file)
index 0000000..8a197bc
--- /dev/null
@@ -0,0 +1,14 @@
+---
+- name: Determine current BIOS firmware version
+  shell: dmidecode --type bios | grep Version | awk '{ print $2 }'
+  register: current_bios_version
+  changed_when: False
+
+- name: Determine if BIOS update is needed
+  set_fact:
+    need_bios_update: true
+  when: current_bios_version.stdout != latest_bios_version
+
+- name: Include BIOS update logic
+  include: roles/firmware/tasks/mira/bios-update.yml
+  when: need_bios_update is defined and need_bios_update == true
diff --git a/roles/firmware/tasks/mira/bmc-update.yml b/roles/firmware/tasks/mira/bmc-update.yml
new file mode 100644 (file)
index 0000000..cac2590
--- /dev/null
@@ -0,0 +1,30 @@
+---
+# This file is only called when current_bmc_version
+# and latest_bmc_version do not match
+
+- name: Install unzip
+  package:
+    name: unzip
+    state: latest
+
+- name: Create BMC update working directory structure
+  file:
+    path: "{{ firmware_update_path }}/bmc-update"
+    state: directory
+
+# Download the archive and rename to something the playbook can consume
+- name: Download BMC archive
+  get_url:
+    url: "{{ bmc_location }}"
+    dest: "{{ firmware_update_path }}/bmc-update/bmc.zip"
+    force: yes
+
+- name: Extract IPMI archive
+  shell: "cd {{ firmware_update_path }}/bmc-update && unzip bmc.zip"
+
+- name: Flash new BMC (Takes around 5 minutes)
+  shell: "cd {{ firmware_update_path }}/bmc-update/Linux* && chmod +x lUpdate && ./lUpdate -f ../*.bin -i kcs -r y"
+  register: bmc_flash_output
+
+# Print output of flash script
+- debug: var=bmc_flash_output.stdout_lines|last
diff --git a/roles/firmware/tasks/mira/bmc.yml b/roles/firmware/tasks/mira/bmc.yml
new file mode 100644 (file)
index 0000000..179d964
--- /dev/null
@@ -0,0 +1,27 @@
+---
+- name: Install ipmitool
+  package:
+    name: ipmitool
+    state: latest
+
+- name: Enable IPMI kernel modules
+  modprobe:
+    name: "{{ item }}"
+    state: present
+  with_items:
+    - ipmi_devintf
+    - ipmi_si
+
+- name: Determine current BMC firmware version
+  shell: ipmitool mc info | grep "Firmware Revision" | awk '{ print $4 }'
+  register: current_bmc_version
+  changed_when: False
+
+- name: Determine if BMC update is needed
+  set_fact:
+    need_bmc_update: true
+  when: current_bmc_version.stdout != latest_bmc_version
+
+- name: Include BMC update logic
+  include: roles/firmware/tasks/mira/bmc-update.yml
+  when: need_bmc_update is defined and need_bmc_update == true