The output looks like this:

 Name: s210_21tb_800gb-ssd_128gb
               Nodes: 1, 2, 3
Requested Protection: +2d:1n
               HDD Used: 13.2094T
               HDD Total: 55.9520T
               HDD % Used: 23.61%

From this output, the following information is extracted.

  • Parity y is the value at the end of the "Requested Protection" line. We want the penultimate character, before the n (1 in this case)
  • The number of nodes cis the last value from the "Nodes:" line
  • The individual capacity in TB m is the value from the "HDD Total" line
  • The used capacity p is similarly the value from the "HDD used" line

Based on these values, we perform the following calculations.

  • Total = m /c * (c-y) TB
  • Effective Total volume = m / c * (c-y)*0.8 TB
  • Used = p / c TB
  • Effective used = p / c* (c-y)*0.8 TB
  • Available volume = (m - p)/c * (c-y)*0.8 TB

Is it possible to get the below output in table with python scripting?

Here is our current script:

y=$(grep -n Protection storage_info | cut -d ':' -f4 | cut -c1)
echo y=$y
c=$(grep -n Node storage_info | awk '{print substr($0,length,1)}')
echo c=$c
m=$(grep "HDD Total" storage_info | cut -d ':' -f2|rev|cut -c 2- | rev)
echo m=$m
p=$(grep "HDD Used" storage_info_info | cut -d ':' -f2|rev|cut -c 2- | rev)
echo p=$p
echo parity=$y
echo Nodenumber=$c
div=$(echo $m/$c| bc)
div1=$(echo $p/$c| bc)
minus=$(echo $c-$y|bc)
minus1=$(echo $m-$p|bc)
Total=$(echo $div \* $minus |bc)
echo "Total = $Total TB"
EffectiveTotalvolume=$(echo $div \* $minus \* 0.8 |bc)
echo "Effective Total volume = $EffectiveTotalvolume TB"
echo "USED =$div1 TB"
Effectiveused=$(echo $div1 \* $minus \* 0.8 |bc)
echo "Effective used=$Effectiveused TB"
Availablevolume=$(echo $minus1/$c \* $minus \* 0.8|bc)
echo "Available volume=$Availablevolume TB"

Here is the desired output:

Total = 36 TB
Effective Total volume = 28.8 TB
Effective used=6.4 TB
Available volume=22.4 TB

(The values do not correspond to the example output, they are different runs, sorry.)

closed as unclear what you're asking by G-Man, dr01, countermode, Jeff Schaller, Archemar Apr 20 '17 at 14:37

Please clarify your specific problem or add additional details to highlight exactly what you need. As it's currently written, it’s hard to tell exactly what you're asking. See the How to Ask page for help clarifying this question. If this question can be reworded to fit the rules in the help center, please edit the question.

  • You seem to be asking us to rewrite a Bash script into a Python script. Why do you want that? What have you tried yourself and where are you stuck? I agree that the Bash script is hideously ugly but moving to Awk might be a smaller and more natural step. – tripleee Apr 20 '17 at 2:55
  • @tripleee I am asking is it possible to create a table in python. – Mongrel Apr 20 '17 at 3:07
  • That's not a very articulated question; a similarly precise answer is "yes". Generally, if it can be done in Bash, it can certainly be done in Python as well (though the two have some relative strengths and weaknesses of course). Formatting printed output is not very hard in most languages. But then what's the rationale for including this repetitive Bash script -- maybe pare it down to a single bc plus echo clause and ask how to do that? – tripleee Apr 20 '17 at 3:18
  • if 'Protection' in line: y=line.split(':')[3][0:1] – tripleee Apr 20 '17 at 3:21
  • print('Effective total volume = {0} TB'.format(div * minus * 0.8)) – tripleee Apr 20 '17 at 3:22

Indeed, Python has versatile and detailed print formatting facilities. A nice overview is available at https://pyformat.info/ with code examples, etc.

However, I'm guessing your real question here is "how can I fix this script so it is less brittle". My suggestion would be to go with Awk.

The general syntax of an Awk script is a sequence of condition { action } blocks. Awk reads a line of the input file and tests it against each condition. The condition can typically be a regular expression which is true if the regex matches anywhere in the current line. If the condition is true, the action is executed.

substr and length are functions which do what you expect and $n addresses the nth field of the current line (by default, the line is simply split into fields on whitespace, though this too is configurable). NF is a variable which contains the number of fields on the current line; so $NF refers to the last field on the current line.

Finally, the END condition is executed when the input file(s) have all been read. (There is also a BEGIN condition you can use to do things before any input has been read.)

isi storagepool list -v |
awk '# Assume parity is second to last character on this line?
    /Requested Protection:/ { parity=substr($NF,length($NF)-1,1) }
    /Nodes:/ { nodes=$NF }
    /HDD Total/ { hdd_total=$NF }  # Awk helpfully ignores T suffix
    /HDD Used/ { hdd_used=$NF }    # here too
    END {
        print "Total = " total " TB"
        print "Effective Total volume = " total*0.8 " TB"
        print "USED =" used " TB"                         # no space after =, really?
        print "Effective used=" used*multiplier*0.8 " TB" # double ditto
        print "Available volume=" (hdd_total-hdd_used)/nodes*multiplier*0.8 " TB" }'

None of your examples contain four colon-separated fields in the "Requested Protection" output so it's not clear how exactly your script handles that; but based on your description, we grab the second to last character from the last field with substr and length.

The HDD fields contain a T suffix in your example but Awk simply disregards that when doing arithmetic on the extracted number so we simply leave it in. (If the suffix could be M or G as well, that would be a problem, though!)

Googling for isi storagepool doesn't really produce any useful documentation for me. (But it seems that there is indeed no way to get properly machine-readable output from this tool, which would be absolutely the best option. Many tools have an option to produce XML or JSON output so you don't have to roll your own parser for every tool you want to automate.)

This could still fail if nothing matches Nodes: in particular (then you'll get division by zero errors) but overall, I think you'll agree that this is more elegant, more readable, more robust, and more efficient than your Bash script. (You can use the single-character variable names from your exposition if you like, of course; but having human-readable variable names is usually much more maintainable.)

Not the answer you're looking for? Browse other questions tagged or ask your own question.