0

I am creating a script that allows comparing two ssh command outputs to a remote Netapp, and that allows comparing between a current value and the maximum value of space that the Netapp cabin has.

I have collected these values ​​in two dictionaries (rv and rv 2), which in turn, I convert to JSON format to be able to compare them based on the warning argument passed to it (if it exceeds this limit, it would have to notify).

import subprocess
import argparse
import sys
import json
import re
from subprocess import check_output
def parse_args(argv):
    parser = argparse.ArgumentParser()  
    parser.add_argument("-u", "--user", action="store",
                        help="User for login",
                        dest="user")
    parser.add_argument("-p", "--pwd", action="store",
                        help="Password",
                        dest="pwd")
    parser.add_argument("-i", "--ip", action="store",
                        help="Machine ip",
                        dest="ip")
    parser.add_argument("-w", "--warning", action="store",
                        help="Warning threshold",
                        type = int,
                        dest="warning")
    parser.add_argument("-m", "--machine_command", action="store",
                        help="Command",
                        type = int,
                        dest="ssh_command")
    parser.add_argument("-M", "--machine_command_max", action="store",
                        help="Max value for command",
                        type = int,
                        dest="ssh_command_max")



    args = parser.parse_args()
    return args
args = parse_args(sys.argv[1:])

command = 'sshpass -p ' +args.pwd+ ' ssh ' + args.user + '@' +args.ip+ args.ssh_command 
output = check_output(command, shell=True)
#Command to retrieve the max_values
command_max = 'sshpass -p ' +args.pwd+ ' ssh ' + args.user + '@' +args.ip+ args.ssh_command_max
output_max = check_output(command_max, shell=True)


rv = {}
current_node = None

for match in re.findall(r'Machine_name (name.*\d+)|(Metric_name_.*)', output):
    node, metric = match
    if node and current_node != node:
       current_node = node
    if current_node and metric:
        name, value = metric.strip().split()
        rv[current_node.strip() + "." + name.replace("Alloc", "")] = [value] 
#print(';'.join(rv))

rv2 = {}
current_node = None

for match in re.findall(r'Machine_name (name.*\d+)|(Max_metric.*)', output_max):
    node, metric = match
    if node and current_node != node:
        current_node = node
    if current_node and metric:
        name, value = metric.strip().split()
        rv2[current_node.strip() + "." + name.replace("Max", "")] = [(value/100) * args.warning] 

json1=json.dumps(rv, sort_keys=True)
json2=json.dumps(rv2, sort_keys=True)



def get_values(json, lst):
  if isinstance(json, list):
    for item in json: get_values(item, lst)
  elif isinstance(json, dict):
    for item in json.values(): get_values(item, lst)
  else: lst.append(json)


list1 = []; get_values(json1, list1)
list2 = []; get_values(json2, list2)

diff = [(n, x, y) for n,(x,y) in enumerate(zip(list1, list2)) if x <= y]
print(diff)

An example of the values that I would like to compare: RV1:

{'node1.storePool_Owner': ['160'], 'node1.storePool_Deleg': ['0'], 'node2.storePool_LockState': ['0']}

RV2:

{'node1.storePool_Owner': ['1024000'], 'node1.storePool_Deleg': ['1024000'], 'node2.storePool_LockState': ['1024000']}

The idea is to compare each of these values, with their maximum equivalent.

Thanks a lot for your help.

An example of how should the comparison be: If this node, with that value:

node1.storePool_Owner': ['160']

Reaches the X% (warning arg) of:

node1.storePool_Owner': ['1024000']

Then it should return:

WARNING: node1.storePool_Owner has exceeded the threshold (x%)
aldegalan
  • 480
  • 2
  • 12
  • What do you want the result of your comparison to be? Or are you asking for advice about what the result of the comparison should be? Also consider a [example]. If you only want advice on how to compare two JSON arrays - your code should be 4 lines tops. Also, does it matter that the arrays have a JSON representation? Are you just comparing Python arrays? – JohnFilleau Jun 09 '20 at 21:36
  • Hello @JohnFilleau , I already edited my questoion with an example of how would I like to compare all values with his equal. I chose to compare Json because I though that it could be easier (I am new at Python, and some basic things I do not master, or do not know how to look for them). I have put the entire code, so you can see the dictionary conversion to json, and if you even consider it better not to make that change (although from what I was looking at, it was the simplest for me). – aldegalan Jun 09 '20 at 21:54
  • The object in a dictionary is the most convenient for comparisons. If you have it in a JSON text format, then to compare, you'd have to... parse it back to some logical representation such as a python dictionary to compare it anyway. You just wrote your own code by the way: `If this node with that value... reaches this other value... then it should return ` – JohnFilleau Jun 09 '20 at 23:07

1 Answers1

0

This will compare the two json files/dictionaries. I noticed the values are lists of string... is that intentional?

import json


def open_json(path):
    with open(path, 'r') as file:
        return json.load(file)


def check_thresholds(data, thresholds):
    for k, v in thresholds.items():
        # your logic/output here
        # k[0] and v[0] because your values are lists of strings... should they be just int of float?
        difference = int(data.get(k)[0]) - int(v[0])
        if difference >= 0:
            print(f'WARNING: {k} has exceeded the threshold by {difference}')
        else:
            print(f'OK: {k}')


def main():
    # load the data into dictionaries
    data = open_json('./rv.json')
    thresholds = open_json('./rv2.json')

    # if your data is a dictionary and not json files then use these
    # data = {'node1.storePool_Owner': ['160'], 'node1.storePool_Deleg': ['0'], 'node2.storePool_LockState': ['0']}
    # thresholds = {'node1.storePool_Owner': ['1024000'], 'node1.storePool_Deleg': ['1024000'], 'node2.storePool_LockState': ['1024000']}

    # run the checks
    check_thresholds(data, thresholds)


main()

Output (I modified some values to show the warning):

WARNING: node1.storePool_Owner has exceeded the threshold by 1000
OK: node1.storePool_Deleg
OK: node2.storePool_LockState
bherbruck
  • 2,167
  • 1
  • 6
  • 17