diff --git a/confluent_client/bin/stats b/confluent_client/bin/stats index 1329f240..39463f90 100755 --- a/confluent_client/bin/stats +++ b/confluent_client/bin/stats @@ -16,6 +16,7 @@ # limitations under the License. import argparse +import csv import fcntl import io import numpy as np @@ -73,7 +74,9 @@ def textplot(plotdata, bins): histogram = False aparser = argparse.ArgumentParser(description='Quick access to common statistics') aparser.add_argument('-c', type=int, default=0, help='Column number to analyze (default is last column)') -aparser.add_argument('-s', default=False, action='store_true', help='Output histogram in sixel format') +aparser.add_argument('-d', default=None, help='Value used to separate columns') +aparser.add_argument('-x', default=False, action='store_true', help='Output histogram in sixel format') +aparser.add_argument('-s', default=0, help='Number of header lines to skip before processing') aparser.add_argument('-g', default=False, action='store_true', help='Open histogram in separate graphical window') aparser.add_argument('-o', default=None, help='Output histogram to the specified filename in PNG format') aparser.add_argument('-t', default=False, action='store_true', help='Output a histogram in text format') @@ -81,13 +84,44 @@ aparser.add_argument('-v', default=False, action='store_true', help='Attempt to aparser.add_argument('-b', type=int, default=10, help='Number of bins to use in histogram (default is 10)') args = aparser.parse_args(sys.argv[1:]) plotdata = [] -data = sys.stdin.readline() +headlines = int(args.s) +while headlines >= 0: + data = sys.stdin.readline() + headlines -= 1 +if args.d: + delimiter = args.d +else: + if '\t' in data: + delimiter = '\t' + elif ' ' in data: + delimiter = ' ' + elif ',' in data: + delimiter = ',' + else: + delimiter = ' ' # handle single column +data = list(csv.reader([data], delimiter=delimiter))[0] nodebydatum = {} +idx = args.c - 1 +autoidx = False while data: node = None - if ':' in data: - node, data = data.split(':', 1) - datum = float(data.split()[args.c - 1]) + if ':' in data[0]: + node, data[0] = data[0].split(':', 1) + else: + node = data[0] + if idx == -1 and not autoidx: + while not autoidx: + try: + datum = float(data[idx]) + except ValueError: + idx -= 1 + continue + except IndexError: + sys.stderr.write('Unable to identify a numerical column\n') + sys.exit(1) + autoidx = True + else: + datum = float(data[idx]) if node: if datum in nodebydatum: nodebydatum[datum].add(node) @@ -95,12 +129,13 @@ while data: nodebydatum[datum] = set([node]) plotdata.append(datum) data = sys.stdin.readline() + data = list(csv.reader([data], delimiter=delimiter))[0] n = None -if args.g or args.o or args.s: +if args.g or args.o or args.x: n, bins = plot(args.g, args.o, plotdata, bins=args.b) if args.t: n, bins = textplot(plotdata, bins=args.b) -print('Samples: {5} Min: {3} Median: {0} Mean: {1} Max: {4} StandardDeviation: {2}'.format(np.median(plotdata), np.mean(plotdata), np.std(plotdata), np.min(plotdata), np.max(plotdata), len(plotdata))) +print('Samples: {5} Min: {3} Median: {0} Mean: {1} Max: {4} StandardDeviation: {2} Sum: {6}'.format(np.median(plotdata), np.mean(plotdata), np.std(plotdata), np.min(plotdata), np.max(plotdata), len(plotdata), np.sum(plotdata))) if args.v and n is not None and nodebydatum: print('') currbin = bins[0] diff --git a/confluent_server/confluent/auth.py b/confluent_server/confluent/auth.py index 7605fc30..da15f491 100644 --- a/confluent_server/confluent/auth.py +++ b/confluent_server/confluent/auth.py @@ -45,6 +45,8 @@ _allowedbyrole = { 'Operator': { 'retrieve': ['*'], 'create': [ + '/noderange/', + '/nodes/', '/node*/media/uploads/', '/node*/inventory/firmware/updates/*', '/node*/suppport/servicedata*', @@ -68,7 +70,8 @@ _allowedbyrole = { '/nodes/*/shell/sessions*', ], 'delete': [ - '/node*/*/events/hardware/log', + '/discovery/*', + '/node*', ], }, 'Monitor': { diff --git a/confluent_server/confluent/discovery/handlers/bmc.py b/confluent_server/confluent/discovery/handlers/bmc.py index 389b429a..dc783f8b 100644 --- a/confluent_server/confluent/discovery/handlers/bmc.py +++ b/confluent_server/confluent/discovery/handlers/bmc.py @@ -32,10 +32,21 @@ DEFAULT_PASS = 'PASSW0RD' class NodeHandler(generic.NodeHandler): - def _get_ipmicmd(self, user=DEFAULT_USER, password=DEFAULT_PASS): - return ipmicommand.Command(self.ipaddr, user, password) + def _get_ipmicmd(self, user=None, password=None): + priv = None + if user is None or password is None: + if self.trieddefault: + raise pygexc.IpmiException() + priv = 4 # manually indicate priv to avoid double-attempt + if user is None: + user = DEFAULT_USER + if password is None: + password = DEFAULT_PASS + return ipmicommand.Command(self.ipaddr, user, password, + privlevel=priv, keepalive=False) def __init__(self, info, configmanager): + self.trieddefault = None super(NodeHandler, self).__init__(info, configmanager) def probe(self): diff --git a/confluent_server/confluent/discovery/handlers/xcc.py b/confluent_server/confluent/discovery/handlers/xcc.py index 1c7280e6..1e222627 100644 --- a/confluent_server/confluent/discovery/handlers/xcc.py +++ b/confluent_server/confluent/discovery/handlers/xcc.py @@ -33,6 +33,7 @@ class NodeHandler(immhandler.NodeHandler): ff = self.info.get('attributes', {}).get('enclosure-form-factor', '') if ff not in ('dense-computing', [u'dense-computing']): return + self.trieddefault = None # Reset state on a preconfig attempt # attempt to enable SMM #it's normal to get a 'not supported' (193) for systems without an SMM ipmicmd = None @@ -44,6 +45,7 @@ class NodeHandler(immhandler.NodeHandler): 'Incorrect password' not in str(e)): # raise an issue if anything other than to be expected raise + self.trieddefault = True #TODO: decide how to clean out if important #as it stands, this can step on itself #if ipmicmd: diff --git a/confluent_server/confluent/plugins/hardwaremanagement/ipmi.py b/confluent_server/confluent/plugins/hardwaremanagement/ipmi.py index d18fb651..8db933c8 100644 --- a/confluent_server/confluent/plugins/hardwaremanagement/ipmi.py +++ b/confluent_server/confluent/plugins/hardwaremanagement/ipmi.py @@ -173,6 +173,7 @@ class IpmiCommandWrapper(ipmicommand.Command): self.node = node self._inhealth = False self._lasthealth = None + kwargs['keepalive'] = False self._attribwatcher = cfm.watch_attributes( (node,), ('secret.hardwaremanagementuser', 'collective.manager', 'secret.hardwaremanagementpassword', 'secret.ipmikg',