Skip to content
Go to file
Cannot retrieve contributors at this time
218 lines (177 sloc) 10.7 KB

Formatting Functions for Nova

The following “functions” are useful for formatting org-mode code blocks. This is part of my Library of Babel collection. Remember to hit the C-c C-v i to add these sections.

OpenStack Table

The os-table-str is a :post function for post-processing the output from a nova table output as a string, and re-formats it into a list data structure so that org-mode can reformat it in its own table format.

To use it, add the following source code block header:

:post os-table(data=*this*) :results output

Or better yet, use the following header line:

#+HEADER: :post os-table(data=*this*) :results output

To use os-table make sure that the :results are set to output. Along with data, you can set header=t in order to retain the headers from the nova command.

(cl-flet* ((non-border-p     (line) (not (string-match "^ *[\+-]+-" line)))
           (separate-row     (line) (split-string line " *| *"))

           (trim-cells-front (cells) (if (string-empty-p (car cells))
                                         (cdr cells)
           (trim-cells-back  (cells) (if (string-empty-p (car (last cells)))
                                         (butlast cells)
           (trim-row-cells   (cells) (trim-cells-back (trim-cells-front cells))))

  (let* ((rows (split-string data "[\n\r]+" t))
         (table-data (mapcar #'trim-row-cells
                             (mapcar #'separate-row
                                     (-filter #'non-border-p rows)))))
    (cond ((equalp header "no")   (cdr table-data))
          ((equalp header "yes")  (append (list (car table-data) 'hline) (cdr table-data)))
          ( t                      table-data))))

To verify this code, we first begin with a typical output from a nova list command:

| ID                                   | Name                 | Status | Task State | Power State | Networks             |
| 521fd286-cbdc-42a6-8c33-0e771d4c37c1 | ha-ci-sdn-chefserver | ACTIVE | -          | Running     | cedev13= |
| 542b9f7d-f380-4d67-9eee-f974ba958e3a | ha-ci-sdn-chefserver | ACTIVE | -          | Running     | cedev13= |

Our org-mode source block does nothing more than echo this data as a string, relying on the :post call to do the work:

echo "$input"

Real world example that attempts to access an OpenStack system at a particular IP address. This assumes that the nova credentials are stored in a file in the home directory, openrc (as it will attempt to source those first).

nova list

OpenStack List with Network Addresses

Uses the os-table block, but attempts to clean up the nova list command with better information.

(replace-regexp-in-string "| *cedev[0-9]+=" "| " data)
nova list

Column Removers

If I know the text of a column, this will remove it. This isn’t the most reliable approach, but this needs to be a pre-processor that operates on a string of the results from OpenStack commands.

We take the comma-separated list of column values, colvals, and then use a reduce function to repeatedly call the data variable and remove more and more column sections:

(cl-flet ((resetter (data col)
                    (replace-regexp-in-string (concat "| *" col " *|") "| " data)))
  (let ((vals (split-string colvals " *, *")))
    (cl-reduce #'resetter vals :initial-value data)))

Let’s test this:

nova list

Unique Columns

What if all the data in a column is the same? Why display it? Let’s remove any columns if every value is the same. This is a more robust and easier-to-use solution, however, I don’t know how we can use it as a pre-processor as it expects results as formatted by the os-table.

;; (setq data '(("521fd286-cbdc-42a6-8c33-0e771d4c37c1" "ha-ci-other-server" "ACTIVE" "-" "Running" "cedev13=") ("542b9f7d-f380-4d67-9eee-f974ba958e3a" "ha-ci-sdn-chefserver" "ACTIVE" "-" "Running" "cedev13=")))

(defun column-same-value-p (table column-number)
  "Return `nil' if values in COLUMN-NUMBER are unique. Return
non-nil if the values are all the same."
  (if (cdr table)
      (let ((column-value (column-unique-p (cdr table) column-number)) )
        (when (equalp column-value (nth column-number (car table)))
    (nth column-number (car table))))

(defun remove-column (table column-value)
  "Given a TABLE (a list of lists), removes a column of data
where the first column is 0."
  (cl-flet ((remove-from-list (lst pos) (append
                                         (butlast lst (- (length lst) pos))
                                         (nthcdr (1+ pos) lst))))
    (mapcar (lambda (row) (remove-from-list row column-value)) table)))

(defun remove-table-same-columns (table &optional column-num)
  "Return given TABLE but without any columns were all columns contain the same value."
  (let* ((col (if column-num
                (1- (length (car table)))))
         (next-col (1- col)))
    (if (< col 0)   ;; Ran out of columns? Bail out...
      (let ((modified-table (if (column-same-value-p table col)
                                (remove-column table col)
        (remove-table-same-columns modified-table next-col)))))

(remove-table-same-columns data)

Now, let’s test that monstrosity out.

nova list
You can’t perform that action at this time.