Permalink
Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
219 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)
                                       cells))
           (trim-cells-back  (cells) (if (string-empty-p (car (last cells)))
                                         (butlast cells)
                                       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=10.96.68.204 |
| 542b9f7d-f380-4d67-9eee-f974ba958e3a | ha-ci-sdn-chefserver | ACTIVE | -          | Running     | cedev13=10.96.68.196 |
+--------------------------------------+----------------------+--------+------------+-------------+----------------------+

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=10.96.68.204") ("542b9f7d-f380-4d67-9eee-f974ba958e3a" "ha-ci-sdn-chefserver" "ACTIVE" "-" "Running" "cedev13=10.96.68.196")))

(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)))
          column-value))
    (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
                  column-num
                (1- (length (car table)))))
         (next-col (1- col)))
    (if (< col 0)   ;; Ran out of columns? Bail out...
        table
      (let ((modified-table (if (column-same-value-p table col)
                                (remove-column table col)
                              table)))
        (remove-table-same-columns modified-table next-col)))))

(remove-table-same-columns data)

Now, let’s test that monstrosity out.

nova list