From 9f3fe01a490ac6b876d29b7ed85aca394ee6dbc9 Mon Sep 17 00:00:00 2001 From: Jarrod Johnson Date: Thu, 2 Nov 2017 17:07:44 -0400 Subject: [PATCH] Evolve the concept, it does not currently work --- confluent_client/bin/nodeconfig | 38 ++++++++++++++++++++++---- confluent_client/confluent/client.py | 27 ++++++++++-------- confluent_server/confluent/core.py | 9 +++--- confluent_server/confluent/messages.py | 29 +++++++++++++++++--- 4 files changed, 79 insertions(+), 24 deletions(-) diff --git a/confluent_client/bin/nodeconfig b/confluent_client/bin/nodeconfig index 7a6fa160..76bf465f 100644 --- a/confluent_client/bin/nodeconfig +++ b/confluent_client/bin/nodeconfig @@ -65,6 +65,8 @@ except IndexError: setmode = None assignment = {} queryparms = {} + + for param in args[1:]: if '=' in param: if setmode is None: @@ -88,18 +90,44 @@ for param in args[1:]: path, attrib = cfgpaths[candidate] path = '/noderange/{0}/{1}'.format(noderange, path) if path not in queryparms: - queryparms[path] = set([]) - queryparms[path].add(attrib) + queryparms[path] = {} + queryparms[path][attrib] = candidate if not matchedparms: bailout('Unrecognized settings category: {0}'.format(param)) elif param not in cfgpaths: bailout('Unrecognized parameter: {0}'.format(param)) else: - queryparms.append(candidate) + path, attrib = cfgpaths[param] + path = '/noderange/{0}/{1}'.format(noderange, path) + if path not in queryparms: + queryparms[path] = {} + queryparms[path][attrib] = param session = client.Command() if setmode: - raise Exception('TODO') + updatebypath = {} + attrnamebypath = {} + for key in assignment: + if key not in cfgpaths: + bailout('Unknown settings key: {0}'.format(key)) + path, attrib = cfgpaths[key] + if path not in updatebypath: + updatebypath[path] = {} + attrnamebypath[path] = {} + updatebypath[path][attrib] = assignment[key] + attrnamebypath[path][attrib] = key + # well, we want to expand things.. + # check ipv4, if requested change method to static + for path in updatebypath: + for r in session.update('/noderange/{0}/{1}'.format(noderange, path), + updatebypath[path]): + for node in r: + keyval = r[node]['value'] + key, val = keyval.split('=') + if key in attrnamebypath[path]: + key = attrnamebypath[path][key] + print('{0}: {1}: {2}'.format(node, key, val)) else: for path in queryparms: - client.print_attrib_path(path, session, queryparms[path], NullOpt()) + client.print_attrib_path(path, session, list(queryparms[path]), + NullOpt(), queryparms[path]) diff --git a/confluent_client/confluent/client.py b/confluent_client/confluent/client.py index 94bbdda7..e514b505 100644 --- a/confluent_client/confluent/client.py +++ b/confluent_client/confluent/client.py @@ -303,7 +303,7 @@ def printattributes(session, requestargs, showtype, nodetype, noderange, options return print_attrib_path(path, session, requestargs, options) -def print_attrib_path(path, session, requestargs, options): +def print_attrib_path(path, session, requestargs, options, rename=None): exitcode = 0 seenattributes = set([]) for res in session.read(path): @@ -314,23 +314,28 @@ def print_attrib_path(path, session, requestargs, options): for node in res['databynode']: for attr in res['databynode'][node]: seenattributes.add(attr) + if rename and attr in rename: + printattr = rename[attr] + else: + printattr = attr currattr = res['databynode'][node][attr] if (requestargs is None or requestargs == [] or attrrequested( attr, requestargs, seenattributes)): if 'value' in currattr: if currattr['value'] is not None: attrout = '{0}: {1}: {2}'.format( - node, attr, currattr['value']) + node, printattr, currattr['value']) else: - attrout = '{0}: {1}:'.format(node, attr) + attrout = '{0}: {1}:'.format(node, printattr) elif 'isset' in currattr: if currattr['isset']: - attrout = '{0}: {1}: ********'.format(node, attr) + attrout = '{0}: {1}: ********'.format(node, + printattr) else: - attrout = '{0}: {1}:'.format(node, attr) + attrout = '{0}: {1}:'.format(node, printattr) elif 'broken' in currattr: attrout = '{0}: {1}: *ERROR* BROKEN EXPRESSION: ' \ - '{2}'.format(node, attr, + '{2}'.format(node, printattr, currattr['broken']) elif isinstance(currattr, list) or isinstance(currattr, tuple): attrout = '{0}: {1}: {2}'.format(node, attr, ','.join(map(str, currattr))) @@ -338,7 +343,7 @@ def print_attrib_path(path, session, requestargs, options): dictout = [] for k, v in currattr.items: dictout.append("{0}={1}".format(k, v)) - attrout = '{0}: {1}: {2}'.format(node, attr, ','.join(map(str, dictout))) + attrout = '{0}: {1}: {2}'.format(node, printattr, ','.join(map(str, dictout))) else: cprint("CODE ERROR" + repr(attr)) @@ -432,18 +437,18 @@ def updateattrib(session, updateargs, nodetype, noderange, options): for val in updateargs[1:]: val = val.split('=') if (nodetype == "nodegroups"): - exitcode = session.simple_nodegroups_command(noderange, 'attributes/all'.format(noderange), + exitcode = session.simple_nodegroups_command(noderange, 'attributes/all', val[1],val[0]) else: - exitcode = session.simple_noderange_command(noderange, 'attributes/all'.format(noderange), + exitcode = session.simple_noderange_command(noderange, 'attributes/all', val[1], val[0]) else: val = updateargs[1].split('=') if nodetype == "nodegroups" : - exitcode = session.simple_nodegroups_command(noderange, 'attributes/all'.format(noderange), + exitcode = session.simple_nodegroups_command(noderange, 'attributes/all', val[1], val[0]) else: - exitcode = session.simple_noderange_command(noderange, 'attributes/all'.format(noderange), + exitcode = session.simple_noderange_command(noderange, 'attributes/all', val[1], val[0]) except: sys.stderr.write('Error: {0} not a valid expression\n'.format(str(updateargs[1:]))) diff --git a/confluent_server/confluent/core.py b/confluent_server/confluent/core.py index b5bee1a4..0db54d20 100644 --- a/confluent_server/confluent/core.py +++ b/confluent_server/confluent/core.py @@ -499,7 +499,7 @@ def handle_nodegroup_request(configmanager, inputdata, raise Exception("TODO") plugroute = routespec.routeinfo inputdata = msg.get_input_message( - pathcomponents[2:], operation, inputdata) + pathcomponents[2:], operation, inputdata, configmanager) if 'handler' in plugroute: # fixed handler definition hfunc = getattr(pluginmap[plugroute['handler']], operation) return hfunc( @@ -611,7 +611,8 @@ def handle_node_request(configmanager, inputdata, operation, passvalues = [] plugroute = routespec.routeinfo inputdata = msg.get_input_message( - pathcomponents, operation, inputdata, nodes, isnoderange) + pathcomponents, operation, inputdata, nodes, isnoderange, + configmanager) if 'handler' in plugroute: # fixed handler definition, easy enough if isinstance(plugroute['handler'], str): hfunc = getattr(pluginmap[plugroute['handler']], operation) @@ -718,7 +719,7 @@ def handle_path(path, operation, configmanager, inputdata=None, autostrip=True): except IndexError: # it's just users/ if operation == 'create': inputdata = msg.get_input_message( - pathcomponents, operation, inputdata) + pathcomponents, operation, inputdata, configmanager) create_user(inputdata.attribs, configmanager) return iterate_collections(configmanager.list_users(), forcecollection=False) @@ -730,7 +731,7 @@ def handle_path(path, operation, configmanager, inputdata=None, autostrip=True): return delete_user(user, configmanager) elif operation == 'update': inputdata = msg.get_input_message( - pathcomponents, operation, inputdata) + pathcomponents, operation, inputdata, configmanager) update_user(user, inputdata.attribs, configmanager) return show_user(user, configmanager) elif pathcomponents[0] == 'events': diff --git a/confluent_server/confluent/messages.py b/confluent_server/confluent/messages.py index fa38a3c9..4ec8712e 100644 --- a/confluent_server/confluent/messages.py +++ b/confluent_server/confluent/messages.py @@ -19,6 +19,7 @@ # Things are defined here to 'encourage' developers to coordinate information # format. This is also how different data formats are supported import confluent.exceptions as exc +import confluent.config.configmanager as cfm from copy import deepcopy from datetime import datetime import json @@ -361,7 +362,8 @@ class ChildCollection(LinkRelation): # InputMCI # InputDomainName # InputNTPServer -def get_input_message(path, operation, inputdata, nodes=None, multinode=False): +def get_input_message(path, operation, inputdata, nodes=None, multinode=False, + configmanager=None): if path[0] == 'power' and path[1] == 'state' and operation != 'retrieve': return InputPowerMessage(path, nodes, inputdata) elif (path in (['power', 'reseat'], ['_enclosure', 'reseat_bay']) and @@ -392,7 +394,8 @@ def get_input_message(path, operation, inputdata, nodes=None, multinode=False): return InputMCI(path, nodes, inputdata) elif (path[:4] == ['configuration', 'management_controller', 'net_interfaces', 'management'] and operation != 'retrieve'): - return InputNetworkConfiguration(path, nodes, inputdata) + return InputNetworkConfiguration(path, nodes, inputdata, + configmanager) elif (path[:3] == ['configuration', 'management_controller', 'domain_name'] and operation != 'retrieve'): return InputDomainName(path, nodes, inputdata) @@ -710,7 +713,7 @@ class InputMCI(ConfluentInputMessage): class InputNetworkConfiguration(ConfluentInputMessage): - def __init__(self, path, nodes, inputdata): + def __init__(self, path, nodes, inputdata, configmanager=None): self.inputbynode = {} self.stripped = False if not inputdata: @@ -734,8 +737,26 @@ class InputNetworkConfiguration(ConfluentInputMessage): if nodes is None: raise exc.InvalidArgumentException( 'This only supports per-node input') + nodeattrmap = {} + for attr in inputdata: + try: + inputdata[attr].format() + except (KeyError, IndexError): + nodeattrmap[attr] = {} + for expanded in cfm.expand_attrib_expression(nodes, + inputdata[attr]): + node, value = expanded + nodeattrmap[attr][node] = value + if not nodeattrmap: + for node in nodes: + self.inputbynode[node] = inputdata + return + # an expression was encountered for node in nodes: - self.inputbynode[node] = inputdata + self.inputbynode[node] = deepcopy(inputdata) + for attr in self.inputbynode[node]: + if attr in nodeattrmap: + self.inputbynode[node][attr] = nodeattrmap[attr][node][attr] def netconfig(self, node): return self.inputbynode[node]